diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2022-04-11 23:13:18 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2022-04-11 23:13:18 +0900 |
| commit | 33c22b5f3efa4110c9b517c224c9fdfba7e6c64b (patch) | |
| tree | c029245de51666da7ab15cf5ae08f05b4ee32622 /packages/backend/src | |
| parent | Merge branch 'develop' (diff) | |
| parent | 12.110.0 (diff) | |
| download | misskey-33c22b5f3efa4110c9b517c224c9fdfba7e6c64b.tar.gz misskey-33c22b5f3efa4110c9b517c224c9fdfba7e6c64b.tar.bz2 misskey-33c22b5f3efa4110c9b517c224c9fdfba7e6c64b.zip | |
Merge branch 'develop'
Diffstat (limited to 'packages/backend/src')
34 files changed, 151 insertions, 96 deletions
diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index f7638a53d0..eb5fc2e186 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -209,7 +209,11 @@ export const db = new DataSource({ }); export async function initDb() { - await db.connect(); + if (db.isInitialized) { + // nop + } else { + await db.connect(); + } } export async function resetDb() { diff --git a/packages/backend/src/misc/captcha.ts b/packages/backend/src/misc/captcha.ts index 293cbdcd37..9a87a4a3c8 100644 --- a/packages/backend/src/misc/captcha.ts +++ b/packages/backend/src/misc/captcha.ts @@ -42,7 +42,8 @@ async function getCaptchaResponse(url: string, secret: string, response: string) headers: { 'User-Agent': config.userAgent, }, - timeout: 10 * 1000, + // TODO + //timeout: 10 * 1000, agent: getAgentByUrl, }).catch(e => { throw `${e.message || e}`; diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts index 47a5cd471a..4b1013c9f5 100644 --- a/packages/backend/src/misc/fetch.ts +++ b/packages/backend/src/misc/fetch.ts @@ -120,9 +120,9 @@ export const httpsAgent = config.proxy */ export function getAgentByUrl(url: URL, bypassProxy = false) { if (bypassProxy || (config.proxyBypassHosts || []).includes(url.hostname)) { - return url.protocol == 'http:' ? _http : _https; + return url.protocol === 'http:' ? _http : _https; } else { - return url.protocol == 'http:' ? httpAgent : httpsAgent; + return url.protocol === 'http:' ? httpAgent : httpsAgent; } } diff --git a/packages/backend/src/misc/get-note-summary.ts b/packages/backend/src/misc/get-note-summary.ts index 93783873da..3f35ccee82 100644 --- a/packages/backend/src/misc/get-note-summary.ts +++ b/packages/backend/src/misc/get-note-summary.ts @@ -23,7 +23,7 @@ export const getNoteSummary = (note: Packed<'Note'>): string => { } // ファイルが添付されているとき - if ((note.files || []).length != 0) { + if ((note.files || []).length !== 0) { summary += ` (📎${note.files!.length})`; } diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index a570400b7b..2d40290e4c 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -1,4 +1,5 @@ import httpSignature from 'http-signature'; +import { v4 as uuid } from 'uuid'; import config from '@/config/index.js'; import { envOption } from '../env.js'; @@ -16,7 +17,7 @@ import { getJobInfo } from './get-job-info.js'; import { systemQueue, dbQueue, deliverQueue, inboxQueue, objectStorageQueue, endedPollNotificationQueue, webhookDeliverQueue } from './queues.js'; import { ThinUser } from './types.js'; import { IActivity } from '@/remote/activitypub/type.js'; -import { Webhook } from '@/models/entities/webhook.js'; +import { Webhook, webhookEventTypes } from '@/models/entities/webhook.js'; function renderError(e: Error): any { return { @@ -262,12 +263,16 @@ export function createCleanRemoteFilesJob() { }); } -export function webhookDeliver(webhook: Webhook, content: unknown) { +export function webhookDeliver(webhook: Webhook, type: typeof webhookEventTypes[number], content: unknown) { const data = { + type, content, webhookId: webhook.id, + userId: webhook.userId, to: webhook.url, secret: webhook.secret, + createdAt: Date.now(), + eventId: uuid(), }; return webhookDeliverQueue.add(data, { diff --git a/packages/backend/src/queue/processors/webhook-deliver.ts b/packages/backend/src/queue/processors/webhook-deliver.ts index a4d39d86e4..d49206f68f 100644 --- a/packages/backend/src/queue/processors/webhook-deliver.ts +++ b/packages/backend/src/queue/processors/webhook-deliver.ts @@ -8,13 +8,9 @@ import config from '@/config/index.js'; const logger = new Logger('webhook'); -let latest: string | null = null; - export default async (job: Bull.Job<WebhookDeliverJobData>) => { try { - if (latest !== (latest = JSON.stringify(job.data.content, null, 2))) { - logger.debug(`delivering ${latest}`); - } + logger.debug(`delivering ${job.data.webhookId}`); const res = await getResponse({ url: job.data.to, @@ -25,7 +21,14 @@ export default async (job: Bull.Job<WebhookDeliverJobData>) => { 'X-Misskey-Hook-Id': job.data.webhookId, 'X-Misskey-Hook-Secret': job.data.secret, }, - body: JSON.stringify(job.data.content), + body: JSON.stringify({ + hookId: job.data.webhookId, + userId: job.data.userId, + eventId: job.data.eventId, + createdAt: job.data.createdAt, + type: job.data.type, + body: job.data.content, + }), }); Webhooks.update({ id: job.data.webhookId }, { diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index 8aeacf4625..6c0b9d9bf6 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -48,10 +48,14 @@ export type EndedPollNotificationJobData = { }; export type WebhookDeliverJobData = { + type: string; content: unknown; webhookId: Webhook['id']; + userId: User['id']; to: string; secret: string; + createdAt: number; + eventId: string; }; export type ThinUser = { diff --git a/packages/backend/src/remote/activitypub/ap-request.ts b/packages/backend/src/remote/activitypub/ap-request.ts index 96bfec3b11..8b55f22477 100644 --- a/packages/backend/src/remote/activitypub/ap-request.ts +++ b/packages/backend/src/remote/activitypub/ap-request.ts @@ -95,7 +95,7 @@ function genSigningString(request: Request, includeHeaders: string[]) { function lcObjectKey(src: Record<string, string>) { const dst: Record<string, string> = {}; - for (const key of Object.keys(src).filter(x => x != '__proto__' && typeof src[x] === 'string')) dst[key.toLowerCase()] = src[key]; + for (const key of Object.keys(src).filter(x => x !== '__proto__' && typeof src[x] === 'string')) dst[key.toLowerCase()] = src[key]; return dst; } diff --git a/packages/backend/src/remote/activitypub/deliver-manager.ts b/packages/backend/src/remote/activitypub/deliver-manager.ts index f95f64f77c..4c1999e4cb 100644 --- a/packages/backend/src/remote/activitypub/deliver-manager.ts +++ b/packages/backend/src/remote/activitypub/deliver-manager.ts @@ -109,15 +109,15 @@ export default class DeliverManager { } } - this.recipes.filter((recipe): recipe is IDirectRecipe => { + this.recipes.filter((recipe): recipe is IDirectRecipe => // followers recipes have already been processed isDirect(recipe) // check that shared inbox has not been added yet && !(recipe.to.sharedInbox && inboxes.has(recipe.to.sharedInbox)) // check that they actually have an inbox - && recipe.to.inbox - }) - .forEach(recipe => inboxes.add(recipe.to.inbox)); + && recipe.to.inbox != null, + ) + .forEach(recipe => inboxes.add(recipe.to.inbox!)); // deliver for (const inbox of inboxes) { diff --git a/packages/backend/src/remote/activitypub/kernel/read.ts b/packages/backend/src/remote/activitypub/kernel/read.ts index 7f1519ac2e..f7b0bcecdf 100644 --- a/packages/backend/src/remote/activitypub/kernel/read.ts +++ b/packages/backend/src/remote/activitypub/kernel/read.ts @@ -18,7 +18,7 @@ export const performReadActivity = async (actor: CacheableRemoteUser, activity: return `skip: message not found`; } - if (actor.id != message.recipientId) { + if (actor.id !== message.recipientId) { return `skip: actor is not a message recipient`; } diff --git a/packages/backend/src/remote/activitypub/kernel/undo/accept.ts b/packages/backend/src/remote/activitypub/kernel/undo/accept.ts index 8f6eab6858..a6e3929b0f 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/accept.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/accept.ts @@ -1,6 +1,6 @@ import unfollow from '@/services/following/delete.js'; import cancelRequest from '@/services/following/requests/cancel.js'; -import {IAccept} from '../../type.js'; +import { IAccept } from '../../type.js'; import { CacheableRemoteUser } from '@/models/entities/user.js'; import { Followings } from '@/models/index.js'; import DbResolver from '../../db-resolver.js'; diff --git a/packages/backend/src/remote/activitypub/misc/ld-signature.ts b/packages/backend/src/remote/activitypub/misc/ld-signature.ts index 5132c6ef96..362a543ece 100644 --- a/packages/backend/src/remote/activitypub/misc/ld-signature.ts +++ b/packages/backend/src/remote/activitypub/misc/ld-signature.ts @@ -113,7 +113,8 @@ export class LdSignature { headers: { Accept: 'application/ld+json, application/json', }, - timeout: this.loderTimeout, + // TODO + //timeout: this.loderTimeout, agent: u => u.protocol === 'http:' ? httpAgent : httpsAgent, }).then(res => { if (!res.ok) { diff --git a/packages/backend/src/remote/activitypub/models/question.ts b/packages/backend/src/remote/activitypub/models/question.ts index 9e75864c63..034501572a 100644 --- a/packages/backend/src/remote/activitypub/models/question.ts +++ b/packages/backend/src/remote/activitypub/models/question.ts @@ -69,7 +69,7 @@ export async function updateQuestion(value: any) { const oldCount = poll.votes[poll.choices.indexOf(choice)]; const newCount = apChoices!.filter(ap => ap.name === choice)[0].replies!.totalItems; - if (oldCount != newCount) { + if (oldCount !== newCount) { changed = true; poll.votes[poll.choices.indexOf(choice)] = newCount; } diff --git a/packages/backend/src/remote/webfinger.ts b/packages/backend/src/remote/webfinger.ts index 9d3bfab24b..337df34c2d 100644 --- a/packages/backend/src/remote/webfinger.ts +++ b/packages/backend/src/remote/webfinger.ts @@ -15,7 +15,7 @@ type IWebFinger = { export default async function(query: string): Promise<IWebFinger> { const url = genUrl(query); - return await getJson(url, 'application/jrd+json, application/json'); + return await getJson(url, 'application/jrd+json, application/json') as IWebFinger; } function genUrl(query: string) { diff --git a/packages/backend/src/server/api/2fa.ts b/packages/backend/src/server/api/2fa.ts index e1c226979a..dce8accaac 100644 --- a/packages/backend/src/server/api/2fa.ts +++ b/packages/backend/src/server/api/2fa.ts @@ -121,14 +121,14 @@ export function verifyLogin({ signature: Buffer, challenge: string }) { - if (clientData.type != 'webauthn.get') { + if (clientData.type !== 'webauthn.get') { throw new Error('type is not webauthn.get'); } - if (hash(clientData.challenge).toString('hex') != challenge) { + if (hash(clientData.challenge).toString('hex') !== challenge) { throw new Error('challenge mismatch'); } - if (clientData.origin != config.scheme + '://' + config.host) { + if (clientData.origin !== config.scheme + '://' + config.host) { throw new Error('origin mismatch'); } @@ -148,11 +148,11 @@ export const procedures = { verify({ publicKey }: {publicKey: Map<number, Buffer>}) { const negTwo = publicKey.get(-2); - if (!negTwo || negTwo.length != 32) { + if (!negTwo || negTwo.length !== 32) { throw new Error('invalid or no -2 key given'); } const negThree = publicKey.get(-3); - if (!negThree || negThree.length != 32) { + if (!negThree || negThree.length !== 32) { throw new Error('invalid or no -3 key given'); } @@ -183,7 +183,7 @@ export const procedures = { rpIdHash: Buffer, credentialId: Buffer, }) { - if (attStmt.alg != -7) { + if (attStmt.alg !== -7) { throw new Error('alg mismatch'); } @@ -196,11 +196,11 @@ export const procedures = { const negTwo = publicKey.get(-2); - if (!negTwo || negTwo.length != 32) { + if (!negTwo || negTwo.length !== 32) { throw new Error('invalid or no -2 key given'); } const negThree = publicKey.get(-3); - if (!negThree || negThree.length != 32) { + if (!negThree || negThree.length !== 32) { throw new Error('invalid or no -3 key given'); } @@ -263,7 +263,7 @@ export const procedures = { .map((key: any) => PEMString(key)) .concat([GSR2]); - if (getCertSubject(certificateChain[0]).CN != 'attest.android.com') { + if (getCertSubject(certificateChain[0]).CN !== 'attest.android.com') { throw new Error('invalid common name'); } @@ -283,11 +283,11 @@ export const procedures = { const negTwo = publicKey.get(-2); - if (!negTwo || negTwo.length != 32) { + if (!negTwo || negTwo.length !== 32) { throw new Error('invalid or no -2 key given'); } const negThree = publicKey.get(-3); - if (!negThree || negThree.length != 32) { + if (!negThree || negThree.length !== 32) { throw new Error('invalid or no -3 key given'); } @@ -332,11 +332,11 @@ export const procedures = { const negTwo = publicKey.get(-2); - if (!negTwo || negTwo.length != 32) { + if (!negTwo || negTwo.length !== 32) { throw new Error('invalid or no -2 key given'); } const negThree = publicKey.get(-3); - if (!negThree || negThree.length != 32) { + if (!negThree || negThree.length !== 32) { throw new Error('invalid or no -3 key given'); } @@ -353,7 +353,7 @@ export const procedures = { // https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-ecdaa-algorithm-v2.0-id-20180227.html#ecdaa-verify-operation throw new Error('ECDAA-Verify is not supported'); } else { - if (attStmt.alg != -7) throw new Error('alg mismatch'); + if (attStmt.alg !== -7) throw new Error('alg mismatch'); throw new Error('self attestation is not supported'); } @@ -377,7 +377,7 @@ export const procedures = { credentialId: Buffer }) { const x5c: Buffer[] = attStmt.x5c; - if (x5c.length != 1) { + if (x5c.length !== 1) { throw new Error('x5c length does not match expectation'); } @@ -387,11 +387,11 @@ export const procedures = { const negTwo: Buffer = publicKey.get(-2); - if (!negTwo || negTwo.length != 32) { + if (!negTwo || negTwo.length !== 32) { throw new Error('invalid or no -2 key given'); } const negThree: Buffer = publicKey.get(-3); - if (!negThree || negThree.length != 32) { + if (!negThree || negThree.length !== 32) { throw new Error('invalid or no -3 key given'); } diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index b6a2cf7200..0939ae3365 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -48,7 +48,6 @@ export const paramDef = { } as const; // eslint-disable-next-line import/no-default-export -// @ts-ignore export default define(meta, paramDef, async (ps, user, _, file, cleanup) => { // Get 'name' parameter let name = ps.name || file.originalname; diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index 0116a55fb7..1afb34bfda 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -50,10 +50,10 @@ export default define(meta, paramDef, async (ps, user) => { const clientData = JSON.parse(ps.clientDataJSON); - if (clientData.type != 'webauthn.create') { + if (clientData.type !== 'webauthn.create') { throw new Error('not a creation attestation'); } - if (clientData.origin != config.scheme + '://' + config.host) { + if (clientData.origin !== config.scheme + '://' + config.host) { throw new Error('origin mismatch'); } @@ -78,7 +78,7 @@ export default define(meta, paramDef, async (ps, user) => { const credentialId = authData.slice(55, 55 + credentialIdLength); const publicKeyData = authData.slice(55 + credentialIdLength); const publicKey: Map<number, any> = await cborDecodeFirst(publicKeyData); - if (publicKey.get(3) != -7) { + if (publicKey.get(3) !== -7) { throw new Error('alg mismatch'); } diff --git a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts index 3301808e75..68bd103a6d 100644 --- a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts +++ b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts @@ -27,7 +27,7 @@ export default define(meta, paramDef, async (ps, user) => { take: ps.limit, skip: ps.offset, order: { - id: ps.sort == 'asc' ? 1 : -1, + id: ps.sort === 'asc' ? 1 : -1, }, }); diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts index 99c8b973f6..2733c826e9 100644 --- a/packages/backend/src/server/api/endpoints/notes.ts +++ b/packages/backend/src/server/api/endpoints/notes.ts @@ -52,19 +52,19 @@ export default define(meta, paramDef, async (ps) => { query.andWhere('note.userHost IS NULL'); } - if (ps.reply != undefined) { + if (ps.reply !== undefined) { query.andWhere(ps.reply ? 'note.replyId IS NOT NULL' : 'note.replyId IS NULL'); } - if (ps.renote != undefined) { + if (ps.renote !== undefined) { query.andWhere(ps.renote ? 'note.renoteId IS NOT NULL' : 'note.renoteId IS NULL'); } - if (ps.withFiles != undefined) { + if (ps.withFiles !== undefined) { query.andWhere(ps.withFiles ? `note.fileIds != '{}'` : `note.fileIds = '{}'`); } - if (ps.poll != undefined) { + if (ps.poll !== undefined) { query.andWhere(ps.poll ? 'note.hasPoll = TRUE' : 'note.hasPoll = FALSE'); } diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 8f5d21db60..b991a495f2 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -57,7 +57,7 @@ export default define(meta, paramDef, async (ps, user) => { conversation.push(p); } - if (conversation.length == ps.limit) { + if (conversation.length === ps.limit) { return; } diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 24d0c8134f..9de05918c0 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -9,6 +9,7 @@ import { Note } from '@/models/entities/note.js'; import { noteVisibilities } from '../../../../types.js'; import { Channel } from '@/models/entities/channel.js'; import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; +import { In } from 'typeorm'; export const meta = { tags: ['notes'], @@ -163,19 +164,18 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { let visibleUsers: User[] = []; if (ps.visibleUserIds) { - visibleUsers = (await Promise.all(ps.visibleUserIds.map(id => Users.findOneBy({ id })))) - .filter(x => x != null) as User[]; + visibleUsers = await Users.findBy({ + id: In(ps.visibleUserIds), + }); } let files: DriveFile[] = []; const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null; if (fileIds != null) { - files = (await Promise.all(fileIds.map(fileId => - DriveFiles.findOneBy({ - id: fileId, - userId: user.id, - }) - ))).filter(file => file != null) as DriveFile[]; + files = await DriveFiles.findBy({ + userId: user.id, + id: In(fileIds), + }); } let renote: Note | null; diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index 6380b331f2..6244b55cf2 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -110,7 +110,7 @@ export default define(meta, paramDef, async (ps, user) => { if (exist.length) { if (poll.multiple) { - if (exist.some(x => x.choice == ps.choice)) { + if (exist.some(x => x.choice === ps.choice)) { throw new ApiError(meta.errors.alreadyVoted); } } else { diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index 068df6940b..c602981b30 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -75,7 +75,8 @@ export default define(meta, paramDef, async (ps, user) => { Accept: 'application/json, */*', }, body: params, - timeout: 10000, + // TODO + //timeout: 10000, agent: getAgentByUrl, }); diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index b1a568145a..183ff1b8bb 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -23,9 +23,9 @@ export const meta = { items: { type: 'object', ref: 'UserDetailed', - } + }, }, - ] + ], }, errors: { @@ -70,7 +70,7 @@ export const paramDef = { description: 'The local host is represented with `null`.', }, }, - required: ['username', 'host'], + required: ['username'], }, ], } as const; diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index 3f7118ad22..7b66657ad8 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -24,17 +24,17 @@ export default async (ctx: Koa.Context) => { ctx.body = { error }; } - if (typeof username != 'string') { + if (typeof username !== 'string') { ctx.status = 400; return; } - if (typeof password != 'string') { + if (typeof password !== 'string') { ctx.status = 400; return; } - if (token != null && typeof token != 'string') { + if (token != null && typeof token !== 'string') { ctx.status = 400; return; } diff --git a/packages/backend/src/server/web/style.css b/packages/backend/src/server/web/style.css index 43fbe1ab06..9c4cd4b9bf 100644 --- a/packages/backend/src/server/web/style.css +++ b/packages/backend/src/server/web/style.css @@ -16,7 +16,7 @@ html { transition: opacity 0.5s ease; } -#splash > img { +#splashIcon { position: absolute; top: 0; right: 0; @@ -27,3 +27,48 @@ html { height: 64px; pointer-events: none; } + +#splashSpinner { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + display: inline-block; + width: 28px; + height: 28px; + transform: translateY(70px); +} + +#splashSpinner:before, +#splashSpinner:after { + content: " "; + display: block; + box-sizing: border-box; + width: 28px; + height: 28px; + border-radius: 50%; + border: solid 4px; +} + +#splashSpinner:before { + border-color: currentColor; + opacity: 0.3; +} + +#splashSpinner:after { + position: absolute; + top: 0; + border-color: currentColor transparent transparent transparent; + animation: splashSpinner 0.5s linear infinite; +} + +@keyframes splashSpinner { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index abacb1ccfc..1513208310 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -59,5 +59,6 @@ html br | Please turn on your JavaScript div#splash - img(src= icon || '/static-assets/splash.png') + img#splashIcon(src= icon || '/static-assets/splash.png') + div#splashSpinner block content diff --git a/packages/backend/src/services/blocking/create.ts b/packages/backend/src/services/blocking/create.ts index 5c67190079..5e96e5037f 100644 --- a/packages/backend/src/services/blocking/create.ts +++ b/packages/backend/src/services/blocking/create.ts @@ -65,8 +65,7 @@ async function cancelRequest(follower: User, followee: User) { const webhooks = (await getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'unfollow', + webhookDeliver(webhook, 'unfollow', { user: packed, }); } @@ -118,8 +117,7 @@ async function unFollow(follower: User, followee: User) { const webhooks = (await getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'unfollow', + webhookDeliver(webhook, 'unfollow', { user: packed, }); } diff --git a/packages/backend/src/services/drive/upload-from-url.ts b/packages/backend/src/services/drive/upload-from-url.ts index 5007fff6ee..79b1b8c2e1 100644 --- a/packages/backend/src/services/drive/upload-from-url.ts +++ b/packages/backend/src/services/drive/upload-from-url.ts @@ -29,7 +29,7 @@ export async function uploadFromUrl({ sensitive = false, force = false, isLink = false, - comment = null + comment = null, }: Args): Promise<DriveFile> { let name = new URL(url).pathname.split('/').pop() || null; if (name == null || !DriveFiles.validateFileName(name)) { @@ -38,7 +38,7 @@ export async function uploadFromUrl({ // If the comment is same as the name, skip comment // (image.name is passed in when receiving attachment) - if (comment !== null && name == comment) { + if (comment !== null && name === comment) { comment = null; } diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts index 2b6f82a910..d5294c5fe8 100644 --- a/packages/backend/src/services/fetch-instance-metadata.ts +++ b/packages/backend/src/services/fetch-instance-metadata.ts @@ -97,7 +97,7 @@ async function fetchNodeinfo(instance: Instance): Promise<NodeInfo> { } else { throw e.statusCode || e.message; } - }); + }) as Record<string, unknown>; if (wellknown.links == null || !Array.isArray(wellknown.links)) { throw 'No wellknown links'; @@ -121,7 +121,7 @@ async function fetchNodeinfo(instance: Instance): Promise<NodeInfo> { logger.succ(`Successfuly fetched nodeinfo of ${instance.host}`); - return info; + return info as NodeInfo; } catch (e) { logger.error(`Failed to fetch nodeinfo of ${instance.host}: ${e}`); @@ -142,12 +142,12 @@ async function fetchDom(instance: Instance): Promise<DOMWindow['document']> { return doc; } -async function fetchManifest(instance: Instance): Promise<Record<string, any> | null> { +async function fetchManifest(instance: Instance): Promise<Record<string, unknown> | null> { const url = 'https://' + instance.host; const manifestUrl = url + '/manifest.json'; - const manifest = await getJson(manifestUrl); + const manifest = await getJson(manifestUrl) as Record<string, unknown>; return manifest; } @@ -167,7 +167,8 @@ async function fetchFaviconUrl(instance: Instance, doc: DOMWindow['document'] | const faviconUrl = url + '/favicon.ico'; const favicon = await fetch(faviconUrl, { - timeout: 10000, + // TODO + //timeout: 10000, agent: getAgentByUrl, }); diff --git a/packages/backend/src/services/following/create.ts b/packages/backend/src/services/following/create.ts index d243317d97..7491c44f83 100644 --- a/packages/backend/src/services/following/create.ts +++ b/packages/backend/src/services/following/create.ts @@ -97,8 +97,7 @@ export async function insertFollowingDoc(followee: { id: User['id']; host: User[ const webhooks = (await getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('follow')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'follow', + webhookDeliver(webhook, 'follow', { user: packed, }); } @@ -108,12 +107,11 @@ export async function insertFollowingDoc(followee: { id: User['id']; host: User[ // Publish followed event if (Users.isLocalUser(followee)) { Users.pack(follower.id, followee).then(async packed => { - publishMainStream(followee.id, 'followed', packed) + publishMainStream(followee.id, 'followed', packed); const webhooks = (await getActiveWebhooks()).filter(x => x.userId === followee.id && x.on.includes('followed')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'followed', + webhookDeliver(webhook, 'followed', { user: packed, }); } diff --git a/packages/backend/src/services/following/delete.ts b/packages/backend/src/services/following/delete.ts index 85e40f1365..241f9606e5 100644 --- a/packages/backend/src/services/following/delete.ts +++ b/packages/backend/src/services/following/delete.ts @@ -38,8 +38,7 @@ export default async function(follower: { id: User['id']; host: User['host']; ur const webhooks = (await getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'unfollow', + webhookDeliver(webhook, 'unfollow', { user: packed, }); } diff --git a/packages/backend/src/services/following/reject.ts b/packages/backend/src/services/following/reject.ts index e1744e05be..691fca2456 100644 --- a/packages/backend/src/services/following/reject.ts +++ b/packages/backend/src/services/following/reject.ts @@ -115,8 +115,7 @@ async function publishUnfollow(followee: Both, follower: Local) { const webhooks = (await getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'unfollow', + webhookDeliver(webhook, 'unfollow', { user: packedFollowee, }); } diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 6f373aaf45..f14bc2059b 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -350,8 +350,7 @@ export default async (user: { id: User['id']; username: User['username']; host: getActiveWebhooks().then(webhooks => { webhooks = webhooks.filter(x => x.userId === user.id && x.on.includes('note')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'note', + webhookDeliver(webhook, 'note', { note: noteObj, }); } @@ -380,8 +379,7 @@ export default async (user: { id: User['id']; username: User['username']; host: const webhooks = (await getActiveWebhooks()).filter(x => x.userId === data.reply!.userId && x.on.includes('reply')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'reply', + webhookDeliver(webhook, 'reply', { note: noteObj, }); } @@ -407,8 +405,7 @@ export default async (user: { id: User['id']; username: User['username']; host: const webhooks = (await getActiveWebhooks()).filter(x => x.userId === data.renote!.userId && x.on.includes('renote')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'renote', + webhookDeliver(webhook, 'renote', { note: noteObj, }); } @@ -650,8 +647,7 @@ async function createMentionedEvents(mentionedUsers: MinimumUser[], note: Note, const webhooks = (await getActiveWebhooks()).filter(x => x.userId === u.id && x.on.includes('mention')); for (const webhook of webhooks) { - webhookDeliver(webhook, { - type: 'mention', + webhookDeliver(webhook, 'mention', { note: detailPackedNote, }); } |