| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- // This script is intended for migrating to the new Autumn release.
- // Please read all TODOs in this file as they will help guide you
- // to migrate your data properly. Please do Ctrl + F "TODO".
- import { MongoClient } from "mongodb";
- /**
- * Map of tags to S3 bucket names
- *
- * TODO: if you've used AUTUMN_S3_BUCKET_PREFIX in the past
- * update the bucket names below to include the prefix
- *
- * NOTE: update `files.s3.default_bucket` in Revolt.toml!
- */
- const BUCKET_MAP = {
- attachments: "attachments",
- avatars: "avatars",
- backgrounds: "backgrounds",
- icons: "icons",
- banners: "banners",
- emojis: "emojis",
- };
- /**
- * Connection URL for MongoDB instance
- *
- * TODO: change if necessary
- */
- const CONNECTION_URL = "mongodb://database";
- const objectLookup = {};
- const mongo = new MongoClient(CONNECTION_URL);
- await mongo.connect();
- async function determineUploaderIdAndUse(f, v, i) {
- if (f.tag === "attachments" && v === "attachments") {
- if (typeof f.message_id !== "string") {
- console.warn(i, "No message id specified.");
- return null;
- }
- if (!objectLookup[f.message_id]) {
- objectLookup[f.message_id] = await mongo
- .db("revolt")
- .collection("messages")
- .findOne({
- _id: f.message_id,
- });
- }
- if (!objectLookup[f.message_id]) {
- console.warn(i, "Message", f.message_id, "doesn't exist anymore!");
- return null;
- }
- return {
- uploaded_at: new Date(decodeTime(f.message_id)),
- uploader_id: objectLookup[f.message_id].author,
- used_for: {
- type: "Message",
- id: f.message_id,
- },
- };
- } else if (f.tag === "banners" && v === "banners") {
- if (typeof f.server_id !== "string") {
- console.warn(i, "No server id specified.");
- return null;
- }
- if (!objectLookup[f.server_id]) {
- objectLookup[f.server_id] = await mongo
- .db("revolt")
- .collection("servers")
- .findOne({
- _id: f.server_id,
- });
- }
- if (!objectLookup[f.server_id]) {
- console.warn(i, "Server", f.server_id, "doesn't exist anymore!");
- return null;
- }
- return {
- uploaded_at: new Date(),
- uploader_id: objectLookup[f.server_id].owner,
- used_for: {
- type: "ServerBanner",
- id: f.server_id,
- },
- };
- } else if (f.tag === "emojis" && v === "emojis") {
- if (typeof f.object_id !== "string") {
- return null;
- }
- if (!objectLookup[f.object_id]) {
- objectLookup[f.object_id] = await mongo
- .db("revolt")
- .collection("emojis")
- .findOne({
- _id: f.object_id,
- });
- }
- if (!objectLookup[f.object_id]) {
- console.warn(i, "Emoji", f.object_id, "doesn't exist anymore!");
- return null;
- }
- return {
- uploaded_at: new Date(decodeTime(f.object_id)),
- uploader_id: objectLookup[f.object_id].creator_id,
- used_for: {
- type: "Emoji",
- id: f.object_id,
- },
- };
- } else if (f.tag === "avatars" && v === "avatars") {
- if (typeof f.user_id !== "string") {
- return null;
- }
- if (!objectLookup[f.user_id]) {
- objectLookup[f.user_id] = await mongo
- .db("revolt")
- .collection("users")
- .findOne({
- _id: f.user_id,
- });
- }
- if (!objectLookup[f.user_id]) {
- console.warn(i, "User", f.user_id, "doesn't exist anymore!");
- return null;
- }
- if (objectLookup[f.user_id].avatar?._id !== f._id) {
- console.warn(
- i,
- "Attachment no longer in use.",
- f._id,
- "for",
- f.user_id,
- "current:",
- objectLookup[f.user_id].avatar?._id
- );
- return null;
- }
- return {
- uploaded_at: new Date(),
- uploader_id: f.user_id,
- used_for: {
- type: "UserAvatar",
- id: f.user_id,
- },
- };
- } else if (f.tag === "backgrounds" && v === "backgrounds") {
- if (typeof f.user_id !== "string") {
- return null;
- }
- if (!objectLookup[f.user_id]) {
- objectLookup[f.user_id] = await mongo
- .db("revolt")
- .collection("users")
- .findOne({
- _id: f.user_id,
- });
- }
- if (!objectLookup[f.user_id]) {
- console.warn(i, "User", f.user_id, "doesn't exist anymore!");
- return null;
- }
- if (objectLookup[f.user_id].profile?.background?._id !== f._id) {
- console.warn(
- i,
- "Attachment no longer in use.",
- f._id,
- "for",
- f.user_id,
- "current:",
- objectLookup[f.user_id].profile?.background?._id
- );
- return null;
- }
- return {
- uploaded_at: new Date(),
- uploader_id: f.user_id,
- used_for: {
- type: "UserProfileBackground",
- id: f.user_id,
- },
- };
- } else if (f.tag === "icons" && v === "icons") {
- if (typeof f.object_id !== "string") {
- return null;
- }
- // some bugged files at start
- // ... expensive to compute at worst case =(
- // so instead we can just disable it until everything is processed
- // then re-run on these!
- if (false) {
- objectLookup[f.object_id] = await mongo
- .db("revolt")
- .collection("users")
- .findOne({
- _id: f.object_id,
- });
- if (!objectLookup[f.object_id]) {
- console.warn(i, "No legacy match!");
- return null;
- }
- return {
- uploaded_at: new Date(),
- uploader_id: f.object_id,
- used_for: {
- type: "LegacyGroupIcon",
- id: f.object_id,
- },
- };
- }
- if (!objectLookup[f.object_id]) {
- objectLookup[f.object_id] = await mongo
- .db("revolt")
- .collection("servers")
- .findOne({
- _id: f.object_id,
- });
- }
- if (
- !objectLookup[f.object_id] ||
- // heuristic for not server
- !objectLookup[f.object_id].channels
- ) {
- console.warn(i, "Server", f.object_id, "doesn't exist!");
- if (!objectLookup[f.object_id]) {
- objectLookup[f.object_id] = await mongo
- .db("revolt")
- .collection("channels")
- .findOne({
- _id: f.object_id,
- });
- }
- if (!objectLookup[f.object_id]) {
- console.warn(i, "Channel", f.object_id, "doesn't exist!");
- return null;
- }
- let server;
- const serverId = objectLookup[f.object_id].server;
- if (serverId) {
- server = objectLookup[serverId];
- if (!server) {
- server = await mongo.db("revolt").collection("servers").findOne({
- _id: serverId,
- });
- console.info(
- i,
- "Couldn't find matching server for channel " + f.object_id + "!"
- );
- if (!server) return null;
- objectLookup[serverId] = server;
- }
- }
- return {
- uploaded_at: new Date(),
- uploader_id: (server ?? objectLookup[f.object_id]).owner,
- used_for: {
- type: "ChannelIcon",
- id: f.object_id,
- },
- };
- }
- return {
- uploaded_at: new Date(),
- uploader_id: objectLookup[f.object_id].owner,
- used_for: {
- type: "ServerIcon",
- id: f.object_id,
- },
- };
- } else {
- throw (
- "couldn't find uploader id for " +
- f._id +
- " expected " +
- v +
- " but got " +
- f.tag
- );
- }
- }
- const dirs = [
- "banners",
- "emojis",
- "avatars",
- "backgrounds",
- "icons",
- "attachments", // https://stackoverflow.com/a/18777877
- ];
- // === add `used_for` field to files
- const files_pt1 = await mongo
- .db("revolt")
- .collection("attachments")
- .find({
- $or: [
- {
- used_for: {
- $exists: false,
- },
- },
- {
- uploader_id: {
- $exists: false,
- },
- },
- {
- uploader_at: {
- $exists: false,
- },
- },
- ],
- })
- .toArray();
- let i = 1;
- for (const file of files_pt1) {
- console.info(i++, files_pt1.length, file);
- const meta = determineUploaderIdAndUse(file, file.tag, i);
- if (meta) {
- await mongo.db("revolt").collection("attachments").updateOne(
- {
- _id: file._id,
- },
- {
- $set: meta,
- }
- );
- }
- }
- // === set hash to id and create relevant objects
- const files_pt2 = await mongo
- .db("revolt")
- .collection("attachments")
- .find({
- hash: {
- $exists: false,
- },
- })
- .toArray();
- await mongo
- .db("revolt")
- .collection("attachment_hashes")
- .insertMany(
- files_pt2.map((file) => ({
- _id: file._id,
- processed_hash: file._id,
- created_at: new Date(),
- bucket_id: BUCKET_MAP[file.tag],
- path: file._id,
- iv: "", // disable encryption for file
- metadata: file.metadata,
- content_type: file.content_type,
- size: file.size,
- }))
- );
- for (const file of files_pt2) {
- await mongo
- .db("revolt")
- .collection("attachments")
- .updateOne(
- {
- _id: file._id,
- },
- {
- $set: {
- hash: file._id,
- },
- }
- );
- }
|