diff options
Diffstat (limited to 'src/server/api/endpoints/notes')
| -rw-r--r-- | src/server/api/endpoints/notes/children.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/create.ts | 30 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/featured.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/global-timeline.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/hybrid-timeline.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/local-timeline.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/mentions.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/polls/vote.ts | 23 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/reactions/create.ts | 9 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/renotes.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/replies.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/search-by-tag.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/search.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/timeline.ts | 2 | ||||
| -rw-r--r-- | src/server/api/endpoints/notes/translate.ts | 82 |
15 files changed, 161 insertions, 5 deletions
diff --git a/src/server/api/endpoints/notes/children.ts b/src/server/api/endpoints/notes/children.ts index adbe714bf4..f4d2958810 100644 --- a/src/server/api/endpoints/notes/children.ts +++ b/src/server/api/endpoints/notes/children.ts @@ -6,6 +6,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query' import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; import { Brackets } from 'typeorm'; import { Notes } from '../../../../models'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -63,6 +64,7 @@ export default define(meta, async (ps, user) => { generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); + if (user) generateBlockedUserQuery(query, user); const notes = await query.take(ps.limit!).getMany(); diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts index ddb5c953ec..9c055683f7 100644 --- a/src/server/api/endpoints/notes/create.ts +++ b/src/server/api/endpoints/notes/create.ts @@ -7,7 +7,7 @@ import { fetchMeta } from '@/misc/fetch-meta'; import { ApiError } from '../../error'; import { ID } from '@/misc/cafy-id'; import { User } from '../../../../models/entities/user'; -import { Users, DriveFiles, Notes, Channels } from '../../../../models'; +import { Users, DriveFiles, Notes, Channels, Blockings } from '../../../../models'; import { DriveFile } from '../../../../models/entities/drive-file'; import { Note } from '../../../../models/entities/note'; import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits'; @@ -171,6 +171,12 @@ export const meta = { code: 'NO_SUCH_CHANNEL', id: 'b1653923-5453-4edc-b786-7c4f39bb0bbb' }, + + youHaveBeenBlocked: { + message: 'You have been blocked by this user.', + code: 'YOU_HAVE_BEEN_BLOCKED', + id: 'b390d7e1-8a5e-46ed-b625-06271cafd3d3' + }, } }; @@ -202,6 +208,17 @@ export default define(meta, async (ps, user) => { } else if (renote.renoteId && !renote.text && !renote.fileIds) { throw new ApiError(meta.errors.cannotReRenote); } + + // Check blocking + if (renote.userId !== user.id) { + const block = await Blockings.findOne({ + blockerId: renote.userId, + blockeeId: user.id, + }); + if (block) { + throw new ApiError(meta.errors.youHaveBeenBlocked); + } + } } let reply: Note | undefined; @@ -217,6 +234,17 @@ export default define(meta, async (ps, user) => { if (reply.renoteId && !reply.text && !reply.fileIds) { throw new ApiError(meta.errors.cannotReplyToPureRenote); } + + // Check blocking + if (reply.userId !== user.id) { + const block = await Blockings.findOne({ + blockerId: reply.userId, + blockeeId: user.id, + }); + if (block) { + throw new ApiError(meta.errors.youHaveBeenBlocked); + } + } } if (ps.poll) { diff --git a/src/server/api/endpoints/notes/featured.ts b/src/server/api/endpoints/notes/featured.ts index 5b4367f7a3..44c0fb23ab 100644 --- a/src/server/api/endpoints/notes/featured.ts +++ b/src/server/api/endpoints/notes/featured.ts @@ -2,6 +2,7 @@ import $ from 'cafy'; import define from '../../define'; import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; import { Notes } from '../../../../models'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -48,6 +49,7 @@ export default define(meta, async (ps, user) => { .leftJoinAndSelect('renote.user', 'renoteUser'); if (user) generateMutedUserQuery(query, user); + if (user) generateBlockedUserQuery(query, user); let notes = await query .orderBy('note.score', 'DESC') diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts index 741c5985a3..96bfde5aa2 100644 --- a/src/server/api/endpoints/notes/global-timeline.ts +++ b/src/server/api/endpoints/notes/global-timeline.ts @@ -9,6 +9,7 @@ import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; import { activeUsersChart } from '../../../../services/chart'; import { generateRepliesQuery } from '../../common/generate-replies-query'; import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -81,6 +82,7 @@ export default define(meta, async (ps, user) => { generateRepliesQuery(query, user); if (user) generateMutedUserQuery(query, user); if (user) generateMutedNoteQuery(query, user); + if (user) generateBlockedUserQuery(query, user); if (ps.withFiles) { query.andWhere('note.fileIds != \'{}\''); diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts index 23fc5a6068..91a36fd0cc 100644 --- a/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -12,6 +12,7 @@ import { activeUsersChart } from '../../../../services/chart'; import { generateRepliesQuery } from '../../common/generate-replies-query'; import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; import { generateChannelQuery } from '../../common/generate-channel-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -108,6 +109,7 @@ export default define(meta, async (ps, user) => { generateVisibilityQuery(query, user); generateMutedUserQuery(query, user); generateMutedNoteQuery(query, user); + generateBlockedUserQuery(query, user); if (ps.includeMyRenotes === false) { query.andWhere(new Brackets(qb => { diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts index 523fbee9a8..4f481b599d 100644 --- a/src/server/api/endpoints/notes/local-timeline.ts +++ b/src/server/api/endpoints/notes/local-timeline.ts @@ -12,6 +12,7 @@ import { Brackets } from 'typeorm'; import { generateRepliesQuery } from '../../common/generate-replies-query'; import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; import { generateChannelQuery } from '../../common/generate-channel-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -94,6 +95,7 @@ export default define(meta, async (ps, user) => { generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); if (user) generateMutedNoteQuery(query, user); + if (user) generateBlockedUserQuery(query, user); if (ps.withFiles) { query.andWhere('note.fileIds != \'{}\''); diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts index e1e916c586..6a2358228b 100644 --- a/src/server/api/endpoints/notes/mentions.ts +++ b/src/server/api/endpoints/notes/mentions.ts @@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query' import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; import { makePaginationQuery } from '../../common/make-pagination-query'; import { Brackets } from 'typeorm'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -66,6 +67,7 @@ export default define(meta, async (ps, user) => { generateVisibilityQuery(query, user); generateMutedUserQuery(query, user); + generateBlockedUserQuery(query, user); if (ps.visibility) { query.andWhere('note.visibility = :visibility', { visibility: ps.visibility }); diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts index b40e187fd8..6f2892960f 100644 --- a/src/server/api/endpoints/notes/polls/vote.ts +++ b/src/server/api/endpoints/notes/polls/vote.ts @@ -9,7 +9,7 @@ import { deliver } from '../../../../../queue'; import { renderActivity } from '../../../../../remote/activitypub/renderer'; import renderVote from '../../../../../remote/activitypub/renderer/vote'; import { deliverQuestionUpdate } from '../../../../../services/note/polls/update'; -import { PollVotes, NoteWatchings, Users, Polls } from '../../../../../models'; +import { PollVotes, NoteWatchings, Users, Polls, Blockings } from '../../../../../models'; import { Not } from 'typeorm'; import { IRemoteUser } from '../../../../../models/entities/user'; import { genId } from '@/misc/gen-id'; @@ -61,6 +61,12 @@ export const meta = { code: 'ALREADY_EXPIRED', id: '1022a357-b085-4054-9083-8f8de358337e' }, + + youHaveBeenBlocked: { + message: 'You cannot vote this poll because you have been blocked by this user.', + code: 'YOU_HAVE_BEEN_BLOCKED', + id: '85a5377e-b1e9-4617-b0b9-5bea73331e49' + }, } }; @@ -77,6 +83,17 @@ export default define(meta, async (ps, user) => { throw new ApiError(meta.errors.noPoll); } + // Check blocking + if (note.userId !== user.id) { + const block = await Blockings.findOne({ + blockerId: note.userId, + blockeeId: user.id, + }); + if (block) { + throw new ApiError(meta.errors.youHaveBeenBlocked); + } + } + const poll = await Polls.findOneOrFail({ noteId: note.id }); if (poll.expiresAt && poll.expiresAt < createdAt) { @@ -103,13 +120,13 @@ export default define(meta, async (ps, user) => { } // Create vote - const vote = await PollVotes.save({ + const vote = await PollVotes.insert({ id: genId(), createdAt, noteId: note.id, userId: user.id, choice: ps.choice - }); + }).then(x => PollVotes.findOneOrFail(x.identifiers[0])); // Increment votes count const index = ps.choice + 1; // In SQL, array index is 1 based diff --git a/src/server/api/endpoints/notes/reactions/create.ts b/src/server/api/endpoints/notes/reactions/create.ts index e8533fee56..3243332c50 100644 --- a/src/server/api/endpoints/notes/reactions/create.ts +++ b/src/server/api/endpoints/notes/reactions/create.ts @@ -33,7 +33,13 @@ export const meta = { message: 'You are already reacting to that note.', code: 'ALREADY_REACTED', id: '71efcf98-86d6-4e2b-b2ad-9d032369366b' - } + }, + + youHaveBeenBlocked: { + message: 'You cannot react this note because you have been blocked by this user.', + code: 'YOU_HAVE_BEEN_BLOCKED', + id: '20ef5475-9f38-4e4c-bd33-de6d979498ec' + }, } }; @@ -44,6 +50,7 @@ export default define(meta, async (ps, user) => { }); await createReaction(user, note, ps.reaction).catch(e => { if (e.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') throw new ApiError(meta.errors.alreadyReacted); + if (e.id === 'e70412a4-7197-4726-8e74-f3e0deb92aa7') throw new ApiError(meta.errors.youHaveBeenBlocked); throw e; }); return; diff --git a/src/server/api/endpoints/notes/renotes.ts b/src/server/api/endpoints/notes/renotes.ts index d384b7962f..5e3b3ccbc6 100644 --- a/src/server/api/endpoints/notes/renotes.ts +++ b/src/server/api/endpoints/notes/renotes.ts @@ -7,6 +7,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query' import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; import { makePaginationQuery } from '../../common/make-pagination-query'; import { Notes } from '../../../../models'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -67,6 +68,7 @@ export default define(meta, async (ps, user) => { generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); + if (user) generateBlockedUserQuery(query, user); const renotes = await query.take(ps.limit!).getMany(); diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts index 79a983e75f..7960078c8e 100644 --- a/src/server/api/endpoints/notes/replies.ts +++ b/src/server/api/endpoints/notes/replies.ts @@ -5,6 +5,7 @@ import { Notes } from '../../../../models'; import { makePaginationQuery } from '../../common/make-pagination-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -52,6 +53,7 @@ export default define(meta, async (ps, user) => { generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); + if (user) generateBlockedUserQuery(query, user); const timeline = await query.take(ps.limit!).getMany(); diff --git a/src/server/api/endpoints/notes/search-by-tag.ts b/src/server/api/endpoints/notes/search-by-tag.ts index bbada17613..39d99babac 100644 --- a/src/server/api/endpoints/notes/search-by-tag.ts +++ b/src/server/api/endpoints/notes/search-by-tag.ts @@ -8,6 +8,7 @@ import { generateVisibilityQuery } from '../../common/generate-visibility-query' import { Brackets } from 'typeorm'; import { safeForSql } from '@/misc/safe-for-sql'; import { normalizeForSearch } from '@/misc/normalize-for-search'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes', 'hashtags'], @@ -75,6 +76,7 @@ export default define(meta, async (ps, me) => { generateVisibilityQuery(query, me); if (me) generateMutedUserQuery(query, me); + if (me) generateBlockedUserQuery(query, me); try { if (ps.tag) { diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts index dc411283a2..0e0eaa06a8 100644 --- a/src/server/api/endpoints/notes/search.ts +++ b/src/server/api/endpoints/notes/search.ts @@ -8,6 +8,7 @@ import config from '@/config'; import { makePaginationQuery } from '../../common/make-pagination-query'; import { generateVisibilityQuery } from '../../common/generate-visibility-query'; import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -82,6 +83,7 @@ export default define(meta, async (ps, me) => { generateVisibilityQuery(query, me); if (me) generateMutedUserQuery(query, me); + if (me) generateBlockedUserQuery(query, me); const notes = await query.take(ps.limit!).getMany(); diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts index 687869a63d..5f03400919 100644 --- a/src/server/api/endpoints/notes/timeline.ts +++ b/src/server/api/endpoints/notes/timeline.ts @@ -10,6 +10,7 @@ import { Brackets } from 'typeorm'; import { generateRepliesQuery } from '../../common/generate-replies-query'; import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; import { generateChannelQuery } from '../../common/generate-channel-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query'; export const meta = { tags: ['notes'], @@ -100,6 +101,7 @@ export default define(meta, async (ps, user) => { generateVisibilityQuery(query, user); generateMutedUserQuery(query, user); generateMutedNoteQuery(query, user); + generateBlockedUserQuery(query, user); if (ps.includeMyRenotes === false) { query.andWhere(new Brackets(qb => { diff --git a/src/server/api/endpoints/notes/translate.ts b/src/server/api/endpoints/notes/translate.ts new file mode 100644 index 0000000000..67c02432c8 --- /dev/null +++ b/src/server/api/endpoints/notes/translate.ts @@ -0,0 +1,82 @@ +import $ from 'cafy'; +import { ID } from '@/misc/cafy-id'; +import define from '../../define'; +import { getNote } from '../../common/getters'; +import { ApiError } from '../../error'; +import fetch from 'node-fetch'; +import config from '@/config'; +import { getAgentByUrl } from '@/misc/fetch'; +import { URLSearchParams } from 'url'; +import { fetchMeta } from '@/misc/fetch-meta'; + +export const meta = { + tags: ['notes'], + + requireCredential: false as const, + + params: { + noteId: { + validator: $.type(ID), + }, + targetLang: { + validator: $.str, + }, + }, + + res: { + type: 'object' as const, + optional: false as const, nullable: false as const, + }, + + errors: { + noSuchNote: { + message: 'No such note.', + code: 'NO_SUCH_NOTE', + id: 'bea9b03f-36e0-49c5-a4db-627a029f8971' + } + } +}; + +export default define(meta, async (ps, user) => { + const note = await getNote(ps.noteId).catch(e => { + if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + throw e; + }); + + if (note.text == null) { + return 204; + } + + const instance = await fetchMeta(); + + if (instance.deeplAuthKey == null) { + return 204; // TODO: 良い感じのエラー返す + } + + let targetLang = ps.targetLang; + if (targetLang.includes('-')) targetLang = targetLang.split('-')[0]; + + const params = new URLSearchParams(); + params.append('auth_key', instance.deeplAuthKey); + params.append('text', note.text); + params.append('target_lang', targetLang); + + const res = await fetch('https://api-free.deepl.com/v2/translate', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'User-Agent': config.userAgent, + Accept: 'application/json, */*' + }, + body: params, + timeout: 10000, + agent: getAgentByUrl, + }); + + const json = await res.json(); + + return { + sourceLang: json.translations[0].detected_source_language, + text: json.translations[0].text + }; +}); |