mirror of
https://git.joinfirefish.org/firefish/firefish.git
synced 2024-05-19 18:21:11 +02:00
Compare commits
8 commits
ff96c20893
...
87c9c76117
Author | SHA1 | Date | |
---|---|---|---|
87c9c76117 | |||
28b9e35f2a | |||
51f9d20073 | |||
98cc23557f | |||
e5bac649c8 | |||
38cd4bafde | |||
d880601d56 | |||
c89525d151 |
|
@ -3,7 +3,7 @@ FROM docker.io/node:20-alpine as build
|
||||||
WORKDIR /firefish
|
WORKDIR /firefish
|
||||||
|
|
||||||
# Install compilation dependencies
|
# Install compilation dependencies
|
||||||
RUN apk update && apk add --no-cache build-base linux-headers curl ca-certificates python3
|
RUN apk update && apk add --no-cache build-base linux-headers curl ca-certificates python3 perl
|
||||||
RUN curl --proto '=https' --tlsv1.2 --silent --show-error --fail https://sh.rustup.rs | sh -s -- -y
|
RUN curl --proto '=https' --tlsv1.2 --silent --show-error --fail https://sh.rustup.rs | sh -s -- -y
|
||||||
ENV PATH="/root/.cargo/bin:${PATH}"
|
ENV PATH="/root/.cargo/bin:${PATH}"
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ RUN corepack enable && corepack prepare pnpm@latest --activate && pnpm install -
|
||||||
|
|
||||||
# Copy in the rest of the rust files
|
# Copy in the rest of the rust files
|
||||||
COPY packages/backend-rs packages/backend-rs/
|
COPY packages/backend-rs packages/backend-rs/
|
||||||
|
# COPY packages/macro-rs packages/macro-rs/
|
||||||
|
|
||||||
# Compile backend-rs
|
# Compile backend-rs
|
||||||
RUN NODE_ENV='production' pnpm run --filter backend-rs build
|
RUN NODE_ENV='production' pnpm run --filter backend-rs build
|
||||||
|
|
1
packages/backend-rs/index.d.ts
vendored
1
packages/backend-rs/index.d.ts
vendored
|
@ -1183,6 +1183,7 @@ export interface PackedEmoji {
|
||||||
height: number | null
|
height: number | null
|
||||||
}
|
}
|
||||||
export function publishToBroadcastStream(emoji: PackedEmoji): void
|
export function publishToBroadcastStream(emoji: PackedEmoji): void
|
||||||
|
export function publishToGroupChatStream(groupId: string, kind: ChatEvent, object: any): void
|
||||||
export interface AbuseUserReportLike {
|
export interface AbuseUserReportLike {
|
||||||
id: string
|
id: string
|
||||||
targetUserId: string
|
targetUserId: string
|
||||||
|
|
|
@ -310,7 +310,7 @@ if (!nativeBinding) {
|
||||||
throw new Error(`Failed to load native binding`)
|
throw new Error(`Failed to load native binding`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initializeRustLogger, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToModerationStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding
|
const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initializeRustLogger, watchNote, unwatchNote, PushNotificationKind, sendPushNotification, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding
|
||||||
|
|
||||||
module.exports.SECOND = SECOND
|
module.exports.SECOND = SECOND
|
||||||
module.exports.MINUTE = MINUTE
|
module.exports.MINUTE = MINUTE
|
||||||
|
@ -373,6 +373,7 @@ module.exports.publishToChatStream = publishToChatStream
|
||||||
module.exports.ChatIndexEvent = ChatIndexEvent
|
module.exports.ChatIndexEvent = ChatIndexEvent
|
||||||
module.exports.publishToChatIndexStream = publishToChatIndexStream
|
module.exports.publishToChatIndexStream = publishToChatIndexStream
|
||||||
module.exports.publishToBroadcastStream = publishToBroadcastStream
|
module.exports.publishToBroadcastStream = publishToBroadcastStream
|
||||||
|
module.exports.publishToGroupChatStream = publishToGroupChatStream
|
||||||
module.exports.publishToModerationStream = publishToModerationStream
|
module.exports.publishToModerationStream = publishToModerationStream
|
||||||
module.exports.getTimestamp = getTimestamp
|
module.exports.getTimestamp = getTimestamp
|
||||||
module.exports.genId = genId
|
module.exports.genId = genId
|
||||||
|
|
|
@ -3,6 +3,7 @@ pub mod channel;
|
||||||
pub mod chat;
|
pub mod chat;
|
||||||
pub mod chat_index;
|
pub mod chat_index;
|
||||||
pub mod custom_emoji;
|
pub mod custom_emoji;
|
||||||
|
pub mod group_chat;
|
||||||
pub mod moderation;
|
pub mod moderation;
|
||||||
|
|
||||||
use crate::config::CONFIG;
|
use crate::config::CONFIG;
|
||||||
|
|
13
packages/backend-rs/src/service/stream/group_chat.rs
Normal file
13
packages/backend-rs/src/service/stream/group_chat.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use crate::service::stream::{chat::ChatEvent, publish_to_stream, Error, Stream};
|
||||||
|
|
||||||
|
// We want to merge `kind` and `object` into a single enum
|
||||||
|
// https://github.com/napi-rs/napi-rs/issues/2036
|
||||||
|
|
||||||
|
#[crate::export(js_name = "publishToGroupChatStream")]
|
||||||
|
pub fn publish(group_id: String, kind: ChatEvent, object: &serde_json::Value) -> Result<(), Error> {
|
||||||
|
publish_to_stream(
|
||||||
|
&Stream::GroupChat { group_id },
|
||||||
|
Some(kind.to_string()),
|
||||||
|
Some(serde_json::to_string(object)?),
|
||||||
|
)
|
||||||
|
}
|
|
@ -7,20 +7,16 @@ import probeImageSize from "probe-image-size";
|
||||||
import isSvg from "is-svg";
|
import isSvg from "is-svg";
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
import { encode } from "blurhash";
|
import { encode } from "blurhash";
|
||||||
import { inspect } from "node:util";
|
|
||||||
|
|
||||||
export type FileInfo = {
|
type FileInfo = {
|
||||||
size: number;
|
size: number;
|
||||||
md5: string;
|
md5: string;
|
||||||
type: {
|
mime: string;
|
||||||
mime: string;
|
fileExtension: string | null;
|
||||||
ext: string | null;
|
|
||||||
};
|
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
orientation?: number;
|
orientation?: number;
|
||||||
blurhash?: string;
|
blurhash?: string;
|
||||||
warnings: string[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const TYPE_OCTET_STREAM = {
|
const TYPE_OCTET_STREAM = {
|
||||||
|
@ -37,8 +33,6 @@ const TYPE_SVG = {
|
||||||
* Get file information
|
* Get file information
|
||||||
*/
|
*/
|
||||||
export async function getFileInfo(path: string): Promise<FileInfo> {
|
export async function getFileInfo(path: string): Promise<FileInfo> {
|
||||||
const warnings = [] as string[];
|
|
||||||
|
|
||||||
const size = await getFileSize(path);
|
const size = await getFileSize(path);
|
||||||
const md5 = await calcHash(path);
|
const md5 = await calcHash(path);
|
||||||
|
|
||||||
|
@ -63,14 +57,12 @@ export async function getFileInfo(path: string): Promise<FileInfo> {
|
||||||
"image/avif",
|
"image/avif",
|
||||||
].includes(type.mime)
|
].includes(type.mime)
|
||||||
) {
|
) {
|
||||||
const imageSize = await detectImageSize(path).catch((e) => {
|
const imageSize = await detectImageSize(path).catch((_) => {
|
||||||
warnings.push(`detectImageSize failed:\n${inspect(e)}`);
|
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
// うまく判定できない画像は octet-stream にする
|
// うまく判定できない画像は octet-stream にする
|
||||||
if (!imageSize) {
|
if (!imageSize) {
|
||||||
warnings.push("cannot detect image dimensions");
|
|
||||||
type = TYPE_OCTET_STREAM;
|
type = TYPE_OCTET_STREAM;
|
||||||
} else if (imageSize.wUnits === "px") {
|
} else if (imageSize.wUnits === "px") {
|
||||||
width = imageSize.width;
|
width = imageSize.width;
|
||||||
|
@ -79,11 +71,8 @@ export async function getFileInfo(path: string): Promise<FileInfo> {
|
||||||
|
|
||||||
// 制限を超えている画像は octet-stream にする
|
// 制限を超えている画像は octet-stream にする
|
||||||
if (imageSize.width > 16383 || imageSize.height > 16383) {
|
if (imageSize.width > 16383 || imageSize.height > 16383) {
|
||||||
warnings.push("image dimensions exceeds limits");
|
|
||||||
type = TYPE_OCTET_STREAM;
|
type = TYPE_OCTET_STREAM;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
warnings.push(`unsupported unit type: ${imageSize.wUnits}`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +89,7 @@ export async function getFileInfo(path: string): Promise<FileInfo> {
|
||||||
"image/avif",
|
"image/avif",
|
||||||
].includes(type.mime)
|
].includes(type.mime)
|
||||||
) {
|
) {
|
||||||
blurhash = await getBlurhash(path).catch((e) => {
|
blurhash = await getBlurhash(path).catch((_) => {
|
||||||
warnings.push(`getBlurhash failed:\n${inspect(e)}`);
|
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -109,12 +97,12 @@ export async function getFileInfo(path: string): Promise<FileInfo> {
|
||||||
return {
|
return {
|
||||||
size,
|
size,
|
||||||
md5,
|
md5,
|
||||||
type,
|
mime: type.mime,
|
||||||
|
fileExtension: type.ext,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
orientation,
|
orientation,
|
||||||
blurhash,
|
blurhash,
|
||||||
warnings,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import {
|
import { publishMainStream } from "@/services/stream.js";
|
||||||
publishMainStream,
|
|
||||||
publishGroupMessagingStream,
|
|
||||||
} from "@/services/stream.js";
|
|
||||||
import {
|
import {
|
||||||
publishToChatStream,
|
publishToChatStream,
|
||||||
|
publishToGroupChatStream,
|
||||||
publishToChatIndexStream,
|
publishToChatIndexStream,
|
||||||
sendPushNotification,
|
sendPushNotification,
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
|
@ -130,9 +128,9 @@ export async function readGroupMessagingMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish event
|
// Publish event
|
||||||
publishGroupMessagingStream(groupId, "read", {
|
publishToGroupChatStream(groupId, ChatEvent.Read, {
|
||||||
ids: reads,
|
ids: reads,
|
||||||
userId: userId,
|
userId,
|
||||||
});
|
});
|
||||||
publishToChatIndexStream(userId, ChatIndexEvent.Read, reads);
|
publishToChatIndexStream(userId, ChatIndexEvent.Read, reads);
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,10 @@ import {
|
||||||
} from "@/models/index.js";
|
} from "@/models/index.js";
|
||||||
import type { AccessToken } from "@/models/entities/access-token.js";
|
import type { AccessToken } from "@/models/entities/access-token.js";
|
||||||
import type { UserProfile } from "@/models/entities/user-profile.js";
|
import type { UserProfile } from "@/models/entities/user-profile.js";
|
||||||
import { publishGroupMessagingStream } from "@/services/stream.js";
|
|
||||||
import {
|
import {
|
||||||
publishToChannelStream,
|
publishToChannelStream,
|
||||||
publishToChatStream,
|
publishToChatStream,
|
||||||
|
publishToGroupChatStream,
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
} from "backend-rs";
|
} from "backend-rs";
|
||||||
import type { UserGroup } from "@/models/entities/user-group.js";
|
import type { UserGroup } from "@/models/entities/user-group.js";
|
||||||
|
@ -531,8 +531,8 @@ export default class Connection {
|
||||||
ChatEvent.Typing,
|
ChatEvent.Typing,
|
||||||
this.user.id,
|
this.user.id,
|
||||||
);
|
);
|
||||||
} else if (param.group) {
|
} else if (param.group != null) {
|
||||||
publishGroupMessagingStream(param.group, "typing", this.user.id);
|
publishToGroupChatStream(param.group, ChatEvent.Typing, this.user.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -477,17 +477,20 @@ export async function addFile({
|
||||||
requestHeaders = null,
|
requestHeaders = null,
|
||||||
usageHint = null,
|
usageHint = null,
|
||||||
}: AddFileArgs): Promise<DriveFile> {
|
}: AddFileArgs): Promise<DriveFile> {
|
||||||
const info = await getFileInfo(path);
|
const fileInfo = await getFileInfo(path);
|
||||||
logger.info(`${JSON.stringify(info)}`);
|
logger.info(`${JSON.stringify(fileInfo)}`);
|
||||||
|
|
||||||
// detect name
|
// detect name
|
||||||
const detectedName =
|
const detectedName =
|
||||||
name || (info.type.ext ? `untitled.${info.type.ext}` : "untitled");
|
name ||
|
||||||
|
(fileInfo.fileExtension
|
||||||
|
? `untitled.${fileInfo.fileExtension}`
|
||||||
|
: "untitled");
|
||||||
|
|
||||||
if (user && !force) {
|
if (user && !force) {
|
||||||
// Check if there is a file with the same hash
|
// Check if there is a file with the same hash
|
||||||
const much = await DriveFiles.findOneBy({
|
const much = await DriveFiles.findOneBy({
|
||||||
md5: info.md5,
|
md5: fileInfo.md5,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -515,7 +518,7 @@ export async function addFile({
|
||||||
logger.debug("drive capacity override applied");
|
logger.debug("drive capacity override applied");
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${
|
`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${
|
||||||
usage + info.size
|
usage + fileInfo.size
|
||||||
}bytes`,
|
}bytes`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -523,7 +526,7 @@ export async function addFile({
|
||||||
logger.debug(`drive usage is ${usage} (max: ${driveCapacity})`);
|
logger.debug(`drive usage is ${usage} (max: ${driveCapacity})`);
|
||||||
|
|
||||||
// If usage limit exceeded
|
// If usage limit exceeded
|
||||||
if (usage + info.size > driveCapacity) {
|
if (usage + fileInfo.size > driveCapacity) {
|
||||||
if (Users.isLocalUser(user)) {
|
if (Users.isLocalUser(user)) {
|
||||||
throw new IdentifiableError(
|
throw new IdentifiableError(
|
||||||
"c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6",
|
"c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6",
|
||||||
|
@ -533,7 +536,7 @@ export async function addFile({
|
||||||
// (アバターまたはバナーを含まず)最も古いファイルを削除する
|
// (アバターまたはバナーを含まず)最も古いファイルを削除する
|
||||||
expireOldFile(
|
expireOldFile(
|
||||||
(await Users.findOneByOrFail({ id: user.id })) as IRemoteUser,
|
(await Users.findOneByOrFail({ id: user.id })) as IRemoteUser,
|
||||||
driveCapacity - info.size,
|
driveCapacity - fileInfo.size,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -561,12 +564,12 @@ export async function addFile({
|
||||||
orientation?: number;
|
orientation?: number;
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
if (info.width) {
|
if (fileInfo.width != null && fileInfo.height != null) {
|
||||||
properties["width"] = info.width;
|
properties.width = fileInfo.width;
|
||||||
properties["height"] = info.height;
|
properties.height = fileInfo.height;
|
||||||
}
|
}
|
||||||
if (info.orientation != null) {
|
if (fileInfo.orientation != null) {
|
||||||
properties["orientation"] = info.orientation;
|
properties.orientation = fileInfo.orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const profile = user
|
const profile = user
|
||||||
|
@ -584,7 +587,7 @@ export async function addFile({
|
||||||
file.folderId = folder != null ? folder.id : null;
|
file.folderId = folder != null ? folder.id : null;
|
||||||
file.comment = comment;
|
file.comment = comment;
|
||||||
file.properties = properties;
|
file.properties = properties;
|
||||||
file.blurhash = info.blurhash || null;
|
file.blurhash = fileInfo.blurhash ?? null;
|
||||||
file.isLink = isLink;
|
file.isLink = isLink;
|
||||||
file.requestIp = requestIp;
|
file.requestIp = requestIp;
|
||||||
file.requestHeaders = requestHeaders;
|
file.requestHeaders = requestHeaders;
|
||||||
|
@ -617,9 +620,9 @@ export async function addFile({
|
||||||
if (isLink) {
|
if (isLink) {
|
||||||
try {
|
try {
|
||||||
file.size = 0;
|
file.size = 0;
|
||||||
file.md5 = info.md5;
|
file.md5 = fileInfo.md5;
|
||||||
file.name = detectedName;
|
file.name = detectedName;
|
||||||
file.type = info.type.mime;
|
file.type = fileInfo.mime;
|
||||||
file.storedInternal = false;
|
file.storedInternal = false;
|
||||||
|
|
||||||
file = await DriveFiles.insert(file).then((x) =>
|
file = await DriveFiles.insert(file).then((x) =>
|
||||||
|
@ -644,9 +647,9 @@ export async function addFile({
|
||||||
file,
|
file,
|
||||||
path,
|
path,
|
||||||
detectedName,
|
detectedName,
|
||||||
info.type.mime,
|
fileInfo.mime,
|
||||||
info.md5,
|
fileInfo.md5,
|
||||||
info.size,
|
fileInfo.size,
|
||||||
usageHint,
|
usageHint,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
genId,
|
genId,
|
||||||
sendPushNotification,
|
sendPushNotification,
|
||||||
publishToChatStream,
|
publishToChatStream,
|
||||||
|
publishToGroupChatStream,
|
||||||
publishToChatIndexStream,
|
publishToChatIndexStream,
|
||||||
toPuny,
|
toPuny,
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
|
@ -18,10 +19,7 @@ import {
|
||||||
PushNotificationKind,
|
PushNotificationKind,
|
||||||
} from "backend-rs";
|
} from "backend-rs";
|
||||||
import type { MessagingMessage } from "@/models/entities/messaging-message.js";
|
import type { MessagingMessage } from "@/models/entities/messaging-message.js";
|
||||||
import {
|
import { publishMainStream } from "@/services/stream.js";
|
||||||
publishMainStream,
|
|
||||||
publishGroupMessagingStream,
|
|
||||||
} from "@/services/stream.js";
|
|
||||||
import { Not } from "typeorm";
|
import { Not } from "typeorm";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import renderNote from "@/remote/activitypub/renderer/note.js";
|
import renderNote from "@/remote/activitypub/renderer/note.js";
|
||||||
|
@ -87,11 +85,11 @@ export async function createMessage(
|
||||||
);
|
);
|
||||||
publishMainStream(recipientUser.id, "messagingMessage", messageObj);
|
publishMainStream(recipientUser.id, "messagingMessage", messageObj);
|
||||||
}
|
}
|
||||||
} else if (recipientGroup) {
|
} else if (recipientGroup != null) {
|
||||||
// グループのストリーム
|
// group's stream
|
||||||
publishGroupMessagingStream(recipientGroup.id, "message", messageObj);
|
publishToGroupChatStream(recipientGroup.id, ChatEvent.Message, messageObj);
|
||||||
|
|
||||||
// メンバーのストリーム
|
// member's stream
|
||||||
const joinings = await UserGroupJoinings.findBy({
|
const joinings = await UserGroupJoinings.findBy({
|
||||||
userGroupId: recipientGroup.id,
|
userGroupId: recipientGroup.id,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import { config } from "@/config.js";
|
import { config } from "@/config.js";
|
||||||
import { MessagingMessages, Users } from "@/models/index.js";
|
import { MessagingMessages, Users } from "@/models/index.js";
|
||||||
import type { MessagingMessage } from "@/models/entities/messaging-message.js";
|
import type { MessagingMessage } from "@/models/entities/messaging-message.js";
|
||||||
import { publishGroupMessagingStream } from "@/services/stream.js";
|
import {
|
||||||
import { publishToChatStream, ChatEvent } from "backend-rs";
|
publishToChatStream,
|
||||||
|
publishToGroupChatStream,
|
||||||
|
ChatEvent,
|
||||||
|
} from "backend-rs";
|
||||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||||
import renderDelete from "@/remote/activitypub/renderer/delete.js";
|
import renderDelete from "@/remote/activitypub/renderer/delete.js";
|
||||||
import renderTombstone from "@/remote/activitypub/renderer/tombstone.js";
|
import renderTombstone from "@/remote/activitypub/renderer/tombstone.js";
|
||||||
|
@ -42,7 +45,7 @@ async function postDeleteMessage(message: MessagingMessage) {
|
||||||
);
|
);
|
||||||
deliver(user, activity, recipient.inbox);
|
deliver(user, activity, recipient.inbox);
|
||||||
}
|
}
|
||||||
} else if (message.groupId) {
|
} else if (message.groupId != null) {
|
||||||
publishGroupMessagingStream(message.groupId, "deleted", message.id);
|
publishToGroupChatStream(message.groupId, ChatEvent.Deleted, message.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { redisClient } from "@/db/redis.js";
|
||||||
import type { User } from "@/models/entities/user.js";
|
import type { User } from "@/models/entities/user.js";
|
||||||
import type { Note } from "@/models/entities/note.js";
|
import type { Note } from "@/models/entities/note.js";
|
||||||
import type { UserList } from "@/models/entities/user-list.js";
|
import type { UserList } from "@/models/entities/user-list.js";
|
||||||
import type { UserGroup } from "@/models/entities/user-group.js";
|
// import type { UserGroup } from "@/models/entities/user-group.js";
|
||||||
import { config } from "@/config.js";
|
import { config } from "@/config.js";
|
||||||
// import type { Antenna } from "@/models/entities/antenna.js";
|
// import type { Antenna } from "@/models/entities/antenna.js";
|
||||||
// import type { Channel } from "@/models/entities/channel.js";
|
// import type { Channel } from "@/models/entities/channel.js";
|
||||||
|
@ -13,7 +13,7 @@ import type {
|
||||||
// BroadcastTypes,
|
// BroadcastTypes,
|
||||||
// ChannelStreamTypes,
|
// ChannelStreamTypes,
|
||||||
DriveStreamTypes,
|
DriveStreamTypes,
|
||||||
GroupMessagingStreamTypes,
|
// GroupMessagingStreamTypes,
|
||||||
InternalStreamTypes,
|
InternalStreamTypes,
|
||||||
MainStreamTypes,
|
MainStreamTypes,
|
||||||
// MessagingIndexStreamTypes,
|
// MessagingIndexStreamTypes,
|
||||||
|
@ -163,19 +163,20 @@ class Publisher {
|
||||||
// );
|
// );
|
||||||
// };
|
// };
|
||||||
|
|
||||||
public publishGroupMessagingStream = <
|
/* ported to backend-rs */
|
||||||
K extends keyof GroupMessagingStreamTypes,
|
// public publishGroupMessagingStream = <
|
||||||
>(
|
// K extends keyof GroupMessagingStreamTypes,
|
||||||
groupId: UserGroup["id"],
|
// >(
|
||||||
type: K,
|
// groupId: UserGroup["id"],
|
||||||
value?: GroupMessagingStreamTypes[K],
|
// type: K,
|
||||||
): void => {
|
// value?: GroupMessagingStreamTypes[K],
|
||||||
this.publish(
|
// ): void => {
|
||||||
`messagingStream:${groupId}`,
|
// this.publish(
|
||||||
type,
|
// `messagingStream:${groupId}`,
|
||||||
typeof value === "undefined" ? null : value,
|
// type,
|
||||||
);
|
// typeof value === "undefined" ? null : value,
|
||||||
};
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
/* ported to backend-rs */
|
/* ported to backend-rs */
|
||||||
// public publishMessagingIndexStream = <
|
// public publishMessagingIndexStream = <
|
||||||
|
@ -225,7 +226,6 @@ export const publishNotesStream = publisher.publishNotesStream;
|
||||||
export const publishUserListStream = publisher.publishUserListStream;
|
export const publishUserListStream = publisher.publishUserListStream;
|
||||||
// export const publishAntennaStream = publisher.publishAntennaStream;
|
// export const publishAntennaStream = publisher.publishAntennaStream;
|
||||||
// export const publishMessagingStream = publisher.publishMessagingStream;
|
// export const publishMessagingStream = publisher.publishMessagingStream;
|
||||||
export const publishGroupMessagingStream =
|
// export const publishGroupMessagingStream = publisher.publishGroupMessagingStream;
|
||||||
publisher.publishGroupMessagingStream;
|
|
||||||
// export const publishMessagingIndexStream = publisher.publishMessagingIndexStream;
|
// export const publishMessagingIndexStream = publisher.publishMessagingIndexStream;
|
||||||
// export const publishAdminStream = publisher.publishAdminStream;
|
// export const publishAdminStream = publisher.publishAdminStream;
|
||||||
|
|
|
@ -379,6 +379,7 @@ export function inputText(props: {
|
||||||
default?: string | null;
|
default?: string | null;
|
||||||
minLength?: number;
|
minLength?: number;
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
|
isPlaintext?: boolean;
|
||||||
}): Promise<
|
}): Promise<
|
||||||
| { canceled: true; result?: undefined }
|
| { canceled: true; result?: undefined }
|
||||||
| {
|
| {
|
||||||
|
@ -400,6 +401,7 @@ export function inputText(props: {
|
||||||
minLength: props.minLength,
|
minLength: props.minLength,
|
||||||
maxLength: props.maxLength,
|
maxLength: props.maxLength,
|
||||||
},
|
},
|
||||||
|
isPlaintext: props.isPlaintext,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
done: (result) => {
|
done: (result) => {
|
||||||
|
|
|
@ -20,6 +20,8 @@ if (isSignedIn(me)) {
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
type: "question",
|
type: "question",
|
||||||
text: i18n.ts.useThisAccountConfirm,
|
text: i18n.ts.useThisAccountConfirm,
|
||||||
|
okText: i18n.ts.yes,
|
||||||
|
cancelText: i18n.ts.no,
|
||||||
});
|
});
|
||||||
|
|
||||||
// use the current account
|
// use the current account
|
||||||
|
@ -32,6 +34,7 @@ if (isSignedIn(me)) {
|
||||||
// Otherwise ask the user what the other account ID is
|
// Otherwise ask the user what the other account ID is
|
||||||
const remoteAccountId = await os.inputText({
|
const remoteAccountId = await os.inputText({
|
||||||
text: i18n.ts.inputAccountId,
|
text: i18n.ts.inputAccountId,
|
||||||
|
isPlaintext: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// If the user do not want enter uri, the user will be redirected to the user page.
|
// If the user do not want enter uri, the user will be redirected to the user page.
|
||||||
|
|
Loading…
Reference in a new issue