summaryrefslogtreecommitdiff
path: root/src/server/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/api')
-rw-r--r--src/server/api/endpoints/admin/update-meta.ts10
-rw-r--r--src/server/api/endpoints/hashtags/show.ts3
-rw-r--r--src/server/api/endpoints/hashtags/trend.ts3
-rw-r--r--src/server/api/endpoints/hashtags/users.ts3
-rw-r--r--src/server/api/endpoints/i/update.ts8
-rw-r--r--src/server/api/endpoints/meta.ts1
-rw-r--r--src/server/api/endpoints/notes/search-by-tag.ts5
-rw-r--r--src/server/api/private/signup.ts24
-rw-r--r--src/server/api/service/discord.ts6
-rw-r--r--src/server/api/stream/channels/hashtag.ts3
-rw-r--r--src/server/api/stream/channels/home-timeline.ts4
-rw-r--r--src/server/api/stream/channels/hybrid-timeline.ts4
-rw-r--r--src/server/api/stream/channels/local-timeline.ts2
-rw-r--r--src/server/api/stream/channels/main.ts4
-rw-r--r--src/server/api/stream/index.ts12
15 files changed, 50 insertions, 42 deletions
diff --git a/src/server/api/endpoints/admin/update-meta.ts b/src/server/api/endpoints/admin/update-meta.ts
index d3addaba8a..163d7a2519 100644
--- a/src/server/api/endpoints/admin/update-meta.ts
+++ b/src/server/api/endpoints/admin/update-meta.ts
@@ -438,7 +438,11 @@ export const meta = {
objectStorageSetPublicRead: {
validator: $.optional.bool
- }
+ },
+
+ objectStorageS3ForcePathStyle: {
+ validator: $.optional.bool
+ },
}
};
@@ -713,6 +717,10 @@ export default define(meta, async (ps, me) => {
set.objectStorageSetPublicRead = ps.objectStorageSetPublicRead;
}
+ if (ps.objectStorageS3ForcePathStyle !== undefined) {
+ set.objectStorageS3ForcePathStyle = ps.objectStorageS3ForcePathStyle;
+ }
+
await getConnection().transaction(async transactionalEntityManager => {
const meta = await transactionalEntityManager.findOne(Meta, {
order: {
diff --git a/src/server/api/endpoints/hashtags/show.ts b/src/server/api/endpoints/hashtags/show.ts
index 9462342aac..49aa36e05a 100644
--- a/src/server/api/endpoints/hashtags/show.ts
+++ b/src/server/api/endpoints/hashtags/show.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
import define from '../../define';
import { ApiError } from '../../error';
import { Hashtags } from '../../../../models';
+import { normalizeForSearch } from '../../../../misc/normalize-for-search';
export const meta = {
desc: {
@@ -38,7 +39,7 @@ export const meta = {
};
export default define(meta, async (ps, user) => {
- const hashtag = await Hashtags.findOne({ name: ps.tag.toLowerCase() });
+ const hashtag = await Hashtags.findOne({ name: normalizeForSearch(ps.tag) });
if (hashtag == null) {
throw new ApiError(meta.errors.noSuchHashtag);
}
diff --git a/src/server/api/endpoints/hashtags/trend.ts b/src/server/api/endpoints/hashtags/trend.ts
index cfa97d1475..3b5dd3c0c1 100644
--- a/src/server/api/endpoints/hashtags/trend.ts
+++ b/src/server/api/endpoints/hashtags/trend.ts
@@ -4,6 +4,7 @@ import { fetchMeta } from '../../../../misc/fetch-meta';
import { Notes } from '../../../../models';
import { Note } from '../../../../models/entities/note';
import { safeForSql } from '../../../../misc/safe-for-sql';
+import { normalizeForSearch } from '../../../../misc/normalize-for-search';
/*
トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
@@ -54,7 +55,7 @@ export const meta = {
export default define(meta, async () => {
const instance = await fetchMeta(true);
- const hiddenTags = instance.hiddenTags.map(t => t.toLowerCase());
+ const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
const now = new Date(); // 5分単位で丸めた現在日時
now.setMinutes(Math.round(now.getMinutes() / 5) * 5, 0, 0);
diff --git a/src/server/api/endpoints/hashtags/users.ts b/src/server/api/endpoints/hashtags/users.ts
index 532a490d9e..d2f5998681 100644
--- a/src/server/api/endpoints/hashtags/users.ts
+++ b/src/server/api/endpoints/hashtags/users.ts
@@ -1,6 +1,7 @@
import $ from 'cafy';
import define from '../../define';
import { Users } from '../../../../models';
+import { normalizeForSearch } from '../../../../misc/normalize-for-search';
export const meta = {
requireCredential: false as const,
@@ -59,7 +60,7 @@ export const meta = {
export default define(meta, async (ps, me) => {
const query = Users.createQueryBuilder('user')
- .where(':tag = ANY(user.tags)', { tag: ps.tag.toLowerCase() });
+ .where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) });
const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5));
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 8ac427cd5b..e4c0e8cec9 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -15,6 +15,7 @@ import { User } from '../../../../models/entities/user';
import { UserProfile } from '../../../../models/entities/user-profile';
import { ensure } from '../../../../prelude/ensure';
import { notificationTypes } from '../../../../types';
+import { normalizeForSearch } from '../../../../misc/normalize-for-search';
export const meta = {
desc: {
@@ -135,6 +136,10 @@ export const meta = {
validator: $.optional.bool,
},
+ receiveAnnouncementEmail: {
+ validator: $.optional.bool,
+ },
+
alwaysMarkNsfw: {
validator: $.optional.bool,
desc: {
@@ -219,6 +224,7 @@ export default define(meta, async (ps, user, token) => {
if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
+ if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
if (typeof ps.alwaysMarkNsfw === 'boolean') profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw;
if (ps.avatarId) {
@@ -281,7 +287,7 @@ export default define(meta, async (ps, user, token) => {
if (newDescription != null) {
const tokens = parse(newDescription);
emojis = emojis.concat(extractEmojis(tokens!));
- tags = extractHashtags(tokens!).map(tag => tag.toLowerCase()).splice(0, 32);
+ tags = extractHashtags(tokens!).map(tag => normalizeForSearch(tag)).splice(0, 32);
}
updates.emojis = emojis;
diff --git a/src/server/api/endpoints/meta.ts b/src/server/api/endpoints/meta.ts
index 81053b26a3..3b647e21cd 100644
--- a/src/server/api/endpoints/meta.ts
+++ b/src/server/api/endpoints/meta.ts
@@ -205,6 +205,7 @@ export default define(meta, async (ps, me) => {
response.objectStorageUseSSL = instance.objectStorageUseSSL;
response.objectStorageUseProxy = instance.objectStorageUseProxy;
response.objectStorageSetPublicRead = instance.objectStorageSetPublicRead;
+ response.objectStorageS3ForcePathStyle = instance.objectStorageS3ForcePathStyle;
}
}
diff --git a/src/server/api/endpoints/notes/search-by-tag.ts b/src/server/api/endpoints/notes/search-by-tag.ts
index 446beb32dd..e0f7f4d62c 100644
--- a/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/src/server/api/endpoints/notes/search-by-tag.ts
@@ -7,6 +7,7 @@ import { generateMutedUserQuery } from '../../common/generate-muted-user-query';
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';
export const meta = {
desc: {
@@ -101,7 +102,7 @@ export default define(meta, async (ps, me) => {
if (ps.tag) {
if (!safeForSql(ps.tag)) return;
- query.andWhere(`'{"${ps.tag.toLowerCase()}"}' <@ note.tags`);
+ query.andWhere(`'{"${normalizeForSearch(ps.tag)}"}' <@ note.tags`);
} else {
let i = 0;
query.andWhere(new Brackets(qb => {
@@ -109,7 +110,7 @@ export default define(meta, async (ps, me) => {
qb.orWhere(new Brackets(qb => {
for (const tag of tags) {
if (!safeForSql(tag)) return;
- qb.andWhere(`'{"${tag.toLowerCase()}"}' <@ note.tags`);
+ qb.andWhere(`'{"${normalizeForSearch(ps.tag)}"}' <@ note.tags`);
i++;
}
}));
diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts
index 6dc252ac45..3d467a0e68 100644
--- a/src/server/api/private/signup.ts
+++ b/src/server/api/private/signup.ts
@@ -1,7 +1,6 @@
import * as Koa from 'koa';
import { fetchMeta } from '../../../misc/fetch-meta';
-import { verify } from 'hcaptcha';
-import * as recaptcha from 'recaptcha-promise';
+import { verifyHcaptcha, verifyRecaptcha } from '../../../misc/captcha';
import { Users, RegistrationTickets } from '../../../models';
import { signup } from '../common/signup';
@@ -14,26 +13,15 @@ export default async (ctx: Koa.Context) => {
// ただしテスト時はこの機構は障害となるため無効にする
if (process.env.NODE_ENV !== 'test') {
if (instance.enableHcaptcha && instance.hcaptchaSecretKey) {
- const success = await verify(instance.hcaptchaSecretKey, body['hcaptcha-response']).then(
- ({ success }) => success,
- () => false,
- );
-
- if (!success) {
- ctx.throw(400, 'hcaptcha-failed');
- }
+ await verifyHcaptcha(instance.hcaptchaSecretKey, body['hcaptcha-response']).catch(e => {
+ ctx.throw(400, e);
+ });
}
if (instance.enableRecaptcha && instance.recaptchaSecretKey) {
- recaptcha.init({
- secret_key: instance.recaptchaSecretKey
+ await verifyRecaptcha(instance.recaptchaSecretKey, body['g-recaptcha-response']).catch(e => {
+ ctx.throw(400, e);
});
-
- const success = await recaptcha(body['g-recaptcha-response']);
-
- if (!success) {
- ctx.throw(400, 'recaptcha-failed');
- }
}
}
diff --git a/src/server/api/service/discord.ts b/src/server/api/service/discord.ts
index a5ad18d99c..007458066d 100644
--- a/src/server/api/service/discord.ts
+++ b/src/server/api/service/discord.ts
@@ -70,7 +70,7 @@ async function getOAuth2() {
return new OAuth2(
meta.discordClientId!,
meta.discordClientSecret!,
- 'https://discordapp.com/',
+ 'https://discord.com/',
'api/oauth2/authorize',
'api/oauth2/token');
} else {
@@ -174,7 +174,7 @@ router.get('/dc/cb', async ctx => {
}
}));
- const { id, username, discriminator } = await getJson('https://discordapp.com/api/users/@me', '*/*', 10 * 1000, {
+ const { id, username, discriminator } = await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, {
'Authorization': `Bearer ${accessToken}`,
});
@@ -245,7 +245,7 @@ router.get('/dc/cb', async ctx => {
}
}));
- const { id, username, discriminator } = await getJson('https://discordapp.com/api/users/@me', '*/*', 10 * 1000, {
+ const { id, username, discriminator } = await getJson('https://discord.com/api/users/@me', '*/*', 10 * 1000, {
'Authorization': `Bearer ${accessToken}`,
});
if (!id || !username || !discriminator) {
diff --git a/src/server/api/stream/channels/hashtag.ts b/src/server/api/stream/channels/hashtag.ts
index 32d8111f72..41447039d5 100644
--- a/src/server/api/stream/channels/hashtag.ts
+++ b/src/server/api/stream/channels/hashtag.ts
@@ -3,6 +3,7 @@ import { isMutedUserRelated } from '../../../../misc/is-muted-user-related';
import Channel from '../channel';
import { Notes } from '../../../../models';
import { PackedNote } from '../../../../models/repositories/note';
+import { normalizeForSearch } from '../../../../misc/normalize-for-search';
export default class extends Channel {
public readonly chName = 'hashtag';
@@ -23,7 +24,7 @@ export default class extends Channel {
@autobind
private async onNote(note: PackedNote) {
const noteTags = note.tags ? note.tags.map((t: string) => t.toLowerCase()) : [];
- const matched = this.q.some(tags => tags.every(tag => noteTags.includes(tag.toLowerCase())));
+ const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag))));
if (!matched) return;
// Renoteなら再pack
diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts
index 15fe7fa6f0..6cfa6eae7b 100644
--- a/src/server/api/stream/channels/home-timeline.ts
+++ b/src/server/api/stream/channels/home-timeline.ts
@@ -19,10 +19,10 @@ export default class extends Channel {
@autobind
private async onNote(note: PackedNote) {
if (note.channelId) {
- if (!this.followingChannels.includes(note.channelId)) return;
+ if (!this.followingChannels.has(note.channelId)) return;
} else {
// その投稿のユーザーをフォローしていなかったら弾く
- if ((this.user!.id !== note.userId) && !this.following.includes(note.userId)) return;
+ if ((this.user!.id !== note.userId) && !this.following.has(note.userId)) return;
}
if (['followers', 'specified'].includes(note.visibility)) {
diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts
index 4dc5f01a32..a9e577cacb 100644
--- a/src/server/api/stream/channels/hybrid-timeline.ts
+++ b/src/server/api/stream/channels/hybrid-timeline.ts
@@ -29,9 +29,9 @@ export default class extends Channel {
// フォローしているチャンネルの投稿 の場合だけ
if (!(
(note.channelId == null && this.user!.id === note.userId) ||
- (note.channelId == null && this.following.includes(note.userId)) ||
+ (note.channelId == null && this.following.has(note.userId)) ||
(note.channelId == null && ((note.user as PackedUser).host == null && note.visibility === 'public')) ||
- (note.channelId != null && this.followingChannels.includes(note.channelId))
+ (note.channelId != null && this.followingChannels.has(note.channelId))
)) return;
if (['followers', 'specified'].includes(note.visibility)) {
diff --git a/src/server/api/stream/channels/local-timeline.ts b/src/server/api/stream/channels/local-timeline.ts
index baeae86603..a3a5e491fc 100644
--- a/src/server/api/stream/channels/local-timeline.ts
+++ b/src/server/api/stream/channels/local-timeline.ts
@@ -27,7 +27,7 @@ export default class extends Channel {
private async onNote(note: PackedNote) {
if ((note.user as PackedUser).host !== null) return;
if (note.visibility !== 'public') return;
- if (note.channelId != null && !this.followingChannels.includes(note.channelId)) return;
+ if (note.channelId != null && !this.followingChannels.has(note.channelId)) return;
// リプライなら再pack
if (note.replyId != null) {
diff --git a/src/server/api/stream/channels/main.ts b/src/server/api/stream/channels/main.ts
index 22e664baca..b69c2ec355 100644
--- a/src/server/api/stream/channels/main.ts
+++ b/src/server/api/stream/channels/main.ts
@@ -16,7 +16,7 @@ export default class extends Channel {
switch (type) {
case 'notification': {
- if (this.muting.includes(body.userId)) return;
+ if (this.muting.has(body.userId)) return;
if (body.note && body.note.isHidden) {
body.note = await Notes.pack(body.note.id, this.user, {
detail: true
@@ -25,7 +25,7 @@ export default class extends Channel {
break;
}
case 'mention': {
- if (this.muting.includes(body.userId)) return;
+ if (this.muting.has(body.userId)) return;
if (body.isHidden) {
body = await Notes.pack(body.id, this.user, {
detail: true
diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts
index 36e08ec05f..5b975d07db 100644
--- a/src/server/api/stream/index.ts
+++ b/src/server/api/stream/index.ts
@@ -19,9 +19,9 @@ import { UserProfile } from '../../../models/entities/user-profile';
export default class Connection {
public user?: User;
public userProfile?: UserProfile;
- public following: User['id'][] = [];
- public muting: User['id'][] = [];
- public followingChannels: ChannelModel['id'][] = [];
+ public following: Set<User['id']> = new Set();
+ public muting: Set<User['id']> = new Set();
+ public followingChannels: Set<ChannelModel['id']> = new Set();
public token?: AccessToken;
private wsConnection: websocket.connection;
public subscriber: EventEmitter;
@@ -267,7 +267,7 @@ export default class Connection {
select: ['followeeId']
});
- this.following = followings.map(x => x.followeeId);
+ this.following = new Set<string>(followings.map(x => x.followeeId));
}
@autobind
@@ -279,7 +279,7 @@ export default class Connection {
select: ['muteeId']
});
- this.muting = mutings.map(x => x.muteeId);
+ this.muting = new Set<string>(mutings.map(x => x.muteeId));
}
@autobind
@@ -291,7 +291,7 @@ export default class Connection {
select: ['followeeId']
});
- this.followingChannels = followings.map(x => x.followeeId);
+ this.followingChannels = new Set<string>(followings.map(x => x.followeeId));
}
@autobind