forked from FoundKeyGang/FoundKey
良い感じに
This commit is contained in:
parent
560bb65384
commit
f7069dcd18
11 changed files with 225 additions and 164 deletions
|
@ -832,7 +832,7 @@ desktop/views/components/settings.vue:
|
||||||
profile: "プロフィール"
|
profile: "プロフィール"
|
||||||
notification: "通知"
|
notification: "通知"
|
||||||
apps: "アプリ"
|
apps: "アプリ"
|
||||||
mute: "ミュート"
|
mute-and-block: "ミュート/ブロック"
|
||||||
blocking: "ブロック"
|
blocking: "ブロック"
|
||||||
security: "セキュリティ"
|
security: "セキュリティ"
|
||||||
signin: "サインイン履歴"
|
signin: "サインイン履歴"
|
||||||
|
@ -974,11 +974,12 @@ common/views/components/drive-settings.vue:
|
||||||
in-use: "使用中"
|
in-use: "使用中"
|
||||||
stats: "統計"
|
stats: "統計"
|
||||||
|
|
||||||
desktop/views/components/settings.mute.vue:
|
common/views/components/mute-and-block.vue:
|
||||||
no-users: "ミュートしているユーザーはいません"
|
mute-and-block: "ミュートとブロック"
|
||||||
|
mute: "ミュート"
|
||||||
desktop/views/components/settings.blocking.vue:
|
block: "ブロック"
|
||||||
no-users: "ブロックしているユーザーはいません"
|
no-muted-users: "ミュートしているユーザーはいません"
|
||||||
|
no-blocked-users: "ブロックしているユーザーはいません"
|
||||||
|
|
||||||
desktop/views/components/settings.password.vue:
|
desktop/views/components/settings.password.vue:
|
||||||
reset: "パスワードを変更する"
|
reset: "パスワードを変更する"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
import muteAndBlock from './mute-and-block.vue';
|
||||||
import error from './error.vue';
|
import error from './error.vue';
|
||||||
import apiSettings from './api-settings.vue';
|
import apiSettings from './api-settings.vue';
|
||||||
import driveSettings from './drive-settings.vue';
|
import driveSettings from './drive-settings.vue';
|
||||||
|
@ -50,6 +51,7 @@ import uiInfo from './ui/info.vue';
|
||||||
import formButton from './ui/form/button.vue';
|
import formButton from './ui/form/button.vue';
|
||||||
import formRadio from './ui/form/radio.vue';
|
import formRadio from './ui/form/radio.vue';
|
||||||
|
|
||||||
|
Vue.component('mk-mute-and-block', muteAndBlock);
|
||||||
Vue.component('mk-error', error);
|
Vue.component('mk-error', error);
|
||||||
Vue.component('mk-api-settings', apiSettings);
|
Vue.component('mk-api-settings', apiSettings);
|
||||||
Vue.component('mk-drive-settings', driveSettings);
|
Vue.component('mk-drive-settings', driveSettings);
|
||||||
|
|
56
src/client/app/common/views/components/mute-and-block.vue
Normal file
56
src/client/app/common/views/components/mute-and-block.vue
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<template>
|
||||||
|
<ui-card>
|
||||||
|
<div slot="title">%fa:ban% %i18n:@mute-and-block%</div>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<header>%i18n:@mute%</header>
|
||||||
|
<ui-info v-if="!muteFetching && mute.length == 0">
|
||||||
|
<p>%i18n:@no-muted-users%</p>
|
||||||
|
</ui-info>
|
||||||
|
<div class="users" v-if="mute.length != 0">
|
||||||
|
<div v-for="user in mute" :key="user.id">
|
||||||
|
<p><b>{{ user | userName }}</b> @{{ user | acct }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<header>%i18n:@block%</header>
|
||||||
|
<ui-info v-if="!blockFetching && block.length == 0">
|
||||||
|
<p>%i18n:@no-blocked-users%</p>
|
||||||
|
</ui-info>
|
||||||
|
<div class="users" v-if="block.length != 0">
|
||||||
|
<div v-for="user in block" :key="user.id">
|
||||||
|
<p><b>{{ user | userName }}</b> @{{ user | acct }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</ui-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
muteFetching: true,
|
||||||
|
blockFetching: true,
|
||||||
|
mute: [],
|
||||||
|
block: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
(this as any).api('mute/list').then(mute => {
|
||||||
|
this.mute = mute.map(x => x.mutee);
|
||||||
|
this.muteFetching = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
(this as any).api('blocking/list').then(blocking => {
|
||||||
|
this.block = blocking.map(x => x.blockee);
|
||||||
|
this.blockFetching = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="none ui info" v-if="!fetching && users.length == 0">
|
|
||||||
<p>%fa:info-circle%%i18n:@no-users%</p>
|
|
||||||
</div>
|
|
||||||
<div class="users" v-if="users.length != 0">
|
|
||||||
<div v-for="user in users" :key="user.id">
|
|
||||||
<p><b>{{ user | userName }}</b> @{{ user | acct }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
fetching: true,
|
|
||||||
users: []
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
(this as any).api('blocking/list').then(x => {
|
|
||||||
this.users = x.users;
|
|
||||||
this.fetching = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="none ui info" v-if="!fetching && users.length == 0">
|
|
||||||
<p>%fa:info-circle%%i18n:@no-users%</p>
|
|
||||||
</div>
|
|
||||||
<div class="users" v-if="users.length != 0">
|
|
||||||
<div v-for="user in users" :key="user.id">
|
|
||||||
<p><b>{{ user | userName }}</b> @{{ user | acct }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
fetching: true,
|
|
||||||
users: []
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
(this as any).api('mute/list').then(x => {
|
|
||||||
this.users = x.users;
|
|
||||||
this.fetching = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -7,8 +7,7 @@
|
||||||
<p :class="{ active: page == 'notification' }" @mousedown="page = 'notification'">%fa:R bell .fw%%i18n:@notification%</p>
|
<p :class="{ active: page == 'notification' }" @mousedown="page = 'notification'">%fa:R bell .fw%%i18n:@notification%</p>
|
||||||
<p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:common.drive%</p>
|
<p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:common.drive%</p>
|
||||||
<p :class="{ active: page == 'hashtags' }" @mousedown="page = 'hashtags'">%fa:hashtag .fw%%i18n:@tags%</p>
|
<p :class="{ active: page == 'hashtags' }" @mousedown="page = 'hashtags'">%fa:hashtag .fw%%i18n:@tags%</p>
|
||||||
<p :class="{ active: page == 'mute' }" @mousedown="page = 'mute'">%fa:ban .fw%%i18n:@mute%</p>
|
<p :class="{ active: page == 'muteAndBlock' }" @mousedown="page = 'muteAndBlock'">%fa:ban .fw%%i18n:@mute-and-block%</p>
|
||||||
<p :class="{ active: page == 'blocking' }" @mousedown="page = 'blocking'">%fa:ban .fw%%i18n:@blocking%</p>
|
|
||||||
<p :class="{ active: page == 'apps' }" @mousedown="page = 'apps'">%fa:puzzle-piece .fw%%i18n:@apps%</p>
|
<p :class="{ active: page == 'apps' }" @mousedown="page = 'apps'">%fa:puzzle-piece .fw%%i18n:@apps%</p>
|
||||||
<p :class="{ active: page == 'security' }" @mousedown="page = 'security'">%fa:unlock-alt .fw%%i18n:@security%</p>
|
<p :class="{ active: page == 'security' }" @mousedown="page = 'security'">%fa:unlock-alt .fw%%i18n:@security%</p>
|
||||||
<p :class="{ active: page == 'api' }" @mousedown="page = 'api'">%fa:key .fw%API</p>
|
<p :class="{ active: page == 'api' }" @mousedown="page = 'api'">%fa:key .fw%API</p>
|
||||||
|
@ -201,19 +200,9 @@
|
||||||
</section>
|
</section>
|
||||||
</ui-card>
|
</ui-card>
|
||||||
|
|
||||||
<ui-card class="mute" v-show="page == 'mute'">
|
<div class="muteAndBlock" v-show="page == 'muteAndBlock'">
|
||||||
<div slot="title">%fa:ban% %i18n:@mute%</div>
|
<mk-mute-and-block/>
|
||||||
<section>
|
</div>
|
||||||
<x-mute/>
|
|
||||||
</section>
|
|
||||||
</ui-card>
|
|
||||||
|
|
||||||
<ui-card class="blocking" v-show="page == 'blocking'">
|
|
||||||
<div slot="title">%fa:ban% %i18n:@blocking%</div>
|
|
||||||
<section>
|
|
||||||
<x-blocking/>
|
|
||||||
</section>
|
|
||||||
</ui-card>
|
|
||||||
|
|
||||||
<ui-card class="apps" v-show="page == 'apps'">
|
<ui-card class="apps" v-show="page == 'apps'">
|
||||||
<div slot="title">%fa:puzzle-piece% %i18n:@apps%</div>
|
<div slot="title">%fa:puzzle-piece% %i18n:@apps%</div>
|
||||||
|
@ -297,8 +286,6 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import XMute from './settings.mute.vue';
|
|
||||||
import XBlocking from './settings.blocking.vue';
|
|
||||||
import XPassword from './settings.password.vue';
|
import XPassword from './settings.password.vue';
|
||||||
import X2fa from './settings.2fa.vue';
|
import X2fa from './settings.2fa.vue';
|
||||||
import XApps from './settings.apps.vue';
|
import XApps from './settings.apps.vue';
|
||||||
|
@ -309,8 +296,6 @@ import checkForUpdate from '../../../common/scripts/check-for-update';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
XMute,
|
|
||||||
XBlocking,
|
|
||||||
XPassword,
|
XPassword,
|
||||||
X2fa,
|
X2fa,
|
||||||
XApps,
|
XApps,
|
||||||
|
|
|
@ -85,6 +85,8 @@
|
||||||
|
|
||||||
<mk-drive-settings/>
|
<mk-drive-settings/>
|
||||||
|
|
||||||
|
<mk-mute-and-block/>
|
||||||
|
|
||||||
<ui-card>
|
<ui-card>
|
||||||
<div slot="title">%fa:volume-up% %i18n:@sound%</div>
|
<div slot="title">%fa:volume-up% %i18n:@sound%</div>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
|
import isObjectId from '../misc/is-objectid';
|
||||||
|
const deepcopy = require('deepcopy');
|
||||||
|
import { pack as packUser } from './user';
|
||||||
|
|
||||||
const Blocking = db.get<IBlocking>('blocking');
|
const Blocking = db.get<IBlocking>('blocking');
|
||||||
|
Blocking.createIndex('blockerId');
|
||||||
|
Blocking.createIndex('blockeeId');
|
||||||
Blocking.createIndex(['blockerId', 'blockeeId'], { unique: true });
|
Blocking.createIndex(['blockerId', 'blockeeId'], { unique: true });
|
||||||
export default Blocking;
|
export default Blocking;
|
||||||
|
|
||||||
|
@ -11,3 +16,39 @@ export type IBlocking = {
|
||||||
blockeeId: mongo.ObjectID;
|
blockeeId: mongo.ObjectID;
|
||||||
blockerId: mongo.ObjectID;
|
blockerId: mongo.ObjectID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const packMany = async (
|
||||||
|
blockings: (string | mongo.ObjectID | IBlocking)[],
|
||||||
|
me?: string | mongo.ObjectID | IUser
|
||||||
|
) => {
|
||||||
|
return (await Promise.all(blockings.map(x => pack(x, me)))).filter(x => x != null);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pack = (
|
||||||
|
blocking: any,
|
||||||
|
me?: any
|
||||||
|
) => new Promise<any>(async (resolve, reject) => {
|
||||||
|
let _blocking: any;
|
||||||
|
|
||||||
|
// Populate the blocking if 'blocking' is ID
|
||||||
|
if (isObjectId(blocking)) {
|
||||||
|
_blocking = await Blocking.findOne({
|
||||||
|
_id: blocking
|
||||||
|
});
|
||||||
|
} else if (typeof blocking === 'string') {
|
||||||
|
_blocking = await Blocking.findOne({
|
||||||
|
_id: new mongo.ObjectID(blocking)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_blocking = deepcopy(blocking);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename _id to id
|
||||||
|
_blocking.id = _blocking._id;
|
||||||
|
delete _blocking._id;
|
||||||
|
|
||||||
|
// Populate blockee
|
||||||
|
_blocking.blockee = await packUser(_blocking.blockeeId, me);
|
||||||
|
|
||||||
|
resolve(_blocking);
|
||||||
|
});
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
|
import isObjectId from '../misc/is-objectid';
|
||||||
|
const deepcopy = require('deepcopy');
|
||||||
|
import { pack as packUser } from './user';
|
||||||
|
|
||||||
const Mute = db.get<IMute>('mute');
|
const Mute = db.get<IMute>('mute');
|
||||||
|
Mute.createIndex('muterId');
|
||||||
|
Mute.createIndex('muteeId');
|
||||||
Mute.createIndex(['muterId', 'muteeId'], { unique: true });
|
Mute.createIndex(['muterId', 'muteeId'], { unique: true });
|
||||||
export default Mute;
|
export default Mute;
|
||||||
|
|
||||||
|
@ -11,3 +16,39 @@ export interface IMute {
|
||||||
muterId: mongo.ObjectID;
|
muterId: mongo.ObjectID;
|
||||||
muteeId: mongo.ObjectID;
|
muteeId: mongo.ObjectID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const packMany = async (
|
||||||
|
mutes: (string | mongo.ObjectID | IMute)[],
|
||||||
|
me?: string | mongo.ObjectID | IUser
|
||||||
|
) => {
|
||||||
|
return (await Promise.all(mutes.map(x => pack(x, me)))).filter(x => x != null);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pack = (
|
||||||
|
mute: any,
|
||||||
|
me?: any
|
||||||
|
) => new Promise<any>(async (resolve, reject) => {
|
||||||
|
let _mute: any;
|
||||||
|
|
||||||
|
// Populate the mute if 'mute' is ID
|
||||||
|
if (isObjectId(mute)) {
|
||||||
|
_mute = await Mute.findOne({
|
||||||
|
_id: mute
|
||||||
|
});
|
||||||
|
} else if (typeof mute === 'string') {
|
||||||
|
_mute = await Mute.findOne({
|
||||||
|
_id: new mongo.ObjectID(mute)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_mute = deepcopy(mute);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename _id to id
|
||||||
|
_mute.id = _mute._id;
|
||||||
|
delete _mute._id;
|
||||||
|
|
||||||
|
// Populate mutee
|
||||||
|
_mute.mutee = await packUser(_mute.muteeId, me);
|
||||||
|
|
||||||
|
resolve(_mute);
|
||||||
|
});
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
||||||
import Blocking from '../../../../models/blocking';
|
import Blocking, { packMany } from '../../../../models/blocking';
|
||||||
import { pack, ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -10,50 +11,54 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'following-read'
|
kind: 'following-read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: $.num.optional.range(1, 100).note({
|
||||||
|
default: 30
|
||||||
|
}),
|
||||||
|
|
||||||
|
sinceId: $.type(ID).optional.note({
|
||||||
|
}),
|
||||||
|
|
||||||
|
untilId: $.type(ID).optional.note({
|
||||||
|
}),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'limit' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [limit = 30, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
if (psErr) return rej(psErr);
|
||||||
if (limitErr) return rej('invalid limit param');
|
|
||||||
|
|
||||||
// Get 'cursor' parameter
|
// Check if both of sinceId and untilId is specified
|
||||||
const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
|
if (ps.sinceId && ps.untilId) {
|
||||||
if (cursorErr) return rej('invalid cursor param');
|
return rej('cannot set sinceId and untilId');
|
||||||
|
}
|
||||||
|
|
||||||
// Construct query
|
|
||||||
const query = {
|
const query = {
|
||||||
blockerId: me._id
|
blockerId: me._id
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
// カーソルが指定されている場合
|
const sort = {
|
||||||
if (cursor) {
|
_id: -1
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ps.sinceId) {
|
||||||
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: cursor
|
$gt: ps.sinceId
|
||||||
|
};
|
||||||
|
} else if (ps.untilId) {
|
||||||
|
query._id = {
|
||||||
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get blockings
|
|
||||||
const blockings = await Blocking
|
const blockings = await Blocking
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit + 1,
|
limit: ps.limit,
|
||||||
sort: { _id: -1 }
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// 「次のページ」があるかどうか
|
res(await packMany(blockings, me));
|
||||||
const inStock = blockings.length === limit + 1;
|
|
||||||
if (inStock) {
|
|
||||||
blockings.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize
|
|
||||||
const users = await Promise.all(blockings.map(async m =>
|
|
||||||
await pack(m.blockeeId, me, { detail: true })));
|
|
||||||
|
|
||||||
// Response
|
|
||||||
res({
|
|
||||||
users: users,
|
|
||||||
next: inStock ? blockings[blockings.length - 1]._id : null,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
import $ from 'cafy'; import ID from '../../../../misc/cafy-id';
|
||||||
import Mute from '../../../../models/mute';
|
import Mute, { packMany } from '../../../../models/mute';
|
||||||
import { pack, ILocalUser } from '../../../../models/user';
|
import { ILocalUser } from '../../../../models/user';
|
||||||
import { getFriendIds } from '../../common/get-friends';
|
import getParams from '../../get-params';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
desc: {
|
desc: {
|
||||||
|
@ -11,64 +11,54 @@ export const meta = {
|
||||||
|
|
||||||
requireCredential: true,
|
requireCredential: true,
|
||||||
|
|
||||||
kind: 'account/read'
|
kind: 'account/read',
|
||||||
|
|
||||||
|
params: {
|
||||||
|
limit: $.num.optional.range(1, 100).note({
|
||||||
|
default: 30
|
||||||
|
}),
|
||||||
|
|
||||||
|
sinceId: $.type(ID).optional.note({
|
||||||
|
}),
|
||||||
|
|
||||||
|
untilId: $.type(ID).optional.note({
|
||||||
|
}),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||||
// Get 'iknow' parameter
|
const [ps, psErr] = getParams(meta, params);
|
||||||
const [iknow = false, iknowErr] = $.bool.optional.get(params.iknow);
|
if (psErr) return rej(psErr);
|
||||||
if (iknowErr) return rej('invalid iknow param');
|
|
||||||
|
|
||||||
// Get 'limit' parameter
|
// Check if both of sinceId and untilId is specified
|
||||||
const [limit = 30, limitErr] = $.num.optional.range(1, 100).get(params.limit);
|
if (ps.sinceId && ps.untilId) {
|
||||||
if (limitErr) return rej('invalid limit param');
|
return rej('cannot set sinceId and untilId');
|
||||||
|
}
|
||||||
|
|
||||||
// Get 'cursor' parameter
|
|
||||||
const [cursor = null, cursorErr] = $.type(ID).optional.get(params.cursor);
|
|
||||||
if (cursorErr) return rej('invalid cursor param');
|
|
||||||
|
|
||||||
// Construct query
|
|
||||||
const query = {
|
const query = {
|
||||||
muterId: me._id,
|
muterId: me._id
|
||||||
deletedAt: { $exists: false }
|
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
if (iknow) {
|
const sort = {
|
||||||
// Get my friends
|
_id: -1
|
||||||
const myFriends = await getFriendIds(me._id);
|
|
||||||
|
|
||||||
query.muteeId = {
|
|
||||||
$in: myFriends
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// カーソルが指定されている場合
|
if (ps.sinceId) {
|
||||||
if (cursor) {
|
sort._id = 1;
|
||||||
query._id = {
|
query._id = {
|
||||||
$lt: cursor
|
$gt: ps.sinceId
|
||||||
|
};
|
||||||
|
} else if (ps.untilId) {
|
||||||
|
query._id = {
|
||||||
|
$lt: ps.untilId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get mutes
|
|
||||||
const mutes = await Mute
|
const mutes = await Mute
|
||||||
.find(query, {
|
.find(query, {
|
||||||
limit: limit + 1,
|
limit: ps.limit,
|
||||||
sort: { _id: -1 }
|
sort: sort
|
||||||
});
|
});
|
||||||
|
|
||||||
// 「次のページ」があるかどうか
|
res(await packMany(mutes, me));
|
||||||
const inStock = mutes.length === limit + 1;
|
|
||||||
if (inStock) {
|
|
||||||
mutes.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize
|
|
||||||
const users = await Promise.all(mutes.map(async m =>
|
|
||||||
await pack(m.muteeId, me, { detail: true })));
|
|
||||||
|
|
||||||
// Response
|
|
||||||
res({
|
|
||||||
users: users,
|
|
||||||
next: inStock ? mutes[mutes.length - 1]._id : null,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue