Merge branch 'master' into sticker

This commit is contained in:
Flam3rboy
2021-10-15 13:32:26 +02:00
20 changed files with 265 additions and 47 deletions
BIN
View File
Binary file not shown.
+5 -3
View File
@@ -38,6 +38,8 @@
"homepage": "https://fosscord.com",
"devDependencies": {
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.8",
"@babel/preset-typescript": "^7.15.0",
"@types/amqplib": "^0.8.1",
"@types/bcrypt": "^5.0.0",
"@types/express": "^4.17.9",
@@ -45,6 +47,7 @@
"@types/jest": "^27.0.1",
"@types/jest-expect-message": "^1.0.3",
"@types/jsonwebtoken": "^8.5.0",
"@types/morgan": "^1.9.3",
"@types/multer": "^1.4.5",
"@types/node": "^14.17.9",
"@types/node-fetch": "^2.5.7",
@@ -57,8 +60,7 @@
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"typescript": "^4.4.2",
"typescript-json-schema": "0.50.1",
"@types/morgan": "^1.9.3"
"typescript-json-schema": "0.50.1"
},
"dependencies": {
"@fosscord/util": "file:../util",
@@ -77,7 +79,7 @@
"i18next-node-fs-backend": "^2.1.3",
"image-size": "^1.0.0",
"jsonwebtoken": "^8.5.1",
"lambert-server": "^1.2.11",
"lambert-server": "^1.2.12",
"missing-native-js-functions": "^1.2.17",
"morgan": "^1.10.0",
"multer": "^1.4.2",
+2
View File
@@ -9,6 +9,8 @@ export const NO_AUTHORIZATION_ROUTES = [
"/ping",
"/gateway",
"/experiments",
"/-/readyz",
"/-/healthz",
/\/guilds\/\d+\/widget\.(json|png)/
];
+17
View File
@@ -0,0 +1,17 @@
import { Router, Response, Request } from "express";
import { route } from "@fosscord/api";
import { getConnection } from "typeorm";
const router = Router();
router.get("/", route({}), (req: Request, res: Response) => {
try {
// test that the database is alive & responding
getConnection();
return res.sendStatus(200);
} catch(e) {
res.sendStatus(503);
}
});
export default router;
+17
View File
@@ -0,0 +1,17 @@
import { Router, Response, Request } from "express";
import { route } from "@fosscord/api";
import { getConnection } from "typeorm";
const router = Router();
router.get("/", route({}), (req: Request, res: Response) => {
try {
// test that the database is alive & responding
getConnection();
return res.sendStatus(200);
} catch(e) {
res.sendStatus(503);
}
});
export default router;
@@ -10,7 +10,8 @@ import {
getPermission,
Message,
MessageCreateEvent,
uploadFile
uploadFile,
Member
} from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
@@ -187,33 +188,34 @@ router.post(
message = await message.save();
await channel.assign({ last_message_id: message.id }).save();
if (channel.isDm()) {
const channel_dto = await DmChannelDTO.from(channel);
for (let recipient of channel.recipients!) {
if (recipient.closed) {
await emitEvent({
event: "CHANNEL_CREATE",
data: channel_dto.excludedRecipients([recipient.user_id]),
user_id: recipient.user_id
});
}
}
//Only one recipients should be closed here, since in group DMs the recipient is deleted not closed
await Promise.all(
channel
.recipients!.filter((r) => r.closed)
.map(async (r) => {
r.closed = false;
return await r.save();
})
channel.recipients!.map((recipient) => {
if (recipient.closed) {
recipient.closed = false;
return Promise.all([
recipient.save(),
emitEvent({
event: "CHANNEL_CREATE",
data: channel_dto.excludedRecipients([recipient.user_id]),
user_id: recipient.user_id
})
]);
}
})
);
}
await emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent);
await Promise.all([
channel.assign({ last_message_id: message.id }).save(),
new Member({ id: req.user_id, last_message_id: message.id }).save(),
emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent)
]);
postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error
return res.json(message);
+82
View File
@@ -0,0 +1,82 @@
import { Router, Request, Response } from "express";
import { Guild, Member, Snowflake } from "@fosscord/util";
import { LessThan, IsNull } from "typeorm";
import { route } from "@fosscord/api";
const router = Router();
//Returns all inactive members, respecting role hierarchy
export const inactiveMembers = async (guild_id: string, user_id: string, days: number, roles: string[] = []) => {
var date = new Date();
date.setDate(date.getDate() - days);
//Snowflake should have `generateFromTime` method? Or similar?
var minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
var members = await Member.find({
where: [
{
guild_id,
last_message_id: LessThan(minId.toString())
},
{
last_message_id: IsNull()
}
],
relations: ["roles"]
});
console.log(members);
if (!members.length) return [];
//I'm sure I can do this in the above db query ( and it would probably be better to do so ), but oh well.
if (roles.length && members.length) members = members.filter((user) => user.roles?.some((role) => roles.includes(role.id)));
const me = await Member.findOneOrFail({ id: user_id, guild_id }, { relations: ["roles"] });
const myHighestRole = Math.max(...(me.roles?.map((x) => x.position) || []));
const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
members = members.filter(
(member) =>
member.id !== guild.owner_id && //can't kick owner
member.roles?.some(
(role) =>
role.position < myHighestRole || //roles higher than me can't be kicked
me.id === guild.owner_id //owner can kick anyone
)
);
return members;
};
router.get("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => {
const days = parseInt(req.query.days as string);
var roles = req.query.include_roles;
if (typeof roles === "string") roles = [roles]; //express will return array otherwise
const members = await inactiveMembers(req.params.guild_id, req.user_id, days, roles as string[]);
res.send({ pruned: members.length });
});
export interface PruneSchema {
/**
* @min 0
*/
days: number;
}
router.post("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => {
const days = parseInt(req.body.days);
var roles = req.query.include_roles;
if (typeof roles === "string") roles = [roles];
const { guild_id } = req.params;
const members = await inactiveMembers(guild_id, req.user_id, days, roles as string[]);
await Promise.all(members.map((x) => Member.removeFromGuild(x.id, guild_id)));
res.send({ purged: members.length });
});
export default router;
+4 -4
View File
@@ -10,9 +10,9 @@ export async function initInstance() {
if (autoJoin.enabled && !autoJoin.guilds?.length) {
let guild = await Guild.findOne({});
if (!guild) guild = await Guild.createGuild({});
// @ts-ignore
await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
if (guild) {
// @ts-ignore
await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
}
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ const request = async (path: string, opts: any = {}): Promise<any> => {
var data = await response.text();
try {
data = JSON.stringify(data);
data = JSON.parse(data);
if (response.status >= 400) throw data;
return data;
} catch (error) {