diff options
author | Samuel <34555296+Flam3rboy@users.noreply.github.com> | 2021-10-15 18:39:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-15 18:39:57 +0200 |
commit | 1bbf789a7eb54e19459931d3928db1e34472f6d2 (patch) | |
tree | 4ac117b32e6b6c8d2c380e552597e6caad70294d /util/src | |
parent | Merge pull request #462 from hbjydev/unit-tests-expanded (diff) | |
parent | :sparkles: sticker events (diff) | |
download | server-1bbf789a7eb54e19459931d3928db1e34472f6d2.tar.xz |
Merge pull request #455 from fosscord/sticker
Stickers
Diffstat (limited to 'util/src')
-rw-r--r-- | util/src/entities/Message.ts | 2 | ||||
-rw-r--r-- | util/src/entities/Migration.ts | 18 | ||||
-rw-r--r-- | util/src/entities/ReadState.ts | 5 | ||||
-rw-r--r-- | util/src/entities/Sticker.ts | 32 | ||||
-rw-r--r-- | util/src/entities/StickerPack.ts | 31 | ||||
-rw-r--r-- | util/src/entities/index.ts | 2 | ||||
-rw-r--r-- | util/src/interfaces/Event.ts | 10 | ||||
-rw-r--r-- | util/src/migrations/1633881705509-VanityInvite.ts | 2 | ||||
-rw-r--r-- | util/src/migrations/1634308884591-Stickers.ts | 66 | ||||
-rw-r--r-- | util/src/migrations/migrate_db_engine.js | 109 | ||||
-rw-r--r-- | util/src/util/Database.ts | 20 | ||||
-rw-r--r-- | util/src/util/cdn.ts | 4 |
12 files changed, 179 insertions, 122 deletions
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts index 63cd6ad3..a4d38315 100644 --- a/util/src/entities/Message.ts +++ b/util/src/entities/Message.ts @@ -127,7 +127,7 @@ export class Message extends BaseClass { mention_channels: Channel[]; @JoinTable({ name: "message_stickers" }) - @ManyToMany(() => Sticker) + @ManyToMany(() => Sticker, { cascade: true, onDelete: "CASCADE" }) sticker_items?: Sticker[]; @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { diff --git a/util/src/entities/Migration.ts b/util/src/entities/Migration.ts new file mode 100644 index 00000000..09df70fb --- /dev/null +++ b/util/src/entities/Migration.ts @@ -0,0 +1,18 @@ +import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn } from "typeorm"; +import { BaseClassWithoutId } from "."; + +export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb") + ? ObjectIdColumn + : PrimaryGeneratedColumn; + +@Entity("migrations") +export class Migration extends BaseClassWithoutId { + @PrimaryIdAutoGenerated() + id: number; + + @Column() + timestamp: number; + + @Column() + name: string; +} diff --git a/util/src/entities/ReadState.ts b/util/src/entities/ReadState.ts index 89480e83..ebef89be 100644 --- a/util/src/entities/ReadState.ts +++ b/util/src/entities/ReadState.ts @@ -32,13 +32,8 @@ export class ReadState extends BaseClass { user: User; @Column({ nullable: true }) - @RelationId((read_state: ReadState) => read_state.last_message) last_message_id: string; - @JoinColumn({ name: "last_message_id" }) - @ManyToOne(() => Message, { nullable: true }) - last_message?: Message; - @Column({ nullable: true }) last_pin_timestamp?: Date; diff --git a/util/src/entities/Sticker.ts b/util/src/entities/Sticker.ts index 036ff2d0..37bc6fbe 100644 --- a/util/src/entities/Sticker.ts +++ b/util/src/entities/Sticker.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { User } from "./User"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; @@ -8,6 +9,7 @@ export enum StickerType { } export enum StickerFormatType { + GIF = 0, // gif is a custom format type and not in discord spec PNG = 1, APNG = 2, LOTTIE = 3, @@ -21,11 +23,22 @@ export class Sticker extends BaseClass { @Column({ nullable: true }) description?: string; - @Column() - tags: string; + @Column({ nullable: true }) + available?: boolean; - @Column() - pack_id: string; + @Column({ nullable: true }) + tags?: string; + + @Column({ nullable: true }) + @RelationId((sticker: Sticker) => sticker.pack) + pack_id?: string; + + @JoinColumn({ name: "pack_id" }) + @ManyToOne(() => require("./StickerPack").StickerPack, { + onDelete: "CASCADE", + nullable: true, + }) + pack: import("./StickerPack").StickerPack; @Column({ nullable: true }) guild_id?: string; @@ -36,6 +49,15 @@ export class Sticker extends BaseClass { }) guild?: Guild; + @Column({ nullable: true }) + user_id?: string; + + @JoinColumn({ name: "user_id" }) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) + user?: User; + @Column({ type: "int" }) type: StickerType; diff --git a/util/src/entities/StickerPack.ts b/util/src/entities/StickerPack.ts new file mode 100644 index 00000000..ec8c69a2 --- /dev/null +++ b/util/src/entities/StickerPack.ts @@ -0,0 +1,31 @@ +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm"; +import { Sticker } from "."; +import { BaseClass } from "./BaseClass"; + +@Entity("sticker_packs") +export class StickerPack extends BaseClass { + @Column() + name: string; + + @Column({ nullable: true }) + description?: string; + + @Column({ nullable: true }) + banner_asset_id?: string; + + @OneToMany(() => Sticker, (sticker: Sticker) => sticker.pack, { + cascade: true, + orphanedRowAction: "delete", + }) + stickers: Sticker[]; + + // sku_id: string + + @Column({ nullable: true }) + @RelationId((pack: StickerPack) => pack.cover_sticker) + cover_sticker_id?: string; + + @ManyToOne(() => Sticker, { nullable: true }) + @JoinColumn() + cover_sticker?: Sticker; +} diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts index 7b1c9750..b52841c9 100644 --- a/util/src/entities/index.ts +++ b/util/src/entities/index.ts @@ -11,6 +11,7 @@ export * from "./Guild"; export * from "./Invite"; export * from "./Member"; export * from "./Message"; +export * from "./Migration"; export * from "./RateLimit"; export * from "./ReadState"; export * from "./Recipient"; @@ -18,6 +19,7 @@ export * from "./Relationship"; export * from "./Role"; export * from "./Session"; export * from "./Sticker"; +export * from "./StickerPack"; export * from "./Team"; export * from "./TeamMember"; export * from "./Template"; diff --git a/util/src/interfaces/Event.ts b/util/src/interfaces/Event.ts index 3c8ab8ab..13fd4b8b 100644 --- a/util/src/interfaces/Event.ts +++ b/util/src/interfaces/Event.ts @@ -12,6 +12,7 @@ import { Interaction } from "./Interaction"; import { ConnectedAccount } from "../entities/ConnectedAccount"; import { Relationship, RelationshipType } from "../entities/Relationship"; import { Presence } from "./Presence"; +import { Sticker } from ".."; export interface Event { guild_id?: string; @@ -193,6 +194,14 @@ export interface GuildEmojisUpdateEvent extends Event { }; } +export interface GuildStickersUpdateEvent extends Event { + event: "GUILD_STICKERS_UPDATE"; + data: { + guild_id: string; + stickers: Sticker[]; + }; +} + export interface GuildIntegrationUpdateEvent extends Event { event: "GUILD_INTEGRATIONS_UPDATE"; data: { @@ -553,6 +562,7 @@ export type EVENT = | "GUILD_BAN_ADD" | "GUILD_BAN_REMOVE" | "GUILD_EMOJIS_UPDATE" + | "GUILD_STICKERS_UPDATE" | "GUILD_INTEGRATIONS_UPDATE" | "GUILD_MEMBER_ADD" | "GUILD_MEMBER_REMOVE" diff --git a/util/src/migrations/1633881705509-VanityInvite.ts b/util/src/migrations/1633881705509-VanityInvite.ts index af9b98ae..45485310 100644 --- a/util/src/migrations/1633881705509-VanityInvite.ts +++ b/util/src/migrations/1633881705509-VanityInvite.ts @@ -1,6 +1,8 @@ import { MigrationInterface, QueryRunner } from "typeorm"; export class VanityInvite1633881705509 implements MigrationInterface { + name = "VanityInvite1633881705509"; + public async up(queryRunner: QueryRunner): Promise<void> { try { await queryRunner.query(`ALTER TABLE "emojis" DROP COLUMN vanity_url_code`); diff --git a/util/src/migrations/1634308884591-Stickers.ts b/util/src/migrations/1634308884591-Stickers.ts new file mode 100644 index 00000000..fbc4649f --- /dev/null +++ b/util/src/migrations/1634308884591-Stickers.ts @@ -0,0 +1,66 @@ +import { MigrationInterface, QueryRunner, Table, TableColumn, TableForeignKey } from "typeorm"; + +export class Stickers1634308884591 implements MigrationInterface { + name = "Stickers1634308884591"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.dropForeignKey("read_states", "FK_6f255d873cfbfd7a93849b7ff74"); + await queryRunner.changeColumn( + "stickers", + "tags", + new TableColumn({ name: "tags", type: "varchar", isNullable: true }) + ); + await queryRunner.changeColumn( + "stickers", + "pack_id", + new TableColumn({ name: "pack_id", type: "varchar", isNullable: true }) + ); + await queryRunner.changeColumn("stickers", "type", new TableColumn({ name: "type", type: "integer" })); + await queryRunner.changeColumn( + "stickers", + "format_type", + new TableColumn({ name: "format_type", type: "integer" }) + ); + await queryRunner.changeColumn( + "stickers", + "available", + new TableColumn({ name: "available", type: "boolean", isNullable: true }) + ); + await queryRunner.changeColumn( + "stickers", + "user_id", + new TableColumn({ name: "user_id", type: "boolean", isNullable: true }) + ); + await queryRunner.createForeignKey( + "stickers", + new TableForeignKey({ + name: "FK_8f4ee73f2bb2325ff980502e158", + columnNames: ["user_id"], + referencedColumnNames: ["id"], + referencedTableName: "users", + onDelete: "CASCADE", + }) + ); + await queryRunner.createTable( + new Table({ + name: "sticker_packs", + columns: [ + new TableColumn({ name: "id", type: "varchar", isPrimary: true }), + new TableColumn({ name: "name", type: "varchar" }), + new TableColumn({ name: "description", type: "varchar", isNullable: true }), + new TableColumn({ name: "banner_asset_id", type: "varchar", isNullable: true }), + new TableColumn({ name: "cover_sticker_id", type: "varchar", isNullable: true }), + ], + foreignKeys: [ + new TableForeignKey({ + columnNames: ["cover_sticker_id"], + referencedColumnNames: ["id"], + referencedTableName: "stickers", + }), + ], + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> {} +} diff --git a/util/src/migrations/migrate_db_engine.js b/util/src/migrations/migrate_db_engine.js deleted file mode 100644 index 79e9d86f..00000000 --- a/util/src/migrations/migrate_db_engine.js +++ /dev/null @@ -1,109 +0,0 @@ -const { config } = require("dotenv"); -config(); -const { createConnection } = require("typeorm"); -const { initDatabase } = require("../../dist/util/Database"); -require("missing-native-js-functions"); -const { - Application, - Attachment, - Ban, - Channel, - ConfigEntity, - ConnectedAccount, - Emoji, - Guild, - Invite, - Member, - Message, - ReadState, - Recipient, - Relationship, - Role, - Sticker, - Team, - TeamMember, - Template, - User, - VoiceState, - Webhook, -} = require("../../dist/entities/index"); - -async function main() { - if (!process.env.TO) throw new Error("TO database env connection string not set"); - - // manually arrange them because of foreign keys - const entities = [ - ConfigEntity, - User, - Guild, - Channel, - Invite, - Role, - Ban, - Application, - Emoji, - ConnectedAccount, - Member, - ReadState, - Recipient, - Relationship, - Sticker, - Team, - TeamMember, - Template, - VoiceState, - Webhook, - Message, - Attachment, - ]; - - const oldDB = await initDatabase(); - - const type = process.env.TO.includes("://") ? process.env.TO.split(":")[0]?.replace("+srv", "") : "sqlite"; - const isSqlite = type.includes("sqlite"); - - // @ts-ignore - const newDB = await createConnection({ - type, - url: isSqlite ? undefined : process.env.TO, - database: isSqlite ? process.env.TO : undefined, - entities, - name: "new", - synchronize: true, - }); - let i = 0; - - try { - for (const entity of entities) { - const entries = await oldDB.manager.find(entity); - - // @ts-ignore - console.log("migrating " + entries.length + " " + entity.name + " ..."); - - for (const entry of entries) { - console.log(i++); - - try { - await newDB.manager.insert(entity, entry); - } catch (error) { - try { - if (!entry.id) throw new Error("object doesn't have a unique id: " + entry); - await newDB.manager.update(entity, { id: entry.id }, entry); - } catch (error) { - console.error("couldn't migrate " + i + " " + entity.name, error); - } - } - } - - // @ts-ignore - console.log("migrated " + entries.length + " " + entity.name); - } - } catch (error) { - console.error(error.message); - } - - console.log("SUCCESS migrated all data"); - await newDB.close(); -} - -main().caught(); diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index 8bce3a6f..6124ffab 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -2,6 +2,7 @@ import path from "path"; import "reflect-metadata"; import { Connection, createConnection } from "typeorm"; import * as Models from "../entities"; +import { Migration } from "../entities/Migration"; import { yellow, green } from "nanocolors"; // UUID extension option is only supported with postgres @@ -33,10 +34,27 @@ export function initDatabase(): Promise<Connection> { bigNumberStrings: false, supportBigNumbers: true, name: "default", + migrations: [path.join(__dirname, "..", "migrations", "*.js")], }); - promise.then((connection) => { + promise.then(async (connection: Connection) => { dbConnection = connection; + + // run migrations, and if it is a new fresh database, set it to the last migration + if (connection.migrations.length) { + if (!(await Migration.findOne({}))) { + let i = 0; + + await Migration.insert( + connection.migrations.map((x) => ({ + id: i++, + name: x.name, + timestamp: Date.now(), + })) + ); + } + } + await connection.runMigrations(); console.log(`[Database] ${green("connected")}`); }); diff --git a/util/src/util/cdn.ts b/util/src/util/cdn.ts index 4dd0078a..ea950cd1 100644 --- a/util/src/util/cdn.ts +++ b/util/src/util/cdn.ts @@ -4,7 +4,9 @@ import fetch from "node-fetch"; import { Config } from "./Config"; import multer from "multer"; -export async function uploadFile(path: string, file: Express.Multer.File) { +export async function uploadFile(path: string, file?: Express.Multer.File) { + if (!file?.buffer) throw new HTTPError("Missing file in body"); + const form = new FormData(); form.append("file", file.buffer, { contentType: file.mimetype, |