diff --git a/api/assets/schemas.json b/api/assets/schemas.json
index a12925e0..2ceaa923 100644
--- a/api/assets/schemas.json
+++ b/api/assets/schemas.json
@@ -2909,6 +2909,9 @@
}
}
},
+ "required": [
+ "image"
+ ],
"definitions": {
"ChannelPermissionOverwriteType": {
"enum": [
@@ -4744,7 +4747,7 @@
"type": "string"
},
"permissions": {
- "type": "array"
+ "type": "string"
},
"color": {
"type": "integer"
diff --git a/api/src/routes/guilds/#guild_id/roles.ts b/api/src/routes/guilds/#guild_id/roles.ts
index 0a57c6a2..b1875598 100644
--- a/api/src/routes/guilds/#guild_id/roles.ts
+++ b/api/src/routes/guilds/#guild_id/roles.ts
@@ -17,7 +17,7 @@ const router: Router = Router();
export interface RoleModifySchema {
name?: string;
- permissions?: bigint;
+ permissions?: string;
color?: number;
hoist?: boolean; // whether the role should be displayed separately in the sidebar
mentionable?: boolean; // whether the role should be mentionable
@@ -57,7 +57,7 @@ router.post("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" })
...body,
guild_id: guild_id,
managed: false,
- permissions: String(req.permission!.bitfield & (body.permissions || BigInt("0"))),
+ permissions: String(req.permission!.bitfield & BigInt(body.permissions || "0")),
tags: undefined
});
@@ -109,7 +109,7 @@ router.patch("/:role_id", route({ body: "RoleModifySchema", permission: "MANAGE_
...body,
id: role_id,
guild_id,
- permissions: String(req.permission!.bitfield & (body.permissions || BigInt("0")))
+ permissions: String(req.permission!.bitfield & BigInt(body.permissions || "0"))
});
await Promise.all([
diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/api/src/routes/guilds/#guild_id/vanity-url.ts
index 061b317c..63173345 100644
--- a/api/src/routes/guilds/#guild_id/vanity-url.ts
+++ b/api/src/routes/guilds/#guild_id/vanity-url.ts
@@ -10,7 +10,7 @@ const InviteRegex = /\W/g;
router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const invite = await Invite.findOne({ where: {guild_id: guild_id, vanity_url: true} });
+ const invite = await Invite.findOne({ where: { guild_id: guild_id, vanity_url: true } });
if (!invite) return res.json({ code: null });
return res.json({ code: invite.code, uses: invite.uses });
@@ -35,15 +35,7 @@ router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" })
const { id } = await Channel.findOneOrFail({ guild_id, type: ChannelType.GUILD_TEXT });
- Promise.all([
- new Invite({
- code: code,
- uses: 0,
- created_at: new Date(),
- guild_id,
- channel_id: id
- }).save()
- ]);
+ await Invite.update({ vanity_url: true, guild_id }, { code: code, channel_id: id });
return res.json({ code: code });
});
diff --git a/bundle/package.json b/bundle/package.json
index eedbdd8c..404c6758 100644
--- a/bundle/package.json
+++ b/bundle/package.json
@@ -9,7 +9,7 @@
"start": "node scripts/build.js && node dist/bundle/src/start.js",
"start:bundle": "node dist/bundle/src/start.js",
"test": "echo \"Error: no test specified\" && exit 1",
- "migrate": "node --require ts-node/register node_modules/typeorm/cli.js -f ../util/ormconfig.json migration:run"
+ "migrate": "cd ../util/ && npm i && node --require ts-node/register node_modules/typeorm/cli.js -f ../util/ormconfig.json migration:run"
},
"repository": {
"type": "git",
diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts
index 4470857f..673dde9d 100644
--- a/gateway/src/opcodes/Identify.ts
+++ b/gateway/src/opcodes/Identify.ts
@@ -94,9 +94,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
// @ts-ignore
x.channel.recipients = x.channel.recipients?.map((x) => x.user);
//TODO is this needed? check if users in group dm that are not friends are sent in the READY event
- users = users.concat(
- x.channel.recipients?.map((x) => x.user) as User[]
- );
+ users = users.concat(x.channel.recipients as unknown as User[]);
if (x.channel.isDm()) {
x.channel.recipients = x.channel.recipients!.filter(
(x) => x.id !== this.user_id
diff --git a/util/src/migrations/1633881705509-VanityInvite.ts b/util/src/migrations/1633881705509-VanityInvite.ts
new file mode 100644
index 00000000..af9b98ae
--- /dev/null
+++ b/util/src/migrations/1633881705509-VanityInvite.ts
@@ -0,0 +1,17 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class VanityInvite1633881705509 implements MigrationInterface {
+ public async up(queryRunner: QueryRunner): Promise<void> {
+ try {
+ await queryRunner.query(`ALTER TABLE "emojis" DROP COLUMN vanity_url_code`);
+ await queryRunner.query(`ALTER TABLE "emojis" DROP CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad`);
+ } catch (error) {}
+ }
+
+ public async down(queryRunner: QueryRunner): Promise<void> {
+ await queryRunner.query(`ALTER TABLE "emojis" ADD vanity_url_code varchar`);
+ await queryRunner.query(
+ `ALTER TABLE "emojis" ADD CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad FOREIGN KEY ("vanity_url_code") REFERENCES "invites"("code") ON DELETE NO ACTION ON UPDATE NO ACTION`
+ );
+ }
+}
diff --git a/util/src/migrations/migrate_db_engine.js b/util/src/migrations/migrate_db_engine.js
new file mode 100644
index 00000000..eab30bc4
--- /dev/null
+++ b/util/src/migrations/migrate_db_engine.js
@@ -0,0 +1,106 @@
+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,
+ 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 = [
+ 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 oldDB = await createConnection({
+ type,
+ url: isSqlite ? undefined : process.env.TO,
+ database: isSqlite ? process.env.TO : undefined,
+ entities,
+ name: "old",
+ });
+ 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/migrations/migrate_db_engine.ts b/util/src/migrations/migrate_db_engine.ts
deleted file mode 100644
index 33024a8d..00000000
--- a/util/src/migrations/migrate_db_engine.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import { config } from "dotenv";
-config();
-import { BaseEntity, createConnection, EntityTarget } from "typeorm";
-import { initDatabase } from "../util/Database";
-import "missing-native-js-functions";
-import {
- Application,
- Attachment,
- Ban,
- Channel,
- ConnectedAccount,
- defaultSettings,
- Emoji,
- Guild,
- Invite,
- Member,
- Message,
- RateLimit,
- ReadState,
- Recipient,
- Relationship,
- Role,
- Sticker,
- Team,
- TeamMember,
- Template,
- User,
- VoiceState,
- Webhook,
-} from "..";
-
-async function main() {
- if (!process.env.FROM) throw new Error("FROM database env connection string not set");
-
- // manually arrange them because of foreign key
- const entities = [
- User,
- Guild,
- Channel,
- Invite,
- Role,
- Ban,
- Application,
- Emoji,
- ConnectedAccount,
- Member,
- ReadState,
- Recipient,
- Relationship,
- Sticker,
- Team,
- TeamMember,
- Template,
- VoiceState,
- Webhook,
- Message,
- Attachment,
- ];
-
- const newDB = await initDatabase();
-
- // @ts-ignore
- const oldDB = await createConnection({
- type: process.env.FROM.split(":")[0]?.replace("+srv", ""),
- url: process.env.FROM,
- entities,
- name: "old",
- });
- let i = 0;
-
- try {
- for (const e of entities) {
- const entity = e as EntityTarget<any>;
- const entries = await oldDB.manager.find(entity);
- //@ts-ignore
- console.log("migrated " + entries.length + " " + entity.name);
-
- for (const entry of entries) {
- console.log(i++);
-
- if (entry instanceof User) {
- console.log("instance of User");
- if (entry.bio == null) entry.bio = "";
- if (entry.rights == null) entry.rights = "0";
- if (entry.disabled == null) entry.disabled = false;
- if (entry.fingerprints == null) entry.fingerprints = [];
- if (entry.deleted == null) entry.deleted = false;
- if (entry.data == null) {
- entry.data = {
- valid_tokens_since: new Date(0),
- hash: undefined,
- };
- // @ts-ignore
- if (entry.user_data) {
- // TODO: relationships
- entry.data = {
- // @ts-ignore
- valid_tokens_since: entry.user_data.valid_tokens_since, // @ts-ignore
- hash: entry.user_data.hash,
- };
- }
- }
- // @ts-ignore
- if (entry.settings == null) {
- entry.settings = defaultSettings;
- // @ts-ignore
- if (entry.user_data) entry.settings = entry.user_settings;
- }
- }
-
- // try {
- await newDB.manager.insert(entity, entry);
- // } catch (error) {
- // if (!entry.id) throw new Error("object doesn't have a unique id: " + entry);
- // await newDB.manager.update(entity, { id: entry.id }, entry);
- // }
- }
- // @ts-ignore
- console.log("migrated all " + entity.name);
- }
- } catch (error) {
- console.error((error as any).message);
- }
-
- console.log("SUCCESS migrated all data");
- await newDB.close();
-}
-
-main().caught();
diff --git a/util/src/util/Rights.ts b/util/src/util/Rights.ts
index a266e4f7..5edd9142 100644
--- a/util/src/util/Rights.ts
+++ b/util/src/util/Rights.ts
@@ -30,7 +30,7 @@ export class Rights extends BitField {
MANAGE_MESSAGES: BitFlag(3), // Can't see other messages but delete/edit them in channels that they can see
MANAGE_RATE_LIMITS: BitFlag(4),
MANAGE_ROUTING: BitFlag(5), // can create custom message routes to any channel/guild
- MANAGE_TICKETS: BitFlag(6),
+ MANAGE_TICKETS: BitFlag(6), // can respond to and resolve support tickets
MANAGE_USERS: BitFlag(7),
ADD_MEMBERS: BitFlag(8), // can manually add any members in their guilds
BYPASS_RATE_LIMITS: BitFlag(9),
@@ -39,7 +39,7 @@ export class Rights extends BitField {
CREATE_DMS: BitFlag(12),
CREATE_DM_GROUPS: BitFlag(13),
CREATE_GUILDS: BitFlag(14),
- CREATE_INVITES: BitFlag(15),
+ CREATE_INVITES: BitFlag(15), // can create mass invites in the guilds that they have CREATE_INSTANT_INVITE
CREATE_ROLES: BitFlag(16),
CREATE_TEMPLATES: BitFlag(17),
CREATE_WEBHOOKS: BitFlag(18),
@@ -50,9 +50,13 @@ export class Rights extends BitField {
SELF_EDIT_MESSAGES: BitFlag(23),
SELF_EDIT_NAME: BitFlag(24),
SEND_MESSAGES: BitFlag(25),
- USE_SCREEN: BitFlag(26),
+ USE_ACTIVITIES: BitFlag(26), // use (game) activities in voice channels (e.g. Watch together)
USE_VIDEO: BitFlag(27),
USE_VOICE: BitFlag(28),
+ INVITE_USERS: BitFlag(29), // can create user-specific invites in the guilds that they have INVITE_USERS
+ SELF_DELETE_DISABLE: BitFlag(30), // can disable/delete own account
+ DEBTABLE: BitFlag(31), // can use pay-to-use features
+ CREDITABLE: BitFlag(32) // can receive money from monetisation related features
};
any(permission: RightResolvable, checkOperator = true) {
|