Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
1092532292 | |||
8a79ba0e2b | |||
ca2949fbb4 | |||
17b373ac07 | |||
7aa66f438f | |||
73641fd78d | |||
64aac9d6ad | |||
2be13736c8 | |||
ff4f5fec1d | |||
7d64f8abe4 | |||
88e6929e9f | |||
5fb0a995dd | |||
58a04ce1a5 | |||
f74e0d9123 | |||
c6249b82d4 | |||
d6131c0b09 | |||
e62c810b7c | |||
2851a1a7ef | |||
12cd2709d6 | |||
bf54e58873 | |||
6b473e3a5c | |||
4b68abd963 | |||
0e764a2b3e | |||
9d1ed1eb0d | |||
a09a3465a2 | |||
001969efaf | |||
e7c515da9a | |||
8367c7dd49 | |||
55e6cae240 | |||
5553c3fb17 | |||
026265cb1e | |||
289c76a802 | |||
7c1bc1d6bc | |||
90cf0d32b5 |
@ -1 +1 @@
|
|||||||
v11.7.0
|
v12.1.0
|
||||||
|
99
CHANGELOG.md
99
CHANGELOG.md
@ -5,6 +5,37 @@ If you encounter any problems with updating, please try the following:
|
|||||||
1. `npm run clean` or `npm run cleanall`
|
1. `npm run clean` or `npm run cleanall`
|
||||||
2. Retry update (Don't forget `npm i`)
|
2. Retry update (Don't forget `npm i`)
|
||||||
|
|
||||||
|
Migration
|
||||||
|
------------------------------
|
||||||
|
#### 1
|
||||||
|
`ormconfig.json`という名前で、Misskeyのインストール場所(package.jsonとかがあるディレクトリ)に新たなファイルを作る。中身は次のようにします:
|
||||||
|
``` json
|
||||||
|
{
|
||||||
|
"type": "postgres",
|
||||||
|
"host": "PostgreSQLのホスト",
|
||||||
|
"port": 5432,
|
||||||
|
"username": "PostgreSQLのユーザー名",
|
||||||
|
"password": "PostgreSQLのパスワード",
|
||||||
|
"database": "PostgreSQLのデータベース名",
|
||||||
|
"entities": ["src/models/entities/*.ts"],
|
||||||
|
"migrations": ["migration/*.ts"],
|
||||||
|
"cli": {
|
||||||
|
"migrationsDir": "migration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
上記の各種PostgreSQLの設定(ポートも)は、設定ファイルに書いてあるものをコピーしてください。
|
||||||
|
|
||||||
|
#### 2
|
||||||
|
```
|
||||||
|
npm i -g ts-node
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3
|
||||||
|
```
|
||||||
|
ts-node ./node_modules/typeorm/cli.js migration:run
|
||||||
|
```
|
||||||
|
|
||||||
How to migrate to v11 from v10
|
How to migrate to v11 from v10
|
||||||
------------------------------
|
------------------------------
|
||||||
### 移行の注意点
|
### 移行の注意点
|
||||||
@ -42,6 +73,43 @@ mongodb:
|
|||||||
8. master ブランチに戻す
|
8. master ブランチに戻す
|
||||||
9. enjoy
|
9. enjoy
|
||||||
|
|
||||||
|
11.11.0 (2019/05/05)
|
||||||
|
--------------------
|
||||||
|
### Improvements
|
||||||
|
* MisskeyPagesにリストから選択関数を追加
|
||||||
|
* MisskeyPagesに確率を指定できるテキストランダム選択関数を追加
|
||||||
|
* 外部サービス連携ログインリンクにアイコン追加
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* MisskeyPagesでifを入れ子にできなくなっていた問題を修正
|
||||||
|
* MisskeyPagesで数値入力を作成するとテキスト入力になる問題を修正
|
||||||
|
* 外部サービス連携に関する問題を修正
|
||||||
|
|
||||||
|
11.10.1 (2019/05/04)
|
||||||
|
--------------------
|
||||||
|
### Fixes
|
||||||
|
* MisskeyPagesでページブロックを削除できなくなっていた問題を修正
|
||||||
|
|
||||||
|
### その他
|
||||||
|
* Node.js v12対応
|
||||||
|
|
||||||
|
11.10.0 (2019/05/03)
|
||||||
|
--------------------
|
||||||
|
### 注意
|
||||||
|
このアップデートを適用した後、プロセスを起動(もしくは再起動)する前に[マイグレーション](#migration)の手順を実行してください
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
* MisskeyPagesに割った余りを求める関数を追加
|
||||||
|
* Mastodon v2.8.0 のフォローリストをインポートできるように
|
||||||
|
* エクスポートリクエストに失敗したらエラーを表示するように
|
||||||
|
* エクスポートファイルでは同一ハッシュチェックをしないように
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* 2段階認証を設定するとログインできなくなる問題を修正
|
||||||
|
* ファイルをアップロードできないことがある問題を修正
|
||||||
|
* リモートファイルをキャッシュしない設定だとサムネイル時にオリジナル画像が表示されない問題を修正
|
||||||
|
* 外部サービス連携の不具合を修正
|
||||||
|
|
||||||
11.9.0 (2019/05/02)
|
11.9.0 (2019/05/02)
|
||||||
-------------------
|
-------------------
|
||||||
### Improvements
|
### Improvements
|
||||||
@ -104,36 +172,7 @@ mongodb:
|
|||||||
11.5.0 (2019/04/29)
|
11.5.0 (2019/04/29)
|
||||||
-------------------
|
-------------------
|
||||||
### 注意
|
### 注意
|
||||||
このアップデートを適用した後、プロセスを起動(もしくは再起動)する前にまず以下の手順を実行してください
|
このアップデートを適用した後、プロセスを起動(もしくは再起動)する前に[マイグレーション](migration)の手順を実行してください
|
||||||
|
|
||||||
#### 1
|
|
||||||
`ormconfig.json`という名前で、Misskeyのインストール場所(package.jsonとかがあるディレクトリ)に新たなファイルを作る。中身は次のようにします:
|
|
||||||
``` json
|
|
||||||
{
|
|
||||||
"type": "postgres",
|
|
||||||
"host": "PostgreSQLのホスト",
|
|
||||||
"port": 5432,
|
|
||||||
"username": "PostgreSQLのユーザー名",
|
|
||||||
"password": "PostgreSQLのパスワード",
|
|
||||||
"database": "PostgreSQLのデータベース名",
|
|
||||||
"entities": ["src/models/entities/*.ts"],
|
|
||||||
"migrations": ["migration/*.ts"],
|
|
||||||
"cli": {
|
|
||||||
"migrationsDir": "migration"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
上記の各種PostgreSQLの設定(ポートも)は、設定ファイルに書いてあるものをコピーしてください。
|
|
||||||
|
|
||||||
#### 2
|
|
||||||
```
|
|
||||||
npm i -g ts-node
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3
|
|
||||||
```
|
|
||||||
ts-node ./node_modules/typeorm/cli.js migration:run
|
|
||||||
```
|
|
||||||
|
|
||||||
### New features
|
### New features
|
||||||
#### MisskeyPages
|
#### MisskeyPages
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM node:11-alpine AS base
|
FROM node:12.1-alpine AS base
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
12
README.md
12
README.md
@ -118,10 +118,10 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table><tr>
|
<table><tr>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1.png?token-time=2145916800&token-hash=FMV7cPKBD1TU2WTbl1jg6AcdKSvTb2BSFcDhgc-EO8w%3D" alt="gutfuckllc" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1.png?token-time=2145916800&token-hash=FMV7cPKBD1TU2WTbl1jg6AcdKSvTb2BSFcDhgc-EO8w%3D" alt="gutfuckllc" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1.png?token-time=2145916800&token-hash=9nEQje_eMvUjq9a7L3uBqW-MQbS-rRMaMgd7UYVoFNM%3D" alt="mydarkstar" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1.png?token-time=2145916800&token-hash=9nEQje_eMvUjq9a7L3uBqW-MQbS-rRMaMgd7UYVoFNM%3D" alt="mydarkstar" width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/12718187" alt="Peter G." width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/12718187" alt="Peter G." width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/18833336" alt="itiradi" width="100"></td>
|
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1.jpe?token-time=2145916800&token-hash=UQRWf01TwHDV4Cls1K0YAOAjM29ssif7hLVq0ESQ0hs%3D" alt="nemu" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1.jpe?token-time=2145916800&token-hash=UQRWf01TwHDV4Cls1K0YAOAjM29ssif7hLVq0ESQ0hs%3D" alt="nemu" width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin" width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
||||||
@ -129,10 +129,10 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
|
<td><a href="https://www.patreon.com/Yuzulia">YuzuRyo61</a></td>
|
||||||
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
||||||
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td>
|
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</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=12718187">Peter G.</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=18833336">itiradi</a></td>
|
|
||||||
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin</a></td>
|
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin</a></td>
|
||||||
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
||||||
@ -146,28 +146,30 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/83884b38afc74d4cbe83c30a13b10edd/1.png?token-time=2145916800&token-hash=R5Tog8RWg0rguRoCIoir3lThokrdPvs8Utfikhc0nhY%3D" alt="Atsuko Tominaga" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/83884b38afc74d4cbe83c30a13b10edd/1.png?token-time=2145916800&token-hash=R5Tog8RWg0rguRoCIoir3lThokrdPvs8Utfikhc0nhY%3D" alt="Atsuko Tominaga" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1.jpe?token-time=2145916800&token-hash=EWxXhVbZYH7KB4IDT3joc8TbIg8zPO40x1r5IDn3R7c%3D" alt="Hiratake" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1.jpe?token-time=2145916800&token-hash=EWxXhVbZYH7KB4IDT3joc8TbIg8zPO40x1r5IDn3R7c%3D" alt="Hiratake" width="100"></td>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/2384390/5681180e1efb46a8b28e0e8d4c8b9037/1.jpg?token-time=2145916800&token-hash=SJcMy-Q1BcS940-LFUVOMfR7-5SgrzsEQGhYb3yowFk%3D" alt="CG" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1.jpeg?token-time=2145916800&token-hash=d8jBQLMOHD87KtXs5C9fk1o58DMF73pQ-dYH3uZJPBE%3D" alt="Gargron" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1.jpeg?token-time=2145916800&token-hash=d8jBQLMOHD87KtXs5C9fk1o58DMF73pQ-dYH3uZJPBE%3D" alt="Gargron" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
|
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><a href="https://www.patreon.com/takimura">takimura</a></td>
|
<td><a href="https://www.patreon.com/takimura">takimura</a></td>
|
||||||
<td><a href="https://www.patreon.com/damillora">Damillora</a></td>
|
<td><a href="https://www.patreon.com/damillora">Damillora</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=16900731">Atsuko Tominaga</a></td>
|
<td><a href="https://www.patreon.com/user?u=16900731">Atsuko Tominaga</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
|
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
|
||||||
<td><a href="https://www.patreon.com/hiratake">Hiratake</a></td>
|
<td><a href="https://www.patreon.com/hiratake">Hiratake</a></td>
|
||||||
|
<td><a href="https://www.patreon.com/Corset">CG</a></td>
|
||||||
<td><a href="https://www.patreon.com/hekovic">Hekovic</a></td>
|
<td><a href="https://www.patreon.com/hekovic">Hekovic</a></td>
|
||||||
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
|
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
|
||||||
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
|
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
|
||||||
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
|
|
||||||
</tr></table>
|
</tr></table>
|
||||||
<table><tr>
|
<table><tr>
|
||||||
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
|
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
|
|
||||||
**Last updated:** Wed, 24 Apr 2019 05:56:07 UTC
|
**Last updated:** Fri, 03 May 2019 05:33:07 UTC
|
||||||
<!-- PATREON_END -->
|
<!-- PATREON_END -->
|
||||||
|
|
||||||
:four_leaf_clover: Copyright
|
:four_leaf_clover: Copyright
|
||||||
|
@ -1865,8 +1865,8 @@ pages:
|
|||||||
font: "フォント"
|
font: "フォント"
|
||||||
fontSerif: "セリフ"
|
fontSerif: "セリフ"
|
||||||
fontSansSerif: "サンセリフ"
|
fontSansSerif: "サンセリフ"
|
||||||
set-eye-catchig-image: "アイキャッチ画像を設定"
|
set-eye-catching-image: "アイキャッチ画像を設定"
|
||||||
remove-eye-catchig-image: "アイキャッチ画像を削除"
|
remove-eye-catching-image: "アイキャッチ画像を削除"
|
||||||
choose-block: "ブロックを追加"
|
choose-block: "ブロックを追加"
|
||||||
select-type: "種類を選択"
|
select-type: "種類を選択"
|
||||||
enter-variable-name: "変数名を決めてください"
|
enter-variable-name: "変数名を決めてください"
|
||||||
@ -1941,6 +1941,7 @@ pages:
|
|||||||
fn: "関数"
|
fn: "関数"
|
||||||
text: "テキスト操作"
|
text: "テキスト操作"
|
||||||
convert: "変換"
|
convert: "変換"
|
||||||
|
list: "リスト"
|
||||||
blocks:
|
blocks:
|
||||||
text: "テキスト"
|
text: "テキスト"
|
||||||
multiLineText: "テキスト(複数行)"
|
multiLineText: "テキスト(複数行)"
|
||||||
@ -1982,6 +1983,10 @@ pages:
|
|||||||
_divide:
|
_divide:
|
||||||
arg1: "A"
|
arg1: "A"
|
||||||
arg2: "B"
|
arg2: "B"
|
||||||
|
remind: "÷ 割った余り"
|
||||||
|
_remind:
|
||||||
|
arg1: "A"
|
||||||
|
arg2: "B"
|
||||||
eq: "AとBが同じ"
|
eq: "AとBが同じ"
|
||||||
_eq:
|
_eq:
|
||||||
arg1: "A"
|
arg1: "A"
|
||||||
@ -2055,6 +2060,13 @@ pages:
|
|||||||
_seedRandomPick:
|
_seedRandomPick:
|
||||||
arg1: "シード"
|
arg1: "シード"
|
||||||
arg2: "リスト"
|
arg2: "リスト"
|
||||||
|
DRPWPM: "確率付きリストからランダムに選択 (ユーザーごとに日替わり)"
|
||||||
|
_DRPWPM:
|
||||||
|
arg1: "テキストのリスト"
|
||||||
|
pick: "リストから選択"
|
||||||
|
_pick:
|
||||||
|
arg1: "リスト"
|
||||||
|
arg2: "位置"
|
||||||
number: "数値"
|
number: "数値"
|
||||||
stringToNumber: "テキストを数値に"
|
stringToNumber: "テキストを数値に"
|
||||||
_stringToNumber:
|
_stringToNumber:
|
||||||
|
23
migration/1556746559567-UserProfile.ts
Normal file
23
migration/1556746559567-UserProfile.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||||
|
|
||||||
|
export class UserProfile1556746559567 implements MigrationInterface {
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`UPDATE "user_profile" SET github = FALSE`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "githubId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "githubId" VARCHAR(64)`);
|
||||||
|
await queryRunner.query(`UPDATE "user_profile" SET discord = FALSE`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "discordExpiresDate"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "discordExpiresDate" VARCHAR(64)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<any> {
|
||||||
|
await queryRunner.query(`UPDATE "user_profile" SET github = FALSE`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "githubId"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "githubId" INTEGER`);
|
||||||
|
await queryRunner.query(`UPDATE "user_profile" SET discord = FALSE`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "discordExpiresDate"`);
|
||||||
|
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "discordExpiresDate" INTEGER`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
package.json
28
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "11.9.0",
|
"version": "11.11.0",
|
||||||
"codename": "daybreak",
|
"codename": "daybreak",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -63,8 +63,8 @@
|
|||||||
"@types/lolex": "3.1.1",
|
"@types/lolex": "3.1.1",
|
||||||
"@types/minio": "7.0.1",
|
"@types/minio": "7.0.1",
|
||||||
"@types/mocha": "5.2.6",
|
"@types/mocha": "5.2.6",
|
||||||
"@types/node": "11.13.4",
|
"@types/node": "11.13.8",
|
||||||
"@types/nodemailer": "4.6.7",
|
"@types/nodemailer": "4.6.8",
|
||||||
"@types/nprogress": "0.0.29",
|
"@types/nprogress": "0.0.29",
|
||||||
"@types/oauth": "0.9.1",
|
"@types/oauth": "0.9.1",
|
||||||
"@types/parse5": "5.0.0",
|
"@types/parse5": "5.0.0",
|
||||||
@ -77,7 +77,7 @@
|
|||||||
"@types/redis": "2.8.12",
|
"@types/redis": "2.8.12",
|
||||||
"@types/rename": "1.0.1",
|
"@types/rename": "1.0.1",
|
||||||
"@types/request": "2.48.1",
|
"@types/request": "2.48.1",
|
||||||
"@types/request-promise-native": "1.0.15",
|
"@types/request-promise-native": "1.0.16",
|
||||||
"@types/request-stats": "3.0.0",
|
"@types/request-stats": "3.0.0",
|
||||||
"@types/rimraf": "2.0.2",
|
"@types/rimraf": "2.0.2",
|
||||||
"@types/seedrandom": "2.4.28",
|
"@types/seedrandom": "2.4.28",
|
||||||
@ -89,7 +89,7 @@
|
|||||||
"@types/tmp": "0.1.0",
|
"@types/tmp": "0.1.0",
|
||||||
"@types/uuid": "3.4.4",
|
"@types/uuid": "3.4.4",
|
||||||
"@types/web-push": "3.3.0",
|
"@types/web-push": "3.3.0",
|
||||||
"@types/webpack": "4.4.27",
|
"@types/webpack": "4.4.29",
|
||||||
"@types/webpack-stream": "3.2.10",
|
"@types/webpack-stream": "3.2.10",
|
||||||
"@types/websocket": "0.0.40",
|
"@types/websocket": "0.0.40",
|
||||||
"@types/ws": "6.0.1",
|
"@types/ws": "6.0.1",
|
||||||
@ -112,12 +112,12 @@
|
|||||||
"cssnano": "4.1.10",
|
"cssnano": "4.1.10",
|
||||||
"dateformat": "3.0.3",
|
"dateformat": "3.0.3",
|
||||||
"deep-equal": "1.0.1",
|
"deep-equal": "1.0.1",
|
||||||
"diskusage": "1.1.0",
|
"diskusage": "1.1.1",
|
||||||
"double-ended-queue": "2.1.0-0",
|
"double-ended-queue": "2.1.0-0",
|
||||||
"emojilib": "2.4.0",
|
"emojilib": "2.4.0",
|
||||||
"eslint": "5.16.0",
|
"eslint": "5.16.0",
|
||||||
"eslint-plugin-vue": "5.2.2",
|
"eslint-plugin-vue": "5.2.2",
|
||||||
"eventemitter3": "3.1.0",
|
"eventemitter3": "3.1.2",
|
||||||
"feed": "2.0.4",
|
"feed": "2.0.4",
|
||||||
"file-type": "10.11.0",
|
"file-type": "10.11.0",
|
||||||
"fuckadblock": "3.2.1",
|
"fuckadblock": "3.2.1",
|
||||||
@ -160,13 +160,13 @@
|
|||||||
"loader-utils": "1.2.3",
|
"loader-utils": "1.2.3",
|
||||||
"lolex": "3.1.0",
|
"lolex": "3.1.0",
|
||||||
"lookup-dns-cache": "2.1.0",
|
"lookup-dns-cache": "2.1.0",
|
||||||
"minio": "7.0.7",
|
"minio": "7.0.8",
|
||||||
"mocha": "6.1.3",
|
"mocha": "6.1.4",
|
||||||
"moji": "0.5.1",
|
"moji": "0.5.1",
|
||||||
"moment": "2.24.0",
|
"moment": "2.24.0",
|
||||||
"ms": "2.1.1",
|
"ms": "2.1.1",
|
||||||
"nested-property": "0.0.7",
|
"nested-property": "0.0.7",
|
||||||
"node-fetch": "2.3.0",
|
"node-fetch": "2.5.0",
|
||||||
"nodemailer": "6.1.1",
|
"nodemailer": "6.1.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"object-assign-deep": "0.4.0",
|
"object-assign-deep": "0.4.0",
|
||||||
@ -234,8 +234,8 @@
|
|||||||
"vue-color": "2.7.0",
|
"vue-color": "2.7.0",
|
||||||
"vue-content-loading": "1.6.0",
|
"vue-content-loading": "1.6.0",
|
||||||
"vue-cropperjs": "3.0.0",
|
"vue-cropperjs": "3.0.0",
|
||||||
"vue-i18n": "8.11.1",
|
"vue-i18n": "8.11.2",
|
||||||
"vue-js-modal": "1.3.28",
|
"vue-js-modal": "1.3.31",
|
||||||
"vue-json-pretty": "1.6.0",
|
"vue-json-pretty": "1.6.0",
|
||||||
"vue-loader": "15.7.0",
|
"vue-loader": "15.7.0",
|
||||||
"vue-marquee-text-component": "1.1.1",
|
"vue-marquee-text-component": "1.1.1",
|
||||||
@ -251,9 +251,9 @@
|
|||||||
"vuex-persistedstate": "2.5.4",
|
"vuex-persistedstate": "2.5.4",
|
||||||
"web-push": "3.3.3",
|
"web-push": "3.3.3",
|
||||||
"webpack": "4.30.0",
|
"webpack": "4.30.0",
|
||||||
"webpack-cli": "3.3.0",
|
"webpack-cli": "3.3.1",
|
||||||
"websocket": "1.0.28",
|
"websocket": "1.0.28",
|
||||||
"ws": "6.2.1",
|
"ws": "7.0.0",
|
||||||
"xev": "2.0.1"
|
"xev": "2.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ body
|
|||||||
.peg
|
.peg
|
||||||
display block
|
display block
|
||||||
position absolute
|
position absolute
|
||||||
right 0px
|
right 0
|
||||||
width 100px
|
width 100px
|
||||||
height 100%
|
height 100%
|
||||||
box-shadow 0 0 10px var(--primary), 0 0 5px var(--primary)
|
box-shadow 0 0 10px var(--primary), 0 0 5px var(--primary)
|
||||||
|
@ -98,7 +98,7 @@ export default Vue.extend({
|
|||||||
margin 0 auto
|
margin 0 auto
|
||||||
text-align center
|
text-align center
|
||||||
background #fff
|
background #fff
|
||||||
box-shadow 0px 4px 16px rgba(#000, 0.2)
|
box-shadow 0 4px 16px rgba(#000, 0.2)
|
||||||
|
|
||||||
> .fetching
|
> .fetching
|
||||||
margin 0
|
margin 0
|
||||||
|
@ -52,7 +52,7 @@ function match(e: KeyboardEvent, patterns: action['patterns']): boolean {
|
|||||||
pattern.ctrl == e.ctrlKey &&
|
pattern.ctrl == e.ctrlKey &&
|
||||||
pattern.shift == e.shiftKey &&
|
pattern.shift == e.shiftKey &&
|
||||||
pattern.alt == e.altKey &&
|
pattern.alt == e.altKey &&
|
||||||
e.metaKey == false
|
!e.metaKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,9 @@ export default function(me, settings, note) {
|
|||||||
return (
|
return (
|
||||||
(!isMyNote && note.reply && includesMutedWords(note.reply.text)) ||
|
(!isMyNote && note.reply && includesMutedWords(note.reply.text)) ||
|
||||||
(!isMyNote && note.renote && includesMutedWords(note.renote.text)) ||
|
(!isMyNote && note.renote && includesMutedWords(note.renote.text)) ||
|
||||||
(settings.showMyRenotes === false && isMyNote && isPureRenote) ||
|
(!settings.showMyRenotes && isMyNote && isPureRenote) ||
|
||||||
(settings.showRenotedMyNotes === false && isPureRenote && note.renote.userId == me.id) ||
|
(!settings.showRenotedMyNotes && isPureRenote && note.renote.userId == me.id) ||
|
||||||
(settings.showLocalRenotes === false && isPureRenote && note.renote.user.host == null) ||
|
(!settings.showLocalRenotes && isPureRenote && note.renote.user.host == null) ||
|
||||||
(!isMyNote && includesMutedWords(note.text))
|
(!isMyNote && includesMutedWords(note.text))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
ms(): number {
|
ms(): number {
|
||||||
return this.now.getMilliseconds() * this.smooth;
|
return this.now.getMilliseconds() * this.smooth;
|
||||||
}
|
},
|
||||||
s(): number {
|
s(): number {
|
||||||
return this.now.getSeconds();
|
return this.now.getSeconds();
|
||||||
},
|
},
|
||||||
|
@ -202,7 +202,7 @@ export default Vue.extend({
|
|||||||
left 0
|
left 0
|
||||||
z-index 1
|
z-index 1
|
||||||
width 100%
|
width 100%
|
||||||
box-shadow 0 0px 2px rgba(#000, 0.2)
|
box-shadow 0 0 2px rgba(#000, 0.2)
|
||||||
|
|
||||||
> .form
|
> .form
|
||||||
background rgba(0, 0, 0, 0.02)
|
background rgba(0, 0, 0, 0.02)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-draggable tag="div" :list="blocks" handle=".drag-handle" :group="{ name: 'blocks' }" animation="150">
|
<x-draggable tag="div" :list="blocks" handle=".drag-handle" :group="{ name: 'blocks' }" animation="150" swap-threshold="0.5">
|
||||||
<component v-for="block in blocks" :is="'x-' + block.type" :value="block" @input="updateItem" @remove="removeItem" :key="block.id" :ai-script="aiScript"/>
|
<component v-for="block in blocks" :is="'x-' + block.type" :value="block" @input="updateItem" @remove="() => removeItem(block)" :key="block.id" :ai-script="aiScript"/>
|
||||||
</x-draggable>
|
</x-draggable>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ import XImage from './els/page-editor.el.image.vue';
|
|||||||
import XButton from './els/page-editor.el.button.vue';
|
import XButton from './els/page-editor.el.button.vue';
|
||||||
import XTextInput from './els/page-editor.el.text-input.vue';
|
import XTextInput from './els/page-editor.el.text-input.vue';
|
||||||
import XTextareaInput from './els/page-editor.el.textarea-input.vue';
|
import XTextareaInput from './els/page-editor.el.textarea-input.vue';
|
||||||
import XNumberInput from './els/page-editor.el.text-input.vue';
|
import XNumberInput from './els/page-editor.el.number-input.vue';
|
||||||
import XSwitch from './els/page-editor.el.switch.vue';
|
import XSwitch from './els/page-editor.el.switch.vue';
|
||||||
import XIf from './els/page-editor.el.if.vue';
|
import XIf from './els/page-editor.el.if.vue';
|
||||||
import XPost from './els/page-editor.el.post.vue';
|
import XPost from './els/page-editor.el.post.vue';
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="cpjygsrt" :class="{ error: error != null, warn: warn != null, draggable }">
|
<div class="cpjygsrt" :class="{ error: error != null, warn: warn != null }">
|
||||||
<header class="drag-handle">
|
<header>
|
||||||
<div class="title"><slot name="header"></slot></div>
|
<div class="title"><slot name="header"></slot></div>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<slot name="func"></slot>
|
<slot name="func"></slot>
|
||||||
<button v-if="removable" @click="remove()">
|
<button v-if="removable" @click="remove()">
|
||||||
<fa :icon="faTrashAlt"/>
|
<fa :icon="faTrashAlt"/>
|
||||||
</button>
|
</button>
|
||||||
|
<button v-if="draggable" class="drag-handle">
|
||||||
|
<fa :icon="faBars"/>
|
||||||
|
</button>
|
||||||
<button @click="toggleContent(!showBody)">
|
<button @click="toggleContent(!showBody)">
|
||||||
<template v-if="showBody"><fa icon="angle-up"/></template>
|
<template v-if="showBody"><fa icon="angle-up"/></template>
|
||||||
<template v-else><fa icon="angle-down"/></template>
|
<template v-else><fa icon="angle-down"/></template>
|
||||||
@ -23,6 +26,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import { faBars } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../../i18n';
|
||||||
|
|
||||||
@ -54,7 +58,7 @@ export default Vue.extend({
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showBody: this.expanded,
|
showBody: this.expanded,
|
||||||
faTrashAlt
|
faTrashAlt, faBars
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -124,8 +128,7 @@ export default Vue.extend({
|
|||||||
&:active
|
&:active
|
||||||
color var(--faceTextButtonActive)
|
color var(--faceTextButtonActive)
|
||||||
|
|
||||||
&.draggable
|
.drag-handle
|
||||||
> header
|
|
||||||
cursor move
|
cursor move
|
||||||
|
|
||||||
> .warn
|
> .warn
|
||||||
|
@ -36,10 +36,10 @@
|
|||||||
</ui-select>
|
</ui-select>
|
||||||
|
|
||||||
<div class="eyeCatch">
|
<div class="eyeCatch">
|
||||||
<ui-button v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage()"><fa :icon="faPlus"/> {{ $t('set-eye-catchig-image') }}</ui-button>
|
<ui-button v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage()"><fa :icon="faPlus"/> {{ $t('set-eye-catching-image') }}</ui-button>
|
||||||
<div v-else-if="eyeCatchingImage">
|
<div v-else-if="eyeCatchingImage">
|
||||||
<img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name"/>
|
<img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name"/>
|
||||||
<ui-button @click="removeEyeCatchingImage()" v-if="!readonly"><fa :icon="faTrashAlt"/> {{ $t('remove-eye-catchig-image') }}</ui-button>
|
<ui-button @click="removeEyeCatchingImage()" v-if="!readonly"><fa :icon="faTrashAlt"/> {{ $t('remove-eye-catching-image') }}</ui-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -337,7 +337,7 @@ export default Vue.extend({
|
|||||||
getScriptBlockList(type: string = null) {
|
getScriptBlockList(type: string = null) {
|
||||||
const list = [];
|
const list = [];
|
||||||
|
|
||||||
const blocks = blockDefs.filter(block => type === null || block.out === null || block.out === type);
|
const blocks = blockDefs.filter(block => type === null || block.out === null || block.out === type || typeof block.out === 'number');
|
||||||
|
|
||||||
for (const block of blocks) {
|
for (const block of blocks) {
|
||||||
const category = list.find(x => x.category === block.category);
|
const category = list.find(x => x.category === block.category);
|
||||||
|
@ -54,7 +54,11 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
document.cookie = `i=${this.$store.state.i.token}`;
|
if (!document.cookie.match(/i=(\w+)/)) {
|
||||||
|
document.cookie = `i=${this.$store.state.i.token}; path=/;` +
|
||||||
|
` domain=${document.location.hostname}; max-age=31536000;` +
|
||||||
|
(document.location.protocol.startsWith('https') ? ' secure' : '');
|
||||||
|
}
|
||||||
this.$watch('$store.state.i', () => {
|
this.$watch('$store.state.i', () => {
|
||||||
if (this.$store.state.i.twitter) {
|
if (this.$store.state.i.twitter) {
|
||||||
if (this.twitterForm) this.twitterForm.close();
|
if (this.twitterForm) this.twitterForm.close();
|
||||||
|
@ -290,12 +290,17 @@ export default Vue.extend({
|
|||||||
this.exportTarget == 'mute' ? 'i/export-mute' :
|
this.exportTarget == 'mute' ? 'i/export-mute' :
|
||||||
this.exportTarget == 'blocking' ? 'i/export-blocking' :
|
this.exportTarget == 'blocking' ? 'i/export-blocking' :
|
||||||
this.exportTarget == 'user-lists' ? 'i/export-user-lists' :
|
this.exportTarget == 'user-lists' ? 'i/export-user-lists' :
|
||||||
null, {});
|
null, {}).then(() => {
|
||||||
|
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
text: this.$t('export-requested')
|
text: this.$t('export-requested')
|
||||||
});
|
});
|
||||||
|
}).catch((e: any) => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e.message
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
doImport() {
|
doImport() {
|
||||||
|
@ -273,7 +273,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
import_() {
|
import_() {
|
||||||
(this.$refs.file as any).click();
|
(this.$refs.file as any).click();
|
||||||
}
|
},
|
||||||
|
|
||||||
export_() {
|
export_() {
|
||||||
const blob = new Blob([this.selectedThemeCode], {
|
const blob = new Blob([this.selectedThemeCode], {
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
<template #prefix><fa icon="gavel"/></template>
|
<template #prefix><fa icon="gavel"/></template>
|
||||||
</ui-input>
|
</ui-input>
|
||||||
<ui-button type="submit" :disabled="signing">{{ signing ? $t('signing-in') : $t('@.signin') }}</ui-button>
|
<ui-button type="submit" :disabled="signing">{{ signing ? $t('signing-in') : $t('@.signin') }}</ui-button>
|
||||||
<p v-if="meta && meta.enableTwitterIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/twitter`">{{ $t('signin-with-twitter') }}</a></p>
|
<p v-if="meta && meta.enableTwitterIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/twitter`"><fa :icon="['fab', 'twitter']"/> {{ $t('signin-with-twitter') }}</a></p>
|
||||||
<p v-if="meta && meta.enableGithubIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/github`">{{ $t('signin-with-github') }}</a></p>
|
<p v-if="meta && meta.enableGithubIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/github`"><fa :icon="['fab', 'github']"/> {{ $t('signin-with-github') }}</a></p>
|
||||||
<p v-if="meta && meta.enableDiscordIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`">{{ $t('signin-with-discord') /* TODO: Make these layouts better */ }}</a></p>
|
<p v-if="meta && meta.enableDiscordIntegration" style="margin: 8px 0;"><a :href="`${apiUrl}/signin/discord`"><fa :icon="['fab', 'discord']"/> {{ $t('signin-with-discord') /* TODO: Make these layouts better */ }}</a></p>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ root(fill)
|
|||||||
|
|
||||||
> .value
|
> .value
|
||||||
display block
|
display block
|
||||||
width 0%
|
width 0
|
||||||
height 100%
|
height 100%
|
||||||
background transparent
|
background transparent
|
||||||
border-radius 6px
|
border-radius 6px
|
||||||
|
@ -166,7 +166,7 @@ export default Vue.extend({
|
|||||||
> .follow-button
|
> .follow-button
|
||||||
position absolute
|
position absolute
|
||||||
top 8px
|
top 8px
|
||||||
right 0px
|
right 0
|
||||||
|
|
||||||
> .more
|
> .more
|
||||||
display block
|
display block
|
||||||
|
@ -160,7 +160,7 @@ export default Vue.extend({
|
|||||||
this.$emit('top');
|
this.$emit('top');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$store.state.settings.fetchOnScroll !== false) {
|
if (this.$store.state.settings.fetchOnScroll) {
|
||||||
const current = this.$refs.body.scrollTop + this.$refs.body.clientHeight;
|
const current = this.$refs.body.scrollTop + this.$refs.body.clientHeight;
|
||||||
if (current > this.$refs.body.scrollHeight - 1) this.$emit('bottom');
|
if (current > this.$refs.body.scrollHeight - 1) this.$emit('bottom');
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ export default Vue.extend({
|
|||||||
top -32px
|
top -32px
|
||||||
left 0
|
left 0
|
||||||
right 0
|
right 0
|
||||||
width 0px
|
width 0
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
border-top solid 16px transparent
|
border-top solid 16px transparent
|
||||||
border-left solid 16px transparent
|
border-left solid 16px transparent
|
||||||
|
@ -102,7 +102,7 @@ class Autocomplete {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isHashtag && opened == false) {
|
if (isHashtag && !opened) {
|
||||||
const hashtag = text.substr(hashtagIndex + 1);
|
const hashtag = text.substr(hashtagIndex + 1);
|
||||||
if (!hashtag.includes(' ')) {
|
if (!hashtag.includes(' ')) {
|
||||||
this.open('hashtag', hashtag);
|
this.open('hashtag', hashtag);
|
||||||
@ -110,7 +110,7 @@ class Autocomplete {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEmoji && opened == false) {
|
if (isEmoji && !opened) {
|
||||||
const emoji = text.substr(emojiIndex + 1);
|
const emoji = text.substr(emojiIndex + 1);
|
||||||
if (!emoji.includes(' ')) {
|
if (!emoji.includes(' ')) {
|
||||||
this.open('emoji', emoji);
|
this.open('emoji', emoji);
|
||||||
|
@ -47,7 +47,7 @@ class Script {
|
|||||||
|
|
||||||
public interpolate(str: string) {
|
public interpolate(str: string) {
|
||||||
if (str == null) return null;
|
if (str == null) return null;
|
||||||
return str.replace(/\{(.+?)\}/g, match => {
|
return str.replace(/{(.+?)}/g, match => {
|
||||||
const v = this.vars[match.slice(1, -1).trim()];
|
const v = this.vars[match.slice(1, -1).trim()];
|
||||||
return v == null ? 'NULL' : v.toString();
|
return v == null ? 'NULL' : v.toString();
|
||||||
});
|
});
|
||||||
|
@ -750,12 +750,17 @@ export default Vue.extend({
|
|||||||
bottom 0
|
bottom 0
|
||||||
animation-delay -1.0s
|
animation-delay -1.0s
|
||||||
|
|
||||||
@keyframes sk-rotate { 100% { transform: rotate(360deg); }}
|
@keyframes sk-rotate {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes sk-bounce {
|
@keyframes sk-bounce {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
transform: scale(0.0);
|
transform: scale(0.0);
|
||||||
} 50% {
|
}
|
||||||
|
50% {
|
||||||
transform: scale(1.0);
|
transform: scale(1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ export default Vue.extend({
|
|||||||
this.releaseQueue();
|
this.releaseQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$store.state.settings.fetchOnScroll !== false) {
|
if (this.$store.state.settings.fetchOnScroll) {
|
||||||
const current = window.scrollY + window.innerHeight;
|
const current = window.scrollY + window.innerHeight;
|
||||||
if (current > document.body.offsetHeight - 8) this.fetchMore();
|
if (current > document.body.offsetHeight - 8) this.fetchMore();
|
||||||
}
|
}
|
||||||
|
@ -377,7 +377,7 @@ export default Vue.extend({
|
|||||||
}, err => {
|
}, err => {
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: this.$t('error')
|
title: this.$t('error'),
|
||||||
text: err.message
|
text: err.message
|
||||||
});
|
});
|
||||||
}, {
|
}, {
|
||||||
|
@ -480,7 +480,7 @@ export default Vue.extend({
|
|||||||
&:focus
|
&:focus
|
||||||
&:not([data-is-modal])
|
&:not([data-is-modal])
|
||||||
> .body
|
> .body
|
||||||
box-shadow 0 0 0px 1px var(--primaryAlpha05), 0 2px 12px 0 var(--desktopWindowShadow)
|
box-shadow 0 0 0 1px var(--primaryAlpha05), 0 2px 12px 0 var(--desktopWindowShadow)
|
||||||
|
|
||||||
> .handle
|
> .handle
|
||||||
$size = 8px
|
$size = 8px
|
||||||
|
@ -352,7 +352,7 @@ export default Vue.extend({
|
|||||||
padding 0 16px
|
padding 0 16px
|
||||||
line-height 48px
|
line-height 48px
|
||||||
background var(--faceHeader)
|
background var(--faceHeader)
|
||||||
box-shadow 0 1px 0px rgba(0, 0, 0, 0.1)
|
box-shadow 0 1px 0 rgba(0, 0, 0, 0.1)
|
||||||
|
|
||||||
& + div
|
& + div
|
||||||
max-height calc(100% - 48px)
|
max-height calc(100% - 48px)
|
||||||
|
@ -173,9 +173,10 @@ export default class MiOS extends EventEmitter {
|
|||||||
|
|
||||||
// Init service worker
|
// Init service worker
|
||||||
if (this.shouldRegisterSw) {
|
if (this.shouldRegisterSw) {
|
||||||
this.getMeta().then(data => {
|
// #4813
|
||||||
this.registerSw(data.swPublickey);
|
//this.getMeta().then(data => {
|
||||||
});
|
// this.registerSw(data.swPublickey);
|
||||||
|
//});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -504,7 +505,7 @@ class WindowSystem extends EventEmitter {
|
|||||||
function urlBase64ToUint8Array(base64String: string): Uint8Array {
|
function urlBase64ToUint8Array(base64String: string): Uint8Array {
|
||||||
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
||||||
const base64 = (base64String + padding)
|
const base64 = (base64String + padding)
|
||||||
.replace(/\-/g, '+')
|
.replace(/-/g, '+')
|
||||||
.replace(/_/g, '/');
|
.replace(/_/g, '/');
|
||||||
|
|
||||||
const rawData = window.atob(base64);
|
const rawData = window.atob(base64);
|
||||||
|
@ -83,7 +83,7 @@ export default Vue.extend({
|
|||||||
hierarchyFolders: [],
|
hierarchyFolders: [],
|
||||||
selectedFiles: [],
|
selectedFiles: [],
|
||||||
info: null,
|
info: null,
|
||||||
connection: null
|
connection: null,
|
||||||
|
|
||||||
fetching: true,
|
fetching: true,
|
||||||
fetchingMoreFiles: false,
|
fetchingMoreFiles: false,
|
||||||
@ -385,7 +385,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
createFolder() {
|
createFolder() {
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
title: this.$t('folder-name')
|
title: this.$t('folder-name'),
|
||||||
input: {
|
input: {
|
||||||
default: this.folder.name
|
default: this.folder.name
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ export default Vue.extend({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
title: this.$t('folder-name')
|
title: this.$t('folder-name'),
|
||||||
input: {
|
input: {
|
||||||
default: this.folder.name
|
default: this.folder.name
|
||||||
}
|
}
|
||||||
@ -597,12 +597,17 @@ export default Vue.extend({
|
|||||||
bottom 0
|
bottom 0
|
||||||
animation-delay -1.0s
|
animation-delay -1.0s
|
||||||
|
|
||||||
@keyframes sk-rotate { 100% { transform: rotate(360deg); }}
|
@keyframes sk-rotate {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes sk-bounce {
|
@keyframes sk-bounce {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
transform: scale(0.0);
|
transform: scale(0.0);
|
||||||
} 50% {
|
}
|
||||||
|
50% {
|
||||||
transform: scale(1.0);
|
transform: scale(1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ export default Vue.extend({
|
|||||||
this.releaseQueue();
|
this.releaseQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$store.state.settings.fetchOnScroll !== false) {
|
if (this.$store.state.settings.fetchOnScroll) {
|
||||||
// 親要素が display none だったら弾く
|
// 親要素が display none だったら弾く
|
||||||
// https://github.com/syuilo/misskey/issues/1569
|
// https://github.com/syuilo/misskey/issues/1569
|
||||||
// http://d.hatena.ne.jp/favril/20091105/1257403319
|
// http://d.hatena.ne.jp/favril/20091105/1257403319
|
||||||
|
@ -115,7 +115,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onScroll() {
|
onScroll() {
|
||||||
if (this.$store.state.settings.fetchOnScroll !== false) {
|
if (this.$store.state.settings.fetchOnScroll) {
|
||||||
// 親要素が display none だったら弾く
|
// 親要素が display none だったら弾く
|
||||||
// https://github.com/syuilo/misskey/issues/1569
|
// https://github.com/syuilo/misskey/issues/1569
|
||||||
// http://d.hatena.ne.jp/favril/20091105/1257403319
|
// http://d.hatena.ne.jp/favril/20091105/1257403319
|
||||||
|
@ -295,7 +295,7 @@ export default Vue.extend({
|
|||||||
}, err => {
|
}, err => {
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
title: this.$t('error')
|
title: this.$t('error'),
|
||||||
text: err.message
|
text: err.message
|
||||||
});
|
});
|
||||||
}, {
|
}, {
|
||||||
@ -341,7 +341,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
post() {
|
post() {
|
||||||
this.posting = true;
|
this.posting = true;
|
||||||
const viaMobile = this.$store.state.settings.disableViaMobile !== true;
|
const viaMobile = !this.$store.state.settings.disableViaMobile;
|
||||||
this.$root.api('notes/create', {
|
this.$root.api('notes/create', {
|
||||||
text: this.text == '' ? undefined : this.text,
|
text: this.text == '' ? undefined : this.text,
|
||||||
fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
||||||
|
@ -49,7 +49,7 @@ export default Vue.extend({
|
|||||||
padding 0 8px
|
padding 0 8px
|
||||||
|
|
||||||
&.shadow
|
&.shadow
|
||||||
box-shadow 0 0px 8px rgba(0, 0, 0, 0.25)
|
box-shadow 0 0 8px rgba(0, 0, 0, 0.25)
|
||||||
|
|
||||||
&, *
|
&, *
|
||||||
user-select none
|
user-select none
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
input
|
input
|
||||||
min-width 0px
|
min-width 0
|
||||||
|
|
||||||
input:not([type])
|
input:not([type])
|
||||||
input[type='text']
|
input[type='text']
|
||||||
|
@ -126,7 +126,7 @@ export default (os: MiOS) => new Vuex.Store({
|
|||||||
|
|
||||||
logout(ctx) {
|
logout(ctx) {
|
||||||
ctx.commit('updateI', null);
|
ctx.commit('updateI', null);
|
||||||
document.cookie = 'i=;';
|
document.cookie = `i=; max-age=0; domain=${document.location.hostname}`;
|
||||||
localStorage.removeItem('i');
|
localStorage.removeItem('i');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3,12 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import composeNotification from './common/scripts/compose-notification';
|
import composeNotification from './common/scripts/compose-notification';
|
||||||
import { erase } from '../../prelude/array';
|
|
||||||
|
|
||||||
// キャッシュするリソース
|
|
||||||
const cachee = [
|
|
||||||
'/'
|
|
||||||
];
|
|
||||||
|
|
||||||
// インストールされたとき
|
// インストールされたとき
|
||||||
self.addEventListener('install', ev => {
|
self.addEventListener('install', ev => {
|
||||||
@ -16,31 +10,9 @@ self.addEventListener('install', ev => {
|
|||||||
|
|
||||||
ev.waitUntil(Promise.all([
|
ev.waitUntil(Promise.all([
|
||||||
self.skipWaiting(), // Force activate
|
self.skipWaiting(), // Force activate
|
||||||
caches.open(_VERSION_).then(cache => cache.addAll(cachee)) // Cache
|
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
|
|
||||||
// アクティベートされたとき
|
|
||||||
self.addEventListener('activate', ev => {
|
|
||||||
// Clean up old caches
|
|
||||||
ev.waitUntil(
|
|
||||||
caches.keys().then(keys => Promise.all(
|
|
||||||
erase(_VERSION_, keys)
|
|
||||||
.map(key => caches.delete(key))
|
|
||||||
))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// リクエストが発生したとき
|
|
||||||
self.addEventListener('fetch', ev => {
|
|
||||||
ev.respondWith(
|
|
||||||
// キャッシュがあるか確認してあればそれを返す
|
|
||||||
caches.match(ev.request).then(response =>
|
|
||||||
response || fetch(ev.request)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// プッシュ通知を受け取ったとき
|
// プッシュ通知を受け取ったとき
|
||||||
self.addEventListener('push', ev => {
|
self.addEventListener('push', ev => {
|
||||||
// クライアント取得
|
// クライアント取得
|
||||||
@ -59,11 +31,3 @@ self.addEventListener('push', ev => {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('message', ev => {
|
|
||||||
if (ev.data == 'clear') {
|
|
||||||
caches.keys().then(keys => {
|
|
||||||
for (const key of keys) caches.delete(key);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
@ -129,7 +129,7 @@ export const mfmLanguage = P.createLanguage({
|
|||||||
mention: () => {
|
mention: () => {
|
||||||
return P((input, i) => {
|
return P((input, i) => {
|
||||||
const text = input.substr(i);
|
const text = input.substr(i);
|
||||||
const match = text.match(/^@\w([\w-]*\w)?(?:@[\w\.\-]+\w)?/);
|
const match = text.match(/^@\w([\w-]*\w)?(?:@[\w.\-]+\w)?/);
|
||||||
if (!match) return P.makeFailure(i, 'not a mention');
|
if (!match) return P.makeFailure(i, 'not a mention');
|
||||||
if (input[i - 1] != null && input[i - 1].match(/[a-z0-9]/i)) return P.makeFailure(i, 'not a mention');
|
if (input[i - 1] != null && input[i - 1].match(/[a-z0-9]/i)) return P.makeFailure(i, 'not a mention');
|
||||||
return P.makeSuccess(i + match[0].length, match[0]);
|
return P.makeSuccess(i + match[0].length, match[0]);
|
||||||
@ -141,7 +141,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);
|
||||||
|
@ -36,4 +36,4 @@ export function createTree(type: string, children: MfmForest, props: any): MfmTr
|
|||||||
return T.createTree({ type, props }, children);
|
return T.createTree({ type, props }, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const urlRegex = /^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.,=\+\-]+/;
|
export const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/;
|
||||||
|
@ -64,7 +64,7 @@ export class ASEvaluator {
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
private interpolate(str: string, scope: Scope) {
|
private interpolate(str: string, scope: Scope) {
|
||||||
return str.replace(/\{(.+?)\}/g, match => {
|
return str.replace(/{(.+?)}/g, match => {
|
||||||
const v = scope.getState(match.slice(1, -1).trim());
|
const v = scope.getState(match.slice(1, -1).trim());
|
||||||
return v == null ? 'NULL' : v.toString();
|
return v == null ? 'NULL' : v.toString();
|
||||||
});
|
});
|
||||||
@ -160,6 +160,7 @@ export class ASEvaluator {
|
|||||||
subtract: (a: number, b: number) => a - b,
|
subtract: (a: number, b: number) => a - b,
|
||||||
multiply: (a: number, b: number) => a * b,
|
multiply: (a: number, b: number) => a * b,
|
||||||
divide: (a: number, b: number) => a / b,
|
divide: (a: number, b: number) => a / b,
|
||||||
|
remind: (a: number, b: number) => a % b,
|
||||||
strLen: (a: string) => a.length,
|
strLen: (a: string) => a.length,
|
||||||
strPick: (a: string, b: number) => a[b - 1],
|
strPick: (a: string, b: number) => a[b - 1],
|
||||||
strReplace: (a: string, b: string, c: string) => a.split(b).join(c),
|
strReplace: (a: string, b: string, c: string) => a.split(b).join(c),
|
||||||
@ -168,6 +169,7 @@ export class ASEvaluator {
|
|||||||
stringToNumber: (a: string) => parseInt(a),
|
stringToNumber: (a: string) => parseInt(a),
|
||||||
numberToString: (a: number) => a.toString(),
|
numberToString: (a: number) => a.toString(),
|
||||||
splitStrByLine: (a: string) => a.split('\n'),
|
splitStrByLine: (a: string) => a.split('\n'),
|
||||||
|
pick: (list: any[], i: number) => list[i - 1],
|
||||||
random: (probability: number) => Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * 100) < probability,
|
random: (probability: number) => Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * 100) < probability,
|
||||||
rannum: (min: number, max: number) => min + Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * (max - min + 1)),
|
rannum: (min: number, max: number) => min + Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * (max - min + 1)),
|
||||||
randomPick: (list: any[]) => list[Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * list.length)],
|
randomPick: (list: any[]) => list[Math.floor(seedrandom(`${this.opts.randomSeed}:${block.id}`)() * list.length)],
|
||||||
@ -177,6 +179,27 @@ export class ASEvaluator {
|
|||||||
seedRandom: (seed: any, probability: number) => Math.floor(seedrandom(seed)() * 100) < probability,
|
seedRandom: (seed: any, probability: number) => Math.floor(seedrandom(seed)() * 100) < probability,
|
||||||
seedRannum: (seed: any, min: number, max: number) => min + Math.floor(seedrandom(seed)() * (max - min + 1)),
|
seedRannum: (seed: any, min: number, max: number) => min + Math.floor(seedrandom(seed)() * (max - min + 1)),
|
||||||
seedRandomPick: (seed: any, list: any[]) => list[Math.floor(seedrandom(seed)() * list.length)],
|
seedRandomPick: (seed: any, list: any[]) => list[Math.floor(seedrandom(seed)() * list.length)],
|
||||||
|
DRPWPM: (list: string[]) => {
|
||||||
|
const xs = [];
|
||||||
|
let totalFactor = 0;
|
||||||
|
for (const x of list) {
|
||||||
|
const parts = x.split(' ');
|
||||||
|
const factor = parseInt(parts.pop()!, 10);
|
||||||
|
const text = parts.join(' ');
|
||||||
|
totalFactor += factor;
|
||||||
|
xs.push({ factor, text });
|
||||||
|
}
|
||||||
|
const r = seedrandom(`${day}:${block.id}`)() * totalFactor;
|
||||||
|
let stackedFactor = 0;
|
||||||
|
for (const x of xs) {
|
||||||
|
if (r >= stackedFactor && r <= x.factor) {
|
||||||
|
return x.text;
|
||||||
|
} else {
|
||||||
|
stackedFactor += x.factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xs[0].text;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const fnName = block.type;
|
const fnName = block.type;
|
||||||
|
@ -23,6 +23,7 @@ import {
|
|||||||
faSortNumericUp,
|
faSortNumericUp,
|
||||||
faExchangeAlt,
|
faExchangeAlt,
|
||||||
faRecycle,
|
faRecycle,
|
||||||
|
faIndent,
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faFlag } from '@fortawesome/free-regular-svg-icons';
|
import { faFlag } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
|
|||||||
subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, },
|
subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, },
|
||||||
multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, },
|
multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, },
|
||||||
divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||||
|
remind: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||||
eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, },
|
eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, },
|
||||||
notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, },
|
notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, },
|
||||||
gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, },
|
gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, },
|
||||||
@ -71,6 +73,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
|
|||||||
stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: faExchangeAlt, },
|
stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: faExchangeAlt, },
|
||||||
numberToString: { in: ['number'], out: 'string', category: 'convert', icon: faExchangeAlt, },
|
numberToString: { in: ['number'], out: 'string', category: 'convert', icon: faExchangeAlt, },
|
||||||
splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: faExchangeAlt, },
|
splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: faExchangeAlt, },
|
||||||
|
pick: { in: [null], out: null, category: 'list', icon: faIndent, },
|
||||||
rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
||||||
dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
||||||
seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: faDice, },
|
||||||
@ -80,6 +83,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
|
|||||||
randomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
randomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
||||||
dailyRandomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
dailyRandomPick: { in: [0], out: 0, category: 'random', icon: faDice, },
|
||||||
seedRandomPick: { in: [null, 0], out: 0, category: 'random', icon: faDice, },
|
seedRandomPick: { in: [null, 0], out: 0, category: 'random', icon: faDice, },
|
||||||
|
DRPWPM: { in: ['stringArray'], out: 'string', category: 'random', icon: faDice, }, // dailyRandomPickWithProbabilityMapping
|
||||||
};
|
};
|
||||||
|
|
||||||
export const literalDefs: Record<string, { out: any; category: string; icon: any; }> = {
|
export const literalDefs: Record<string, { out: any; category: string; icon: any; }> = {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { ulid } from 'ulid';
|
import { ulid } from 'ulid';
|
||||||
import { genAid } from './id/aid';
|
import { genAid } from './id/aid';
|
||||||
import { genMeid } from './id/meid';
|
import { genMeid } from './id/meid';
|
||||||
|
import { genMeidg } from './id/meidg';
|
||||||
import { genObjectId } from './id/object-id';
|
import { genObjectId } from './id/object-id';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ export function genId(date?: Date): string {
|
|||||||
switch (metohd) {
|
switch (metohd) {
|
||||||
case 'aid': return genAid(date);
|
case 'aid': return genAid(date);
|
||||||
case 'meid': return genMeid(date);
|
case 'meid': return genMeid(date);
|
||||||
|
case 'meidg': return genMeidg(date);
|
||||||
case 'ulid': return ulid(date.getTime());
|
case 'ulid': return ulid(date.getTime());
|
||||||
case 'objectid': return genObjectId(date);
|
case 'objectid': return genObjectId(date);
|
||||||
default: throw new Error('unknown id generation method');
|
default: throw new Error('unknown id generation method');
|
||||||
|
28
src/misc/id/meidg.ts
Normal file
28
src/misc/id/meidg.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
const CHARS = '0123456789abcdef';
|
||||||
|
|
||||||
|
// 4bit Fixed hex value 'g'
|
||||||
|
// 44bit UNIX Time ms in Hex
|
||||||
|
// 48bit Random value in Hex
|
||||||
|
|
||||||
|
function getTime(time: number) {
|
||||||
|
if (time < 0) time = 0;
|
||||||
|
if (time === 0) {
|
||||||
|
return CHARS[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.toString(16).padStart(11, CHARS[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandom() {
|
||||||
|
let str = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < 12; i++) {
|
||||||
|
str += CHARS[Math.floor(Math.random() * CHARS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function genMeidg(date: Date): string {
|
||||||
|
return 'g' + getTime(date.getTime()) + getRandom();
|
||||||
|
}
|
@ -26,7 +26,7 @@ export class UserProfile {
|
|||||||
public birthday: string | null;
|
public birthday: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 1024, nullable: true,
|
length: 2048, nullable: true,
|
||||||
comment: 'The description (bio) of the User.'
|
comment: 'The description (bio) of the User.'
|
||||||
})
|
})
|
||||||
public description: string | null;
|
public description: string | null;
|
||||||
@ -144,10 +144,10 @@ export class UserProfile {
|
|||||||
})
|
})
|
||||||
public githubAccessToken: string | null;
|
public githubAccessToken: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column('varchar', {
|
||||||
nullable: true, default: null,
|
length: 64, nullable: true, default: null,
|
||||||
})
|
})
|
||||||
public githubId: number | null;
|
public githubId: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 64, nullable: true, default: null,
|
length: 64, nullable: true, default: null,
|
||||||
@ -169,10 +169,10 @@ export class UserProfile {
|
|||||||
})
|
})
|
||||||
public discordRefreshToken: string | null;
|
public discordRefreshToken: string | null;
|
||||||
|
|
||||||
@Column('integer', {
|
@Column('varchar', {
|
||||||
nullable: true, default: null,
|
length: 64, nullable: true, default: null,
|
||||||
})
|
})
|
||||||
public discordExpiresDate: number | null;
|
public discordExpiresDate: string | null;
|
||||||
|
|
||||||
@Column('varchar', {
|
@Column('varchar', {
|
||||||
length: 64, nullable: true, default: null,
|
length: 64, nullable: true, default: null,
|
||||||
|
@ -127,6 +127,20 @@ export class UserRepository extends Repository<User> {
|
|||||||
pinnedNotes: Notes.packMany(pins.map(pin => pin.noteId), meId, {
|
pinnedNotes: Notes.packMany(pins.map(pin => pin.noteId), meId, {
|
||||||
detail: true
|
detail: true
|
||||||
}),
|
}),
|
||||||
|
twoFactorEnabled: profile!.twoFactorEnabled,
|
||||||
|
twitter: profile!.twitter ? {
|
||||||
|
id: profile!.twitterUserId,
|
||||||
|
screenName: profile!.twitterScreenName
|
||||||
|
} : null,
|
||||||
|
github: profile!.github ? {
|
||||||
|
id: profile!.githubId,
|
||||||
|
login: profile!.githubLogin
|
||||||
|
} : null,
|
||||||
|
discord: profile!.discord ? {
|
||||||
|
id: profile!.discordId,
|
||||||
|
username: profile!.discordUsername,
|
||||||
|
discriminator: profile!.discordDiscriminator
|
||||||
|
} : null,
|
||||||
} : {}),
|
} : {}),
|
||||||
|
|
||||||
...(opts.detail && meId === user.id ? {
|
...(opts.detail && meId === user.id ? {
|
||||||
@ -135,7 +149,6 @@ export class UserRepository extends Repository<User> {
|
|||||||
autoWatch: profile!.autoWatch,
|
autoWatch: profile!.autoWatch,
|
||||||
alwaysMarkNsfw: profile!.alwaysMarkNsfw,
|
alwaysMarkNsfw: profile!.alwaysMarkNsfw,
|
||||||
carefulBot: profile!.carefulBot,
|
carefulBot: profile!.carefulBot,
|
||||||
twoFactorEnabled: profile!.twoFactorEnabled,
|
|
||||||
hasUnreadMessagingMessage: MessagingMessages.count({
|
hasUnreadMessagingMessage: MessagingMessages.count({
|
||||||
where: {
|
where: {
|
||||||
recipientId: user.id,
|
recipientId: user.id,
|
||||||
@ -217,7 +230,7 @@ export class UserRepository extends Repository<User> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public isValidBirthday(birthday: string): boolean {
|
public isValidBirthday(birthday: string): boolean {
|
||||||
return typeof birthday == 'string' && /^([0-9]{4})\-([0-9]{2})-([0-9]{2})$/.test(birthday);
|
return typeof birthday == 'string' && /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.test(birthday);
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ export async function exportBlocking(job: Bull.Job, done: any): Promise<void> {
|
|||||||
logger.succ(`Exported to: ${path}`);
|
logger.succ(`Exported to: ${path}`);
|
||||||
|
|
||||||
const fileName = 'blocking-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
const fileName = 'blocking-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
||||||
const driveFile = await addFile(user, path, fileName);
|
const driveFile = await addFile(user, path, fileName, null, null, true);
|
||||||
|
|
||||||
logger.succ(`Exported to: ${driveFile.id}`);
|
logger.succ(`Exported to: ${driveFile.id}`);
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -85,7 +85,7 @@ export async function exportFollowing(job: Bull.Job, done: any): Promise<void> {
|
|||||||
logger.succ(`Exported to: ${path}`);
|
logger.succ(`Exported to: ${path}`);
|
||||||
|
|
||||||
const fileName = 'following-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
const fileName = 'following-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
||||||
const driveFile = await addFile(user, path, fileName);
|
const driveFile = await addFile(user, path, fileName, null, null, true);
|
||||||
|
|
||||||
logger.succ(`Exported to: ${driveFile.id}`);
|
logger.succ(`Exported to: ${driveFile.id}`);
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -85,7 +85,7 @@ export async function exportMute(job: Bull.Job, done: any): Promise<void> {
|
|||||||
logger.succ(`Exported to: ${path}`);
|
logger.succ(`Exported to: ${path}`);
|
||||||
|
|
||||||
const fileName = 'mute-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
const fileName = 'mute-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
||||||
const driveFile = await addFile(user, path, fileName);
|
const driveFile = await addFile(user, path, fileName, null, null, true);
|
||||||
|
|
||||||
logger.succ(`Exported to: ${driveFile.id}`);
|
logger.succ(`Exported to: ${driveFile.id}`);
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -108,7 +108,7 @@ export async function exportNotes(job: Bull.Job, done: any): Promise<void> {
|
|||||||
logger.succ(`Exported to: ${path}`);
|
logger.succ(`Exported to: ${path}`);
|
||||||
|
|
||||||
const fileName = 'notes-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.json';
|
const fileName = 'notes-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.json';
|
||||||
const driveFile = await addFile(user, path, fileName);
|
const driveFile = await addFile(user, path, fileName, null, null, true);
|
||||||
|
|
||||||
logger.succ(`Exported to: ${driveFile.id}`);
|
logger.succ(`Exported to: ${driveFile.id}`);
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -62,7 +62,7 @@ export async function exportUserLists(job: Bull.Job, done: any): Promise<void> {
|
|||||||
logger.succ(`Exported to: ${path}`);
|
logger.succ(`Exported to: ${path}`);
|
||||||
|
|
||||||
const fileName = 'user-lists-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
const fileName = 'user-lists-' + dateFormat(new Date(), 'yyyy-mm-dd-HH-MM-ss') + '.csv';
|
||||||
const driveFile = await addFile(user, path, fileName);
|
const driveFile = await addFile(user, path, fileName, null, null, true);
|
||||||
|
|
||||||
logger.succ(`Exported to: ${driveFile.id}`);
|
logger.succ(`Exported to: ${driveFile.id}`);
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -35,7 +35,8 @@ export async function importFollowing(job: Bull.Job, done: any): Promise<void> {
|
|||||||
linenum++;
|
linenum++;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { username, host } = parseAcct(line.trim());
|
const acct = line.split(',')[0].trim();
|
||||||
|
const { username, host } = parseAcct(acct);
|
||||||
|
|
||||||
let target = isSelfHost(host!) ? await Users.findOne({
|
let target = isSelfHost(host!) ? await Users.findOne({
|
||||||
host: null,
|
host: null,
|
||||||
|
@ -37,7 +37,7 @@ export const meta = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
type: {
|
type: {
|
||||||
validator: $.optional.str.match(/^[a-zA-Z\/\-\*]+$/)
|
validator: $.optional.str.match(/^[a-zA-Z\/\-*]+$/)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ export const meta = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
type: {
|
type: {
|
||||||
validator: $.optional.str.match(/^[a-zA-Z\/\-\*]+$/)
|
validator: $.optional.str.match(/^[a-zA-Z\/\-*]+$/)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ for (const endpoint of endpoints) {
|
|||||||
} else {
|
} else {
|
||||||
if (endpoint.name.includes('-')) {
|
if (endpoint.name.includes('-')) {
|
||||||
// 後方互換性のため
|
// 後方互換性のため
|
||||||
router.post(`/${endpoint.name.replace(/\-/g, '_')}`, handler.bind(null, endpoint));
|
router.post(`/${endpoint.name.replace(/-/g, '_')}`, handler.bind(null, endpoint));
|
||||||
}
|
}
|
||||||
router.post(`/${endpoint.name}`, handler.bind(null, endpoint));
|
router.post(`/${endpoint.name}`, handler.bind(null, endpoint));
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ export function convertSchemaToOpenApiSchema(schema: Schema) {
|
|||||||
const res: any = schema;
|
const res: any = schema;
|
||||||
|
|
||||||
if (schema.type === 'object' && schema.properties) {
|
if (schema.type === 'object' && schema.properties) {
|
||||||
res.required = Object.entries(schema.properties).filter(([k, v]) => v.optional !== true).map(([k]) => k);
|
res.required = Object.entries(schema.properties).filter(([k, v]) => !v.optional).map(([k]) => k);
|
||||||
|
|
||||||
for (const k of Object.keys(schema.properties)) {
|
for (const k of Object.keys(schema.properties)) {
|
||||||
res.properties[k] = convertSchemaToOpenApiSchema(schema.properties[k]);
|
res.properties[k] = convertSchemaToOpenApiSchema(schema.properties[k]);
|
||||||
|
@ -203,12 +203,8 @@ router.get('/dc/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const profile = await UserProfiles.createQueryBuilder()
|
const profile = await UserProfiles.createQueryBuilder()
|
||||||
.where('discord @> :discord', {
|
.where('"discordId" = :id', { id: id })
|
||||||
discord: {
|
.andWhere('"userHost" IS NULL')
|
||||||
id: id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.andWhere('userHost IS NULL')
|
|
||||||
.getOne();
|
.getOne();
|
||||||
|
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
|
@ -193,12 +193,8 @@ router.get('/gh/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const link = await UserProfiles.createQueryBuilder()
|
const link = await UserProfiles.createQueryBuilder()
|
||||||
.where('github @> :github', {
|
.where('"githubId" = :id', { id: id })
|
||||||
github: {
|
.andWhere('"userHost" IS NULL')
|
||||||
id: id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.andWhere('userHost IS NULL')
|
|
||||||
.getOne();
|
.getOne();
|
||||||
|
|
||||||
if (link == null) {
|
if (link == null) {
|
||||||
|
@ -141,12 +141,8 @@ router.get('/tw/cb', async ctx => {
|
|||||||
const result = await twAuth!.done(JSON.parse(twCtx), ctx.query.oauth_verifier);
|
const result = await twAuth!.done(JSON.parse(twCtx), ctx.query.oauth_verifier);
|
||||||
|
|
||||||
const link = await UserProfiles.createQueryBuilder()
|
const link = await UserProfiles.createQueryBuilder()
|
||||||
.where('twitter @> :twitter', {
|
.where('"twitterUserId" = :id', { id: result.userId })
|
||||||
twitter: {
|
.andWhere('"userHost" IS NULL')
|
||||||
userId: result.userId,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.andWhere('userHost IS NULL')
|
|
||||||
.getOne();
|
.getOne();
|
||||||
|
|
||||||
if (link == null) {
|
if (link == null) {
|
||||||
|
@ -393,6 +393,8 @@ export default async function(
|
|||||||
|
|
||||||
if (isLink) {
|
if (isLink) {
|
||||||
file.url = url;
|
file.url = url;
|
||||||
|
file.thumbnailUrl = url;
|
||||||
|
file.webpublicUrl = url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
"radix": false,
|
"radix": false,
|
||||||
"ban-types": [
|
"ban-types": [
|
||||||
true,
|
true,
|
||||||
"Object"
|
["Object", "Use {} instead."]
|
||||||
],
|
],
|
||||||
"ban": [
|
"ban": [
|
||||||
true,
|
true,
|
||||||
|
@ -95,7 +95,7 @@ module.exports = {
|
|||||||
loader: 'css-loader'
|
loader: 'css-loader'
|
||||||
}, postcss]
|
}, postcss]
|
||||||
}, {
|
}, {
|
||||||
test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/,
|
test: /\.(eot|woff|woff2|svg|ttf)([?]?.*)$/,
|
||||||
loader: 'url-loader'
|
loader: 'url-loader'
|
||||||
}, {
|
}, {
|
||||||
test: /\.json5$/,
|
test: /\.json5$/,
|
||||||
|
Reference in New Issue
Block a user