0
0
mirror of https://github.com/yude-jp/yude.jp synced 2025-10-16 21:28:38 +09:00

112 Commits

Author SHA1 Message Date
dependabot[bot]
8e1e6a6b4e Bump json5 from 1.0.1 to 1.0.2
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-08 01:28:11 +00:00
79246ee600 Merge pull request #21 from yudejp/dependabot/npm_and_yarn/minimatch-3.1.2
Bump minimatch from 3.0.4 to 3.1.2
2023-03-08 10:27:47 +09:00
98ad910a9b Merge pull request #22 from yudejp/dependabot/npm_and_yarn/loader-utils-2.0.4
Bump loader-utils from 2.0.0 to 2.0.4
2023-03-08 10:27:38 +09:00
fc90f87285 Merge pull request #19 from yudejp/dependabot/npm_and_yarn/terser-5.14.2
Bump terser from 5.9.0 to 5.14.2
2023-03-08 10:27:27 +09:00
b07d6412ff Merge pull request #18 from yudejp/dependabot/npm_and_yarn/moment-2.29.4
Bump moment from 2.29.1 to 2.29.4
2023-03-08 10:27:14 +09:00
dependabot[bot]
6d6365c240 Bump loader-utils from 2.0.0 to 2.0.4
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 2.0.0 to 2.0.4.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v2.0.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v2.0.0...v2.0.4)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-16 03:22:55 +00:00
dependabot[bot]
1dd86ac2c8 Bump minimatch from 3.0.4 to 3.1.2
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-10 18:24:43 +00:00
dependabot[bot]
496fe5ee4b Bump terser from 5.9.0 to 5.14.2
Bumps [terser](https://github.com/terser/terser) from 5.9.0 to 5.14.2.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-20 04:01:00 +00:00
dependabot[bot]
cdcce3a39b Bump moment from 2.29.1 to 2.29.4
Bumps [moment](https://github.com/moment/moment) from 2.29.1 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.1...2.29.4)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-08 09:16:19 +00:00
7f3a8f8230 Merge pull request #15 from yudejp/dependabot/npm_and_yarn/next-12.1.0
Bump next from 11.1.3 to 12.1.0
2022-02-19 14:50:46 +09:00
dependabot[bot]
fae52872f1 Bump next from 11.1.3 to 12.1.0
Bumps [next](https://github.com/vercel/next.js) from 11.1.3 to 12.1.0.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v11.1.3...v12.1.0)

---
updated-dependencies:
- dependency-name: next
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-17 21:07:17 +00:00
1c8bf364dd Merge pull request #14 from yudejp/dependabot/npm_and_yarn/follow-redirects-1.14.8
Bump follow-redirects from 1.14.7 to 1.14.8
2022-02-17 11:54:04 +09:00
dependabot[bot]
ef653ed749 Bump follow-redirects from 1.14.7 to 1.14.8
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-15 12:14:34 +00:00
8deac1fede Merge pull request #12 from yudejp/dependabot/npm_and_yarn/follow-redirects-1.14.7
Bump follow-redirects from 1.14.4 to 1.14.7
2022-02-06 17:02:06 +09:00
3fb52ddcfa Merge pull request #13 from yudejp/dependabot/npm_and_yarn/nanoid-3.2.0
Bump nanoid from 3.1.25 to 3.2.0
2022-02-06 17:01:57 +09:00
dependabot[bot]
a36785dded Bump nanoid from 3.1.25 to 3.2.0
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.25 to 3.2.0.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.25...3.2.0)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-22 02:29:26 +00:00
c60270c1c6 Fix link to hidden services 2022-01-17 13:17:06 +09:00
1b7319617b Add link to metrics.torproject.org 2022-01-17 13:15:30 +09:00
dependabot[bot]
aa6f4417e7 Bump follow-redirects from 1.14.4 to 1.14.7
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.4 to 1.14.7.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.4...v1.14.7)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-15 08:15:43 +00:00
ae6c8aa9c9 Merge branch 'master' of https://github.com/yudejp/yude.jp 2022-01-06 07:56:17 +09:00
9389cc55f7 Add host oracle-a1-1, Replace iframe with img for reducing requests 2022-01-06 07:56:14 +09:00
ba0e41579a Fix close button on WakaTime.js 2022-01-06 07:49:45 +09:00
b35caef45c Fix icon size on LangSelector 2022-01-02 18:34:06 +09:00
7ac1c7199f Merge branch 'master' of https://github.com/yudejp/yude.jp 2022-01-02 18:18:39 +09:00
f697eb9b85 Fix Font Awesome icon size 2022-01-02 18:18:31 +09:00
16bb6398e4 Remove weird space 2022-01-02 18:18:25 +09:00
02b1adcf55 Add "contents" 2021-12-29 06:41:51 +09:00
34e335037c Not passing lang parameters on external links 2021-12-28 05:29:08 +09:00
0cb27e3cda Update Minecraft required version 2021-12-28 05:28:18 +09:00
92459e594f Fix TS3 2021-12-27 06:09:39 +09:00
c30312a46a Update en.md 2021-12-26 11:09:54 +09:00
5531b3a3bf Remove link to Tor & I2P from footer 2021-12-26 10:34:05 +09:00
f0cf3729a0 Merge branch 'master' of https://github.com/yudejp/yude.jp 2021-12-26 07:35:50 +09:00
ec530601b4 Add services/ 2021-12-26 07:35:41 +09:00
30547e3b81 Fix i18n tag 2021-12-26 06:58:15 +09:00
2529afa286 Update README.md 2021-12-23 18:16:55 +09:00
b62f95d483 Add links to Tor, I2P 2021-12-22 06:28:44 +09:00
2bd3b69da1 Update icon size 2021-12-12 07:15:34 +09:00
5a0e87d7d4 Update icon size 2021-12-11 21:40:26 +09:00
b6f427d605 Fix image centering 2021-12-11 21:32:51 +09:00
92bb8b995c Remove FreeSpeech banner 2021-12-11 21:32:42 +09:00
52c8cd8d1c Fix: Discord playing data fetching 2021-12-11 21:13:44 +09:00
22385a42c8 Ignore @next/next/no-img-element, react-hooks/exhaustive-deps 2021-12-11 21:13:29 +09:00
99f776b861 Avoid using next/image 2021-12-11 19:19:50 +09:00
24327251ee Remove .env.local.sample 2021-12-11 19:13:37 +09:00
1f7456db3c Fix misc errors 2021-12-11 19:07:11 +09:00
a8321b6c60 This <Link> does not need query 2021-12-11 19:03:47 +09:00
ff98956a10 Cleanup 2021-12-11 19:01:18 +09:00
db6855fbc6 Remove microCMS 2021-12-11 18:57:22 +09:00
b446a2ebae Prepare for SSG 2021-12-11 18:55:57 +09:00
86844984d2 Add .DS_Store to .gitignore 2021-12-11 18:55:39 +09:00
a72a778a03 WIP 2021-12-11 18:17:20 +09:00
d9559dd072 WIP 2021-12-11 18:07:22 +09:00
c856a34867 Add out to .gitignore 2021-12-11 07:15:52 +09:00
d3283b12b2 https://github.com/vercel/next.js/issues/28596 2021-12-11 07:15:37 +09:00
8513ee795f Cleanup 2021-12-11 06:58:32 +09:00
49bd87b276 Merge branch 'master' of https://github.com/yudejp/yude.jp 2021-12-11 06:47:47 +09:00
a095e20b6b Remove /api/PlayerName 2021-12-11 06:42:23 +09:00
33dbec3339 bye Fitbit 2021-12-11 06:32:00 +09:00
6eb140fc0a Merge pull request #11 from yudejp/dependabot/npm_and_yarn/next-11.1.3
Bump next from 11.1.2 to 11.1.3
2021-12-09 12:15:50 +09:00
dependabot[bot]
08d054f8f6 Bump next from 11.1.2 to 11.1.3
Bumps [next](https://github.com/vercel/next.js) from 11.1.2 to 11.1.3.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v11.1.2...v11.1.3)

---
updated-dependencies:
- dependency-name: next
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-09 03:10:12 +00:00
bed955aa95 Update README.md 2021-11-25 05:59:23 +09:00
37adbffcef Update server.js 2021-10-13 09:57:45 +09:00
b1a778b5d0 Update hostname 2021-10-13 09:45:36 +09:00
e32dde3363 Temporary remove Fitbit function 2021-10-11 11:50:37 +09:00
429407820f Delete hosts 2021-10-09 06:59:56 +09:00
4e8f0435f2 Update label 2021-10-08 13:58:39 +09:00
d764ae8f32 Update docs 2021-10-03 13:55:34 +09:00
db8a0af6ca Add "またはプレイヤー名" 2021-10-03 13:18:08 +09:00
9e2f51eb5f Add UUID lookup function
Now player's profile page works on IGN query too
2021-10-03 13:12:11 +09:00
979bbe2a7f Fix implementation of heartrate retrieving, Update styling 2021-10-02 14:23:12 +09:00
de69c49d46 Delete garbage comment 2021-10-02 12:49:27 +09:00
1411e37d8f Add sleep duration, heartrate on /profile 2021-10-02 12:45:12 +09:00
a08bd36c3e Add package: date-fns 2021-10-02 12:24:49 +09:00
aaa92c3a73 Add public keys 2021-09-27 08:03:20 +09:00
ea617dd8dc Fix 404 page @ minecraft/players/[uuid] 2021-09-26 13:36:23 +09:00
5276456ac2 Fix title during page loading 2021-09-26 13:24:10 +09:00
2b6ca4354d Fix: loading implementation 2021-09-26 12:52:37 +09:00
7e7066317c Remove console.log() for debug 2021-09-26 12:27:35 +09:00
3afef82031 Add yude.keys 2021-09-25 23:09:23 +09:00
4d0b82dee3 Update [uuid].js 2021-09-25 22:14:02 +09:00
c19e797fa4 Replace "class" to "className" 2021-09-25 21:53:57 +09:00
365559158d Add group badge @ /minecraft/players/[uuid] 2021-09-25 21:51:35 +09:00
967c0f77af Add biography on minecraft/players/[uuid] 2021-09-25 07:51:13 +09:00
85c649ddca Update ja.md 2021-09-24 19:24:18 +09:00
3898a6951d Avoid using toString() 2021-09-24 19:08:39 +09:00
7ad04ba8ef Update export default name 2021-09-24 19:07:48 +09:00
e3e4cc5a5e Fix page title @ /minecraft/players/[uuid] 2021-09-24 19:06:26 +09:00
a4982c7ef3 Fix: error handling on 404 2021-09-24 17:43:07 +09:00
c957d791a6 Update return format 2021-09-24 17:25:26 +09:00
971be8ab25 Replace "class" to "className" 2021-09-24 16:49:49 +09:00
eb46a60119 Remove weird comments 2021-09-24 16:49:07 +09:00
7629eb6c49 Implement basic user page for Minecraft server 2021-09-24 16:47:45 +09:00
f8357e2068 Add crafatar.com to trusted source of images 2021-09-24 16:47:27 +09:00
ee913461f1 Using next.config.js rewrite for UUID validation 2021-09-24 10:08:30 +09:00
b95c6b4cd5 [/minecraft/players/] Add basic function to retrieve player's data 2021-09-24 09:15:03 +09:00
b0b900cc10 Update comment 2021-09-24 08:10:26 +09:00
296e4d6298 Add redirects to Amazon wishlist, Scrapbox (via Next.js) 2021-09-22 08:23:29 +09:00
2c0bc0f5f6 Add unmet dependencies 2021-09-22 07:51:08 +09:00
73d159c1a6 Update packages 2021-09-22 07:46:38 +09:00
34df66d050 Fix: Do not pass children as props. 2021-09-22 07:43:10 +09:00
0258de61b0 Fix unused val, Add comments 2021-09-22 07:24:00 +09:00
958e9803fb Fix typo 2021-09-22 07:19:34 +09:00
7ee5d348dd Fix: avoid doing export default and val declare at the same time 2021-09-22 07:19:12 +09:00
24cf758cad Add alt to images 2021-09-22 07:13:49 +09:00
a8186fb801 Enable Next.js lint 2021-09-22 07:13:44 +09:00
65fbb55a33 Add redirects to wishlist, Scrapbox 2021-09-22 07:09:49 +09:00
b59a6b6926 Add .vercel to .gitignore 2021-09-22 07:07:59 +09:00
623db08e1a Merge pull request #10 from yudejp/dependabot/npm_and_yarn/nth-check-2.0.1
Bump nth-check from 2.0.0 to 2.0.1
2021-09-21 13:18:04 +09:00
dependabot[bot]
3a947d2932 Bump nth-check from 2.0.0 to 2.0.1
Bumps [nth-check](https://github.com/fb55/nth-check) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/fb55/nth-check/releases)
- [Commits](https://github.com/fb55/nth-check/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: nth-check
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-09-21 04:17:03 +00:00
yude
8f6953df10 Add server status for "saika" host 2021-09-21 13:16:09 +09:00
yude
3c7d783a9c Add link to my Amazon wishlist 2021-09-21 13:12:56 +09:00
80 changed files with 3716 additions and 2781 deletions

View File

@@ -1,5 +0,0 @@
SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=
SPOTIFY_REFRESH_TOKEN=
MICROCMS_API_KEY=

8
.eslintrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"extends": "next/core-web-vitals",
"rules": {
"@next/next/no-document-import-in-page": "off",
"@next/next/no-img-element": "off",
"react-hooks/exhaustive-deps": "off"
}
}

3
.gitignore vendored
View File

@@ -11,3 +11,6 @@ yarn-error.log
.vimrc~ .vimrc~
..vimrc.un~ ..vimrc.un~
.env.local .env.local
out
.vercel
.DS_Store

View File

@@ -3,14 +3,11 @@
<img alt="Next JS" src="https://img.shields.io/badge/nextjs-%23000000.svg?style=for-the-badge&logo=next.js&logoColor=white"/> <img alt="Next JS" src="https://img.shields.io/badge/nextjs-%23000000.svg?style=for-the-badge&logo=next.js&logoColor=white"/>
<img alt="TailwindCSS" src="https://img.shields.io/badge/tailwindcss-%2338B2AC.svg?style=for-the-badge&logo=tailwind-css&logoColor=white"/>\ <img alt="TailwindCSS" src="https://img.shields.io/badge/tailwindcss-%2338B2AC.svg?style=for-the-badge&logo=tailwind-css&logoColor=white"/>\
Source code of [yude.jp](https://yude.jp).\ Source code of [yude.jp](https://yude.jp).\
Built with [Next.js](https://nextjs.org/) and [Tailwind CSS](https://tailwindcss.com/) and deployed on [Vercel](https://vercel.com). Built with [Next.js](https://nextjs.org/) and [Tailwind CSS](https://tailwindcss.com/) and deployed to [Cloudflare Pages](https://pages.cloudflare.com/).
## Development ## Development
### Setup 1. Run `yarn` to install dependencies.
1. Run `yarn`. 2. Run `yarn dev` to serve.
1. Rename `.env.local.sample` as `.env.local` and set value.
### Preview
* Run `yarn dev`.
## License ## License
This repository is provided under the MIT License. This repository is provided under the MIT License.

View File

@@ -1,17 +1,16 @@
このアカウントは**非公式**アカウントです。また、内容を保証するものではありません。 このアカウントは**非公式**アカウントです。また、内容を保証するものではありません。
# 管理者 # 連絡先
広島市立大学 情報科学部 2年の [yude](https://yude.jp/profile) が管理しています。このアカウントについての連絡は下記までお願いします。 広島市立大学 情報科学部 2年の [yude](https://yude.jp/profile) が管理しています。このアカウントについての連絡は下記までお願いします。
## 連絡先
* 電子メール: [admin@yude.jp](mailto:admin@yude.jp) * 電子メール: [admin@yude.jp](mailto:admin@yude.jp)
* Twitter: [@yude_jp](https://twitter.com/yude_jp) * Twitter: [@yude_jp](https://twitter.com/yude_jp)
# 稼働方法 # 仕組み
Microsoft Power Automate によって広島市立大学WebページのRSSフィードを取得し、新しい記事が投稿されている場合にツイートします。\ Microsoft Power Automate によって広島市立大学 Web ページの RSS フィードを取得し、新しい記事が投稿されている場合にツイートします。\
次の URL を監視しています。 次の URL を監視しています。
* [お知らせ|広島市立大学](https://www.hiroshima-cu.ac.jp/news/) * [お知らせ|広島市立大学](https://www.hiroshima-cu.ac.jp/news/)
* [お知らせ(在学生・保護者の方へ)|広島市立大学](https://www.hiroshima-cu.ac.jp/news_student/) * [お知らせ(在学生・保護者の方へ)|広島市立大学](https://www.hiroshima-cu.ac.jp/news_student/)
* [在学生・保護者の方へ|広島市立大学](https://www.hiroshima-cu.ac.jp/student/) * [在学生・保護者の方へ|広島市立大学](https://www.hiroshima-cu.ac.jp/student/)
# 関連リンク # 関連リンク
* [広島市立大学](https://www.hiroshima-cu.ac.jp/) * [広島市立大学](https://www.hiroshima-cu.ac.jp/)

View File

@@ -4,7 +4,7 @@ The following applies in addition to [yude.jp Terms of Service](https://yude.jp/
* Don't troll. * Don't troll.
* Don't cheat. * Don't cheat.
# List of available commands # Part of the list of available commands ()
* `/ll`: Switch the visibility of spawn checker. * `/ll`: Switch the visibility of spawn checker.
* `/mvspawn`: Teleport to spawn point of the world you're in. * `/mvspawn`: Teleport to spawn point of the world you're in.
@@ -17,6 +17,12 @@ You can also create a shared block by writing the player ID across multiple line
![Chest Protection](/images/minecraft/lockette/chest.png) ![Chest Protection](/images/minecraft/lockette/chest.png)
## Skills ## Skills
You can use skills powered by mcMMO. You can use skills powered by mcMMO.
## Warp
You can warp to registered points.
To show registered points, run `/warps`. To warp, run `/warp <name>`.
# Game specifications
* `keepInventory` is `true`, which means you won't drop inventory on death.
# Facility introduction # Facility introduction
## Shrine (by shirachan_1204) ## Shrine (by shirachan_1204)

View File

@@ -3,7 +3,7 @@
* ワールドのどこであっても自由に建築することができます。 * ワールドのどこであっても自由に建築することができます。
* トロール (荒らし) を行わないでください。 * トロール (荒らし) を行わないでください。
* チートを行わないでください。 * チートを行わないでください。
# 使用可能なコマンドの一覧 # 主な使用可能なコマンドの一覧
* `/ll`: スポーンチェッカーの表示を切り替えます。 * `/ll`: スポーンチェッカーの表示を切り替えます。
* `/mvspawn`: ワールドのスポーン地点へ転移します。 * `/mvspawn`: ワールドのスポーン地点へ転移します。
@@ -16,6 +16,12 @@
![Chest Protection](/images/minecraft/lockette/chest.png) ![Chest Protection](/images/minecraft/lockette/chest.png)
## スキル ## スキル
mcMMO を導入しているので、プラグインによるスキルを利用できます。 mcMMO を導入しているので、プラグインによるスキルを利用できます。
## ワープ
登録されている地点へワープできます。
`/warps` で登録地点の一覧を表示し、`/warp (登録名)` でワープします。
# ゲームの仕様
* `keepInventory``true` になっています。したがって、死亡によるインベントリーのドロップはありません。
# 施設紹介 # 施設紹介
## 神社 (by shirachan_1204) ## 神社 (by shirachan_1204)

23
docs/services/en.md Normal file
View File

@@ -0,0 +1,23 @@
# Available services on yude.jp
## Softwares
* [AutoMuteUs](https://github.com/denverquane/automuteus)\
Among Us helper; API: [`galactus.yude.jp`](https://galactus.yude.jp)
* [Nextcloud](https://nc.yude.jp)
* [Mastodon](https://mstdn.yude.jp)
* [Misskey](https://misskey.yude.jp)
* [Pleroma](https//pleroma.yude.jp)
* TeamSpeak 3: `yude.jp`
* [Gitea](https://git.yude.jp)
* [h5ai](https://files.yude.jp)
* [JMusicBot (forked)](https://discord.com/oauth2/authorize?client_id=429638220456656896&scope=bot&permissions=338963472)
* [Owncast](https://live.yude.jp)
* [Minecraft Server](https://yude.jp/minecraft)
## Anonymous communication
### Tor
* Relay: [yudejp](https://metrics.torproject.org/rs.html#details/CF762EF3C86B104C301511894547C72371F952A4)
* Hidden Service: [yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion](http://yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion)
### I2P
* Hidden Service: [yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p](http://yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p)

23
docs/services/ja.md Normal file
View File

@@ -0,0 +1,23 @@
# yude.jp で運用中のサービス
## ソフトウェア
* [AutoMuteUs](https://github.com/denverquane/automuteus)\
Among Us の自動ミュートボット; API: [`galactus.yude.jp`](https://galactus.yude.jp)
* [Nextcloud](https://nc.yude.jp)
* [Mastodon](https://mstdn.yude.jp)
* [Misskey](https://misskey.yude.jp)
* [Pleroma](https//pleroma.yude.jp)
* TeamSpeak 3: `yude.jp`
* [Gitea](https://git.yude.jp)
* [h5ai](https://files.yude.jp)
* [JMusicBot (フォーク)](https://discord.com/oauth2/authorize?client_id=429638220456656896&scope=bot&permissions=338963472)
* [Owncast](https://live.yude.jp)
* [Minecraft サーバー](https://yude.jp/minecraft)
## 秘匿化ネットワーク
### Tor
* リレー: [yudejp](https://metrics.torproject.org/rs.html#details/CF762EF3C86B104C301511894547C72371F952A4)
* Hidden Service: [yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion](http://yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion)
### I2P
* Hidden Service: [yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p](http://yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p)

View File

@@ -1,15 +0,0 @@
{
"locales": ["en", "ja"],
"defaultLocale": "ja",
"pages": {
"*": ["common"],
"/": ["index", "minecraft", "common"],
"/profile": ["profile", "common"],
"/server": ["server", "common"],
"/house": ["house", "common"],
"/tos": ["tos", "common"],
"/hcunews": ["hcunews", "common"],
"/minecraft": ["minecraft", "common"],
"/404": ["404", "common"]
}
}

12
i18n/index.js Normal file
View File

@@ -0,0 +1,12 @@
var ja = require('./translations.ja.json');
var en = require('./translations.en.json')
const i18n = {
translations: {
ja: ja,
en: en,
},
defaultLang: 'ja'
}
module.exports = i18n;

67
i18n/translations.en.json Normal file
View File

@@ -0,0 +1,67 @@
{
"caption": "The requested page does not exist on this website.",
"return": "Return to top",
"footer": "This page is provided under the MIT License.",
"source": "Source code",
"tos": "yude.jp Terms of Service",
"yes_playing": "Playing {{playing}}",
"listening": "Listening to {{listening}}",
"close": "Close",
"mutual": "Mutual links",
"status": "Service Status",
"icon_1": "Icon: ",
"icon_2": " ",
"post_list": "Posts listing",
"hcunews": "About @hcunews",
"house": "yude's house",
"home": "Home",
"profile": "yude's profile",
"blog": "yude's blog",
"status": "yude.jp Server Status",
"house": "yude's house",
"discord": "yude.jp Discord Server",
"mastodon": "Mastodon instance",
"title": "Minecraft Multiplayer",
"playing": "{{count}} player(s) online.",
"no_one": "No one is playing.",
"offline": "Server is down.",
"address": "Server address",
"fail": "Failed to retrieve server status.",
"loading": "Retrieving server status...",
"version": "Version",
"about": "About yude",
"desc": "Description",
"school": "Faculty of Information Science, Hiroshima City University.",
"hiroshima": "Hiroshima, Japan",
"location": "Location",
"link": "Links",
"link_all": "To see all of yude's account, please visit ",
"link_all_late": ".",
"here": "here",
"mail": "E-mail",
"birth": "Birthday",
"date": "November the 19th, 2001",
"contact": "Accounts",
"belongs": "Organization",
"grade": "B2",
"keys": "Public keys",
"download": "Download",
"fingerprint": "Digital fingerprint",
"view": "View",
"device": "Devices",
"account": "Accounts",
"wishlist": "Amazon Wishlist",
"status": "Server Status",
"location": "Location",
"tottori": "Tottori, Japan",
"hiroshima": "Hiroshima, Japan",
"model": "Model",
"region": "Region",
"service": "Service",
"shape": "Shape",
"tos": "yude.jp Terms of Service",
"input": "en",
"services": "Services",
"contents": "Contents",
"Blog": "Weblog"
}

67
i18n/translations.ja.json Normal file
View File

@@ -0,0 +1,67 @@
{
"caption": "要求されたページはこのウェブサイト上に存在しません。",
"return": "トップページへ戻る",
"footer": "このページは MIT License のもと提供されています。",
"source": "ソースコード",
"tos": "yude.jp サービス利用規約",
"yes_playing": "{{playing}} をプレイ中",
"listening": "{{listening}} を再生中",
"close": "閉じる",
"mutual": "相互リンク",
"status": "サービスの状態",
"icon_1": "アイコン: ",
"icon_2": "さん",
"post_list": "記事一覧",
"hcunews": "@hcunews について",
"house": "ゆでハウス",
"home": "ホーム",
"profile": "yude のプロフィール",
"blog": "yude のブログ",
"status": "yude.jp サーバー情報",
"house": "ゆでハウス",
"discord": "yude.jp Discord サーバー",
"mastodon": "Mastodon インスタンス",
"title": "Minecraft マルチプレイ",
"playing": "{{count}} 人がプレイしています。",
"no_one": "現在、誰もログインしていません。",
"offline": "サーバーがオフラインのようです。",
"address": "サーバー アドレス",
"fail": "サーバーの状態を取得できませんでした。",
"loading": "サーバーの状態を取得しています...",
"version": "バージョン",
"about": "yude について",
"desc": "概要",
"school": "広島市立大学 情報科学部",
"hiroshima": "日本, 広島県",
"location": "所在地",
"link": "リンク",
"link_all": "yude が所持しているすべてのアカウントの一覧は、",
"link_all_late": "にあります。",
"here": "こちら",
"mail": "メール",
"birth": "生年月日",
"date": "2001年11月19日",
"contact": "アカウント",
"belongs": "所属",
"grade": "2年",
"keys": "公開鍵",
"download": "ダウンロード",
"fingerprint": "電子指紋",
"view": "閲覧",
"device": "デバイス",
"account": "アカウント",
"wishlist": "Amazon ほしいものリスト",
"status": "サーバー情報",
"location": "場所",
"tottori": "日本, 鳥取県",
"hiroshima": "日本, 広島県",
"model": "モデル",
"region": "リージョン",
"service": "サービス",
"shape": "シェイプ",
"tos": "yude.jp サービス利用規約",
"input": "ja",
"services": "サービス",
"contents": "コンテンツ",
"blog": "ブログ"
}

View File

@@ -1,6 +0,0 @@
import { createClient } from 'microcms-js-sdk';
export const client = createClient({
serviceDomain: 'yude',
apiKey: process.env.MICROCMS_API_KEY,
});

View File

@@ -1,4 +0,0 @@
{
"caption": "The requested page does not exist on this website.",
"return": "Return to top"
}

View File

@@ -1,13 +0,0 @@
{
"footer": "This page is provided under the MIT License.",
"source": "Source code",
"tos": "yude.jp Terms of Service",
"yes_playing": "Playing {{playing}}",
"listening": "Listening to {{listening}}",
"close": "Close",
"mutual": "Mutual links",
"status": "Service Status",
"icon_1": "Icon: ",
"icon_2": "",
"post_list": "Posts listing"
}

View File

@@ -1,3 +0,0 @@
{
"hcunews": "About @hcunews"
}

View File

@@ -1,3 +0,0 @@
{
"house": "yude's house"
}

View File

@@ -1,9 +0,0 @@
{
"home": "Home",
"profile": "yude's profile",
"blog": "yude's blog",
"status": "yude.jp Server Status",
"house": "yude's house",
"discord": "yude.jp Discord Server",
"mastodon": "Mastodon instance"
}

View File

@@ -1,10 +0,0 @@
{
"title": "Minecraft Multiplayer",
"playing": "{{count}} player(s) online.",
"no_one": "No one is playing.",
"offline": "Server is down.",
"address": "Server address",
"fail": "Failed to retrieve server status.",
"loading": "Retrieving server status...",
"version": "Version"
}

View File

@@ -1,23 +0,0 @@
{
"about": "About yude",
"desc": "Description",
"school": "Faculty of Information Science, Hiroshima City University.",
"hiroshima": "Hiroshima, Japan",
"location": "Location",
"link": "Links",
"link_all": "To see all of yude's account, please visit ",
"link_all_late": ".",
"here": "here",
"mail": "E-mail",
"birth": "Birthday",
"date": "November the 19th, 2001",
"contact": "Get in touch",
"belongs": "Organization",
"grade": "B2",
"keys": "Public keys",
"download": "Download",
"fingerprint": "Digital fingerprint",
"view": "View",
"device": "Devices",
"account": "Accounts"
}

View File

@@ -1,10 +0,0 @@
{
"status": "Server Status",
"location": "Location",
"tottori": "Tottori, Japan",
"hiroshima": "Hiroshima, Japan",
"model": "Model",
"region": "Region",
"service": "Service",
"shape": "Shape"
}

View File

@@ -1,4 +0,0 @@
{
"tos": "yude.jp Terms of Service",
"input": "en"
}

View File

@@ -1,4 +0,0 @@
{
"caption": "要求されたページはこのウェブサイト上に存在しません。",
"return": "トップページへ戻る"
}

View File

@@ -1,13 +0,0 @@
{
"footer": "このページは MIT License のもと提供されています。",
"source": "ソースコード",
"tos": "yude.jp サービス利用規約",
"yes_playing": "{{playing}} をプレイ中",
"listening": "{{listening}} を再生中",
"close": "閉じる",
"mutual": "相互リンク",
"status": "サービスの状態",
"icon_1": "アイコン: ",
"icon_2": "さん",
"post_list": "記事一覧"
}

View File

@@ -1,3 +0,0 @@
{
"hcunews": "@hcunews について"
}

View File

@@ -1,3 +0,0 @@
{
"house": "ゆでハウス"
}

View File

@@ -1,9 +0,0 @@
{
"home": "ホーム",
"profile": "yude のプロフィール",
"blog": "yude のブログ",
"status": "yude.jp サーバー情報",
"house": "ゆでハウス",
"discord": "yude.jp Discord サーバー",
"mastodon": "Mastodon インスタンス"
}

View File

@@ -1,10 +0,0 @@
{
"title": "Minecraft マルチプレイ",
"playing": "{{count}} 人がプレイしています。",
"no_one": "現在、誰もログインしていません。",
"offline": "サーバーがオフラインのようです。",
"address": "サーバー アドレス",
"fail": "サーバーの状態を取得できませんでした。",
"loading": "サーバーの状態を取得しています...",
"version": "バージョン"
}

View File

@@ -1,23 +0,0 @@
{
"about": "yude について",
"desc": "概要",
"school": "広島市立大学 情報科学部",
"hiroshima": "日本, 広島県",
"location": "所在地",
"link": "リンク",
"link_all": "yude が所持しているすべてのアカウントの一覧は、",
"link_all_late": "にあります。",
"here": "こちら",
"mail": "メール",
"birth": "生年月日",
"date": "2001年11月19日",
"contact": "連絡先 / SNS",
"belongs": "所属",
"grade": "2年",
"keys": "公開鍵",
"download": "ダウンロード",
"fingerprint": "電子指紋",
"view": "閲覧",
"device": "デバイス",
"account": "アカウント"
}

View File

@@ -1,10 +0,0 @@
{
"status": "サーバー情報",
"location": "場所",
"tottori": "日本, 鳥取県",
"hiroshima": "日本, 広島県",
"model": "モデル",
"region": "リージョン",
"service": "サービス",
"shape": "シェイプ"
}

View File

@@ -1,4 +0,0 @@
{
"tos": "yude.jp サービス利用規約",
"input": "ja"
}

View File

@@ -1,12 +1,19 @@
const nextTranslate = require('next-translate') const rewrites = async () => {
return [
module.exports = nextTranslate({ {
i18n: { source: '/minecraft/players/:uuid(\[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})',
locales: ['ja', 'en'], destination: '/minecraft/players/:uuid'
defaultLocale: 'ja',
}, },
{
source: '/minecraft/players/:ign',
destination: '/minecraft/lookup/:ign'
}
]
}
module.exports = {
images: { images: {
domains: ['mackerel.io', 'mc-heads.net'], domains: ['mackerel.io', 'mc-heads.net', 'crafatar.com'],
}, },
webpack: function (config) { webpack: function (config) {
config.module.rules.push({ config.module.rules.push({
@@ -15,4 +22,19 @@ module.exports = nextTranslate({
}) })
return config return config
}, },
}) async redirects() {
return [
{
source: '/wishlist',
destination: 'https://www.amazon.jp/hz/wishlist/ls/8WTKCPWKOJ2N?ref_=wl_share',
permanent: true,
},
{
source: '/scrapbox',
destination: 'https://scrapbox.io/yude',
permanent: true,
}
]
},
rewrites,
}

View File

@@ -7,7 +7,8 @@
"dev": "next", "dev": "next",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"export": "next export" "export": "next export",
"lint": "next lint"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -21,39 +22,44 @@
}, },
"homepage": "https://github.com/yudemoe/yude.jp#readme", "homepage": "https://github.com/yudemoe/yude.jp#readme",
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.35", "@babel/core": "^7.15.5",
"@fortawesome/free-brands-svg-icons": "^5.15.3", "@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.3", "@fortawesome/free-brands-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.14", "@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.15",
"@tailwindcss/typography": "^0.4.0", "@tailwindcss/typography": "^0.4.0",
"autoprefixer": "^10.2.5", "autoprefixer": "^10.3.4",
"axios": "^0.21.1", "axios": "^0.21.4",
"microcms-js-sdk": "^1.2.0", "date-fns": "^2.24.0",
"moment": "^2.29.1", "moment": "^2.29.4",
"next": "^11.1.1", "next": "^12.1.0",
"next-seo": "^4.26.0", "next-export-i18n": "^1.2.1",
"next-themes": "^0.0.14", "next-seo": "^4.28.1",
"next-translate": "^1.0.7", "next-themes": "^0.0.15",
"next-translate": "^1.2.0",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"postcss": "^8.3.0", "postcss": "^8.3.6",
"prop-types": "^15.7.2",
"querystring": "^0.2.1", "querystring": "^0.2.1",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-markdown": "^6.0.2", "react-markdown": "^7.0.1",
"react-moment": "^1.1.1", "react-moment": "^1.1.1",
"react-switch": "^6.0.0", "react-switch": "^6.0.0",
"remark-gfm": "^1.0.0", "remark-gfm": "^2.0.0",
"swr": "^0.5.6", "swr": "^1.0.1",
"tailwindcss": "^2.1.4", "tailwindcss": "^2.2.15",
"tailwindcss-filters": "^3.0.0", "tailwindcss-filters": "^3.0.0",
"tailwindcss-responsive-embed": "^1.0.0", "tailwindcss-responsive-embed": "^1.0.0",
"webpack": "^5.37.1" "webpack": "^5.53.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^15.6.0", "@types/node": "^16.9.6",
"@types/react": "^17.0.6", "@types/react": "^17.0.24",
"babel-plugin-inline-react-svg": "^2.0.1", "babel-plugin-inline-react-svg": "^2.0.1",
"typescript": "^4.2.4" "eslint": "7.32.0",
"eslint-config-next": "11.1.2",
"typescript": "^4.4.3"
} }
} }

View File

@@ -1,29 +0,0 @@
// Base layout
import Layout from "./components/Layout"
// React Router
import { useRouter } from 'next/router'
// Next.js
import Link from 'next/link'
import useTranslation from 'next-translate/useTranslation'
export default function Custom404(props) {
const router = useRouter()
const { locale, locales, defaultLocale, pathname } = router
const { t, lang } = useTranslation("404")
return (
<Layout title="404">
<div className="text-center mb-10 mt-10">
<p className="text-3xl">404</p>
<p className="text-xl">{t('caption')}</p>
<Link href="/">
<a>
<p className="mt-5">{t('return')}</p>
</a>
</Link>
</div>
</Layout>
)
}

View File

@@ -1,58 +0,0 @@
import querystring from 'querystring';
const {
SPOTIFY_CLIENT_ID: client_id,
SPOTIFY_CLIENT_SECRET: client_secret,
SPOTIFY_REFRESH_TOKEN: refresh_token,
} = process.env;
const basic = Buffer.from(`${client_id}:${client_secret}`).toString('base64');
const NOW_PLAYING_ENDPOINT = `https://api.spotify.com/v1/me/player/currently-playing`;
const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`;
const getAccessToken = async () => {
const response = await fetch(TOKEN_ENDPOINT, {
method: 'POST',
headers: {
Authorization: `Basic ${basic}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: querystring.stringify({
grant_type: 'refresh_token',
refresh_token,
}),
});
return response.json();
};
export const getNowPlaying = async () => {
const { access_token } = await getAccessToken();
return fetch(NOW_PLAYING_ENDPOINT, {
headers: {
Authorization: `Bearer ${access_token}`,
},
});
};
export default async (_, res) => {
const response = await getNowPlaying();
if (response.status === 204 || response.status > 400) {
return res.status(200).json({ isPlaying: false });
}
const song = await response.json();
const isPlaying = song.is_playing;
const title = song.item.name;
const artist = song.item.artists.map((_artist) => _artist.name).join(', ');
const album = song.item.album.name;
return res.status(200).json({
album,
artist,
isPlaying,
title,
});
};

View File

@@ -1,44 +1,38 @@
// React
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import axios from 'axios';
import useTranslation from 'next-translate/useTranslation'
import { useRouter } from 'next/router'
function App (){ // Data fetching
const router = useRouter() import useSwr from 'swr'
const { locale, locales, defaultLocale, pathname } = router const fetcher = (url) => fetch(url).then((res) => res.json())
const { t, lang } = useTranslation("common")
const [data, setData] = useState({ hits: [] }); // i18n
useEffect(() => { import { useTranslation, useLanguageQuery } from 'next-export-i18n';
const fetchData = async () => {
const result = await axios( export default function DiscordPlaying() {
'https://discord.com/api/guilds/723409709306216498/widget.json', const { t } = useTranslation();
); const [query] = useLanguageQuery();
setData(result.data);
};
fetchData();
}, []);
if (data === undefined){
console.log("[Discord API] データの取得に失敗しました。 / Failed to retrieve data.")
return <p></p>
}else{
const str = JSON.stringify(data)
if (str.indexOf("game") !== -1){ const { data, error } = useSwr(
const yes_playing = t('yes_playing', {playing: data.members[0].game.name}) `https://discord.com/api/guilds/723409709306216498/widget.json`,
return <p>{yes_playing}</p> fetcher
}else{ )
return <p></p> if (error){
} console.log("[Discord API] データの取得に失敗しました。 / Failed to retrieve data.")
return <></>
} else {
if (!data) {
return <p>Loading...</p>
} else {
if (data.members) {
if (data.members[0].game) {
const yes_playing = t('yes_playing', {playing: data.members[0].game.name})
return <p>{yes_playing}</p>
} else {
return <></>
}
} else {
return <></>
}
}
} }
};
export async function getServerSideProps() {
// Fetch data from external API
const res = await fetch(url)
const data = await res.json()
// Pass data to the page via props
return { props: { data } }
} }
export default App;

View File

@@ -1,4 +1,7 @@
// React
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
// Data fetching
import axios from 'axios'; import axios from 'axios';
const App = () => { const App = () => {

View File

@@ -1,19 +0,0 @@
// Next.js
import Link from 'next/link'
import Image from 'next/image'
const happybusy = (props) => {
return (
<Link href="https://www.eff.org/pages/blue-ribbon-campaign">
<a>
<Image
src="/images/brstrip.gif"
width={150}
height={41}
/>
</a>
</Link>
)
}
export default happybusy

View File

@@ -1,13 +1,15 @@
// Tailwind CSS
import "tailwindcss/tailwind.css"; import "tailwindcss/tailwind.css";
import Link from 'next/link';
import useTranslation from 'next-translate/useTranslation'
import { useRouter } from 'next/router'
export default function Footer(props) {
const router = useRouter()
const { locale, locales, defaultLocale, pathname } = router
const { t, lang } = useTranslation("common")
// Next.js
import Link from 'next/link';
// i18n
import { useTranslation, useLanguageQuery } from 'next-export-i18n';
export default function Footer(props) {
const { t } = useTranslation();
const [query] = useLanguageQuery();
return ( return (
<> <>
<div className="container mx-auto px-6"> <div className="container mx-auto px-6">

View File

@@ -1,15 +1,16 @@
// Next.js // Next.js
import Link from 'next/link' import Link from 'next/link'
import Image from 'next/image'
const HappyBusy = (props) => { const HappyBusy = (props) => {
return ( return (
<Link href="https://sites.google.com/site/happybusy/"> <Link href="https://sites.google.com/site/happybusy/">
<a> <a>
<Image <img
src="/images/busy_banner.png" src="/images/busy_banner.png"
width={200} width={200}
height={42} height={42}
alt="時間のないサイト運営者リング"
className="mx-auto"
/> />
</a> </a>
</Link> </Link>

View File

@@ -1,14 +1,14 @@
import React from "react"; import React from "react";
import Popper from "popper.js"; import Popper from "popper.js";
import { useRouter } from 'next/router'
import Link from 'next/link'; import Link from 'next/link';
import { faLanguage } from '@fortawesome/free-solid-svg-icons' import { faLanguage } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
const Dropdown = ({ color }) => { // i18n
const router = useRouter() import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
const { locale, locales, defaultLocale, pathname } = router
const Dropdown = ({ color }) => {
// dropdown props // dropdown props
const [dropdownPopoverShow, setDropdownPopoverShow] = React.useState(false); const [dropdownPopoverShow, setDropdownPopoverShow] = React.useState(false);
const btnDropdownRef = React.createRef(); const btnDropdownRef = React.createRef();
@@ -31,7 +31,7 @@ const Dropdown = ({ color }) => {
<> <>
<div className="text-left mr-2 ml-2 my-3 float-right"> <div className="text-left mr-2 ml-2 my-3 float-right">
<button type="button" className="inline-flex justify-center w-full rounded-md border border-gray-300 dark:border-gray-800 shadow-sm px-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 dark:text-white focus:outline-none" id="options-menu" aria-haspopup="true" aria-expanded="true" <button type="button" className="inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-800 shadow-sm px-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 dark:text-white focus:outline-none h-10" id="options-menu" aria-haspopup="true" aria-expanded="true"
style={{ transition: "all .15s ease" }} style={{ transition: "all .15s ease" }}
ref={btnDropdownRef} ref={btnDropdownRef}
onClick={() => { onClick={() => {
@@ -40,20 +40,20 @@ const Dropdown = ({ color }) => {
: openDropdownPopover(); : openDropdownPopover();
}} }}
> >
<FontAwesomeIcon icon={faLanguage} className="w-12 h-9" /> <FontAwesomeIcon icon={faLanguage} size="3x" />
<svg className="-mr-1 ml-2 h-9 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <svg className="-mr-1 ml-2 h-9 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fillRule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" /> <path fillRule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" />
</svg> </svg>
</button> </button>
<div ref={popoverDropdownRef} className={ <div ref={popoverDropdownRef} className={
(dropdownPopoverShow ? "block " : "hidden ") + "z-10 origin-top-right absolute right-0 mt-2 w-40 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 dark:bg-gray-700"}> (dropdownPopoverShow ? "block " : "hidden ") + "z-10 origin-top-right absolute right-0 mt-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 dark:bg-gray-700"}>
<div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu"> <div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
<Link href="#" locale="ja"> <LanguageSwitcher lang="ja">
<a href="#" className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">日本語</a> <a href="#" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">日本語</a>
</Link> </LanguageSwitcher>
<Link href="#" locale="en"> <LanguageSwitcher lang="en">
<a href="#" className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">English</a> <a href="#" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">English</a>
</Link> </LanguageSwitcher>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,21 +1,19 @@
// Next.js
import Head from "next/head" import Head from "next/head"
// Tailwind CSS
import "tailwindcss/tailwind.css"; import "tailwindcss/tailwind.css";
import useTranslation from 'next-translate/useTranslation'
import { useRouter } from 'next/router' // React
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
// Components
import Footer from "./Footer/Footer" import Footer from "./Footer/Footer"
import Navbar from "./Navbar" import Navbar from "./Navbar"
const Layout = (props) => { const Layout = (props) => {
const { title, children } = props const { title, children } = props
const siteTitle = "yude.jp" const siteTitle = "yude.jp"
const router = useRouter()
const { locale, locales, defaultLocale, pathname } = router
const { t, lang } = useTranslation("common")
const footer = t('footer')
const source = t('source')
const tos = t('tos')
return ( return (
<div className="page"> <div className="page">
<Head> <Head>

View File

@@ -5,13 +5,13 @@ import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const FontAwesomeMenu = (props) => { const FontAwesomeMenu = (props) => {
const { icon, dest } = props const { icon, dest, query } = props
return ( return (
<div> <div>
<Link href={`${dest}`}> <Link href={{ pathname: dest, query: query }}>
<a> <a>
<FontAwesomeIcon icon={icon} className="w-10 h-10 fill-current inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" /> <FontAwesomeIcon icon={icon} size="5x" className="w-9 h-9 fill-current inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" />
</a> </a>
</Link> </Link>
</div> </div>

View File

@@ -1,10 +1,15 @@
// Next.js // Next.js
import Link from 'next/link' import Link from 'next/link'
const MinecraftMenu = () => { const MinecraftMenu = (props) => {
const { query } = props
if (!query) {
return <p>Loading...</p>
} else {
return ( return (
<div> <div>
<Link href="/minecraft"> <Link href={{ pathname: "/minecraft", query: query }}>
<a> <a>
<svg className="fill-current text-black dark:text-white w-10 h-10 inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 304.8 304.8"> <svg className="fill-current text-black dark:text-white w-10 h-10 inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 304.8 304.8">
<path d="M 39.10262 126.138 L 39.16748 12.39574 L 152.7982 12.33506 L 266.4289 12.27438 L 266.4289 126.0773 L 266.4289 239.8803 L 152.7333 239.8803 L 39.03775 239.8803 L 39.10262 126.138 Z M 260.4857 126.0776 L 260.4857 18.55703 L 152.8628 18.55703 L 45.23985 18.55703 L 45.23985 126.0776 L 45.23985 233.5982 L 152.8628 233.5982 L 260.4857 233.5982 L 260.4857 126.0776 Z M 103.8963 162.9245 L 103.8963 126.0776 L 116.1702 126.0776 L 128.4441 126.0776 L 128.4441 113.8758 L 128.4441 101.674 L 152.8628 101.674 L 177.2814 101.674 L 177.2814 113.8758 L 177.2814 126.0776 L 189.3835 126.0776 L 201.4856 126.0776 L 201.6573 150.5415 C 201.7517 163.9967 201.829 180.5779 201.8291 187.3885 L 201.8293 199.7715 L 189.6869 199.7715 L 177.5446 199.7715 L 177.4776 187.5093 L 177.4106 175.2471 L 152.7982 175.1855 L 128.1857 175.1239 L 128.1857 187.4477 L 128.1857 199.7715 L 116.041 199.7715 L 103.8963 199.7715 L 103.8963 162.9245 Z M 79.34843 77.02888 L 79.34843 52.62534 L 103.7671 52.62534 L 128.1857 52.62534 L 128.1857 77.02888 L 128.1857 101.4324 L 103.7671 101.4324 L 79.34843 101.4324 L 79.34843 77.02888 Z M 177.5398 77.02888 L 177.5398 52.62534 L 201.9585 52.62534 L 226.3771 52.62534 L 226.3771 77.02888 L 226.3771 101.4324 L 201.9585 101.4324 L 177.5398 101.4324 L 177.5398 77.02888 Z"/> <path d="M 39.10262 126.138 L 39.16748 12.39574 L 152.7982 12.33506 L 266.4289 12.27438 L 266.4289 126.0773 L 266.4289 239.8803 L 152.7333 239.8803 L 39.03775 239.8803 L 39.10262 126.138 Z M 260.4857 126.0776 L 260.4857 18.55703 L 152.8628 18.55703 L 45.23985 18.55703 L 45.23985 126.0776 L 45.23985 233.5982 L 152.8628 233.5982 L 260.4857 233.5982 L 260.4857 126.0776 Z M 103.8963 162.9245 L 103.8963 126.0776 L 116.1702 126.0776 L 128.4441 126.0776 L 128.4441 113.8758 L 128.4441 101.674 L 152.8628 101.674 L 177.2814 101.674 L 177.2814 113.8758 L 177.2814 126.0776 L 189.3835 126.0776 L 201.4856 126.0776 L 201.6573 150.5415 C 201.7517 163.9967 201.829 180.5779 201.8291 187.3885 L 201.8293 199.7715 L 189.6869 199.7715 L 177.5446 199.7715 L 177.4776 187.5093 L 177.4106 175.2471 L 152.7982 175.1855 L 128.1857 175.1239 L 128.1857 187.4477 L 128.1857 199.7715 L 116.041 199.7715 L 103.8963 199.7715 L 103.8963 162.9245 Z M 79.34843 77.02888 L 79.34843 52.62534 L 103.7671 52.62534 L 128.1857 52.62534 L 128.1857 77.02888 L 128.1857 101.4324 L 103.7671 101.4324 L 79.34843 101.4324 L 79.34843 77.02888 Z M 177.5398 77.02888 L 177.5398 52.62534 L 201.9585 52.62534 L 226.3771 52.62534 L 226.3771 77.02888 L 226.3771 101.4324 L 201.9585 101.4324 L 177.5398 101.4324 L 177.5398 77.02888 Z"/>
@@ -14,5 +19,6 @@ const MinecraftMenu = () => {
</div> </div>
) )
} }
}
export default MinecraftMenu export default MinecraftMenu

View File

@@ -1,15 +1,14 @@
// React
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import useTranslation from 'next-translate/useTranslation'
import { useRouter } from 'next/router' // i18n
import { useTranslation, useLanguageQuery } from 'next-export-i18n';
import axios from 'axios'; import axios from 'axios';
import Image from 'next/image'
import { list } from 'postcss';
export default function Minecraft(props) { export default function Minecraft(props) {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("minecraft")
const [data, setData] = useState({ hits: [] }); const [data, setData] = useState({ hits: [] });
useEffect(() => { useEffect(() => {
@@ -25,7 +24,7 @@ export default function Minecraft(props) {
if (data === undefined){ if (data === undefined){
console.log("[Minecraft Query] データの取得に失敗しました。 / Failed to retrieve data.") console.log("[Minecraft Query] データの取得に失敗しました。 / Failed to retrieve data.")
return ( return (
<p>{t('minecraft:fail')}</p> <p>{t('fail')}</p>
) )
}else{ }else{
const status = data.online const status = data.online
@@ -36,13 +35,13 @@ export default function Minecraft(props) {
{(() => { {(() => {
if (status == true) { if (status == true) {
if (player == undefined || player == 0) { if (player == undefined || player == 0) {
return <span>{t('minecraft:no_one')}</span> return <span>{t('no_one')}</span>
} else { } else {
return <span>{t('minecraft:playing', {count: player})}</span> return <span>{t('playing', {count: player})}</span>
}}else if (status == false) { }}else if (status == false) {
return <span>{t('minecraft:offline')}</span> return <span>{t('offline')}</span>
}else { }else {
return <span>{t('minecraft:loading')}</span> return <span>{t('loading')}</span>
} }
})()} })()}
@@ -54,7 +53,7 @@ export default function Minecraft(props) {
url.push('https://mc-heads.net/avatar/' + data.players.list[i]) url.push('https://mc-heads.net/avatar/' + data.players.list[i])
} }
for (var i in url){ for (var i in url){
list.push(<Image src={url[i]} key={i} className="inline" height="50" width="50" />) list.push(<img src={url[i]} key={i} className="inline" height="50" width="50" alt={i}/>)
} }
return <div>{list}</div> return <div>{list}</div>
} }

View File

@@ -0,0 +1,33 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App (props) {
const uuid = props;
const [data, setData] = useState({ hits: [] });
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://playersbio.yude.jp/' + uuid.uuid,
);
setData(result.data);
};
fetchData();
}, []);
if (data === undefined){
console.log("[Minecraft: PlayersBio] データの取得に失敗しました。 / Failed to retrieve data.")
return <p></p>
}else {
if (data.toString() == "[object Object]"){
return <p>読み込み中...</p>
} else {
if (data.toString() == "") {
return <p>ひとことは設定されていません...</p>
} else {
return <p>ひとこと: <span className="italic">{data.toString()}</span></p>
}
}
};
}
export default App;

View File

@@ -0,0 +1,30 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useRouter } from 'next/router'
function App (props) {
const uuid = props;
const [data, setData] = useState({ hits: [] });
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://minecraft.yude.jp/group/' + uuid.uuid,
);
setData(result.data);
};
fetchData();
}, []);
if (data === undefined || data === null){
return <p></p>
}else {
if (data.toString() == "staff") {
return <span className="inline-flex items-center justify-center px-3 py-2 text-base font-bold leading-none text-indigo-100 bg-indigo-700 rounded ml-3">Staff</span>
} else {
return <></>
}
};
}
export default App;

View File

@@ -0,0 +1,15 @@
import React, { useState, useEffect } from 'react';
function App (props) {
const uuid = props;
return (
<img
src={"https://crafatar.com/renders/body/" + uuid.uuid}
width={110}
height={250}
/>
)
}
export default App;

View File

@@ -0,0 +1,65 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function App (props) {
const uuid = props;
const [data, setData] = useState({ hits: [] });
const timeAgo = (prevDate) => {
const diff = Number(new Date()) - prevDate;
const minute = 60 * 1000;
const hour = minute * 60;
const day = hour * 24;
const month = day * 30;
const year = day * 365;
switch (true) {
case diff < minute:
const seconds = Math.round(diff / 1000);
return `${seconds} 秒前`
case diff < hour:
return Math.round(diff / minute) + ' 分前';
case diff < day:
return Math.round(diff / hour) + ' 時間前';
case diff < month:
return Math.round(diff / day) + ' 日前';
case diff < year:
return Math.round(diff / month) + ' ヶ月前';
case diff > year:
return Math.round(diff / year) + ' 年前';
default:
return "";
}
};
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://minecraft.yude.jp/last/' + uuid.uuid,
);
setData(result.data);
};
fetchData();
}, []);
if (data === undefined){
console.log("[Minecraft: 最終プレイ日時] データの取得に失敗しました。 / Failed to retrieve data.")
return <p></p>
}else {
if (data.toString() == "[object Object]") {
return <p>取得中です...</p>
} else {
if (data.toString() == "not_found") {
return <></>
} else {
let dateTime = new Date(parseInt(data.toString()) * 1000);
return (
<div className='has-tooltip'>
<span className='tooltip rounded shadow-lg p-1 bg-gray-100 text-red-500 -mt-8'>{dateTime.toLocaleDateString() + " " + dateTime.toLocaleTimeString()}</span>
最終ログイン: {timeAgo(dateTime)}
</div>
)
}
}
};
}
export default App;

View File

@@ -0,0 +1,44 @@
// React
import React, { useState, useEffect } from 'react';
// Data fetching
import axios from 'axios';
// i18n
import { useTranslation, useLanguageQuery } from 'next-export-i18n';
// Components
import LastPlayed from './LastPlayed'
function App (props) {
const { t } = useTranslation();
const [query] = useLanguageQuery();
const uuid = props;
const [data, setData] = useState({ hits: [] });
useEffect(() => {
const fetchData = async () => {
const result = await axios(
'https://minecraft.yude.jp/online/' + uuid.uuid,
);
setData(result.data);
};
fetchData();
}, []);
if (data === undefined){
console.log("[Minecraft: オンライン状況] データの取得に失敗しました。 / Failed to retrieve data.")
return <p></p>
}else {
if (data.toString() == "false") {
return <LastPlayed uuid={uuid.uuid} />
} else {
if (data.toString() == "true") {
return <p>オンライン</p>
} else {
return <p>取得中...</p>
}
}
};
}
export default App;

View File

@@ -0,0 +1,38 @@
// React
import React, { useState, useEffect } from 'react';
// Data fetching
import axios from 'axios';
function App (props) {
const uuid = props;
const [data, setData] = useState({ hits: [] });
useEffect(() => {
const fetchData = async () => {
let result = null;
try {
result = await axios('https://api.ashcon.app/mojang/v2/user/' + uuid.uuid);
setData(result.data);
} catch (err) {
result = 404;
setData(result);
}
};
fetchData();
}, []);
if (data === undefined){
console.log("[Minecraft: UUID to player's name] データの取得に失敗しました。 / Failed to retrieve data.")
return <>取得中...</>
}else {
if (data === 404) {
return <>404</>
} else {
return (
<>{data.username}</>
)
}
};
}
export default App;

View File

@@ -0,0 +1,39 @@
// Component
import Group from './Group';
// Data fetching
import useSwr from 'swr'
const fetcher = (url) => fetch(url).then((res) => res.json())
function App (props) {
const uuid = props;
const { data, error } = useSwr(
uuid.uuid ? `https://api.ashcon.app/mojang/v2/user/${uuid.uuid}` : null,
fetcher
)
if (error) {
return (
<>エラーが発生しました</>
)
} else {
if (!data) {
return (
<>読み込み中...</>
)
} else {
return (
<>
<div className='has-tooltip'>
<span className='tooltip rounded shadow-lg p-1 bg-gray-100 text-red-500 -mt-8 font-mono text-sm'>UUID: {uuid.uuid}</span>
<p className="text-2xl inline">{data.username}</p>
<Group uuid={uuid.uuid} />
</div>
</>
)
}
}
}
export default App;

View File

@@ -0,0 +1,25 @@
// Components
import Online from './Online'
import Head from './Head'
import PlayerNameHolder from './PlayerNameHolder'
import Biography from './Biography'
function App (props) {
const uuid = props;
return (
<div className="w-full flex flex-wrap">
<div>
<Head uuid={uuid.uuid} />
</div>
<div className="w-5"></div>
<div>
<p className="text-2xl text-mono"><PlayerNameHolder uuid={uuid.uuid} /></p>
<p><Online uuid={uuid.uuid} /></p>
<p><Biography uuid={uuid.uuid} /></p>
</div>
</div>
)
}
export default App;

View File

@@ -0,0 +1,9 @@
function App (props) {
return (
<div className="text-center">
<h2>入力された UUID またはプレイヤー名に該当するプレイヤーが見つかりませんでした</h2>
</div>
)
}
export default App;

View File

@@ -1,13 +1,24 @@
// Tailwind CSS
import "tailwindcss/tailwind.css"; import "tailwindcss/tailwind.css";
// Next.js
import Link from 'next/link'; import Link from 'next/link';
// Components
import LangSelector from "./LangSelector" import LangSelector from "./LangSelector"
import ThemeSelector from "./ThemeSelector" import ThemeSelector from "./ThemeSelector"
// i18n
import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
const Navbar = () => { const Navbar = () => {
const { t } = useTranslation();
const [query] = useLanguageQuery();
return ( return (
<> <>
<nav className='flex items-center flex-wrap p-3'> <nav className='flex items-center flex-wrap p-3'>
<Link href='/'> <Link href={{ pathname: '/', query: query }}>
<a className='inline-flex items-center p-2'> <a className='inline-flex items-center p-2'>
<span className='text-xl text-black font-bold tracking-wide dark:text-white font-mono animate-heartbeat'> <span className='text-xl text-black font-bold tracking-wide dark:text-white font-mono animate-heartbeat'>
yude.jp yude.jp

View File

@@ -7,10 +7,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
const Button = (props) => { const Button = (props) => {
const { icon, dest, caption } = props const { icon, dest, caption } = props
return ( return (
<Link href={`${dest}`}> <Link href={{ pathname: dest }}>
<a> <a>
<button <button
className="bg-pink-600 text-white active:bg-pink-600 mt-3 font-bold text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" className="bg-pink-600 text-white active:bg-pink-600 mt-3 font-bold text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
type="button" type="button"
> >
<FontAwesomeIcon icon={icon} className="w-5 h-5 inline"/> {caption} <FontAwesomeIcon icon={icon} className="w-5 h-5 inline"/> {caption}

View File

@@ -8,9 +8,9 @@ const Contact = (props) => {
const { icon, dest, caption } = props const { icon, dest, caption } = props
return ( return (
<div className="hover:underline"> <div className="hover:underline">
<Link href={`${dest}`}> <Link href={{ pathname: dest }}>
<a> <a>
<FontAwesomeIcon icon={icon} className="w-7 h-7 inline lg:w-10 lg:h-10 md:w-7 md:h-7"/> <FontAwesomeIcon icon={icon} size="5x" className="w-9 h-9 fill-current inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" />
<p className="font-mono text-xl">{caption}</p> <p className="font-mono text-xl">{caption}</p>
</a> </a>
</Link> </Link>

View File

@@ -1,20 +1,20 @@
// React
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import useTranslation from 'next-translate/useTranslation'
// i18n
import { useTranslation, useLanguageQuery } from 'next-export-i18n';
// Font Awesome
import { faKey, faEye, faDownload } from '@fortawesome/free-solid-svg-icons' import { faKey, faEye, faDownload } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useRouter } from 'next/router'
// Next.js
import Link from 'next/link' import Link from 'next/link'
export default function Modal() { export default function Modal() {
const [showModal, setShowModal] = React.useState(false); const [showModal, setShowModal] = React.useState(false);
const router = useRouter() const { t } = useTranslation();
const { t, lang } = useTranslation("common") const [query] = useLanguageQuery();
const { locale, locales, defaultLocale, pathname } = router
const close = t('common:close')
const keys = t('profile:keys')
const view = t('profile:view')
const fingerprint = t('profile:fingerprint')
const download = t('profile:download')
return ( return (
<> <>
@@ -23,7 +23,7 @@ export default function Modal() {
type="button" type="button"
onClick={() => setShowModal(true)} onClick={() => setShowModal(true)}
> >
<FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {keys} <FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {t('keys')}
</button> </button>
{showModal ? ( {showModal ? (
<> <>
@@ -36,17 +36,17 @@ export default function Modal() {
{/* Modal body */} {/* Modal body */}
<div className="relative p-2 flex-auto text-black text-left"> <div className="relative p-2 flex-auto text-black text-left">
<p className="text-2xl"><FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {keys}</p> <p className="text-2xl"><FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {t('keys')}</p>
<ul className="list-disc my-2"> <ul className="list-disc my-2">
<li> <li>
<span className="font-bold">PGP&nbsp;</span> <span className="font-bold">PGP&nbsp;</span>
<Link href="/yudejp.gpg"> <Link href="/yudejp.gpg">
<a className="hover:underline"> <a className="hover:underline">
<FontAwesomeIcon icon={faDownload} className="w-5 h-5 inline"/>&nbsp; <FontAwesomeIcon icon={faDownload} className="w-5 h-5 inline"/>&nbsp;
{download} {t('download')}
</a> </a>
</Link> </Link>
<p>{fingerprint}:</p> <p>{t('fingerprint')}:</p>
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<div className="whitespace-nowrap"> <div className="whitespace-nowrap">
<code>3745 F270 DB4E 8975 6B07 62BE EB0F E5D9 25C4 A968</code> <code>3745 F270 DB4E 8975 6B07 62BE EB0F E5D9 25C4 A968</code>
@@ -58,10 +58,10 @@ export default function Modal() {
<Link href="https://github.com/yude.keys"> <Link href="https://github.com/yude.keys">
<a className="hover:underline"> <a className="hover:underline">
<FontAwesomeIcon icon={faEye} className="w-5 h-5 inline"/>&nbsp; <FontAwesomeIcon icon={faEye} className="w-5 h-5 inline"/>&nbsp;
{view} {t('view')}
</a> </a>
</Link> </Link>
<p>{fingerprint}:</p> <p>{t('fingerprint')}:</p>
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<div className="whitespace-nowrap"> <div className="whitespace-nowrap">
<code>2048 SHA256:xwSL4DORWmroWdC6P0GU1m1yZl/cXqjo9rCCWqqO+Dc</code> <code>2048 SHA256:xwSL4DORWmroWdC6P0GU1m1yZl/cXqjo9rCCWqqO+Dc</code>
@@ -78,7 +78,7 @@ export default function Modal() {
type="button" type="button"
onClick={() => setShowModal(false)} onClick={() => setShowModal(false)}
> >
{close} {t('close')}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -1,17 +1,21 @@
// React
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
// Data fetching
import axios from 'axios'; import axios from 'axios';
import useTranslation from 'next-translate/useTranslation'
import { useRouter } from 'next/router' // i18n
import { useTranslation, useLanguageQuery } from 'next-export-i18n';
function App () { function App () {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("common")
const [data, setData] = useState({ hits: [] }); const [data, setData] = useState({ hits: [] });
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
const result = await axios( const result = await axios(
'/api/Spotify', 'https://vercel-spotify-api.vercel.app/api/Spotify',
); );
setData(result.data); setData(result.data);
}; };
@@ -25,7 +29,7 @@ function App () {
const status = data.artist + ' / ' + data.title const status = data.artist + ' / ' + data.title
return <p>{t('listening', {listening: status})}</p> return <p>{t('listening', {listening: status})}</p>
}else{ }else{
return <p></p> return <></>
} }
}; };
} }

View File

@@ -1,15 +1,17 @@
import React, { useState, useEffect } from 'react'; // React
import useTranslation from 'next-translate/useTranslation' import React from 'react';
// Font Awesome
import { faUserClock } from '@fortawesome/free-solid-svg-icons' import { faUserClock } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useRouter } from 'next/router'
// i18n
import { useTranslation } from 'next-export-i18n';
export default function Modal() { export default function Modal() {
const [showModal, setShowModal] = React.useState(false); const [showModal, setShowModal] = React.useState(false);
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router
const { t, lang } = useTranslation("common")
const close = t('common:close')
return ( return (
<> <>
<button <button
@@ -38,7 +40,7 @@ export default function Modal() {
type="button" type="button"
onClick={() => setShowModal(false)} onClick={() => setShowModal(false)}
> >
{close} {t('close')}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -7,9 +7,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
const ThemeSelector = (props) => { const ThemeSelector = (props) => {
const { title, children } = props const { title, children } = props
const router = useRouter()
const { locale, locales, defaultLocale, pathname } = router
const [isMounted, setIsMounted] = useState(false); const [isMounted, setIsMounted] = useState(false);
const { theme, setTheme, getTheme } = useTheme(); const { theme, setTheme, getTheme } = useTheme();
useEffect(() => { useEffect(() => {

View File

@@ -1,27 +1,40 @@
// Base layout
import Layout from "./components/Layout" import Layout from "./components/Layout"
import useTranslation from 'next-translate/useTranslation'
import { useRouter } from 'next/router' // i18n
import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
// React
import React from "react" import React from "react"
import ReactMarkdown from "react-markdown" import ReactMarkdown from "react-markdown"
// Markdown
import gfm from 'remark-gfm'; import gfm from 'remark-gfm';
import ja from '../docs/hcunews/ja.md' import ja from '../docs/hcunews/ja.md'
import en from '../docs/hcunews/en.md' import en from '../docs/hcunews/en.md'
export default function Tos(props) { export default function HcuNews() {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("hcunews")
return( if (!query) {
<Layout title={t('hcunews')}> return <p>Loading...</p>
<div> } else {
<h1>{t('hcunews')}</h1> return (
{lang === 'ja' ? ( <Layout title={t('hcunews')}>
<ReactMarkdown plugins={[gfm]} children={ja} /> <div>
) : ( <h1>{t('hcunews')}</h1>
<ReactMarkdown plugins={[gfm]} children={en} /> {query["lang"] === 'ja' ? (
)} <ReactMarkdown plugins={[gfm]}>
</div> {ja}
</Layout> </ReactMarkdown>
) ) : (
} <ReactMarkdown plugins={[gfm]}>
{en}
</ReactMarkdown>
)}
</div>
</Layout>
)
}
}

View File

@@ -1,17 +1,21 @@
// Base layout
import Layout from "./components/Layout" import Layout from "./components/Layout"
import useTranslation from 'next-translate/useTranslation'
// i18n
import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
// Next.js router
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
export default function About(props) { export default function About(props) {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("house")
return ( return (
<Layout title={t('house')}> <Layout title={t('house')}>
<div> <div>
<p className="my-2 text-3xl text-center">{t('house')}</p> <p className="my-2 text-3xl text-center">{t('house')}</p>
<iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/4mVIU29WCRVZgHUxQPzWsfXo953uxiAegbjDb83hTQ7szesCunwdpVkBIzhnLc9i?period=1d" frameborder="0" scrolling="no"></iframe> <iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/4mVIU29WCRVZgHUxQPzWsfXo953uxiAegbjDb83hTQ7szesCunwdpVkBIzhnLc9i?period=1d" frameBorder="0" scrolling="no"></iframe>
</div> </div>
</Layout> </Layout>
) )

View File

@@ -1,70 +1,68 @@
// Load base layout // Base layout
import Layout from "./components/Layout" import Layout from "./components/Layout"
// Menu // Menu
import FAMenu from "./components/Menu/FontAwesomeMenu" import FAMenu from "./components/Menu/FontAwesomeMenu"
// Banner // Banner
import BlueRibbon from "./components/Footer/BlueRibbon"
import HappyBusy from "./components/Footer/HappyBusy" import HappyBusy from "./components/Footer/HappyBusy"
// Next.js // Next.js
import Image from 'next/image'
import Link from 'next/link' import Link from 'next/link'
// i18n // i18n
import useTranslation from 'next-translate/useTranslation' import { useTranslation, useLanguageQuery } from 'next-export-i18n';
// React Router // React Router
import { useRouter } from 'next/router'
import MinecraftMenu from "./components/Menu/MinecraftMenu" import MinecraftMenu from "./components/Menu/MinecraftMenu"
// Font Awesome // Font Awesome
import { faDiscord, faGit, faMastodon, faGithub } from '@fortawesome/free-brands-svg-icons' import { faDiscord, faGit, faGithub } from '@fortawesome/free-brands-svg-icons'
import { faBook, faUser, faServer, faHouseUser, faHeart } from '@fortawesome/free-solid-svg-icons' import { faBook, faUser, faServer, faScrewdriver, faHeart } from '@fortawesome/free-solid-svg-icons'
export default function Index(props) { export default function Index(props) {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("index")
if (!query) {
return <p>Loading...</p>
} else {
return ( return (
<> <>
<Layout title={t('home')}> <Layout title={t('home')}>
<div className="my-9 text-center"> <div className="my-9 text-center">
<div className="m-10"> <div className="m-10">
<Image <img
className = "mx-auto"
src = "/images/avatar_riru.png" src = "/images/avatar_riru.png"
alt = "yude's avatar" alt = "yude's avatar"
width = {200} width = {200}
height = {200} height = {200}
unoptimized = {true}
/> />
</div> </div>
{/* Index menu */} {/* Index menu */}
<div className="grid grid-cols-3 gap-10"> <div className="grid grid-cols-3 gap-10">
<FAMenu dest="/profile" icon={faUser} /> <FAMenu dest="/profile" query={query} icon={faUser} />
<FAMenu dest="/server" icon={faServer} /> <FAMenu dest="/server" query={query} icon={faServer} />
<FAMenu dest="/house" icon={faHouseUser} /> <FAMenu dest="/services" query={query} icon={faScrewdriver} />
<FAMenu dest="https://scrapbox.io/yude" icon={faBook} />
<FAMenu dest="https://discord.gg/X6srY7X" icon={faDiscord} /> <FAMenu dest="https://discord.gg/X6srY7X" icon={faDiscord} />
<FAMenu dest="https://github.com/yudejp" icon={faGithub} /> <FAMenu dest="https://github.com/yudejp" icon={faGithub} />
<FAMenu dest="https://git.yude.jp" icon={faGit} /> <FAMenu dest="https://git.yude.jp" icon={faGit} />
<MinecraftMenu /> <MinecraftMenu query={query} />
<FAMenu dest="/mutual" icon={faHeart} /> <FAMenu dest="/mutual" icon={faHeart} query={query} />
</div> </div>
{/* Banner */} {/* Banner */}
<div className="mx-auto mt-10"> <div className="mx-auto mt-10">
<BlueRibbon />
<HappyBusy /> <HappyBusy />
</div> </div>
{/* Avatar by */} {/* Avatar by */}
<p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('common:icon_1')}<Link href="https://twitter.com/R_I_R_U_"><a className="hover:underline">梨留りる {t('common:icon_2')}</a></Link></p> <p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('icon_1')}<Link href="https://twitter.com/R_I_R_U_"><a className="hover:underline">梨留りる {t('icon_2')}</a></Link></p>
</div> </div>
</Layout> </Layout>
</> </>
) )
} }
}

View File

@@ -6,10 +6,9 @@ import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
// i18n // i18n
import useTranslation from 'next-translate/useTranslation' import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
// Next.js // Next.js
import Image from 'next/image'
import Link from 'next/link' import Link from 'next/link'
// Custom pages // Custom pages
@@ -29,17 +28,17 @@ import en from '../docs/minecraft/en.md'
import { NextSeo } from 'next-seo'; import { NextSeo } from 'next-seo';
export default function About(props) { export default function About(props) {
const router = useRouter() const { t } = useTranslation();
const [query] = useLanguageQuery();
// i18n
const { locale, locales, defaultLocale, pathname } = router
const { t, lang } = useTranslation("minecraft")
// Copy server address to clipboard // Copy server address to clipboard
const copyText = () => { const copyText = () => {
navigator.clipboard.writeText("yude.jp"); navigator.clipboard.writeText("yude.jp");
}; };
if (!query) {
return <p>Loading...</p>
} else {
return ( return (
<> <>
<NextSeo <NextSeo
@@ -51,10 +50,9 @@ export default function About(props) {
<div> <div>
<p className="my-2 text-3xl text-center">{t('title')}</p> <p className="my-2 text-3xl text-center">{t('title')}</p>
<div className="w-full"> <div className="w-full">
<Image <img
src = "/images/dynmap.png" src = "/images/dynmap.png"
alt = "Dynmap Header" alt = "Minecraft brief world map generated by Dynmap"
unoptimized = {true}
width = {1354} width = {1354}
height = {619} height = {619}
/> />
@@ -73,7 +71,7 @@ export default function About(props) {
</button> </button>
</p> </p>
<p>{t('version')}: 1.17</p> <p>{t('version')}: 1.18.1</p>
<Link href="https://bluemap.yude.jp"> <Link href="https://bluemap.yude.jp">
<a> <a>
@@ -87,14 +85,18 @@ export default function About(props) {
</div> </div>
{/* Load markdown contents */} {/* Load markdown contents */}
{lang === 'ja' ? ( {query["lang"] === 'ja' ? (
<ReactMarkdown plugins={[gfm]} children={ja} /> <ReactMarkdown plugins={[gfm]}>
) : ( {ja}
<ReactMarkdown plugins={[gfm]} children={en} /> </ReactMarkdown>
)} ) : (
<ReactMarkdown plugins={[gfm]}>
{en}
</ReactMarkdown>
)}
</div> </div>
</Layout> </Layout>
</> </>
) )
}
} }

View File

@@ -0,0 +1,56 @@
// Base layout
import Layout from "../../components/Layout"
// React
import { useRouter } from 'next/router'
// Data fetching
import useSwr from 'swr'
const fetcher = (url) => fetch(url).then((res) => res.json())
// Components
import WrongUUID from '../../components/Minecraft/WrongUUID'
export default function UUID() {
const router = useRouter()
const { ign } = router.query
const { data, error } = useSwr(
ign ? `https://api.ashcon.app/mojang/v2/user/${ign}` : null,
fetcher
)
if (error) {
return (
<>
<Layout title="エラー - プレイヤー情報">
<p className="text-2xl">エラーが発生しました</p>
</Layout>
</>
)
} else {
if (!data) {
return (
<>
<Layout title="読み込み中... - プレイヤー情報">
<p className="text-2xl">読み込み中</p>
</Layout>
</>
)
} else {
if (data.code) {
return (
<>
<Layout title="404 - プレイヤー情報">
<WrongUUID />
</Layout>
</>
)
} else {
router.push('/minecraft/players/' + data.uuid)
return (
<p>リダイレクトしています...</p>
)
}
}
}
}

View File

@@ -0,0 +1,59 @@
// Base layout
import Layout from "../../components/Layout"
// React
import { useRouter } from 'next/router'
// Data fetching
import Players from '../../components/Minecraft/Players'
import useSwr from 'swr'
const fetcher = (url) => fetch(url).then((res) => res.json())
// Components
import WrongUUID from '../../components/Minecraft/WrongUUID'
export default function UUID() {
const router = useRouter()
const { uuid } = router.query
const { data, error } = useSwr(
uuid ? `https://api.ashcon.app/mojang/v2/user/${uuid}` : null,
fetcher
)
if (error) {
return (
<>
<Layout title="エラー - プレイヤー情報">
<p className="text-2xl">エラーが発生しました</p>
</Layout>
</>
)
} else {
if (!data) {
return (
<>
<Layout title="読み込み中... - プレイヤー情報">
<Players uuid={uuid} />
</Layout>
</>
)
} else {
if (!data.username) {
return (
<>
<Layout title="404 - プレイヤー情報">
<WrongUUID />
</Layout>
</>
)
} else {
return (
<>
<Layout title={data.username + " - " + "プレイヤー情報"}>
<Players uuid={uuid} />
</Layout>
</>
)
}
}
}
}

View File

@@ -2,7 +2,7 @@
import Layout from "./components/Layout" import Layout from "./components/Layout"
// i18n // i18n
import useTranslation from 'next-translate/useTranslation' import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
// React Router etc. // React Router etc.
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
@@ -18,24 +18,32 @@ import en from '../docs/mutual/en.md'
import { NextSeo } from 'next-seo'; import { NextSeo } from 'next-seo';
export default function Tos(props) { export default function Tos(props) {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("common")
if (!query) {
return <p>Loading...</p>
} else {
return( return(
<> <>
<NextSeo <NextSeo
title="相互リンク" title="相互リンク"
description="yude.jp と相互にリンクを貼っている Web サイトの一覧" description="yude.jp と相互にリンクを貼っている Web サイトの一覧"
/> />
<Layout title={t('common:mutual')}> <Layout title={t('mutual')}>
<div> <div>
{lang === 'ja' ? ( {query["lang"] === 'ja' ? (
<ReactMarkdown plugins={[gfm]} children={ja} /> <ReactMarkdown plugins={[gfm]}>
{ja}
</ReactMarkdown>
) : ( ) : (
<ReactMarkdown plugins={[gfm]} children={en} /> <ReactMarkdown plugins={[gfm]}>
{en}
</ReactMarkdown>
)} )}
</div> </div>
</Layout> </Layout>
</> </>
) )
}
} }

View File

@@ -1,54 +0,0 @@
// Base layout
import Layout from "./components/Layout"
// Next.js
import Link from "next/link";
// i18n
import { useRouter } from 'next/router'
import useTranslation from 'next-translate/useTranslation'
// microCMS library
import { client } from "../libs/client";
// next-seo
import { NextSeo } from 'next-seo';
export default function Home({ blog }) {
const router = useRouter()
const { locale, locales, defaultLocale, pathname } = router
const { t, lang } = useTranslation("common")
return (
<>
<NextSeo
title="記事一覧"
description="yude のブログの記事一覧 / yude's blog posts listing"
/>
<Layout title={t('common:post_list')}>
<div>
<h1 className="text-center">{t('common:post_list')}</h1>
<ul>
{blog.map((blog) => (
<li key={blog.id}>
<Link href={`/posts/${blog.id}`}>
<a>{blog.title}</a>
</Link>
</li>
))}
</ul>
</div>
</Layout>
</>
);
}
// Passing data to template
export const getStaticProps = async () => {
const data = await client.get({ endpoint: "blog" });
return {
props: {
blog: data.contents,
},
};
};

View File

@@ -1,58 +0,0 @@
// Base layout
import Layout from "../components/Layout"
// microCMS library
import { client } from "../../libs/client";
// next-seo
import { NextSeo } from 'next-seo';
// React
import * as React from "react";
// React Moment
import Moment from 'react-moment';
export default function BlogId({ blog }) {
return (
<>
<Layout title={blog.title + " - yude.jp"}>
<NextSeo
title={blog.title + " - yude.jp"}
description={blog.publishedAt + "に更新された「" + blog.title + "」というタイトルの記事です。"}
/>
<h1>{blog.title}</h1>
<p>
<Moment format="YYYY/MM/DD HH:mm">
{blog.updated}
</Moment>
</p>
<div
dangerouslySetInnerHTML={{
__html: `${blog.content}`,
}}
/>
</Layout>
</>
);
}
// Specify path for static generator
export const getStaticPaths = async () => {
const data = await client.get({ endpoint: "blog" });
const paths = data.contents.map((content) => `/posts/${content.id}`);
return { paths, fallback: false };
};
// Passing data to template
export const getStaticProps = async (context) => {
const id = context.params.id;
const data = await client.get({ endpoint: "blog", contentId: id });
return {
props: {
blog: data,
},
};
};

View File

@@ -2,17 +2,15 @@
import Layout from "./components/Layout" import Layout from "./components/Layout"
// i18n // i18n
import useTranslation from 'next-translate/useTranslation' import { useTranslation, useLanguageQuery } from 'next-export-i18n';
// Font Awesome // Font Awesome
import { faDiscord, faTwitter, faGithub, faKeybase, faInstagram, faMastodon, faSteam } from '@fortawesome/free-brands-svg-icons' import { faDiscord, faTwitter, faGithub, faKeybase, faInstagram, faMastodon, faSteam, faAmazon } from '@fortawesome/free-brands-svg-icons'
import { faEnvelope, faBirthdayCake, faMapPin, faSchool, faPhone, faInfo, faLink, faMobile } from '@fortawesome/free-solid-svg-icons' import { faEnvelope, faBirthdayCake, faMapPin, faSchool, faPhone, faBlog, faBookDead, faInfo, faBookmark, faLink, faMobile } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
// Next.js, React // Next.js, React
import Link from 'next/link' import Link from 'next/link'
import Image from 'next/image'
import { useRouter } from 'next/router'
// Discord // Discord
import DiscordStatus from './components/Discord/DiscordStatus' import DiscordStatus from './components/Discord/DiscordStatus'
@@ -30,9 +28,8 @@ import NintendoSW from "./components/Profile/NintendoSW"
import { NextSeo } from 'next-seo'; import { NextSeo } from 'next-seo';
export default function Profile(props) { export default function Profile(props) {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("profile")
return ( return (
<> <>
@@ -47,7 +44,7 @@ export default function Profile(props) {
} }
<div> <div>
<div className="flex mb-10 justify-center"> <div className="flex mb-10 justify-center">
<Image <img
className = "rounded-full hover:animate-rumble z-0 p-15" className = "rounded-full hover:animate-rumble z-0 p-15"
src = "/images/avatar_mel.png" src = "/images/avatar_mel.png"
alt = "yude's avatar" alt = "yude's avatar"
@@ -89,6 +86,19 @@ export default function Profile(props) {
<p className="ml-9">{t('hiroshima')}</p> <p className="ml-9">{t('hiroshima')}</p>
</div> </div>
</div> </div>
{
// Contents
}
<div>
<div className="text-left">
<p className="text-2xl"><FontAwesomeIcon icon={faBookDead} className="w-5 h-5 inline"/> {t('contents')}</p>
</div>
<div className="my-2 grid grid-cols-2 lg:grid-cols-5 md:grid-cols-3 sm:grid-cols-2justify-items-center gap-y-6">
<Contact dest="https://blog.yude.jp" icon={faBlog} caption={t('blog')} />
<Contact dest="https://scrapbox.io/yude" icon={faBookmark} caption="Scrapbox" />
</div>
</div>
{ {
// Contact // Contact
@@ -115,11 +125,12 @@ export default function Profile(props) {
<WakaTime /> <WakaTime />
<PublicKeys /> <PublicKeys />
<Button dest="https://scrapbox.io/yude/%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88" icon={faLink} caption={t('account')}/> <Button dest="https://scrapbox.io/yude/%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88" icon={faLink} caption={t('account')}/>
<Button dest="https://scrapbox.io/yude/%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9" icon={faMobile} caption={t('device')}/> <Button dest="https://scrapbox.io/yude/%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9" icon={faMobile} caption={t('device')}/>
<Button dest="https://www.amazon.jp/hz/wishlist/ls/8WTKCPWKOJ2N?ref_=wl_share" icon={faAmazon} caption={t('wishlist')}/>
</div> </div>
</div> </div>
<p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('common:icon_1')}<Link href="https://twitter.com/xmnts"><a className="hover:underline">Minkasy {t('common:icon_2')}</a></Link></p> <p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('icon_1')}<Link href="https://twitter.com/xmnts"><a className="hover:underline">Minkasy {t('icon_2')}</a></Link></p>
</div> </div>
</Layout> </Layout>

View File

@@ -2,18 +2,14 @@
import Layout from "./components/Layout" import Layout from "./components/Layout"
// i18n // i18n
import useTranslation from 'next-translate/useTranslation' import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
// React Router
import { useRouter } from 'next/router'
// next-seo // next-seo
import { NextSeo } from 'next-seo'; import { NextSeo } from 'next-seo';
export default function Server(props) { export default function Server(props) {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("server")
return ( return (
<> <>
@@ -32,33 +28,22 @@ export default function Server(props) {
</div> </div>
{ {
// yui // sandy
} }
<h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">yui</h2> <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">sandy</h2>
<div className="flex xl:w-2/3 text-center"> <div className="flex xl:w-2/3 text-center">
<div className="flex-1"><p className="font-bold">CPU </p>i7-2600</div> <div className="flex-1"><p className="font-bold">CPU </p>i7-2600</div>
<div className="flex-1"><p className="font-bold">RAM </p>DDR3 24GB</div> <div className="flex-1"><p className="font-bold">RAM </p>DDR3 24GB</div>
<div className="flex-1"><p className="font-bold">OS </p>Arch Linux</div> <div className="flex-1"><p className="font-bold">OS </p>Arch Linux</div>
<div className="flex-1"><p className="font-bold">{t('location')} </p>{t('hiroshima')}</div> <div className="flex-1"><p className="font-bold">{t('location')} </p>{t('hiroshima')}</div>
</div> </div>
<iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/heHnGhDanoIDlf7jjxUe9yPVrsG3deeH5ptD8suErrq5w46crWEIYdLfzLoukzfF?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> <a href="https://mackerel.io/orgs/yude/hosts/4dkbQuMQjvo/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/heHnGhDanoIDlf7jjxUe9yPVrsG3deeH5ptD8suErrq5w46crWEIYdLfzLoukzfF.png?period=10m" className="w-full" /></a>
{ {
// yukino // oracle1
} }
<h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">yukino</h2> <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">oracle1</h2>
<div className="flex xl:w-2/3 text-center">
<div className="flex-1"><p className="font-bold">{t('model')} </p>Raspberry Pi 4 Model B Rev 1.2</div>
<div className="flex-1"><p className="font-bold">RAM </p>4GB</div>
<div className="flex-1"><p className="font-bold">OS </p>Raspbian GNU/Linux 10 (buster)</div>
<div className="flex-1"><p className="font-bold">{t('location')} </p>{t('tottori')}</div>
</div>
<iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/5HVbQiwuxrMithyrGjmmQCCOVgJ6Ptf94SDA2qWSTsh2rtz7pjePihYzaW5QEml4?period=24h" height="400" frameBorder="0" scrolling="no"></iframe>
{
// iroha
}
<h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">iroha</h2>
<div className="flex xl:w-2/3 text-center"> <div className="flex xl:w-2/3 text-center">
<div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div> <div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div>
<div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</div> <div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</div>
@@ -66,13 +51,12 @@ export default function Server(props) {
<div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04 LTS</div> <div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04 LTS</div>
<div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div>
</div> </div>
<iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/wgmTz7aTgvwfyU6qVHrJJmQlpOHCUJK6qw0W9sJTX68WOI8TFtc27YvJ7dwkQEGv?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> <a href="https://mackerel.io/orgs/yude/hosts/4ftHfeojMCU/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/vcn6LE4P2hh6GzvtMbIAWxsXpDh6eSoNyAXdhfYaj9yDN6FJwOHIiz9ktqToj1HG.png?period=10m" className="w-full" /></a>
{ {
// komachi // oracle2
} }
<h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">komachi</h2> <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">oracle2</h2>
<div className="flex xl:w-2/3 text-center"> <div className="flex xl:w-2/3 text-center">
<div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div> <div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div>
<div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</div> <div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</div>
@@ -80,8 +64,21 @@ export default function Server(props) {
<div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04 LTS</div> <div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04 LTS</div>
<div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div>
</div> </div>
<iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/vcn6LE4P2hh6GzvtMbIAWxsXpDh6eSoNyAXdhfYaj9yDN6FJwOHIiz9ktqToj1HG?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> <a href="https://mackerel.io/orgs/yude/hosts/4frgQ1QuivJ/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/wgmTz7aTgvwfyU6qVHrJJmQlpOHCUJK6qw0W9sJTX68WOI8TFtc27YvJ7dwkQEGv.png?period=10m" className="w-full" /></a>
{
// oracle-a1-1
}
<h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">oracle-a1-1</h2>
<div className="flex xl:w-2/3 text-center">
<div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div>
<div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.A1.Flex</div>
<div className="flex-1"><p className="font-bold">RAM </p>6GB</div>
<div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04.3 LTS</div>
<div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div>
</div>
<a href="https://mackerel.io/orgs/yude/hosts/4qzeqT6kToQ/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/2C7NdtqLgGFGPiO2IctDGuaMdjBwhXyp0i8imkaJT2GFI55syPaxxACEYIRWDHnS.png?period=10m" className="w-full" /></a>
</div> </div>
</Layout> </Layout>
</> </>

49
pages/services.js Normal file
View File

@@ -0,0 +1,49 @@
// Base layout
import Layout from "./components/Layout"
// i18n
import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
// React Router etc.
import { useRouter } from 'next/router'
import React from "react"
// React Markdown
import ReactMarkdown from "react-markdown"
import gfm from 'remark-gfm';
import ja from '../docs/services/ja.md'
import en from '../docs/services/en.md'
// next-seo
import { NextSeo } from 'next-seo';
export default function Tos(props) {
const { t } = useTranslation();
const [query] = useLanguageQuery();
if (!query) {
return <p>Loading...</p>
} else {
return(
<>
<NextSeo
title="サービス"
description="yude.jp で運用中のサービス"
/>
<Layout title={t('services')}>
<div>
{query["lang"] === 'ja' ? (
<ReactMarkdown plugins={[gfm]}>
{ja}
</ReactMarkdown>
) : (
<ReactMarkdown plugins={[gfm]}>
{en}
</ReactMarkdown>
)}
</div>
</Layout>
</>
)
}
}

View File

@@ -1,25 +1,40 @@
// Base layout
import Layout from "./components/Layout" import Layout from "./components/Layout"
import useTranslation from 'next-translate/useTranslation'
// i18n
import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n';
// Next.js, React
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import React from "react" import React from "react"
// React Markdown
import ReactMarkdown from "react-markdown" import ReactMarkdown from "react-markdown"
import gfm from 'remark-gfm'; import gfm from 'remark-gfm';
import ja from '../docs/tos/ja.md' import ja from '../docs/tos/ja.md'
import en from '../docs/tos/en.md' import en from '../docs/tos/en.md'
export default function Tos(props) { export default function Tos(props) {
const router = useRouter() const { t } = useTranslation();
const { locale, locales, defaultLocale, pathname } = router const [query] = useLanguageQuery();
const { t, lang } = useTranslation("tos")
return( if (!query) {
<Layout title={t('tos')}> return <p>Loading...</p>
<div> } else {
{lang === 'ja' ? ( return (
<ReactMarkdown plugins={[gfm]} children={ja} /> <Layout title={t('tos')}>
) : ( <div>
<ReactMarkdown plugins={[gfm]} children={en} /> {query["lang"] === 'ja' ? (
)} <ReactMarkdown plugins={[gfm]}>
</div> {ja}
</Layout> </ReactMarkdown>
) ) : (
} <ReactMarkdown plugins={[gfm]}>
{en}
</ReactMarkdown>
)}
</div>
</Layout>
)
}
}

67
public/yude.asc Normal file
View File

@@ -0,0 +1,67 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGBFtIIBEADvtdeDZreuQ/iktUbhSqAOwbmAVNqbuKYvIbxp1AKPlEVD3oxR
s+pnfLwMswobAT98VjQMHYnQM8hp4ngBgiZUqfh5RWO750TvlNIRRlG4vMoR06gP
maDVz6t0D+UPW0lnuPk7TnHOROPEQCJzjn+J8xd+a1wXHP9ExAOpGLjnjUDPZK2v
U7ls3j4/7YWa1/lpbccWbbnZ/siqbz1VE3F+RwXWtxzTIOyreriAAKY5se8Z/fE1
FYQlsDlAfFZa5K8+4LiTLongzBJpjwRsWiTYNQxpEUv47jWJuO2DgD5/8+bG4P/F
n4OC6GP4odwWZZnga/rIrbYM0rl6pCHzKxg9nrwba0ZsbO6H0++Inii3TIHT9Nm1
vBCHUMvoW3DEWD6SB/fut8nNCamQKJwAHp8wl/OCJ8vUbwM0tTiaC7ymRdQXehSG
5kWf4tSNAz9QJGQPyn3qFehuD59/B7yMdlIAExKH/fHtUknpb/KNJx8aIRfxC58X
e9syXLvNO1XBpI3dl7QWGVLSErVNtWTO3RSywjhDL73rZVxY4fJvz63eo0T/bIHp
YdL7ThdTr+PbwcRvmJrJmYqzSzg6kDT+jIyV3vNvUCb/m3nSm41Z4cSGMCU/9/Nm
7eUJRnWdFOeEfOrn3TRrbNXDMerXRe/+ITO4K5Xc1AD9I8ILXM/K4QV9iQARAQAB
tBJ5dWRlanAgPGlAeXVkZS5qcD6JBUwEEwEIAzYCGwMFCQWjmoAFCwkIBwIGFQoJ
CAsCBBYCAwECHgECF4AWIQQ3RfJw206JdWsHYr7rD+XZJcSpaAUCYRmCYjsUgAAA
AAASACBwcm9vZkBtZXRhY29kZS5iaXpodHRwczovL2Rldi50by95dWRlL29wZW5w
Z3AtMzkyZIMUgAAAAAASAGhwcm9vZkBtZXRhY29kZS5iaXpodHRwczovL3d3dy5y
ZWRkaXQuY29tL3VzZXIveXVkZTExMTkvY29tbWVudHMvb253eHI2L29wZW5wZ3A0
ZnByMzc0NWYyNzBkYjRlODk3NTZiMDc2MmJlZWIwZmU1ZDkyNWM0YTk2Ly8UgAAA
AAASABRwcm9vZkBtZXRhY29kZS5iaXpkbnM6eXVkZS5qcD90eXBlPVRYVFMUgAAA
AAASADhwcm9vZkBtZXRhY29kZS5iaXpodHRwczovL3R3aXR0ZXIuY29tL3l1ZGVf
dW5pdi9zdGF0dXMvMTQxNzI5ODQ4ODY5NDUwOTU4N1EUgAAAAAASADZwcm9vZkBt
ZXRhY29kZS5iaXpodHRwczovL3R3aXR0ZXIuY29tL3l1ZGVfanAvc3RhdHVzLzE0
MTcyOTc1MDYxNjIwMTIxNjBYFIAAAAAAEgA9cHJvb2ZAbWV0YWNvZGUuYml6aHR0
cHM6Ly9naXN0LmdpdGh1Yi5jb20veXVkZS80NmNkNDE3MWNjM2M3ZjZlNTQ1N2Vk
YWU2YzczMjJjMjYUgAAAAAASABtwcm9vZkBtZXRhY29kZS5iaXpodHRwczovL21z
dGRuLnl1ZGUuanAvQHl1ZGVRFIAAAAAAEgA2cHJvb2ZAbWV0YWNvZGUuYml6aHR0
cHM6Ly90d2l0dGVyLmNvbS95dWRlX1JUL3N0YXR1cy8xNDE3Mjk4NTAxOTQwMTE3
NTA2PxSAAAAAABIAJHByb29mQG1ldGFjb2RlLmJpemh0dHBzOi8vZ2l0bGFiLmNv
bS95dWRlL2dpdGxhYl9wcm9vZj8UgAAAAAASACRwcm9vZkBtZXRhY29kZS5iaXpo
dHRwczovL2dpdC55dWRlLmpwL3l1ZGUvZ2l0ZWFfcHJvb2YACgkQ6w/l2SXEqWjY
BxAAtMXaDLJCq9qzP6jPs22R+LXM99Pmtf3QiJ/a9qa8L+qJBT2g7mXqlQGXBBy2
N0VY+IeTvNHc9hvuKrUVBLxOy7YWnf3D7jPlfttDQrQWVcvtn0//DwCf84Bzl+VC
NzB5Fc9FYP+qUv5d4+lsNaRcrO+L1Fr6HWcFDMeb6uKWEoFtKLLVVhrkGAbLOR2H
CAmJyspU4Zuw2vo/Cx5TE3IotGXidjYQXt50q0WxbggWYdRsS1E+gS7dMTaS/8+O
wcWb0/6QGR1U45gF6BVpF+IwGXGZRHvWykZ9e3xZx5OdjbsC0QRk2b0nxp/c1qN8
Ua1L3HurIqqr+yWuLae2DB6hgrpJEi2HwM6uj0LAVgkNG2EMv3cky1+nOsa5xzGy
t7OjUKAXX+XHnT2HRSlhET/e3Gqw4VFnTD876CbEPfbJ5aR5jB1lWKcMujiDsg35
E/pNkkeLpEy4D6+pZLt8+k+KDNwCazjzNil6aFm4ogSKRH5vmfaJyObLGqChD1bb
TfkJXzfIacYzf1L1KjNCLCPyxxUrjzyxHZZRAPm+bg7h494EM4hDoRevWJNdnm2C
GQlcZGI7pF4StQR+YkisgaLYBUyAjuerWaMrXp8NWYPdeJEeqDjTxmJyFZRRCVKR
CPq0IgEOOkdl1lgQxYEroFlvSgwWoJBNTTFu+LDg6ZuBwMa5Ag0EYEW0ggEQAN0h
PmgU7XV0dRqJ1/Mb1WpnnXsshVr3SGZoqUn4XVMRWEhLc3xzp3tLMPqCytLMddAF
rBaBItuOA+yE9w5Yqpt9Z1axrqA6TqzHbCBUPhacynPmS5VcnsZDOF/P67s1y0/L
RX6idF94ElEYgc1KAzj1wD5Q1bW2yIQUzjhgkDFhZOY4nqbSfg6NDbGQo3coquMs
YcLdnEBwPq95WSns62hr4naohMRalbFZDt+BydWvv8XoT2RkoQnWN35+332rUlu6
HECBtI+RBVtVwKWGymY8GFcSau20j+4JseSla6iA2XeXi9rN4Kj03n0Nx2L4NOAP
W0XfzlpFBBzhcthgJ8ahspIf9z+fvQbBQ9v9xq15/nj5sqLSBN6SZP1Q9ykXM63/
HzxSFTDUVyC3OFvS+FsVU08oG/QzfjHp4MWr1zVhAaLBZxDZt7nw5osec+/OgiAm
Tt9HU5UiUfbfa5nQEHMapOD/r0HJu5RFA3EHMmmr9Es63OKcNrCfrZzy3b/4mv0h
J3sDulsvgu1GSinI0oubU1OJ+l+hEPEvbV3B2xMm/m7anJUEa31GHuu5ZiZJSZZS
Hxa4m43X1mRfRnI8h4LNpXgGhm6wh+zO8xx4PztNPNq9zA+CYRlMTMI15xr78Ui6
eKzLE5/cliuPaP0CyHEEQNSxxsgk57mdO9xldoShABEBAAGJAjwEGAEIACYWIQQ3
RfJw206JdWsHYr7rD+XZJcSpaAUCYEW0ggIbDAUJBaOagAAKCRDrD+XZJcSpaGhO
D/0e8q1DCKQUud/BwfT6ELR488ojdIu9Jag0aGKul3qemnLnk3jSSoz5rNKHAemY
D6PUNeARU9Unksy88EJMB3GMlbnfrWwTEfMfE1eZSqntCo/xoL1mr013CZKMYlLT
K8J0oC5Y3ENi24R5BZIpsAnnqL3L6iPtuTRVkHMYpFgHgWnxRNqpdqbtXHu/1Z5l
XLhea7o6NF/Chrl73zTyI6qlrRftERVmyTB/TxbUFTAAXGoUO/Ag/rGt+uoLIjE3
usfeoc4KR4uqEKuVN/aLMNSrCYHPTZRltKK6w1XpdASIGFblnFzeT0xHHgI7xtmT
hyQPnHhyup9GHYqjj9J1A9BcvZh13gh5efnzEWfvSITpD3XALSRba5NhI3ex9Ene
UlKjlGYjxrgpSBtmk/pm6rYo+/YXZY62JhjMt+juBvhgQZQ9cpg003AMNnKY80/f
thpA+hR4xLPhAId7grWaAf5zdyqeKPBp+uAaJuf9Ii4VrR6rl0M+nHNLZR2mgN90
2z2nvKiGpMuMwLtelW86OAH3CZimx+kxbIO3yj0+mH8PvAKqTI1n5vT82124bLp6
avwOcnA246pF6S2k/VnfT8mhQwbUxwkKpvxoyvQDuqo5FcO2O19I6o8EakE8Iruo
6hJACt4WXbzR3gPBmptL32eJlo99ZV1gvY4Sy69EAtw2kg==
=dc5x
-----END PGP PUBLIC KEY BLOCK-----

1
public/yude.keys Normal file
View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfEH46roc6pn97+Bi0UxWaeogvN38U5/7W+s2TWAQfpE8gv7ibFwZ5FVvHguT8BbCkK8YuXW7Oug1n8S6o3ABhUQD/zGIuEBLVKO6BTUYNDpYNxmmXKZ+dbB1nz++bvson8pYv/MdkeeeRrmqVgmrZzDifgBqYicGep+LKobhXvgCX6Qb9cHC9MCx+3mUzT0RhwwxEL/AsBm6f5oPJZdnF3agnOi61KA+wrK7RPU5v88HY5jHb87irFjNbc2xvyoLJmx+ILyKIcdsaADiTdy2JX5fqsO4S3WFELK+utw1MgBnGt0ENaev2Tce9r2QuUZQYNpa1+vAcdsc0qcR2W9wV

6
vercel.json Normal file
View File

@@ -0,0 +1,6 @@
{
"redirects": [
{ "source": "/wishlist", "destination": "https://www.amazon.jp/hz/wishlist/ls/8WTKCPWKOJ2N?ref_=wl_share" },
{ "source": "/scrapbox", "destination": "https://scrapbox.io/yude" }
]
}

4651
yarn.lock

File diff suppressed because it is too large Load Diff