Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
46c258d77a | |||
3b5b3cf521 | |||
5e0bdd8a78 | |||
b299988bb5 | |||
e26bec6ab4 | |||
e9955e01d6 | |||
1974d8f58b | |||
08c0be11b2 | |||
87c7058494 | |||
b92addffa9 | |||
e8b49df842 | |||
18fd39b335 | |||
8a11322802 | |||
31929dad61 | |||
4a41d2fddc | |||
4c65b0cd6f | |||
3e89dc603d | |||
9595a56346 | |||
c7e8c27ce6 | |||
67792fcb5e | |||
353fc18f19 | |||
cf9e8ed39e | |||
8b71006fbe |
@ -1,6 +1,11 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
10.82.1
|
||||||
|
----------
|
||||||
|
* クラスタリング環境でのジョブキューの動作を修正
|
||||||
|
* その他の軽微な改善
|
||||||
|
|
||||||
10.82.0
|
10.82.0
|
||||||
----------
|
----------
|
||||||
* 自分の投稿情報をエクスポートできるように
|
* 自分の投稿情報をエクスポートできるように
|
||||||
|
@ -61,6 +61,10 @@ Organize and store your files! Want to post a picture you have already uploaded?
|
|||||||
|
|
||||||
...and more! Experience Misskey with your own eyes at [misskey.xyz](https://misskey.xyz) or join one of the [other instances](https://joinmisskey.github.io/) that are available.
|
...and more! Experience Misskey with your own eyes at [misskey.xyz](https://misskey.xyz) or join one of the [other instances](https://joinmisskey.github.io/) that are available.
|
||||||
|
|
||||||
|
:new: What's new
|
||||||
|
----------------------------------------------------------------
|
||||||
|
Please see the [Release notes](./CHANGELOG.md).
|
||||||
|
|
||||||
:package: Create your own instance
|
:package: Create your own instance
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
Please see the [Setup and Installation Guide](./docs/setup.en.md).
|
Please see the [Setup and Installation Guide](./docs/setup.en.md).
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "Email Address"
|
email-address: "Email Address"
|
||||||
email-verified: "Your email has been verified."
|
email-verified: "Your email has been verified."
|
||||||
email-not-verified: "Email address is not confirmed. Please check your inbox."
|
email-not-verified: "Email address is not confirmed. Please check your inbox."
|
||||||
|
export: "Export"
|
||||||
|
export-notes: "Export all of your Notes"
|
||||||
|
export-requested: "You have requested an export. This may take a while. After the export is complete, the resulting file will be added to the drive."
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "User"
|
users: "User"
|
||||||
rename: "Rename list"
|
rename: "Rename list"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "Correo electrónico"
|
email-address: "Correo electrónico"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "Usuarios"
|
users: "Usuarios"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "Adresse de courrier électronique"
|
email-address: "Adresse de courrier électronique"
|
||||||
email-verified: "L’adresse du courrier électronique a été vérifiée."
|
email-verified: "L’adresse du courrier électronique a été vérifiée."
|
||||||
email-not-verified: "Adresse de courriel n’est pas confirmée. Veuillez vérifier votre boite de réception."
|
email-not-verified: "Adresse de courriel n’est pas confirmée. Veuillez vérifier votre boite de réception."
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "Utilisateur·rice"
|
users: "Utilisateur·rice"
|
||||||
rename: "Renommer la liste"
|
rename: "Renommer la liste"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "このメールアドレスOKや!"
|
email-verified: "このメールアドレスOKや!"
|
||||||
email-not-verified: "メールアドレスが確認されとらん。メールボックスもっぺん見てくれへん?"
|
email-not-verified: "メールアドレスが確認されとらん。メールボックスもっぺん見てくれへん?"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "메일 주소"
|
email-address: "메일 주소"
|
||||||
email-verified: "매일 주소가 확인되었습니다"
|
email-verified: "매일 주소가 확인되었습니다"
|
||||||
email-not-verified: "메일 주소가 확인되지 않았습니다. 받은 편지함을 확인하여 주시기 바랍니다."
|
email-not-verified: "메일 주소가 확인되지 않았습니다. 받은 편지함을 확인하여 주시기 바랍니다."
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "사용자"
|
users: "사용자"
|
||||||
rename: "리스트 이름 바꾸기"
|
rename: "리스트 이름 바꾸기"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "Adres e-mail"
|
email-address: "Adres e-mail"
|
||||||
email-verified: "Twój adres e-mail został zweryfikowany."
|
email-verified: "Twój adres e-mail został zweryfikowany."
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "Użytkownicy"
|
users: "Użytkownicy"
|
||||||
rename: "Zmień nazwę listy"
|
rename: "Zmień nazwę listy"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "メールアドレス"
|
email-address: "メールアドレス"
|
||||||
email-verified: "メールアドレスが確認されました"
|
email-verified: "メールアドレスが確認されました"
|
||||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||||
|
export: "エクスポート"
|
||||||
|
export-notes: "すべての投稿のエクスポート"
|
||||||
|
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "ユーザー"
|
users: "ユーザー"
|
||||||
rename: "リスト名を変更"
|
rename: "リスト名を変更"
|
||||||
|
@ -509,6 +509,9 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "电子邮件地址"
|
email-address: "电子邮件地址"
|
||||||
email-verified: "电子邮件地址已验证"
|
email-verified: "电子邮件地址已验证"
|
||||||
email-not-verified: "邮件地址尚未验证。 请检查您的邮箱。"
|
email-not-verified: "邮件地址尚未验证。 请检查您的邮箱。"
|
||||||
|
export: "导出"
|
||||||
|
export-notes: "导出所有帖子"
|
||||||
|
export-requested: "导出请求已提交。可能需要花一些时间。导出的文件将保存到网盘中。"
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "用户"
|
users: "用户"
|
||||||
rename: "重命名列表"
|
rename: "重命名列表"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "10.82.0",
|
"version": "10.82.1",
|
||||||
"clientVersion": "2.0.14114",
|
"clientVersion": "2.0.14137",
|
||||||
"codename": "nighthike",
|
"codename": "nighthike",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -70,7 +70,7 @@
|
|||||||
"@types/mkdirp": "0.5.2",
|
"@types/mkdirp": "0.5.2",
|
||||||
"@types/mocha": "5.2.5",
|
"@types/mocha": "5.2.5",
|
||||||
"@types/mongodb": "3.1.19",
|
"@types/mongodb": "3.1.19",
|
||||||
"@types/node": "10.12.18",
|
"@types/node": "10.12.21",
|
||||||
"@types/nodemailer": "4.6.5",
|
"@types/nodemailer": "4.6.5",
|
||||||
"@types/nprogress": "0.0.29",
|
"@types/nprogress": "0.0.29",
|
||||||
"@types/oauth": "0.9.1",
|
"@types/oauth": "0.9.1",
|
||||||
@ -147,9 +147,8 @@
|
|||||||
"insert-text-at-cursor": "0.1.1",
|
"insert-text-at-cursor": "0.1.1",
|
||||||
"is-root": "2.0.0",
|
"is-root": "2.0.0",
|
||||||
"is-svg": "3.0.0",
|
"is-svg": "3.0.0",
|
||||||
"is-url": "1.2.4",
|
|
||||||
"js-yaml": "3.12.1",
|
"js-yaml": "3.12.1",
|
||||||
"jsdom": "13.1.0",
|
"jsdom": "13.2.0",
|
||||||
"json5": "2.1.0",
|
"json5": "2.1.0",
|
||||||
"json5-loader": "1.0.1",
|
"json5-loader": "1.0.1",
|
||||||
"katex": "0.10.0",
|
"katex": "0.10.0",
|
||||||
|
@ -5,11 +5,15 @@ program
|
|||||||
.version(pkg.version)
|
.version(pkg.version)
|
||||||
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
|
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
|
||||||
.option('--disable-clustering', 'Disable clustering')
|
.option('--disable-clustering', 'Disable clustering')
|
||||||
.option('--disable-queue', 'Disable job queue')
|
.option('--disable-queue', 'Disable job queue processing')
|
||||||
|
.option('--only-queue', 'Pocessing job queue only')
|
||||||
.option('--quiet', 'Suppress all logs')
|
.option('--quiet', 'Suppress all logs')
|
||||||
.option('--verbose', 'Enable all logs')
|
.option('--verbose', 'Enable all logs')
|
||||||
.option('--slow', 'Delay all requests (for debbuging)')
|
.option('--slow', 'Delay all requests (for debbuging)')
|
||||||
.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.')
|
.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.')
|
||||||
.parse(process.argv);
|
.parse(process.argv);
|
||||||
|
|
||||||
|
if (process.env.MK_DISABLE_QUEUE) program.disableQueue = true;
|
||||||
|
if (process.env.MK_ONLY_QUEUE) program.onlyQueue = true;
|
||||||
|
|
||||||
export { program };
|
export { program };
|
||||||
|
@ -119,11 +119,11 @@ export default Vue.extend({
|
|||||||
font-size 16px
|
font-size 16px
|
||||||
cursor pointer
|
cursor pointer
|
||||||
transition inherit
|
transition inherit
|
||||||
|
color var(--text)
|
||||||
|
|
||||||
> span
|
> span
|
||||||
display block
|
display block
|
||||||
line-height 20px
|
line-height 20px
|
||||||
color var(--text)
|
|
||||||
transition inherit
|
transition inherit
|
||||||
|
|
||||||
> p
|
> p
|
||||||
|
@ -6,7 +6,6 @@ import * as fs from 'fs';
|
|||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
import { Source, Mixin } from './types';
|
import { Source, Mixin } from './types';
|
||||||
import isUrl = require('is-url');
|
|
||||||
import * as pkg from '../../package.json';
|
import * as pkg from '../../package.json';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,10 +25,7 @@ export default function load() {
|
|||||||
|
|
||||||
const mixin = {} as Mixin;
|
const mixin = {} as Mixin;
|
||||||
|
|
||||||
// Validate URLs
|
const url = validateUrl(config.url);
|
||||||
if (!isUrl(config.url)) throw `url="${config.url}" is not a valid URL`;
|
|
||||||
|
|
||||||
const url = new URL(config.url);
|
|
||||||
config.url = normalizeUrl(config.url);
|
config.url = normalizeUrl(config.url);
|
||||||
|
|
||||||
mixin.host = url.host;
|
mixin.host = url.host;
|
||||||
@ -51,6 +47,21 @@ export default function load() {
|
|||||||
return Object.assign(config, mixin);
|
return Object.assign(config, mixin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tryCreateUrl(url: string) {
|
||||||
|
try {
|
||||||
|
return new URL(url);
|
||||||
|
} catch (e) {
|
||||||
|
throw `url="${url}" is not a valid URL.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateUrl(url: string) {
|
||||||
|
const result = tryCreateUrl(url);
|
||||||
|
if (result.pathname.replace('/', '').length) throw `url="${url}" is not a valid URL, has a pathname.`;
|
||||||
|
if (!url.includes(result.host)) throw `url="${url}" is not a valid URL, has an invalid hostname.`;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeUrl(url: string) {
|
function normalizeUrl(url: string) {
|
||||||
return url.endsWith('/') ? url.substr(0, url.length - 1) : url;
|
return url.endsWith('/') ? url.substr(0, url.length - 1) : url;
|
||||||
}
|
}
|
||||||
|
80
src/index.ts
80
src/index.ts
@ -35,6 +35,11 @@ const ev = new Xev();
|
|||||||
function main() {
|
function main() {
|
||||||
process.title = `Misskey (${cluster.isMaster ? 'master' : 'worker'})`;
|
process.title = `Misskey (${cluster.isMaster ? 'master' : 'worker'})`;
|
||||||
|
|
||||||
|
if (program.onlyQueue) {
|
||||||
|
queueMain();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (cluster.isMaster || program.disableClustering) {
|
if (cluster.isMaster || program.disableClustering) {
|
||||||
masterMain();
|
masterMain();
|
||||||
|
|
||||||
@ -53,12 +58,7 @@ function main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function greet() {
|
||||||
* Init master process
|
|
||||||
*/
|
|
||||||
async function masterMain() {
|
|
||||||
let config: Config;
|
|
||||||
|
|
||||||
if (!program.quiet) {
|
if (!program.quiet) {
|
||||||
//#region Misskey logo
|
//#region Misskey logo
|
||||||
const v = `v${pkg.version}`;
|
const v = `v${pkg.version}`;
|
||||||
@ -75,10 +75,34 @@ async function masterMain() {
|
|||||||
bootLogger.info('Welcome to Misskey!');
|
bootLogger.info('Welcome to Misskey!');
|
||||||
bootLogger.info(`Misskey v${pkg.version}`, true);
|
bootLogger.info(`Misskey v${pkg.version}`, true);
|
||||||
bootLogger.info('Misskey is maintained by @syuilo, @AyaMorisawa, @mei23, and @acid-chicken.');
|
bootLogger.info('Misskey is maintained by @syuilo, @AyaMorisawa, @mei23, and @acid-chicken.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init master process
|
||||||
|
*/
|
||||||
|
async function masterMain() {
|
||||||
|
greet();
|
||||||
|
|
||||||
|
let config: Config;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// initialize app
|
// initialize app
|
||||||
config = await init();
|
config = await init();
|
||||||
|
|
||||||
|
if (config.port == null) {
|
||||||
|
bootLogger.error('The port is not configured. Please configure port.', true);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.platform === 'linux' && isWellKnownPort(config.port) && !isRoot()) {
|
||||||
|
bootLogger.error('You need root privileges to listen on well-known port on Linux', true);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!await isPortAvailable(config.port)) {
|
||||||
|
bootLogger.error(`Port ${config.port} is already in use`, true);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
bootLogger.error('Fatal error occurred during initialization', true);
|
bootLogger.error('Fatal error occurred during initialization', true);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@ -90,6 +114,9 @@ async function masterMain() {
|
|||||||
await spawnWorkers(config.clusterLimit);
|
await spawnWorkers(config.clusterLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start queue
|
||||||
|
require('./queue').default();
|
||||||
|
|
||||||
bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, true);
|
bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,15 +127,35 @@ async function workerMain() {
|
|||||||
// start server
|
// start server
|
||||||
await require('./server').default();
|
await require('./server').default();
|
||||||
|
|
||||||
// start processor
|
|
||||||
require('./queue').default();
|
|
||||||
|
|
||||||
if (cluster.isWorker) {
|
if (cluster.isWorker) {
|
||||||
// Send a 'ready' message to parent process
|
// Send a 'ready' message to parent process
|
||||||
process.send('ready');
|
process.send('ready');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function queueMain() {
|
||||||
|
greet();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// initialize app
|
||||||
|
await init();
|
||||||
|
} catch (e) {
|
||||||
|
bootLogger.error('Fatal error occurred during initialization', true);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bootLogger.succ('Misskey initialized');
|
||||||
|
|
||||||
|
// start processor
|
||||||
|
const queue = require('./queue').default();
|
||||||
|
|
||||||
|
if (queue) {
|
||||||
|
bootLogger.succ('Queue started', true);
|
||||||
|
} else {
|
||||||
|
bootLogger.error('Queue not available');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const runningNodejsVersion = process.version.slice(1).split('.').map(x => parseInt(x, 10));
|
const runningNodejsVersion = process.version.slice(1).split('.').map(x => parseInt(x, 10));
|
||||||
const requiredNodejsVersion = [10, 0, 0];
|
const requiredNodejsVersion = [10, 0, 0];
|
||||||
const satisfyNodejsVersion = !lessThan(runningNodejsVersion, requiredNodejsVersion);
|
const satisfyNodejsVersion = !lessThan(runningNodejsVersion, requiredNodejsVersion);
|
||||||
@ -170,21 +217,6 @@ async function init(): Promise<Config> {
|
|||||||
|
|
||||||
configLogger.succ('Loaded');
|
configLogger.succ('Loaded');
|
||||||
|
|
||||||
if (config.port == null) {
|
|
||||||
bootLogger.error('The port is not configured. Please configure port.', true);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform === 'linux' && isWellKnownPort(config.port) && !isRoot()) {
|
|
||||||
bootLogger.error('You need root privileges to listen on well-known port on Linux', true);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!await isPortAvailable(config.port)) {
|
|
||||||
bootLogger.error(`Port ${config.port} is already in use`, true);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to connect to MongoDB
|
// Try to connect to MongoDB
|
||||||
try {
|
try {
|
||||||
await checkMongoDB(config, bootLogger);
|
await checkMongoDB(config, bootLogger);
|
||||||
|
@ -142,7 +142,7 @@ export const mfmLanguage = P.createLanguage({
|
|||||||
},
|
},
|
||||||
hashtag: () => P((input, i) => {
|
hashtag: () => P((input, i) => {
|
||||||
const text = input.substr(i);
|
const text = input.substr(i);
|
||||||
const match = text.match(/^#([^\s\.,!\?'"#:]+)/i);
|
const match = text.match(/^#([^\s\.,!\?'"#:\/]+)/i);
|
||||||
if (!match) return P.makeFailure(i, 'not a hashtag');
|
if (!match) return P.makeFailure(i, 'not a hashtag');
|
||||||
let hashtag = match[1];
|
let hashtag = match[1];
|
||||||
hashtag = removeOrphanedBrackets(hashtag);
|
hashtag = removeOrphanedBrackets(hashtag);
|
||||||
|
@ -45,7 +45,7 @@ export default class Logger {
|
|||||||
this.log(important ? chalk.bgGreen.white('DONE') : chalk.green('DONE'), chalk.green(message), important);
|
this.log(important ? chalk.bgGreen.white('DONE') : chalk.green('DONE'), chalk.green(message), important);
|
||||||
}
|
}
|
||||||
|
|
||||||
public debug(message: string, important = false): void { // デバッグ用に使う(開発者にとっては必要だが利用者にとっては不要な情報)
|
public debug(message: string, important = false): void { // デバッグ用に使う(開発者に必要だが利用者に不要な情報)
|
||||||
if (process.env.NODE_ENV != 'production' || program.verbose) {
|
if (process.env.NODE_ENV != 'production' || program.verbose) {
|
||||||
this.log(chalk.gray('VERB'), chalk.gray(message), important);
|
this.log(chalk.gray('VERB'), chalk.gray(message), important);
|
||||||
}
|
}
|
||||||
|
20
src/prelude/maybe.ts
Normal file
20
src/prelude/maybe.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export interface Maybe<T> {
|
||||||
|
isJust(): this is Just<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Just<T> = Maybe<T> & {
|
||||||
|
get(): T
|
||||||
|
};
|
||||||
|
|
||||||
|
export function just<T>(value: T): Just<T> {
|
||||||
|
return {
|
||||||
|
isJust: () => true,
|
||||||
|
get: () => value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function nothing<T>(): Maybe<T> {
|
||||||
|
return {
|
||||||
|
isJust: () => false,
|
||||||
|
};
|
||||||
|
}
|
@ -4,13 +4,15 @@ import config from '../config';
|
|||||||
import { ILocalUser } from '../models/user';
|
import { ILocalUser } from '../models/user';
|
||||||
import { program } from '../argv';
|
import { program } from '../argv';
|
||||||
import handler from './processors';
|
import handler from './processors';
|
||||||
|
import { queueLogger } from './logger';
|
||||||
|
|
||||||
const enableQueue = config.redis != null && !program.disableQueue;
|
const enableQueue = !program.disableQueue;
|
||||||
|
const queueAvailable = config.redis != null;
|
||||||
|
|
||||||
const queue = initializeQueue();
|
const queue = initializeQueue();
|
||||||
|
|
||||||
function initializeQueue() {
|
function initializeQueue() {
|
||||||
if (enableQueue) {
|
if (queueAvailable) {
|
||||||
return new Queue('misskey', {
|
return new Queue('misskey', {
|
||||||
redis: {
|
redis: {
|
||||||
port: config.redis.port,
|
port: config.redis.port,
|
||||||
@ -30,7 +32,7 @@ function initializeQueue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createHttpJob(data: any) {
|
export function createHttpJob(data: any) {
|
||||||
if (enableQueue) {
|
if (queueAvailable) {
|
||||||
return queue.createJob(data)
|
return queue.createJob(data)
|
||||||
.retries(4)
|
.retries(4)
|
||||||
.backoff('exponential', 16384) // 16s
|
.backoff('exponential', 16384) // 16s
|
||||||
@ -52,7 +54,7 @@ export function deliver(user: ILocalUser, content: any, to: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createExportNotesJob(user: ILocalUser) {
|
export function createExportNotesJob(user: ILocalUser) {
|
||||||
if (!enableQueue) throw 'queue disabled';
|
if (!queueAvailable) throw 'queue unavailable';
|
||||||
|
|
||||||
return queue.createJob({
|
return queue.createJob({
|
||||||
type: 'exportNotes',
|
type: 'exportNotes',
|
||||||
@ -62,7 +64,10 @@ export function createExportNotesJob(user: ILocalUser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
if (enableQueue) {
|
if (queueAvailable && enableQueue) {
|
||||||
queue.process(128, handler);
|
queue.process(128, handler);
|
||||||
|
queueLogger.succ('Processing started');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return queue;
|
||||||
}
|
}
|
||||||
|
@ -19,23 +19,28 @@ export default class Resolver {
|
|||||||
: value;
|
: value;
|
||||||
|
|
||||||
switch (collection.type) {
|
switch (collection.type) {
|
||||||
case 'Collection':
|
case 'Collection': {
|
||||||
collection.objects = collection.items;
|
collection.objects = collection.items;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'OrderedCollection':
|
case 'OrderedCollection': {
|
||||||
collection.objects = collection.orderedItems;
|
collection.objects = collection.orderedItems;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default: {
|
||||||
|
logger.error(`unknown collection type: ${collection.type}`);
|
||||||
throw new Error(`unknown collection type: ${collection.type}`);
|
throw new Error(`unknown collection type: ${collection.type}`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async resolve(value: any): Promise<IObject> {
|
public async resolve(value: any): Promise<IObject> {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
logger.error('resolvee is null (or undefined)');
|
||||||
throw new Error('resolvee is null (or undefined)');
|
throw new Error('resolvee is null (or undefined)');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +49,7 @@ export default class Resolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.history.has(value)) {
|
if (this.history.has(value)) {
|
||||||
|
logger.error(`cannot resolve already resolved one`);
|
||||||
throw new Error('cannot resolve already resolved one');
|
throw new Error('cannot resolve already resolved one');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +65,7 @@ export default class Resolver {
|
|||||||
},
|
},
|
||||||
json: true
|
json: true
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
|
logger.error(`request error: ${e.message}`);
|
||||||
throw new Error(`request error: ${e.message}`);
|
throw new Error(`request error: ${e.message}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -42,7 +42,12 @@ export async function proxyMedia(ctx: Koa.BaseContext) {
|
|||||||
ctx.body = image.data;
|
ctx.body = image.data;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
serverLogger.error(e);
|
serverLogger.error(e);
|
||||||
|
|
||||||
|
if (typeof e == 'number' && e >= 400 && e < 500) {
|
||||||
|
ctx.status = e;
|
||||||
|
} else {
|
||||||
ctx.status = 500;
|
ctx.status = 500;
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
@ -611,6 +611,14 @@ describe('MFM', () => {
|
|||||||
text('(#123)'),
|
text('(#123)'),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('ignore slash', () => {
|
||||||
|
const tokens = parse('#foo/bar');
|
||||||
|
assert.deepStrictEqual(tokens, [
|
||||||
|
leaf('hashtag', { hashtag: 'foo' }),
|
||||||
|
text('/bar'),
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('quote', () => {
|
describe('quote', () => {
|
||||||
|
28
test/prelude/maybe.ts
Normal file
28
test/prelude/maybe.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Tests of Maybe
|
||||||
|
*
|
||||||
|
* How to run the tests:
|
||||||
|
* > mocha test/prelude/maybe.ts --require ts-node/register
|
||||||
|
*
|
||||||
|
* To specify test:
|
||||||
|
* > mocha test/prelude/maybe.ts --require ts-node/register -g 'test name'
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import { just, nothing } from '../../src/prelude/maybe';
|
||||||
|
|
||||||
|
describe('just', () => {
|
||||||
|
it('has a value', () => {
|
||||||
|
assert.deepStrictEqual(just(3).isJust(), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has the inverse called get', () => {
|
||||||
|
assert.deepStrictEqual(just(3).get(), 3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('nothing', () => {
|
||||||
|
it('has no value', () => {
|
||||||
|
assert.deepStrictEqual(nothing().isJust(), false);
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user