mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-24 07:23:08 +02:00
Merge branch 'develop'
This commit is contained in:
commit
723d3e6871
146 changed files with 1813 additions and 899 deletions
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
|
@ -1,7 +1,7 @@
|
|||
# PATH OWNERS
|
||||
/.autogen/ @acid-chicken
|
||||
/.circleci/ @syuilo @acid-chicken
|
||||
/.config/ @syuilo @AyaMorisawa @mei23 @acid-chicken
|
||||
/.config/ @syuilo @AyaMorisawa @mei23 @acid-chicken @rinsuki
|
||||
# /.config/mongo_initdb_example.js @khws4v1
|
||||
/.github/ @syuilo @AyaMorisawa @acid-chicken
|
||||
/.vscode/ @acid-chicken
|
||||
|
@ -12,7 +12,7 @@
|
|||
# /docs/*.fr.md @BoFFire
|
||||
# /docs/docker.*.md @khws4v1
|
||||
/locales/ @syuilo
|
||||
/src/ @syuilo @AyaMorisawa @mei23 @acid-chicken
|
||||
/src/ @syuilo @AyaMorisawa @mei23 @acid-chicken @rinsuki
|
||||
# /src/crypto_key.cc @akihikodaki
|
||||
# /src/crypto_key.d.ts @akihikodaki
|
||||
/.dockerignore @syuilo # @khws4v1
|
||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -35,6 +35,17 @@ mongodb:
|
|||
8. master ブランチに戻す
|
||||
9. enjoy
|
||||
|
||||
11.3.0 (2019/04/24)
|
||||
-------------------
|
||||
### Improvements
|
||||
* お知らせにMFMを使えるように
|
||||
* お知らせに画像を添付できるように
|
||||
|
||||
### Fixes
|
||||
* 投稿のタグ検索APIで大文字小文字が区別されていたのを修正
|
||||
* 公開範囲がホームの投稿がグローバルTLに流れる問題を修正
|
||||
* モバイルビューの投稿詳細にて acct が長いとアイコンが圧迫面接される問題を修正
|
||||
|
||||
11.2.2 (2019/04/22)
|
||||
-------------------
|
||||
### Fixes
|
||||
|
|
12
README.md
12
README.md
|
@ -88,12 +88,14 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||
<td><img src="https://avatars0.githubusercontent.com/u/10798641?s=460&v=4" alt="AyaMorisawa" width="100"></td>
|
||||
<td><img src="https://avatars1.githubusercontent.com/u/30769358?s=460&v=4" alt="mei23" width="100"></td>
|
||||
<td><img src="https://avatars2.githubusercontent.com/u/20679825?s=460&v=4" alt="acid-chicken" width="100"></td>
|
||||
<td><img src="https://avatars2.githubusercontent.com/u/6533808?s=460&v=4" alt="rinsuki" width="100"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/syuilo">@syuilo</a></td>
|
||||
<td align="center"><a href="https://github.com/AyaMorisawa">@AyaMorisawa</a></td>
|
||||
<td align="center"><a href="https://github.com/mei23">@mei23</a></td>
|
||||
<td align="center"><a href="https://github.com/acid-chicken">@acid-chicken</a></td>
|
||||
<td align="center"><a href="https://github.com/rinsuki">@rinsuki</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
@ -102,14 +104,14 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||
<!-- PATREON_START -->
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5888816/36da0f7c15954df0ab13f9abdf227f66/1.jpeg?token-time=2145916800&token-hash=at8QpJXJ8C0zINY_NmoMKv-MhXVoUK-YzTgaJPJzJYU%3D" alt="Hiroshi Seki" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weep" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weepjp" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1.jpe?token-time=2145916800&token-hash=bqwLTk0Wo0hUJJ8J5y7ii05bLzz-_CDA7Bo0Mp4RFU0%3D" alt="ne_moni" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/4.jpe?token-time=2145916800&token-hash=zEyJqVM7u9d8Ri-65fJYSJcWF1jBH1nJ5a3taRzrTmw%3D" alt="Melilot" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/rane_hs">Hiroshi Seki</a></td>
|
||||
<td><a href="https://www.patreon.com/weepjp">weep</a></td>
|
||||
<td><a href="https://www.patreon.com/weepjp">weepjp</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
|
||||
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
|
||||
|
@ -124,7 +126,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/1.jpeg?token-time=2145916800&token-hash=3aMtpAjhwf01G3Uf8iIKYL8FUXXgxV7NvoQLne7lAKE%3D" alt="Ryosuke Yamamoto" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
||||
|
@ -135,7 +137,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin</a></td>
|
||||
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=17463605">Sampot</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=19356899">Ryosuke Yamamoto</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=19356899">sheeta.s</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
|
||||
</tr></table>
|
||||
<table><tr>
|
||||
|
@ -165,7 +167,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||
</tr></table>
|
||||
|
||||
**Last updated:** Thu, 18 Apr 2019 23:38:06 UTC
|
||||
**Last updated:** Wed, 24 Apr 2019 05:56:07 UTC
|
||||
<!-- PATREON_END -->
|
||||
|
||||
:four_leaf_clover: Copyright
|
||||
|
|
|
@ -13,7 +13,7 @@ common:
|
|||
rich-contents-desc: "Partagez vos idées, les événements et les sujets qui vous tiennent à cœur ainsi que tout autre chose que vous souhaitez partager avec les autres. Si vous le désirez, vous pouvez décorer vos messages en utilisant une syntaxe différente ou en y joignant des sondages et des fichiers, tels que les photos ou les vidéos que vous aimez."
|
||||
reaction: "Réactions"
|
||||
reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateurs. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »."
|
||||
ui: "Interface utilisateur"
|
||||
ui: "Interface"
|
||||
ui-desc: "Aucune interface graphique ne peut plaire à tout le monde. Par conséquent, Misskey possède une interface utilisateur hautement personnalisable selon vos goûts. Vous pouvez rendre votre page d'accueil originale en modifiant la mise en page de votre fil et en déplaçant les widgets que vous pouvez facilement ajuster pour vous approprier cet espace."
|
||||
drive: "Drive"
|
||||
drive-desc: "Vous voulez poster une photo que vous avez déjà transférée ? Vous souhaitez organiser, nommer et créer un dossier pour vos fichiers téléversés ? Misskey Drive est la meilleure solution pour vous. Très facile de partager vos fichiers en ligne."
|
||||
|
@ -33,6 +33,7 @@ common:
|
|||
signin: "Se connecter"
|
||||
signup: "S'enregistrer"
|
||||
signout: "Se déconnecter"
|
||||
reload-to-apply-the-setting: "Le rechargement de la page est nécessaire pour appliquer ces paramètres. Désirez-vous la recharger maintenant ?"
|
||||
got-it: "J’ai compris !"
|
||||
customization-tips:
|
||||
title: "Conseils de personnalisation"
|
||||
|
@ -73,6 +74,8 @@ common:
|
|||
"read:drive": "Parcourir le Drive"
|
||||
"write:drive": "Écrire sur le Drive"
|
||||
"read:favorites": "Afficher les favoris"
|
||||
"write:notes": "Créer ou supprimer des publications"
|
||||
"read:notifications": "Afficher les notifications"
|
||||
"read:reactions": "Lire les réactions"
|
||||
"write:votes": "Vote"
|
||||
empty-timeline-info:
|
||||
|
@ -209,16 +212,16 @@ common:
|
|||
debug-mode: "Activer le mode débogage"
|
||||
debug-mode-desc: "Ce paramètre est stocké dans le navigateur."
|
||||
navbar-position: "Position de la barre de navigation"
|
||||
navbar-position-top: "en haut"
|
||||
navbar-position-top: "En haut"
|
||||
navbar-position-left: "À gauche"
|
||||
navbar-position-right: "à droite"
|
||||
navbar-position-right: "À droite"
|
||||
i-am-under-limited-internet: "J'ai un accès Internet limité"
|
||||
post-style: "Style d'affichage des notes"
|
||||
post-style-standard: "Standard"
|
||||
post-style-smart: "Intelligent"
|
||||
notification-position: "Afficher les notifications"
|
||||
notification-position-bottom: "en bas"
|
||||
notification-position-top: "en haut"
|
||||
notification-position-top: "En haut"
|
||||
disable-via-mobile: "Enlever la mention publié via 'mobile'"
|
||||
load-raw-images: "Afficher les photos jointes dans leur qualité originale"
|
||||
load-remote-media: "Afficher les médias depuis le serveur distant"
|
||||
|
@ -307,6 +310,7 @@ common/views/pages/explore.vue:
|
|||
explore: "Explorer {host}"
|
||||
users-info: "Actuellement, {users} utilisateurs se sont inscrit ici"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "Activer la lecture"
|
||||
disable-player: "Fermer le lecteur"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "Il n'y a aucun utilisateur"
|
||||
|
@ -647,6 +651,7 @@ common/views/components/profile-editor.vue:
|
|||
blocking-list: "Liste des comptes bloqués"
|
||||
user-lists: "Listes"
|
||||
export-requested: "Vous avez demandé une exportation. Cela peut prendre un certain temps. Une fois l'exportation terminée, le fichier résultant sera ajouté dans le Drive."
|
||||
import-requested: "Vous avez initié un import. Ceci peut prendre un peu de temps."
|
||||
enter-password: "Veuillez saisir votre mot de passe"
|
||||
danger-zone: "Zone de danger"
|
||||
delete-account: "Supprimer le compte"
|
||||
|
@ -659,6 +664,7 @@ common/views/components/user-list-editor.vue:
|
|||
delete-are-you-sure: "Voulez-vous vraiment supprimer la liste « $1 » ?"
|
||||
deleted: "Supprimé"
|
||||
common/views/components/user-lists.vue:
|
||||
create-list: "Créer une liste"
|
||||
list-name: "Nom de la liste"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Récupération"
|
||||
|
|
|
@ -34,6 +34,7 @@ common:
|
|||
signup: "注册"
|
||||
signout: "退出"
|
||||
reload-to-apply-the-setting: "必须重新加载页面以应用此设置。 确实要立即重新加载吗?"
|
||||
fetching-as-ap-object: "联合查询"
|
||||
got-it: "知道了"
|
||||
customization-tips:
|
||||
title: "自定义提示"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "11.2.2",
|
||||
"version": "11.3.0",
|
||||
"codename": "daybreak",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -29,7 +29,6 @@
|
|||
"@fortawesome/free-solid-svg-icons": "5.7.2",
|
||||
"@fortawesome/vue-fontawesome": "0.1.5",
|
||||
"@koa/cors": "2.2.3",
|
||||
"@prezzemolo/rap": "0.1.2",
|
||||
"@prezzemolo/zip": "0.0.3",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/bull": "3.5.11",
|
||||
|
|
|
@ -27,7 +27,7 @@ function greet() {
|
|||
console.log(' ' + chalk.gray(v) + (' |___|\n'.substr(v.length)));
|
||||
//#endregion
|
||||
|
||||
console.log(' Misskey is maintained by @syuilo, @AyaMorisawa, @mei23, and @acid-chicken.');
|
||||
console.log(' Misskey is maintained by @syuilo, @AyaMorisawa, @mei23, @acid-chicken, and @rinsuki.');
|
||||
console.log(chalk.keyword('orange')(' If you like Misskey, please donate to support development. https://www.patreon.com/syuilo'));
|
||||
|
||||
console.log('');
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
<ui-textarea v-model="announcement.text">
|
||||
<span>{{ $t('text') }}</span>
|
||||
</ui-textarea>
|
||||
<ui-input v-model="announcement.image">
|
||||
<span>{{ $t('image-url') }}</span>
|
||||
</ui-input>
|
||||
<ui-horizon-group class="fit-bottom">
|
||||
<ui-button @click="save()"><fa :icon="['far', 'save']"/> {{ $t('save') }}</ui-button>
|
||||
<ui-button @click="remove(i)"><fa :icon="['far', 'trash-alt']"/> {{ $t('remove') }}</ui-button>
|
||||
|
@ -43,7 +46,8 @@ export default Vue.extend({
|
|||
add() {
|
||||
this.announcements.unshift({
|
||||
title: '',
|
||||
text: ''
|
||||
text: '',
|
||||
image: null
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ export default Vue.extend({
|
|||
.mk-avatar
|
||||
display inline-block
|
||||
vertical-align bottom
|
||||
flex-shrink 0
|
||||
|
||||
&:not(.cat)
|
||||
overflow hidden
|
||||
|
|
|
@ -77,11 +77,11 @@ export default Vue.extend({
|
|||
input: {
|
||||
default: this.list.name
|
||||
}
|
||||
}).then(({ canceled, result: title }) => {
|
||||
}).then(({ canceled, result: name }) => {
|
||||
if (canceled) return;
|
||||
this.$root.api('users/lists/update', {
|
||||
listId: this.list.id,
|
||||
title: title
|
||||
name: name
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
@ -28,10 +28,10 @@ export default Vue.extend({
|
|||
this.$root.dialog({
|
||||
title: this.$t('list-name'),
|
||||
input: true
|
||||
}).then(async ({ canceled, result: title }) => {
|
||||
}).then(async ({ canceled, result: name }) => {
|
||||
if (canceled) return;
|
||||
const list = await this.$root.api('users/lists/create', {
|
||||
title
|
||||
name
|
||||
});
|
||||
|
||||
this.lists.push(list)
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
<p class="fetching" v-if="fetching">{{ $t('fetching') }}<mk-ellipsis/></p>
|
||||
<h1 v-if="!fetching">{{ announcements.length == 0 ? $t('no-broadcasts') : announcements[i].title }}</h1>
|
||||
<p v-if="!fetching">
|
||||
<span v-if="announcements.length != 0" v-html="announcements[i].text"></span>
|
||||
<mfm v-if="announcements.length != 0" :text="announcements[i].text"/>
|
||||
<img v-if="announcements.length != 0 && announcements[i].image" :src="announcements[i].image" alt="" style="display: block; max-height: 130px; max-width: 100%;"/>
|
||||
<template v-if="announcements.length == 0">{{ $t('have-a-nice-day') }}</template>
|
||||
</p>
|
||||
<a v-if="announcements.length > 1" @click="next">{{ $t('next') }} >></a>
|
||||
|
|
|
@ -123,10 +123,10 @@ export default Vue.extend({
|
|||
this.$root.dialog({
|
||||
title: this.$t('list-name'),
|
||||
input: true
|
||||
}).then(async ({ canceled, result: title }) => {
|
||||
}).then(async ({ canceled, result: name }) => {
|
||||
if (canceled) return;
|
||||
const list = await this.$root.api('users/lists/create', {
|
||||
title
|
||||
name
|
||||
});
|
||||
|
||||
this.list = list;
|
||||
|
|
|
@ -44,7 +44,8 @@
|
|||
<div v-if="announcements && announcements.length > 0">
|
||||
<div v-for="announcement in announcements">
|
||||
<h1 v-html="announcement.title"></h1>
|
||||
<div v-html="announcement.text"></div>
|
||||
<mfm :text="announcement.text"/>
|
||||
<img v-if="announcement.image" :src="announcement.image" alt="" style="display: block; max-height: 130px; max-width: 100%;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -215,11 +215,6 @@ export default Vue.extend({
|
|||
@media (min-width 500px)
|
||||
padding 28px 32px 18px 32px
|
||||
|
||||
&:after
|
||||
content ""
|
||||
display block
|
||||
clear both
|
||||
|
||||
> header
|
||||
display flex
|
||||
line-height 1.1em
|
||||
|
@ -236,6 +231,7 @@ export default Vue.extend({
|
|||
height 60px
|
||||
|
||||
> div
|
||||
min-width 0
|
||||
|
||||
> .name
|
||||
display inline-block
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
<div class="announcements" v-if="announcements && announcements.length > 0">
|
||||
<article v-for="announcement in announcements">
|
||||
<span v-html="announcement.title" class="title"></span>
|
||||
<div v-html="announcement.text"></div>
|
||||
<mfm :text="announcement.text"/>
|
||||
<img v-if="announcement.image" :src="announcement.image" alt="" style="display: block; max-height: 120px; max-width: 100%;"/>
|
||||
</article>
|
||||
</div>
|
||||
<a :href="aboutUrl"><p class="about">{{ $t('about') }}</p></a>
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
<div class="announcements" v-if="announcements && announcements.length > 0">
|
||||
<article v-for="announcement in announcements">
|
||||
<span class="title" v-html="announcement.title"></span>
|
||||
<div v-html="announcement.text"></div>
|
||||
<mfm :text="announcement.text"/>
|
||||
<img v-if="announcement.image" :src="announcement.image" alt="" style="display: block; max-height: 120px; max-width: 100%;"/>
|
||||
</article>
|
||||
</div>
|
||||
<article class="about-misskey">
|
||||
|
|
|
@ -19,7 +19,7 @@ export const cafeTheme: Theme = require('../themes/cafe.json5');
|
|||
export const japaneseSushiSetTheme: Theme = require('../themes/japanese-sushi-set.json5');
|
||||
export const gruvboxDarkTheme: Theme = require('../themes/gruvbox-dark.json5');
|
||||
export const monokaiTheme: Theme = require('../themes/monokai.json5');
|
||||
export const colorfulTheme: Theme = require('../themes/colorful.json5');
|
||||
export const vividTheme: Theme = require('../themes/vivid.json5');
|
||||
export const rainyTheme: Theme = require('../themes/rainy.json5');
|
||||
export const mauveTheme: Theme = require('../themes/mauve.json5');
|
||||
export const grayTheme: Theme = require('../themes/gray.json5');
|
||||
|
@ -35,7 +35,7 @@ export const builtinThemes = [
|
|||
japaneseSushiSetTheme,
|
||||
gruvboxDarkTheme,
|
||||
monokaiTheme,
|
||||
colorfulTheme,
|
||||
vividTheme,
|
||||
rainyTheme,
|
||||
mauveTheme,
|
||||
grayTheme,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
id: '2d066d6e-bd39-4f23-bd48-686d5c1c6ae8',
|
||||
|
||||
name: 'Colorful',
|
||||
name: 'Vivid',
|
||||
author: 'syuilo',
|
||||
|
||||
base: 'light',
|
|
@ -1,7 +1,11 @@
|
|||
import { Meta } from '../models/entities/meta';
|
||||
import { getConnection } from 'typeorm';
|
||||
|
||||
export default async function(): Promise<Meta> {
|
||||
let cache: Meta;
|
||||
|
||||
export async function fetchMeta(noCache = false): Promise<Meta> {
|
||||
if (!noCache && cache) return cache;
|
||||
|
||||
return await getConnection().transaction(async transactionalEntityManager => {
|
||||
// バグでレコードが複数出来てしまっている可能性があるので新しいIDを優先する
|
||||
const meta = await transactionalEntityManager.findOne(Meta, {
|
||||
|
@ -11,11 +15,21 @@ export default async function(): Promise<Meta> {
|
|||
});
|
||||
|
||||
if (meta) {
|
||||
cache = meta;
|
||||
return meta;
|
||||
} else {
|
||||
return await transactionalEntityManager.save(Meta, {
|
||||
const saved = await transactionalEntityManager.save(Meta, {
|
||||
id: 'x'
|
||||
}) as Meta;
|
||||
|
||||
cache = saved;
|
||||
return saved;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
fetchMeta(true).then(meta => {
|
||||
cache = meta;
|
||||
});
|
||||
}, 5000);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import fetchMeta from './fetch-meta';
|
||||
import { fetchMeta } from './fetch-meta';
|
||||
import { ILocalUser } from '../models/entities/user';
|
||||
import { Users } from '../models';
|
||||
import { ensure } from '../prelude/ensure';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { emojiRegex } from './emoji-regex';
|
||||
import fetchMeta from './fetch-meta';
|
||||
import { fetchMeta } from './fetch-meta';
|
||||
import { Emojis } from '../models';
|
||||
|
||||
const basic10: Record<string, string> = {
|
||||
|
|
|
@ -1,14 +1,46 @@
|
|||
export const types = {
|
||||
boolean: 'boolean' as 'boolean',
|
||||
string: 'string' as 'string',
|
||||
number: 'number' as 'number',
|
||||
array: 'array' as 'array',
|
||||
object: 'object' as 'object',
|
||||
any: 'any' as 'any',
|
||||
};
|
||||
|
||||
export const bool = {
|
||||
true: true as true,
|
||||
false: false as false,
|
||||
};
|
||||
|
||||
export type Schema = {
|
||||
type: 'number' | 'string' | 'array' | 'object' | any;
|
||||
optional?: boolean;
|
||||
type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any';
|
||||
nullable: boolean;
|
||||
optional: boolean;
|
||||
items?: Schema;
|
||||
properties?: Obj;
|
||||
description?: string;
|
||||
example?: any;
|
||||
format?: string;
|
||||
ref?: string;
|
||||
enum?: string[];
|
||||
};
|
||||
|
||||
type NonUndefinedPropertyNames<T extends Obj> = {
|
||||
[K in keyof T]: T[K]['optional'] extends true ? never : K
|
||||
}[keyof T];
|
||||
|
||||
type UndefinedPropertyNames<T extends Obj> = {
|
||||
[K in keyof T]: T[K]['optional'] extends true ? K : never
|
||||
}[keyof T];
|
||||
|
||||
type OnlyRequired<T extends Obj> = Pick<T, NonUndefinedPropertyNames<T>>;
|
||||
type OnlyOptional<T extends Obj> = Pick<T, UndefinedPropertyNames<T>>;
|
||||
|
||||
export type Obj = { [key: string]: Schema };
|
||||
|
||||
export type ObjType<s extends Obj> = { [P in keyof s]: SchemaType<s[P]> };
|
||||
export type ObjType<s extends Obj> =
|
||||
{ [P in keyof OnlyOptional<s>]?: SchemaType<s[P]> } &
|
||||
{ [P in keyof OnlyRequired<s>]: SchemaType<s[P]> };
|
||||
|
||||
// https://qiita.com/hrsh7th@github/items/84e8968c3601009cdcf2
|
||||
type MyType<T extends Schema> = {
|
||||
|
@ -16,26 +48,20 @@ type MyType<T extends Schema> = {
|
|||
1: SchemaType<T>;
|
||||
}[T extends Schema ? 1 : 0];
|
||||
|
||||
export type SchemaType<p extends Schema> =
|
||||
p['type'] extends 'number' ? number :
|
||||
p['type'] extends 'string' ? string :
|
||||
p['type'] extends 'array' ? MyType<NonNullable<p['items']>>[] :
|
||||
p['type'] extends 'object' ? ObjType<NonNullable<p['properties']>> :
|
||||
any;
|
||||
type NullOrUndefined<p extends Schema, T> =
|
||||
p['nullable'] extends true
|
||||
? p['optional'] extends true
|
||||
? (T | null | undefined)
|
||||
: (T | null)
|
||||
: p['optional'] extends true
|
||||
? (T | undefined)
|
||||
: T;
|
||||
|
||||
export function convertOpenApiSchema(schema: Schema) {
|
||||
const x = JSON.parse(JSON.stringify(schema)); // copy
|
||||
if (!['string', 'number', 'boolean', 'array', 'object'].includes(x.type)) {
|
||||
x['$ref'] = `#/components/schemas/${x.type}`;
|
||||
}
|
||||
if (x.type === 'array' && x.items) {
|
||||
x.items = convertOpenApiSchema(x.items);
|
||||
}
|
||||
if (x.type === 'object' && x.properties) {
|
||||
x.required = Object.entries(x.properties).filter(([k, v]: any) => !v.isOptional).map(([k, v]: any) => k);
|
||||
for (const k of Object.keys(x.properties)) {
|
||||
x.properties[k] = convertOpenApiSchema(x.properties[k]);
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
export type SchemaType<p extends Schema> =
|
||||
p['type'] extends 'number' ? NullOrUndefined<p, number> :
|
||||
p['type'] extends 'string' ? NullOrUndefined<p, string> :
|
||||
p['type'] extends 'boolean' ? NullOrUndefined<p, boolean> :
|
||||
p['type'] extends 'array' ? NullOrUndefined<p, MyType<NonNullable<p['items']>>[]> :
|
||||
p['type'] extends 'object' ? NullOrUndefined<p, ObjType<NonNullable<p['properties']>>> :
|
||||
p['type'] extends 'any' ? NullOrUndefined<p, any> :
|
||||
any;
|
||||
|
|
|
@ -36,7 +36,7 @@ export class NoteReaction {
|
|||
public note: Note | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 32
|
||||
length: 128
|
||||
})
|
||||
public reaction: string;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { AbuseUserReport } from '../entities/abuse-user-report';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
|
||||
@EntityRepository(AbuseUserReport)
|
||||
export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
|
||||
|
@ -17,7 +17,7 @@ export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
|
|||
) {
|
||||
const report = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: report.id,
|
||||
createdAt: report.createdAt,
|
||||
reporterId: report.reporterId,
|
||||
|
|
|
@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm';
|
|||
import { App } from '../entities/app';
|
||||
import { AccessTokens } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { types, bool, SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedApp = SchemaType<typeof packedAppSchema>;
|
||||
|
||||
@EntityRepository(App)
|
||||
export class AppRepository extends Repository<App> {
|
||||
|
@ -13,7 +16,7 @@ export class AppRepository extends Repository<App> {
|
|||
includeSecret?: boolean,
|
||||
includeProfileImageIds?: boolean
|
||||
}
|
||||
) {
|
||||
): Promise<PackedApp> {
|
||||
const opts = Object.assign({
|
||||
detail: false,
|
||||
includeSecret: false,
|
||||
|
@ -37,3 +40,40 @@ export class AppRepository extends Repository<App> {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const packedAppSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this Note.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
name: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'アプリケーションの名前'
|
||||
},
|
||||
callbackUrl: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.true,
|
||||
description: 'コールバックするURL'
|
||||
},
|
||||
permission: {
|
||||
type: types.array,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
items: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
}
|
||||
},
|
||||
secret: {
|
||||
type: types.string,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
description: 'アプリケーションのシークレットキー'
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Apps } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { AuthSession } from '../entities/auth-session';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
|
||||
@EntityRepository(AuthSession)
|
||||
export class AuthSessionRepository extends Repository<AuthSession> {
|
||||
|
@ -12,7 +12,7 @@ export class AuthSessionRepository extends Repository<AuthSession> {
|
|||
) {
|
||||
const session = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: session.id,
|
||||
app: Apps.pack(session.appId, me),
|
||||
token: session.token
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { Blocking } from '../entities/blocking';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType, types, bool } from '../../misc/schema';
|
||||
|
||||
export type PackedBlocking = SchemaType<typeof packedBlockingSchema>;
|
||||
|
||||
@EntityRepository(Blocking)
|
||||
export class BlockingRepository extends Repository<Blocking> {
|
||||
|
@ -16,14 +19,47 @@ export class BlockingRepository extends Repository<Blocking> {
|
|||
public async pack(
|
||||
src: Blocking['id'] | Blocking,
|
||||
me?: any
|
||||
) {
|
||||
): Promise<PackedBlocking> {
|
||||
const blocking = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: blocking.id,
|
||||
createdAt: blocking.createdAt.toISOString(),
|
||||
blockeeId: blocking.blockeeId,
|
||||
blockee: Users.pack(blocking.blockeeId, me, {
|
||||
detail: true
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const packedBlockingSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this blocking.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the blocking was created.'
|
||||
},
|
||||
blockeeId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
},
|
||||
blockee: {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'User',
|
||||
description: 'The blockee.'
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { DriveFile } from '../entities/drive-file';
|
||||
import { Users, DriveFolders } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { User } from '../entities/user';
|
||||
import { toPuny } from '../../misc/convert-host';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { types, bool, SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedDriveFile = SchemaType<typeof packedDriveFileSchema>;
|
||||
|
||||
@EntityRepository(DriveFile)
|
||||
export class DriveFileRepository extends Repository<DriveFile> {
|
||||
|
@ -82,7 +85,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
|
|||
self?: boolean,
|
||||
withUser?: boolean,
|
||||
}
|
||||
) {
|
||||
): Promise<PackedDriveFile> {
|
||||
const opts = Object.assign({
|
||||
detail: false,
|
||||
self: false
|
||||
|
@ -90,9 +93,9 @@ export class DriveFileRepository extends Repository<DriveFile> {
|
|||
|
||||
const file = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: file.id,
|
||||
createdAt: file.createdAt,
|
||||
createdAt: file.createdAt.toISOString(),
|
||||
name: file.name,
|
||||
type: file.type,
|
||||
md5: file.md5,
|
||||
|
@ -109,3 +112,66 @@ export class DriveFileRepository extends Repository<DriveFile> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const packedDriveFileSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this Drive file.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the Drive file was created on Misskey.'
|
||||
},
|
||||
name: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The file name with extension.',
|
||||
example: 'lenna.jpg'
|
||||
},
|
||||
type: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The MIME type of this Drive file.',
|
||||
example: 'image/jpeg'
|
||||
},
|
||||
md5: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'md5',
|
||||
description: 'The MD5 hash of this Drive file.',
|
||||
example: '15eca7fba0480996e2245f5185bf39f2'
|
||||
},
|
||||
size: {
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The size of this Drive file. (bytes)',
|
||||
example: 51469
|
||||
},
|
||||
url: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.true,
|
||||
format: 'url',
|
||||
description: 'The URL of this Drive file.',
|
||||
},
|
||||
folderId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.true,
|
||||
format: 'id',
|
||||
description: 'The parent folder ID of this Drive file.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
isSensitive: {
|
||||
type: types.boolean,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'Whether this Drive file is sensitive.',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { DriveFolders, DriveFiles } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { DriveFolder } from '../entities/drive-folder';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType, types, bool } from '../../misc/schema';
|
||||
|
||||
export type PackedDriveFolder = SchemaType<typeof packedDriveFolderSchema>;
|
||||
|
||||
@EntityRepository(DriveFolder)
|
||||
export class DriveFolderRepository extends Repository<DriveFolder> {
|
||||
|
@ -18,16 +21,16 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
|
|||
options?: {
|
||||
detail: boolean
|
||||
}
|
||||
): Promise<Record<string, any>> {
|
||||
): Promise<PackedDriveFolder> {
|
||||
const opts = Object.assign({
|
||||
detail: false
|
||||
}, options);
|
||||
|
||||
const folder = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: folder.id,
|
||||
createdAt: folder.createdAt,
|
||||
createdAt: folder.createdAt.toISOString(),
|
||||
name: folder.name,
|
||||
parentId: folder.parentId,
|
||||
|
||||
|
@ -48,3 +51,50 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const packedDriveFolderSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this Drive folder.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the Drive folder was created.'
|
||||
},
|
||||
name: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The folder name.',
|
||||
},
|
||||
foldersCount: {
|
||||
type: types.number,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
description: 'The count of child folders.',
|
||||
},
|
||||
filesCount: {
|
||||
type: types.number,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
description: 'The count of child files.',
|
||||
},
|
||||
parentId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.true,
|
||||
format: 'id',
|
||||
description: 'The parent folder ID of this folder.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
parent: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
ref: 'DriveFolder'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { Following } from '../entities/following';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType, types, bool } from '../../misc/schema';
|
||||
|
||||
type LocalFollowerFollowing = Following & {
|
||||
followerHost: null;
|
||||
|
@ -28,6 +29,8 @@ type RemoteFolloweeFollowing = Following & {
|
|||
followeeSharedInbox: string;
|
||||
};
|
||||
|
||||
export type PackedFollowing = SchemaType<typeof packedFollowingSchema>;
|
||||
|
||||
@EntityRepository(Following)
|
||||
export class FollowingRepository extends Repository<Following> {
|
||||
public isLocalFollower(following: Following): following is LocalFollowerFollowing {
|
||||
|
@ -64,22 +67,64 @@ export class FollowingRepository extends Repository<Following> {
|
|||
populateFollowee?: boolean;
|
||||
populateFollower?: boolean;
|
||||
}
|
||||
) {
|
||||
): Promise<PackedFollowing> {
|
||||
const following = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
if (opts == null) opts = {};
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: following.id,
|
||||
createdAt: following.createdAt,
|
||||
createdAt: following.createdAt.toISOString(),
|
||||
followeeId: following.followeeId,
|
||||
followerId: following.followerId,
|
||||
followee: opts.populateFollowee ? Users.pack(following.followee || following.followeeId, me, {
|
||||
detail: true
|
||||
}) : null,
|
||||
}) : undefined,
|
||||
follower: opts.populateFollower ? Users.pack(following.follower || following.followerId, me, {
|
||||
detail: true
|
||||
}) : null,
|
||||
}) : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const packedFollowingSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this following.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the following was created.'
|
||||
},
|
||||
followeeId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
},
|
||||
followee: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
ref: 'User',
|
||||
description: 'The followee.'
|
||||
},
|
||||
followerId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
},
|
||||
follower: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
ref: 'User',
|
||||
description: 'The follower.'
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { ReversiMatching } from '../../../entities/games/reversi/matching';
|
||||
import { Users } from '../../..';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
import { awaitAll } from '../../../../prelude/await-all';
|
||||
|
||||
@EntityRepository(ReversiMatching)
|
||||
export class ReversiMatchingRepository extends Repository<ReversiMatching> {
|
||||
|
@ -12,7 +12,7 @@ export class ReversiMatchingRepository extends Repository<ReversiMatching> {
|
|||
) {
|
||||
const matching = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: matching.id,
|
||||
createdAt: matching.createdAt,
|
||||
parentId: matching.parentId,
|
||||
|
|
|
@ -2,6 +2,9 @@ import { EntityRepository, Repository } from 'typeorm';
|
|||
import { MessagingMessage } from '../entities/messaging-message';
|
||||
import { Users, DriveFiles } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { types, bool, SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSchema>;
|
||||
|
||||
@EntityRepository(MessagingMessage)
|
||||
export class MessagingMessageRepository extends Repository<MessagingMessage> {
|
||||
|
@ -15,7 +18,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
|
|||
options?: {
|
||||
populateRecipient: boolean
|
||||
}
|
||||
) {
|
||||
): Promise<PackedMessagingMessage> {
|
||||
const opts = options || {
|
||||
populateRecipient: true
|
||||
};
|
||||
|
@ -24,15 +27,73 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
|
|||
|
||||
return {
|
||||
id: message.id,
|
||||
createdAt: message.createdAt,
|
||||
createdAt: message.createdAt.toISOString(),
|
||||
text: message.text,
|
||||
userId: message.userId,
|
||||
user: await Users.pack(message.user || message.userId, me),
|
||||
recipientId: message.recipientId,
|
||||
recipient: opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : null,
|
||||
recipient: opts.populateRecipient ? await Users.pack(message.recipient || message.recipientId, me) : undefined,
|
||||
fileId: message.fileId,
|
||||
file: message.fileId ? await DriveFiles.pack(message.fileId) : null,
|
||||
isRead: message.isRead
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const packedMessagingMessageSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this MessagingMessage.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the MessagingMessage was created.'
|
||||
},
|
||||
userId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
},
|
||||
user: {
|
||||
type: types.object,
|
||||
ref: 'User',
|
||||
optional: bool.true, nullable: bool.false,
|
||||
},
|
||||
text: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.true,
|
||||
},
|
||||
fileId: {
|
||||
type: types.string,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
format: 'id',
|
||||
},
|
||||
file: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
ref: 'DriveFile',
|
||||
},
|
||||
recipientId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
},
|
||||
recipient: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
ref: 'User'
|
||||
},
|
||||
isRead: {
|
||||
type: types.boolean,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { Muting } from '../entities/muting';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { types, bool, SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedMuting = SchemaType<typeof packedMutingSchema>;
|
||||
|
||||
@EntityRepository(Muting)
|
||||
export class MutingRepository extends Repository<Muting> {
|
||||
|
@ -16,14 +19,47 @@ export class MutingRepository extends Repository<Muting> {
|
|||
public async pack(
|
||||
src: Muting['id'] | Muting,
|
||||
me?: any
|
||||
) {
|
||||
): Promise<PackedMuting> {
|
||||
const muting = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: muting.id,
|
||||
createdAt: muting.createdAt.toISOString(),
|
||||
muteeId: muting.muteeId,
|
||||
mutee: Users.pack(muting.muteeId, me, {
|
||||
detail: true
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const packedMutingSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this muting.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the muting was created.'
|
||||
},
|
||||
muteeId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
},
|
||||
mutee: {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'User',
|
||||
description: 'The mutee.'
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,18 +2,54 @@ import { EntityRepository, Repository } from 'typeorm';
|
|||
import { NoteReaction } from '../entities/note-reaction';
|
||||
import { Users } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { types, bool, SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedNoteReaction = SchemaType<typeof packedNoteReactionSchema>;
|
||||
|
||||
@EntityRepository(NoteReaction)
|
||||
export class NoteReactionRepository extends Repository<NoteReaction> {
|
||||
public async pack(
|
||||
src: NoteReaction['id'] | NoteReaction,
|
||||
me?: any
|
||||
) {
|
||||
): Promise<PackedNoteReaction> {
|
||||
const reaction = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return {
|
||||
id: reaction.id,
|
||||
createdAt: reaction.createdAt.toISOString(),
|
||||
user: await Users.pack(reaction.userId, me),
|
||||
type: reaction.reaction,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const packedNoteReactionSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this reaction.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the reaction was created.'
|
||||
},
|
||||
user: {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'User',
|
||||
description: 'User who performed this reaction.'
|
||||
},
|
||||
type: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The reaction type.'
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,8 +4,11 @@ import { User } from '../entities/user';
|
|||
import { unique, concat } from '../../prelude/array';
|
||||
import { nyaize } from '../../misc/nyaize';
|
||||
import { Emojis, Users, Apps, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType, types, bool } from '../../misc/schema';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
|
||||
export type PackedNote = SchemaType<typeof packedNoteSchema>;
|
||||
|
||||
@EntityRepository(Note)
|
||||
export class NoteRepository extends Repository<Note> {
|
||||
|
@ -13,18 +16,18 @@ export class NoteRepository extends Repository<Note> {
|
|||
return x.trim().length <= 100;
|
||||
}
|
||||
|
||||
private async hideNote(packedNote: any, meId: User['id'] | null) {
|
||||
private async hideNote(packedNote: PackedNote, meId: User['id'] | null) {
|
||||
let hide = false;
|
||||
|
||||
// visibility が specified かつ自分が指定されていなかったら非表示
|
||||
if (packedNote.visibility == 'specified') {
|
||||
if (packedNote.visibility === 'specified') {
|
||||
if (meId == null) {
|
||||
hide = true;
|
||||
} else if (meId === packedNote.userId) {
|
||||
hide = false;
|
||||
} else {
|
||||
// 指定されているかどうか
|
||||
const specified = packedNote.visibleUserIds.some((id: any) => meId === id);
|
||||
const specified = packedNote.visibleUserIds!.some((id: any) => meId === id);
|
||||
|
||||
if (specified) {
|
||||
hide = false;
|
||||
|
@ -40,10 +43,10 @@ export class NoteRepository extends Repository<Note> {
|
|||
hide = true;
|
||||
} else if (meId === packedNote.userId) {
|
||||
hide = false;
|
||||
} else if (packedNote.reply && (meId === packedNote.reply.userId)) {
|
||||
} else if (packedNote.reply && (meId === (packedNote.reply as PackedNote).userId)) {
|
||||
// 自分の投稿に対するリプライ
|
||||
hide = false;
|
||||
} else if (packedNote.mentions && packedNote.mentions.some((id: any) => meId === id)) {
|
||||
} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
|
||||
// 自分へのメンション
|
||||
hide = false;
|
||||
} else {
|
||||
|
@ -62,14 +65,13 @@ export class NoteRepository extends Repository<Note> {
|
|||
}
|
||||
|
||||
if (hide) {
|
||||
packedNote.visibleUserIds = null;
|
||||
packedNote.visibleUserIds = undefined;
|
||||
packedNote.fileIds = [];
|
||||
packedNote.files = [];
|
||||
packedNote.text = null;
|
||||
packedNote.poll = null;
|
||||
packedNote.poll = undefined;
|
||||
packedNote.cw = null;
|
||||
packedNote.tags = [];
|
||||
packedNote.geo = null;
|
||||
packedNote.geo = undefined;
|
||||
packedNote.isHidden = true;
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +94,7 @@ export class NoteRepository extends Repository<Note> {
|
|||
detail?: boolean;
|
||||
skipHide?: boolean;
|
||||
}
|
||||
): Promise<Record<string, any>> {
|
||||
): Promise<PackedNote> {
|
||||
const opts = Object.assign({
|
||||
detail: true,
|
||||
skipHide: false
|
||||
|
@ -159,9 +161,9 @@ export class NoteRepository extends Repository<Note> {
|
|||
|
||||
const reactionEmojis = unique(concat([note.emojis, Object.keys(note.reactions)]));
|
||||
|
||||
const packed = await rap({
|
||||
const packed = await awaitAll({
|
||||
id: note.id,
|
||||
createdAt: note.createdAt,
|
||||
createdAt: note.createdAt.toISOString(),
|
||||
app: note.appId ? Apps.pack(note.appId) : undefined,
|
||||
userId: note.userId,
|
||||
user: Users.pack(note.user || note.userId, meId),
|
||||
|
@ -213,3 +215,127 @@ export class NoteRepository extends Repository<Note> {
|
|||
return packed;
|
||||
}
|
||||
}
|
||||
|
||||
export const packedNoteSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this Note.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the Note was created on Misskey.'
|
||||
},
|
||||
text: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.true,
|
||||
},
|
||||
cw: {
|
||||
type: types.string,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
},
|
||||
userId: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
},
|
||||
user: {
|
||||
type: types.object,
|
||||
ref: 'User',
|
||||
optional: bool.false, nullable: bool.false,
|
||||
},
|
||||
replyId: {
|
||||
type: types.string,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
renoteId: {
|
||||
type: types.string,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
reply: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
ref: 'Note'
|
||||
},
|
||||
renote: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
ref: 'Note'
|
||||
},
|
||||
viaMobile: {
|
||||
type: types.boolean,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
},
|
||||
isHidden: {
|
||||
type: types.boolean,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
},
|
||||
visibility: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
},
|
||||
mentions: {
|
||||
type: types.array,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
items: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id'
|
||||
}
|
||||
},
|
||||
visibleUserIds: {
|
||||
type: types.array,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
items: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id'
|
||||
}
|
||||
},
|
||||
fileIds: {
|
||||
type: types.array,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
items: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id'
|
||||
}
|
||||
},
|
||||
files: {
|
||||
type: types.array,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
items: {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFile'
|
||||
}
|
||||
},
|
||||
tags: {
|
||||
type: types.array,
|
||||
optional: bool.true, nullable: bool.false,
|
||||
items: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
}
|
||||
},
|
||||
poll: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
},
|
||||
geo: {
|
||||
type: types.object,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users, Notes } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { Notification } from '../entities/notification';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { types, bool, SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedNotification = SchemaType<typeof packedNotificationSchema>;
|
||||
|
||||
@EntityRepository(Notification)
|
||||
export class NotificationRepository extends Repository<Notification> {
|
||||
|
@ -14,12 +17,12 @@ export class NotificationRepository extends Repository<Notification> {
|
|||
|
||||
public async pack(
|
||||
src: Notification['id'] | Notification,
|
||||
) {
|
||||
): Promise<PackedNotification> {
|
||||
const notification = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
return await rap({
|
||||
return await awaitAll({
|
||||
id: notification.id,
|
||||
createdAt: notification.createdAt,
|
||||
createdAt: notification.createdAt.toISOString(),
|
||||
type: notification.type,
|
||||
userId: notification.notifierId,
|
||||
user: Users.pack(notification.notifier || notification.notifierId),
|
||||
|
@ -46,3 +49,39 @@ export class NotificationRepository extends Repository<Notification> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const packedNotificationSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this notification.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the notification was created.'
|
||||
},
|
||||
type: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
enum: ['follow', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'],
|
||||
description: 'The type of the notification.'
|
||||
},
|
||||
userId: {
|
||||
type: types.string,
|
||||
optional: bool.true, nullable: bool.true,
|
||||
format: 'id',
|
||||
},
|
||||
user: {
|
||||
type: types.object,
|
||||
ref: 'User',
|
||||
optional: bool.true, nullable: bool.true,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,12 +2,15 @@ import { EntityRepository, Repository } from 'typeorm';
|
|||
import { UserList } from '../entities/user-list';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { UserListJoinings } from '..';
|
||||
import { bool, types, SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedUserList = SchemaType<typeof packedUserListSchema>;
|
||||
|
||||
@EntityRepository(UserList)
|
||||
export class UserListRepository extends Repository<UserList> {
|
||||
public async pack(
|
||||
src: UserList['id'] | UserList,
|
||||
) {
|
||||
): Promise<PackedUserList> {
|
||||
const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
|
||||
const users = await UserListJoinings.find({
|
||||
|
@ -16,8 +19,43 @@ export class UserListRepository extends Repository<UserList> {
|
|||
|
||||
return {
|
||||
id: userList.id,
|
||||
createdAt: userList.createdAt.toISOString(),
|
||||
name: userList.name,
|
||||
userIds: users.map(x => x.userId)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const packedUserListSchema = {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this UserList.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'date-time',
|
||||
description: 'The date that the UserList was created.'
|
||||
},
|
||||
name: {
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The name of the UserList.'
|
||||
},
|
||||
userIds: {
|
||||
type: types.array,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
items: {
|
||||
type: types.string,
|
||||
nullable: bool.false, optional: bool.false,
|
||||
format: 'id',
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { EntityRepository, Repository, In } from 'typeorm';
|
||||
import { User, ILocalUser, IRemoteUser } from '../entities/user';
|
||||
import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles } from '..';
|
||||
import rap from '@prezzemolo/rap';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import config from '../../config';
|
||||
import { SchemaType, bool, types } from '../../misc/schema';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
|
||||
export type PackedUser = SchemaType<typeof packedUserSchema>;
|
||||
|
||||
@EntityRepository(User)
|
||||
export class UserRepository extends Repository<User> {
|
||||
|
@ -71,7 +74,7 @@ export class UserRepository extends Repository<User> {
|
|||
includeSecrets?: boolean,
|
||||
includeHasUnreadNotes?: boolean
|
||||
}
|
||||
): Promise<Record<string, any>> {
|
||||
): Promise<PackedUser> {
|
||||
const opts = Object.assign({
|
||||
detail: false,
|
||||
includeSecrets: false
|
||||
|
@ -86,7 +89,7 @@ export class UserRepository extends Repository<User> {
|
|||
|
||||
const falsy = opts.detail ? false : undefined;
|
||||
|
||||
return await rap({
|
||||
const packed = {
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
username: user.username,
|
||||
|
@ -120,8 +123,8 @@ export class UserRepository extends Repository<User> {
|
|||
|
||||
...(opts.detail ? {
|
||||
url: profile!.url,
|
||||
createdAt: user.createdAt,
|
||||
updatedAt: user.updatedAt,
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,
|
||||
bannerUrl: user.bannerUrl,
|
||||
bannerColor: user.bannerColor,
|
||||
isLocked: user.isLocked,
|
||||
|
@ -179,7 +182,9 @@ export class UserRepository extends Repository<User> {
|
|||
isBlocked: relation.isBlocked,
|
||||
isMuted: relation.isMuted,
|
||||
} : {})
|
||||
});
|
||||
};
|
||||
|
||||
return await awaitAll(packed);
|
||||
}
|
||||
|
||||
public isLocalUser(user: User): user is ILocalUser {
|
||||
|
@ -216,3 +221,156 @@ export class UserRepository extends Repository<User> {
|
|||
}
|
||||
//#endregion
|
||||
}
|
||||
|
||||
export const packedUserSchema = {
|
||||
type: types.object,
|
||||
nullable: bool.false, optional: bool.false,
|
||||
properties: {
|
||||
id: {
|
||||
type: types.string,
|
||||
nullable: bool.false, optional: bool.false,
|
||||
format: 'id',
|
||||
description: 'The unique identifier for this User.',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
username: {
|
||||
type: types.string,
|
||||
nullable: bool.false, optional: bool.false,
|
||||
description: 'The screen name, handle, or alias that this user identifies themselves with.',
|
||||
example: 'ai'
|
||||
},
|
||||
name: {
|
||||
type: types.string,
|
||||
nullable: bool.true, optional: bool.false,
|
||||
description: 'The name of the user, as they’ve defined it.',
|
||||
example: '藍'
|
||||
},
|
||||
url: {
|
||||
type: types.string,
|
||||
format: 'url',
|
||||
nullable: bool.true, optional: bool.true,
|
||||
},
|
||||
avatarUrl: {
|
||||
type: types.string,
|
||||
format: 'url',
|
||||
nullable: bool.true, optional: bool.false,
|
||||
},
|
||||
avatarColor: {
|
||||
type: types.any,
|
||||
nullable: bool.true, optional: bool.false,
|
||||
},
|
||||
bannerUrl: {
|
||||
type: types.string,
|
||||
format: 'url',
|
||||
nullable: bool.true, optional: bool.true,
|
||||
},
|
||||
bannerColor: {
|
||||
type: types.any,
|
||||
nullable: bool.true, optional: bool.true,
|
||||
},
|
||||
emojis: {
|
||||
type: types.any,
|
||||
nullable: bool.true, optional: bool.false,
|
||||
},
|
||||
host: {
|
||||
type: types.string,
|
||||
nullable: bool.true, optional: bool.false,
|
||||
example: 'misskey.example.com'
|
||||
},
|
||||
description: {
|
||||
type: types.string,
|
||||
nullable: bool.true, optional: bool.true,
|
||||
description: 'The user-defined UTF-8 string describing their account.',
|
||||
example: 'Hi masters, I am Ai!'
|
||||
},
|
||||
birthday: {
|
||||
type: types.string,
|
||||
nullable: bool.true, optional: bool.true,
|
||||
example: '2018-03-12'
|
||||
},
|
||||
createdAt: {
|
||||
type: types.string,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
format: 'date-time',
|
||||
description: 'The date that the user account was created on Misskey.'
|
||||
},
|
||||
updatedAt: {
|
||||
type: types.string,
|
||||
nullable: bool.true, optional: bool.true,
|
||||
format: 'date-time',
|
||||
},
|
||||
location: {
|
||||
type: types.string,
|
||||
nullable: bool.true, optional: bool.true,
|
||||
},
|
||||
followersCount: {
|
||||
type: types.number,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
description: 'The number of followers this account currently has.'
|
||||
},
|
||||
followingCount: {
|
||||
type: types.number,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
description: 'The number of users this account is following.'
|
||||
},
|
||||
notesCount: {
|
||||
type: types.number,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
description: 'The number of Notes (including renotes) issued by the user.'
|
||||
},
|
||||
isBot: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
description: 'Whether this account is a bot.'
|
||||
},
|
||||
pinnedNoteIds: {
|
||||
type: types.array,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
items: {
|
||||
type: types.string,
|
||||
nullable: bool.false, optional: bool.false,
|
||||
format: 'id',
|
||||
}
|
||||
},
|
||||
pinnedNotes: {
|
||||
type: types.array,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
items: {
|
||||
type: types.object,
|
||||
nullable: bool.false, optional: bool.false,
|
||||
ref: 'Note'
|
||||
}
|
||||
},
|
||||
isCat: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
description: 'Whether this account is a cat.'
|
||||
},
|
||||
isAdmin: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
description: 'Whether this account is the admin.'
|
||||
},
|
||||
isModerator: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
description: 'Whether this account is a moderator.'
|
||||
},
|
||||
isVerified: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
},
|
||||
isLocked: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
},
|
||||
hasUnreadSpecifiedNotes: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
},
|
||||
hasUnreadMentions: {
|
||||
type: types.boolean,
|
||||
nullable: bool.false, optional: bool.true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
23
src/prelude/await-all.ts
Normal file
23
src/prelude/await-all.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
type Await<T> = T extends Promise<infer U> ? U : T;
|
||||
|
||||
type AwaitAll<T> = {
|
||||
[P in keyof T]: Await<T[P]>;
|
||||
};
|
||||
|
||||
export async function awaitAll<T>(obj: T): Promise<AwaitAll<T>> {
|
||||
const target = {} as any;
|
||||
const keys = Object.keys(obj);
|
||||
const values = Object.values(obj);
|
||||
|
||||
const resolvedValues = await Promise.all(values.map(value =>
|
||||
(!value || !value.constructor || value.constructor.name !== 'Object')
|
||||
? value
|
||||
: awaitAll(value)
|
||||
));
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
target[keys[i]] = resolvedValues[i];
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
|
@ -10,7 +10,7 @@ import { registerOrFetchInstanceDoc } from '../../services/register-or-fetch-ins
|
|||
import { Instances, Users, UserPublickeys } from '../../models';
|
||||
import { instanceChart } from '../../services/chart';
|
||||
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 { validActor } from '../../remote/activitypub/type';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
@ -48,7 +48,6 @@ export default async (job: Bull.Job): Promise<void> => {
|
|||
}
|
||||
|
||||
// ブロックしてたら中断
|
||||
// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(host)) {
|
||||
logger.info(`Blocked request: ${host}`);
|
||||
|
|
|
@ -6,7 +6,7 @@ import { fetchNote, resolveNote } from '../../models/note';
|
|||
import { resolvePerson } from '../../models/person';
|
||||
import { apLogger } from '../../logger';
|
||||
import { extractDbHost } from '../../../../misc/convert-host';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
|
||||
const logger = apLogger;
|
||||
|
||||
|
@ -26,7 +26,6 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
|
|||
}
|
||||
|
||||
// アナウンス先をブロックしてたら中断
|
||||
// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(extractDbHost(uri))) return;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import uploadFromUrl from '../../../services/drive/upload-from-url';
|
||||
import { IRemoteUser } from '../../../models/entities/user';
|
||||
import Resolver from '../resolver';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { apLogger } from '../logger';
|
||||
import { DriveFile } from '../../../models/entities/drive-file';
|
||||
import { DriveFiles } from '../../../models';
|
||||
|
|
|
@ -20,7 +20,7 @@ import { Note } from '../../../models/entities/note';
|
|||
import { IObject, INote } from '../type';
|
||||
import { Emoji } from '../../../models/entities/emoji';
|
||||
import { genId } from '../../../misc/gen-id';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
const logger = apLogger;
|
||||
|
@ -233,7 +233,6 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver):
|
|||
if (uri == null) throw new Error('missing uri');
|
||||
|
||||
// ブロックしてたら中断
|
||||
// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(extractDbHost(uri))) throw { statusCode: 451 };
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { ILocalUser } from '../../models/entities/user';
|
|||
import { publishApLogStream } from '../../services/stream';
|
||||
import { apLogger } from './logger';
|
||||
import { UserKeypairs } from '../../models';
|
||||
import fetchMeta from '../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../misc/fetch-meta';
|
||||
import { toPuny } from '../../misc/convert-host';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
|
@ -24,7 +24,6 @@ export default async (user: ILocalUser, url: string, object: any) => {
|
|||
const { protocol, host, hostname, port, pathname, search } = new URL(url);
|
||||
|
||||
// ブロックしてたら中断
|
||||
// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(toPuny(host))) return;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ILocalUser } from '../../models/entities/user';
|
|||
import { IEndpointMeta } from './endpoints';
|
||||
import { ApiError } from './error';
|
||||
import { App } from '../../models/entities/app';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
type Params<T extends IEndpointMeta> = {
|
||||
[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
|
||||
|
@ -12,7 +13,11 @@ type Params<T extends IEndpointMeta> = {
|
|||
|
||||
export type Response = Record<string, any> | void;
|
||||
|
||||
export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T>, user: ILocalUser, app: App, file?: any, cleanup?: Function) => Promise<Response>): (params: any, user: ILocalUser, app: App, file?: any) => Promise<any> {
|
||||
type executor<T extends IEndpointMeta> =
|
||||
(params: Params<T>, user: ILocalUser, app: App, file?: any, cleanup?: Function) => Promise<T['res'] extends undefined ? Response : SchemaType<NonNullable<T['res']>>>;
|
||||
|
||||
export default function <T extends IEndpointMeta>(meta: T, cb: executor<T>)
|
||||
: (params: any, user: ILocalUser, app: App, file?: any) => Promise<any> {
|
||||
return (params: any, user: ILocalUser, app: App, file?: any) => {
|
||||
function cleanup() {
|
||||
fs.unlink(file.path, () => {});
|
||||
|
|
|
@ -164,7 +164,7 @@ export const meta = {
|
|||
},
|
||||
|
||||
maintainerName: {
|
||||
validator: $.optional.str,
|
||||
validator: $.optional.nullable.str,
|
||||
desc: {
|
||||
'ja-JP': 'インスタンスの管理者名'
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { extractDbHost } from '../../../../misc/convert-host';
|
|||
import { Users, Notes } from '../../../../models';
|
||||
import { Note } from '../../../../models/entities/note';
|
||||
import { User } from '../../../../models/entities/user';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import { validActor } from '../../../../remote/activitypub/type';
|
||||
|
||||
export const meta = {
|
||||
|
|
|
@ -4,6 +4,7 @@ import define from '../../define';
|
|||
import { Apps } from '../../../../models';
|
||||
import { genId } from '../../../../misc/gen-id';
|
||||
import { unique } from '../../../../prelude/array';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['app'],
|
||||
|
@ -52,27 +53,10 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'アプリケーションのID'
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'アプリケーションの名前'
|
||||
},
|
||||
callbackUrl: {
|
||||
type: 'string',
|
||||
nullable: true,
|
||||
description: 'コールバックするURL'
|
||||
},
|
||||
secret: {
|
||||
type: 'string',
|
||||
description: 'アプリケーションのシークレットキー'
|
||||
}
|
||||
}
|
||||
}
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'App',
|
||||
},
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
|
|||
import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { Apps } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['app'],
|
||||
|
@ -13,6 +14,12 @@ export const meta = {
|
|||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'App',
|
||||
},
|
||||
|
||||
errors: {
|
||||
noSuchApp: {
|
||||
message: 'No such app.',
|
||||
|
|
|
@ -5,6 +5,7 @@ import define from '../../../define';
|
|||
import { ApiError } from '../../../error';
|
||||
import { Apps, AuthSessions } from '../../../../../models';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
|
@ -27,14 +28,18 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
token: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'セッションのトークン'
|
||||
},
|
||||
url: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
format: 'url',
|
||||
description: 'セッションのURL'
|
||||
},
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import define from '../../../define';
|
|||
import { ApiError } from '../../../error';
|
||||
import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
|
@ -28,15 +29,19 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'ユーザーのアクセストークン',
|
||||
},
|
||||
|
||||
user: {
|
||||
type: 'User',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'User',
|
||||
description: '認証したユーザー'
|
||||
},
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
|
|||
import define from '../../define';
|
||||
import { Blockings } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -32,9 +33,12 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Blocking',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Blocking',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import define from '../define';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { DriveFiles } from '../../../models';
|
||||
import { types, bool } from '../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -15,20 +16,23 @@ export const meta = {
|
|||
kind: 'read:drive',
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
capacity: {
|
||||
type: 'number'
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
},
|
||||
usage: {
|
||||
type: 'number'
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const instance = await fetchMeta();
|
||||
const instance = await fetchMeta(true);
|
||||
|
||||
// Calculate drive usage
|
||||
const usage = await DriveFiles.clacDriveUsageOf(user);
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
|
|||
import define from '../../define';
|
||||
import { DriveFiles } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -41,10 +42,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'DriveFile',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFile',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ import $ from 'cafy';
|
|||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
import { DriveFiles, Notes } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
@ -29,10 +30,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
@ -55,8 +59,11 @@ export default define(meta, async (ps, user) => {
|
|||
throw new ApiError(meta.errors.noSuchFile);
|
||||
}
|
||||
|
||||
/* v11 TODO
|
||||
return await packMany(file.metadata.attachedNoteIds || [], user, {
|
||||
const notes = await Notes.createQueryBuilder('note')
|
||||
.where(':file = ANY(note.fileIds)', { file: file.id })
|
||||
.getMany();
|
||||
|
||||
return await Notes.packMany(notes, user, {
|
||||
detail: true
|
||||
});*/
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -24,7 +25,8 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'DriveFile',
|
||||
type: types.boolean,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -34,7 +36,5 @@ export default define(meta, async (ps, user) => {
|
|||
userId: user.id,
|
||||
});
|
||||
|
||||
return {
|
||||
file: file ? await DriveFiles.pack(file, { self: true }) : null
|
||||
};
|
||||
return file != null;
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@ import define from '../../../define';
|
|||
import { apiLogger } from '../../../logger';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -56,7 +57,9 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'DriveFile',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFile',
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
@ -87,7 +90,7 @@ export default define(meta, async (ps, user, app, file, cleanup) => {
|
|||
try {
|
||||
// Create file
|
||||
const driveFile = await create(user, file.path, name, null, ps.folderId, ps.force, false, null, null, ps.isSensitive);
|
||||
return DriveFiles.pack(driveFile, { self: true });
|
||||
return await DriveFiles.pack(driveFile, { self: true });
|
||||
} catch (e) {
|
||||
apiLogger.error(e);
|
||||
throw new ApiError();
|
||||
|
|
44
src/server/api/endpoints/drive/files/find-by-hash.ts
Normal file
44
src/server/api/endpoints/drive/files/find-by-hash.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
'ja-JP': '与えられたMD5ハッシュ値を持つファイルを取得します。',
|
||||
},
|
||||
|
||||
tags: ['drive'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
md5: {
|
||||
validator: $.str,
|
||||
desc: {
|
||||
'ja-JP': 'ファイルのMD5ハッシュ'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
res: {
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFile',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const files = await DriveFiles.find({
|
||||
md5: ps.md5,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
return await DriveFiles.packMany(files, { self: true });
|
||||
});
|
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
|||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
@ -22,7 +23,17 @@ export const meta = {
|
|||
'ja-JP': 'フォルダID'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
res: {
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFile',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
|
|
|
@ -4,6 +4,7 @@ import define from '../../../define';
|
|||
import { ApiError } from '../../../error';
|
||||
import { DriveFile } from '../../../../../models/entities/drive-file';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
@ -38,7 +39,9 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'DriveFile',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFile',
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
|
|||
import define from '../../define';
|
||||
import { DriveFolders } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -37,10 +38,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'DriveFolder',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFolder',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
|||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { DriveFolders } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['drive'],
|
||||
|
@ -25,10 +26,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'DriveFolder',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFolder',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../../../misc/cafy-id';
|
|||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFolders } from '../../../../../models';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
@ -29,7 +30,9 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'DriveFolder',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFolder',
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
|
|||
import define from '../../define';
|
||||
import { DriveFiles } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['drive'],
|
||||
|
@ -31,10 +32,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'DriveFile',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'DriveFile',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import { Instances } from '../../../../models';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
|
||||
export const meta = {
|
||||
tags: ['federation'],
|
||||
|
@ -62,7 +62,7 @@ export default define(meta, async (ps, me) => {
|
|||
}
|
||||
|
||||
if (typeof ps.blocked === 'boolean') {
|
||||
const meta = await fetchMeta();
|
||||
const meta = await fetchMeta(true);
|
||||
if (ps.blocked) {
|
||||
query.andWhere('instance.host IN (:...blocks)', { blocks: meta.blockedHosts });
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import { Hashtags } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['hashtags'],
|
||||
|
@ -47,9 +48,12 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Hashtag'
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Hashtag',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import { Hashtags } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -37,9 +38,11 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'string'
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import { Notes } from '../../../../models';
|
||||
import { Note } from '../../../../models/entities/note';
|
||||
|
||||
|
@ -24,7 +24,7 @@ export const meta = {
|
|||
};
|
||||
|
||||
export default define(meta, async () => {
|
||||
const instance = await fetchMeta();
|
||||
const instance = await fetchMeta(true);
|
||||
const hiddenTags = instance.hiddenTags.map(t => t.toLowerCase());
|
||||
|
||||
const tagNotes = await Notes.createQueryBuilder('note')
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import { Users } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: false,
|
||||
|
@ -47,9 +48,12 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'User'
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'User',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import define from '../define';
|
||||
import { Users } from '../../../models';
|
||||
import { types, bool } from '../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
@ -15,8 +16,10 @@ export const meta = {
|
|||
params: {},
|
||||
|
||||
res: {
|
||||
type: 'User',
|
||||
}
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'User',
|
||||
},
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user, app) => {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { readNotification } from '../../common/read-notification';
|
|||
import define from '../../define';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { Notifications, Followings, Mutings } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -53,10 +54,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Notification',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Notification',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import $ from 'cafy';
|
|||
import { publishMainStream } from '../../../../services/stream';
|
||||
import define from '../../define';
|
||||
import * as nodemailer from 'nodemailer';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import rndstr from 'rndstr';
|
||||
import config from '../../../../config';
|
||||
import * as ms from 'ms';
|
||||
|
@ -63,7 +63,7 @@ export default define(meta, async (ps, user) => {
|
|||
emailVerifyCode: code
|
||||
});
|
||||
|
||||
const meta = await fetchMeta();
|
||||
const meta = await fetchMeta(true);
|
||||
|
||||
const enableAuth = meta.smtpUser != null && meta.smtpUser !== '';
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import define from '../../define';
|
|||
import { MessagingMessage } from '../../../../models/entities/messaging-message';
|
||||
import { MessagingMessages, Mutings } from '../../../../models';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -24,10 +25,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'MessagingMessage',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'MessagingMessage',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import { ApiError } from '../../error';
|
|||
import { getUser } from '../../common/getters';
|
||||
import { MessagingMessages } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -48,10 +49,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'MessagingMessage',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'MessagingMessage',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -9,6 +9,7 @@ import { getUser } from '../../../common/getters';
|
|||
import { MessagingMessages, DriveFiles, Mutings } from '../../../../../models';
|
||||
import { MessagingMessage } from '../../../../../models/entities/messaging-message';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
import { types, bool } from '../../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -41,7 +42,9 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'MessagingMessage',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'MessagingMessage',
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -2,9 +2,10 @@ import $ from 'cafy';
|
|||
import * as os from 'os';
|
||||
import config from '../../../config';
|
||||
import define from '../define';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import * as pkg from '../../../../package.json';
|
||||
import { Emojis } from '../../../models';
|
||||
import { types, bool } from '../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
@ -26,32 +27,40 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
version: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The version of Misskey of this instance.',
|
||||
example: pkg.version
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The name of this instance.',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The description of this instance.',
|
||||
},
|
||||
announcements: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'object',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The title of the announcement.',
|
||||
},
|
||||
text: {
|
||||
type: 'string',
|
||||
type: types.string,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The text of the announcement. (can be HTML)',
|
||||
},
|
||||
}
|
||||
|
@ -59,19 +68,23 @@ export const meta = {
|
|||
description: 'The announcements of this instance.',
|
||||
},
|
||||
disableRegistration: {
|
||||
type: 'boolean',
|
||||
type: types.boolean,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'Whether disabled open registration.',
|
||||
},
|
||||
disableLocalTimeline: {
|
||||
type: 'boolean',
|
||||
type: types.boolean,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'Whether disabled LTL and STL.',
|
||||
},
|
||||
disableGlobalTimeline: {
|
||||
type: 'boolean',
|
||||
type: types.boolean,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'Whether disabled GTL.',
|
||||
},
|
||||
enableEmojiReaction: {
|
||||
type: 'boolean',
|
||||
type: types.boolean,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'Whether enabled emoji reaction.',
|
||||
},
|
||||
}
|
||||
|
@ -79,7 +92,7 @@ export const meta = {
|
|||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const instance = await fetchMeta();
|
||||
const instance = await fetchMeta(true);
|
||||
|
||||
const emojis = await Emojis.find({ host: null });
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../../misc/cafy-id';
|
|||
import define from '../../define';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { Mutings } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -32,9 +33,12 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Muting',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Muting',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ID } from '../../../misc/cafy-id';
|
|||
import define from '../define';
|
||||
import { makePaginationQuery } from '../common/make-pagination-query';
|
||||
import { Notes } from '../../../models';
|
||||
import { types, bool } from '../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -62,9 +63,12 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
|
|||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { Notes } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -41,10 +42,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import { ApiError } from '../../error';
|
|||
import { getNote } from '../../common/getters';
|
||||
import { Note } from '../../../../models/entities/note';
|
||||
import { Notes } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -37,10 +38,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -3,13 +3,14 @@ import * as ms from 'ms';
|
|||
import { length } from 'stringz';
|
||||
import create from '../../../../services/note/create';
|
||||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import { ApiError } from '../../error';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import { User } from '../../../../models/entities/user';
|
||||
import { Users, DriveFiles, Notes } from '../../../../models';
|
||||
import { DriveFile } from '../../../../models/entities/drive-file';
|
||||
import { Note } from '../../../../models/entities/note';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
let maxNoteTextLength = 1000;
|
||||
|
||||
|
@ -174,10 +175,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
createdNote: {
|
||||
type: 'Note',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
description: '作成した投稿'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
|||
import define from '../../define';
|
||||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { Notes } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -24,10 +25,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import $ from 'cafy';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import { ApiError } from '../../error';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { Notes } from '../../../../models';
|
||||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { activeUsersChart } from '../../../../services/chart';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -46,10 +47,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
@ -62,7 +66,6 @@ export const meta = {
|
|||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// TODO どっかにキャッシュ
|
||||
const m = await fetchMeta();
|
||||
if (m.disableGlobalTimeline) {
|
||||
if (user == null || (!user.isAdmin && !user.isModerator)) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import $ from 'cafy';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import { ApiError } from '../../error';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { Followings, Notes } from '../../../../models';
|
||||
|
@ -9,6 +9,7 @@ import { Brackets } from 'typeorm';
|
|||
import { generateVisibilityQuery } from '../../common/generate-visibility-query';
|
||||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { activeUsersChart } from '../../../../services/chart';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -89,10 +90,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
@ -105,7 +109,6 @@ export const meta = {
|
|||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// TODO どっかにキャッシュ
|
||||
const m = await fetchMeta();
|
||||
if (m.disableLocalTimeline && !user.isAdmin && !user.isModerator) {
|
||||
throw new ApiError(meta.errors.stlDisabled);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import $ from 'cafy';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import { ApiError } from '../../error';
|
||||
import { Notes } from '../../../../models';
|
||||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
|
@ -9,6 +9,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query';
|
|||
import { generateVisibilityQuery } from '../../common/generate-visibility-query';
|
||||
import { activeUsersChart } from '../../../../services/chart';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -63,10 +64,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
@ -79,7 +83,6 @@ export const meta = {
|
|||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// TODO どっかにキャッシュ
|
||||
const m = await fetchMeta();
|
||||
if (m.disableLocalTimeline) {
|
||||
if (user == null || (!user.isAdmin && !user.isModerator)) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
|
|||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -43,10 +44,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import define from '../../define';
|
|||
import { getNote } from '../../common/getters';
|
||||
import { ApiError } from '../../error';
|
||||
import { NoteReactions } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -44,9 +45,12 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Reaction'
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'NoteReaction',
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
|
|||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { Notes } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -42,10 +43,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { Notes } from '../../../../models';
|
|||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { generateVisibilityQuery } from '../../common/generate-visibility-query';
|
||||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -46,10 +47,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Notes } from '../../../../models';
|
|||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { generateVisibilityQuery } from '../../common/generate-visibility-query';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -81,10 +82,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -96,14 +100,14 @@ export default define(meta, async (ps, me) => {
|
|||
if (me) generateMuteQuery(query, me);
|
||||
|
||||
if (ps.tag) {
|
||||
query.andWhere(':tag = ANY(note.tags)', { tag: ps.tag });
|
||||
query.andWhere(':tag = ANY(note.tags)', { tag: ps.tag.toLowerCase() });
|
||||
} else {
|
||||
let i = 0;
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const tags of ps.query!) {
|
||||
qb.orWhere(new Brackets(qb => {
|
||||
for (const tag of tags) {
|
||||
qb.andWhere(`:tag${i} = ANY(note.tags)`, { [`tag${i}`]: tag });
|
||||
qb.andWhere(`:tag${i} = ANY(note.tags)`, { [`tag${i}`]: tag.toLowerCase() });
|
||||
i++;
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -4,6 +4,7 @@ import define from '../../define';
|
|||
import { ApiError } from '../../error';
|
||||
import { Notes } from '../../../../models';
|
||||
import { In } from 'typeorm';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -32,10 +33,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -4,6 +4,7 @@ import define from '../../define';
|
|||
import { getNote } from '../../common/getters';
|
||||
import { ApiError } from '../../error';
|
||||
import { Notes } from '../../../../models';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
@ -28,7 +29,9 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'Note',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query'
|
|||
import { generateMuteQuery } from '../../common/generate-mute-query';
|
||||
import { activeUsersChart } from '../../../../services/chart';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -88,10 +89,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import { UserLists, UserListJoinings, Notes } from '../../../../models';
|
|||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { generateVisibilityQuery } from '../../common/generate-visibility-query';
|
||||
import { activeUsersChart } from '../../../../services/chart';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -94,10 +95,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Note',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Note',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import define from '../define';
|
||||
import { Notes, Users } from '../../../models';
|
||||
import { federationChart, driveChart } from '../../../services/chart';
|
||||
import { bool, types } from '../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: false,
|
||||
|
@ -15,26 +16,32 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
properties: {
|
||||
notesCount: {
|
||||
type: 'number',
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The count of all (local/remote) notes of this instance.',
|
||||
},
|
||||
originalNotesCount: {
|
||||
type: 'number',
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The count of all local notes of this instance.',
|
||||
},
|
||||
usersCount: {
|
||||
type: 'number',
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The count of all (local/remote) accounts of this instance.',
|
||||
},
|
||||
originalUsersCount: {
|
||||
type: 'number',
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The count of all local accounts of this instance.',
|
||||
},
|
||||
instances: {
|
||||
type: 'number',
|
||||
type: types.number,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
description: 'The count of federated instances.',
|
||||
},
|
||||
}
|
||||
|
@ -42,7 +49,14 @@ export const meta = {
|
|||
};
|
||||
|
||||
export default define(meta, async () => {
|
||||
const [notesCount, originalNotesCount, usersCount, originalUsersCount, instances, driveUsageLocal, driveUsageRemote] = await Promise.all([
|
||||
const [notesCount,
|
||||
originalNotesCount,
|
||||
usersCount,
|
||||
originalUsersCount,
|
||||
instances,
|
||||
driveUsageLocal,
|
||||
driveUsageRemote
|
||||
] = await Promise.all([
|
||||
Notes.count(),
|
||||
Notes.count({ userHost: null }),
|
||||
Users.count(),
|
||||
|
@ -53,6 +67,12 @@ export default define(meta, async () => {
|
|||
]);
|
||||
|
||||
return {
|
||||
notesCount, originalNotesCount, usersCount, originalUsersCount, instances, driveUsageLocal, driveUsageRemote
|
||||
notesCount,
|
||||
originalNotesCount,
|
||||
usersCount,
|
||||
originalUsersCount,
|
||||
instances,
|
||||
driveUsageLocal,
|
||||
driveUsageRemote
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { fetchMeta } from '../../../../misc/fetch-meta';
|
||||
import { genId } from '../../../../misc/gen-id';
|
||||
import { SwSubscriptions } from '../../../../models';
|
||||
|
||||
|
@ -33,7 +33,7 @@ export default define(meta, async (ps, user) => {
|
|||
publickey: ps.publickey,
|
||||
});
|
||||
|
||||
const instance = await fetchMeta();
|
||||
const instance = await fetchMeta(true);
|
||||
|
||||
if (exist != null) {
|
||||
return {
|
||||
|
|
|
@ -2,6 +2,7 @@ import $ from 'cafy';
|
|||
import define from '../define';
|
||||
import { Users } from '../../../models';
|
||||
import { generateMuteQueryForUsers } from '../common/generate-mute-query';
|
||||
import { types, bool } from '../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
tags: ['users'],
|
||||
|
@ -53,9 +54,12 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'User',
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'User',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@ import { ApiError } from '../../error';
|
|||
import { Users, Followings } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { toPunyNullable } from '../../../../misc/convert-host';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -48,10 +49,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Following',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Following',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { ApiError } from '../../error';
|
|||
import { Users, Followings } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { toPunyNullable } from '../../../../misc/convert-host';
|
||||
import { types, bool } from '../../../../misc/schema';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
|
@ -48,10 +49,13 @@ export const meta = {
|
|||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
type: types.array,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
items: {
|
||||
type: 'Following',
|
||||
},
|
||||
type: types.object,
|
||||
optional: bool.false, nullable: bool.false,
|
||||
ref: 'Following',
|
||||
}
|
||||
},
|
||||
|
||||
errors: {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue