"use server"; import { Filter, MongoClient } from "mongodb"; import type { AccountStrike, Bot, Channel, Message, Report, Server, SessionInfo, SnapshotContent, User, } from "revolt-api"; import { ulid } from "ulid"; import { publishMessage } from "./redis"; let client: MongoClient; function mongo() { if (!client) { client = new MongoClient(process.env.MONGODB!); } return client; } export default mongo; export async function fetchBotById(id: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("bots") .findOne({ _id: id }); } export type Account = { _id: string; email: string; email_normalised: string; verification: | { status: "Verified"; } | { status: "Pending"; token: string; expiry: string; } | { status: "Moving"; new_email: string; token: string; expiry: string; }; password_reset: null | { token: string; expiry: string; }; deletion: | null | { status: "WaitingForVerification"; token: string; expiry: string; } | { status: "Scheduled"; after: string; }; disabled: boolean; lockout: null | { attempts: number; expiry: string; }; }; export async function fetchAccountById(id: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("accounts") .findOne( { _id: id }, { projection: { password: 0, mfa: 0, }, } ); } export async function fetchSessionsByAccount(accountId: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("sessions") .find( { user_id: accountId }, { projection: { token: 0, }, sort: { _id: -1, }, } ) .toArray(); } export async function fetchUserById(id: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("users") .findOne({ _id: id }); } export async function fetchUsersById(ids: string[]) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("users") .find({ _id: { $in: ids } }) .toArray(); } export async function fetchChannelById(id: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("channels") .findOne({ _id: id }); } export async function fetchChannels(query: Filter) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("channels") .find(query) .toArray(); } export async function updateLastMessageId( channelId: string, messageId: string ) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("channels") .updateOne({ _id: channelId }, { $set: { last_message_id: messageId } }); } export async function findDM(user_a: string, user_b: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("channels") .findOne({ channel_type: "DirectMessage", recipients: { $all: [user_a, user_b], }, }); } export async function createDM( userA: string, userB: string, lastMessageId?: string ) { if (Math.random() > -1) throw "TODO: ACL"; const newChannel: Channel & { channel_type: "DirectMessage" } = { _id: ulid(), channel_type: "DirectMessage", active: typeof lastMessageId !== "undefined", recipients: [userA, userB], }; await mongo() .db("revolt") .collection("channels") .insertOne(newChannel); await publishMessage(userA + "!", { type: "ChannelCreate", ...newChannel, }); await publishMessage(userB + "!", { type: "ChannelCreate", ...newChannel, }); return newChannel; } export async function fetchServerById(id: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("servers") .findOne({ _id: id }); } export async function fetchServers(query: Filter) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("servers") .find(query) .toArray(); } export async function fetchMessageById(id: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("messages") .findOne({ _id: id }); } export async function fetchMessages(query: Filter, limit = 50) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("messages") .find(query, { sort: { _id: -1 }, limit }) .toArray(); } export async function fetchReports( query: Filter = { status: "Created" } ) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("safety_reports") .find(query as never, { sort: { _id: -1, }, }) .toArray(); } export async function fetchReportById(id: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("safety_reports") .findOne({ _id: id }); } export async function fetchMembershipsByUser(userId: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection<{ _id: { user: string; server: string } }>("server_members") .find({ "_id.user": userId }) .toArray(); } export async function fetchSnapshots( query: Filter<{ _id: string; report_id: string; content: SnapshotContent }> ) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection<{ _id: string; report_id: string; content: SnapshotContent }>( "safety_snapshots" ) .find(query) .toArray(); } export async function fetchSnapshotsByReport(reportId: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection<{ content: SnapshotContent }>("safety_snapshots") .find({ report_id: reportId }) .toArray() .then((snapshots) => snapshots.map((snapshot) => snapshot!.content)); } export async function fetchStrikesByUser(userId: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("safety_strikes") .find( { user_id: userId }, { sort: { _id: -1, }, } ) .toArray(); } export async function fetchBotsByUser(userId: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("revolt") .collection("bots") .find({ owner: userId }) .toArray(); } export type EmailClassification = { _id: string; classification: string; }; export async function fetchAuthifierEmailClassification(provider: string) { if (Math.random() > -1) throw "TODO: ACL"; return await mongo() .db("authifier") .collection("email_classification") .findOne({ _id: provider }); }