summaryrefslogtreecommitdiff
path: root/packages/backend/src/services
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-06-11 19:31:03 +0900
committerGitHub <noreply@github.com>2022-06-11 19:31:03 +0900
commit182a1bf653ecfbcf76e4530b3077c6252b0d4827 (patch)
tree45d1472747d4cac017e96616f844292f5785ccdd /packages/backend/src/services
parent12.110.1 (diff)
parent12.111.0 (diff)
downloadsharkey-182a1bf653ecfbcf76e4530b3077c6252b0d4827.tar.gz
sharkey-182a1bf653ecfbcf76e4530b3077c6252b0d4827.tar.bz2
sharkey-182a1bf653ecfbcf76e4530b3077c6252b0d4827.zip
Merge pull request #8783 from misskey-dev/develop
Release: 12.111.0
Diffstat (limited to 'packages/backend/src/services')
-rw-r--r--packages/backend/src/services/blocking/create.ts30
-rw-r--r--packages/backend/src/services/blocking/delete.ts9
-rw-r--r--packages/backend/src/services/chart/core.ts27
-rw-r--r--packages/backend/src/services/chart/entities.ts12
-rw-r--r--packages/backend/src/services/create-notification.ts4
-rw-r--r--packages/backend/src/services/drive/add-file.ts29
-rw-r--r--packages/backend/src/services/drive/generate-video-thumbnail.ts54
-rw-r--r--packages/backend/src/services/drive/image-processor.ts28
-rw-r--r--packages/backend/src/services/drive/upload-from-url.ts25
-rw-r--r--packages/backend/src/services/fetch-instance-metadata.ts14
-rw-r--r--packages/backend/src/services/following/create.ts6
-rw-r--r--packages/backend/src/services/following/delete.ts11
-rw-r--r--packages/backend/src/services/messages/create.ts2
-rw-r--r--packages/backend/src/services/note/create.ts5
-rw-r--r--packages/backend/src/services/note/delete.ts8
-rw-r--r--packages/backend/src/services/note/reaction/create.ts5
-rw-r--r--packages/backend/src/services/push-notification.ts24
-rw-r--r--packages/backend/src/services/relay.ts6
18 files changed, 147 insertions, 152 deletions
diff --git a/packages/backend/src/services/blocking/create.ts b/packages/backend/src/services/blocking/create.ts
index 5e96e5037f..a2c61cca22 100644
--- a/packages/backend/src/services/blocking/create.ts
+++ b/packages/backend/src/services/blocking/create.ts
@@ -2,9 +2,10 @@ import { publishMainStream, publishUserEvent } from '@/services/stream.js';
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
import renderFollow from '@/remote/activitypub/renderer/follow.js';
import renderUndo from '@/remote/activitypub/renderer/undo.js';
-import renderBlock from '@/remote/activitypub/renderer/block.js';
+import { renderBlock } from '@/remote/activitypub/renderer/block.js';
import { deliver } from '@/queue/index.js';
import renderReject from '@/remote/activitypub/renderer/reject.js';
+import { Blocking } from '@/models/entities/blocking.js';
import { User } from '@/models/entities/user.js';
import { Blockings, Users, FollowRequests, Followings, UserListJoinings, UserLists } from '@/models/index.js';
import { perUserFollowingChart } from '@/services/chart/index.js';
@@ -22,15 +23,19 @@ export default async function(blocker: User, blockee: User) {
removeFromList(blockee, blocker),
]);
- await Blockings.insert({
+ const blocking = {
id: genId(),
createdAt: new Date(),
+ blocker,
blockerId: blocker.id,
+ blockee,
blockeeId: blockee.id,
- });
+ } as Blocking;
+
+ await Blockings.insert(blocking);
if (Users.isLocalUser(blocker) && Users.isRemoteUser(blockee)) {
- const content = renderActivity(renderBlock(blocker, blockee));
+ const content = renderActivity(renderBlock(blocking));
deliver(blocker, content, blockee.inbox);
}
}
@@ -95,17 +100,12 @@ async function unFollow(follower: User, followee: User) {
return;
}
- Followings.delete(following.id);
-
- //#region Decrement following count
- Users.decrement({ id: follower.id }, 'followingCount', 1);
- //#endregion
-
- //#region Decrement followers count
- Users.decrement({ id: followee.id }, 'followersCount', 1);
- //#endregion
-
- perUserFollowingChart.update(follower, followee, false);
+ await Promise.all([
+ Followings.delete(following.id),
+ Users.decrement({ id: follower.id }, 'followingCount', 1),
+ Users.decrement({ id: followee.id }, 'followersCount', 1),
+ perUserFollowingChart.update(follower, followee, false),
+ ]);
// Publish unfollow event
if (Users.isLocalUser(follower)) {
diff --git a/packages/backend/src/services/blocking/delete.ts b/packages/backend/src/services/blocking/delete.ts
index d7b5ddd5ff..cb16651bc0 100644
--- a/packages/backend/src/services/blocking/delete.ts
+++ b/packages/backend/src/services/blocking/delete.ts
@@ -1,5 +1,5 @@
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
-import renderBlock from '@/remote/activitypub/renderer/block.js';
+import { renderBlock } from '@/remote/activitypub/renderer/block.js';
import renderUndo from '@/remote/activitypub/renderer/undo.js';
import { deliver } from '@/queue/index.js';
import Logger from '../logger.js';
@@ -19,11 +19,16 @@ export default async function(blocker: CacheableUser, blockee: CacheableUser) {
return;
}
+ // Since we already have the blocker and blockee, we do not need to fetch
+ // them in the query above and can just manually insert them here.
+ blocking.blocker = blocker;
+ blocking.blockee = blockee;
+
Blockings.delete(blocking.id);
// deliver if remote bloking
if (Users.isLocalUser(blocker) && Users.isRemoteUser(blockee)) {
- const content = renderActivity(renderUndo(renderBlock(blocker, blockee), blocker));
+ const content = renderActivity(renderUndo(renderBlock(blocking), blocker));
deliver(blocker, content, blockee.inbox);
}
}
diff --git a/packages/backend/src/services/chart/core.ts b/packages/backend/src/services/chart/core.ts
index cf69e2194d..2960bac8f7 100644
--- a/packages/backend/src/services/chart/core.ts
+++ b/packages/backend/src/services/chart/core.ts
@@ -91,27 +91,20 @@ type ToJsonSchema<S> = {
};
export function getJsonSchema<S extends Schema>(schema: S): ToJsonSchema<Unflatten<ChartResult<S>>> {
- const object = {};
- for (const [k, v] of Object.entries(schema)) {
- nestedProperty.set(object, k, null);
- }
+ const jsonSchema = {
+ type: 'object',
+ properties: {} as Record<string, unknown>,
+ required: [],
+ };
- function f(obj: Record<string, null | Record<string, unknown>>) {
- const jsonSchema = {
- type: 'object',
- properties: {} as Record<string, unknown>,
- required: [],
+ for (const k in schema) {
+ jsonSchema.properties[k] = {
+ type: 'array',
+ items: { type: 'number' },
};
- for (const [k, v] of Object.entries(obj)) {
- jsonSchema.properties[k] = v === null ? {
- type: 'array',
- items: { type: 'number' },
- } : f(v as Record<string, null | Record<string, unknown>>);
- }
- return jsonSchema;
}
- return f(object) as ToJsonSchema<Unflatten<ChartResult<S>>>;
+ return jsonSchema as ToJsonSchema<Unflatten<ChartResult<S>>>;
}
/**
diff --git a/packages/backend/src/services/chart/entities.ts b/packages/backend/src/services/chart/entities.ts
index 13e994cb65..a9eeabd639 100644
--- a/packages/backend/src/services/chart/entities.ts
+++ b/packages/backend/src/services/chart/entities.ts
@@ -11,6 +11,11 @@ import { entity as PerUserFollowingChart } from './charts/entities/per-user-foll
import { entity as PerUserDriveChart } from './charts/entities/per-user-drive.js';
import { entity as ApRequestChart } from './charts/entities/ap-request.js';
+import { entity as TestChart } from './charts/entities/test.js';
+import { entity as TestGroupedChart } from './charts/entities/test-grouped.js';
+import { entity as TestUniqueChart } from './charts/entities/test-unique.js';
+import { entity as TestIntersectionChart } from './charts/entities/test-intersection.js';
+
export const entities = [
FederationChart.hour, FederationChart.day,
NotesChart.hour, NotesChart.day,
@@ -24,4 +29,11 @@ export const entities = [
PerUserFollowingChart.hour, PerUserFollowingChart.day,
PerUserDriveChart.hour, PerUserDriveChart.day,
ApRequestChart.hour, ApRequestChart.day,
+
+ ...(process.env.NODE_ENV === 'test' ? [
+ TestChart.hour, TestChart.day,
+ TestGroupedChart.hour, TestGroupedChart.day,
+ TestUniqueChart.hour, TestUniqueChart.day,
+ TestIntersectionChart.hour, TestIntersectionChart.day,
+ ] : []),
];
diff --git a/packages/backend/src/services/create-notification.ts b/packages/backend/src/services/create-notification.ts
index 9a53db1f38..d53a4235b8 100644
--- a/packages/backend/src/services/create-notification.ts
+++ b/packages/backend/src/services/create-notification.ts
@@ -1,5 +1,5 @@
import { publishMainStream } from '@/services/stream.js';
-import pushSw from './push-notification.js';
+import { pushNotification } from '@/services/push-notification.js';
import { Notifications, Mutings, UserProfiles, Users } from '@/models/index.js';
import { genId } from '@/misc/gen-id.js';
import { User } from '@/models/entities/user.js';
@@ -52,8 +52,8 @@ export async function createNotification(
//#endregion
publishMainStream(notifieeId, 'unreadNotification', packed);
+ pushNotification(notifieeId, 'notification', packed);
- pushSw(notifieeId, 'notification', packed);
if (type === 'follow') sendEmailNotification.follow(notifieeId, await Users.findOneByOrFail({ id: data.notifierId! }));
if (type === 'receiveFollowRequest') sendEmailNotification.receiveFollowRequest(notifieeId, await Users.findOneByOrFail({ id: data.notifierId! }));
}, 2000);
diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts
index 549b11c9fe..cfbcb60ddf 100644
--- a/packages/backend/src/services/drive/add-file.ts
+++ b/packages/backend/src/services/drive/add-file.ts
@@ -7,7 +7,7 @@ import { deleteFile } from './delete-file.js';
import { fetchMeta } from '@/misc/fetch-meta.js';
import { GenerateVideoThumbnail } from './generate-video-thumbnail.js';
import { driveLogger } from './logger.js';
-import { IImage, convertSharpToJpeg, convertSharpToWebp, convertSharpToPng, convertSharpToPngOrJpeg } from './image-processor.js';
+import { IImage, convertSharpToJpeg, convertSharpToWebp, convertSharpToPng } from './image-processor.js';
import { contentDisposition } from '@/misc/content-disposition.js';
import { getFileInfo } from '@/misc/get-file-info.js';
import { DriveFiles, DriveFolders, Users, Instances, UserProfiles } from '@/models/index.js';
@@ -179,6 +179,7 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
}
let img: sharp.Sharp | null = null;
+ let satisfyWebpublic: boolean;
try {
img = sharp(path);
@@ -192,6 +193,13 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
thumbnail: null,
};
}
+
+ satisfyWebpublic = !!(
+ type !== 'image/svg+xml' && type !== 'image/webp' &&
+ !(metadata.exif || metadata.iptc || metadata.xmp || metadata.tifftagPhotoshop) &&
+ metadata.width && metadata.width <= 2048 &&
+ metadata.height && metadata.height <= 2048
+ );
} catch (err) {
logger.warn(`sharp failed: ${err}`);
return {
@@ -203,15 +211,15 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
// #region webpublic
let webpublic: IImage | null = null;
- if (generateWeb) {
+ if (generateWeb && !satisfyWebpublic) {
logger.info(`creating web image`);
try {
- if (['image/jpeg'].includes(type)) {
+ if (['image/jpeg', 'image/webp'].includes(type)) {
webpublic = await convertSharpToJpeg(img, 2048, 2048);
- } else if (['image/webp'].includes(type)) {
- webpublic = await convertSharpToWebp(img, 2048, 2048);
- } else if (['image/png', 'image/svg+xml'].includes(type)) {
+ } else if (['image/png'].includes(type)) {
+ webpublic = await convertSharpToPng(img, 2048, 2048);
+ } else if (['image/svg+xml'].includes(type)) {
webpublic = await convertSharpToPng(img, 2048, 2048);
} else {
logger.debug(`web image not created (not an required image)`);
@@ -220,7 +228,8 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
logger.warn(`web image not created (an error occured)`, err as Error);
}
} else {
- logger.info(`web image not created (from remote)`);
+ if (satisfyWebpublic) logger.info(`web image not created (original satisfies webpublic)`);
+ else logger.info(`web image not created (from remote)`);
}
// #endregion webpublic
@@ -228,10 +237,8 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
let thumbnail: IImage | null = null;
try {
- if (['image/jpeg', 'image/webp'].includes(type)) {
- thumbnail = await convertSharpToJpeg(img, 498, 280);
- } else if (['image/png', 'image/svg+xml'].includes(type)) {
- thumbnail = await convertSharpToPngOrJpeg(img, 498, 280);
+ if (['image/jpeg', 'image/webp', 'image/png', 'image/svg+xml'].includes(type)) {
+ thumbnail = await convertSharpToWebp(img, 498, 280);
} else {
logger.debug(`thumbnail not created (not an required file)`);
}
diff --git a/packages/backend/src/services/drive/generate-video-thumbnail.ts b/packages/backend/src/services/drive/generate-video-thumbnail.ts
index 04a7a83346..ca12ab8d3d 100644
--- a/packages/backend/src/services/drive/generate-video-thumbnail.ts
+++ b/packages/backend/src/services/drive/generate-video-thumbnail.ts
@@ -1,37 +1,31 @@
import * as fs from 'node:fs';
-import * as tmp from 'tmp';
+import * as path from 'node:path';
+import { createTemp } from '@/misc/create-temp.js';
import { IImage, convertToJpeg } from './image-processor.js';
-import * as FFmpeg from 'fluent-ffmpeg';
+import FFmpeg from 'fluent-ffmpeg';
-export async function GenerateVideoThumbnail(path: string): Promise<IImage> {
- const [outDir, cleanup] = await new Promise<[string, any]>((res, rej) => {
- tmp.dir((e, path, cleanup) => {
- if (e) return rej(e);
- res([path, cleanup]);
- });
- });
+export async function GenerateVideoThumbnail(source: string): Promise<IImage> {
+ const [file, cleanup] = await createTemp();
+ const parsed = path.parse(file);
- await new Promise((res, rej) => {
- FFmpeg({
- source: path,
- })
- .on('end', res)
- .on('error', rej)
- .screenshot({
- folder: outDir,
- filename: 'output.png',
- count: 1,
- timestamps: ['5%'],
+ try {
+ await new Promise((res, rej) => {
+ FFmpeg({
+ source,
+ })
+ .on('end', res)
+ .on('error', rej)
+ .screenshot({
+ folder: parsed.dir,
+ filename: parsed.base,
+ count: 1,
+ timestamps: ['5%'],
+ });
});
- });
-
- const outPath = `${outDir}/output.png`;
-
- const thumbnail = await convertToJpeg(outPath, 498, 280);
-
- // cleanup
- await fs.promises.unlink(outPath);
- cleanup();
- return thumbnail;
+ // JPEGに変換 (Webpでもいいが、MastodonはWebpをサポートせず表示できなくなる)
+ return await convertToJpeg(498, 280);
+ } finally {
+ cleanup();
+ }
}
diff --git a/packages/backend/src/services/drive/image-processor.ts b/packages/backend/src/services/drive/image-processor.ts
index 146dcfb6ca..2c564ea595 100644
--- a/packages/backend/src/services/drive/image-processor.ts
+++ b/packages/backend/src/services/drive/image-processor.ts
@@ -38,11 +38,11 @@ export async function convertSharpToJpeg(sharp: sharp.Sharp, width: number, heig
* Convert to WebP
* with resize, remove metadata, resolve orientation, stop animation
*/
-export async function convertToWebp(path: string, width: number, height: number): Promise<IImage> {
- return convertSharpToWebp(await sharp(path), width, height);
+export async function convertToWebp(path: string, width: number, height: number, quality: number = 85): Promise<IImage> {
+ return convertSharpToWebp(await sharp(path), width, height, quality);
}
-export async function convertSharpToWebp(sharp: sharp.Sharp, width: number, height: number): Promise<IImage> {
+export async function convertSharpToWebp(sharp: sharp.Sharp, width: number, height: number, quality: number = 85): Promise<IImage> {
const data = await sharp
.resize(width, height, {
fit: 'inside',
@@ -50,7 +50,7 @@ export async function convertSharpToWebp(sharp: sharp.Sharp, width: number, heig
})
.rotate()
.webp({
- quality: 85,
+ quality,
})
.toBuffer();
@@ -85,23 +85,3 @@ export async function convertSharpToPng(sharp: sharp.Sharp, width: number, heigh
type: 'image/png',
};
}
-
-/**
- * Convert to PNG or JPEG
- * with resize, remove metadata, resolve orientation, stop animation
- */
-export async function convertToPngOrJpeg(path: string, width: number, height: number): Promise<IImage> {
- return convertSharpToPngOrJpeg(await sharp(path), width, height);
-}
-
-export async function convertSharpToPngOrJpeg(sharp: sharp.Sharp, width: number, height: number): Promise<IImage> {
- const stats = await sharp.stats();
- const metadata = await sharp.metadata();
-
- // 不透明で300x300pxの範囲を超えていればJPEG
- if (stats.isOpaque && ((metadata.width && metadata.width >= 300) || (metadata.height && metadata!.height >= 300))) {
- return await convertSharpToJpeg(sharp, width, height);
- } else {
- return await convertSharpToPng(sharp, width, height);
- }
-}
diff --git a/packages/backend/src/services/drive/upload-from-url.ts b/packages/backend/src/services/drive/upload-from-url.ts
index 79b1b8c2e1..001fc49ee4 100644
--- a/packages/backend/src/services/drive/upload-from-url.ts
+++ b/packages/backend/src/services/drive/upload-from-url.ts
@@ -45,29 +45,20 @@ export async function uploadFromUrl({
// Create temp file
const [path, cleanup] = await createTemp();
- // write content at URL to temp file
- await downloadUrl(url, path);
-
- let driveFile: DriveFile;
- let error;
-
try {
- driveFile = await addFile({ user, path, name, comment, folderId, force, isLink, url, uri, sensitive });
+ // write content at URL to temp file
+ await downloadUrl(url, path);
+
+ const driveFile = await addFile({ user, path, name, comment, folderId, force, isLink, url, uri, sensitive });
logger.succ(`Got: ${driveFile.id}`);
+ return driveFile!;
} catch (e) {
- error = e;
logger.error(`Failed to create drive file: ${e}`, {
url: url,
e: e,
});
- }
-
- // clean-up
- cleanup();
-
- if (error) {
- throw error;
- } else {
- return driveFile!;
+ throw e;
+ } finally {
+ cleanup();
}
}
diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts
index d5294c5fe8..029c388dc2 100644
--- a/packages/backend/src/services/fetch-instance-metadata.ts
+++ b/packages/backend/src/services/fetch-instance-metadata.ts
@@ -1,5 +1,6 @@
import { DOMWindow, JSDOM } from 'jsdom';
import fetch from 'node-fetch';
+import tinycolor from 'tinycolor2';
import { getJson, getHtml, getAgentByUrl } from '@/misc/fetch.js';
import { Instance } from '@/models/entities/instance.js';
import { Instances } from '@/models/index.js';
@@ -208,16 +209,11 @@ async function fetchIconUrl(instance: Instance, doc: DOMWindow['document'] | nul
}
async function getThemeColor(doc: DOMWindow['document'] | null, manifest: Record<string, any> | null): Promise<string | null> {
- if (doc) {
- const themeColor = doc.querySelector('meta[name="theme-color"]')?.getAttribute('content');
+ const themeColor = doc?.querySelector('meta[name="theme-color"]')?.getAttribute('content') || manifest?.theme_color;
- if (themeColor) {
- return themeColor;
- }
- }
-
- if (manifest) {
- return manifest.theme_color;
+ if (themeColor) {
+ const color = new tinycolor(themeColor);
+ if (color.isValid()) return color.toHexString();
}
return null;
diff --git a/packages/backend/src/services/following/create.ts b/packages/backend/src/services/following/create.ts
index 7491c44f83..72c24676bb 100644
--- a/packages/backend/src/services/following/create.ts
+++ b/packages/backend/src/services/following/create.ts
@@ -67,8 +67,10 @@ export async function insertFollowingDoc(followee: { id: User['id']; host: User[
if (alreadyFollowed) return;
//#region Increment counts
- Users.increment({ id: follower.id }, 'followingCount', 1);
- Users.increment({ id: followee.id }, 'followersCount', 1);
+ await Promise.all([
+ Users.increment({ id: follower.id }, 'followingCount', 1),
+ Users.increment({ id: followee.id }, 'followersCount', 1),
+ ]);
//#endregion
//#region Update instance stats
diff --git a/packages/backend/src/services/following/delete.ts b/packages/backend/src/services/following/delete.ts
index 241f9606e5..91b5a3d61d 100644
--- a/packages/backend/src/services/following/delete.ts
+++ b/packages/backend/src/services/following/delete.ts
@@ -58,12 +58,11 @@ export default async function(follower: { id: User['id']; host: User['host']; ur
}
export async function decrementFollowing(follower: { id: User['id']; host: User['host']; }, followee: { id: User['id']; host: User['host']; }) {
- //#region Decrement following count
- Users.decrement({ id: follower.id }, 'followingCount', 1);
- //#endregion
-
- //#region Decrement followers count
- Users.decrement({ id: followee.id }, 'followersCount', 1);
+ //#region Decrement following / followers counts
+ await Promise.all([
+ Users.decrement({ id: follower.id }, 'followingCount', 1),
+ Users.decrement({ id: followee.id }, 'followersCount', 1),
+ ]);
//#endregion
//#region Update instance stats
diff --git a/packages/backend/src/services/messages/create.ts b/packages/backend/src/services/messages/create.ts
index e5cd5a30d2..e6b3204922 100644
--- a/packages/backend/src/services/messages/create.ts
+++ b/packages/backend/src/services/messages/create.ts
@@ -5,7 +5,7 @@ import { MessagingMessages, UserGroupJoinings, Mutings, Users } from '@/models/i
import { genId } from '@/misc/gen-id.js';
import { MessagingMessage } from '@/models/entities/messaging-message.js';
import { publishMessagingStream, publishMessagingIndexStream, publishMainStream, publishGroupMessagingStream } from '@/services/stream.js';
-import pushNotification from '../push-notification.js';
+import { pushNotification } from '@/services/push-notification.js';
import { Not } from 'typeorm';
import { Note } from '@/models/entities/note.js';
import renderNote from '@/remote/activitypub/renderer/note.js';
diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts
index f14bc2059b..e2bf9d5b59 100644
--- a/packages/backend/src/services/note/create.ts
+++ b/packages/backend/src/services/note/create.ts
@@ -187,6 +187,8 @@ export default async (user: { id: User['id']; username: User['username']; host:
if (data.text) {
data.text = data.text.trim();
+ } else {
+ data.text = null;
}
let tags = data.apHashtags;
@@ -310,7 +312,8 @@ export default async (user: { id: User['id']; username: User['username']; host:
endedPollNotificationQueue.add({
noteId: note.id,
}, {
- delay
+ delay,
+ removeOnComplete: true,
});
}
diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts
index ffd609dd84..4963200161 100644
--- a/packages/backend/src/services/note/delete.ts
+++ b/packages/backend/src/services/note/delete.ts
@@ -1,3 +1,4 @@
+import { Brackets, In } from 'typeorm';
import { publishNoteStream } from '@/services/stream.js';
import renderDelete from '@/remote/activitypub/renderer/delete.js';
import renderAnnounce from '@/remote/activitypub/renderer/announce.js';
@@ -5,15 +6,14 @@ import renderUndo from '@/remote/activitypub/renderer/undo.js';
import { renderActivity } from '@/remote/activitypub/renderer/index.js';
import renderTombstone from '@/remote/activitypub/renderer/tombstone.js';
import config from '@/config/index.js';
-import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js';
import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js';
import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js';
import { Notes, Users, Instances } from '@/models/index.js';
import { notesChart, perUserNotesChart, instanceChart } from '@/services/chart/index.js';
import { deliverToFollowers, deliverToUser } from '@/remote/activitypub/deliver-manager.js';
import { countSameRenotes } from '@/misc/count-same-renotes.js';
+import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js';
import { deliverToRelays } from '../relay.js';
-import { Brackets, In } from 'typeorm';
/**
* 投稿を削除します。
@@ -40,7 +40,7 @@ export default async function(user: { id: User['id']; uri: User['uri']; host: Us
//#region ローカルの投稿なら削除アクティビティを配送
if (Users.isLocalUser(user) && !note.localOnly) {
- let renote: Note | null;
+ let renote: Note | null = null;
// if deletd note is renote
if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) {
@@ -113,7 +113,7 @@ async function getMentionedRemoteUsers(note: Note) {
const uris = (JSON.parse(note.mentionedRemoteUsers) as IMentionedRemoteUsers).map(x => x.uri);
if (uris.length > 0) {
where.push(
- { uri: In(uris) }
+ { uri: In(uris) },
);
}
diff --git a/packages/backend/src/services/note/reaction/create.ts b/packages/backend/src/services/note/reaction/create.ts
index 5a0948bca9..83d302826a 100644
--- a/packages/backend/src/services/note/reaction/create.ts
+++ b/packages/backend/src/services/note/reaction/create.ts
@@ -27,6 +27,11 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
}
}
+ // check visibility
+ if (!await Notes.isVisibleForMe(note, user.id)) {
+ throw new IdentifiableError('68e9d2d1-48bf-42c2-b90a-b20e09fd3d48', 'Note not accessible for you.');
+ }
+
// TODO: cache
reaction = await toDbReaction(reaction, user.host);
diff --git a/packages/backend/src/services/push-notification.ts b/packages/backend/src/services/push-notification.ts
index 41122c92e8..5c3bafbb34 100644
--- a/packages/backend/src/services/push-notification.ts
+++ b/packages/backend/src/services/push-notification.ts
@@ -5,8 +5,15 @@ import { fetchMeta } from '@/misc/fetch-meta.js';
import { Packed } from '@/misc/schema.js';
import { getNoteSummary } from '@/misc/get-note-summary.js';
-type notificationType = 'notification' | 'unreadMessagingMessage';
-type notificationBody = Packed<'Notification'> | Packed<'MessagingMessage'>;
+// Defined also packages/sw/types.ts#L14-L21
+type pushNotificationsTypes = {
+ 'notification': Packed<'Notification'>;
+ 'unreadMessagingMessage': Packed<'MessagingMessage'>;
+ 'readNotifications': { notificationIds: string[] };
+ 'readAllNotifications': undefined;
+ 'readAllMessagingMessages': undefined;
+ 'readAllMessagingMessagesOfARoom': { userId: string } | { groupId: string };
+};
// プッシュメッセージサーバーには文字数制限があるため、内容を削減します
function truncateNotification(notification: Packed<'Notification'>): any {
@@ -17,12 +24,11 @@ function truncateNotification(notification: Packed<'Notification'>): any {
...notification.note,
// textをgetNoteSummaryしたものに置き換える
text: getNoteSummary(notification.type === 'renote' ? notification.note.renote as Packed<'Note'> : notification.note),
- ...{
- cw: undefined,
- reply: undefined,
- renote: undefined,
- user: undefined as any, // 通知を受け取ったユーザーである場合が多いのでこれも捨てる
- }
+
+ cw: undefined,
+ reply: undefined,
+ renote: undefined,
+ user: undefined as any, // 通知を受け取ったユーザーである場合が多いのでこれも捨てる
}
};
}
@@ -30,7 +36,7 @@ function truncateNotification(notification: Packed<'Notification'>): any {
return notification;
}
-export default async function(userId: string, type: notificationType, body: notificationBody) {
+export async function pushNotification<T extends keyof pushNotificationsTypes>(userId: string, type: T, body: pushNotificationsTypes[T]) {
const meta = await fetchMeta();
if (!meta.enableServiceWorker || meta.swPublicKey == null || meta.swPrivateKey == null) return;
diff --git a/packages/backend/src/services/relay.ts b/packages/backend/src/services/relay.ts
index 1ab45588da..6bc4304436 100644
--- a/packages/backend/src/services/relay.ts
+++ b/packages/backend/src/services/relay.ts
@@ -1,4 +1,4 @@
-import { createSystemUser } from './create-system-user.js';
+import { IsNull } from 'typeorm';
import { renderFollowRelay } from '@/remote/activitypub/renderer/follow-relay.js';
import { renderActivity, attachLdSignature } from '@/remote/activitypub/renderer/index.js';
import renderUndo from '@/remote/activitypub/renderer/undo.js';
@@ -8,7 +8,7 @@ import { Users, Relays } from '@/models/index.js';
import { genId } from '@/misc/gen-id.js';
import { Cache } from '@/misc/cache.js';
import { Relay } from '@/models/entities/relay.js';
-import { IsNull } from 'typeorm';
+import { createSystemUser } from './create-system-user.js';
const ACTOR_USERNAME = 'relay.actor' as const;
@@ -88,6 +88,8 @@ export async function deliverToRelays(user: { id: User['id']; host: null; }, act
}));
if (relays.length === 0) return;
+ // TODO
+ //const copy = structuredClone(activity);
const copy = JSON.parse(JSON.stringify(activity));
if (!copy.to) copy.to = ['https://www.w3.org/ns/activitystreams#Public'];