Compare commits
35 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
07560a4fdd | ||
![]() |
7edca21c05 | ||
![]() |
34105abd9d | ||
![]() |
1bbca48a0b | ||
![]() |
21f6a86772 | ||
![]() |
6559197c55 | ||
![]() |
05f9ad11bb | ||
![]() |
f06d586680 | ||
![]() |
4f45e8125c | ||
![]() |
cc2843503d | ||
![]() |
324a974dec | ||
![]() |
4d4ffd70ac | ||
![]() |
bf98a11b65 | ||
![]() |
1117ce4b54 | ||
![]() |
57e93b9b4e | ||
![]() |
9e4b061ed0 | ||
![]() |
1067bef7d6 | ||
![]() |
8bff529acd | ||
![]() |
4b08677839 | ||
![]() |
70997cb551 | ||
![]() |
bf0ef17e23 | ||
![]() |
7dae5107f8 | ||
![]() |
2dea88a147 | ||
![]() |
f44c2a3e4f | ||
![]() |
1fad3cbaae | ||
![]() |
40d2e3e97c | ||
![]() |
2efabe612e | ||
![]() |
3107cbd6b9 | ||
![]() |
3a061ed1c3 | ||
![]() |
d4f0e6461a | ||
![]() |
3285687652 | ||
![]() |
51c53f64d0 | ||
![]() |
1d582f5ad2 | ||
![]() |
8a62748e39 | ||
![]() |
6db3d6dfb6 |
@@ -60,11 +60,6 @@ mongodb:
|
|||||||
user: example-misskey-user
|
user: example-misskey-user
|
||||||
pass: example-misskey-pass
|
pass: example-misskey-pass
|
||||||
|
|
||||||
redis:
|
|
||||||
host: localhost
|
|
||||||
port: 6379
|
|
||||||
pass: example-pass
|
|
||||||
|
|
||||||
# Drive capacity of a local user (MB)
|
# Drive capacity of a local user (MB)
|
||||||
localDriveCapacityMb: 256
|
localDriveCapacityMb: 256
|
||||||
|
|
||||||
@@ -122,47 +117,50 @@ drive:
|
|||||||
# Below settings are optional
|
# Below settings are optional
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
#redis:
|
||||||
|
# host: localhost
|
||||||
|
# port: 6379
|
||||||
|
# pass: example-pass
|
||||||
|
|
||||||
# Elasticsearch
|
# Elasticsearch
|
||||||
# elasticsearch:
|
#elasticsearch:
|
||||||
# host: localhost
|
# host: localhost
|
||||||
# port: 9200
|
# port: 9200
|
||||||
# pass: null
|
# pass: null
|
||||||
|
|
||||||
# reCAPTCHA
|
# reCAPTCHA
|
||||||
# recaptcha:
|
#recaptcha:
|
||||||
# site_key: example-site-key
|
# site_key: example-site-key
|
||||||
# secret_key: example-secret-key
|
# secret_key: example-secret-key
|
||||||
|
|
||||||
# ServiceWorker
|
# ServiceWorker
|
||||||
# sw:
|
#sw:
|
||||||
# # Public key of VAPID
|
# # Public key of VAPID
|
||||||
# public_key: example-sw-public-key
|
# public_key: example-sw-public-key
|
||||||
|
#
|
||||||
# # Private key of VAPID
|
# # Private key of VAPID
|
||||||
# private_key: example-sw-private-key
|
# private_key: example-sw-private-key
|
||||||
|
|
||||||
# google_maps_api_key: example-google-maps-api-key
|
|
||||||
|
|
||||||
# Twitter integration
|
# Twitter integration
|
||||||
# You need to set the oauth callback url as : https://<your-misskey-instance>/api/tw/cb
|
# You need to set the oauth callback url as : https://<your-misskey-instance>/api/tw/cb
|
||||||
# twitter:
|
#twitter:
|
||||||
# consumer_key: example-twitter-consumer-key
|
# consumer_key: example-twitter-consumer-key
|
||||||
# consumer_secret: example-twitter-consumer-secret-key
|
# consumer_secret: example-twitter-consumer-secret-key
|
||||||
|
|
||||||
# Ghost
|
# Ghost
|
||||||
# Ghost account is an account used for the purpose of delegating
|
# Ghost account is an account used for the purpose of delegating
|
||||||
# followers when putting users in the list.
|
# followers when putting users in the list.
|
||||||
# ghost: user-id-of-your-ghost-account
|
#ghost: user-id-of-your-ghost-account
|
||||||
|
|
||||||
# Clustering
|
# Clustering
|
||||||
# clusterLimit: 1
|
#clusterLimit: 1
|
||||||
|
|
||||||
# Summaly proxy
|
# Summaly proxy
|
||||||
# summalyProxy: "http://example.com"
|
#summalyProxy: "http://example.com"
|
||||||
|
|
||||||
# User recommendation
|
# User recommendation
|
||||||
user_recommendation:
|
#user_recommendation:
|
||||||
external: true
|
# external: true
|
||||||
engine: http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}
|
# engine: http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}
|
||||||
timeout: 300000
|
# timeout: 300000
|
||||||
|
|
||||||
|
@@ -24,12 +24,12 @@ Please install and setup these softwares:
|
|||||||
#### Dependencies :package:
|
#### Dependencies :package:
|
||||||
* **[Node.js](https://nodejs.org/en/)**
|
* **[Node.js](https://nodejs.org/en/)**
|
||||||
* **[MongoDB](https://www.mongodb.com/)** >= 3.6
|
* **[MongoDB](https://www.mongodb.com/)** >= 3.6
|
||||||
* **[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/) - used to provide searching feature instead of MongoDB
|
* [Elasticsearch](https://www.elastic.co/) - used to provide searching feature instead of MongoDB
|
||||||
|
|
||||||
|
|
||||||
*3.* Setup MongoDB
|
*3.* Setup MongoDB
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
In root :
|
In root :
|
||||||
|
@@ -24,10 +24,17 @@ adduser --disabled-password --disabled-login misskey
|
|||||||
#### 依存関係 :package:
|
#### 依存関係 :package:
|
||||||
* **[Node.js](https://nodejs.org/en/)**
|
* **[Node.js](https://nodejs.org/en/)**
|
||||||
* **[MongoDB](https://www.mongodb.com/)** (3.6以上)
|
* **[MongoDB](https://www.mongodb.com/)** (3.6以上)
|
||||||
* **[Redis](https://redis.io/)**
|
|
||||||
|
|
||||||
##### オプション
|
##### オプション
|
||||||
* [Elasticsearch](https://www.elastic.co/) - 検索機能を向上させるために用います。
|
* [Redis](https://redis.io/)
|
||||||
|
* Redisはオプションですが、インストールすることを強く推奨します。
|
||||||
|
* インストールしなくていいのは、あなたのインスタンスが自分専用のときだけとお考えください。
|
||||||
|
* 具体的には、Redisをインストールしないと、次の事が出来なくなります:
|
||||||
|
* Misskeyプロセスを複数起動しての負荷分散
|
||||||
|
* レートリミット
|
||||||
|
* Twitter連携
|
||||||
|
* [Elasticsearch](https://www.elastic.co/)
|
||||||
|
* 検索機能を有効にするためにはインストールが必要です。
|
||||||
|
|
||||||
*3.* MongoDBの設定
|
*3.* MongoDBの設定
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
@@ -83,17 +83,17 @@ common:
|
|||||||
pudding: "Pudding"
|
pudding: "Pudding"
|
||||||
note-visibility:
|
note-visibility:
|
||||||
public: "Public"
|
public: "Public"
|
||||||
home: "Accueil"
|
home: "Principal"
|
||||||
home-desc: "Publier sur le fil local uniquement"
|
home-desc: "Publier sur le fil principal uniquement"
|
||||||
followers: "Abonnés·es"
|
followers: "Abonnés·es"
|
||||||
followers-desc: "Publier à vos abonnés·es uniquement"
|
followers-desc: "Publier à vos abonnés·es uniquement"
|
||||||
specified: "Direct"
|
specified: "Direct"
|
||||||
specified-desc: "Publier aux utilisateurs·trices mentionnés·es"
|
specified-desc: "Publier uniquement aux utilisateurs·rices mentionnés·es"
|
||||||
private: "Privé"
|
private: "Privé"
|
||||||
note-placeholders:
|
note-placeholders:
|
||||||
a: "Que faites-vous maintenant ?"
|
a: "Que faites-vous maintenant ?"
|
||||||
b: "Quoi de neuf ?"
|
b: "Quoi de neuf ?"
|
||||||
c: "Qu'avez-vous en tête ?"
|
c: "Qu’avez-vous en tête ?"
|
||||||
d: "Désirez-vous publier quelques mots ?"
|
d: "Désirez-vous publier quelques mots ?"
|
||||||
e: "Écrivez ici"
|
e: "Écrivez ici"
|
||||||
f: "En attente de vos écrits"
|
f: "En attente de vos écrits"
|
||||||
@@ -103,7 +103,7 @@ common:
|
|||||||
ok: "OK"
|
ok: "OK"
|
||||||
update-available-title: "Mise à jour disponible"
|
update-available-title: "Mise à jour disponible"
|
||||||
update-available: "Une nouvelle version de Misskey est disponible ({newer}, version actuelle: {current}). Veuillez recharger la page pour appliquer la mise à jour."
|
update-available: "Une nouvelle version de Misskey est disponible ({newer}, version actuelle: {current}). Veuillez recharger la page pour appliquer la mise à jour."
|
||||||
my-token-regenerated: "Votre token vient d'être généré, vous allez maintenant être déconnecté."
|
my-token-regenerated: "Votre jeton vient d’être généré, vous allez maintenant être déconnecté."
|
||||||
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
|
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
|
||||||
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
|
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
|
||||||
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
|
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
|
||||||
@@ -120,7 +120,7 @@ common:
|
|||||||
my-turn: "C’est votre tour"
|
my-turn: "C’est votre tour"
|
||||||
opponent-turn: "Tour de l’adversaire"
|
opponent-turn: "Tour de l’adversaire"
|
||||||
turn-of: "C’est le tour de {}"
|
turn-of: "C’est le tour de {}"
|
||||||
past-turn-of: "C'est au tour de {}"
|
past-turn-of: "C’est au tour de {}"
|
||||||
won: "{} a gagné"
|
won: "{} a gagné"
|
||||||
black: "Noirs"
|
black: "Noirs"
|
||||||
white: "Blancs"
|
white: "Blancs"
|
||||||
@@ -267,8 +267,8 @@ common/views/components/media-banner.vue:
|
|||||||
common/views/components/theme.vue:
|
common/views/components/theme.vue:
|
||||||
light-theme: "非ダークモード時に使用するテーマ"
|
light-theme: "非ダークモード時に使用するテーマ"
|
||||||
dark-theme: "ダークモード時に使用するテーマ"
|
dark-theme: "ダークモード時に使用するテーマ"
|
||||||
light-themes: "明るいテーマ"
|
light-themes: "Thème clair"
|
||||||
dark-themes: "暗いテーマ"
|
dark-themes: "Thème sombre"
|
||||||
install-a-theme: "Installer un thème"
|
install-a-theme: "Installer un thème"
|
||||||
theme-code: "Code du thème"
|
theme-code: "Code du thème"
|
||||||
install: "Installation"
|
install: "Installation"
|
||||||
@@ -286,16 +286,16 @@ common/views/components/theme.vue:
|
|||||||
invalid-theme: "Thème n’est pas valide."
|
invalid-theme: "Thème n’est pas valide."
|
||||||
already-installed: "Le thème est déjà installé."
|
already-installed: "Le thème est déjà installé."
|
||||||
saved: "enregistré"
|
saved: "enregistré"
|
||||||
manage-themes: "テーマの管理"
|
manage-themes: "Gestion des thèmes"
|
||||||
builtin-themes: "標準テーマ"
|
builtin-themes: "Thèmes standards"
|
||||||
my-themes: "マイテーマ"
|
my-themes: "Mes thèmes"
|
||||||
installed-themes: "Thèmes installés"
|
installed-themes: "Thèmes installés"
|
||||||
select-theme: "Veuillez sélectionner un thème"
|
select-theme: "Veuillez sélectionner un thème"
|
||||||
uninstall: "Désinstaller"
|
uninstall: "Désinstaller"
|
||||||
uninstalled: "« {} » a été désinstallé"
|
uninstalled: "« {} » a été désinstallé"
|
||||||
author: "Auteur"
|
author: "Auteur"
|
||||||
desc: "Description"
|
desc: "Description"
|
||||||
export: "エクスポート"
|
export: "Exporter"
|
||||||
import: "Importer"
|
import: "Importer"
|
||||||
import-by-code: "Ou coller du code"
|
import-by-code: "Ou coller du code"
|
||||||
theme-name-required: "Nom du thème est obligatoire."
|
theme-name-required: "Nom du thème est obligatoire."
|
||||||
@@ -329,8 +329,8 @@ common/views/components/nav.vue:
|
|||||||
wiki: "Wiki"
|
wiki: "Wiki"
|
||||||
donors: "Donateur·rice·s"
|
donors: "Donateur·rice·s"
|
||||||
repository: "Dépôt"
|
repository: "Dépôt"
|
||||||
develop: "Développeur·se·s"
|
develop: "Développeurs"
|
||||||
feedback: "Remarques"
|
feedback: "Suggestions"
|
||||||
common/views/components/note-menu.vue:
|
common/views/components/note-menu.vue:
|
||||||
detail: "Détails"
|
detail: "Détails"
|
||||||
copy-link: "Copier le lien"
|
copy-link: "Copier le lien"
|
||||||
@@ -410,10 +410,10 @@ common/views/components/visibility-chooser.vue:
|
|||||||
followers: "Abonné·e·s"
|
followers: "Abonné·e·s"
|
||||||
followers-desc: "Publier à vos abonné·e·s uniquement"
|
followers-desc: "Publier à vos abonné·e·s uniquement"
|
||||||
specified: "Direct"
|
specified: "Direct"
|
||||||
specified-desc: "Publier aux utilisateur·rice·s mentionné·e·s"
|
specified-desc: "Publier uniquement aux utilisateurs·rices mentionné·e·s"
|
||||||
private: "Privé"
|
private: "Privé"
|
||||||
common/views/components/trends.vue:
|
common/views/components/trends.vue:
|
||||||
count: "{} utilisateurs·trices mentionnés·es"
|
count: "{} utilisateurs·rices mentionnés·es"
|
||||||
empty: "Aucune tendance"
|
empty: "Aucune tendance"
|
||||||
common/views/widgets/broadcast.vue:
|
common/views/widgets/broadcast.vue:
|
||||||
fetching: "Récupération"
|
fetching: "Récupération"
|
||||||
@@ -514,7 +514,7 @@ desktop/views/components/charts.vue:
|
|||||||
notes: "投稿の増減 (統合)"
|
notes: "投稿の増減 (統合)"
|
||||||
local-notes: "投稿の増減 (ローカル)"
|
local-notes: "投稿の増減 (ローカル)"
|
||||||
remote-notes: "投稿の増減 (リモート)"
|
remote-notes: "投稿の増減 (リモート)"
|
||||||
notes-total: "投稿の積算"
|
notes-total: "Total des notes"
|
||||||
users: "Nombre d’utilisateurs·trices : augmentation/diminution"
|
users: "Nombre d’utilisateurs·trices : augmentation/diminution"
|
||||||
users-total: "ユーザーの積算"
|
users-total: "ユーザーの積算"
|
||||||
drive: "ドライブ使用量の増減"
|
drive: "ドライブ使用量の増減"
|
||||||
@@ -858,7 +858,7 @@ desktop/views/components/timeline.vue:
|
|||||||
list-name: "Nom de la liste"
|
list-name: "Nom de la liste"
|
||||||
desktop/views/components/ui.header.vue:
|
desktop/views/components/ui.header.vue:
|
||||||
welcome-back: "Content de vous revoir !"
|
welcome-back: "Content de vous revoir !"
|
||||||
adjective: "さん"
|
adjective: "M."
|
||||||
desktop/views/components/ui.header.account.vue:
|
desktop/views/components/ui.header.account.vue:
|
||||||
profile: "Votre profil"
|
profile: "Votre profil"
|
||||||
drive: "Drive"
|
drive: "Drive"
|
||||||
@@ -911,9 +911,9 @@ desktop/views/pages/admin/admin.vue:
|
|||||||
desktop/views/pages/admin/admin.dashboard.vue:
|
desktop/views/pages/admin/admin.dashboard.vue:
|
||||||
dashboard: "Tableau de bord"
|
dashboard: "Tableau de bord"
|
||||||
all-users: "Toutes les utilisateurrices"
|
all-users: "Toutes les utilisateurrices"
|
||||||
original-users: "Utilisateurrices sur cette instance"
|
original-users: "Utilisateur·rice·s sur cette instance"
|
||||||
all-notes: "Toutes les publications"
|
all-notes: "Toutes les publications"
|
||||||
original-notes: "Publication sur cette instance"
|
original-notes: "Publications sur cette instance"
|
||||||
invite: "Invitation"
|
invite: "Invitation"
|
||||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||||
suspend-user: "Suspendre un·e utilisateur·rice"
|
suspend-user: "Suspendre un·e utilisateur·rice"
|
||||||
@@ -941,9 +941,9 @@ desktop/views/pages/deck/deck.note.vue:
|
|||||||
deleted: "cette publication a été supprimée"
|
deleted: "cette publication a été supprimée"
|
||||||
desktop/views/pages/stats/stats.vue:
|
desktop/views/pages/stats/stats.vue:
|
||||||
all-users: "Toutes les utilisateurrices"
|
all-users: "Toutes les utilisateurrices"
|
||||||
original-users: "Utilisateurrices sur cette instance"
|
original-users: "Utilisateur·rice·s sur cette instance"
|
||||||
all-notes: "Toutes les publications"
|
all-notes: "Toutes les publications"
|
||||||
original-notes: "Publication sur cette instance"
|
original-notes: "Publications sur cette instance"
|
||||||
desktop/views/pages/welcome.vue:
|
desktop/views/pages/welcome.vue:
|
||||||
about: "à propos"
|
about: "à propos"
|
||||||
gotit: "J'ai compris !"
|
gotit: "J'ai compris !"
|
||||||
@@ -986,13 +986,13 @@ desktop/views/pages/user/user.followers-you-know.vue:
|
|||||||
loading: "Chargement en cours"
|
loading: "Chargement en cours"
|
||||||
no-users: "Pas d'utilisateurs"
|
no-users: "Pas d'utilisateurs"
|
||||||
desktop/views/pages/user/user.friends.vue:
|
desktop/views/pages/user/user.friends.vue:
|
||||||
title: "Personnes qui répondent le plus"
|
title: "Mentions fréquentes"
|
||||||
loading: "Chargement en cours"
|
loading: "Chargement en cours"
|
||||||
no-users: "Pas d'utilisateurs"
|
no-users: "Pas d'utilisateurs"
|
||||||
desktop/views/pages/user/user.vue:
|
desktop/views/pages/user/user.vue:
|
||||||
is-suspended: "Ce compte a été suspendu."
|
is-suspended: "Ce compte a été suspendu."
|
||||||
is-remote: "Cet utilisateur n'est pas un utilisateur de Misskey. Certaines informations peuvent être erronées"
|
is-remote: "Cet utilisateur n'est pas un utilisateur Misskey. Certaines informations peuvent ne pas refléter ce profil dans sa totalité."
|
||||||
view-remote: "Voir les informations détaillées"
|
view-remote: "Consulter le profil complet"
|
||||||
desktop/views/pages/user/user.home.vue:
|
desktop/views/pages/user/user.home.vue:
|
||||||
last-used-at: "Last used at"
|
last-used-at: "Last used at"
|
||||||
desktop/views/pages/user/user.photos.vue:
|
desktop/views/pages/user/user.photos.vue:
|
||||||
@@ -1000,7 +1000,7 @@ desktop/views/pages/user/user.photos.vue:
|
|||||||
loading: "Chargement en cours"
|
loading: "Chargement en cours"
|
||||||
no-photos: "Pas de photos"
|
no-photos: "Pas de photos"
|
||||||
desktop/views/pages/user/user.profile.vue:
|
desktop/views/pages/user/user.profile.vue:
|
||||||
follows-you: "Vous suis"
|
follows-you: "Vous suit"
|
||||||
stalk: "Traquer"
|
stalk: "Traquer"
|
||||||
stalking: "ストーキングしています"
|
stalking: "ストーキングしています"
|
||||||
unstalk: "ストーク解除"
|
unstalk: "ストーク解除"
|
||||||
@@ -1171,7 +1171,7 @@ mobile/views/pages/drive.vue:
|
|||||||
drive: "Drive"
|
drive: "Drive"
|
||||||
more: "Afficher plus ..."
|
more: "Afficher plus ..."
|
||||||
mobile/views/pages/signup.vue:
|
mobile/views/pages/signup.vue:
|
||||||
lets-start: "Commençons ! 📦"
|
lets-start: "Votre compte est prêt ! 📦"
|
||||||
mobile/views/pages/followers.vue:
|
mobile/views/pages/followers.vue:
|
||||||
followers-of: "Abonné·e·s de {}"
|
followers-of: "Abonné·e·s de {}"
|
||||||
mobile/views/pages/following.vue:
|
mobile/views/pages/following.vue:
|
||||||
@@ -1286,7 +1286,7 @@ mobile/views/pages/settings.vue:
|
|||||||
sound: "Sons"
|
sound: "Sons"
|
||||||
enable-sounds: "Activer les sons"
|
enable-sounds: "Activer les sons"
|
||||||
mobile/views/pages/user.vue:
|
mobile/views/pages/user.vue:
|
||||||
follows-you: "vous suit"
|
follows-you: "Vous suit"
|
||||||
following: "Abonnements"
|
following: "Abonnements"
|
||||||
followers: "Abonné·e·s"
|
followers: "Abonné·e·s"
|
||||||
notes: "Notes"
|
notes: "Notes"
|
||||||
@@ -1294,8 +1294,8 @@ mobile/views/pages/user.vue:
|
|||||||
timeline: "Fil d'actualité"
|
timeline: "Fil d'actualité"
|
||||||
media: "Media"
|
media: "Media"
|
||||||
is-suspended: "This account has been suspended."
|
is-suspended: "This account has been suspended."
|
||||||
is-remote: "Cet utilisateur n'est pas un utilisateur de Misskey. Certaines informations peuvent être erronées "
|
is-remote: "Ceci est le profil d’un utilisateur·rice distant·e. Certaines informations peuvent ne pas refléter ce profil dans sa totalité."
|
||||||
view-remote: "Voir les informations détaillées"
|
view-remote: "Consulter son profil complet"
|
||||||
mobile/views/pages/user/home.vue:
|
mobile/views/pages/user/home.vue:
|
||||||
recent-notes: "Notes récentes"
|
recent-notes: "Notes récentes"
|
||||||
images: "Images"
|
images: "Images"
|
||||||
@@ -1319,7 +1319,7 @@ mobile/views/pages/user/home.photos.vue:
|
|||||||
no-photos: "Pas de photos"
|
no-photos: "Pas de photos"
|
||||||
docs:
|
docs:
|
||||||
edit-this-page-on-github: "Vous avez trouvé une erreur ou vous voulez contribuer à la documentation?"
|
edit-this-page-on-github: "Vous avez trouvé une erreur ou vous voulez contribuer à la documentation?"
|
||||||
edit-this-page-on-github-link: "Modifiez cette page sur github!"
|
edit-this-page-on-github-link: "Éditez cette page sur Github !"
|
||||||
api:
|
api:
|
||||||
entities:
|
entities:
|
||||||
properties: "Propriétés"
|
properties: "Propriétés"
|
||||||
|
16
package.json
16
package.json
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "10.5.0",
|
"version": "10.8.0",
|
||||||
"clientVersion": "1.0.10405",
|
"clientVersion": "1.0.10417",
|
||||||
"codename": "nighthike",
|
"codename": "nighthike",
|
||||||
"main": "./built/index.js",
|
"main": "./built/index.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
"@types/koa-bodyparser": "5.0.1",
|
"@types/koa-bodyparser": "5.0.1",
|
||||||
"@types/koa-compress": "2.0.8",
|
"@types/koa-compress": "2.0.8",
|
||||||
"@types/koa-favicon": "2.0.19",
|
"@types/koa-favicon": "2.0.19",
|
||||||
"@types/koa-logger": "3.1.0",
|
"@types/koa-logger": "3.1.1",
|
||||||
"@types/koa-mount": "3.0.1",
|
"@types/koa-mount": "3.0.1",
|
||||||
"@types/koa-multer": "1.0.0",
|
"@types/koa-multer": "1.0.0",
|
||||||
"@types/koa-router": "7.0.32",
|
"@types/koa-router": "7.0.32",
|
||||||
@@ -58,9 +58,9 @@
|
|||||||
"@types/minio": "7.0.0",
|
"@types/minio": "7.0.0",
|
||||||
"@types/mkdirp": "0.5.2",
|
"@types/mkdirp": "0.5.2",
|
||||||
"@types/mocha": "5.2.3",
|
"@types/mocha": "5.2.3",
|
||||||
"@types/mongodb": "3.1.11",
|
"@types/mongodb": "3.1.12",
|
||||||
"@types/ms": "0.7.30",
|
"@types/ms": "0.7.30",
|
||||||
"@types/node": "10.11.5",
|
"@types/node": "10.11.7",
|
||||||
"@types/portscanner": "2.1.0",
|
"@types/portscanner": "2.1.0",
|
||||||
"@types/pug": "2.0.4",
|
"@types/pug": "2.0.4",
|
||||||
"@types/qrcode": "1.3.0",
|
"@types/qrcode": "1.3.0",
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
"@types/tinycolor2": "1.4.1",
|
"@types/tinycolor2": "1.4.1",
|
||||||
"@types/tmp": "0.0.33",
|
"@types/tmp": "0.0.33",
|
||||||
"@types/uuid": "3.4.4",
|
"@types/uuid": "3.4.4",
|
||||||
"@types/webpack": "4.4.15",
|
"@types/webpack": "4.4.16",
|
||||||
"@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",
|
||||||
@@ -206,12 +206,12 @@
|
|||||||
"typescript": "2.9.2",
|
"typescript": "2.9.2",
|
||||||
"typescript-eslint-parser": "20.0.0",
|
"typescript-eslint-parser": "20.0.0",
|
||||||
"uglify-es": "3.3.9",
|
"uglify-es": "3.3.9",
|
||||||
"url-loader": "1.1.1",
|
"url-loader": "1.1.2",
|
||||||
"uuid": "3.3.2",
|
"uuid": "3.3.2",
|
||||||
"v-animate-css": "0.0.2",
|
"v-animate-css": "0.0.2",
|
||||||
"vue": "2.5.17",
|
"vue": "2.5.17",
|
||||||
"vue-chartjs": "3.4.0",
|
"vue-chartjs": "3.4.0",
|
||||||
"vue-color": "2.6.0",
|
"vue-color": "2.7.0",
|
||||||
"vue-cropperjs": "2.2.2",
|
"vue-cropperjs": "2.2.2",
|
||||||
"vue-js-modal": "1.3.26",
|
"vue-js-modal": "1.3.26",
|
||||||
"vue-json-tree-view": "2.1.4",
|
"vue-json-tree-view": "2.1.4",
|
||||||
|
@@ -131,15 +131,28 @@ pre
|
|||||||
[data-fa]
|
[data-fa]
|
||||||
display inline-block
|
display inline-block
|
||||||
|
|
||||||
|
.swal2-container
|
||||||
|
z-index 10000 !important
|
||||||
|
|
||||||
|
&.swal2-shown
|
||||||
|
background-color rgba(0, 0, 0, 0.5) !important
|
||||||
|
|
||||||
.swal2-popup
|
.swal2-popup
|
||||||
background var(--face) !important
|
background var(--face) !important
|
||||||
|
|
||||||
.swal-icon-only
|
.swal2-content
|
||||||
width 180px !important
|
color var(--text) !important
|
||||||
|
|
||||||
> .swal2-header
|
.swal2-confirm
|
||||||
> .swal2-icon
|
background-color var(--primary) !important
|
||||||
margin 1.25em auto 1.875em
|
border-left-color var(--primary) !important
|
||||||
|
border-right-color var(--primary) !important
|
||||||
|
color var(--primaryForeground) !important
|
||||||
|
|
||||||
> .swal2-title
|
&:hover
|
||||||
display none
|
background-image none !important
|
||||||
|
background-color var(--primaryDarken5) !important
|
||||||
|
|
||||||
|
&:active
|
||||||
|
background-image none !important
|
||||||
|
background-color var(--primaryDarken5) !important
|
||||||
|
@@ -11,6 +11,7 @@ export default class Stream extends EventEmitter {
|
|||||||
private stream: ReconnectingWebsocket;
|
private stream: ReconnectingWebsocket;
|
||||||
private state: string;
|
private state: string;
|
||||||
private buffer: any[];
|
private buffer: any[];
|
||||||
|
private sharedConnectionPools: Pool[] = [];
|
||||||
private sharedConnections: SharedConnection[] = [];
|
private sharedConnections: SharedConnection[] = [];
|
||||||
private nonSharedConnections: NonSharedConnection[] = [];
|
private nonSharedConnections: NonSharedConnection[] = [];
|
||||||
|
|
||||||
@@ -28,26 +29,27 @@ export default class Stream extends EventEmitter {
|
|||||||
this.stream.addEventListener('message', this.onMessage);
|
this.stream.addEventListener('message', this.onMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public useSharedConnection = (channel: string): SharedConnection => {
|
@autobind
|
||||||
const existConnection = this.sharedConnections.find(c => c.channel === channel);
|
public useSharedConnection(channel: string): SharedConnection {
|
||||||
|
let pool = this.sharedConnectionPools.find(p => p.channel === channel);
|
||||||
|
|
||||||
if (existConnection) {
|
if (pool == null) {
|
||||||
existConnection.use();
|
pool = new Pool(this, channel);
|
||||||
return existConnection;
|
this.sharedConnectionPools.push(pool);
|
||||||
} else {
|
|
||||||
const connection = new SharedConnection(this, channel);
|
|
||||||
connection.use();
|
|
||||||
this.sharedConnections.push(connection);
|
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const connection = new SharedConnection(this, channel, pool);
|
||||||
|
this.sharedConnections.push(connection);
|
||||||
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
public removeSharedConnection(connection: SharedConnection) {
|
public removeSharedConnection(connection: SharedConnection) {
|
||||||
this.sharedConnections = this.sharedConnections.filter(c => c.id !== connection.id);
|
this.sharedConnections = this.sharedConnections.filter(c => c !== connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public connectToChannel = (channel: string, params?: any): NonSharedConnection => {
|
@autobind
|
||||||
|
public connectToChannel(channel: string, params?: any): NonSharedConnection {
|
||||||
const connection = new NonSharedConnection(this, channel, params);
|
const connection = new NonSharedConnection(this, channel, params);
|
||||||
this.nonSharedConnections.push(connection);
|
this.nonSharedConnections.push(connection);
|
||||||
return connection;
|
return connection;
|
||||||
@@ -55,7 +57,7 @@ export default class Stream extends EventEmitter {
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
public disconnectToChannel(connection: NonSharedConnection) {
|
public disconnectToChannel(connection: NonSharedConnection) {
|
||||||
this.nonSharedConnections = this.nonSharedConnections.filter(c => c.id !== connection.id);
|
this.nonSharedConnections = this.nonSharedConnections.filter(c => c !== connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,8 +79,8 @@ export default class Stream extends EventEmitter {
|
|||||||
|
|
||||||
// チャンネル再接続
|
// チャンネル再接続
|
||||||
if (isReconnect) {
|
if (isReconnect) {
|
||||||
this.sharedConnections.forEach(c => {
|
this.sharedConnectionPools.forEach(p => {
|
||||||
c.connect();
|
p.connect();
|
||||||
});
|
});
|
||||||
this.nonSharedConnections.forEach(c => {
|
this.nonSharedConnections.forEach(c => {
|
||||||
c.connect();
|
c.connect();
|
||||||
@@ -104,8 +106,18 @@ export default class Stream extends EventEmitter {
|
|||||||
|
|
||||||
if (type == 'channel') {
|
if (type == 'channel') {
|
||||||
const id = body.id;
|
const id = body.id;
|
||||||
const connection = this.sharedConnections.find(c => c.id === id) || this.nonSharedConnections.find(c => c.id === id);
|
|
||||||
connection.emit(body.type, body.body);
|
let connections: Connection[];
|
||||||
|
|
||||||
|
connections = this.sharedConnections.filter(c => c.id === id);
|
||||||
|
|
||||||
|
if (connections.length === 0) {
|
||||||
|
connections = [this.nonSharedConnections.find(c => c.id === id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
connections.filter(c => c != null).forEach(c => {
|
||||||
|
c.emit(body.type, body.body);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.emit(type, body);
|
this.emit(type, body);
|
||||||
}
|
}
|
||||||
@@ -140,19 +152,131 @@ export default class Stream extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Connection extends EventEmitter {
|
class Pool {
|
||||||
public channel: string;
|
public channel: string;
|
||||||
public id: string;
|
public id: string;
|
||||||
protected params: any;
|
|
||||||
protected stream: Stream;
|
protected stream: Stream;
|
||||||
|
private users = 0;
|
||||||
|
private disposeTimerId: any;
|
||||||
|
private isConnected = false;
|
||||||
|
|
||||||
constructor(stream: Stream, channel: string, params?: any) {
|
constructor(stream: Stream, channel: string) {
|
||||||
|
this.channel = channel;
|
||||||
|
this.stream = stream;
|
||||||
|
|
||||||
|
this.id = Math.random().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public inc() {
|
||||||
|
if (this.users === 0 && !this.isConnected) {
|
||||||
|
this.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.users++;
|
||||||
|
|
||||||
|
// タイマー解除
|
||||||
|
if (this.disposeTimerId) {
|
||||||
|
clearTimeout(this.disposeTimerId);
|
||||||
|
this.disposeTimerId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public dec() {
|
||||||
|
this.users--;
|
||||||
|
|
||||||
|
// そのコネクションの利用者が誰もいなくなったら
|
||||||
|
if (this.users === 0) {
|
||||||
|
// また直ぐに再利用される可能性があるので、一定時間待ち、
|
||||||
|
// 新たな利用者が現れなければコネクションを切断する
|
||||||
|
this.disposeTimerId = setTimeout(() => {
|
||||||
|
this.disconnect();
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public connect() {
|
||||||
|
this.isConnected = true;
|
||||||
|
this.stream.send('connect', {
|
||||||
|
channel: this.channel,
|
||||||
|
id: this.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
private disconnect() {
|
||||||
|
this.isConnected = false;
|
||||||
|
this.disposeTimerId = null;
|
||||||
|
this.stream.send('disconnect', { id: this.id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Connection extends EventEmitter {
|
||||||
|
public channel: string;
|
||||||
|
protected stream: Stream;
|
||||||
|
public abstract id: string;
|
||||||
|
|
||||||
|
constructor(stream: Stream, channel: string) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public send(id: string, typeOrPayload, payload?) {
|
||||||
|
const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
|
||||||
|
const body = payload === undefined ? typeOrPayload.body : payload;
|
||||||
|
|
||||||
|
this.stream.send('ch', {
|
||||||
|
id: id,
|
||||||
|
type: type,
|
||||||
|
body: body
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SharedConnection extends Connection {
|
||||||
|
private pool: Pool;
|
||||||
|
|
||||||
|
public get id(): string {
|
||||||
|
return this.pool.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(stream: Stream, channel: string, pool: Pool) {
|
||||||
|
super(stream, channel);
|
||||||
|
|
||||||
|
this.pool = pool;
|
||||||
|
this.pool.inc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public send(typeOrPayload, payload?) {
|
||||||
|
super.send(this.pool.id, typeOrPayload, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public dispose() {
|
||||||
|
this.pool.dec();
|
||||||
|
this.removeAllListeners();
|
||||||
|
this.stream.removeSharedConnection(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NonSharedConnection extends Connection {
|
||||||
|
public id: string;
|
||||||
|
protected params: any;
|
||||||
|
|
||||||
|
constructor(stream: Stream, channel: string, params?: any) {
|
||||||
|
super(stream, channel);
|
||||||
|
|
||||||
this.params = params;
|
this.params = params;
|
||||||
this.id = Math.random().toString();
|
this.id = Math.random().toString();
|
||||||
|
|
||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,59 +291,7 @@ abstract class Connection extends EventEmitter {
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
public send(typeOrPayload, payload?) {
|
public send(typeOrPayload, payload?) {
|
||||||
const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
|
super.send(this.id, typeOrPayload, payload);
|
||||||
const body = payload === undefined ? typeOrPayload.body : payload;
|
|
||||||
|
|
||||||
this.stream.send('ch', {
|
|
||||||
id: this.id,
|
|
||||||
type: type,
|
|
||||||
body: body
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract dispose(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SharedConnection extends Connection {
|
|
||||||
private users = 0;
|
|
||||||
private disposeTimerId: any;
|
|
||||||
|
|
||||||
constructor(stream: Stream, channel: string) {
|
|
||||||
super(stream, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@autobind
|
|
||||||
public use() {
|
|
||||||
this.users++;
|
|
||||||
|
|
||||||
// タイマー解除
|
|
||||||
if (this.disposeTimerId) {
|
|
||||||
clearTimeout(this.disposeTimerId);
|
|
||||||
this.disposeTimerId = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@autobind
|
|
||||||
public dispose() {
|
|
||||||
this.users--;
|
|
||||||
|
|
||||||
// そのコネクションの利用者が誰もいなくなったら
|
|
||||||
if (this.users === 0) {
|
|
||||||
// また直ぐに再利用される可能性があるので、一定時間待ち、
|
|
||||||
// 新たな利用者が現れなければコネクションを切断する
|
|
||||||
this.disposeTimerId = setTimeout(() => {
|
|
||||||
this.disposeTimerId = null;
|
|
||||||
this.removeAllListeners();
|
|
||||||
this.stream.send('disconnect', { id: this.id });
|
|
||||||
this.stream.removeSharedConnection(this);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NonSharedConnection extends Connection {
|
|
||||||
constructor(stream: Stream, channel: string, params?: any) {
|
|
||||||
super(stream, channel, params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
|
@@ -71,7 +71,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.connection =((this as any).os.stream.connectToChannel('messaging', { otherparty: this.user.id });
|
this.connection = (this as any).os.stream.connectToChannel('messaging', { otherparty: this.user.id });
|
||||||
|
|
||||||
this.connection.on('message', this.onMessage);
|
this.connection.on('message', this.onMessage);
|
||||||
this.connection.on('read', this.onRead);
|
this.connection.on('read', this.onRead);
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { url } from '../../../config';
|
import { url } from '../../../config';
|
||||||
import copyToClipboard from '../../../common/scripts/copy-to-clipboard';
|
import copyToClipboard from '../../../common/scripts/copy-to-clipboard';
|
||||||
|
import Ok from './ok.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: ['note', 'source', 'compact'],
|
props: ['note', 'source', 'compact'],
|
||||||
@@ -78,6 +79,7 @@ export default Vue.extend({
|
|||||||
(this as any).api('i/pin', {
|
(this as any).api('i/pin', {
|
||||||
noteId: this.note.id
|
noteId: this.note.id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
(this as any).os.new(Ok);
|
||||||
this.destroyDom();
|
this.destroyDom();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -103,12 +105,7 @@ export default Vue.extend({
|
|||||||
(this as any).api('notes/favorites/create', {
|
(this as any).api('notes/favorites/create', {
|
||||||
noteId: this.note.id
|
noteId: this.note.id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$swal({
|
(this as any).os.new(Ok);
|
||||||
type: 'success',
|
|
||||||
showConfirmButton: false,
|
|
||||||
timer: 1250,
|
|
||||||
customClass: 'swal-icon-only'
|
|
||||||
});
|
|
||||||
this.destroyDom();
|
this.destroyDom();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
175
src/client/app/common/views/components/ok.vue
Normal file
175
src/client/app/common/views/components/ok.vue
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
<template>
|
||||||
|
<div class="yvbkymdqeusiqucuuloahhiqflzinufs">
|
||||||
|
<div class="bg" ref="bg"></div>
|
||||||
|
<div class="body" ref="body">
|
||||||
|
<div class="icon">
|
||||||
|
<div class="circle left"></div>
|
||||||
|
<span class="check tip"></span>
|
||||||
|
<span class="check long"></span>
|
||||||
|
<div class="ring"></div>
|
||||||
|
<div class="fix"></div>
|
||||||
|
<div class="circle right"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import * as anime from 'animejs';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
anime({
|
||||||
|
targets: this.$refs.bg,
|
||||||
|
opacity: 1,
|
||||||
|
duration: 300,
|
||||||
|
easing: 'linear'
|
||||||
|
});
|
||||||
|
|
||||||
|
anime({
|
||||||
|
targets: this.$refs.body,
|
||||||
|
opacity: 1,
|
||||||
|
scale: [1.2, 1],
|
||||||
|
duration: 300,
|
||||||
|
easing: [0, 0.5, 0.5, 1]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
anime({
|
||||||
|
targets: this.$refs.bg,
|
||||||
|
opacity: 0,
|
||||||
|
duration: 300,
|
||||||
|
easing: 'linear'
|
||||||
|
});
|
||||||
|
|
||||||
|
anime({
|
||||||
|
targets: this.$refs.body,
|
||||||
|
opacity: 0,
|
||||||
|
scale: 0.8,
|
||||||
|
duration: 300,
|
||||||
|
easing: [0.5, 0, 1, 0.5],
|
||||||
|
complete: () => this.destroyDom()
|
||||||
|
});
|
||||||
|
}, 1250);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.yvbkymdqeusiqucuuloahhiqflzinufs
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
|
> .bg
|
||||||
|
display block
|
||||||
|
position fixed
|
||||||
|
z-index 10000
|
||||||
|
top 0
|
||||||
|
left 0
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
background rgba(#000, 0.7)
|
||||||
|
opacity 0
|
||||||
|
|
||||||
|
> .body
|
||||||
|
position fixed
|
||||||
|
z-index 10000
|
||||||
|
top 0
|
||||||
|
right 0
|
||||||
|
left 0
|
||||||
|
bottom 0
|
||||||
|
margin auto
|
||||||
|
width 150px
|
||||||
|
height 150px
|
||||||
|
background var(--face)
|
||||||
|
border-radius 8px
|
||||||
|
opacity 0
|
||||||
|
|
||||||
|
> .icon
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
position absolute
|
||||||
|
top 0
|
||||||
|
right 0
|
||||||
|
left 0
|
||||||
|
bottom 0
|
||||||
|
width 5em
|
||||||
|
height 5em
|
||||||
|
margin auto
|
||||||
|
border .25em solid transparent
|
||||||
|
border-radius 50%
|
||||||
|
line-height 5em
|
||||||
|
cursor default
|
||||||
|
box-sizing content-box
|
||||||
|
user-select none
|
||||||
|
zoom normal
|
||||||
|
border-color #a5dc86
|
||||||
|
|
||||||
|
> .circle
|
||||||
|
position absolute
|
||||||
|
width 3.75em
|
||||||
|
height 7.5em
|
||||||
|
transform rotate(45deg)
|
||||||
|
border-radius 50%
|
||||||
|
background var(--face)
|
||||||
|
|
||||||
|
&.left
|
||||||
|
top -.4375em
|
||||||
|
left -2.0635em
|
||||||
|
transform rotate(-45deg)
|
||||||
|
transform-origin 3.75em 3.75em
|
||||||
|
border-radius 7.5em 0 0 7.5em
|
||||||
|
|
||||||
|
&.right
|
||||||
|
top -.6875em
|
||||||
|
left 1.875em
|
||||||
|
transform rotate(-45deg)
|
||||||
|
transform-origin 0 3.75em
|
||||||
|
border-radius 0 7.5em 7.5em 0
|
||||||
|
animation swal2-rotate-success-circular-line 4.25s ease-in
|
||||||
|
|
||||||
|
> .check
|
||||||
|
display block
|
||||||
|
position absolute
|
||||||
|
height .3125em
|
||||||
|
border-radius .125em
|
||||||
|
background-color #a5dc86
|
||||||
|
z-index 2
|
||||||
|
|
||||||
|
&.tip
|
||||||
|
top 2.875em
|
||||||
|
left .875em
|
||||||
|
width 1.5625em
|
||||||
|
transform rotate(45deg)
|
||||||
|
animation swal2-animate-success-line-tip .75s
|
||||||
|
|
||||||
|
&.long
|
||||||
|
top 2.375em
|
||||||
|
right .5em
|
||||||
|
width 2.9375em
|
||||||
|
transform rotate(-45deg)
|
||||||
|
animation swal2-animate-success-line-long .75s
|
||||||
|
|
||||||
|
> .fix
|
||||||
|
position absolute
|
||||||
|
top .5em
|
||||||
|
left 1.625em
|
||||||
|
width .4375em
|
||||||
|
height 5.625em
|
||||||
|
transform rotate(-45deg)
|
||||||
|
z-index 1
|
||||||
|
background var(--face)
|
||||||
|
|
||||||
|
> .ring
|
||||||
|
position absolute
|
||||||
|
top -.25em
|
||||||
|
left -.25em
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
border .25em solid rgba(165,220,134,.3)
|
||||||
|
border-radius 50%
|
||||||
|
z-index 2
|
||||||
|
box-sizing content-box
|
||||||
|
</style>
|
@@ -219,7 +219,10 @@ export default Vue.extend({
|
|||||||
try {
|
try {
|
||||||
theme = JSON5.parse(code);
|
theme = JSON5.parse(code);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert('%i18n:@invalid-theme%');
|
this.$swal({
|
||||||
|
type: 'error',
|
||||||
|
text: '%i18n:@invalid-theme%'
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,12 +232,18 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (theme.id == null) {
|
if (theme.id == null) {
|
||||||
alert('%i18n:@invalid-theme%');
|
this.$swal({
|
||||||
|
type: 'error',
|
||||||
|
text: '%i18n:@invalid-theme%'
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$store.state.device.themes.some(t => t.id == theme.id)) {
|
if (this.$store.state.device.themes.some(t => t.id == theme.id)) {
|
||||||
alert('%i18n:@already-installed%');
|
this.$swal({
|
||||||
|
type: 'info',
|
||||||
|
text: '%i18n:@already-installed%'
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +252,10 @@ export default Vue.extend({
|
|||||||
key: 'themes', value: themes
|
key: 'themes', value: themes
|
||||||
});
|
});
|
||||||
|
|
||||||
alert('%i18n:@installed%'.replace('{}', theme.name));
|
this.$swal({
|
||||||
|
type: 'success',
|
||||||
|
text: '%i18n:@installed%'.replace('{}', theme.name)
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
uninstall() {
|
uninstall() {
|
||||||
@@ -252,7 +264,11 @@ export default Vue.extend({
|
|||||||
this.$store.commit('device/set', {
|
this.$store.commit('device/set', {
|
||||||
key: 'themes', value: themes
|
key: 'themes', value: themes
|
||||||
});
|
});
|
||||||
alert('%i18n:@uninstalled%'.replace('{}', theme.name));
|
|
||||||
|
this.$swal({
|
||||||
|
type: 'info',
|
||||||
|
text: '%i18n:@uninstalled%'.replace('{}', theme.name)
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
import_() {
|
import_() {
|
||||||
@@ -284,16 +300,26 @@ export default Vue.extend({
|
|||||||
|
|
||||||
gen() {
|
gen() {
|
||||||
const theme = this.myTheme;
|
const theme = this.myTheme;
|
||||||
|
|
||||||
if (theme.name == null || theme.name.trim() == '') {
|
if (theme.name == null || theme.name.trim() == '') {
|
||||||
alert('%i18n:@theme-name-required%');
|
this.$swal({
|
||||||
|
type: 'warning',
|
||||||
|
text: '%i18n:@theme-name-required%'
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
theme.id = uuid();
|
theme.id = uuid();
|
||||||
|
|
||||||
const themes = this.$store.state.device.themes.concat(theme);
|
const themes = this.$store.state.device.themes.concat(theme);
|
||||||
this.$store.commit('device/set', {
|
this.$store.commit('device/set', {
|
||||||
key: 'themes', value: themes
|
key: 'themes', value: themes
|
||||||
});
|
});
|
||||||
alert('%i18n:@saved%');
|
|
||||||
|
this.$swal({
|
||||||
|
type: 'success',
|
||||||
|
text: '%i18n:@saved%'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -91,8 +91,6 @@ export default Vue.extend({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
|
|
||||||
|
|
||||||
.mk-dialog
|
.mk-dialog
|
||||||
> .bg
|
> .bg
|
||||||
display block
|
display block
|
||||||
|
@@ -170,7 +170,10 @@ export default Vue.extend({
|
|||||||
this.$store.state.i.bannerUrl = i.bannerUrl;
|
this.$store.state.i.bannerUrl = i.bannerUrl;
|
||||||
|
|
||||||
if (notify) {
|
if (notify) {
|
||||||
alert('%i18n:@saved%');
|
this.$swal({
|
||||||
|
type: 'success',
|
||||||
|
text: '%i18n:@saved%'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -93,11 +93,9 @@ export type Source = {
|
|||||||
private_key: string;
|
private_key: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
google_maps_api_key: string;
|
|
||||||
|
|
||||||
clusterLimit?: number;
|
clusterLimit?: number;
|
||||||
|
|
||||||
user_recommendation: {
|
user_recommendation?: {
|
||||||
external: boolean;
|
external: boolean;
|
||||||
engine: string;
|
engine: string;
|
||||||
timeout: number;
|
timeout: number;
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import * as redis from 'redis';
|
import * as redis from 'redis';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
|
||||||
export default redis.createClient(
|
export default config.redis ? redis.createClient(
|
||||||
config.redis.port,
|
config.redis.port,
|
||||||
config.redis.host,
|
config.redis.host,
|
||||||
{
|
{
|
||||||
auth_pass: config.redis.pass
|
auth_pass: config.redis.pass
|
||||||
}
|
}
|
||||||
);
|
) : null;
|
||||||
|
@@ -166,7 +166,7 @@ export const pack = (
|
|||||||
|
|
||||||
// (データベースの欠損などで)ファイルがデータベース上に見つからなかったとき
|
// (データベースの欠損などで)ファイルがデータベース上に見つからなかったとき
|
||||||
if (_file == null) {
|
if (_file == null) {
|
||||||
console.warn(`in packaging driveFile: driveFile not found on database: ${_file}`);
|
console.warn(`[DAMAGED DB] (missing) pkg: driveFile :: ${file}`);
|
||||||
return resolve(null);
|
return resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -79,7 +79,7 @@ export const pack = (
|
|||||||
|
|
||||||
// (データベースの不具合などで)投稿が見つからなかったら
|
// (データベースの不具合などで)投稿が見つからなかったら
|
||||||
if (_favorite.note == null) {
|
if (_favorite.note == null) {
|
||||||
console.warn(`in packaging favorite: note not found on database: ${_favorite.noteId}`);
|
console.warn(`[DAMAGED DB] (missing) pkg: favorite -> note :: ${_favorite.id} (note ${_favorite.noteId})`);
|
||||||
return resolve(null);
|
return resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -281,9 +281,9 @@ export const pack = async (
|
|||||||
_note = deepcopy(note);
|
_note = deepcopy(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 投稿がデータベース上に見つからなかったとき
|
// (データベースの欠損などで)投稿がデータベース上に見つからなかったとき
|
||||||
if (_note == null) {
|
if (_note == null) {
|
||||||
console.warn(`note not found on database: ${note}`);
|
console.warn(`[DAMAGED DB] (missing) pkg: note :: ${note}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,12 +380,25 @@ export const pack = async (
|
|||||||
// resolve promises in _note object
|
// resolve promises in _note object
|
||||||
_note = await rap(_note);
|
_note = await rap(_note);
|
||||||
|
|
||||||
// (データベースの欠損などで)ユーザーがデータベース上に見つからなかったとき
|
//#region (データベースの欠損などで)参照しているデータがデータベース上に見つからなかったとき
|
||||||
if (_note.user == null) {
|
if (_note.user == null) {
|
||||||
console.warn(`in packaging note: note user not found on database: note(${_note.id})`);
|
console.warn(`[DAMAGED DB] (missing) pkg: note -> user :: ${_note.id} (user ${_note.userId})`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts.detail) {
|
||||||
|
if (_note.replyId != null && _note.reply == null) {
|
||||||
|
console.warn(`[DAMAGED DB] (missing) pkg: note -> reply :: ${_note.id} (reply ${_note.replyId})`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_note.renoteId != null && _note.renote == null) {
|
||||||
|
console.warn(`[DAMAGED DB] (missing) pkg: note -> renote :: ${_note.id} (renote ${_note.renoteId})`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
if (_note.user.isCat && _note.text) {
|
if (_note.user.isCat && _note.text) {
|
||||||
_note.text = _note.text.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ');
|
_note.text = _note.text.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ');
|
||||||
}
|
}
|
||||||
|
@@ -132,7 +132,7 @@ export const pack = (notification: any) => new Promise<any>(async (resolve, reje
|
|||||||
|
|
||||||
// (データベースの不具合などで)投稿が見つからなかったら
|
// (データベースの不具合などで)投稿が見つからなかったら
|
||||||
if (_notification.note == null) {
|
if (_notification.note == null) {
|
||||||
console.warn(`in packaging notification: note not found on database: ${_notification.noteId}`);
|
console.warn(`[DAMAGED DB] (missing) pkg: notification -> note :: ${_notification.id} (note ${_notification.noteId})`);
|
||||||
return resolve(null);
|
return resolve(null);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -27,7 +27,8 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
|||||||
|
|
||||||
const file = await DriveFile.findOne({
|
const file = await DriveFile.findOne({
|
||||||
md5: md5,
|
md5: md5,
|
||||||
'metadata.userId': user._id
|
'metadata.userId': user._id,
|
||||||
|
'metadata.deletedAt': { $exists: false }
|
||||||
});
|
});
|
||||||
|
|
||||||
if (file === null) {
|
if (file === null) {
|
||||||
|
@@ -22,7 +22,8 @@ export default async (params: any, user: ILocalUser) => {
|
|||||||
const file = await DriveFile
|
const file = await DriveFile
|
||||||
.findOne({
|
.findOne({
|
||||||
_id: fileId,
|
_id: fileId,
|
||||||
'metadata.userId': user._id
|
'metadata.userId': user._id,
|
||||||
|
'metadata.deletedAt': { $exists: false }
|
||||||
});
|
});
|
||||||
|
|
||||||
if (file === null) {
|
if (file === null) {
|
||||||
|
@@ -8,6 +8,12 @@ import { IUser } from '../../models/user';
|
|||||||
const log = debug('misskey:limitter');
|
const log = debug('misskey:limitter');
|
||||||
|
|
||||||
export default (endpoint: IEndpoint, user: IUser) => new Promise((ok, reject) => {
|
export default (endpoint: IEndpoint, user: IUser) => 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')
|
||||||
|
@@ -55,7 +55,7 @@ router.get('/disconnect/twitter', async ctx => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config.twitter == null) {
|
if (config.twitter == null || redis == null) {
|
||||||
router.get('/connect/twitter', ctx => {
|
router.get('/connect/twitter', ctx => {
|
||||||
ctx.body = '現在Twitterへ接続できません (このインスタンスではTwitterはサポートされていません)';
|
ctx.body = '現在Twitterへ接続できません (このインスタンスではTwitterはサポートされていません)';
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import autobind from 'autobind-decorator';
|
import autobind from 'autobind-decorator';
|
||||||
import * as CRC32 from 'crc-32';
|
import * as CRC32 from 'crc-32';
|
||||||
|
import * as mongo from 'mongodb';
|
||||||
import ReversiGame, { pack } from '../../../../../models/games/reversi/game';
|
import ReversiGame, { pack } from '../../../../../models/games/reversi/game';
|
||||||
import { publishReversiGameStream } from '../../../../../stream';
|
import { publishReversiGameStream } from '../../../../../stream';
|
||||||
import Reversi from '../../../../../games/reversi/core';
|
import Reversi from '../../../../../games/reversi/core';
|
||||||
@@ -7,11 +8,11 @@ import * as maps from '../../../../../games/reversi/maps';
|
|||||||
import Channel from '../../channel';
|
import Channel from '../../channel';
|
||||||
|
|
||||||
export default class extends Channel {
|
export default class extends Channel {
|
||||||
private gameId: string;
|
private gameId: mongo.ObjectID;
|
||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
public async init(params: any) {
|
public async init(params: any) {
|
||||||
this.gameId = params.gameId as string;
|
this.gameId = new mongo.ObjectID(params.gameId as string);
|
||||||
|
|
||||||
// Subscribe game stream
|
// Subscribe game stream
|
||||||
this.subscriber.on(`reversiGameStream:${this.gameId}`, data => {
|
this.subscriber.on(`reversiGameStream:${this.gameId}`, data => {
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import autobind from 'autobind-decorator';
|
import autobind from 'autobind-decorator';
|
||||||
import * as websocket from 'websocket';
|
import * as websocket from 'websocket';
|
||||||
import Xev from 'xev';
|
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
|
|
||||||
import User, { IUser } from '../../../models/user';
|
import User, { IUser } from '../../../models/user';
|
||||||
@@ -11,6 +10,7 @@ import readNote from '../../../services/note/read';
|
|||||||
|
|
||||||
import Channel from './channel';
|
import Channel from './channel';
|
||||||
import channels from './channels';
|
import channels from './channels';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
const log = debug('misskey');
|
const log = debug('misskey');
|
||||||
|
|
||||||
@@ -21,14 +21,14 @@ export default class Connection {
|
|||||||
public user?: IUser;
|
public user?: IUser;
|
||||||
public app: IApp;
|
public app: IApp;
|
||||||
private wsConnection: websocket.connection;
|
private wsConnection: websocket.connection;
|
||||||
public subscriber: Xev;
|
public subscriber: EventEmitter;
|
||||||
private channels: Channel[] = [];
|
private channels: Channel[] = [];
|
||||||
private subscribingNotes: any = {};
|
private subscribingNotes: any = {};
|
||||||
public sendMessageToWsOverride: any = null; // 後方互換性のため
|
public sendMessageToWsOverride: any = null; // 後方互換性のため
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
wsConnection: websocket.connection,
|
wsConnection: websocket.connection,
|
||||||
subscriber: Xev,
|
subscriber: EventEmitter,
|
||||||
user: IUser,
|
user: IUser,
|
||||||
app: IApp
|
app: IApp
|
||||||
) {
|
) {
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
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 Xev from 'xev';
|
import Xev from 'xev';
|
||||||
|
|
||||||
import MainStreamConnection from './stream';
|
import MainStreamConnection from './stream';
|
||||||
import { ParsedUrlQuery } from 'querystring';
|
import { ParsedUrlQuery } from 'querystring';
|
||||||
import authenticate from './authenticate';
|
import authenticate from './authenticate';
|
||||||
import channels from './stream/channels';
|
import channels from './stream/channels';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import config from '../../config';
|
||||||
|
|
||||||
module.exports = (server: http.Server) => {
|
module.exports = (server: http.Server) => {
|
||||||
// Init websocket server
|
// Init websocket server
|
||||||
@@ -16,11 +19,34 @@ module.exports = (server: http.Server) => {
|
|||||||
ws.on('request', async (request) => {
|
ws.on('request', async (request) => {
|
||||||
const connection = request.accept();
|
const connection = request.accept();
|
||||||
|
|
||||||
const ev = new Xev();
|
|
||||||
|
|
||||||
const q = request.resourceURL.query as ParsedUrlQuery;
|
const q = request.resourceURL.query as ParsedUrlQuery;
|
||||||
const [user, app] = await authenticate(q.i as string);
|
const [user, app] = await authenticate(q.i as string);
|
||||||
|
|
||||||
|
let ev: EventEmitter;
|
||||||
|
|
||||||
|
if (config.redis) {
|
||||||
|
// Connect to Redis
|
||||||
|
const subscriber = redis.createClient(
|
||||||
|
config.redis.port, config.redis.host);
|
||||||
|
|
||||||
|
subscriber.subscribe('misskey');
|
||||||
|
|
||||||
|
ev = new EventEmitter();
|
||||||
|
|
||||||
|
subscriber.on('message', async (_, data) => {
|
||||||
|
const obj = JSON.parse(data);
|
||||||
|
|
||||||
|
ev.emit(obj.channel, obj.message);
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.once('close', () => {
|
||||||
|
subscriber.unsubscribe();
|
||||||
|
subscriber.quit();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ev = new Xev();
|
||||||
|
}
|
||||||
|
|
||||||
const main = new MainStreamConnection(connection, ev, user, app);
|
const main = new MainStreamConnection(connection, ev, user, app);
|
||||||
|
|
||||||
// 後方互換性のため
|
// 後方互換性のため
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
|
import redis from './db/redis';
|
||||||
import Xev from 'xev';
|
import Xev from 'xev';
|
||||||
import Meta, { IMeta } from './models/meta';
|
import Meta, { IMeta } from './models/meta';
|
||||||
|
|
||||||
@@ -9,7 +10,10 @@ class Publisher {
|
|||||||
private meta: IMeta;
|
private meta: IMeta;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.ev = new Xev();
|
// Redisがインストールされてないときはプロセス間通信を使う
|
||||||
|
if (redis == null) {
|
||||||
|
this.ev = new Xev();
|
||||||
|
}
|
||||||
|
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
this.meta = await Meta.findOne({});
|
this.meta = await Meta.findOne({});
|
||||||
@@ -28,7 +32,14 @@ class Publisher {
|
|||||||
{ type: type, body: null } :
|
{ type: type, body: null } :
|
||||||
{ type: type, body: value };
|
{ type: type, body: value };
|
||||||
|
|
||||||
this.ev.emit(channel, message);
|
if (this.ev) {
|
||||||
|
this.ev.emit(channel, message);
|
||||||
|
} else {
|
||||||
|
redis.publish('misskey', JSON.stringify({
|
||||||
|
channel: channel,
|
||||||
|
message: message
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public publishMainStream = (userId: ID, type: string, value?: any): void => {
|
public publishMainStream = (userId: ID, type: string, value?: any): void => {
|
||||||
|
@@ -10,11 +10,21 @@ DriveFile.find({
|
|||||||
withoutChunks: { $exists: false }
|
withoutChunks: { $exists: false }
|
||||||
}, {
|
}, {
|
||||||
withoutChunks: false
|
withoutChunks: false
|
||||||
}]
|
}],
|
||||||
|
'metadata.deletedAt': { $exists: false }
|
||||||
|
}, {
|
||||||
|
fields: {
|
||||||
|
_id: true
|
||||||
|
}
|
||||||
}).then(async files => {
|
}).then(async files => {
|
||||||
|
console.log(`there is ${files.length} files`);
|
||||||
|
|
||||||
await sequential(files.map(file => async () => {
|
await sequential(files.map(file => async () => {
|
||||||
|
file = await DriveFile.findOne({ _id: file._id });
|
||||||
|
|
||||||
const minio = new Minio.Client(config.drive.config);
|
const minio = new Minio.Client(config.drive.config);
|
||||||
|
|
||||||
|
const name = file.filename;
|
||||||
const keyDir = `${config.drive.prefix}/${uuid.v4()}`;
|
const keyDir = `${config.drive.prefix}/${uuid.v4()}`;
|
||||||
const key = `${keyDir}/${name}`;
|
const key = `${keyDir}/${name}`;
|
||||||
const thumbnailKeyDir = `${config.drive.prefix}/${uuid.v4()}`;
|
const thumbnailKeyDir = `${config.drive.prefix}/${uuid.v4()}`;
|
||||||
|
Reference in New Issue
Block a user