Compare commits

...

39 Commits
7.1.0 ... 7.2.0

Author SHA1 Message Date
82059d4fd9 7.2.0 2018-08-22 05:24:16 +09:00
07ddeae2f1 Clean up 2018-08-22 04:53:02 +09:00
f2279758b2 Merge pull request #2366 from acid-chicken/patch-autogen
[AUTOMATED] Update README.md
2018-08-22 03:30:12 +09:00
1ed189a518 Merge pull request #2386 from acid-chicken/patch-3
Update boot.js
2018-08-22 02:25:41 +09:00
137741d307 Update index.js 2018-08-22 01:52:13 +09:00
d702f6e090 Rename ja-ks.yml to ja-KS.yml 2018-08-22 01:51:42 +09:00
f33701233c Update boot.js 2018-08-22 01:50:13 +09:00
70003269e5 Update boot.js 2018-08-22 01:48:08 +09:00
61896d2386 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-22 01:46:13 +09:00
52d640c5a7 Fix 2018-08-22 01:46:10 +09:00
c65f5761e1 Merge pull request #2385 from mei23/mei-0821-aptype
ActivityPub で Content-Type を正しく扱う
2018-08-22 01:23:43 +09:00
3016ac4805 Fix bug 2018-08-22 01:02:56 +09:00
28a47cd331 Fix 2018-08-22 00:59:07 +09:00
6ecb88b0d1 #2338 2018-08-22 00:52:00 +09:00
8df1278c8e Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-22 00:44:26 +09:00
52bec430d4 use ja-JP 2018-08-22 00:44:07 +09:00
da4cec8767 Merge pull request #2362 from syuilo/greenkeeper/vue-loader-15.4.0
Update vue-loader to the latest version 🚀
2018-08-22 00:11:24 +09:00
ad0087d7dd Merge pull request #2382 from syuilo/greenkeeper/webpack-4.17.0
Update webpack to the latest version 🚀
2018-08-22 00:11:12 +09:00
9630860035 Merge pull request #2383 from syuilo/greenkeeper/sharp-0.20.7
fix(package): update sharp to version 0.20.7
2018-08-22 00:11:01 +09:00
75e4c8d74d Better reponse 2018-08-21 23:56:15 +09:00
1a5ee81e7e fix(package): update sharp to version 0.20.7
Closes #2368
2018-08-21 11:18:21 +00:00
3476be16ab Merge pull request #2381 from mei23/mei-0821-apnote
ActivityPub Note/Outbox の公開範囲の修正
2018-08-21 20:07:33 +09:00
c42f61a0f4 fix(package): update webpack to version 4.17.0 2018-08-21 08:48:10 +00:00
b42a9e1c4e Set ActivityPub Content-Type 2018-08-21 13:48:03 +09:00
4495525705 Respect visibility in ActivityPub Note/Outbox 2018-08-21 13:22:30 +09:00
a603602f32 Clean up 2018-08-21 05:42:31 +09:00
fd947407af Revert "Fix bug?"
This reverts commit 2c9bacfcea.
2018-08-21 01:23:39 +09:00
30444e5f1a #2359 など 2018-08-21 01:03:58 +09:00
f0d818de24 Fix bug 2018-08-21 00:12:45 +09:00
3fb98e808f 7.1.2 2018-08-20 23:49:27 +09:00
2c9bacfcea Fix bug? 2018-08-20 23:49:00 +09:00
ae0284b1b1 Update README.md [AUTOGEN] 2018-08-20 19:03:01 +09:00
ec5aa10167 fix(package): update vue-loader to version 15.4.0 2018-08-20 00:44:56 +00:00
a542765cf8 Merge pull request #2352 from acid-chicken/patch-2
Update README.md
2018-08-20 07:45:35 +09:00
fd3f8d43db Merge pull request #2356 from acid-chicken/patch-3
Fix z-index
2018-08-20 07:44:57 +09:00
4f4496078a Update user.vue 2018-08-20 02:05:57 +09:00
8f4f5b4ce0 7.1.1 2018-08-20 01:42:56 +09:00
bdc6718ae5 Fix bug 2018-08-20 01:41:53 +09:00
09d1f1c20d Update README.md 2018-08-19 23:14:22 +09:00
26 changed files with 326 additions and 101 deletions

View File

@ -39,9 +39,15 @@ please see [Setup and installation guide](./docs/setup.en.md).
----------------------------------------------------------------
**[PR](https://github.com/syuilo/misskey/pulls)s welcome!**
If you want to...
* i18n ... please see [Translation guide](./docs/translate.en.md).
* l10n ... please visit https://crowdin.com/project/misskey
### i18n
Please see [Translation guide](./docs/translate.en.md).
### l10n
Misskey is using Crowdin for l10n.
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)](https://crowdin.com/project/misskey)
:heart: Backers & Sponsors
----------------------------------------------------------------
@ -53,8 +59,8 @@ If you want to...
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/3384329/8b713330cb27404ea6e9fac50ff96efe/1?token-time=2145916800&token-hash=0eu4-m1gTWA9PhptVZt6rdKcusqcD7RB87rJT23VVFI%3D" alt="べすれい"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D" alt="gutfuckllc"></td>
<td><img src="https://c8.patreon.com/2/100/12718187" alt="Peter G."></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=zwSu01tOtn5xTUucDZHuPsCxF2HBEMVs9ROJKTlEV_o%3D" alt="nemu"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/2?token-time=2145916800&token-hash=zElv7ZcPL3viGsXbNG_KWiKrbV0vvw1gk0panx8DJoo%3D" alt="Naoki Kosaka"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12931605/ead494101f364dffa90efe49e36fb494/1?token-time=2145916800&token-hash=NzSFPjIlodXyv41rwK61aZWVZWfI4surJaNj8vWKvqM%3D" alt="Reiju"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=12378075">39ff</a></td>
<td><a href="https://www.patreon.com/user?u=12731202">negao</a></td>
@ -62,22 +68,26 @@ If you want to...
<td><a href="https://www.patreon.com/user?u=3384329">べすれい</a></td>
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
<td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td>
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
<td><a href="https://www.patreon.com/user?u=5881381">Naoki Kosaka</a></td>
<td><a href="https://www.patreon.com/user?u=12931605">Reiju</a></td>
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12931605/ead494101f364dffa90efe49e36fb494/1?token-time=2145916800&token-hash=NzSFPjIlodXyv41rwK61aZWVZWfI4surJaNj8vWKvqM%3D" alt="Reiju"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1?token-time=2145916800&token-hash=UERBN4OyP7Nh5XwwdDg0N0IE5cD6_qUQMO81Z5Wizso%3D" alt="Hiratake"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D" alt="dansup"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4950409/28e7d016209243759d9316be2e21381d/2?token-time=2145916800&token-hash=LuEaDkchH3GQWUcTOhBQ8xfKQYF0s5FjlZRd7Yduia8%3D" alt="mikan54951"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D" alt="Takashi Shibuya"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12959468/c249e15aebec4424b5c0f427173671b6/1?token-time=2145916800&token-hash=lubpCEdxAkxPlpR2O6bvZ7BIh8Q4nGf-U_mE1qpjVAQ%3D" alt="fujishan"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=12931605">Reiju</a></td>
<td><a href="https://www.patreon.com/hiratake">Hiratake</a></td>
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
<td><a href="https://www.patreon.com/user?u=4950409">mikan54951</a></td>
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
<td><a href="https://www.patreon.com/fujishan">fujishan</a></td>
</tr></table>
**Last updated:** Sat, 18 Aug 2018 02:02:58 UTC
**Last updated:** Mon, 20 Aug 2018 10:02:31 UTC
<!-- PATREON_END -->
:four_leaf_clover: Copyright

View File

@ -11,12 +11,12 @@ If you find an untranslated part on Misskey:
- In fact, `foo` should be a word that is appropriate for the situation and is easy to understand in English.
- For example, if the untranslated portion is the following "タイムライン" you must write: `%i18n:@timeline%`.
3. Open the `locales/ja.yml`, check whether the <strong>file name (path)</strong> found in step 1 exists, if not, create it.
3. Open the `locales/ja-JP.yml`, check whether the <strong>file name (path)</strong> found in step 1 exists, if not, create it.
- Do not put the beginning of the path `src/client/app/` in the locale file.
- For example, in this case we want to modify untranslated parts of `src/client/app/mobile/views/pages/home.vue`, so the key is `mobile/views/pages/home.vue`.
4. Add the text property using the `foo` keyword below the path that you found or created in step 2. Make sure to type your text in quotation marks. Text should always be inside of quotes.
- For example, in this case we add timeline: `timeline: "タイムライン"` to `locales/ja.yml`.
- For example, in this case we add timeline: `timeline: "タイムライン"` to `locales/ja-JP.yml`.
5. And done

View File

@ -16,7 +16,7 @@ Si vous trouvez un segment non-traduit sur Misskey :
- Par exemple, dans ce cas de figure, nous voulons modifier le segment non-traduit de : `src/client/app/mobile/views/pages/home.vue`donc il faut juste écrire : `mobile/views/pages/home.vue` dans les fichiers linguistiques.
4. Ajoutez la propriété du texte traduit grâce à la clef `foo`, en-dessous du chemin correspondant à votre modification que vous avez trouvé ou créé dans l'étape 2. À côté, veuillez indiquer entre "guillemets" la valeur de votre traduction.
- Par exemple, dans ce cas de figure, nous ajoutons la propriété et la traduction `timeline: "Timeline"` à `locales/fr.yml`, mais aussi la propriété et la version originale `timeline: "タイムライン"` à `locales/ja.yml`.
- Par exemple, dans ce cas de figure, nous ajoutons la propriété et la traduction `timeline: "Timeline"` à `locales/fr.yml`, mais aussi la propriété et la version originale `timeline: "タイムライン"` à `locales/ja-JP.yml`.
5. Vous avez réussi à traduire une portion de misskey

View File

@ -11,12 +11,12 @@ Misskey内の未翻訳箇所を見つけたら
- `foo`は実際にはその場に適したわかりやすい(英語の)名前にしてください。
- 例えば未翻訳箇所が「タイムライン」というテキストだった場合、`%i18n:@timeline%`のようにします。
3. `locales/ja.yml`を開き、1.で見つけた<strong>ファイル名(パス)</strong>のキーが存在するか確認し、無ければ作成してください。
3. `locales/ja-JP.yml`を開き、1.で見つけた<strong>ファイル名(パス)</strong>のキーが存在するか確認し、無ければ作成してください。
- パスの`src/client/app/`は省略してください。
- 例えば、今回の例では`src/client/app/mobile/views/pages/home.vue`の未翻訳箇所を修正したいので、キーは`mobile/views/pages/home.vue`になります。
4. そのキーの直下に2.で置換した`foo`の部分をキーとし、テキストを値とするプロパティを追加します。
- 例えば、今回の例で言うと`locales/ja.yml``timeline: "タイムライン"`を追加します。
- 例えば、今回の例で言うと`locales/ja-JP.yml``timeline: "タイムライン"`を追加します。
5. 完了です!

View File

@ -23,7 +23,6 @@ const uglifyes = require('uglify-es');
const locales = require('./locales');
import { fa } from './src/misc/fa';
import config from './src/config';
const uglify = uglifyComposer(uglifyes, console);
@ -118,7 +117,6 @@ gulp.task('build:client:script', () => {
const client = require('./built/client/meta.json');
return gulp.src(['./src/client/app/boot.js', './src/client/app/safe.js'])
.pipe(replace('VERSION', JSON.stringify(client.version)))
.pipe(replace('API', JSON.stringify(config.api_url)))
.pipe(replace('ENV', JSON.stringify(env)))
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
.pipe(isProduction ? uglify({

View File

@ -1,4 +1,4 @@
# **Please DO NOT edit these files** except `ja.yml`.
# **Please DO NOT edit these files** except `ja-JP.yml`.
If you want to...
* i18n ... please see [Translation guide](../docs/translate.en.md).

View File

@ -8,14 +8,14 @@ const yaml = require('js-yaml');
const loadLang = lang => yaml.safeLoad(
fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8'));
const native = loadLang('ja');
const native = loadLang('ja-JP');
const langs = {
'de': loadLang('de'),
'en': loadLang('en'),
'fr': loadLang('fr'),
'ja': native,
'ja-ks': loadLang('ja-ks'),
'ja-KS': loadLang('ja-KS'),
'pl': loadLang('pl'),
'es': loadLang('es')
};

File diff suppressed because it is too large Load Diff

View File

@ -691,7 +691,6 @@ desktop/views/components/settings.vue:
password: "パスワード"
2fa: "二段階認証"
other: "その他"
license: "ライセンス"
behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み"

View File

@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "7.1.0",
"clientVersion": "1.0.8685",
"version": "7.2.0",
"clientVersion": "1.0.8724",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@ -181,7 +181,7 @@
"s-age": "1.1.2",
"sass-loader": "7.1.0",
"seedrandom": "2.4.4",
"sharp": "0.20.5",
"sharp": "0.20.7",
"showdown": "1.8.6",
"showdown-highlightjs-extension": "0.1.2",
"single-line-log": "1.1.2",
@ -208,7 +208,7 @@
"vue-cropperjs": "2.2.1",
"vue-js-modal": "1.3.17",
"vue-json-tree-view": "2.1.4",
"vue-loader": "15.3.0",
"vue-loader": "15.4.0",
"vue-router": "3.0.1",
"vue-style-loader": "4.1.2",
"vue-template-compiler": "2.5.17",
@ -217,7 +217,7 @@
"vuex-persistedstate": "2.5.4",
"web-push": "3.3.2",
"webfinger.js": "2.6.6",
"webpack": "4.16.5",
"webpack": "4.17.0",
"webpack-cli": "3.1.0",
"websocket": "1.0.26",
"ws": "6.0.0",

View File

@ -32,13 +32,15 @@
//#region Detect app name
let app = null;
if (url.pathname == '/docs' || url.pathname.startsWith('/docs/')) app = 'docs';
if (url.pathname == '/dev' || url.pathname.startsWith('/dev/')) app = 'dev';
if (url.pathname == '/auth' || url.pathname.startsWith('/auth/')) app = 'auth';
if (`${url.pathname}/`.startsWith('/docs/')) app = 'docs';
if (`${url.pathname}/`.startsWith('/dev/')) app = 'dev';
if (`${url.pathname}/`.startsWith('/auth/')) app = 'auth';
//#endregion
//#region Detect the user language
let lang = navigator.language.split('-')[0];
let lang = navigator.language;
if (!LANGS.includes(lang)) lang = lang.split('-')[0];
// The default language is English
if (!LANGS.includes(lang)) lang = 'en';
@ -104,7 +106,7 @@
// グローバルにタイマーIDを代入しておく
window.mkBootTimer = window.setTimeout(async () => {
// Fetch meta
const res = await fetch(API + '/meta', {
const res = await fetch('/api/meta', {
method: 'POST',
cache: 'no-cache'
});

View File

@ -36,8 +36,7 @@ export default Vue.extend({
password: '',
token: '',
apiUrl,
host,
twitterIntegration
host
};
},
methods: {

View File

@ -1,41 +1,43 @@
<template>
<form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()">
<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
<span>%i18n:@invitation-code%</span>
<span slot="prefix">%fa:id-card-alt%</span>
<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p>
</ui-input>
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername">
<span>%i18n:@username%</span>
<span slot="prefix">@</span>
<span slot="suffix">@{{ host }}</span>
<p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw% %i18n:@checking%</p>
<p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw% %i18n:@available%</p>
<p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@unavailable%</p>
<p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@error%</p>
<p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@invalid-format%</p>
<p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-short%</p>
<p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-long%</p>
</ui-input>
<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true">
<span>%i18n:@password%</span>
<span slot="prefix">%fa:lock%</span>
<div slot="text">
<p slot="text" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@weak-password%</p>
<p slot="text" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw% %i18n:@normal-password%</p>
<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p>
</div>
</ui-input>
<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype">
<span>%i18n:@password% (%i18n:@retype%)</span>
<span slot="prefix">%fa:lock%</span>
<div slot="text">
<p slot="text" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw% %i18n:@password-matched%</p>
<p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p>
</div>
</ui-input>
<div v-if="meta && meta.recaptchaSitekey != null" class="g-recaptcha" :data-sitekey="meta.recaptchaSitekey" style="margin: 16px 0;"></div>
<ui-button type="submit">%i18n:@create%</ui-button>
<template v-if="meta">
<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
<span>%i18n:@invitation-code%</span>
<span slot="prefix">%fa:id-card-alt%</span>
<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p>
</ui-input>
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername">
<span>%i18n:@username%</span>
<span slot="prefix">@</span>
<span slot="suffix">@{{ host }}</span>
<p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw% %i18n:@checking%</p>
<p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw% %i18n:@available%</p>
<p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@unavailable%</p>
<p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@error%</p>
<p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@invalid-format%</p>
<p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-short%</p>
<p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-long%</p>
</ui-input>
<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true">
<span>%i18n:@password%</span>
<span slot="prefix">%fa:lock%</span>
<div slot="text">
<p slot="text" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@weak-password%</p>
<p slot="text" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw% %i18n:@normal-password%</p>
<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p>
</div>
</ui-input>
<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype">
<span>%i18n:@password% (%i18n:@retype%)</span>
<span slot="prefix">%fa:lock%</span>
<div slot="text">
<p slot="text" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw% %i18n:@password-matched%</p>
<p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p>
</div>
</ui-input>
<div v-if="meta.recaptchaSitekey != null" class="g-recaptcha" :data-sitekey="meta.recaptchaSitekey" style="margin: 16px 0;"></div>
<ui-button type="submit">%i18n:@create%</ui-button>
</template>
</form>
</template>

View File

@ -4,7 +4,6 @@ declare const _THEME_COLOR_: string;
declare const _COPYRIGHT_: string;
declare const _VERSION_: string;
declare const _CODENAME_: string;
declare const _LICENSE_: string;
const address = new URL(location.href);
@ -19,4 +18,3 @@ export const themeColor = _THEME_COLOR_;
export const copyright = _COPYRIGHT_;
export const version = _VERSION_;
export const codename = _CODENAME_;
export const license = _LICENSE_;

View File

@ -191,12 +191,6 @@
<button class="ui button block" @click="taskmngr">%i18n:@task-manager%</button>
</details>
</section>
<section class="other" v-show="page == 'other'">
<h1>%i18n:@license%</h1>
<div v-html="license"></div>
<a :href="licenseUrl" target="_blank">%i18n:@third-parties%</a>
</section>
</div>
</div>
</template>
@ -211,7 +205,7 @@ import XApi from './settings.api.vue';
import XApps from './settings.apps.vue';
import XSignins from './settings.signins.vue';
import XDrive from './settings.drive.vue';
import { url, docsUrl, license, lang, langs, version } from '../../../config';
import { url, langs, version } from '../../../config';
import checkForUpdate from '../../../common/scripts/check-for-update';
import MkTaskManager from './taskmanager.vue';
@ -230,7 +224,6 @@ export default Vue.extend({
return {
page: 'profile',
meta: null,
license,
version,
langs,
latestVersion: undefined,
@ -238,10 +231,6 @@ export default Vue.extend({
};
},
computed: {
licenseUrl(): string {
return `${docsUrl}/${lang}/license`;
},
apiViaStream: {
get() { return this.$store.state.device.apiViaStream; },
set(value) { this.$store.commit('device/set', { key: 'apiViaStream', value }); }

View File

@ -247,7 +247,7 @@ root(isDark)
top 47px
box-shadow 0 4px 4px isDark ? rgba(#000, 0.3) : rgba(#000, 0.07)
background-color $bg
z-index 1
z-index 2
> .nav-container
display flex

View File

@ -118,6 +118,7 @@ export interface IRemoteUser extends IUserBase {
publicKeyPem: string;
};
updatedAt: Date;
isAdmin: false;
}
export type IUser = ILocalUser | IRemoteUser;

View File

@ -41,10 +41,20 @@ function inbox(ctx: Router.IRouterContext) {
}
function isActivityPubReq(ctx: Router.IRouterContext) {
ctx.response.vary('Accept');
const accepted = ctx.accepts('html', 'application/activity+json', 'application/ld+json');
return ['application/activity+json', 'application/ld+json'].includes(accepted as string);
}
export function setResponseType(ctx: Router.IRouterContext) {
const accpet = ctx.accepts('application/activity+json', 'application/ld+json');
if (accpet === 'application/ld+json') {
ctx.response.type = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8';
} else {
ctx.response.type = 'application/activity+json; charset=utf-8';
}
}
// inbox
router.post('/inbox', json(), inbox);
router.post('/users/:user/inbox', json(), inbox);
@ -54,7 +64,8 @@ router.get('/notes/:note', async (ctx, next) => {
if (!isActivityPubReq(ctx)) return await next();
const note = await Note.findOne({
_id: new mongo.ObjectID(ctx.params.note)
_id: new mongo.ObjectID(ctx.params.note),
$or: [ { visibility: 'public' }, { visibility: 'home' } ]
});
if (note === null) {
@ -62,7 +73,8 @@ router.get('/notes/:note', async (ctx, next) => {
return;
}
ctx.body = pack(await renderNote(note));
ctx.body = pack(await renderNote(note, false));
setResponseType(ctx);
});
// outbox
@ -90,6 +102,7 @@ router.get('/users/:user/publickey', async ctx => {
if (isLocalUser(user)) {
ctx.body = pack(renderKey(user));
setResponseType(ctx);
} else {
ctx.status = 400;
}
@ -103,6 +116,7 @@ async function userInfo(ctx: Router.IRouterContext, user: IUser) {
}
ctx.body = pack(await renderPerson(user as ILocalUser));
setResponseType(ctx);
}
router.get('/users/:user', async ctx => {

View File

@ -1,5 +1,5 @@
import * as mongo from 'mongodb';
import * as Koa from 'koa';
import * as Router from 'koa-router';
import config from '../../config';
import $ from 'cafy'; import ID from '../../misc/cafy-id';
import User from '../../models/user';
@ -8,8 +8,9 @@ import pack from '../../remote/activitypub/renderer';
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page';
import renderFollowUser from '../../remote/activitypub/renderer/follow-user';
import { setResponseType } from '../activitypub';
export default async (ctx: Koa.Context) => {
export default async (ctx: Router.IRouterContext) => {
const userId = new mongo.ObjectID(ctx.params.user);
// Get 'cursor' parameter
@ -72,9 +73,11 @@ export default async (ctx: Koa.Context) => {
);
ctx.body = pack(rendered);
setResponseType(ctx);
} else {
// index page
const rendered = renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`, null);
ctx.body = pack(rendered);
setResponseType(ctx);
}
};

View File

@ -1,5 +1,5 @@
import * as mongo from 'mongodb';
import * as Koa from 'koa';
import * as Router from 'koa-router';
import config from '../../config';
import $ from 'cafy'; import ID from '../../misc/cafy-id';
import User from '../../models/user';
@ -8,8 +8,9 @@ import pack from '../../remote/activitypub/renderer';
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page';
import renderFollowUser from '../../remote/activitypub/renderer/follow-user';
import { setResponseType } from '../activitypub';
export default async (ctx: Koa.Context) => {
export default async (ctx: Router.IRouterContext) => {
const userId = new mongo.ObjectID(ctx.params.user);
// Get 'cursor' parameter
@ -72,9 +73,11 @@ export default async (ctx: Koa.Context) => {
);
ctx.body = pack(rendered);
setResponseType(ctx);
} else {
// index page
const rendered = renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`, null);
ctx.body = pack(rendered);
setResponseType(ctx);
}
};

View File

@ -1,16 +1,17 @@
import * as mongo from 'mongodb';
import * as Koa from 'koa';
import * as Router from 'koa-router';
import config from '../../config';
import $ from 'cafy'; import ID from '../../misc/cafy-id';
import User from '../../models/user';
import pack from '../../remote/activitypub/renderer';
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
import renderOrderedCollectionPage from '../../remote/activitypub/renderer/ordered-collection-page';
import { setResponseType } from '../activitypub';
import Note from '../../models/note';
import renderNote from '../../remote/activitypub/renderer/note';
export default async (ctx: Koa.Context) => {
export default async (ctx: Router.IRouterContext) => {
const userId = new mongo.ObjectID(ctx.params.user);
// Get 'sinceId' parameter
@ -83,7 +84,7 @@ export default async (ctx: Koa.Context) => {
if (sinceId) notes.reverse();
const renderedNotes = await Promise.all(notes.map(note => renderNote(note)));
const renderedNotes = await Promise.all(notes.map(note => renderNote(note, false)));
const rendered = renderOrderedCollectionPage(
`${partOf}?page=true${sinceId ? `&since_id=${sinceId}` : ''}${untilId ? `&until_id=${untilId}` : ''}`,
user.notesCount, renderedNotes, partOf,
@ -92,6 +93,7 @@ export default async (ctx: Koa.Context) => {
);
ctx.body = pack(rendered);
setResponseType(ctx);
} else {
// index page
const rendered = renderOrderedCollection(partOf, user.notesCount,
@ -99,5 +101,6 @@ export default async (ctx: Koa.Context) => {
`${partOf}?page=true&since_id=000000000000000000000000`
);
ctx.body = pack(rendered);
setResponseType(ctx);
}
};

View File

@ -1,6 +1,6 @@
import { performance } from 'perf_hooks';
import limitter from './limitter';
import { IUser, isLocalUser } from '../../models/user';
import { IUser } from '../../models/user';
import { IApp } from '../../models/app';
import endpoints from './endpoints';
@ -21,7 +21,7 @@ export default (endpoint: string, user: IUser, app: IApp, data: any, file?: any)
return rej('YOUR_ACCOUNT_HAS_BEEN_SUSPENDED');
}
if (ep.meta.requireAdmin && !(isLocalUser(user) && user.isAdmin)) {
if (ep.meta.requireAdmin && !user.isAdmin) {
return rej('YOU_ARE_NOT_ADMIN');
}

View File

@ -34,6 +34,10 @@ export default (params: any) => new Promise(async (res, rej) => {
return rej('user not found');
}
if (user.isAdmin) {
return rej('cannot suspend admin');
}
await User.findOneAndUpdate({
_id: user._id
}, {

View File

@ -63,7 +63,7 @@ export default async (ctx: Koa.Context) => {
if (verified) {
signin(ctx, user);
} else {
ctx.throw(400, {
ctx.throw(403, {
error: 'invalid token'
});
}
@ -71,7 +71,7 @@ export default async (ctx: Koa.Context) => {
signin(ctx, user);
}
} else {
ctx.throw(400, {
ctx.throw(403, {
error: 'incorrect password'
});
}

View File

@ -11,13 +11,13 @@ export default async function(
subscriber: Xev,
user: IUser
) {
const mute = await Mute.find({ muterId: user._id });
const mutedUserIds = mute.map(m => m.muteeId.toString());
// Subscribe stream
subscriber.on('hybrid-timeline', onEvent);
subscriber.on(`hybrid-timeline:${user._id}`, onEvent);
const mute = await Mute.find({ muterId: user._id });
const mutedUserIds = mute.map(m => m.muteeId.toString());
async function onEvent(note: any) {
//#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
if (mutedUserIds.indexOf(note.userId) != -1) {

View File

@ -16,7 +16,6 @@ import I18nReplacer from './src/misc/i18n';
import { pattern as i18nPattern, replacement as i18nReplacement } from './webpack/i18n';
import { pattern as faPattern, replacement as faReplacement } from './src/misc/fa';
const constants = require('./src/const.json');
import { licenseHtml } from './src/misc/license';
const locales = require('./locales');
const meta = require('./package.json');
@ -74,8 +73,7 @@ const consts = {
_VERSION_: version,
_CODENAME_: codename,
_LANG_: '%lang%',
_LANGS_: Object.keys(locales).map(l => [l, locales[l].meta.lang]),
_LICENSE_: licenseHtml
_LANGS_: Object.keys(locales).map(l => [l, locales[l].meta.lang])
};
const _consts: { [ key: string ]: any } = {};