Use PostgreSQL instead of MongoDB (#4572)
* wip * Update note.ts * Update timeline.ts * Update core.ts * wip * Update generate-visibility-query.ts * wip * wip * wip * wip * wip * Update global-timeline.ts * wip * wip * wip * Update vote.ts * wip * wip * Update create.ts * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update files.ts * wip * wip * Update CONTRIBUTING.md * wip * wip * wip * wip * wip * wip * wip * wip * Update read-notification.ts * wip * wip * wip * wip * wip * wip * wip * Update cancel.ts * wip * wip * wip * Update show.ts * wip * wip * Update gen-id.ts * Update create.ts * Update id.ts * wip * wip * wip * wip * wip * wip * wip * Docker: Update files about Docker (#4599) * Docker: Use cache if files used by `yarn install` was not updated This patch reduces the number of times to installing node_modules. For example, `yarn install` step will be skipped when only ".config/default.yml" is updated. * Docker: Migrate MongoDB to Postgresql Misskey uses Postgresql as a database instead of Mongodb since version 11. * Docker: Uncomment about data persistence This patch will save a lot of databases. * wip * wip * wip * Update activitypub.ts * wip * wip * wip * Update logs.ts * wip * Update drive-file.ts * Update register.ts * wip * wip * Update mentions.ts * wip * wip * wip * Update recommendation.ts * wip * Update index.ts * wip * Update recommendation.ts * Doc: Update docker.ja.md and docker.en.md (#1) (#4608) Update how to set up misskey. * wip * ✌️ * wip * Update note.ts * Update postgre.ts * wip * wip * wip * wip * Update add-file.ts * wip * wip * wip * Clean up * Update logs.ts * wip * 🍕 * wip * Ad notes * wip * Update api-visibility.ts * Update note.ts * Update add-file.ts * tests * tests * Update postgre.ts * Update utils.ts * wip * wip * Refactor * wip * Refactor * wip * wip * Update show-users.ts * Update update-instance.ts * wip * Update feed.ts * Update outbox.ts * Update outbox.ts * Update user.ts * wip * Update list.ts * Update update-hashtag.ts * wip * Update update-hashtag.ts * Refactor * Update update.ts * wip * wip * ✌️ * clean up * docs * Update push.ts * wip * Update api.ts * wip * ✌️ * Update make-pagination-query.ts * ✌️ * Delete hashtags.ts * Update instances.ts * Update instances.ts * Update create.ts * Update search.ts * Update reversi-game.ts * Update signup.ts * Update user.ts * id * Update example.yml * 🎨 * objectid * fix * reversi * reversi * Fix bug of chart engine * Add test of chart engine * Improve test * Better testing * Improve chart engine * Refactor * Add test of chart engine * Refactor * Add chart test * Fix bug * コミットし忘れ * Refactoring * ✌️ * Add tests * Add test * Extarct note tests * Refactor * 存在しないユーザーにメンションできなくなっていた問題を修正 * Fix bug * Update update-meta.ts * Fix bug * Update mention.vue * Fix bug * Update meta.ts * Update CONTRIBUTING.md * Fix bug * Fix bug * Fix bug * Clean up * Clean up * Update notification.ts * Clean up * Add mute tests * Add test * Refactor * Add test * Fix test * Refactor * Refactor * Add tests * Update utils.ts * Update utils.ts * Fix test * Update package.json * Update update.ts * Update manifest.ts * Fix bug * Fix bug * Add test * 🎨 * Update endpoint permissions * Updaye permisison * Update person.ts #4299 * データベースと同期しないように * Fix bug * Fix bug * Update reversi-game.ts * Use a feature of Node v11.7.0 to extract a public key (#4644) * wip * wip * ✌️ * Refactoring #1540 * test * test * test * test * test * test * test * Fix bug * Fix test * 🍣 * wip * #4471 * Add test for #4335 * Refactor * Fix test * Add tests * 🕓 * Fix bug * Add test * Add test * rename * Fix bug
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import Report, { packMany } from '../../../../models/abuse-user-report';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { AbuseUserReports } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -17,37 +18,18 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
const query = {} as any;
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
query._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
query._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
}
|
||||
const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId);
|
||||
|
||||
const reports = await Report
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
const reports = await query.take(ps.limit).getMany();
|
||||
|
||||
return await packMany(reports);
|
||||
return await AbuseUserReports.packMany(reports);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import File, { packMany } from '../../../../../models/drive-file';
|
||||
import define from '../../../define';
|
||||
import { fallback } from '../../../../../prelude/symbol';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -41,27 +41,25 @@ export const meta = {
|
||||
};
|
||||
|
||||
const sort: any = { // < https://github.com/Microsoft/TypeScript/issues/1863
|
||||
'+createdAt': { uploadDate: -1 },
|
||||
'-createdAt': { uploadDate: 1 },
|
||||
'+size': { length: -1 },
|
||||
'-size': { length: 1 },
|
||||
[fallback]: { _id: -1 }
|
||||
'+createdAt': { createdAt: -1 },
|
||||
'-createdAt': { createdAt: 1 },
|
||||
'+size': { size: -1 },
|
||||
'-size': { size: 1 },
|
||||
[fallback]: { id: -1 }
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const q = {
|
||||
'metadata.deletedAt': { $exists: false },
|
||||
} as any;
|
||||
const q = {} as any;
|
||||
|
||||
if (ps.origin == 'local') q['metadata._user.host'] = null;
|
||||
if (ps.origin == 'remote') q['metadata._user.host'] = { $ne: null };
|
||||
if (ps.origin == 'local') q['userHost'] = null;
|
||||
if (ps.origin == 'remote') q['userHost'] = { $ne: null };
|
||||
|
||||
const files = await File
|
||||
.find(q, {
|
||||
limit: ps.limit,
|
||||
sort: sort[ps.sort] || sort[fallback],
|
||||
skip: ps.offset
|
||||
});
|
||||
const files = await DriveFiles.find({
|
||||
where: q,
|
||||
take: ps.limit,
|
||||
order: sort[ps.sort] || sort[fallback],
|
||||
skip: ps.offset
|
||||
});
|
||||
|
||||
return await packMany(files, { detail: true, withUser: true, self: true });
|
||||
return await DriveFiles.packMany(files, { detail: true, withUser: true, self: true });
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -13,7 +13,6 @@ export const meta = {
|
||||
params: {
|
||||
fileId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
},
|
||||
|
||||
@ -27,9 +26,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const file = await DriveFile.findOne({
|
||||
_id: ps.fileId
|
||||
});
|
||||
const file = await DriveFiles.findOne(ps.fileId);
|
||||
|
||||
if (file == null) {
|
||||
throw new ApiError(meta.errors.noSuchFile);
|
||||
|
@ -1,7 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import Emoji from '../../../../../models/emoji';
|
||||
import define from '../../../define';
|
||||
import { detectUrlMine } from '../../../../../misc/detect-url-mine';
|
||||
import { Emojis } from '../../../../../models';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -32,7 +33,8 @@ export const meta = {
|
||||
export default define(meta, async (ps) => {
|
||||
const type = await detectUrlMine(ps.url);
|
||||
|
||||
const emoji = await Emoji.insert({
|
||||
const emoji = await Emojis.save({
|
||||
id: genId(),
|
||||
updatedAt: new Date(),
|
||||
name: ps.name,
|
||||
host: null,
|
||||
@ -42,6 +44,6 @@ export default define(meta, async (ps) => {
|
||||
});
|
||||
|
||||
return {
|
||||
id: emoji._id
|
||||
id: emoji.id
|
||||
};
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import Emoji from '../../../../../models/emoji';
|
||||
import define from '../../../define';
|
||||
import { Emojis } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -21,12 +21,12 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const emojis = await Emoji.find({
|
||||
const emojis = await Emojis.find({
|
||||
host: ps.host
|
||||
});
|
||||
|
||||
return emojis.map(e => ({
|
||||
id: e._id,
|
||||
id: e.id,
|
||||
name: e.name,
|
||||
aliases: e.aliases,
|
||||
host: e.host,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import Emoji from '../../../../../models/emoji';
|
||||
import define from '../../../define';
|
||||
import ID from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { Emojis } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -21,13 +21,9 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const emoji = await Emoji.findOne({
|
||||
_id: ps.id
|
||||
});
|
||||
const emoji = await Emojis.findOne(ps.id);
|
||||
|
||||
if (emoji == null) throw new Error('emoji not found');
|
||||
|
||||
await Emoji.remove({ _id: emoji._id });
|
||||
|
||||
return;
|
||||
await Emojis.delete(emoji.id);
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import Emoji from '../../../../../models/emoji';
|
||||
import define from '../../../define';
|
||||
import ID from '../../../../../misc/cafy-id';
|
||||
import { detectUrlMine } from '../../../../../misc/detect-url-mine';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { Emojis } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -34,23 +34,17 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const emoji = await Emoji.findOne({
|
||||
_id: ps.id
|
||||
});
|
||||
const emoji = await Emojis.findOne(ps.id);
|
||||
|
||||
if (emoji == null) throw new Error('emoji not found');
|
||||
|
||||
const type = await detectUrlMine(ps.url);
|
||||
|
||||
await Emoji.update({ _id: emoji._id }, {
|
||||
$set: {
|
||||
updatedAt: new Date(),
|
||||
name: ps.name,
|
||||
aliases: ps.aliases,
|
||||
url: ps.url,
|
||||
type,
|
||||
}
|
||||
await Emojis.update(emoji.id, {
|
||||
updatedAt: new Date(),
|
||||
name: ps.name,
|
||||
aliases: ps.aliases,
|
||||
url: ps.url,
|
||||
type,
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,8 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import Following from '../../../../../models/following';
|
||||
import User from '../../../../../models/user';
|
||||
import deleteFollowing from '../../../../../services/following/delete';
|
||||
import { Followings, Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -18,13 +17,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const followings = await Following.find({
|
||||
'_follower.host': ps.host
|
||||
const followings = await Followings.find({
|
||||
followerHost: ps.host
|
||||
});
|
||||
|
||||
const pairs = await Promise.all(followings.map(f => Promise.all([
|
||||
User.findOne({ _id: f.followerId }),
|
||||
User.findOne({ _id: f.followeeId })
|
||||
Users.findOne(f.followerId),
|
||||
Users.findOne(f.followeeId)
|
||||
])));
|
||||
|
||||
for (const pair of pairs) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import Instance from '../../../../../models/instance';
|
||||
import { Instances } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -13,10 +13,6 @@ export const meta = {
|
||||
validator: $.str
|
||||
},
|
||||
|
||||
isBlocked: {
|
||||
validator: $.bool
|
||||
},
|
||||
|
||||
isClosed: {
|
||||
validator: $.bool
|
||||
},
|
||||
@ -24,18 +20,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const instance = await Instance.findOne({ host: ps.host });
|
||||
const instance = await Instances.findOne({ host: ps.host });
|
||||
|
||||
if (instance == null) {
|
||||
throw new Error('instance not found');
|
||||
}
|
||||
|
||||
Instance.update({ host: ps.host }, {
|
||||
$set: {
|
||||
isBlocked: ps.isBlocked,
|
||||
isMarkedAsClosed: ps.isClosed
|
||||
}
|
||||
Instances.update({ host: ps.host }, {
|
||||
isMarkedAsClosed: ps.isClosed
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import rndstr from 'rndstr';
|
||||
import RegistrationTicket from '../../../../models/registration-tickets';
|
||||
import define from '../../define';
|
||||
import { RegistrationTickets } from '../../../../models';
|
||||
import { genId } from '../../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -18,7 +19,8 @@ export const meta = {
|
||||
export default define(meta, async (ps) => {
|
||||
const code = rndstr({ length: 5, chars: '0-9' });
|
||||
|
||||
await RegistrationTicket.insert({
|
||||
await RegistrationTickets.save({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
code: code
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import Log from '../../../../models/log';
|
||||
import { Logs } from '../../../../models';
|
||||
import { Brackets } from 'typeorm';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -27,41 +28,44 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
const query = {} as any;
|
||||
const query = Logs.createQueryBuilder('log');
|
||||
|
||||
if (ps.level) query.andWhere('log.level = :level', { level: ps.level });
|
||||
|
||||
if (ps.level) query.level = ps.level;
|
||||
if (ps.domain) {
|
||||
for (const d of ps.domain.split(' ')) {
|
||||
const qs: any[] = [];
|
||||
let i = 0;
|
||||
for (const sd of (d.startsWith('-') ? d.substr(1) : d).split('.')) {
|
||||
qs.push({
|
||||
[`domain.${i}`]: d.startsWith('-') ? { $ne: sd } : sd
|
||||
});
|
||||
i++;
|
||||
}
|
||||
if (d.startsWith('-')) {
|
||||
if (query['$and'] == null) query['$and'] = [];
|
||||
query['$and'].push({
|
||||
$and: qs
|
||||
});
|
||||
} else {
|
||||
if (query['$or'] == null) query['$or'] = [];
|
||||
query['$or'].push({
|
||||
$and: qs
|
||||
});
|
||||
}
|
||||
const whiteDomains = ps.domain.split(' ').filter(x => !x.startsWith('-'));
|
||||
const blackDomains = ps.domain.split(' ').filter(x => x.startsWith('-'));
|
||||
|
||||
if (whiteDomains.length > 0) {
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const whiteDomain of whiteDomains) {
|
||||
let i = 0;
|
||||
for (const subDomain of whiteDomain.split('.')) {
|
||||
const p = `whiteSubDomain_${subDomain}_${i}`;
|
||||
// SQL is 1 based, so we need '+ 1'
|
||||
qb.orWhere(`log.domain[${i + 1}] = :${p}`, { [p]: subDomain });
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (blackDomains.length > 0) {
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const blackDomain of blackDomains) {
|
||||
let i = 0;
|
||||
for (const subDomain of blackDomain.split('.')) {
|
||||
const p = `blackSubDomain_${subDomain}_${i}`;
|
||||
// SQL is 1 based, so we need '+ 1'
|
||||
qb.andWhere(`log.domain[${i + 1}] != :${p}`, { [p]: subDomain });
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
const logs = await Log
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
const logs = await query.take(ps.limit).getMany();
|
||||
|
||||
return logs;
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import User from '../../../../../models/user';
|
||||
import { Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID'
|
||||
@ -27,21 +26,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
await User.update({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isModerator: true
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isModerator: true
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import User from '../../../../../models/user';
|
||||
import { Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID'
|
||||
@ -27,21 +26,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
await User.update({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isModerator: false
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isModerator: false
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import AbuseUserReport from '../../../../models/abuse-user-report';
|
||||
import { AbuseUserReports } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -12,23 +12,16 @@ export const meta = {
|
||||
params: {
|
||||
reportId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const report = await AbuseUserReport.findOne({
|
||||
_id: ps.reportId
|
||||
});
|
||||
const report = await AbuseUserReports.findOne(ps.reportId);
|
||||
|
||||
if (report == null) {
|
||||
throw new Error('report not found');
|
||||
}
|
||||
|
||||
await AbuseUserReport.remove({
|
||||
_id: report._id
|
||||
});
|
||||
|
||||
return;
|
||||
await AbuseUserReports.delete(report.id);
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User from '../../../../models/user';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import rndstr from 'rndstr';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -18,7 +18,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to suspend'
|
||||
@ -28,9 +27,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
@ -45,12 +42,8 @@ export default define(meta, async (ps) => {
|
||||
// Generate hash of password
|
||||
const hash = bcrypt.hashSync(passwd);
|
||||
|
||||
await User.findOneAndUpdate({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
password: hash
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
password: hash
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User from '../../../../models/user';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -16,7 +16,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to suspend'
|
||||
@ -26,9 +25,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
|
@ -1,7 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import User, { pack } from '../../../../models/user';
|
||||
import define from '../../define';
|
||||
import { fallback } from '../../../../prelude/symbol';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -55,51 +54,38 @@ export const meta = {
|
||||
}
|
||||
};
|
||||
|
||||
const sort: any = { // < https://github.com/Microsoft/TypeScript/issues/1863
|
||||
'+follower': { followersCount: -1 },
|
||||
'-follower': { followersCount: 1 },
|
||||
'+createdAt': { createdAt: -1 },
|
||||
'-createdAt': { createdAt: 1 },
|
||||
'+updatedAt': { updatedAt: -1 },
|
||||
'-updatedAt': { updatedAt: 1 },
|
||||
[fallback]: { _id: -1 }
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const q = {
|
||||
$and: []
|
||||
} as any;
|
||||
const query = Users.createQueryBuilder('user');
|
||||
|
||||
// state
|
||||
q.$and.push(
|
||||
ps.state == 'admin' ? { isAdmin: true } :
|
||||
ps.state == 'moderator' ? { isModerator: true } :
|
||||
ps.state == 'adminOrModerator' ? {
|
||||
$or: [{
|
||||
isAdmin: true
|
||||
}, {
|
||||
isModerator: true
|
||||
}]
|
||||
} :
|
||||
ps.state == 'verified' ? { isVerified: true } :
|
||||
ps.state == 'silenced' ? { isSilenced: true } :
|
||||
ps.state == 'suspended' ? { isSuspended: true } :
|
||||
{}
|
||||
);
|
||||
switch (ps.state) {
|
||||
case 'admin': query.where('user.isAdmin = TRUE'); break;
|
||||
case 'moderator': query.where('user.isModerator = TRUE'); break;
|
||||
case 'adminOrModerator': query.where('user.isAdmin = TRUE OR isModerator = TRUE'); break;
|
||||
case 'verified': query.where('user.isVerified = TRUE'); break;
|
||||
case 'alive': query.where('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break;
|
||||
case 'silenced': query.where('user.isSilenced = TRUE'); break;
|
||||
case 'suspended': query.where('user.isSuspended = TRUE'); break;
|
||||
}
|
||||
|
||||
// origin
|
||||
q.$and.push(
|
||||
ps.origin == 'local' ? { host: null } :
|
||||
ps.origin == 'remote' ? { host: { $ne: null } } :
|
||||
{}
|
||||
);
|
||||
switch (ps.origin) {
|
||||
case 'local': query.andWhere('user.host IS NULL'); break;
|
||||
case 'remote': query.andWhere('user.host IS NOT NULL'); break;
|
||||
}
|
||||
|
||||
const users = await User
|
||||
.find(q, {
|
||||
limit: ps.limit,
|
||||
sort: sort[ps.sort] || sort[fallback],
|
||||
skip: ps.offset
|
||||
});
|
||||
switch (ps.sort) {
|
||||
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
||||
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
|
||||
case '+updatedAt': query.orderBy('user.updatedAt', 'DESC'); break;
|
||||
case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break;
|
||||
default: query.orderBy('user.id', 'ASC'); break;
|
||||
}
|
||||
|
||||
return await Promise.all(users.map(user => pack(user, me, { detail: true })));
|
||||
query.take(ps.limit);
|
||||
query.skip(ps.offset);
|
||||
|
||||
const users = await query.getMany();
|
||||
|
||||
return await Users.packMany(users, me, { detail: true });
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User from '../../../../models/user';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to make silence'
|
||||
@ -27,9 +26,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
@ -39,13 +36,7 @@ export default define(meta, async (ps) => {
|
||||
throw new Error('cannot silence admin');
|
||||
}
|
||||
|
||||
await User.findOneAndUpdate({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isSilenced: true
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isSilenced: true
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User, { IUser } from '../../../../models/user';
|
||||
import Following from '../../../../models/following';
|
||||
import deleteFollowing from '../../../../services/following/delete';
|
||||
import { Users, Followings } from '../../../../models';
|
||||
import { User } from '../../../../models/entities/user';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -19,7 +19,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to suspend'
|
||||
@ -29,9 +28,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
@ -45,27 +42,21 @@ export default define(meta, async (ps) => {
|
||||
throw new Error('cannot suspend moderator');
|
||||
}
|
||||
|
||||
await User.findOneAndUpdate({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isSuspended: true
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isSuspended: true
|
||||
});
|
||||
|
||||
unFollowAll(user);
|
||||
|
||||
return;
|
||||
});
|
||||
|
||||
async function unFollowAll(follower: IUser) {
|
||||
const followings = await Following.find({
|
||||
followerId: follower._id
|
||||
async function unFollowAll(follower: User) {
|
||||
const followings = await Followings.find({
|
||||
followerId: follower.id
|
||||
});
|
||||
|
||||
for (const following of followings) {
|
||||
const followee = await User.findOne({
|
||||
_id: following.followeeId
|
||||
const followee = await Users.findOne({
|
||||
id: following.followeeId
|
||||
});
|
||||
|
||||
if (followee == null) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User from '../../../../models/user';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to unsilence'
|
||||
@ -27,21 +26,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
await User.findOneAndUpdate({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isSilenced: false
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isSilenced: false
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User from '../../../../models/user';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to unsuspend'
|
||||
@ -27,21 +26,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
await User.findOneAndUpdate({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isSuspended: false
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isSuspended: false
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User from '../../../../models/user';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to unverify'
|
||||
@ -27,21 +26,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
await User.findOneAndUpdate({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isVerified: false
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isVerified: false
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import Meta from '../../../../models/meta';
|
||||
import define from '../../define';
|
||||
import { Metas } from '../../../../models';
|
||||
import { Meta } from '../../../../models/entities/meta';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -55,7 +56,7 @@ export const meta = {
|
||||
}
|
||||
},
|
||||
|
||||
hidedTags: {
|
||||
hiddenTags: {
|
||||
validator: $.optional.nullable.arr($.str),
|
||||
desc: {
|
||||
'ja-JP': '統計などで無視するハッシュタグ'
|
||||
@ -253,27 +254,6 @@ export const meta = {
|
||||
}
|
||||
},
|
||||
|
||||
enableExternalUserRecommendation: {
|
||||
validator: $.optional.bool,
|
||||
desc: {
|
||||
'ja-JP': '外部ユーザーレコメンデーションを有効にする'
|
||||
}
|
||||
},
|
||||
|
||||
externalUserRecommendationEngine: {
|
||||
validator: $.optional.nullable.str,
|
||||
desc: {
|
||||
'ja-JP': '外部ユーザーレコメンデーションのサードパーティエンジン'
|
||||
}
|
||||
},
|
||||
|
||||
externalUserRecommendationTimeout: {
|
||||
validator: $.optional.nullable.num.min(0),
|
||||
desc: {
|
||||
'ja-JP': '外部ユーザーレコメンデーションのタイムアウト (ミリ秒)'
|
||||
}
|
||||
},
|
||||
|
||||
enableEmail: {
|
||||
validator: $.optional.bool,
|
||||
desc: {
|
||||
@ -347,7 +327,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const set = {} as any;
|
||||
const set = {} as Partial<Meta>;
|
||||
|
||||
if (ps.announcements) {
|
||||
set.announcements = ps.announcements;
|
||||
@ -373,8 +353,8 @@ export default define(meta, async (ps) => {
|
||||
set.useStarForReactionFallback = ps.useStarForReactionFallback;
|
||||
}
|
||||
|
||||
if (Array.isArray(ps.hidedTags)) {
|
||||
set.hidedTags = ps.hidedTags;
|
||||
if (Array.isArray(ps.hiddenTags)) {
|
||||
set.hiddenTags = ps.hiddenTags;
|
||||
}
|
||||
|
||||
if (ps.mascotImageUrl !== undefined) {
|
||||
@ -430,11 +410,11 @@ export default define(meta, async (ps) => {
|
||||
}
|
||||
|
||||
if (ps.maintainerName !== undefined) {
|
||||
set['maintainer.name'] = ps.maintainerName;
|
||||
set.maintainerName = ps.maintainerName;
|
||||
}
|
||||
|
||||
if (ps.maintainerEmail !== undefined) {
|
||||
set['maintainer.email'] = ps.maintainerEmail;
|
||||
set.maintainerEmail = ps.maintainerEmail;
|
||||
}
|
||||
|
||||
if (ps.langs !== undefined) {
|
||||
@ -481,18 +461,6 @@ export default define(meta, async (ps) => {
|
||||
set.discordClientSecret = ps.discordClientSecret;
|
||||
}
|
||||
|
||||
if (ps.enableExternalUserRecommendation !== undefined) {
|
||||
set.enableExternalUserRecommendation = ps.enableExternalUserRecommendation;
|
||||
}
|
||||
|
||||
if (ps.externalUserRecommendationEngine !== undefined) {
|
||||
set.externalUserRecommendationEngine = ps.externalUserRecommendationEngine;
|
||||
}
|
||||
|
||||
if (ps.externalUserRecommendationTimeout !== undefined) {
|
||||
set.externalUserRecommendationTimeout = ps.externalUserRecommendationTimeout;
|
||||
}
|
||||
|
||||
if (ps.enableEmail !== undefined) {
|
||||
set.enableEmail = ps.enableEmail;
|
||||
}
|
||||
@ -537,9 +505,11 @@ export default define(meta, async (ps) => {
|
||||
set.swPrivateKey = ps.swPrivateKey;
|
||||
}
|
||||
|
||||
await Meta.update({}, {
|
||||
$set: set
|
||||
}, { upsert: true });
|
||||
const meta = await Metas.findOne();
|
||||
|
||||
return;
|
||||
if (meta) {
|
||||
await Metas.update(meta.id, set);
|
||||
} else {
|
||||
await Metas.save(set);
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { getRemoteUser } from '../../common/getters';
|
||||
import { updatePerson } from '../../../../remote/activitypub/models/person';
|
||||
@ -19,7 +18,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to update'
|
||||
@ -29,11 +27,6 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
await updatePersonById(ps.userId);
|
||||
return;
|
||||
});
|
||||
|
||||
async function updatePersonById(userId: mongo.ObjectID) {
|
||||
const user = await getRemoteUser(userId);
|
||||
const user = await getRemoteUser(ps.userId);
|
||||
await updatePerson(user.uri);
|
||||
}
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import User from '../../../../models/user';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーID',
|
||||
'en-US': 'The user ID which you want to verify'
|
||||
@ -27,21 +26,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const user = await User.findOne({
|
||||
_id: ps.userId
|
||||
});
|
||||
const user = await Users.findOne(ps.userId as string);
|
||||
|
||||
if (user == null) {
|
||||
throw new Error('user not found');
|
||||
}
|
||||
|
||||
await User.findOneAndUpdate({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: {
|
||||
isVerified: true
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
isVerified: true
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,72 +0,0 @@
|
||||
import Note from '../../../../models/note';
|
||||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
|
||||
export const meta = {
|
||||
tags: ['hashtags'],
|
||||
|
||||
requireCredential: false,
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const instance = await fetchMeta();
|
||||
const hidedTags = instance.hidedTags.map(t => t.toLowerCase());
|
||||
|
||||
// 重い
|
||||
//const span = 1000 * 60 * 60 * 24 * 7; // 1週間
|
||||
const span = 1000 * 60 * 60 * 24; // 1日
|
||||
|
||||
//#region 1. 指定期間の内に投稿されたハッシュタグ(とユーザーのペア)を集計
|
||||
const data = await Note.aggregate([{
|
||||
$match: {
|
||||
createdAt: {
|
||||
$gt: new Date(Date.now() - span)
|
||||
},
|
||||
tagsLower: {
|
||||
$exists: true,
|
||||
$ne: []
|
||||
}
|
||||
}
|
||||
}, {
|
||||
$unwind: '$tagsLower'
|
||||
}, {
|
||||
$group: {
|
||||
_id: { tag: '$tagsLower', userId: '$userId' }
|
||||
}
|
||||
}]) as {
|
||||
_id: {
|
||||
tag: string;
|
||||
userId: any;
|
||||
}
|
||||
}[];
|
||||
//#endregion
|
||||
|
||||
if (data.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let tags: {
|
||||
name: string;
|
||||
count: number;
|
||||
}[] = [];
|
||||
|
||||
// カウント
|
||||
for (const x of data.map(x => x._id).filter(x => !hidedTags.includes(x.tag))) {
|
||||
const i = tags.findIndex(tag => tag.name == x.tag);
|
||||
if (i != -1) {
|
||||
tags[i].count++;
|
||||
} else {
|
||||
tags.push({
|
||||
name: x.tag,
|
||||
count: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// タグを人気順に並べ替え
|
||||
tags.sort((a, b) => b.count - a.count);
|
||||
|
||||
tags = tags.slice(0, 30);
|
||||
|
||||
return tags;
|
||||
});
|
@ -1,15 +1,15 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import config from '../../../../config';
|
||||
import * as mongo from 'mongodb';
|
||||
import User, { pack as packUser, IUser } from '../../../../models/user';
|
||||
import { createPerson } from '../../../../remote/activitypub/models/person';
|
||||
import Note, { pack as packNote, INote } from '../../../../models/note';
|
||||
import { createNote } from '../../../../remote/activitypub/models/note';
|
||||
import Resolver from '../../../../remote/activitypub/resolver';
|
||||
import { ApiError } from '../../error';
|
||||
import Instance from '../../../../models/instance';
|
||||
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';
|
||||
|
||||
export const meta = {
|
||||
tags: ['federation'],
|
||||
@ -53,25 +53,40 @@ export default define(meta, async (ps) => {
|
||||
async function fetchAny(uri: string) {
|
||||
// URIがこのサーバーを指しているなら、ローカルユーザーIDとしてDBからフェッチ
|
||||
if (uri.startsWith(config.url + '/')) {
|
||||
const id = new mongo.ObjectID(uri.split('/').pop());
|
||||
const [user, note] = await Promise.all([
|
||||
User.findOne({ _id: id }),
|
||||
Note.findOne({ _id: id })
|
||||
]);
|
||||
const parts = uri.split('/');
|
||||
const id = parts.pop();
|
||||
const type = parts.pop();
|
||||
|
||||
const packed = await mergePack(user, note);
|
||||
if (packed !== null) return packed;
|
||||
if (type === 'notes') {
|
||||
const note = await Notes.findOne(id);
|
||||
|
||||
if (note) {
|
||||
return {
|
||||
type: 'Note',
|
||||
object: await Notes.pack(note, null, { detail: true })
|
||||
};
|
||||
}
|
||||
} else if (type === 'users') {
|
||||
const user = await Users.findOne(id);
|
||||
|
||||
if (user) {
|
||||
return {
|
||||
type: 'User',
|
||||
object: await Users.pack(user, null, { detail: true })
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ブロックしてたら中断
|
||||
const instance = await Instance.findOne({ host: extractDbHost(uri) });
|
||||
if (instance && instance.isBlocked) return null;
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(extractDbHost(uri))) return null;
|
||||
|
||||
// URI(AP Object id)としてDB検索
|
||||
{
|
||||
const [user, note] = await Promise.all([
|
||||
User.findOne({ uri: uri }),
|
||||
Note.findOne({ uri: uri })
|
||||
Users.findOne({ uri: uri }),
|
||||
Notes.findOne({ uri: uri })
|
||||
]);
|
||||
|
||||
const packed = await mergePack(user, note);
|
||||
@ -86,8 +101,8 @@ async function fetchAny(uri: string) {
|
||||
// これはDBに存在する可能性があるため再度DB検索
|
||||
if (uri !== object.id) {
|
||||
const [user, note] = await Promise.all([
|
||||
User.findOne({ uri: object.id }),
|
||||
Note.findOne({ uri: object.id })
|
||||
Users.findOne({ uri: object.id }),
|
||||
Notes.findOne({ uri: object.id })
|
||||
]);
|
||||
|
||||
const packed = await mergePack(user, note);
|
||||
@ -99,7 +114,7 @@ async function fetchAny(uri: string) {
|
||||
const user = await createPerson(object.id);
|
||||
return {
|
||||
type: 'User',
|
||||
object: await packUser(user, null, { detail: true })
|
||||
object: await Users.pack(user, null, { detail: true })
|
||||
};
|
||||
}
|
||||
|
||||
@ -107,25 +122,25 @@ async function fetchAny(uri: string) {
|
||||
const note = await createNote(object.id);
|
||||
return {
|
||||
type: 'Note',
|
||||
object: await packNote(note, null, { detail: true })
|
||||
object: await Notes.pack(note, null, { detail: true })
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function mergePack(user: IUser, note: INote) {
|
||||
async function mergePack(user: User, note: Note) {
|
||||
if (user !== null) {
|
||||
return {
|
||||
type: 'User',
|
||||
object: await packUser(user, null, { detail: true })
|
||||
object: await Users.pack(user, null, { detail: true })
|
||||
};
|
||||
}
|
||||
|
||||
if (note !== null) {
|
||||
return {
|
||||
type: 'Note',
|
||||
object: await packNote(note, null, { detail: true })
|
||||
object: await Notes.pack(note, null, { detail: true })
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import rndstr from 'rndstr';
|
||||
import $ from 'cafy';
|
||||
import App, { pack } from '../../../../models/app';
|
||||
import define from '../../define';
|
||||
import { Apps } from '../../../../models';
|
||||
import { genId } from '../../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
tags: ['app'],
|
||||
@ -34,9 +35,10 @@ export default define(meta, async (ps, user) => {
|
||||
const secret = rndstr('a-zA-Z0-9', 32);
|
||||
|
||||
// Create account
|
||||
const app = await App.insert({
|
||||
const app = await Apps.save({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
userId: user && user._id,
|
||||
userId: user && user.id,
|
||||
name: ps.name,
|
||||
description: ps.description,
|
||||
permission: ps.permission,
|
||||
@ -44,7 +46,7 @@ export default define(meta, async (ps, user) => {
|
||||
secret: secret
|
||||
});
|
||||
|
||||
return await pack(app, null, {
|
||||
return await Apps.pack(app, null, {
|
||||
detail: true,
|
||||
includeSecret: true
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import App, { pack } from '../../../../models/app';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { Apps } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['app'],
|
||||
@ -10,7 +10,6 @@ export const meta = {
|
||||
params: {
|
||||
appId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform
|
||||
},
|
||||
},
|
||||
|
||||
@ -27,14 +26,14 @@ export default define(meta, async (ps, user, app) => {
|
||||
const isSecure = user != null && app == null;
|
||||
|
||||
// Lookup app
|
||||
const ap = await App.findOne({ _id: ps.appId });
|
||||
const ap = await Apps.findOne(ps.appId);
|
||||
|
||||
if (ap === null) {
|
||||
if (ap == null) {
|
||||
throw new ApiError(meta.errors.noSuchApp);
|
||||
}
|
||||
|
||||
return await pack(ap, user, {
|
||||
return await Apps.pack(ap, user, {
|
||||
detail: true,
|
||||
includeSecret: isSecure && ap.userId.equals(user._id)
|
||||
includeSecret: isSecure && (ap.userId === user.id)
|
||||
});
|
||||
});
|
||||
|
@ -1,11 +1,10 @@
|
||||
import rndstr from 'rndstr';
|
||||
import * as crypto from 'crypto';
|
||||
import $ from 'cafy';
|
||||
import App from '../../../../models/app';
|
||||
import AuthSess from '../../../../models/auth-session';
|
||||
import AccessToken from '../../../../models/access-token';
|
||||
import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { AuthSessions, AccessTokens, Apps } from '../../../../models';
|
||||
import { genId } from '../../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
@ -31,10 +30,10 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Fetch token
|
||||
const session = await AuthSess
|
||||
const session = await AuthSessions
|
||||
.findOne({ token: ps.token });
|
||||
|
||||
if (session === null) {
|
||||
if (session == null) {
|
||||
throw new ApiError(meta.errors.noSuchSession);
|
||||
}
|
||||
|
||||
@ -42,16 +41,14 @@ export default define(meta, async (ps, user) => {
|
||||
const accessToken = rndstr('a-zA-Z0-9', 32);
|
||||
|
||||
// Fetch exist access token
|
||||
const exist = await AccessToken.findOne({
|
||||
const exist = await AccessTokens.findOne({
|
||||
appId: session.appId,
|
||||
userId: user._id,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
if (exist === null) {
|
||||
if (exist == null) {
|
||||
// Lookup app
|
||||
const app = await App.findOne({
|
||||
_id: session.appId
|
||||
});
|
||||
const app = await Apps.findOne(session.appId);
|
||||
|
||||
// Generate Hash
|
||||
const sha256 = crypto.createHash('sha256');
|
||||
@ -59,20 +56,19 @@ export default define(meta, async (ps, user) => {
|
||||
const hash = sha256.digest('hex');
|
||||
|
||||
// Insert access token doc
|
||||
await AccessToken.insert({
|
||||
await AccessTokens.save({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
appId: session.appId,
|
||||
userId: user._id,
|
||||
userId: user.id,
|
||||
token: accessToken,
|
||||
hash: hash
|
||||
});
|
||||
}
|
||||
|
||||
// Update session
|
||||
await AuthSess.update(session._id, {
|
||||
$set: {
|
||||
userId: user._id
|
||||
}
|
||||
await AuthSessions.update(session.id, {
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
return;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import * as uuid from 'uuid';
|
||||
import $ from 'cafy';
|
||||
import App from '../../../../../models/app';
|
||||
import AuthSess from '../../../../../models/auth-session';
|
||||
import config from '../../../../../config';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { Apps, AuthSessions } from '../../../../../models';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
@ -46,7 +46,7 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
// Lookup app
|
||||
const app = await App.findOne({
|
||||
const app = await Apps.findOne({
|
||||
secret: ps.appSecret
|
||||
});
|
||||
|
||||
@ -58,9 +58,10 @@ export default define(meta, async (ps) => {
|
||||
const token = uuid.v4();
|
||||
|
||||
// Create session token document
|
||||
const doc = await AuthSess.insert({
|
||||
const doc = await AuthSessions.save({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
appId: app._id,
|
||||
appId: app.id,
|
||||
token: token
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import AuthSess, { pack } from '../../../../../models/auth-session';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { AuthSessions } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
@ -29,7 +29,7 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Lookup session
|
||||
const session = await AuthSess.findOne({
|
||||
const session = await AuthSessions.findOne({
|
||||
token: ps.token
|
||||
});
|
||||
|
||||
@ -37,5 +37,5 @@ export default define(meta, async (ps, user) => {
|
||||
throw new ApiError(meta.errors.noSuchSession);
|
||||
}
|
||||
|
||||
return await pack(session, user);
|
||||
return await AuthSessions.pack(session, user);
|
||||
});
|
||||
|
@ -1,10 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import App from '../../../../../models/app';
|
||||
import AuthSess from '../../../../../models/auth-session';
|
||||
import AccessToken from '../../../../../models/access-token';
|
||||
import { pack } from '../../../../../models/user';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
@ -67,7 +64,7 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
// Lookup app
|
||||
const app = await App.findOne({
|
||||
const app = await Apps.findOne({
|
||||
secret: ps.appSecret
|
||||
});
|
||||
|
||||
@ -76,13 +73,12 @@ export default define(meta, async (ps) => {
|
||||
}
|
||||
|
||||
// Fetch token
|
||||
const session = await AuthSess
|
||||
.findOne({
|
||||
token: ps.token,
|
||||
appId: app._id
|
||||
});
|
||||
const session = await AuthSessions.findOne({
|
||||
token: ps.token,
|
||||
appId: app.id
|
||||
});
|
||||
|
||||
if (session === null) {
|
||||
if (session == null) {
|
||||
throw new ApiError(meta.errors.noSuchSession);
|
||||
}
|
||||
|
||||
@ -91,25 +87,17 @@ export default define(meta, async (ps) => {
|
||||
}
|
||||
|
||||
// Lookup access token
|
||||
const accessToken = await AccessToken.findOne({
|
||||
appId: app._id,
|
||||
const accessToken = await AccessTokens.findOne({
|
||||
appId: app.id,
|
||||
userId: session.userId
|
||||
});
|
||||
|
||||
// Delete session
|
||||
|
||||
/* https://github.com/Automattic/monk/issues/178
|
||||
AuthSess.deleteOne({
|
||||
_id: session._id
|
||||
});
|
||||
*/
|
||||
AuthSess.remove({
|
||||
_id: session._id
|
||||
});
|
||||
AuthSessions.delete(session.id);
|
||||
|
||||
return {
|
||||
accessToken: accessToken.token,
|
||||
user: await pack(session.userId, null, {
|
||||
user: await Users.pack(session.userId, null, {
|
||||
detail: true
|
||||
})
|
||||
};
|
||||
|
@ -1,12 +1,11 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import * as ms from 'ms';
|
||||
import { pack } from '../../../../models/user';
|
||||
import Blocking from '../../../../models/blocking';
|
||||
import create from '../../../../services/blocking/create';
|
||||
import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { getUser } from '../../common/getters';
|
||||
import { Blockings, NoteWatchings } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -25,12 +24,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-write',
|
||||
kind: 'write:blocks',
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -63,7 +61,7 @@ export default define(meta, async (ps, user) => {
|
||||
const blocker = user;
|
||||
|
||||
// 自分自身
|
||||
if (user._id.equals(ps.userId)) {
|
||||
if (user.id === ps.userId) {
|
||||
throw new ApiError(meta.errors.blockeeIsYourself);
|
||||
}
|
||||
|
||||
@ -74,19 +72,22 @@ export default define(meta, async (ps, user) => {
|
||||
});
|
||||
|
||||
// Check if already blocking
|
||||
const exist = await Blocking.findOne({
|
||||
blockerId: blocker._id,
|
||||
blockeeId: blockee._id
|
||||
const exist = await Blockings.findOne({
|
||||
blockerId: blocker.id,
|
||||
blockeeId: blockee.id
|
||||
});
|
||||
|
||||
if (exist !== null) {
|
||||
if (exist != null) {
|
||||
throw new ApiError(meta.errors.alreadyBlocking);
|
||||
}
|
||||
|
||||
// Create blocking
|
||||
await create(blocker, blockee);
|
||||
|
||||
return await pack(blockee._id, user, {
|
||||
detail: true
|
||||
NoteWatchings.delete({
|
||||
userId: blocker.id,
|
||||
noteUserId: blockee.id
|
||||
});
|
||||
|
||||
return await Blockings.pack(blockee.id, user);
|
||||
});
|
||||
|
@ -1,12 +1,11 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import * as ms from 'ms';
|
||||
import { pack } from '../../../../models/user';
|
||||
import Blocking from '../../../../models/blocking';
|
||||
import deleteBlocking from '../../../../services/blocking/delete';
|
||||
import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { getUser } from '../../common/getters';
|
||||
import { Blockings } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -25,12 +24,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-write',
|
||||
kind: 'write:blocks',
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -63,7 +61,7 @@ export default define(meta, async (ps, user) => {
|
||||
const blocker = user;
|
||||
|
||||
// Check if the blockee is yourself
|
||||
if (user._id.equals(ps.userId)) {
|
||||
if (user.id === ps.userId) {
|
||||
throw new ApiError(meta.errors.blockeeIsYourself);
|
||||
}
|
||||
|
||||
@ -74,19 +72,17 @@ export default define(meta, async (ps, user) => {
|
||||
});
|
||||
|
||||
// Check not blocking
|
||||
const exist = await Blocking.findOne({
|
||||
blockerId: blocker._id,
|
||||
blockeeId: blockee._id
|
||||
const exist = await Blockings.findOne({
|
||||
blockerId: blocker.id,
|
||||
blockeeId: blockee.id
|
||||
});
|
||||
|
||||
if (exist === null) {
|
||||
if (exist == null) {
|
||||
throw new ApiError(meta.errors.notBlocking);
|
||||
}
|
||||
|
||||
// Delete blocking
|
||||
await deleteBlocking(blocker, blockee);
|
||||
|
||||
return await pack(blockee._id, user, {
|
||||
detail: true
|
||||
});
|
||||
return await Blockings.pack(blockee.id, user);
|
||||
});
|
||||
|
@ -1,7 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import Blocking, { packMany } from '../../../../models/blocking';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { Blockings } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -13,7 +14,7 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-read',
|
||||
kind: 'read:blocks',
|
||||
|
||||
params: {
|
||||
limit: {
|
||||
@ -23,12 +24,10 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
},
|
||||
|
||||
@ -41,30 +40,12 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const query = {
|
||||
blockerId: me._id
|
||||
} as any;
|
||||
const query = makePaginationQuery(Blockings.createQueryBuilder('blocking'), ps.sinceId, ps.untilId)
|
||||
.andWhere(`blocking.blockerId = :meId`, { meId: me.id });
|
||||
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
const blockings = await query
|
||||
.take(ps.limit)
|
||||
.getMany();
|
||||
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
query._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
query._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
}
|
||||
|
||||
const blockings = await Blocking
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
|
||||
return await packMany(blockings, me);
|
||||
return await Blockings.packMany(blockings, me);
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import activeUsersChart from '../../../../services/chart/active-users';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { activeUsersChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -28,12 +29,7 @@ export const meta = {
|
||||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
res: convertLog(activeUsersChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import driveChart, { driveLogSchema } from '../../../../services/chart/drive';
|
||||
import { convertLog } from '../../../../services/chart';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { driveChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -29,7 +29,7 @@ export const meta = {
|
||||
},
|
||||
},
|
||||
|
||||
res: convertLog(driveLogSchema),
|
||||
res: convertLog(driveChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import federationChart from '../../../../services/chart/federation';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { federationChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -28,12 +29,7 @@ export const meta = {
|
||||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
res: convertLog(federationChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import hashtagChart from '../../../../services/chart/hashtag';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { hashtagChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -35,12 +36,7 @@ export const meta = {
|
||||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
res: convertLog(hashtagChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import instanceChart from '../../../../services/chart/instance';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { instanceChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -36,12 +37,7 @@ export const meta = {
|
||||
}
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
res: convertLog(instanceChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import networkChart from '../../../../services/chart/network';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { networkChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -28,12 +29,7 @@ export const meta = {
|
||||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
res: convertLog(networkChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import notesChart, { notesLogSchema } from '../../../../services/chart/notes';
|
||||
import { convertLog } from '../../../../services/chart';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { notesChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -29,7 +29,7 @@ export const meta = {
|
||||
},
|
||||
},
|
||||
|
||||
res: convertLog(notesLogSchema),
|
||||
res: convertLog(notesChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import perUserDriveChart, { perUserDriveLogSchema } from '../../../../../services/chart/per-user-drive';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { convertLog } from '../../../../../services/chart';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { convertLog } from '../../../../../services/chart/core';
|
||||
import { perUserDriveChart } from '../../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -31,7 +31,6 @@ export const meta = {
|
||||
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -39,7 +38,7 @@ export const meta = {
|
||||
}
|
||||
},
|
||||
|
||||
res: convertLog(perUserDriveLogSchema),
|
||||
res: convertLog(perUserDriveChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import perUserFollowingChart, { perUserFollowingLogSchema } from '../../../../../services/chart/per-user-following';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { convertLog } from '../../../../../services/chart';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { convertLog } from '../../../../../services/chart/core';
|
||||
import { perUserFollowingChart } from '../../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -31,7 +31,6 @@ export const meta = {
|
||||
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -39,9 +38,9 @@ export const meta = {
|
||||
}
|
||||
},
|
||||
|
||||
res: convertLog(perUserFollowingLogSchema),
|
||||
res: convertLog(perUserFollowingChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
return await perUserFollowingChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
return await perUserFollowingChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import perUserNotesChart, { perUserNotesLogSchema } from '../../../../../services/chart/per-user-notes';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { convertLog } from '../../../../../services/chart';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { convertLog } from '../../../../../services/chart/core';
|
||||
import { perUserNotesChart } from '../../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -31,7 +31,6 @@ export const meta = {
|
||||
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -39,7 +38,7 @@ export const meta = {
|
||||
}
|
||||
},
|
||||
|
||||
res: convertLog(perUserNotesLogSchema),
|
||||
res: convertLog(perUserNotesChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import perUserReactionsChart from '../../../../../services/chart/per-user-reactions';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { convertLog } from '../../../../../services/chart/core';
|
||||
import { perUserReactionsChart } from '../../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -30,7 +31,6 @@ export const meta = {
|
||||
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -38,12 +38,7 @@ export const meta = {
|
||||
}
|
||||
},
|
||||
|
||||
res: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
res: convertLog(perUserReactionsChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import usersChart, { usersLogSchema } from '../../../../services/chart/users';
|
||||
import { convertLog } from '../../../../services/chart';
|
||||
import { convertLog } from '../../../../services/chart/core';
|
||||
import { usersChart } from '../../../../services/chart';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -29,7 +29,7 @@ export const meta = {
|
||||
},
|
||||
},
|
||||
|
||||
res: convertLog(usersLogSchema),
|
||||
res: convertLog(usersChart.schema),
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import DriveFile from '../../../models/drive-file';
|
||||
import define from '../define';
|
||||
import fetchMeta from '../../../misc/fetch-meta';
|
||||
import { DriveFiles } from '../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -12,7 +12,7 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
@ -31,27 +31,7 @@ export default define(meta, async (ps, user) => {
|
||||
const instance = await fetchMeta();
|
||||
|
||||
// Calculate drive usage
|
||||
const usage = await DriveFile.aggregate([{
|
||||
$match: {
|
||||
'metadata.userId': user._id,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then((aggregates: any[]) => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
const usage = await DriveFiles.clacDriveUsageOf(user);
|
||||
|
||||
return {
|
||||
capacity: 1024 * 1024 * instance.localDriveCapacityMb,
|
||||
|
@ -1,7 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import DriveFile, { packMany } from '../../../../models/drive-file';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { DriveFiles } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -13,7 +14,7 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
limit: {
|
||||
@ -23,18 +24,15 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
folderId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
default: null as any,
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
type: {
|
||||
@ -51,36 +49,24 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId)
|
||||
.andWhere('file.userId = :userId', { userId: user.id });
|
||||
|
||||
const query = {
|
||||
'metadata.userId': user._id,
|
||||
'metadata.folderId': ps.folderId,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
} as any;
|
||||
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
query._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
query._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
if (ps.folderId) {
|
||||
query.andWhere('file.folderId = :folderId', { folderId: ps.folderId });
|
||||
} else {
|
||||
query.andWhere('file.folderId IS NULL');
|
||||
}
|
||||
|
||||
if (ps.type) {
|
||||
query.contentType = new RegExp(`^${ps.type.replace(/\*/g, '.+?')}$`);
|
||||
if (ps.type.endsWith('/*')) {
|
||||
query.andWhere('file.type like :type', { type: ps.type.replace('/*', '/') + '%' });
|
||||
} else {
|
||||
query.andWhere('file.type = :type', { type: ps.type });
|
||||
}
|
||||
}
|
||||
|
||||
const files = await DriveFile
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
const files = await query.take(ps.limit).getMany();
|
||||
|
||||
return await packMany(files, { detail: false, self: true });
|
||||
return await DriveFiles.packMany(files, { detail: false, self: true });
|
||||
});
|
||||
|
@ -1,9 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { packMany } from '../../../../../models/note';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -17,12 +16,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
fileId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のファイルID',
|
||||
'en-US': 'Target file ID'
|
||||
@ -48,18 +46,17 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Fetch file
|
||||
const file = await DriveFile
|
||||
.findOne({
|
||||
_id: ps.fileId,
|
||||
'metadata.userId': user._id,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
});
|
||||
const file = await DriveFiles.findOne({
|
||||
id: ps.fileId,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
if (file === null) {
|
||||
if (file == null) {
|
||||
throw new ApiError(meta.errors.noSuchFile);
|
||||
}
|
||||
|
||||
/* v11 TODO
|
||||
return await packMany(file.metadata.attachedNoteIds || [], user, {
|
||||
detail: true
|
||||
});
|
||||
});*/
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import DriveFile, { pack } from '../../../../../models/drive-file';
|
||||
import define from '../../../define';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -12,7 +12,7 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
md5: {
|
||||
@ -29,11 +29,12 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const file = await DriveFile.findOne({
|
||||
const file = await DriveFiles.findOne({
|
||||
md5: ps.md5,
|
||||
'metadata.userId': user._id,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
return { file: file ? await pack(file, { self: true }) : null };
|
||||
return {
|
||||
file: file ? await DriveFiles.pack(file, { self: true }) : null
|
||||
};
|
||||
});
|
||||
|
@ -1,11 +1,11 @@
|
||||
import * as ms from 'ms';
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { validateFileName, pack } from '../../../../../models/drive-file';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import create from '../../../../../services/drive/add-file';
|
||||
import define from '../../../define';
|
||||
import { apiLogger } from '../../../logger';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -24,12 +24,11 @@ export const meta = {
|
||||
|
||||
requireFile: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
kind: 'write:drive',
|
||||
|
||||
params: {
|
||||
folderId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
transform: transform,
|
||||
default: null as any,
|
||||
desc: {
|
||||
'ja-JP': 'フォルダID'
|
||||
@ -78,7 +77,7 @@ export default define(meta, async (ps, user, app, file, cleanup) => {
|
||||
name = null;
|
||||
} else if (name === 'blob') {
|
||||
name = null;
|
||||
} else if (!validateFileName(name)) {
|
||||
} else if (!DriveFiles.validateFileName(name)) {
|
||||
throw new ApiError(meta.errors.invalidFileName);
|
||||
}
|
||||
} else {
|
||||
@ -88,7 +87,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 pack(driveFile, { self: true });
|
||||
return DriveFiles.pack(driveFile, { self: true });
|
||||
} catch (e) {
|
||||
apiLogger.error(e);
|
||||
throw new ApiError();
|
||||
|
@ -1,10 +1,10 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import del from '../../../../../services/drive/delete-file';
|
||||
import { publishDriveStream } from '../../../../../services/stream';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -18,12 +18,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
kind: 'write:drive',
|
||||
|
||||
params: {
|
||||
fileId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のファイルID',
|
||||
'en-US': 'Target file ID'
|
||||
@ -47,17 +46,13 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Fetch file
|
||||
const file = await DriveFile
|
||||
.findOne({
|
||||
_id: ps.fileId
|
||||
});
|
||||
const file = await DriveFiles.findOne(ps.fileId);
|
||||
|
||||
if (file === null) {
|
||||
if (file == null) {
|
||||
throw new ApiError(meta.errors.noSuchFile);
|
||||
}
|
||||
|
||||
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
|
||||
if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
|
||||
throw new ApiError(meta.errors.accessDenied);
|
||||
}
|
||||
|
||||
@ -65,7 +60,5 @@ export default define(meta, async (ps, user) => {
|
||||
await del(file);
|
||||
|
||||
// Publish fileDeleted event
|
||||
publishDriveStream(user._id, 'fileDeleted', file._id);
|
||||
|
||||
return;
|
||||
publishDriveStream(user.id, 'fileDeleted', file.id);
|
||||
});
|
||||
|
@ -1,14 +1,14 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFile, { pack } from '../../../../../models/drive-file';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
|
||||
tags: ['drive'],
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
name: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
|
||||
folderId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
transform: transform,
|
||||
default: null as any,
|
||||
desc: {
|
||||
'ja-JP': 'フォルダID'
|
||||
@ -27,12 +26,11 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const files = await DriveFile
|
||||
.find({
|
||||
filename: ps.name,
|
||||
'metadata.userId': user._id,
|
||||
'metadata.folderId': ps.folderId
|
||||
});
|
||||
const files = await DriveFiles.find({
|
||||
name: ps.name,
|
||||
userId: user.id,
|
||||
folderId: ps.folderId
|
||||
});
|
||||
|
||||
return await Promise.all(files.map(file => pack(file, { self: true })));
|
||||
return await Promise.all(files.map(file => DriveFiles.pack(file, { self: true })));
|
||||
});
|
||||
|
@ -1,10 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import * as mongo from 'mongodb';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFile, { pack, IDriveFile } from '../../../../../models/drive-file';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import config from '../../../../../config';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFile } from '../../../../../models/entities/drive-file';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -18,12 +17,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
fileId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のファイルID',
|
||||
'en-US': 'Target file ID'
|
||||
@ -65,49 +63,33 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
let file: IDriveFile;
|
||||
let file: DriveFile;
|
||||
|
||||
if (ps.fileId) {
|
||||
file = await DriveFile.findOne({
|
||||
_id: ps.fileId,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
});
|
||||
file = await DriveFiles.findOne(ps.fileId);
|
||||
} else if (ps.url) {
|
||||
const isInternalStorageUrl = ps.url.startsWith(config.driveUrl);
|
||||
if (isInternalStorageUrl) {
|
||||
// Extract file ID from url
|
||||
// e.g.
|
||||
// http://misskey.local/files/foo?original=bar --> foo
|
||||
const fileId = new mongo.ObjectID(ps.url.replace(config.driveUrl, '').replace(/\?(.*)$/, '').replace(/\//g, ''));
|
||||
file = await DriveFile.findOne({
|
||||
_id: fileId,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
});
|
||||
} else {
|
||||
file = await DriveFile.findOne({
|
||||
$or: [{
|
||||
'metadata.url': ps.url
|
||||
}, {
|
||||
'metadata.webpublicUrl': ps.url
|
||||
}, {
|
||||
'metadata.thumbnailUrl': ps.url
|
||||
}],
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
});
|
||||
}
|
||||
file = await DriveFiles.findOne({
|
||||
where: [{
|
||||
url: ps.url
|
||||
}, {
|
||||
webpublicUrl: ps.url
|
||||
}, {
|
||||
thumbnailUrl: ps.url
|
||||
}],
|
||||
});
|
||||
} else {
|
||||
throw new ApiError(meta.errors.fileIdOrUrlRequired);
|
||||
}
|
||||
|
||||
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
|
||||
if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
|
||||
throw new ApiError(meta.errors.accessDenied);
|
||||
}
|
||||
|
||||
if (file === null) {
|
||||
if (file == null) {
|
||||
throw new ApiError(meta.errors.noSuchFile);
|
||||
}
|
||||
|
||||
return await pack(file, {
|
||||
return await DriveFiles.pack(file, {
|
||||
detail: true,
|
||||
self: true
|
||||
});
|
||||
|
@ -1,11 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFolder from '../../../../../models/drive-folder';
|
||||
import DriveFile, { validateFileName, pack } from '../../../../../models/drive-file';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { publishDriveStream } from '../../../../../services/stream';
|
||||
import define from '../../../define';
|
||||
import Note from '../../../../../models/note';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFiles, DriveFolders } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,12 +15,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
kind: 'write:drive',
|
||||
|
||||
params: {
|
||||
fileId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のファイルID'
|
||||
}
|
||||
@ -30,7 +27,6 @@ export const meta = {
|
||||
|
||||
folderId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
transform: transform,
|
||||
default: undefined as any,
|
||||
desc: {
|
||||
'ja-JP': 'フォルダID'
|
||||
@ -38,7 +34,7 @@ export const meta = {
|
||||
},
|
||||
|
||||
name: {
|
||||
validator: $.optional.str.pipe(validateFileName),
|
||||
validator: $.optional.str.pipe(DriveFiles.validateFileName),
|
||||
default: undefined as any,
|
||||
desc: {
|
||||
'ja-JP': 'ファイル名',
|
||||
@ -78,69 +74,47 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Fetch file
|
||||
const file = await DriveFile
|
||||
.findOne({
|
||||
_id: ps.fileId
|
||||
});
|
||||
const file = await DriveFiles.findOne(ps.fileId);
|
||||
|
||||
if (file === null) {
|
||||
if (file == null) {
|
||||
throw new ApiError(meta.errors.noSuchFile);
|
||||
}
|
||||
|
||||
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
|
||||
if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
|
||||
throw new ApiError(meta.errors.accessDenied);
|
||||
}
|
||||
|
||||
if (ps.name) file.filename = ps.name;
|
||||
if (ps.name) file.name = ps.name;
|
||||
|
||||
if (ps.isSensitive !== undefined) file.metadata.isSensitive = ps.isSensitive;
|
||||
if (ps.isSensitive !== undefined) file.isSensitive = ps.isSensitive;
|
||||
|
||||
if (ps.folderId !== undefined) {
|
||||
if (ps.folderId === null) {
|
||||
file.metadata.folderId = null;
|
||||
file.folderId = null;
|
||||
} else {
|
||||
// Fetch folder
|
||||
const folder = await DriveFolder
|
||||
.findOne({
|
||||
_id: ps.folderId,
|
||||
userId: user._id
|
||||
});
|
||||
const folder = await DriveFolders.findOne({
|
||||
id: ps.folderId,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
if (folder === null) {
|
||||
if (folder == null) {
|
||||
throw new ApiError(meta.errors.noSuchFolder);
|
||||
}
|
||||
|
||||
file.metadata.folderId = folder._id;
|
||||
file.folderId = folder.id;
|
||||
}
|
||||
}
|
||||
|
||||
await DriveFile.update(file._id, {
|
||||
$set: {
|
||||
filename: file.filename,
|
||||
'metadata.folderId': file.metadata.folderId,
|
||||
'metadata.isSensitive': file.metadata.isSensitive
|
||||
}
|
||||
await DriveFiles.update(file.id, {
|
||||
name: file.name,
|
||||
folderId: file.folderId,
|
||||
isSensitive: file.isSensitive
|
||||
});
|
||||
|
||||
// ドライブのファイルが非正規化されているドキュメントも更新
|
||||
Note.find({
|
||||
'_files._id': file._id
|
||||
}).then(notes => {
|
||||
for (const note of notes) {
|
||||
note._files[note._files.findIndex(f => f._id.equals(file._id))] = file;
|
||||
Note.update({ _id: note._id }, {
|
||||
$set: {
|
||||
_files: note._files
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const fileObj = await pack(file, { self: true });
|
||||
const fileObj = await DriveFiles.pack(file, { self: true });
|
||||
|
||||
// Publish fileUpdated event
|
||||
publishDriveStream(user._id, 'fileUpdated', fileObj);
|
||||
publishDriveStream(user.id, 'fileUpdated', fileObj);
|
||||
|
||||
return fileObj;
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import * as ms from 'ms';
|
||||
import { pack } from '../../../../../models/drive-file';
|
||||
import uploadFromUrl from '../../../../../services/drive/upload-from-url';
|
||||
import define from '../../../define';
|
||||
import { DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -19,7 +19,7 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
kind: 'write:drive',
|
||||
|
||||
params: {
|
||||
url: {
|
||||
@ -30,7 +30,6 @@ export const meta = {
|
||||
folderId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
default: null as any,
|
||||
transform: transform
|
||||
},
|
||||
|
||||
isSensitive: {
|
||||
@ -53,5 +52,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
return await pack(await uploadFromUrl(ps.url, user, ps.folderId, null, ps.isSensitive, ps.force), { self: true });
|
||||
return await DriveFiles.pack(await uploadFromUrl(ps.url, user, ps.folderId, null, ps.isSensitive, ps.force), { self: true });
|
||||
});
|
||||
|
@ -1,7 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import DriveFolder, { pack } from '../../../../models/drive-folder';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { DriveFolders } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -13,7 +14,7 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
limit: {
|
||||
@ -23,18 +24,15 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
folderId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
default: null as any,
|
||||
transform: transform,
|
||||
}
|
||||
},
|
||||
|
||||
@ -47,29 +45,16 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
const query = {
|
||||
userId: user._id,
|
||||
parentId: ps.folderId
|
||||
} as any;
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
query._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
query._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
const query = makePaginationQuery(DriveFolders.createQueryBuilder('folder'), ps.sinceId, ps.untilId)
|
||||
.andWhere('folder.userId = :userId', { userId: user.id });
|
||||
|
||||
if (ps.folderId) {
|
||||
query.andWhere('folder.parentId = :parentId', { parentId: ps.folderId });
|
||||
} else {
|
||||
query.andWhere('folder.parentId IS NULL');
|
||||
}
|
||||
|
||||
const folders = await DriveFolder
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
const folders = await query.take(ps.limit).getMany();
|
||||
|
||||
return await Promise.all(folders.map(folder => pack(folder)));
|
||||
return await Promise.all(folders.map(folder => DriveFolders.pack(folder)));
|
||||
});
|
||||
|
@ -1,9 +1,10 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { publishDriveStream } from '../../../../../services/stream';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFolders } from '../../../../../models';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -17,11 +18,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
kind: 'write:drive',
|
||||
|
||||
params: {
|
||||
name: {
|
||||
validator: $.optional.str.pipe(isValidFolderName),
|
||||
validator: $.optional.str.pipe(DriveFolders.validateFolderName),
|
||||
default: 'Untitled',
|
||||
desc: {
|
||||
'ja-JP': 'フォルダ名',
|
||||
@ -31,7 +32,6 @@ export const meta = {
|
||||
|
||||
parentId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '親フォルダID',
|
||||
'en-US': 'Parent folder ID'
|
||||
@ -53,29 +53,29 @@ export default define(meta, async (ps, user) => {
|
||||
let parent = null;
|
||||
if (ps.parentId) {
|
||||
// Fetch parent folder
|
||||
parent = await DriveFolder
|
||||
.findOne({
|
||||
_id: ps.parentId,
|
||||
userId: user._id
|
||||
});
|
||||
parent = await DriveFolders.findOne({
|
||||
id: ps.parentId,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
if (parent === null) {
|
||||
if (parent == null) {
|
||||
throw new ApiError(meta.errors.noSuchFolder);
|
||||
}
|
||||
}
|
||||
|
||||
// Create folder
|
||||
const folder = await DriveFolder.insert({
|
||||
const folder = await DriveFolders.save({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
name: ps.name,
|
||||
parentId: parent !== null ? parent._id : null,
|
||||
userId: user._id
|
||||
parentId: parent !== null ? parent.id : null,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
const folderObj = await pack(folder);
|
||||
const folderObj = await DriveFolders.pack(folder);
|
||||
|
||||
// Publish folderCreated event
|
||||
publishDriveStream(user._id, 'folderCreated', folderObj);
|
||||
publishDriveStream(user.id, 'folderCreated', folderObj);
|
||||
|
||||
return folderObj;
|
||||
});
|
||||
|
@ -1,10 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFolder from '../../../../../models/drive-folder';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { publishDriveStream } from '../../../../../services/stream';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFolders, DriveFiles } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -18,12 +17,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
kind: 'write:drive',
|
||||
|
||||
params: {
|
||||
folderId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のフォルダID',
|
||||
'en-US': 'Target folder ID'
|
||||
@ -48,29 +46,26 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Get folder
|
||||
const folder = await DriveFolder
|
||||
.findOne({
|
||||
_id: ps.folderId,
|
||||
userId: user._id
|
||||
});
|
||||
const folder = await DriveFolders.findOne({
|
||||
id: ps.folderId,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
if (folder === null) {
|
||||
if (folder == null) {
|
||||
throw new ApiError(meta.errors.noSuchFolder);
|
||||
}
|
||||
|
||||
const [childFoldersCount, childFilesCount] = await Promise.all([
|
||||
DriveFolder.count({ parentId: folder._id }),
|
||||
DriveFile.count({ 'metadata.folderId': folder._id })
|
||||
DriveFolders.count({ parentId: folder.id }),
|
||||
DriveFiles.count({ folderId: folder.id })
|
||||
]);
|
||||
|
||||
if (childFoldersCount !== 0 || childFilesCount !== 0) {
|
||||
throw new ApiError(meta.errors.hasChildFilesOrFolders);
|
||||
}
|
||||
|
||||
await DriveFolder.remove({ _id: folder._id });
|
||||
await DriveFolders.delete(folder.id);
|
||||
|
||||
// Publish folderCreated event
|
||||
publishDriveStream(user._id, 'folderDeleted', folder._id);
|
||||
|
||||
return;
|
||||
publishDriveStream(user.id, 'folderDeleted', folder.id);
|
||||
});
|
||||
|
@ -1,14 +1,14 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { DriveFolders } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['drive'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
name: {
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
|
||||
parentId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
transform: transform,
|
||||
default: null as any,
|
||||
desc: {
|
||||
'ja-JP': 'フォルダID'
|
||||
@ -34,12 +33,11 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const folders = await DriveFolder
|
||||
.find({
|
||||
name: ps.name,
|
||||
userId: user._id,
|
||||
parentId: ps.parentId
|
||||
});
|
||||
const folders = await DriveFolders.find({
|
||||
name: ps.name,
|
||||
userId: user.id,
|
||||
parentId: ps.parentId
|
||||
});
|
||||
|
||||
return await Promise.all(folders.map(folder => pack(folder)));
|
||||
return await Promise.all(folders.map(folder => DriveFolders.pack(folder)));
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFolders } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -16,12 +16,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
folderId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のフォルダID',
|
||||
'en-US': 'Target folder ID'
|
||||
@ -44,17 +43,16 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Get folder
|
||||
const folder = await DriveFolder
|
||||
.findOne({
|
||||
_id: ps.folderId,
|
||||
userId: user._id
|
||||
});
|
||||
const folder = await DriveFolders.findOne({
|
||||
id: ps.folderId,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
if (folder === null) {
|
||||
if (folder == null) {
|
||||
throw new ApiError(meta.errors.noSuchFolder);
|
||||
}
|
||||
|
||||
return await pack(folder, {
|
||||
return await DriveFolders.pack(folder, {
|
||||
detail: true
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { publishDriveStream } from '../../../../../services/stream';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { DriveFolders } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -17,12 +17,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
kind: 'write:drive',
|
||||
|
||||
params: {
|
||||
folderId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のフォルダID',
|
||||
'en-US': 'Target folder ID'
|
||||
@ -30,7 +29,7 @@ export const meta = {
|
||||
},
|
||||
|
||||
name: {
|
||||
validator: $.optional.str.pipe(isValidFolderName),
|
||||
validator: $.optional.str.pipe(DriveFolders.validateFolderName),
|
||||
desc: {
|
||||
'ja-JP': 'フォルダ名',
|
||||
'en-US': 'Folder name'
|
||||
@ -39,7 +38,6 @@ export const meta = {
|
||||
|
||||
parentId: {
|
||||
validator: $.optional.nullable.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '親フォルダID',
|
||||
'en-US': 'Parent folder ID'
|
||||
@ -70,46 +68,41 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Fetch folder
|
||||
const folder = await DriveFolder
|
||||
.findOne({
|
||||
_id: ps.folderId,
|
||||
userId: user._id
|
||||
});
|
||||
const folder = await DriveFolders.findOne({
|
||||
id: ps.folderId,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
if (folder === null) {
|
||||
if (folder == null) {
|
||||
throw new ApiError(meta.errors.noSuchFolder);
|
||||
}
|
||||
|
||||
if (ps.name) folder.name = ps.name;
|
||||
|
||||
if (ps.parentId !== undefined) {
|
||||
if (ps.parentId.equals(folder._id)) {
|
||||
if (ps.parentId === folder.id) {
|
||||
throw new ApiError(meta.errors.recursiveNesting);
|
||||
} else if (ps.parentId === null) {
|
||||
folder.parentId = null;
|
||||
} else {
|
||||
// Get parent folder
|
||||
const parent = await DriveFolder
|
||||
.findOne({
|
||||
_id: ps.parentId,
|
||||
userId: user._id
|
||||
});
|
||||
const parent = await DriveFolders.findOne({
|
||||
id: ps.parentId,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
if (parent === null) {
|
||||
if (parent == null) {
|
||||
throw new ApiError(meta.errors.noSuchParentFolder);
|
||||
}
|
||||
|
||||
// Check if the circular reference will occur
|
||||
async function checkCircle(folderId: any): Promise<boolean> {
|
||||
// Fetch folder
|
||||
const folder2 = await DriveFolder.findOne({
|
||||
_id: folderId
|
||||
}, {
|
||||
_id: true,
|
||||
parentId: true
|
||||
const folder2 = await DriveFolders.findOne({
|
||||
id: folderId
|
||||
});
|
||||
|
||||
if (folder2._id.equals(folder._id)) {
|
||||
if (folder2.id === folder.id) {
|
||||
return true;
|
||||
} else if (folder2.parentId) {
|
||||
return await checkCircle(folder2.parentId);
|
||||
@ -124,22 +117,20 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
}
|
||||
|
||||
folder.parentId = parent._id;
|
||||
folder.parentId = parent.id;
|
||||
}
|
||||
}
|
||||
|
||||
// Update
|
||||
DriveFolder.update(folder._id, {
|
||||
$set: {
|
||||
name: folder.name,
|
||||
parentId: folder.parentId
|
||||
}
|
||||
DriveFolders.update(folder.id, {
|
||||
name: folder.name,
|
||||
parentId: folder.parentId
|
||||
});
|
||||
|
||||
const folderObj = await pack(folder);
|
||||
const folderObj = await DriveFolders.pack(folder);
|
||||
|
||||
// Publish folderUpdated event
|
||||
publishDriveStream(user._id, 'folderUpdated', folderObj);
|
||||
publishDriveStream(user.id, 'folderUpdated', folderObj);
|
||||
|
||||
return folderObj;
|
||||
});
|
||||
|
@ -1,14 +1,15 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import DriveFile, { packMany } from '../../../../models/drive-file';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { DriveFiles } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
|
||||
export const meta = {
|
||||
tags: ['drive'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read',
|
||||
kind: 'read:drive',
|
||||
|
||||
params: {
|
||||
limit: {
|
||||
@ -18,12 +19,10 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
type: {
|
||||
@ -40,35 +39,18 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
|
||||
const query = {
|
||||
'metadata.userId': user._id,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
} as any;
|
||||
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
query._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
query._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
}
|
||||
const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId)
|
||||
.andWhere('file.userId = :userId', { userId: user.id });
|
||||
|
||||
if (ps.type) {
|
||||
query.contentType = new RegExp(`^${ps.type.replace(/\*/g, '.+?')}$`);
|
||||
if (ps.type.endsWith('/*')) {
|
||||
query.andWhere('file.type like :type', { type: ps.type.replace('/*', '/') + '%' });
|
||||
} else {
|
||||
query.andWhere('file.type = :type', { type: ps.type });
|
||||
}
|
||||
}
|
||||
|
||||
const files = await DriveFile
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
const files = await query.take(ps.limit).getMany();
|
||||
|
||||
return await packMany(files, { self: true });
|
||||
return await DriveFiles.packMany(files, { detail: false, self: true });
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import Instance from '../../../../models/instance';
|
||||
import { Instances } from '../../../../models';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
|
||||
export const meta = {
|
||||
tags: ['federation'],
|
||||
@ -37,92 +38,55 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
let sort;
|
||||
const query = Instances.createQueryBuilder('instance');
|
||||
|
||||
if (ps.sort) {
|
||||
if (ps.sort == '+notes') {
|
||||
sort = {
|
||||
notesCount: -1
|
||||
};
|
||||
} else if (ps.sort == '-notes') {
|
||||
sort = {
|
||||
notesCount: 1
|
||||
};
|
||||
} else if (ps.sort == '+users') {
|
||||
sort = {
|
||||
usersCount: -1
|
||||
};
|
||||
} else if (ps.sort == '-users') {
|
||||
sort = {
|
||||
usersCount: 1
|
||||
};
|
||||
} else if (ps.sort == '+following') {
|
||||
sort = {
|
||||
followingCount: -1
|
||||
};
|
||||
} else if (ps.sort == '-following') {
|
||||
sort = {
|
||||
followingCount: 1
|
||||
};
|
||||
} else if (ps.sort == '+followers') {
|
||||
sort = {
|
||||
followersCount: -1
|
||||
};
|
||||
} else if (ps.sort == '-followers') {
|
||||
sort = {
|
||||
followersCount: 1
|
||||
};
|
||||
} else if (ps.sort == '+caughtAt') {
|
||||
sort = {
|
||||
caughtAt: -1
|
||||
};
|
||||
} else if (ps.sort == '-caughtAt') {
|
||||
sort = {
|
||||
caughtAt: 1
|
||||
};
|
||||
} else if (ps.sort == '+lastCommunicatedAt') {
|
||||
sort = {
|
||||
lastCommunicatedAt: -1
|
||||
};
|
||||
} else if (ps.sort == '-lastCommunicatedAt') {
|
||||
sort = {
|
||||
lastCommunicatedAt: 1
|
||||
};
|
||||
} else if (ps.sort == '+driveUsage') {
|
||||
sort = {
|
||||
driveUsage: -1
|
||||
};
|
||||
} else if (ps.sort == '-driveUsage') {
|
||||
sort = {
|
||||
driveUsage: 1
|
||||
};
|
||||
} else if (ps.sort == '+driveFiles') {
|
||||
sort = {
|
||||
driveFiles: -1
|
||||
};
|
||||
} else if (ps.sort == '-driveFiles') {
|
||||
sort = {
|
||||
driveFiles: 1
|
||||
};
|
||||
}
|
||||
} else {
|
||||
sort = {
|
||||
_id: -1
|
||||
};
|
||||
switch (ps.sort) {
|
||||
case '+notes': query.orderBy('instance.notesCount', 'DESC'); break;
|
||||
case '-notes': query.orderBy('instance.notesCount', 'ASC'); break;
|
||||
case '+usersCount': query.orderBy('instance.usersCount', 'DESC'); break;
|
||||
case '-usersCount': query.orderBy('instance.usersCount', 'ASC'); break;
|
||||
case '+followingCount': query.orderBy('instance.followingCount', 'DESC'); break;
|
||||
case '-followingCount': query.orderBy('instance.followingCount', 'ASC'); break;
|
||||
case '+followersCount': query.orderBy('instance.followersCount', 'DESC'); break;
|
||||
case '-followersCount': query.orderBy('instance.followersCount', 'ASC'); break;
|
||||
case '+caughtAt': query.orderBy('instance.caughtAt', 'DESC'); break;
|
||||
case '-caughtAt': query.orderBy('instance.caughtAt', 'ASC'); break;
|
||||
case '+lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'DESC'); break;
|
||||
case '-lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'ASC'); break;
|
||||
case '+driveUsage': query.orderBy('instance.driveUsage', 'DESC'); break;
|
||||
case '-driveUsage': query.orderBy('instance.driveUsage', 'ASC'); break;
|
||||
case '+driveFiles': query.orderBy('instance.driveFiles', 'DESC'); break;
|
||||
case '-driveFiles': query.orderBy('instance.driveFiles', 'ASC'); break;
|
||||
|
||||
default: query.orderBy('instance.id', 'DESC'); break;
|
||||
}
|
||||
|
||||
const q = {} as any;
|
||||
if (typeof ps.blocked === 'boolean') {
|
||||
const meta = await fetchMeta();
|
||||
if (ps.blocked) {
|
||||
query.andWhere('instance.host IN (:...blocks)', { blocks: meta.blockedHosts });
|
||||
} else {
|
||||
query.andWhere('instance.host NOT IN (:...blocks)', { blocks: meta.blockedHosts });
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof ps.blocked === 'boolean') q.isBlocked = ps.blocked;
|
||||
if (typeof ps.notResponding === 'boolean') q.isNotResponding = ps.notResponding;
|
||||
if (typeof ps.markedAsClosed === 'boolean') q.isMarkedAsClosed = ps.markedAsClosed;
|
||||
if (typeof ps.notResponding === 'boolean') {
|
||||
if (ps.notResponding) {
|
||||
query.andWhere('instance.isNotResponding = TRUE');
|
||||
} else {
|
||||
query.andWhere('instance.isNotResponding = FALSE');
|
||||
}
|
||||
}
|
||||
|
||||
const instances = await Instance
|
||||
.find(q, {
|
||||
limit: ps.limit,
|
||||
sort: sort,
|
||||
skip: ps.offset
|
||||
});
|
||||
if (typeof ps.markedAsClosed === 'boolean') {
|
||||
if (ps.markedAsClosed) {
|
||||
query.andWhere('instance.isMarkedAsClosed = TRUE');
|
||||
} else {
|
||||
query.andWhere('instance.isMarkedAsClosed = FALSE');
|
||||
}
|
||||
}
|
||||
|
||||
const instances = await query.take(ps.limit).skip(ps.offset).getMany();
|
||||
|
||||
return instances;
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import Instance from '../../../../models/instance';
|
||||
import { Instances } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['federation'],
|
||||
@ -15,7 +15,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const instance = await Instance
|
||||
const instance = await Instances
|
||||
.findOne({ host: ps.host });
|
||||
|
||||
return instance;
|
||||
|
@ -1,12 +1,11 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import * as ms from 'ms';
|
||||
import { pack } from '../../../../models/user';
|
||||
import Following from '../../../../models/following';
|
||||
import create from '../../../../services/following/create';
|
||||
import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { getUser } from '../../common/getters';
|
||||
import { Followings, Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -25,12 +24,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-write',
|
||||
kind: 'write:following',
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -75,7 +73,7 @@ export default define(meta, async (ps, user) => {
|
||||
const follower = user;
|
||||
|
||||
// 自分自身
|
||||
if (user._id.equals(ps.userId)) {
|
||||
if (user.id === ps.userId) {
|
||||
throw new ApiError(meta.errors.followeeIsYourself);
|
||||
}
|
||||
|
||||
@ -86,12 +84,12 @@ export default define(meta, async (ps, user) => {
|
||||
});
|
||||
|
||||
// Check if already following
|
||||
const exist = await Following.findOne({
|
||||
followerId: follower._id,
|
||||
followeeId: followee._id
|
||||
const exist = await Followings.findOne({
|
||||
followerId: follower.id,
|
||||
followeeId: followee.id
|
||||
});
|
||||
|
||||
if (exist !== null) {
|
||||
if (exist != null) {
|
||||
throw new ApiError(meta.errors.alreadyFollowing);
|
||||
}
|
||||
|
||||
@ -103,5 +101,5 @@ export default define(meta, async (ps, user) => {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return await pack(followee._id, user);
|
||||
return await Users.pack(followee.id, user);
|
||||
});
|
||||
|
@ -1,12 +1,11 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import * as ms from 'ms';
|
||||
import { pack } from '../../../../models/user';
|
||||
import Following from '../../../../models/following';
|
||||
import deleteFollowing from '../../../../services/following/delete';
|
||||
import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { getUser } from '../../common/getters';
|
||||
import { Followings, Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -25,12 +24,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-write',
|
||||
kind: 'write:following',
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -63,7 +61,7 @@ export default define(meta, async (ps, user) => {
|
||||
const follower = user;
|
||||
|
||||
// Check if the followee is yourself
|
||||
if (user._id.equals(ps.userId)) {
|
||||
if (user.id === ps.userId) {
|
||||
throw new ApiError(meta.errors.followeeIsYourself);
|
||||
}
|
||||
|
||||
@ -74,16 +72,16 @@ export default define(meta, async (ps, user) => {
|
||||
});
|
||||
|
||||
// Check not following
|
||||
const exist = await Following.findOne({
|
||||
followerId: follower._id,
|
||||
followeeId: followee._id
|
||||
const exist = await Followings.findOne({
|
||||
followerId: follower.id,
|
||||
followeeId: followee.id
|
||||
});
|
||||
|
||||
if (exist === null) {
|
||||
if (exist == null) {
|
||||
throw new ApiError(meta.errors.notFollowing);
|
||||
}
|
||||
|
||||
await deleteFollowing(follower, followee);
|
||||
|
||||
return await pack(followee._id, user);
|
||||
return await Users.pack(followee.id, user);
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import acceptFollowRequest from '../../../../../services/following/requests/accept';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
@ -15,12 +15,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-write',
|
||||
kind: 'write:following',
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
|
@ -1,10 +1,10 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import cancelFollowRequest from '../../../../../services/following/requests/cancel';
|
||||
import { pack } from '../../../../../models/user';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { getUser } from '../../../common/getters';
|
||||
import { Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -16,12 +16,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-write',
|
||||
kind: 'write:following',
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -58,5 +57,5 @@ export default define(meta, async (ps, user) => {
|
||||
throw e;
|
||||
}
|
||||
|
||||
return await pack(followee._id, user);
|
||||
return await Users.pack(followee.id, user);
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import FollowRequest, { pack } from '../../../../../models/follow-request';
|
||||
import define from '../../../define';
|
||||
import { FollowRequests } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -11,13 +11,13 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-read'
|
||||
kind: 'read:following'
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const reqs = await FollowRequest.find({
|
||||
followeeId: user._id
|
||||
const reqs = await FollowRequests.find({
|
||||
followeeId: user.id
|
||||
});
|
||||
|
||||
return await Promise.all(reqs.map(req => pack(req)));
|
||||
return await Promise.all(reqs.map(req => FollowRequests.pack(req)));
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import rejectFollowRequest from '../../../../../services/following/requests/reject';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
@ -15,12 +15,11 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'following-write',
|
||||
kind: 'write:following',
|
||||
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
|
@ -1,7 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import ReversiGame, { pack } from '../../../../../models/games/reversi/game';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import define from '../../../define';
|
||||
import { ReversiGames } from '../../../../../models';
|
||||
import { makePaginationQuery } from '../../../common/make-pagination-query';
|
||||
import { Brackets } from 'typeorm';
|
||||
|
||||
export const meta = {
|
||||
tags: ['games'],
|
||||
@ -14,12 +16,10 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
my: {
|
||||
@ -30,39 +30,20 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const q: any = ps.my ? {
|
||||
isStarted: true,
|
||||
$or: [{
|
||||
user1Id: user._id
|
||||
}, {
|
||||
user2Id: user._id
|
||||
}]
|
||||
} : {
|
||||
isStarted: true
|
||||
};
|
||||
const query = makePaginationQuery(ReversiGames.createQueryBuilder('game'), ps.sinceId, ps.untilId)
|
||||
.andWhere('game.isStarted = TRUE');
|
||||
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
q._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
q._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
if (ps.my) {
|
||||
query.andWhere(new Brackets(qb => { qb
|
||||
.where('game.user1Id = :userId', { userId: user.id })
|
||||
.orWhere('game.user2Id = :userId', { userId: user.id });
|
||||
}));
|
||||
}
|
||||
|
||||
// Fetch games
|
||||
const games = await ReversiGame.find(q, {
|
||||
sort: sort,
|
||||
limit: ps.limit
|
||||
});
|
||||
const games = await query.take(ps.limit).getMany();
|
||||
|
||||
return await Promise.all(games.map((g) => pack(g, user, {
|
||||
return await Promise.all(games.map((g) => ReversiGames.pack(g, user, {
|
||||
detail: false
|
||||
})));
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../../misc/cafy-id';
|
||||
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
|
||||
import { ID } from '../../../../../../misc/cafy-id';
|
||||
import Reversi from '../../../../../../games/reversi/core';
|
||||
import define from '../../../../define';
|
||||
import { ApiError } from '../../../../error';
|
||||
import { ReversiGames } from '../../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['games'],
|
||||
@ -11,7 +11,6 @@ export const meta = {
|
||||
params: {
|
||||
gameId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
},
|
||||
|
||||
@ -25,22 +24,23 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const game = await ReversiGame.findOne({ _id: ps.gameId });
|
||||
const game = await ReversiGames.findOne(ps.gameId);
|
||||
|
||||
if (game == null) {
|
||||
throw new ApiError(meta.errors.noSuchGame);
|
||||
}
|
||||
|
||||
const o = new Reversi(game.settings.map, {
|
||||
isLlotheo: game.settings.isLlotheo,
|
||||
canPutEverywhere: game.settings.canPutEverywhere,
|
||||
loopedBoard: game.settings.loopedBoard
|
||||
const o = new Reversi(game.map, {
|
||||
isLlotheo: game.isLlotheo,
|
||||
canPutEverywhere: game.canPutEverywhere,
|
||||
loopedBoard: game.loopedBoard
|
||||
});
|
||||
|
||||
for (const log of game.logs)
|
||||
for (const log of game.logs) {
|
||||
o.put(log.color, log.pos);
|
||||
}
|
||||
|
||||
const packed = await pack(game, user);
|
||||
const packed = await ReversiGames.pack(game, user);
|
||||
|
||||
return Object.assign({
|
||||
board: o.board,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../../misc/cafy-id';
|
||||
import ReversiGame, { pack } from '../../../../../../models/games/reversi/game';
|
||||
import { ID } from '../../../../../../misc/cafy-id';
|
||||
import { publishReversiGameStream } from '../../../../../../services/stream';
|
||||
import define from '../../../../define';
|
||||
import { ApiError } from '../../../../error';
|
||||
import { ReversiGames } from '../../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['games'],
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
gameId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '投了したい対局'
|
||||
}
|
||||
@ -46,7 +45,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const game = await ReversiGame.findOne({ _id: ps.gameId });
|
||||
const game = await ReversiGames.findOne(ps.gameId);
|
||||
|
||||
if (game == null) {
|
||||
throw new ApiError(meta.errors.noSuchGame);
|
||||
@ -56,26 +55,20 @@ export default define(meta, async (ps, user) => {
|
||||
throw new ApiError(meta.errors.alreadyEnded);
|
||||
}
|
||||
|
||||
if (!game.user1Id.equals(user._id) && !game.user2Id.equals(user._id)) {
|
||||
if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) {
|
||||
throw new ApiError(meta.errors.accessDenied);
|
||||
}
|
||||
|
||||
const winnerId = game.user1Id.equals(user._id) ? game.user2Id : game.user1Id;
|
||||
const winnerId = game.user1Id === user.id ? game.user2Id : game.user1Id;
|
||||
|
||||
await ReversiGame.update({
|
||||
_id: game._id
|
||||
}, {
|
||||
$set: {
|
||||
surrendered: user._id,
|
||||
isEnded: true,
|
||||
winnerId: winnerId
|
||||
}
|
||||
await ReversiGames.update(game.id, {
|
||||
surrendered: user.id,
|
||||
isEnded: true,
|
||||
winnerId: winnerId
|
||||
});
|
||||
|
||||
publishReversiGameStream(game._id, 'ended', {
|
||||
publishReversiGameStream(game.id, 'ended', {
|
||||
winnerId: winnerId,
|
||||
game: await pack(game._id, user)
|
||||
game: await ReversiGames.pack(game.id, user)
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Matching, { pack as packMatching } from '../../../../../models/games/reversi/matching';
|
||||
import define from '../../../define';
|
||||
import { ReversiMatchings } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['games'],
|
||||
@ -9,13 +9,9 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Find session
|
||||
const invitations = await Matching.find({
|
||||
childId: user._id
|
||||
}, {
|
||||
sort: {
|
||||
_id: -1
|
||||
}
|
||||
const invitations = await ReversiMatchings.find({
|
||||
childId: user.id
|
||||
});
|
||||
|
||||
return await Promise.all(invitations.map((i) => packMatching(i, user)));
|
||||
return await Promise.all(invitations.map((i) => ReversiMatchings.pack(i, user)));
|
||||
});
|
||||
|
@ -1,12 +1,14 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import Matching, { pack as packMatching } from '../../../../../models/games/reversi/matching';
|
||||
import ReversiGame, { pack as packGame } from '../../../../../models/games/reversi/game';
|
||||
import { ID } from '../../../../../misc/cafy-id';
|
||||
import { publishMainStream, publishReversiStream } from '../../../../../services/stream';
|
||||
import { eighteight } from '../../../../../games/reversi/maps';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { getUser } from '../../../common/getters';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
import { ReversiMatchings, ReversiGames } from '../../../../../models';
|
||||
import { ReversiGame } from '../../../../../models/entities/games/reversi/game';
|
||||
import { ReversiMatching } from '../../../../../models/entities/games/reversi/matching';
|
||||
|
||||
export const meta = {
|
||||
tags: ['games'],
|
||||
@ -16,7 +18,6 @@ export const meta = {
|
||||
params: {
|
||||
userId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のユーザーのID',
|
||||
'en-US': 'Target user ID'
|
||||
@ -41,50 +42,47 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Myself
|
||||
if (ps.userId.equals(user._id)) {
|
||||
if (ps.userId === user.id) {
|
||||
throw new ApiError(meta.errors.isYourself);
|
||||
}
|
||||
|
||||
// Find session
|
||||
const exist = await Matching.findOne({
|
||||
const exist = await ReversiMatchings.findOne({
|
||||
parentId: ps.userId,
|
||||
childId: user._id
|
||||
childId: user.id
|
||||
});
|
||||
|
||||
if (exist) {
|
||||
// Destroy session
|
||||
Matching.remove({
|
||||
_id: exist._id
|
||||
});
|
||||
ReversiMatchings.delete(exist.id);
|
||||
|
||||
// Create game
|
||||
const game = await ReversiGame.insert({
|
||||
const game = await ReversiGames.save({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
user1Id: exist.parentId,
|
||||
user2Id: user._id,
|
||||
user2Id: user.id,
|
||||
user1Accepted: false,
|
||||
user2Accepted: false,
|
||||
isStarted: false,
|
||||
isEnded: false,
|
||||
logs: [],
|
||||
settings: {
|
||||
map: eighteight.data,
|
||||
bw: 'random',
|
||||
isLlotheo: false
|
||||
}
|
||||
});
|
||||
map: eighteight.data,
|
||||
bw: 'random',
|
||||
isLlotheo: false
|
||||
} as ReversiGame);
|
||||
|
||||
publishReversiStream(exist.parentId, 'matched', await packGame(game, exist.parentId));
|
||||
publishReversiStream(exist.parentId, 'matched', await ReversiGames.pack(game, exist.parentId));
|
||||
|
||||
const other = await Matching.count({
|
||||
childId: user._id
|
||||
const other = await ReversiMatchings.count({
|
||||
childId: user.id
|
||||
});
|
||||
|
||||
if (other == 0) {
|
||||
publishMainStream(user._id, 'reversiNoInvites');
|
||||
publishMainStream(user.id, 'reversiNoInvites');
|
||||
}
|
||||
|
||||
return await packGame(game, user);
|
||||
return await ReversiGames.pack(game, user);
|
||||
} else {
|
||||
// Fetch child
|
||||
const child = await getUser(ps.userId).catch(e => {
|
||||
@ -93,21 +91,22 @@ export default define(meta, async (ps, user) => {
|
||||
});
|
||||
|
||||
// 以前のセッションはすべて削除しておく
|
||||
await Matching.remove({
|
||||
parentId: user._id
|
||||
await ReversiMatchings.delete({
|
||||
parentId: user.id
|
||||
});
|
||||
|
||||
// セッションを作成
|
||||
const matching = await Matching.insert({
|
||||
const matching = await ReversiMatchings.save({
|
||||
id: genId(),
|
||||
createdAt: new Date(),
|
||||
parentId: user._id,
|
||||
childId: child._id
|
||||
});
|
||||
parentId: user.id,
|
||||
childId: child.id
|
||||
} as ReversiMatching);
|
||||
|
||||
const packed = await packMatching(matching, child);
|
||||
publishReversiStream(child._id, 'invited', packed);
|
||||
publishMainStream(child._id, 'reversiInvited', packed);
|
||||
const packed = await ReversiMatchings.pack(matching, child);
|
||||
publishReversiStream(child.id, 'invited', packed);
|
||||
publishMainStream(child.id, 'reversiInvited', packed);
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Matching from '../../../../../../models/games/reversi/matching';
|
||||
import define from '../../../../define';
|
||||
import { ReversiMatchings } from '../../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['games'],
|
||||
@ -8,9 +8,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
await Matching.remove({
|
||||
parentId: user._id
|
||||
await ReversiMatchings.delete({
|
||||
parentId: user.id
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import define from '../../define';
|
||||
import Hashtag from '../../../../models/hashtag';
|
||||
import { Hashtags } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
tags: ['hashtags'],
|
||||
@ -54,40 +54,39 @@ export const meta = {
|
||||
},
|
||||
};
|
||||
|
||||
const sort: any = {
|
||||
'+mentionedUsers': { mentionedUsersCount: -1 },
|
||||
'-mentionedUsers': { mentionedUsersCount: 1 },
|
||||
'+mentionedLocalUsers': { mentionedLocalUsersCount: -1 },
|
||||
'-mentionedLocalUsers': { mentionedLocalUsersCount: 1 },
|
||||
'+mentionedRemoteUsers': { mentionedRemoteUsersCount: -1 },
|
||||
'-mentionedRemoteUsers': { mentionedRemoteUsersCount: 1 },
|
||||
'+attachedUsers': { attachedUsersCount: -1 },
|
||||
'-attachedUsers': { attachedUsersCount: 1 },
|
||||
'+attachedLocalUsers': { attachedLocalUsersCount: -1 },
|
||||
'-attachedLocalUsers': { attachedLocalUsersCount: 1 },
|
||||
'+attachedRemoteUsers': { attachedRemoteUsersCount: -1 },
|
||||
'-attachedRemoteUsers': { attachedRemoteUsersCount: 1 },
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const q = {} as any;
|
||||
if (ps.attachedToUserOnly) q.attachedUsersCount = { $ne: 0 };
|
||||
if (ps.attachedToLocalUserOnly) q.attachedLocalUsersCount = { $ne: 0 };
|
||||
if (ps.attachedToRemoteUserOnly) q.attachedRemoteUsersCount = { $ne: 0 };
|
||||
const tags = await Hashtag
|
||||
.find(q, {
|
||||
limit: ps.limit,
|
||||
sort: sort[ps.sort],
|
||||
fields: {
|
||||
tag: true,
|
||||
mentionedUsersCount: true,
|
||||
mentionedLocalUsersCount: true,
|
||||
mentionedRemoteUsersCount: true,
|
||||
attachedUsersCount: true,
|
||||
attachedLocalUsersCount: true,
|
||||
attachedRemoteUsersCount: true
|
||||
}
|
||||
});
|
||||
const query = Hashtags.createQueryBuilder('tag');
|
||||
|
||||
if (ps.attachedToUserOnly) query.andWhere('tag.attachedUsersCount != 0');
|
||||
if (ps.attachedToLocalUserOnly) query.andWhere('tag.attachedLocalUsersCount != 0');
|
||||
if (ps.attachedToRemoteUserOnly) query.andWhere('tag.attachedRemoteUsersCount != 0');
|
||||
|
||||
switch (ps.sort) {
|
||||
case '+mentionedUsers': query.orderBy('tag.mentionedUsersCount', 'DESC'); break;
|
||||
case '-mentionedUsers': query.orderBy('tag.mentionedUsersCount', 'ASC'); break;
|
||||
case '+mentionedLocalUsers': query.orderBy('tag.mentionedLocalUsersCount', 'DESC'); break;
|
||||
case '-mentionedLocalUsers': query.orderBy('tag.mentionedLocalUsersCount', 'ASC'); break;
|
||||
case '+mentionedRemoteUsers': query.orderBy('tag.mentionedRemoteUsersCount', 'DESC'); break;
|
||||
case '-mentionedRemoteUsers': query.orderBy('tag.mentionedRemoteUsersCount', 'ASC'); break;
|
||||
case '+attachedUsers': query.orderBy('tag.attachedUsersCount', 'DESC'); break;
|
||||
case '-attachedUsers': query.orderBy('tag.attachedUsersCount', 'ASC'); break;
|
||||
case '+attachedLocalUsers': query.orderBy('tag.attachedLocalUsersCount', 'DESC'); break;
|
||||
case '-attachedLocalUsers': query.orderBy('tag.attachedLocalUsersCount', 'ASC'); break;
|
||||
case '+attachedRemoteUsers': query.orderBy('tag.attachedRemoteUsersCount', 'DESC'); break;
|
||||
case '-attachedRemoteUsers': query.orderBy('tag.attachedRemoteUsersCount', 'ASC'); break;
|
||||
}
|
||||
|
||||
query.select([
|
||||
'tag.name',
|
||||
'tag.mentionedUsersCount',
|
||||
'tag.mentionedLocalUsersCount',
|
||||
'tag.mentionedRemoteUsersCount',
|
||||
'tag.attachedUsersCount',
|
||||
'tag.attachedLocalUsersCount',
|
||||
'tag.attachedRemoteUsersCount',
|
||||
]);
|
||||
|
||||
const tags = await query.take(ps.limit).getMany();
|
||||
|
||||
return tags;
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import Hashtag from '../../../../models/hashtag';
|
||||
import define from '../../define';
|
||||
import * as escapeRegexp from 'escape-regexp';
|
||||
import { Hashtags } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -46,16 +45,12 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
const hashtags = await Hashtag
|
||||
.find({
|
||||
tag: new RegExp('^' + escapeRegexp(ps.query.toLowerCase()))
|
||||
}, {
|
||||
sort: {
|
||||
count: -1
|
||||
},
|
||||
limit: ps.limit,
|
||||
skip: ps.offset
|
||||
});
|
||||
const hashtags = await Hashtags.createQueryBuilder('tag')
|
||||
.where('tag.name like :q', { q: ps.query.toLowerCase() + '%' })
|
||||
.orderBy('tag.count', 'DESC')
|
||||
.take(ps.limit)
|
||||
.skip(ps.offset)
|
||||
.getMany();
|
||||
|
||||
return hashtags.map(tag => tag.tag);
|
||||
return hashtags.map(tag => tag.name);
|
||||
});
|
||||
|
@ -1,17 +1,19 @@
|
||||
import Note from '../../../../models/note';
|
||||
import { erase } from '../../../../prelude/array';
|
||||
import define from '../../define';
|
||||
import fetchMeta from '../../../../misc/fetch-meta';
|
||||
import { Notes } from '../../../../models';
|
||||
import { Note } from '../../../../models/entities/note';
|
||||
|
||||
/*
|
||||
トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
|
||||
ユニーク投稿数とはそのハッシュタグと投稿ユーザーのペアのカウントで、例えば同じユーザーが複数回同じハッシュタグを投稿してもそのハッシュタグのユニーク投稿数は1とカウントされる
|
||||
|
||||
..が理想だけどPostgreSQLでどうするのか分からないので単に「直近Aの内に投稿されたユニーク投稿数が多いハッシュタグ」で妥協する
|
||||
*/
|
||||
|
||||
const rangeA = 1000 * 60 * 30; // 30分
|
||||
const rangeB = 1000 * 60 * 120; // 2時間
|
||||
const coefficient = 1.25; // 「n倍」の部分
|
||||
const requiredUsers = 3; // 最低何人がそのタグを投稿している必要があるか
|
||||
//const rangeB = 1000 * 60 * 120; // 2時間
|
||||
//const coefficient = 1.25; // 「n倍」の部分
|
||||
//const requiredUsers = 3; // 最低何人がそのタグを投稿している必要があるか
|
||||
|
||||
const max = 5;
|
||||
|
||||
@ -23,92 +25,47 @@ export const meta = {
|
||||
|
||||
export default define(meta, async () => {
|
||||
const instance = await fetchMeta();
|
||||
const hidedTags = instance.hidedTags.map(t => t.toLowerCase());
|
||||
const hiddenTags = instance.hiddenTags.map(t => t.toLowerCase());
|
||||
|
||||
//#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計
|
||||
const data = await Note.aggregate([{
|
||||
$match: {
|
||||
createdAt: {
|
||||
$gt: new Date(Date.now() - rangeA)
|
||||
},
|
||||
tagsLower: {
|
||||
$exists: true,
|
||||
$ne: []
|
||||
}
|
||||
}
|
||||
}, {
|
||||
$unwind: '$tagsLower'
|
||||
}, {
|
||||
$group: {
|
||||
_id: { tag: '$tagsLower', userId: '$userId' }
|
||||
}
|
||||
}]) as {
|
||||
_id: {
|
||||
tag: string;
|
||||
userId: any;
|
||||
}
|
||||
}[];
|
||||
//#endregion
|
||||
const tagNotes = await Notes.createQueryBuilder('note')
|
||||
.where(`note.createdAt > :date`, { date: new Date(Date.now() - rangeA) })
|
||||
.andWhere(`note.tags != '{}'`)
|
||||
.select(['note.tags', 'note.userId'])
|
||||
.getMany();
|
||||
|
||||
if (data.length == 0) {
|
||||
if (tagNotes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const tags: {
|
||||
name: string;
|
||||
count: number;
|
||||
users: Note['userId'][];
|
||||
}[] = [];
|
||||
|
||||
// カウント
|
||||
for (const x of data.map(x => x._id).filter(x => !hidedTags.includes(x.tag))) {
|
||||
const i = tags.findIndex(tag => tag.name == x.tag);
|
||||
if (i != -1) {
|
||||
tags[i].count++;
|
||||
} else {
|
||||
tags.push({
|
||||
name: x.tag,
|
||||
count: 1
|
||||
});
|
||||
for (const note of tagNotes) {
|
||||
for (const tag of note.tags) {
|
||||
if (hiddenTags.includes(tag)) continue;
|
||||
|
||||
const x = tags.find(x => x.name === tag);
|
||||
if (x) {
|
||||
if (!x.users.includes(note.userId)) {
|
||||
x.users.push(note.userId);
|
||||
}
|
||||
} else {
|
||||
tags.push({
|
||||
name: tag,
|
||||
users: [note.userId]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最低要求投稿者数を下回るならカットする
|
||||
const limitedTags = tags.filter(tag => tag.count >= requiredUsers);
|
||||
|
||||
//#region 2. 1で取得したそれぞれのタグについて、「直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上」かどうかを判定する
|
||||
const hotsPromises = limitedTags.map(async tag => {
|
||||
const passedCount = (await Note.distinct('userId', {
|
||||
tagsLower: tag.name,
|
||||
createdAt: {
|
||||
$lt: new Date(Date.now() - rangeA),
|
||||
$gt: new Date(Date.now() - rangeB)
|
||||
}
|
||||
}) as any).length;
|
||||
|
||||
if (tag.count >= (passedCount * coefficient)) {
|
||||
return tag;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
|
||||
// タグを人気順に並べ替え
|
||||
let hots = erase(null, await Promise.all(hotsPromises))
|
||||
.sort((a, b) => b.count - a.count)
|
||||
const hots = tags
|
||||
.sort((a, b) => b.users.length - a.users.length)
|
||||
.map(tag => tag.name)
|
||||
.slice(0, max);
|
||||
|
||||
//#region 3. もし上記の方法でのトレンド抽出の結果、求められているタグ数に達しなければ「ただ単に現在投稿数が多いハッシュタグ」に切り替える
|
||||
if (hots.length < max) {
|
||||
hots = hots.concat(tags
|
||||
.filter(tag => hots.indexOf(tag.name) == -1)
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.map(tag => tag.name)
|
||||
.slice(0, max - hots.length));
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 2(または3)で話題と判定されたタグそれぞれについて過去の投稿数グラフを取得する
|
||||
const countPromises: Promise<any[]>[] = [];
|
||||
|
||||
@ -118,23 +75,25 @@ export default define(meta, async () => {
|
||||
const interval = 1000 * 60 * 10;
|
||||
|
||||
for (let i = 0; i < range; i++) {
|
||||
countPromises.push(Promise.all(hots.map(tag => Note.distinct('userId', {
|
||||
tagsLower: tag,
|
||||
createdAt: {
|
||||
$lt: new Date(Date.now() - (interval * i)),
|
||||
$gt: new Date(Date.now() - (interval * (i + 1)))
|
||||
}
|
||||
}))));
|
||||
countPromises.push(Promise.all(hots.map(tag => Notes.createQueryBuilder('note')
|
||||
.select('count(distinct note.userId)')
|
||||
.where(':tag = ANY(note.tags)', { tag: tag })
|
||||
.andWhere('note.createdAt < :lt', { lt: new Date(Date.now() - (interval * i)) })
|
||||
.andWhere('note.createdAt > :gt', { gt: new Date(Date.now() - (interval * (i + 1))) })
|
||||
.getRawOne()
|
||||
.then(x => parseInt(x.count, 10))
|
||||
)));
|
||||
}
|
||||
|
||||
const countsLog = await Promise.all(countPromises);
|
||||
|
||||
const totalCounts: any = await Promise.all(hots.map(tag => Note.distinct('userId', {
|
||||
tagsLower: tag,
|
||||
createdAt: {
|
||||
$gt: new Date(Date.now() - (interval * range))
|
||||
}
|
||||
})));
|
||||
const totalCounts: any = await Promise.all(hots.map(tag => Notes.createQueryBuilder('note')
|
||||
.select('count(distinct note.userId)')
|
||||
.where(':tag = ANY(note.tags)', { tag: tag })
|
||||
.andWhere('note.createdAt > :gt', { gt: new Date(Date.now() - (interval * range)) })
|
||||
.getRawOne()
|
||||
.then(x => parseInt(x.count, 10))
|
||||
));
|
||||
//#endregion
|
||||
|
||||
const stats = hots.map((tag, i) => ({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import User, { pack } from '../../../../models/user';
|
||||
import define from '../../define';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: false,
|
||||
@ -54,39 +54,32 @@ export const meta = {
|
||||
},
|
||||
};
|
||||
|
||||
const sort: any = {
|
||||
'+follower': { followersCount: -1 },
|
||||
'-follower': { followersCount: 1 },
|
||||
'+createdAt': { createdAt: -1 },
|
||||
'-createdAt': { createdAt: 1 },
|
||||
'+updatedAt': { updatedAt: -1 },
|
||||
'-updatedAt': { updatedAt: 1 },
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const q = {
|
||||
tags: ps.tag,
|
||||
$and: []
|
||||
} as any;
|
||||
const query = Users.createQueryBuilder('user')
|
||||
.where(':tag = ANY(user.tags)', { tag: ps.tag });
|
||||
|
||||
// state
|
||||
q.$and.push(
|
||||
ps.state == 'alive' ? { updatedAt: { $gt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 5)) } } :
|
||||
{}
|
||||
);
|
||||
const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5));
|
||||
|
||||
// origin
|
||||
q.$and.push(
|
||||
ps.origin == 'local' ? { host: null } :
|
||||
ps.origin == 'remote' ? { host: { $ne: null } } :
|
||||
{}
|
||||
);
|
||||
if (ps.state === 'alive') {
|
||||
query.andWhere('user.updatedAt > :date', { date: recent });
|
||||
}
|
||||
|
||||
const users = await User
|
||||
.find(q, {
|
||||
limit: ps.limit,
|
||||
sort: sort[ps.sort],
|
||||
});
|
||||
if (ps.origin === 'local') {
|
||||
query.andWhere('user.host IS NULL');
|
||||
} else if (ps.origin === 'remote') {
|
||||
query.andWhere('user.host IS NOT NULL');
|
||||
}
|
||||
|
||||
return await Promise.all(users.map(user => pack(user, me, { detail: true })));
|
||||
switch (ps.sort) {
|
||||
case '+follower': query.orderBy('user.followersCount', 'DESC'); break;
|
||||
case '-follower': query.orderBy('user.followersCount', 'ASC'); break;
|
||||
case '+createdAt': query.orderBy('user.createdAt', 'DESC'); break;
|
||||
case '-createdAt': query.orderBy('user.createdAt', 'ASC'); break;
|
||||
case '+updatedAt': query.orderBy('user.updatedAt', 'DESC'); break;
|
||||
case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break;
|
||||
}
|
||||
|
||||
const users = await query.take(ps.limit).getMany();
|
||||
|
||||
return await Users.packMany(users, me, { detail: true });
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { pack } from '../../../models/user';
|
||||
import define from '../define';
|
||||
import { Users } from '../../../models';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
@ -22,7 +22,7 @@ export const meta = {
|
||||
export default define(meta, async (ps, user, app) => {
|
||||
const isSecure = user != null && app == null;
|
||||
|
||||
return await pack(user, user, {
|
||||
return await Users.pack(user, user, {
|
||||
detail: true,
|
||||
includeHasUnreadNotes: true,
|
||||
includeSecrets: isSecure
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import * as speakeasy from 'speakeasy';
|
||||
import User from '../../../../../models/user';
|
||||
import define from '../../../define';
|
||||
import { Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -32,12 +32,8 @@ export default define(meta, async (ps, user) => {
|
||||
throw new Error('not verified');
|
||||
}
|
||||
|
||||
await User.update(user._id, {
|
||||
$set: {
|
||||
'twoFactorSecret': user.twoFactorTempSecret,
|
||||
'twoFactorEnabled': true
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
twoFactorSecret: user.twoFactorTempSecret,
|
||||
twoFactorEnabled: true
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -2,9 +2,9 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import * as speakeasy from 'speakeasy';
|
||||
import * as QRCode from 'qrcode';
|
||||
import User from '../../../../../models/user';
|
||||
import config from '../../../../../config';
|
||||
import define from '../../../define';
|
||||
import { Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -31,10 +31,8 @@ export default define(meta, async (ps, user) => {
|
||||
length: 32
|
||||
});
|
||||
|
||||
await User.update(user._id, {
|
||||
$set: {
|
||||
twoFactorTempSecret: secret.base32
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
twoFactorTempSecret: secret.base32
|
||||
});
|
||||
|
||||
// Get the data URL of the authenticator URL
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import User from '../../../../../models/user';
|
||||
import define from '../../../define';
|
||||
import { Users } from '../../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -23,11 +23,9 @@ export default define(meta, async (ps, user) => {
|
||||
throw new Error('incorrect password');
|
||||
}
|
||||
|
||||
await User.update(user._id, {
|
||||
$set: {
|
||||
'twoFactorSecret': null,
|
||||
'twoFactorEnabled': false
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
twoFactorSecret: null,
|
||||
twoFactorEnabled: false
|
||||
});
|
||||
|
||||
return;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import $ from 'cafy';
|
||||
import AccessToken from '../../../../models/access-token';
|
||||
import { pack } from '../../../../models/app';
|
||||
import define from '../../define';
|
||||
import { AccessTokens, Apps } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -28,18 +27,18 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
// Get tokens
|
||||
const tokens = await AccessToken
|
||||
.find({
|
||||
userId: user._id
|
||||
}, {
|
||||
limit: ps.limit,
|
||||
skip: ps.offset,
|
||||
sort: {
|
||||
_id: ps.sort == 'asc' ? 1 : -1
|
||||
}
|
||||
});
|
||||
const tokens = await AccessTokens.find({
|
||||
where: {
|
||||
userId: user.id
|
||||
},
|
||||
take: ps.limit,
|
||||
skip: ps.offset,
|
||||
order: {
|
||||
id: ps.sort == 'asc' ? 1 : -1
|
||||
}
|
||||
});
|
||||
|
||||
return await Promise.all(tokens.map(token => pack(token.appId, user, {
|
||||
return await Promise.all(tokens.map(token => Apps.pack(token.appId, user, {
|
||||
detail: true
|
||||
})));
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import User from '../../../../models/user';
|
||||
import define from '../../define';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -31,11 +31,7 @@ export default define(meta, async (ps, user) => {
|
||||
const salt = await bcrypt.genSalt(8);
|
||||
const hash = await bcrypt.hash(ps.newPassword, salt);
|
||||
|
||||
await User.update(user._id, {
|
||||
$set: {
|
||||
'password': hash
|
||||
}
|
||||
await Users.update(user.id, {
|
||||
password: hash
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,23 +0,0 @@
|
||||
import User from '../../../../models/user';
|
||||
import define from '../../define';
|
||||
|
||||
export const meta = {
|
||||
tags: ['account', 'following'],
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'account-write',
|
||||
|
||||
params: {
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
await User.update({ _id: user._id }, {
|
||||
$set: {
|
||||
pendingReceivedFollowRequestsCount: 0
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
});
|
@ -1,10 +1,7 @@
|
||||
import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import User from '../../../../models/user';
|
||||
import define from '../../define';
|
||||
import { createDeleteNotesJob, createDeleteDriveFilesJob } from '../../../../queue';
|
||||
import Message from '../../../../models/messaging-message';
|
||||
import Signin from '../../../../models/signin';
|
||||
import { Users } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true,
|
||||
@ -26,27 +23,5 @@ export default define(meta, async (ps, user) => {
|
||||
throw new Error('incorrect password');
|
||||
}
|
||||
|
||||
await User.update({ _id: user._id }, {
|
||||
$set: {
|
||||
isDeleted: true,
|
||||
name: null,
|
||||
description: null,
|
||||
pinnedNoteIds: [],
|
||||
password: null,
|
||||
email: null,
|
||||
twitter: null,
|
||||
github: null,
|
||||
discord: null,
|
||||
profile: {},
|
||||
fields: [],
|
||||
clientSettings: {},
|
||||
}
|
||||
});
|
||||
|
||||
Message.remove({ userId: user._id });
|
||||
Signin.remove({ userId: user._id });
|
||||
createDeleteNotesJob(user);
|
||||
createDeleteDriveFilesJob(user);
|
||||
|
||||
return;
|
||||
await Users.delete(user.id);
|
||||
});
|
||||
|
@ -13,6 +13,4 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
createExportBlockingJob(user);
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -13,6 +13,4 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
createExportFollowingJob(user);
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -13,6 +13,4 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
createExportMuteJob(user);
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -13,6 +13,4 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
createExportNotesJob(user);
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -13,6 +13,4 @@ export const meta = {
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
createExportUserListsJob(user);
|
||||
|
||||
return;
|
||||
});
|
||||
|
@ -1,7 +1,8 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import Favorite, { packMany } from '../../../../models/favorite';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { NoteFavorites } from '../../../../models';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -23,42 +24,22 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const query = {
|
||||
userId: user._id
|
||||
} as any;
|
||||
const query = makePaginationQuery(NoteFavorites.createQueryBuilder('favorite'), ps.sinceId, ps.untilId)
|
||||
.andWhere(`favorite.userId = :meId`, { meId: user.id })
|
||||
.leftJoinAndSelect('favorite.note', 'note');
|
||||
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
const favorites = await query
|
||||
.take(ps.limit)
|
||||
.getMany();
|
||||
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
query._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
query._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
}
|
||||
|
||||
// Get favorites
|
||||
const favorites = await Favorite
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
|
||||
return await packMany(favorites, user);
|
||||
return await NoteFavorites.packMany(favorites, user);
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { createImportFollowingJob } from '../../../../queue';
|
||||
import ms = require('ms');
|
||||
import DriveFile from '../../../../models/drive-file';
|
||||
import { ApiError } from '../../error';
|
||||
import { DriveFiles } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
secure: true,
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
fileId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
}
|
||||
},
|
||||
|
||||
@ -49,16 +48,12 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const file = await DriveFile.findOne({
|
||||
_id: ps.fileId
|
||||
});
|
||||
const file = await DriveFiles.findOne(ps.fileId);
|
||||
|
||||
if (file == null) throw new ApiError(meta.errors.noSuchFile);
|
||||
//if (!file.contentType.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
|
||||
if (file.length > 50000) throw new ApiError(meta.errors.tooBigFile);
|
||||
if (file.length === 0) throw new ApiError(meta.errors.emptyFile);
|
||||
//if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
|
||||
if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile);
|
||||
if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
|
||||
|
||||
createImportFollowingJob(user, file._id);
|
||||
|
||||
return;
|
||||
createImportFollowingJob(user, file.id);
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import define from '../../define';
|
||||
import { createImportUserListsJob } from '../../../../queue';
|
||||
import ms = require('ms');
|
||||
import DriveFile from '../../../../models/drive-file';
|
||||
import { ApiError } from '../../error';
|
||||
import { DriveFiles } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
secure: true,
|
||||
@ -17,7 +17,6 @@ export const meta = {
|
||||
params: {
|
||||
fileId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
}
|
||||
},
|
||||
|
||||
@ -49,16 +48,12 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const file = await DriveFile.findOne({
|
||||
_id: ps.fileId
|
||||
});
|
||||
const file = await DriveFiles.findOne(ps.fileId);
|
||||
|
||||
if (file == null) throw new ApiError(meta.errors.noSuchFile);
|
||||
//if (!file.contentType.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
|
||||
if (file.length > 30000) throw new ApiError(meta.errors.tooBigFile);
|
||||
if (file.length === 0) throw new ApiError(meta.errors.emptyFile);
|
||||
//if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType);
|
||||
if (file.size > 30000) throw new ApiError(meta.errors.tooBigFile);
|
||||
if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
|
||||
|
||||
createImportUserListsJob(user, file._id);
|
||||
|
||||
return;
|
||||
createImportUserListsJob(user, file.id);
|
||||
});
|
||||
|
@ -1,11 +1,9 @@
|
||||
import $ from 'cafy';
|
||||
import ID, { transform } from '../../../../misc/cafy-id';
|
||||
import Notification from '../../../../models/notification';
|
||||
import { packMany } from '../../../../models/notification';
|
||||
import { getFriendIds } from '../../common/get-friends';
|
||||
import read from '../../common/read-notification';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import { readNotification } from '../../common/read-notification';
|
||||
import define from '../../define';
|
||||
import { getHideUserIds } from '../../common/get-hide-users';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||
import { Notifications, Followings, Mutings } from '../../../../models';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -17,7 +15,7 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'account-read',
|
||||
kind: 'read:notifications',
|
||||
|
||||
params: {
|
||||
limit: {
|
||||
@ -27,12 +25,10 @@ export const meta = {
|
||||
|
||||
sinceId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
untilId: {
|
||||
validator: $.optional.type(ID),
|
||||
transform: transform,
|
||||
},
|
||||
|
||||
following: {
|
||||
@ -46,12 +42,12 @@ export const meta = {
|
||||
},
|
||||
|
||||
includeTypes: {
|
||||
validator: $.optional.arr($.str.or(['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'poll_vote', 'receiveFollowRequest'])),
|
||||
validator: $.optional.arr($.str.or(['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest'])),
|
||||
default: [] as string[]
|
||||
},
|
||||
|
||||
excludeTypes: {
|
||||
validator: $.optional.arr($.str.or(['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'poll_vote', 'receiveFollowRequest'])),
|
||||
validator: $.optional.arr($.str.or(['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest'])),
|
||||
default: [] as string[]
|
||||
}
|
||||
},
|
||||
@ -65,63 +61,38 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const hideUserIds = await getHideUserIds(user);
|
||||
const followingQuery = Followings.createQueryBuilder('following')
|
||||
.select('following.followeeId')
|
||||
.where('following.followerId = :followerId', { followerId: user.id });
|
||||
|
||||
const query = {
|
||||
notifieeId: user._id,
|
||||
$and: [{
|
||||
notifierId: {
|
||||
$nin: hideUserIds
|
||||
}
|
||||
}]
|
||||
} as any;
|
||||
const mutingQuery = Mutings.createQueryBuilder('muting')
|
||||
.select('muting.muteeId')
|
||||
.where('muting.muterId = :muterId', { muterId: user.id });
|
||||
|
||||
const sort = {
|
||||
_id: -1
|
||||
};
|
||||
const query = makePaginationQuery(Notifications.createQueryBuilder('notification'), ps.sinceId, ps.untilId)
|
||||
.andWhere(`notification.notifieeId = :meId`, { meId: user.id })
|
||||
.leftJoinAndSelect('notification.notifier', 'notifier');
|
||||
|
||||
query.andWhere(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`);
|
||||
query.setParameters(mutingQuery.getParameters());
|
||||
|
||||
if (ps.following) {
|
||||
// ID list of the user itself and other users who the user follows
|
||||
const followingIds = await getFriendIds(user._id);
|
||||
|
||||
query.$and.push({
|
||||
notifierId: {
|
||||
$in: followingIds
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (ps.sinceId) {
|
||||
sort._id = 1;
|
||||
query._id = {
|
||||
$gt: ps.sinceId
|
||||
};
|
||||
} else if (ps.untilId) {
|
||||
query._id = {
|
||||
$lt: ps.untilId
|
||||
};
|
||||
query.andWhere(`((notification.notifierId IN (${ followingQuery.getQuery() })) OR (notification.notifierId = :meId))`, { meId: user.id });
|
||||
query.setParameters(followingQuery.getParameters());
|
||||
}
|
||||
|
||||
if (ps.includeTypes.length > 0) {
|
||||
query.type = {
|
||||
$in: ps.includeTypes
|
||||
};
|
||||
query.andWhere(`notification.type IN (:...includeTypes)`, { includeTypes: ps.includeTypes });
|
||||
} else if (ps.excludeTypes.length > 0) {
|
||||
query.type = {
|
||||
$nin: ps.excludeTypes
|
||||
};
|
||||
query.andWhere(`notification.type NOT IN (:...excludeTypes)`, { excludeTypes: ps.excludeTypes });
|
||||
}
|
||||
|
||||
const notifications = await Notification
|
||||
.find(query, {
|
||||
limit: ps.limit,
|
||||
sort: sort
|
||||
});
|
||||
const notifications = await query.take(ps.limit).getMany();
|
||||
|
||||
// Mark all as read
|
||||
if (notifications.length > 0 && ps.markAsRead) {
|
||||
read(user._id, notifications);
|
||||
readNotification(user.id, notifications.map(x => x.id));
|
||||
}
|
||||
|
||||
return await packMany(notifications);
|
||||
return await Notifications.packMany(notifications);
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user