Compare commits
28 Commits
11.0.0-bet
...
11.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
f6f8cdbcf2 | |||
f46f53b8a3 | |||
a2fcae4383 | |||
483f043768 | |||
f8e0f4f21f | |||
9c3613e96d | |||
d9cacdc86d | |||
aa3d2deeaa | |||
e64912545a | |||
b247be80cc | |||
343f2f1f33 | |||
2d590df900 | |||
ba56b2b9fd | |||
bf472b0c5e | |||
f7961f34c5 | |||
e369031a28 | |||
186d7bbfd9 | |||
60a11f8da5 | |||
1181fcdceb | |||
8cb9852058 | |||
53d46d1cbe | |||
275e1c8de9 | |||
d46eca4c87 | |||
2927fb1597 | |||
8c72e011d2 | |||
69662e24c3 | |||
96099ffe98 | |||
ae16b45c11 |
@ -65,9 +65,9 @@ db:
|
|||||||
# ┌─────────────────────┐
|
# ┌─────────────────────┐
|
||||||
#───┘ Redis configuration └─────────────────────────────────────
|
#───┘ Redis configuration └─────────────────────────────────────
|
||||||
|
|
||||||
#redis:
|
redis:
|
||||||
# host: localhost
|
host: localhost
|
||||||
# port: 6379
|
port: 6379
|
||||||
#pass: example-pass
|
#pass: example-pass
|
||||||
|
|
||||||
# ┌─────────────────────────────┐
|
# ┌─────────────────────────────┐
|
||||||
@ -127,28 +127,12 @@ drive:
|
|||||||
# change it according to your preferences.
|
# change it according to your preferences.
|
||||||
|
|
||||||
# Available methods:
|
# Available methods:
|
||||||
# aid1 ... Use AID for ID generation (with random 1 char)
|
# aid ... Short, Millisecond accuracy
|
||||||
# aid2 ... Use AID for ID generation (with random 2 chars)
|
# meid ... Similar to ObjectID, Millisecond accuracy
|
||||||
# aid3 ... Use AID for ID generation (with random 3 chars)
|
# ulid ... Millisecond accuracy
|
||||||
# aid4 ... Use AID for ID generation (with random 4 chars)
|
# objectid ... This is left for backward compatibility
|
||||||
# ulid ... Use ulid for ID generation
|
|
||||||
# objectid ... This is left for backward compatibility.
|
|
||||||
|
|
||||||
# AID(n) is the original ID generation method.
|
id: 'aid'
|
||||||
# The trailing n represents the number of random characters that
|
|
||||||
# will be suffixed.
|
|
||||||
# The larger n is the safer. If n is small, the possibility of
|
|
||||||
# collision at the same time increases, but there are also
|
|
||||||
# advantages such as shortening of the URL.
|
|
||||||
|
|
||||||
# ULID: Universally Unique Lexicographically Sortable Identifier.
|
|
||||||
# for more details: https://github.com/ulid/spec
|
|
||||||
# * Normally, AID should be sufficient.
|
|
||||||
|
|
||||||
# ObjectID is the method used in previous versions of Misskey.
|
|
||||||
# * Choose this if you are migrating from a previous Misskey.
|
|
||||||
|
|
||||||
id: 'aid2'
|
|
||||||
|
|
||||||
# ┌─────────────────────┐
|
# ┌─────────────────────┐
|
||||||
#───┘ Other configuration └─────────────────────────────────────
|
#───┘ Other configuration └─────────────────────────────────────
|
||||||
|
12
CHANGELOG.md
12
CHANGELOG.md
@ -7,7 +7,8 @@ If you encounter any problems with updating, please try the following:
|
|||||||
|
|
||||||
11.0.0
|
11.0.0
|
||||||
----------
|
----------
|
||||||
* データベースがMongoDBからPostgreSQLに変更されました
|
* **データベースがMongoDBからPostgreSQLに変更されました**
|
||||||
|
* **Redisが必須に**
|
||||||
* アカウントを完全に削除できるように
|
* アカウントを完全に削除できるように
|
||||||
* ミュート/ブロック時にそのユーザーの投稿のウォッチをすべて解除するように
|
* ミュート/ブロック時にそのユーザーの投稿のウォッチをすべて解除するように
|
||||||
* フォロー申請数が実際より1すくなくなる問題を修正
|
* フォロー申請数が実際より1すくなくなる問題を修正
|
||||||
@ -19,6 +20,15 @@ If you encounter any problems with updating, please try the following:
|
|||||||
### APIの破壊的変更
|
### APIの破壊的変更
|
||||||
* v10時点で deprecated だったパラメータなどを削除
|
* v10時点で deprecated だったパラメータなどを削除
|
||||||
* ユーザーリストの title が name に
|
* ユーザーリストの title が name に
|
||||||
|
* リバーシの対局の`settings`プロパティがなくなり、その中にあったプロパティがすべて上の階層に
|
||||||
|
* 例えば`game.settings.map`は`game.map`になる
|
||||||
|
|
||||||
|
### 既知の問題
|
||||||
|
* アプリが作成できない
|
||||||
|
* 依存ライブラリの問題と思わるため、対応が難しい
|
||||||
|
|
||||||
|
### Migration
|
||||||
|
coming soon...
|
||||||
|
|
||||||
10.100.0
|
10.100.0
|
||||||
----------
|
----------
|
||||||
|
@ -24,18 +24,13 @@ Please install and setup these softwares:
|
|||||||
#### Dependencies :package:
|
#### Dependencies :package:
|
||||||
* **[Node.js](https://nodejs.org/en/)** >= 11.7.0
|
* **[Node.js](https://nodejs.org/en/)** >= 11.7.0
|
||||||
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
|
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
|
||||||
|
* **[Redis](https://redis.io/)**
|
||||||
|
|
||||||
##### Optional
|
##### Optional
|
||||||
* [Redis](https://redis.io/)
|
|
||||||
* Redis is optional, but we strongly recommended to install it
|
|
||||||
* [Elasticsearch](https://www.elastic.co/) - required to enable the search feature
|
* [Elasticsearch](https://www.elastic.co/) - required to enable the search feature
|
||||||
* [FFmpeg](https://www.ffmpeg.org/)
|
* [FFmpeg](https://www.ffmpeg.org/)
|
||||||
|
|
||||||
*3.* Setup PostgreSQL
|
*3.* Install Misskey
|
||||||
----------------------------------------------------------------
|
|
||||||
:)
|
|
||||||
|
|
||||||
*4.* Install Misskey
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
1. `su - misskey` Connect to misskey user.
|
1. `su - misskey` Connect to misskey user.
|
||||||
2. `git clone -b master git://github.com/syuilo/misskey.git` Clone the misskey repo from master branch.
|
2. `git clone -b master git://github.com/syuilo/misskey.git` Clone the misskey repo from master branch.
|
||||||
@ -43,12 +38,12 @@ Please install and setup these softwares:
|
|||||||
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest)
|
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest)
|
||||||
5. `npm install` Install misskey dependencies.
|
5. `npm install` Install misskey dependencies.
|
||||||
|
|
||||||
*5.* Configure Misskey
|
*4.* Configure Misskey
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
|
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
|
||||||
2. Edit `default.yml`
|
2. Edit `default.yml`
|
||||||
|
|
||||||
*6.* Build Misskey
|
*5.* Build Misskey
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
Build misskey with the following:
|
Build misskey with the following:
|
||||||
@ -64,13 +59,13 @@ If you're still encountering errors about some modules, use node-gyp:
|
|||||||
3. `node-gyp build`
|
3. `node-gyp build`
|
||||||
4. `NODE_ENV=production npm run build`
|
4. `NODE_ENV=production npm run build`
|
||||||
|
|
||||||
*7.* Init DB
|
*6.* Init DB
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
``` shell
|
``` shell
|
||||||
npm run init
|
npm run init
|
||||||
```
|
```
|
||||||
|
|
||||||
*8.* That is it.
|
*7.* That is it.
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
Well done! Now, you have an environment that run to Misskey.
|
Well done! Now, you have an environment that run to Misskey.
|
||||||
|
|
||||||
|
@ -24,18 +24,13 @@ Installez les paquets suivants :
|
|||||||
#### Dépendences :package:
|
#### Dépendences :package:
|
||||||
* **[Node.js](https://nodejs.org/en/)** >= 11.7.0
|
* **[Node.js](https://nodejs.org/en/)** >= 11.7.0
|
||||||
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
|
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
|
||||||
|
* **[Redis](https://redis.io/)**
|
||||||
|
|
||||||
##### Optionnels
|
##### Optionnels
|
||||||
* [Redis](https://redis.io/)
|
|
||||||
* Redis est optionnel mais nous vous recommandons vivement de l'installer
|
|
||||||
* [Elasticsearch](https://www.elastic.co/) - requis pour pouvoir activer la fonctionnalité de recherche
|
* [Elasticsearch](https://www.elastic.co/) - requis pour pouvoir activer la fonctionnalité de recherche
|
||||||
* [FFmpeg](https://www.ffmpeg.org/)
|
* [FFmpeg](https://www.ffmpeg.org/)
|
||||||
|
|
||||||
*3.* Paramètrage de PostgreSQL
|
*3.* Installation de Misskey
|
||||||
----------------------------------------------------------------
|
|
||||||
:)
|
|
||||||
|
|
||||||
*4.* Installation de Misskey
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
1. `su - misskey` Basculez vers l'utilisateur misskey.
|
1. `su - misskey` Basculez vers l'utilisateur misskey.
|
||||||
2. `git clone -b master git://github.com/syuilo/misskey.git` Clonez la branche master du dépôt misskey.
|
2. `git clone -b master git://github.com/syuilo/misskey.git` Clonez la branche master du dépôt misskey.
|
||||||
@ -43,12 +38,12 @@ Installez les paquets suivants :
|
|||||||
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest)
|
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest)
|
||||||
5. `npm install` Installez les dépendances de misskey.
|
5. `npm install` Installez les dépendances de misskey.
|
||||||
|
|
||||||
*5.* Création du fichier de configuration
|
*4.* Création du fichier de configuration
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
1. `cp .config/example.yml .config/default.yml` Copiez le fichier `.config/example.yml` et renommez-le`default.yml`.
|
1. `cp .config/example.yml .config/default.yml` Copiez le fichier `.config/example.yml` et renommez-le`default.yml`.
|
||||||
2. Editez le fichier `default.yml`
|
2. Editez le fichier `default.yml`
|
||||||
|
|
||||||
*6.* Construction de Misskey
|
*5.* Construction de Misskey
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
Construisez Misskey comme ceci :
|
Construisez Misskey comme ceci :
|
||||||
@ -64,7 +59,7 @@ Si vous rencontrez des erreurs concernant certains modules, utilisez node-gyp:
|
|||||||
3. `node-gyp build`
|
3. `node-gyp build`
|
||||||
4. `NODE_ENV=production npm run build`
|
4. `NODE_ENV=production npm run build`
|
||||||
|
|
||||||
*7.* C'est tout.
|
*6.* C'est tout.
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
Excellent ! Maintenant, vous avez un environnement prêt pour lancer Misskey
|
Excellent ! Maintenant, vous avez un environnement prêt pour lancer Misskey
|
||||||
|
|
||||||
|
@ -24,25 +24,14 @@ adduser --disabled-password --disabled-login misskey
|
|||||||
#### 依存関係 :package:
|
#### 依存関係 :package:
|
||||||
* **[Node.js](https://nodejs.org/en/)** (11.7.0以上)
|
* **[Node.js](https://nodejs.org/en/)** (11.7.0以上)
|
||||||
* **[PostgreSQL](https://www.postgresql.org/)** (10以上)
|
* **[PostgreSQL](https://www.postgresql.org/)** (10以上)
|
||||||
|
* **[Redis](https://redis.io/)**
|
||||||
|
|
||||||
##### オプション
|
##### オプション
|
||||||
* [Redis](https://redis.io/)
|
|
||||||
* Redisはオプションですが、インストールすることを強く推奨します。
|
|
||||||
* インストールしなくていいのは、あなたのインスタンスが自分専用のときだけとお考えください。
|
|
||||||
* 具体的には、Redisをインストールしないと、次の事が出来なくなります:
|
|
||||||
* Misskeyプロセスを複数起動しての負荷分散
|
|
||||||
* レートリミット
|
|
||||||
* ジョブキュー
|
|
||||||
* Twitter連携
|
|
||||||
* [Elasticsearch](https://www.elastic.co/)
|
* [Elasticsearch](https://www.elastic.co/)
|
||||||
* 検索機能を有効にするためにはインストールが必要です。
|
* 検索機能を有効にするためにはインストールが必要です。
|
||||||
* [FFmpeg](https://www.ffmpeg.org/)
|
* [FFmpeg](https://www.ffmpeg.org/)
|
||||||
|
|
||||||
*3.* PostgreSQLの設定
|
*3.* Misskeyのインストール
|
||||||
----------------------------------------------------------------
|
|
||||||
:)
|
|
||||||
|
|
||||||
*4.* Misskeyのインストール
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
1. `su - misskey` misskeyユーザーを使用
|
1. `su - misskey` misskeyユーザーを使用
|
||||||
2. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン
|
2. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン
|
||||||
@ -50,12 +39,12 @@ adduser --disabled-password --disabled-login misskey
|
|||||||
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
|
4. `git checkout $(git tag -l | grep -Ev -- '-(rc|alpha)\.[0-9]+$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
|
||||||
5. `npm install` Misskeyの依存パッケージをインストール
|
5. `npm install` Misskeyの依存パッケージをインストール
|
||||||
|
|
||||||
*5.* 設定ファイルを作成する
|
*4.* 設定ファイルを作成する
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする。
|
1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする。
|
||||||
2. `default.yml` を編集する。
|
2. `default.yml` を編集する。
|
||||||
|
|
||||||
*6.* Misskeyのビルド
|
*5.* Misskeyのビルド
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
次のコマンドでMisskeyをビルドしてください:
|
次のコマンドでMisskeyをビルドしてください:
|
||||||
@ -70,13 +59,13 @@ Debianをお使いであれば、`build-essential`パッケージをインスト
|
|||||||
3. `node-gyp build`
|
3. `node-gyp build`
|
||||||
4. `NODE_ENV=production npm run build`
|
4. `NODE_ENV=production npm run build`
|
||||||
|
|
||||||
*7.* データベースを初期化
|
*6.* データベースを初期化
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
``` shell
|
``` shell
|
||||||
npm run init
|
npm run init
|
||||||
```
|
```
|
||||||
|
|
||||||
*8.* 以上です!
|
*7.* 以上です!
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
お疲れ様でした。これでMisskeyを動かす準備は整いました。
|
お疲れ様でした。これでMisskeyを動かす準備は整いました。
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "11.0.0-beta.7",
|
"version": "11.0.0-beta.13",
|
||||||
"codename": "daybreak",
|
"codename": "daybreak",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as redis from 'redis';
|
import * as redis from 'redis';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
|
||||||
export default config.redis ? redis.createClient(
|
export default redis.createClient(
|
||||||
config.redis.port,
|
config.redis.port,
|
||||||
config.redis.host,
|
config.redis.host,
|
||||||
{
|
{
|
||||||
@ -9,4 +9,4 @@ export default config.redis ? redis.createClient(
|
|||||||
prefix: config.redis.prefix,
|
prefix: config.redis.prefix,
|
||||||
db: config.redis.db || 0
|
db: config.redis.db || 0
|
||||||
}
|
}
|
||||||
) : null;
|
);
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
// AID
|
|
||||||
// 長さ8の[2000年1月1日からの経過ミリ秒をbase36でエンコードしたもの] + 長さnの[ランダムな文字列]
|
|
||||||
|
|
||||||
const CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
|
||||||
const TIME2000 = 946684800000;
|
|
||||||
|
|
||||||
function getTime(time: number) {
|
|
||||||
time = time - TIME2000;
|
|
||||||
if (time < 0) time = 0;
|
|
||||||
|
|
||||||
return time.toString(36);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRandom(length: number) {
|
|
||||||
let str = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
str += CHARS[Math.floor(Math.random() * CHARS.length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function genAid(date: Date, rand: number): string {
|
|
||||||
return getTime(date.getTime()).padStart(8, CHARS[0]) + getRandom(rand);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
// AID(Cheep)
|
|
||||||
// 長さ6の[2000年1月1日からの経過秒をbase36でエンコードしたもの] + 長さ3の[ランダムな文字列]
|
|
||||||
|
|
||||||
const CHARS = '0123456789abcdefghijklmnopqrstuvwxyz';
|
|
||||||
const TIME2000 = 946684800000;
|
|
||||||
|
|
||||||
function getTime(time: number) {
|
|
||||||
time = time - TIME2000;
|
|
||||||
if (time < 0) time = 0;
|
|
||||||
time = Math.floor(time / 1000);
|
|
||||||
return time.toString(36);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRandom() {
|
|
||||||
let str = '';
|
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
str += CHARS[Math.floor(Math.random() * CHARS.length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function genAidc(date: Date): string {
|
|
||||||
return getTime(date.getTime()).padStart(6, CHARS[0]) + getRandom();
|
|
||||||
}
|
|
@ -19,3 +19,8 @@ export function extractDbHost(uri: string) {
|
|||||||
export function toPuny(host: string) {
|
export function toPuny(host: string) {
|
||||||
return toASCII(host.toLowerCase());
|
return toASCII(host.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toPunyNullable(host: string | null | undefined): string | null {
|
||||||
|
if (host == null) return null;
|
||||||
|
return toASCII(host.toLowerCase());
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ulid } from 'ulid';
|
import { ulid } from 'ulid';
|
||||||
import { genAid } from './aid';
|
import { genAid } from './id/aid';
|
||||||
import { genAidc } from './aidc';
|
import { genMeid } from './id/meid';
|
||||||
import { genObjectId } from './object-id';
|
import { genObjectId } from './id/object-id';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
|
||||||
const metohd = config.id.toLowerCase();
|
const metohd = config.id.toLowerCase();
|
||||||
@ -10,11 +10,8 @@ export function genId(date?: Date): string {
|
|||||||
if (!date || (date > new Date())) date = new Date();
|
if (!date || (date > new Date())) date = new Date();
|
||||||
|
|
||||||
switch (metohd) {
|
switch (metohd) {
|
||||||
case 'aidc': return genAidc(date);
|
case 'aid': return genAid(date);
|
||||||
case 'aid1': return genAid(date, 1);
|
case 'meid': return genMeid(date);
|
||||||
case 'aid2': return genAid(date, 2);
|
|
||||||
case 'aid3': return genAid(date, 3);
|
|
||||||
case 'aid4': return genAid(date, 4);
|
|
||||||
case 'ulid': return ulid(date.getTime());
|
case 'ulid': return ulid(date.getTime());
|
||||||
case 'objectid': return genObjectId(date);
|
case 'objectid': return genObjectId(date);
|
||||||
default: throw 'unknown id generation method';
|
default: throw 'unknown id generation method';
|
||||||
|
23
src/misc/id/aid.ts
Normal file
23
src/misc/id/aid.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// AID
|
||||||
|
// 長さ8の[2000年1月1日からの経過ミリ秒をbase36でエンコードしたもの] + 長さ2の[ノイズ文字列]
|
||||||
|
|
||||||
|
import * as cluster from 'cluster';
|
||||||
|
|
||||||
|
const TIME2000 = 946684800000;
|
||||||
|
let counter = process.pid + (cluster.isMaster ? 0 : cluster.worker.id);
|
||||||
|
|
||||||
|
function getTime(time: number) {
|
||||||
|
time = time - TIME2000;
|
||||||
|
if (time < 0) time = 0;
|
||||||
|
|
||||||
|
return time.toString(36).padStart(8, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNoise() {
|
||||||
|
return counter.toString(36).padStart(2, '0').slice(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function genAid(date: Date): string {
|
||||||
|
counter++;
|
||||||
|
return getTime(date.getTime()) + getNoise();
|
||||||
|
}
|
26
src/misc/id/meid.ts
Normal file
26
src/misc/id/meid.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const CHARS = '0123456789abcdef';
|
||||||
|
|
||||||
|
function getTime(time: number) {
|
||||||
|
if (time < 0) time = 0;
|
||||||
|
if (time === 0) {
|
||||||
|
return CHARS[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
time += 0x800000000000;
|
||||||
|
|
||||||
|
return time.toString(16).padStart(12, 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 genMeid(date: Date): string {
|
||||||
|
return 'f' + getTime(date.getTime()) + getRandom();
|
||||||
|
}
|
@ -8,7 +8,7 @@ function getTime(time: number) {
|
|||||||
|
|
||||||
time = Math.floor(time / 1000);
|
time = Math.floor(time / 1000);
|
||||||
|
|
||||||
return time.toString(16);
|
return time.toString(16).padStart(8, CHARS[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandom() {
|
function getRandom() {
|
@ -20,7 +20,7 @@ export async function getFallbackReaction(): Promise<string> {
|
|||||||
return meta.useStarForReactionFallback ? 'star' : 'like';
|
return meta.useStarForReactionFallback ? 'star' : 'like';
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function toDbReaction(reaction: string, enableEmoji = true): Promise<string> {
|
export async function toDbReaction(reaction?: string | null, enableEmoji = true): Promise<string> {
|
||||||
if (reaction == null) return await getFallbackReaction();
|
if (reaction == null) return await getFallbackReaction();
|
||||||
|
|
||||||
// 既存の文字列リアクションはそのまま
|
// 既存の文字列リアクションはそのまま
|
||||||
|
@ -19,11 +19,15 @@ export class AuthSession {
|
|||||||
})
|
})
|
||||||
public token: string;
|
public token: string;
|
||||||
|
|
||||||
@Column(id())
|
@Column({
|
||||||
|
...id(),
|
||||||
|
nullable: true
|
||||||
|
})
|
||||||
public userId: User['id'];
|
public userId: User['id'];
|
||||||
|
|
||||||
@ManyToOne(type => User, {
|
@ManyToOne(type => User, {
|
||||||
onDelete: 'CASCADE'
|
onDelete: 'CASCADE',
|
||||||
|
nullable: true
|
||||||
})
|
})
|
||||||
@JoinColumn()
|
@JoinColumn()
|
||||||
public user: User | null;
|
public user: User | null;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { EntityRepository, Repository } from 'typeorm';
|
import { EntityRepository, Repository } from 'typeorm';
|
||||||
import { UserList } from '../entities/user-list';
|
import { UserList } from '../entities/user-list';
|
||||||
import { ensure } from '../../prelude/ensure';
|
import { ensure } from '../../prelude/ensure';
|
||||||
|
import { UserListJoinings } from '..';
|
||||||
|
|
||||||
@EntityRepository(UserList)
|
@EntityRepository(UserList)
|
||||||
export class UserListRepository extends Repository<UserList> {
|
export class UserListRepository extends Repository<UserList> {
|
||||||
@ -9,9 +10,14 @@ export class UserListRepository extends Repository<UserList> {
|
|||||||
) {
|
) {
|
||||||
const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||||
|
|
||||||
|
const users = await UserListJoinings.find({
|
||||||
|
userListId: userList.id
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: userList.id,
|
id: userList.id,
|
||||||
name: userList.name
|
name: userList.name,
|
||||||
|
userIds: users.map(x => x.userId)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,14 @@ function initializeQueue(name: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderError(e: Error): any {
|
||||||
|
return {
|
||||||
|
stack: e.stack,
|
||||||
|
message: e.message,
|
||||||
|
name: e.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export const deliverQueue = initializeQueue('deliver');
|
export const deliverQueue = initializeQueue('deliver');
|
||||||
export const inboxQueue = initializeQueue('inbox');
|
export const inboxQueue = initializeQueue('inbox');
|
||||||
export const dbQueue = initializeQueue('db');
|
export const dbQueue = initializeQueue('db');
|
||||||
@ -34,16 +42,16 @@ deliverQueue
|
|||||||
.on('waiting', (jobId) => deliverLogger.debug(`waiting id=${jobId}`))
|
.on('waiting', (jobId) => deliverLogger.debug(`waiting id=${jobId}`))
|
||||||
.on('active', (job) => deliverLogger.debug(`active id=${job.id} to=${job.data.to}`))
|
.on('active', (job) => deliverLogger.debug(`active id=${job.id} to=${job.data.to}`))
|
||||||
.on('completed', (job, result) => deliverLogger.debug(`completed(${result}) id=${job.id} to=${job.data.to}`))
|
.on('completed', (job, result) => deliverLogger.debug(`completed(${result}) id=${job.id} to=${job.data.to}`))
|
||||||
.on('failed', (job, err) => deliverLogger.warn(`failed(${err}) id=${job.id} to=${job.data.to}`))
|
.on('failed', (job, err) => deliverLogger.warn(`failed(${err}) id=${job.id} to=${job.data.to}`, renderError(err)))
|
||||||
.on('error', (error) => deliverLogger.error(`error ${error}`))
|
.on('error', (error) => deliverLogger.error(`error ${error}`, renderError(error)))
|
||||||
.on('stalled', (job) => deliverLogger.warn(`stalled id=${job.id} to=${job.data.to}`));
|
.on('stalled', (job) => deliverLogger.warn(`stalled id=${job.id} to=${job.data.to}`));
|
||||||
|
|
||||||
inboxQueue
|
inboxQueue
|
||||||
.on('waiting', (jobId) => inboxLogger.debug(`waiting id=${jobId}`))
|
.on('waiting', (jobId) => inboxLogger.debug(`waiting id=${jobId}`))
|
||||||
.on('active', (job) => inboxLogger.debug(`active id=${job.id}`))
|
.on('active', (job) => inboxLogger.debug(`active id=${job.id}`))
|
||||||
.on('completed', (job, result) => inboxLogger.debug(`completed(${result}) id=${job.id}`))
|
.on('completed', (job, result) => inboxLogger.debug(`completed(${result}) id=${job.id}`))
|
||||||
.on('failed', (job, err) => inboxLogger.warn(`failed(${err}) id=${job.id} activity=${job.data.activity ? job.data.activity.id : 'none'}`))
|
.on('failed', (job, err) => inboxLogger.warn(`failed(${err}) id=${job.id} activity=${job.data.activity ? job.data.activity.id : 'none'}`, renderError(err)))
|
||||||
.on('error', (error) => inboxLogger.error(`error ${error}`))
|
.on('error', (error) => inboxLogger.error(`error ${error}`, renderError(error)))
|
||||||
.on('stalled', (job) => inboxLogger.warn(`stalled id=${job.id} activity=${job.data.activity ? job.data.activity.id : 'none'}`));
|
.on('stalled', (job) => inboxLogger.warn(`stalled id=${job.id} activity=${job.data.activity ? job.data.activity.id : 'none'}`));
|
||||||
|
|
||||||
export function deliver(user: ILocalUser, content: any, to: any) {
|
export function deliver(user: ILocalUser, content: any, to: any) {
|
||||||
|
@ -12,7 +12,7 @@ import { Instances, Users, UserPublickeys } from '../../models';
|
|||||||
import { instanceChart } from '../../services/chart';
|
import { instanceChart } from '../../services/chart';
|
||||||
import { UserPublickey } from '../../models/entities/user-publickey';
|
import { UserPublickey } from '../../models/entities/user-publickey';
|
||||||
import fetchMeta from '../../misc/fetch-meta';
|
import fetchMeta from '../../misc/fetch-meta';
|
||||||
import { toPuny } from '../../misc/convert-host';
|
import { toPuny, toPunyNullable } from '../../misc/convert-host';
|
||||||
import { validActor } from '../../remote/activitypub/type';
|
import { validActor } from '../../remote/activitypub/type';
|
||||||
import { ensure } from '../../prelude/ensure';
|
import { ensure } from '../../prelude/ensure';
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ export default async (job: Bull.Job): Promise<void> => {
|
|||||||
|
|
||||||
if (keyIdLower.startsWith('acct:')) {
|
if (keyIdLower.startsWith('acct:')) {
|
||||||
const acct = parseAcct(keyIdLower.slice('acct:'.length));
|
const acct = parseAcct(keyIdLower.slice('acct:'.length));
|
||||||
const host = acct.host ? toPuny(acct.host) : null;
|
const host = toPunyNullable(acct.host);
|
||||||
const username = toPuny(acct.username);
|
const username = toPuny(acct.username);
|
||||||
|
|
||||||
if (host === null) {
|
if (host === null) {
|
||||||
|
@ -120,13 +120,15 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
|
|||||||
: [];
|
: [];
|
||||||
|
|
||||||
// リプライ
|
// リプライ
|
||||||
const reply: Note | undefined | null = note.inReplyTo
|
const reply: Note | null = note.inReplyTo
|
||||||
? await resolveNote(note.inReplyTo, resolver).catch(e => {
|
? await resolveNote(note.inReplyTo, resolver).then(x => {
|
||||||
// 4xxの場合はリプライしてないことにする
|
if (x == null) {
|
||||||
if (e.statusCode >= 400 && e.statusCode < 500) {
|
logger.warn(`Specified inReplyTo, but nout found`);
|
||||||
logger.warn(`Ignored inReplyTo ${note.inReplyTo} - ${e.statusCode} `);
|
throw 'inReplyTo not found';
|
||||||
return null;
|
} else {
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
}).catch(e => {
|
||||||
logger.warn(`Error in inReplyTo ${note.inReplyTo} - ${e.statusCode || e}`);
|
logger.warn(`Error in inReplyTo ${note.inReplyTo} - ${e.statusCode || e}`);
|
||||||
throw e;
|
throw e;
|
||||||
})
|
})
|
||||||
@ -150,11 +152,11 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
|
|||||||
const cw = note.summary === '' ? null : note.summary;
|
const cw = note.summary === '' ? null : note.summary;
|
||||||
|
|
||||||
// テキストのパース
|
// テキストのパース
|
||||||
const text = note._misskey_content || fromHtml(note.content);
|
const text = note._misskey_content || (note.content ? fromHtml(note.content) : null);
|
||||||
|
|
||||||
// vote
|
// vote
|
||||||
if (reply && reply.hasPoll) {
|
if (reply && reply.hasPoll) {
|
||||||
const poll = await Polls.findOne({ noteId: reply.id }).then(ensure);
|
const poll = await Polls.findOne(reply.id).then(ensure);
|
||||||
|
|
||||||
const tryCreateVote = async (name: string, index: number): Promise<null> => {
|
const tryCreateVote = async (name: string, index: number): Promise<null> => {
|
||||||
if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) {
|
if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) {
|
||||||
|
@ -12,7 +12,7 @@ export interface IObject {
|
|||||||
attachment?: any[];
|
attachment?: any[];
|
||||||
inReplyTo?: any;
|
inReplyTo?: any;
|
||||||
replies?: ICollection;
|
replies?: ICollection;
|
||||||
content: string;
|
content?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
startTime?: Date;
|
startTime?: Date;
|
||||||
endTime?: Date;
|
endTime?: Date;
|
||||||
@ -44,16 +44,16 @@ export interface IOrderedCollection extends IObject {
|
|||||||
|
|
||||||
export interface INote extends IObject {
|
export interface INote extends IObject {
|
||||||
type: 'Note' | 'Question';
|
type: 'Note' | 'Question';
|
||||||
_misskey_content: string;
|
_misskey_content?: string;
|
||||||
_misskey_quote: string;
|
_misskey_quote?: string;
|
||||||
_misskey_question: string;
|
_misskey_question?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IQuestion extends IObject {
|
export interface IQuestion extends IObject {
|
||||||
type: 'Note' | 'Question';
|
type: 'Note' | 'Question';
|
||||||
_misskey_content: string;
|
_misskey_content?: string;
|
||||||
_misskey_quote: string;
|
_misskey_quote?: string;
|
||||||
_misskey_question: string;
|
_misskey_question?: string;
|
||||||
oneOf?: IQuestionChoice[];
|
oneOf?: IQuestionChoice[];
|
||||||
anyOf?: IQuestionChoice[];
|
anyOf?: IQuestionChoice[];
|
||||||
endTime?: Date;
|
endTime?: Date;
|
||||||
@ -129,7 +129,7 @@ export interface IRemove extends IActivity {
|
|||||||
|
|
||||||
export interface ILike extends IActivity {
|
export interface ILike extends IActivity {
|
||||||
type: 'Like';
|
type: 'Like';
|
||||||
_misskey_reaction: string;
|
_misskey_reaction?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAnnounce extends IActivity {
|
export interface IAnnounce extends IActivity {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import define from '../../../define';
|
import define from '../../../define';
|
||||||
import { Emojis } from '../../../../../models';
|
import { Emojis } from '../../../../../models';
|
||||||
import { toPuny } from '../../../../../misc/convert-host';
|
import { toPunyNullable } from '../../../../../misc/convert-host';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
@ -23,7 +23,7 @@ export const meta = {
|
|||||||
|
|
||||||
export default define(meta, async (ps) => {
|
export default define(meta, async (ps) => {
|
||||||
const emojis = await Emojis.find({
|
const emojis = await Emojis.find({
|
||||||
host: ps.host ? toPuny(ps.host) : null
|
host: toPunyNullable(ps.host)
|
||||||
});
|
});
|
||||||
|
|
||||||
return emojis.map(e => ({
|
return emojis.map(e => ({
|
||||||
|
@ -38,7 +38,7 @@ export default define(meta, async (ps, user) => {
|
|||||||
const app = await Apps.save({
|
const app = await Apps.save({
|
||||||
id: genId(),
|
id: genId(),
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
userId: user && user.id,
|
userId: user ? user.id : null,
|
||||||
name: ps.name,
|
name: ps.name,
|
||||||
description: ps.description,
|
description: ps.description,
|
||||||
permission: ps.permission,
|
permission: ps.permission,
|
||||||
|
@ -71,6 +71,4 @@ export default define(meta, async (ps, user) => {
|
|||||||
await AuthSessions.update(session.id, {
|
await AuthSessions.update(session.id, {
|
||||||
userId: user.id
|
userId: user.id
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
|
@ -124,7 +124,7 @@ export default define(meta, async (ps, user) => {
|
|||||||
|
|
||||||
// Increment votes count
|
// Increment votes count
|
||||||
const index = ps.choice + 1; // In SQL, array index is 1 based
|
const index = ps.choice + 1; // In SQL, array index is 1 based
|
||||||
await Polls.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE noteId = '${poll.noteId}'`);
|
await Polls.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE "noteId" = '${poll.noteId}'`);
|
||||||
|
|
||||||
publishNoteStream(note.id, 'pollVoted', {
|
publishNoteStream(note.id, 'pollVoted', {
|
||||||
choice: ps.choice,
|
choice: ps.choice,
|
||||||
|
@ -4,7 +4,7 @@ import define from '../../define';
|
|||||||
import { ApiError } from '../../error';
|
import { ApiError } from '../../error';
|
||||||
import { Users, Followings } from '../../../../models';
|
import { Users, Followings } from '../../../../models';
|
||||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||||
import { toPuny } from '../../../../misc/convert-host';
|
import { toPunyNullable } from '../../../../misc/convert-host';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
@ -66,7 +66,7 @@ export const meta = {
|
|||||||
export default define(meta, async (ps, me) => {
|
export default define(meta, async (ps, me) => {
|
||||||
const user = await Users.findOne(ps.userId != null
|
const user = await Users.findOne(ps.userId != null
|
||||||
? { id: ps.userId }
|
? { id: ps.userId }
|
||||||
: { usernameLower: ps.username!.toLowerCase(), host: toPuny(ps.host!) });
|
: { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) });
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new ApiError(meta.errors.noSuchUser);
|
throw new ApiError(meta.errors.noSuchUser);
|
||||||
|
@ -4,7 +4,7 @@ import define from '../../define';
|
|||||||
import { ApiError } from '../../error';
|
import { ApiError } from '../../error';
|
||||||
import { Users, Followings } from '../../../../models';
|
import { Users, Followings } from '../../../../models';
|
||||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||||
import { toPuny } from '../../../../misc/convert-host';
|
import { toPunyNullable } from '../../../../misc/convert-host';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
@ -66,7 +66,7 @@ export const meta = {
|
|||||||
export default define(meta, async (ps, me) => {
|
export default define(meta, async (ps, me) => {
|
||||||
const user = await Users.findOne(ps.userId != null
|
const user = await Users.findOne(ps.userId != null
|
||||||
? { id: ps.userId }
|
? { id: ps.userId }
|
||||||
: { usernameLower: ps.username!.toLowerCase(), host: toPuny(ps.host!) });
|
: { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) });
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new ApiError(meta.errors.noSuchUser);
|
throw new ApiError(meta.errors.noSuchUser);
|
||||||
|
@ -8,12 +8,6 @@ import Logger from '../../services/logger';
|
|||||||
const logger = new Logger('limiter');
|
const logger = new Logger('limiter');
|
||||||
|
|
||||||
export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) => {
|
export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) => {
|
||||||
// Redisがインストールされてない場合は常に許可
|
|
||||||
if (limiterDB == null) {
|
|
||||||
ok();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const limitation = endpoint.meta.limit!;
|
const limitation = endpoint.meta.limit!;
|
||||||
|
|
||||||
const key = limitation.hasOwnProperty('key')
|
const key = limitation.hasOwnProperty('key')
|
||||||
|
@ -10,7 +10,7 @@ import { genId } from '../../../misc/gen-id';
|
|||||||
import { usersChart } from '../../../services/chart';
|
import { usersChart } from '../../../services/chart';
|
||||||
import { User } from '../../../models/entities/user';
|
import { User } from '../../../models/entities/user';
|
||||||
import { UserKeypair } from '../../../models/entities/user-keypair';
|
import { UserKeypair } from '../../../models/entities/user-keypair';
|
||||||
import { toPuny } from '../../../misc/convert-host';
|
import { toPunyNullable } from '../../../misc/convert-host';
|
||||||
import { UserProfile } from '../../../models/entities/user-profile';
|
import { UserProfile } from '../../../models/entities/user-profile';
|
||||||
import { getConnection } from 'typeorm';
|
import { getConnection } from 'typeorm';
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ export default async (ctx: Koa.BaseContext) => {
|
|||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
username: username,
|
username: username,
|
||||||
usernameLower: username.toLowerCase(),
|
usernameLower: username.toLowerCase(),
|
||||||
host: host ? toPuny(host) : null,
|
host: toPunyNullable(host),
|
||||||
token: secret,
|
token: secret,
|
||||||
isAdmin: config.autoAdmin && usersCount === 0,
|
isAdmin: config.autoAdmin && usersCount === 0,
|
||||||
}));
|
}));
|
||||||
|
@ -83,8 +83,6 @@ async function getOAuth2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.get('/connect/discord', async ctx => {
|
router.get('/connect/discord', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
if (!compareOrigin(ctx)) {
|
if (!compareOrigin(ctx)) {
|
||||||
ctx.throw(400, 'invalid origin');
|
ctx.throw(400, 'invalid origin');
|
||||||
return;
|
return;
|
||||||
@ -110,8 +108,6 @@ router.get('/connect/discord', async ctx => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/signin/discord', async ctx => {
|
router.get('/signin/discord', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
const sessid = uuid();
|
const sessid = uuid();
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
@ -138,8 +134,6 @@ router.get('/signin/discord', async ctx => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/dc/cb', async ctx => {
|
router.get('/dc/cb', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
const userToken = getUserToken(ctx);
|
const userToken = getUserToken(ctx);
|
||||||
|
|
||||||
const oauth2 = await getOAuth2();
|
const oauth2 = await getOAuth2();
|
||||||
@ -160,7 +154,7 @@ router.get('/dc/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||||
redis!.get(sessid, async (_, state) => {
|
redis.get(sessid, async (_, state) => {
|
||||||
res(JSON.parse(state));
|
res(JSON.parse(state));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -241,7 +235,7 @@ router.get('/dc/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||||
redis!.get(userToken, async (_, state) => {
|
redis.get(userToken, async (_, state) => {
|
||||||
res(JSON.parse(state));
|
res(JSON.parse(state));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -80,8 +80,6 @@ async function getOath2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.get('/connect/github', async ctx => {
|
router.get('/connect/github', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
if (!compareOrigin(ctx)) {
|
if (!compareOrigin(ctx)) {
|
||||||
ctx.throw(400, 'invalid origin');
|
ctx.throw(400, 'invalid origin');
|
||||||
return;
|
return;
|
||||||
@ -106,8 +104,6 @@ router.get('/connect/github', async ctx => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/signin/github', async ctx => {
|
router.get('/signin/github', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
const sessid = uuid();
|
const sessid = uuid();
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
@ -133,8 +129,6 @@ router.get('/signin/github', async ctx => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/gh/cb', async ctx => {
|
router.get('/gh/cb', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
const userToken = getUserToken(ctx);
|
const userToken = getUserToken(ctx);
|
||||||
|
|
||||||
const oauth2 = await getOath2();
|
const oauth2 = await getOath2();
|
||||||
@ -155,7 +149,7 @@ router.get('/gh/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||||
redis!.get(sessid, async (_, state) => {
|
redis.get(sessid, async (_, state) => {
|
||||||
res(JSON.parse(state));
|
res(JSON.parse(state));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -222,7 +216,7 @@ router.get('/gh/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
const { redirect_uri, state } = await new Promise<any>((res, rej) => {
|
||||||
redis!.get(userToken, async (_, state) => {
|
redis.get(userToken, async (_, state) => {
|
||||||
res(JSON.parse(state));
|
res(JSON.parse(state));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -79,8 +79,6 @@ async function getTwAuth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.get('/connect/twitter', async ctx => {
|
router.get('/connect/twitter', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
if (!compareOrigin(ctx)) {
|
if (!compareOrigin(ctx)) {
|
||||||
ctx.throw(400, 'invalid origin');
|
ctx.throw(400, 'invalid origin');
|
||||||
return;
|
return;
|
||||||
@ -99,8 +97,6 @@ router.get('/connect/twitter', async ctx => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/signin/twitter', async ctx => {
|
router.get('/signin/twitter', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
const twAuth = await getTwAuth();
|
const twAuth = await getTwAuth();
|
||||||
const twCtx = await twAuth!.begin();
|
const twCtx = await twAuth!.begin();
|
||||||
|
|
||||||
@ -122,8 +118,6 @@ router.get('/signin/twitter', async ctx => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/tw/cb', async ctx => {
|
router.get('/tw/cb', async ctx => {
|
||||||
if (redis == null) return;
|
|
||||||
|
|
||||||
const userToken = getUserToken(ctx);
|
const userToken = getUserToken(ctx);
|
||||||
|
|
||||||
const twAuth = await getTwAuth();
|
const twAuth = await getTwAuth();
|
||||||
@ -137,7 +131,7 @@ router.get('/tw/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const get = new Promise<any>((res, rej) => {
|
const get = new Promise<any>((res, rej) => {
|
||||||
redis!.get(sessid, async (_, twCtx) => {
|
redis.get(sessid, async (_, twCtx) => {
|
||||||
res(twCtx);
|
res(twCtx);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -170,7 +164,7 @@ router.get('/tw/cb', async ctx => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const get = new Promise<any>((res, rej) => {
|
const get = new Promise<any>((res, rej) => {
|
||||||
redis!.get(userToken, async (_, twCtx) => {
|
redis.get(userToken, async (_, twCtx) => {
|
||||||
res(twCtx);
|
res(twCtx);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import * as websocket from 'websocket';
|
import * as websocket from 'websocket';
|
||||||
import * as redis from 'redis';
|
import * as redis from 'redis';
|
||||||
import Xev from 'xev';
|
|
||||||
|
|
||||||
import MainStreamConnection from './stream';
|
import MainStreamConnection from './stream';
|
||||||
import { ParsedUrlQuery } from 'querystring';
|
import { ParsedUrlQuery } from 'querystring';
|
||||||
@ -23,7 +22,6 @@ module.exports = (server: http.Server) => {
|
|||||||
|
|
||||||
let ev: EventEmitter;
|
let ev: EventEmitter;
|
||||||
|
|
||||||
if (config.redis) {
|
|
||||||
// Connect to Redis
|
// Connect to Redis
|
||||||
const subscriber = redis.createClient(
|
const subscriber = redis.createClient(
|
||||||
config.redis.port, config.redis.host);
|
config.redis.port, config.redis.host);
|
||||||
@ -42,9 +40,6 @@ module.exports = (server: http.Server) => {
|
|||||||
subscriber.unsubscribe();
|
subscriber.unsubscribe();
|
||||||
subscriber.quit();
|
subscriber.quit();
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
ev = new Xev();
|
|
||||||
}
|
|
||||||
|
|
||||||
const main = new MainStreamConnection(connection, ev, user, app);
|
const main = new MainStreamConnection(connection, ev, user, app);
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import { genId } from '../../../misc/gen-id';
|
|||||||
import { createNotification } from '../../create-notification';
|
import { createNotification } from '../../create-notification';
|
||||||
|
|
||||||
export default async function(user: User, note: Note, choice: number) {
|
export default async function(user: User, note: Note, choice: number) {
|
||||||
const poll = await Polls.findOne({ noteId: note.id });
|
const poll = await Polls.findOne(note.id);
|
||||||
|
|
||||||
if (poll == null) throw 'poll not found';
|
if (poll == null) throw 'poll not found';
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ export default async function(user: User, note: Note, choice: number) {
|
|||||||
|
|
||||||
// Increment votes count
|
// Increment votes count
|
||||||
const index = choice + 1; // In SQL, array index is 1 based
|
const index = choice + 1; // In SQL, array index is 1 based
|
||||||
await Polls.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE noteId = '${poll.noteId}'`);
|
await Polls.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE "noteId" = '${poll.noteId}'`);
|
||||||
|
|
||||||
publishNoteStream(note.id, 'pollVoted', {
|
publishNoteStream(note.id, 'pollVoted', {
|
||||||
choice: choice,
|
choice: choice,
|
||||||
|
@ -16,7 +16,7 @@ import { NoteReaction } from '../../../models/entities/note-reaction';
|
|||||||
import { createNotification } from '../../create-notification';
|
import { createNotification } from '../../create-notification';
|
||||||
import { isDuplicateKeyValueError } from '../../../misc/is-duplicate-key-value-error';
|
import { isDuplicateKeyValueError } from '../../../misc/is-duplicate-key-value-error';
|
||||||
|
|
||||||
export default async (user: User, note: Note, reaction: string) => {
|
export default async (user: User, note: Note, reaction?: string) => {
|
||||||
// Myself
|
// Myself
|
||||||
if (note.userId === user.id) {
|
if (note.userId === user.id) {
|
||||||
throw new IdentifiableError('2d8e7297-1873-4c00-8404-792c68d7bef0', 'cannot react to my note');
|
throw new IdentifiableError('2d8e7297-1873-4c00-8404-792c68d7bef0', 'cannot react to my note');
|
||||||
|
@ -1,34 +1,20 @@
|
|||||||
import redis from '../db/redis';
|
import redis from '../db/redis';
|
||||||
import Xev from 'xev';
|
|
||||||
import { User } from '../models/entities/user';
|
import { User } from '../models/entities/user';
|
||||||
import { Note } from '../models/entities/note';
|
import { Note } from '../models/entities/note';
|
||||||
import { UserList } from '../models/entities/user-list';
|
import { UserList } from '../models/entities/user-list';
|
||||||
import { ReversiGame } from '../models/entities/games/reversi/game';
|
import { ReversiGame } from '../models/entities/games/reversi/game';
|
||||||
|
|
||||||
class Publisher {
|
class Publisher {
|
||||||
private ev: Xev | null = null;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
// Redisがインストールされてないときはプロセス間通信を使う
|
|
||||||
if (redis == null) {
|
|
||||||
this.ev = new Xev();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private publish = (channel: string, type: string | null, value?: any): void => {
|
private publish = (channel: string, type: string | null, value?: any): void => {
|
||||||
const message = type == null ? value : value == null ?
|
const message = type == null ? value : value == null ?
|
||||||
{ type: type, body: null } :
|
{ type: type, body: null } :
|
||||||
{ type: type, body: value };
|
{ type: type, body: value };
|
||||||
|
|
||||||
if (this.ev) {
|
redis.publish('misskey', JSON.stringify({
|
||||||
this.ev.emit(channel, message);
|
|
||||||
} else {
|
|
||||||
redis!.publish('misskey', JSON.stringify({
|
|
||||||
channel: channel,
|
channel: channel,
|
||||||
message: message
|
message: message
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public publishMainStream = (userId: User['id'], type: string, value?: any): void => {
|
public publishMainStream = (userId: User['id'], type: string, value?: any): void => {
|
||||||
this.publish(`mainStream:${userId}`, type, typeof value === 'undefined' ? null : value);
|
this.publish(`mainStream:${userId}`, type, typeof value === 'undefined' ? null : value);
|
||||||
|
@ -63,7 +63,9 @@ export async function updateHashtag(user: User, tag: string, isUserAttached = fa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Object.keys(set).length > 0) {
|
||||||
q.execute();
|
q.execute();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isUserAttached) {
|
if (isUserAttached) {
|
||||||
Hashtags.save({
|
Hashtags.save({
|
||||||
|
Reference in New Issue
Block a user