2023-07-19 16:35:47 +02:00
|
|
|
import config from "@/config/index.js";
|
2023-07-24 18:23:57 +02:00
|
|
|
import type { PopulatedEmoji } from "@/misc/populate-emojis.js";
|
2023-07-25 13:28:08 +02:00
|
|
|
import type { Note } from "@/models/entities/note.js";
|
2023-07-24 18:23:57 +02:00
|
|
|
import type { NoteReaction } from "@/models/entities/note-reaction.js";
|
|
|
|
import { Client, types } from "cassandra-driver";
|
2023-07-27 00:59:23 +02:00
|
|
|
import { noteVisibilities } from "@/types.js";
|
2023-07-19 16:35:47 +02:00
|
|
|
|
|
|
|
function newClient(): Client | null {
|
|
|
|
if (!config.scylla) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Client({
|
|
|
|
contactPoints: config.scylla.nodes,
|
2023-07-24 11:35:44 +02:00
|
|
|
localDataCenter: config.scylla.localDataCentre,
|
2023-07-19 16:35:47 +02:00
|
|
|
keyspace: config.scylla.keyspace,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
export const scyllaClient = newClient();
|
|
|
|
|
|
|
|
export const prepared = {
|
2023-07-24 11:35:44 +02:00
|
|
|
note: {
|
2023-07-19 16:35:47 +02:00
|
|
|
insert: `INSERT INTO note (
|
2023-07-24 11:35:44 +02:00
|
|
|
"createdAtDate",
|
|
|
|
"createdAt",
|
|
|
|
"id",
|
|
|
|
"visibility",
|
|
|
|
"content",
|
|
|
|
"name",
|
|
|
|
"cw",
|
|
|
|
"localOnly",
|
|
|
|
"renoteCount",
|
|
|
|
"repliesCount",
|
|
|
|
"uri",
|
|
|
|
"url",
|
|
|
|
"score",
|
|
|
|
"files",
|
2023-07-25 13:28:08 +02:00
|
|
|
"visibleUserIds",
|
2023-07-24 11:35:44 +02:00
|
|
|
"mentions",
|
|
|
|
"emojis",
|
|
|
|
"tags",
|
|
|
|
"hasPoll",
|
|
|
|
"threadId",
|
|
|
|
"channelId",
|
|
|
|
"channelName",
|
|
|
|
"userId",
|
|
|
|
"replyId",
|
|
|
|
"renoteId",
|
|
|
|
"reactions",
|
|
|
|
"noteEdit",
|
|
|
|
"updatedAt"
|
2023-07-19 16:35:47 +02:00
|
|
|
)
|
|
|
|
VALUES
|
2023-07-25 13:28:08 +02:00
|
|
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
2023-07-19 16:35:47 +02:00
|
|
|
select: {
|
2023-07-24 18:23:57 +02:00
|
|
|
byDate: `SELECT * FROM note WHERE "createdAtDate" IN ?`,
|
2023-07-24 13:52:35 +02:00
|
|
|
byId: `SELECT * FROM note WHERE "id" IN ?`,
|
2023-07-24 18:23:57 +02:00
|
|
|
byUri: `SELECT * FROM note WHERE "uri" IN ?`,
|
|
|
|
byUrl: `SELECT * FROM note WHERE "url" IN ?`,
|
|
|
|
byUserId: `SELECT * FROM note_by_userid WHERE "userId" IN ?`,
|
2023-07-19 16:35:47 +02:00
|
|
|
},
|
2023-07-25 13:28:08 +02:00
|
|
|
delete: `DELETE FROM note WHERE "createdAtDate" = ? AND "createdAt" = ? AND "id" = ?`,
|
2023-07-24 11:35:44 +02:00
|
|
|
update: {
|
2023-07-25 13:28:08 +02:00
|
|
|
renoteCount: `UPDATE note SET
|
|
|
|
"renoteCount" = ?,
|
|
|
|
"score" = ?
|
|
|
|
WHERE "createdAtDate" = ? AND "createdAt" = ? AND "id" = ? IF EXISTS`,
|
|
|
|
reactions: `UPDATE note SET
|
|
|
|
"emojis" = ?,
|
|
|
|
"reactions" = ?,
|
|
|
|
"score" = ?
|
|
|
|
WHERE "createdAtDate" = ? AND "createdAt" = ? AND "id" = ? IF EXISTS`,
|
2023-07-24 13:52:35 +02:00
|
|
|
},
|
2023-07-19 16:35:47 +02:00
|
|
|
},
|
2023-07-24 11:35:44 +02:00
|
|
|
reaction: {
|
2023-07-24 13:52:35 +02:00
|
|
|
insert: `INSERT INTO reaction
|
|
|
|
("id", "noteId", "userId", "reaction", "emoji", "createdAt")
|
|
|
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
2023-07-24 18:23:57 +02:00
|
|
|
select: {
|
|
|
|
byNoteId: `SELECT * FROM reaction WHERE "noteId" IN ?`,
|
|
|
|
byUserId: `SELECT * FROM reaction_by_userid WHERE "userId" IN ?`,
|
|
|
|
byNoteAndUser: `SELECT * FROM reaction WHERE "noteId" = ? AND "userId" = ?`,
|
|
|
|
byId: `SELECT * FROM reaction WHERE "id" IN ?`,
|
|
|
|
},
|
|
|
|
delete: `DELETE FROM reaction WHERE "noteId" = ? AND "userId" = ?`,
|
2023-07-24 11:35:44 +02:00
|
|
|
},
|
|
|
|
};
|
2023-07-24 04:29:38 +02:00
|
|
|
|
|
|
|
export interface ScyllaDriveFile {
|
|
|
|
id: string;
|
|
|
|
type: string;
|
|
|
|
createdAt: Date;
|
|
|
|
name: string;
|
|
|
|
comment: string | null;
|
|
|
|
blurhash: string | null;
|
|
|
|
url: string;
|
|
|
|
thumbnailUrl: string;
|
|
|
|
isSensitive: boolean;
|
|
|
|
isLink: boolean;
|
|
|
|
md5: string;
|
|
|
|
size: number;
|
|
|
|
}
|
2023-07-24 18:23:57 +02:00
|
|
|
|
2023-07-25 13:28:08 +02:00
|
|
|
export interface ScyllaNoteEditHistory {
|
|
|
|
content: string;
|
|
|
|
cw: string;
|
|
|
|
files: ScyllaDriveFile[];
|
|
|
|
updatedAt: Date;
|
|
|
|
}
|
|
|
|
|
2023-07-27 00:59:23 +02:00
|
|
|
export type ScyllaNote = Note & {
|
2023-07-25 13:28:08 +02:00
|
|
|
createdAtDate: Date;
|
2023-07-27 00:59:23 +02:00
|
|
|
createdAt: Note["createdAt"];
|
|
|
|
id: Note["id"];
|
|
|
|
visibility: Note["visibility"];
|
|
|
|
text: Note["text"];
|
|
|
|
name: Note["name"];
|
|
|
|
cw: Note["cw"];
|
|
|
|
localOnly: Note["localOnly"];
|
|
|
|
renoteCount: Note["renoteCount"];
|
|
|
|
repliesCount: Note["repliesCount"];
|
|
|
|
uri: Note["uri"];
|
|
|
|
url: Note["url"];
|
|
|
|
score: Note["score"];
|
2023-07-25 13:28:08 +02:00
|
|
|
files: ScyllaDriveFile[];
|
2023-07-27 00:59:23 +02:00
|
|
|
fileIds: Note["fileIds"];
|
|
|
|
attachedFileTypes: Note["attachedFileTypes"];
|
|
|
|
visibleUserIds: Note["visibleUserIds"];
|
|
|
|
mentions: Note["mentions"];
|
|
|
|
emojis: Note["emojis"];
|
|
|
|
tags: Note["tags"];
|
|
|
|
hasPoll: Note["hasPoll"];
|
|
|
|
threadId: Note["threadId"];
|
|
|
|
channelId: Note["channelId"];
|
2023-07-25 13:28:08 +02:00
|
|
|
channelName: string;
|
2023-07-27 00:59:23 +02:00
|
|
|
userId: Note["userId"];
|
|
|
|
replyId: Note["replyId"];
|
|
|
|
renoteId: Note["renoteId"];
|
|
|
|
reactions: Note["reactions"];
|
2023-07-25 13:28:08 +02:00
|
|
|
noteEdit: ScyllaNoteEditHistory[];
|
2023-07-27 00:59:23 +02:00
|
|
|
updatedAt: Note["updatedAt"];
|
2023-07-25 13:28:08 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export function parseScyllaNote(row: types.Row): ScyllaNote {
|
|
|
|
const files: ScyllaDriveFile[] = row.get("files");
|
|
|
|
return {
|
|
|
|
createdAtDate: row.get("createdAtDate"),
|
|
|
|
createdAt: row.get("createdAt"),
|
|
|
|
id: row.get("id"),
|
|
|
|
visibility: row.get("visibility"),
|
|
|
|
text: row.get("content"),
|
|
|
|
name: row.get("name"),
|
|
|
|
cw: row.get("cw"),
|
|
|
|
localOnly: row.get("localOnly"),
|
|
|
|
renoteCount: row.get("renoteCount"),
|
|
|
|
repliesCount: row.get("repliesCount"),
|
|
|
|
uri: row.get("uri"),
|
|
|
|
url: row.get("url"),
|
|
|
|
score: row.get("score"),
|
|
|
|
files,
|
|
|
|
fileIds: files.map((file) => file.id),
|
|
|
|
attachedFileTypes: files.map((file) => file.type),
|
|
|
|
visibleUserIds: row.get("visibleUserIds"),
|
|
|
|
mentions: row.get("mentions"),
|
|
|
|
emojis: row.get("emojis"),
|
|
|
|
tags: row.get("tags"),
|
|
|
|
hasPoll: row.get("hasPoll"),
|
|
|
|
threadId: row.get("threadId"),
|
|
|
|
channelId: row.get("channelId"),
|
|
|
|
channelName: row.get("channelName"),
|
|
|
|
userId: row.get("userId"),
|
|
|
|
replyId: row.get("replyId"),
|
|
|
|
renoteId: row.get("replyId"),
|
|
|
|
reactions: row.get("reactions"),
|
|
|
|
noteEdit: row.get("noteEdit"),
|
|
|
|
updatedAt: row.get("updatedAt"),
|
2023-07-27 00:59:23 +02:00
|
|
|
/* unused postgres denormalization */
|
|
|
|
channel: null,
|
|
|
|
renote: null,
|
|
|
|
reply: null,
|
|
|
|
renoteUserHost: null,
|
|
|
|
renoteUserId: null,
|
|
|
|
mentionedRemoteUsers: "",
|
|
|
|
replyUserHost: null,
|
|
|
|
replyUserId: null,
|
|
|
|
user: null,
|
|
|
|
userHost: null,
|
|
|
|
};
|
2023-07-25 13:28:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface ScyllaNoteReaction extends NoteReaction {
|
|
|
|
emoji: PopulatedEmoji;
|
2023-07-24 18:23:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function parseScyllaReaction(row: types.Row): ScyllaNoteReaction {
|
|
|
|
return {
|
|
|
|
id: row.get("id"),
|
|
|
|
noteId: row.get("noteId"),
|
|
|
|
userId: row.get("userId"),
|
|
|
|
reaction: row.get("reaction"),
|
|
|
|
createdAt: row.get("createdAt"),
|
|
|
|
emoji: row.get("emoji"),
|
2023-07-25 13:28:08 +02:00
|
|
|
};
|
2023-07-24 18:23:57 +02:00
|
|
|
}
|