Merge branch 'develop' into refactor/push-notification
This commit is contained in:
commit
d8a6631f16
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,6 @@ napi-derive = "2.16.2"
|
|||
napi-build = "2.1.3"
|
||||
|
||||
argon2 = "0.5.3"
|
||||
async-trait = "0.1.80"
|
||||
basen = "0.1.0"
|
||||
bcrypt = "0.15.1"
|
||||
cfg-if = "1.0.0"
|
||||
|
@ -19,9 +18,7 @@ convert_case = "0.6.0"
|
|||
cuid2 = "0.1.2"
|
||||
emojis = "0.6.1"
|
||||
idna = "0.5.0"
|
||||
jsonschema = "0.17.1"
|
||||
once_cell = "1.19.0"
|
||||
parse-display = "0.9.0"
|
||||
pretty_assertions = "1.4.0"
|
||||
proc-macro2 = "1.0.79"
|
||||
quote = "1.0.36"
|
||||
|
@ -29,7 +26,6 @@ rand = "0.8.5"
|
|||
redis = "0.25.3"
|
||||
regex = "1.10.4"
|
||||
rmp-serde = "1.2.0"
|
||||
schemars = "0.8.16"
|
||||
sea-orm = "0.12.15"
|
||||
serde = "1.0.197"
|
||||
serde_json = "1.0.115"
|
||||
|
|
|
@ -18,7 +18,6 @@ napi = { workspace = true, optional = true, default-features = false, features =
|
|||
napi-derive = { workspace = true, optional = true }
|
||||
|
||||
argon2 = { workspace = true, features = ["std"] }
|
||||
async-trait = { workspace = true }
|
||||
basen = { workspace = true }
|
||||
bcrypt = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
|
@ -26,14 +25,11 @@ chrono = { workspace = true }
|
|||
cuid2 = { workspace = true }
|
||||
emojis = { workspace = true }
|
||||
idna = { workspace = true }
|
||||
jsonschema = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
parse-display = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
redis = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
rmp-serde = { workspace = true }
|
||||
schemars = { workspace = true, features = ["chrono"] }
|
||||
sea-orm = { workspace = true, features = ["sqlx-postgres", "runtime-tokio-rustls"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
@ -1129,6 +1129,13 @@ export enum PushNotificationKind {
|
|||
ReadAllNotifications = 'readAllNotifications'
|
||||
}
|
||||
export function sendPushNotification(receiverUserId: string, kind: PushNotificationKind, content: any): Promise<void>
|
||||
export enum ChatEvent {
|
||||
Message = 'message',
|
||||
Read = 'read',
|
||||
Deleted = 'deleted',
|
||||
Typing = 'typing'
|
||||
}
|
||||
export function publishToChatStream(senderUserId: string, receiverUserId: string, kind: ChatEvent, object: any): void
|
||||
/** Initializes Cuid2 generator. Must be called before any [create_id]. */
|
||||
export function initIdGenerator(length: number, fingerprint: string): void
|
||||
export function getTimestamp(id: string): number
|
||||
|
|
|
@ -310,7 +310,7 @@ if (!nativeBinding) {
|
|||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, PushNotificationKind, sendPushNotification, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding
|
||||
const { loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, PushNotificationKind, sendPushNotification, ChatEvent, publishToChatStream, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding
|
||||
|
||||
module.exports.loadEnv = loadEnv
|
||||
module.exports.loadConfig = loadConfig
|
||||
|
@ -355,6 +355,8 @@ module.exports.UserProfileFfvisibilityEnum = UserProfileFfvisibilityEnum
|
|||
module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum
|
||||
module.exports.PushNotificationKind = PushNotificationKind
|
||||
module.exports.sendPushNotification = sendPushNotification
|
||||
module.exports.ChatEvent = ChatEvent
|
||||
module.exports.publishToChatStream = publishToChatStream
|
||||
module.exports.initIdGenerator = initIdGenerator
|
||||
module.exports.getTimestamp = getTimestamp
|
||||
module.exports.genId = genId
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
#[error("Failed to parse string: {0}")]
|
||||
ParseError(#[from] parse_display::ParseError),
|
||||
#[error("Database error: {0}")]
|
||||
DbError(#[from] sea_orm::DbErr),
|
||||
#[error("Requested entity not found")]
|
||||
NotFound,
|
||||
}
|
|
@ -1,4 +1 @@
|
|||
pub mod entity;
|
||||
pub mod error;
|
||||
// pub mod repository;
|
||||
pub mod schema;
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
use async_trait::async_trait;
|
||||
use schemars::JsonSchema;
|
||||
|
||||
use super::error::Error;
|
||||
|
||||
/// Repositories have a packer that converts a database model to its
|
||||
/// corresponding API schema.
|
||||
#[async_trait]
|
||||
pub trait Repository<T: JsonSchema> {
|
||||
async fn pack(self) -> Result<T, Error>;
|
||||
/// Retrieves one model by its id and pack it.
|
||||
async fn pack_by_id(id: String) -> Result<T, Error>;
|
||||
}
|
||||
|
||||
mod macros {
|
||||
/// Provides the default implementation of
|
||||
/// [crate::model::repository::Repository::pack_by_id].
|
||||
macro_rules! impl_pack_by_id {
|
||||
($a:ty, $b:ident) => {
|
||||
match <$a>::find_by_id($b)
|
||||
.one(crate::database::get_database()?)
|
||||
.await?
|
||||
{
|
||||
None => Err(Error::NotFound),
|
||||
Some(m) => m.pack().await,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use impl_pack_by_id;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
use jsonschema::JSONSchema;
|
||||
use schemars::{schema_for, JsonSchema};
|
||||
|
||||
/// Structs of schema defitions implement this trait in order to
|
||||
/// provide the JSON Schema validator [`jsonschema::JSONSchema`].
|
||||
pub trait Schema<T: JsonSchema> {
|
||||
/// Returns the validator of [JSON Schema Draft
|
||||
/// 7](https://json-schema.org/specification-links.html#draft-7) with the
|
||||
/// default settings of [`schemars::gen::SchemaSettings`].
|
||||
fn validator() -> JSONSchema {
|
||||
let root = schema_for!(T);
|
||||
let schema = serde_json::to_value(&root).expect("Schema definition invalid");
|
||||
JSONSchema::options()
|
||||
.with_draft(jsonschema::Draft::Draft7)
|
||||
.compile(&schema)
|
||||
.expect("Unable to compile schema")
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
pub mod antenna;
|
||||
pub mod chat;
|
||||
|
||||
use crate::config::CONFIG;
|
||||
use crate::database::redis_conn;
|
||||
|
@ -51,7 +52,7 @@ pub enum Error {
|
|||
|
||||
pub fn publish_to_stream(
|
||||
stream: &Stream,
|
||||
kind: Option<&str>,
|
||||
kind: Option<String>,
|
||||
value: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
let message = if let Some(kind) = kind {
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::service::stream::{publish_to_stream, Error, Stream};
|
|||
pub fn publish(antenna_id: String, note: ¬e::Model) -> Result<(), Error> {
|
||||
publish_to_stream(
|
||||
&Stream::Antenna { antenna_id },
|
||||
Some("note"),
|
||||
Some("note".to_string()),
|
||||
Some(serde_json::to_string(note)?),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
use crate::service::stream::{publish_to_stream, Error, Stream};
|
||||
|
||||
#[derive(strum::Display)]
|
||||
#[crate::export(string_enum = "camelCase")]
|
||||
pub enum ChatEvent {
|
||||
#[strum(serialize = "message")]
|
||||
Message,
|
||||
#[strum(serialize = "read")]
|
||||
Read,
|
||||
#[strum(serialize = "deleted")]
|
||||
Deleted,
|
||||
#[strum(serialize = "typing")]
|
||||
Typing,
|
||||
}
|
||||
|
||||
#[crate::export(js_name = "publishToChatStream")]
|
||||
pub fn publish(
|
||||
sender_user_id: String,
|
||||
receiver_user_id: String,
|
||||
kind: ChatEvent,
|
||||
object: &serde_json::Value, // TODO?: change this to enum
|
||||
) -> Result<(), Error> {
|
||||
publish_to_stream(
|
||||
&Stream::Chat {
|
||||
sender_user_id,
|
||||
receiver_user_id,
|
||||
},
|
||||
Some(kind.to_string()),
|
||||
Some(serde_json::to_string(object)?),
|
||||
)
|
||||
}
|
|
@ -2,7 +2,7 @@ import {
|
|||
publishMainStream,
|
||||
publishGroupMessagingStream,
|
||||
} from "@/services/stream.js";
|
||||
import { publishMessagingStream } from "@/services/stream.js";
|
||||
import { publishToChatStream, ChatEvent } from "backend-rs";
|
||||
import { publishMessagingIndexStream } from "@/services/stream.js";
|
||||
import { sendPushNotification, PushNotificationKind } from "backend-rs";
|
||||
import type { User, IRemoteUser } from "@/models/entities/user.js";
|
||||
|
@ -54,7 +54,7 @@ export async function readUserMessagingMessage(
|
|||
);
|
||||
|
||||
// Publish event
|
||||
publishMessagingStream(otherpartyId, userId, "read", messageIds);
|
||||
publishToChatStream(otherpartyId, userId, ChatEvent.Read, messageIds);
|
||||
publishMessagingIndexStream(userId, "read", messageIds);
|
||||
|
||||
if (!(await Users.getHasUnreadMessagingMessage(userId))) {
|
||||
|
|
|
@ -4,7 +4,6 @@ import readNote from "@/services/note/read.js";
|
|||
import type { User } from "@/models/entities/user.js";
|
||||
import type { Channel as ChannelModel } from "@/models/entities/channel.js";
|
||||
import {
|
||||
Users,
|
||||
Followings,
|
||||
Mutings,
|
||||
RenoteMutings,
|
||||
|
@ -18,8 +17,8 @@ import type { UserProfile } from "@/models/entities/user-profile.js";
|
|||
import {
|
||||
publishChannelStream,
|
||||
publishGroupMessagingStream,
|
||||
publishMessagingStream,
|
||||
} from "@/services/stream.js";
|
||||
import { publishToChatStream, ChatEvent } from "backend-rs";
|
||||
import type { UserGroup } from "@/models/entities/user-group.js";
|
||||
import type { Packed } from "@/misc/schema.js";
|
||||
import { readNotification } from "@/server/api/common/read-notification.js";
|
||||
|
@ -525,10 +524,10 @@ export default class Connection {
|
|||
}) {
|
||||
if (this.user) {
|
||||
if (param.partner) {
|
||||
publishMessagingStream(
|
||||
publishToChatStream(
|
||||
param.partner,
|
||||
this.user.id,
|
||||
"typing",
|
||||
ChatEvent.Typing,
|
||||
this.user.id,
|
||||
);
|
||||
} else if (param.group) {
|
||||
|
|
|
@ -10,12 +10,13 @@ import {
|
|||
import {
|
||||
genId,
|
||||
sendPushNotification,
|
||||
publishToChatStream,
|
||||
toPuny,
|
||||
PushNotificationKind,
|
||||
ChatEvent
|
||||
} from "backend-rs";
|
||||
import type { MessagingMessage } from "@/models/entities/messaging-message.js";
|
||||
import {
|
||||
publishMessagingStream,
|
||||
publishMessagingIndexStream,
|
||||
publishMainStream,
|
||||
publishGroupMessagingStream,
|
||||
|
@ -56,10 +57,10 @@ export async function createMessage(
|
|||
if (recipientUser) {
|
||||
if (Users.isLocalUser(user)) {
|
||||
// 自分のストリーム
|
||||
publishMessagingStream(
|
||||
publishToChatStream(
|
||||
message.userId,
|
||||
recipientUser.id,
|
||||
"message",
|
||||
ChatEvent.Message,
|
||||
messageObj,
|
||||
);
|
||||
publishMessagingIndexStream(message.userId, "message", messageObj);
|
||||
|
@ -68,10 +69,10 @@ export async function createMessage(
|
|||
|
||||
if (Users.isLocalUser(recipientUser)) {
|
||||
// 相手のストリーム
|
||||
publishMessagingStream(
|
||||
publishToChatStream(
|
||||
recipientUser.id,
|
||||
message.userId,
|
||||
"message",
|
||||
ChatEvent.Message,
|
||||
messageObj,
|
||||
);
|
||||
publishMessagingIndexStream(recipientUser.id, "message", messageObj);
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import { config } from "@/config.js";
|
||||
import { MessagingMessages, Users } from "@/models/index.js";
|
||||
import type { MessagingMessage } from "@/models/entities/messaging-message.js";
|
||||
import {
|
||||
publishGroupMessagingStream,
|
||||
publishMessagingStream,
|
||||
} from "@/services/stream.js";
|
||||
import { publishGroupMessagingStream } from "@/services/stream.js";
|
||||
import { publishToChatStream, ChatEvent } from "backend-rs";
|
||||
import { renderActivity } from "@/remote/activitypub/renderer/index.js";
|
||||
import renderDelete from "@/remote/activitypub/renderer/delete.js";
|
||||
import renderTombstone from "@/remote/activitypub/renderer/tombstone.js";
|
||||
|
@ -21,17 +19,17 @@ async function postDeleteMessage(message: MessagingMessage) {
|
|||
const recipient = await Users.findOneByOrFail({ id: message.recipientId });
|
||||
|
||||
if (Users.isLocalUser(user))
|
||||
publishMessagingStream(
|
||||
publishToChatStream(
|
||||
message.userId,
|
||||
message.recipientId,
|
||||
"deleted",
|
||||
ChatEvent.Deleted,
|
||||
message.id,
|
||||
);
|
||||
if (Users.isLocalUser(recipient))
|
||||
publishMessagingStream(
|
||||
publishToChatStream(
|
||||
message.recipientId,
|
||||
message.userId,
|
||||
"deleted",
|
||||
ChatEvent.Deleted,
|
||||
message.id,
|
||||
);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import type {
|
|||
InternalStreamTypes,
|
||||
MainStreamTypes,
|
||||
MessagingIndexStreamTypes,
|
||||
MessagingStreamTypes,
|
||||
// MessagingStreamTypes,
|
||||
NoteStreamTypes,
|
||||
UserListStreamTypes,
|
||||
UserStreamTypes,
|
||||
|
@ -147,18 +147,19 @@ class Publisher {
|
|||
// );
|
||||
// };
|
||||
|
||||
public publishMessagingStream = <K extends keyof MessagingStreamTypes>(
|
||||
userId: User["id"],
|
||||
otherpartyId: User["id"],
|
||||
type: K,
|
||||
value?: MessagingStreamTypes[K],
|
||||
): void => {
|
||||
this.publish(
|
||||
`messagingStream:${userId}-${otherpartyId}`,
|
||||
type,
|
||||
typeof value === "undefined" ? null : value,
|
||||
);
|
||||
};
|
||||
/* ported to backend-rs */
|
||||
// public publishMessagingStream = <K extends keyof MessagingStreamTypes>(
|
||||
// userId: User["id"],
|
||||
// otherpartyId: User["id"],
|
||||
// type: K,
|
||||
// value?: MessagingStreamTypes[K],
|
||||
// ): void => {
|
||||
// this.publish(
|
||||
// `messagingStream:${userId}-${otherpartyId}`,
|
||||
// type,
|
||||
// typeof value === "undefined" ? null : value,
|
||||
// );
|
||||
// };
|
||||
|
||||
public publishGroupMessagingStream = <
|
||||
K extends keyof GroupMessagingStreamTypes,
|
||||
|
@ -219,7 +220,7 @@ export const publishNotesStream = publisher.publishNotesStream;
|
|||
export const publishChannelStream = publisher.publishChannelStream;
|
||||
export const publishUserListStream = publisher.publishUserListStream;
|
||||
// export const publishAntennaStream = publisher.publishAntennaStream;
|
||||
export const publishMessagingStream = publisher.publishMessagingStream;
|
||||
// export const publishMessagingStream = publisher.publishMessagingStream;
|
||||
export const publishGroupMessagingStream =
|
||||
publisher.publishGroupMessagingStream;
|
||||
export const publishMessagingIndexStream =
|
||||
|
|
Loading…
Reference in New Issue