Merge branch 'master' into slowcord

This commit is contained in:
Madeline 2022-03-31 00:06:13 +11:00
commit 6972dac560
7 changed files with 43 additions and 22 deletions

View File

@ -2,7 +2,7 @@
"openapi": "3.0.0", "openapi": "3.0.0",
"servers": [ "servers": [
{ {
"url": "https://api.fosscord.com/v{version}", "url": "https://api.fosscord.com/api/v{version}",
"description": "Official fosscord instance", "description": "Official fosscord instance",
"variables": { "variables": {
"version": { "version": {
@ -2960,7 +2960,7 @@
"type": { "type": {
"type": "string" "type": "string"
}, },
"verifie": { "verified": {
"type": "boolean" "type": "boolean"
}, },
"visibility": { "visibility": {
@ -2980,7 +2980,7 @@
"type", "type",
"user", "user",
"user_id", "user_id",
"verifie", "verified",
"visibility" "visibility"
] ]
}, },

View File

@ -0,0 +1,12 @@
// Remove `<link id="logincss" rel="stylesheet" href="/assets/fosscord-login.css" />` from header when we're not accessing `/login` or `/register`
// fosscord-login.css replaces discord's TOS tooltip with something more fitting for fosscord, which when included in the main app, causes other tooltips
// to be affected, which is potentially unwanted.
//
// This script removes fosscord-login.css when a user reloads the page. From testing, it appears fosscord already properly removes
// fosscord-login.css after login is successful, but not if you reload the page after logging in. This script is to remove fosscord-login.css in
// that specific case.
var token = JSON.parse(localStorage.getItem("token"));
if (!token && location.pathname !== "/login" && location.pathname !== "/register") {
document.getElementById("logincss").remove();
}

View File

@ -355,11 +355,11 @@
"type": { "type": {
"type": "string" "type": "string"
}, },
"verifie": { "verified": {
"type": "boolean" "type": "boolean"
} }
}, },
"required": ["name", "type", "verifie"] "required": ["name", "type", "verified"]
} }
}, },
"$schema": "http://json-schema.org/draft-07/schema#" "$schema": "http://json-schema.org/draft-07/schema#"

View File

@ -14,12 +14,12 @@ import { Webhook } from "./Webhook";
import { DmChannelDTO } from "../dtos"; import { DmChannelDTO } from "../dtos";
export enum ChannelType { export enum ChannelType {
GUILD_TEXT = 0, // a text channel within a server GUILD_TEXT = 0, // a text channel within a guild
DM = 1, // a direct message between users DM = 1, // a direct message between users
GUILD_VOICE = 2, // a voice channel within a server GUILD_VOICE = 2, // a voice channel within a guild
GROUP_DM = 3, // a direct message between multiple users GROUP_DM = 3, // a direct message between multiple users
GUILD_CATEGORY = 4, // an organizational category that contains up to 50 channels GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels
GUILD_NEWS = 5, // a channel that users can follow and crosspost into their own server GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route
GUILD_STORE = 6, // a channel in which game developers can sell their game on Discord GUILD_STORE = 6, // a channel in which game developers can sell their game on Discord
ENCRYPTED = 7, // end-to-end encrypted channel ENCRYPTED = 7, // end-to-end encrypted channel
ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel
@ -72,7 +72,7 @@ export class Channel extends BaseClass {
@ManyToOne(() => Channel) @ManyToOne(() => Channel)
parent?: Channel; parent?: Channel;
// only for group dms // for group DMs and owned custom channel types
@Column({ nullable: true }) @Column({ nullable: true })
@RelationId((channel: Channel) => channel.owner) @RelationId((channel: Channel) => channel.owner)
owner_id: string; owner_id: string;
@ -117,6 +117,9 @@ export class Channel extends BaseClass {
}) })
invites?: Invite[]; invites?: Invite[];
@Column({ nullable: true })
retention_policy_id?: string;
@OneToMany(() => Message, (message: Message) => message.channel, { @OneToMany(() => Message, (message: Message) => message.channel, {
cascade: true, cascade: true,
orphanedRowAction: "delete", orphanedRowAction: "delete",
@ -182,6 +185,7 @@ export class Channel extends BaseClass {
switch (channel.type) { switch (channel.type) {
case ChannelType.GUILD_TEXT: case ChannelType.GUILD_TEXT:
case ChannelType.GUILD_NEWS:
case ChannelType.GUILD_VOICE: case ChannelType.GUILD_VOICE:
if (channel.parent_id && !opts?.skipExistsCheck) { if (channel.parent_id && !opts?.skipExistsCheck) {
const exists = await Channel.findOneOrFail({ id: channel.parent_id }); const exists = await Channel.findOneOrFail({ id: channel.parent_id });
@ -191,25 +195,24 @@ export class Channel extends BaseClass {
} }
break; break;
case ChannelType.GUILD_CATEGORY: case ChannelType.GUILD_CATEGORY:
case ChannelType.UNHANDLED:
break; break;
case ChannelType.DM: case ChannelType.DM:
case ChannelType.GROUP_DM: case ChannelType.GROUP_DM:
throw new HTTPError("You can't create a dm channel in a guild"); throw new HTTPError("You can't create a dm channel in a guild");
// TODO: check if guild is community server
case ChannelType.GUILD_STORE: case ChannelType.GUILD_STORE:
case ChannelType.GUILD_NEWS:
default: default:
throw new HTTPError("Not yet supported"); throw new HTTPError("Not yet supported");
} }
if (!channel.permission_overwrites) channel.permission_overwrites = []; if (!channel.permission_overwrites) channel.permission_overwrites = [];
// TODO: auto generate position // TODO: eagerly auto generate position of all guild channels
channel = { channel = {
...channel, ...channel,
...(!opts?.keepId && { id: Snowflake.generate() }), ...(!opts?.keepId && { id: Snowflake.generate() }),
created_at: new Date(), created_at: new Date(),
position: channel.position || 0, position: (channel.type === ChannelType.UNHANDLED ? 0 : channel.position) || 0,
}; };
await Promise.all([ await Promise.all([
@ -231,11 +234,13 @@ export class Channel extends BaseClass {
const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) }); const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) });
// TODO: check config for max number of recipients // TODO: check config for max number of recipients
/** if you want to disallow note to self channels, uncomment the conditional below
if (otherRecipientsUsers.length !== recipients.length) { if (otherRecipientsUsers.length !== recipients.length) {
throw new HTTPError("Recipient/s not found"); throw new HTTPError("Recipient/s not found");
} }
**/
const type = recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_DM; const type = recipients.length > 1 ? ChannelType.DM : ChannelType.GROUP_DM;
let channel = null; let channel = null;
@ -288,7 +293,8 @@ export class Channel extends BaseClass {
await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id }); await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id });
} }
return channel_dto.excludedRecipients([creator_user_id]); if (recipients.length === 1) return channel_dto;
else return channel_dto.excludedRecipients([creator_user_id]);
} }
static async removeRecipientFromChannel(channel: Channel, user_id: string) { static async removeRecipientFromChannel(channel: Channel, user_id: string) {
@ -354,4 +360,5 @@ export interface ChannelPermissionOverwrite {
export enum ChannelPermissionOverwriteType { export enum ChannelPermissionOverwriteType {
role = 0, role = 0,
member = 1, member = 1,
group = 2,
} }

View File

@ -2,7 +2,7 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass"; import { BaseClass } from "./BaseClass";
import { User } from "./User"; import { User } from "./User";
export interface PublicConnectedAccount extends Pick<ConnectedAccount, "name" | "type" | "verifie"> {} export interface PublicConnectedAccount extends Pick<ConnectedAccount, "name" | "type" | "verified"> {}
@Entity("connected_accounts") @Entity("connected_accounts")
export class ConnectedAccount extends BaseClass { export class ConnectedAccount extends BaseClass {
@ -35,7 +35,7 @@ export class ConnectedAccount extends BaseClass {
type: string; type: string;
@Column() @Column()
verifie: boolean; verified: boolean;
@Column({ select: false }) @Column({ select: false })
visibility: number; visibility: number;

View File

@ -85,8 +85,8 @@ export class Member extends BaseClassWithoutId {
@Column() @Column()
joined_at: Date; joined_at: Date;
@Column({ type: "bigint", nullable: true }) @Column()
premium_since?: number; premium_since?: Date;
@Column() @Column()
deaf: boolean; deaf: boolean;
@ -245,7 +245,7 @@ export class Member extends BaseClassWithoutId {
nick: undefined, nick: undefined,
roles: [guild_id], // @everyone role roles: [guild_id], // @everyone role
joined_at: new Date(), joined_at: new Date(),
premium_since: (new Date()).getTime(), premium_since: new Date(),
deaf: false, deaf: false,
mute: false, mute: false,
pending: false, pending: false,

View File

@ -12,11 +12,13 @@ export interface Interaction {
} }
export enum InteractionType { export enum InteractionType {
SelfCommand = 0,
Ping = 1, Ping = 1,
ApplicationCommand = 2, ApplicationCommand = 2,
} }
export enum InteractionResponseType { export enum InteractionResponseType {
SelfCommandResponse = 0,
Pong = 1, Pong = 1,
Acknowledge = 2, Acknowledge = 2,
ChannelMessage = 3, ChannelMessage = 3,