mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-10 20:52:42 +01:00
Merge branch 'master' into cdn-s3
This commit is contained in:
commit
4d04e6fcc5
@ -9,6 +9,8 @@ export const NO_AUTHORIZATION_ROUTES = [
|
||||
"/ping",
|
||||
"/gateway",
|
||||
"/experiments",
|
||||
"/-/readyz",
|
||||
"/-/healthz",
|
||||
/\/guilds\/\d+\/widget\.(json|png)/
|
||||
];
|
||||
|
||||
|
17
api/src/routes/-/healthz.ts
Normal file
17
api/src/routes/-/healthz.ts
Normal 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
api/src/routes/-/readyz.ts
Normal file
17
api/src/routes/-/readyz.ts
Normal 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";
|
||||
@ -186,33 +187,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
api/src/routes/guilds/#guild_id/prune.ts
Normal file
82
api/src/routes/guilds/#guild_id/prune.ts
Normal 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;
|
@ -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] } } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ const dirs = ["api", "util", "cdn", "gateway", "bundle"];
|
||||
|
||||
const verbose = argv.includes("verbose") || argv.includes("v");
|
||||
|
||||
if(argv.includes("clean")){
|
||||
dirs.forEach(a=>{
|
||||
var d = "../"+a+"/dist";
|
||||
if(fse.existsSync(d)) {
|
||||
fse.rmSync(d,{recursive: true});
|
||||
if(verbose) console.log(`Deleted ${d}!`);
|
||||
if (argv.includes("clean")) {
|
||||
dirs.forEach((a) => {
|
||||
var d = "../" + a + "/dist";
|
||||
if (fse.existsSync(d)) {
|
||||
fse.rmSync(d, { recursive: true });
|
||||
if (verbose) console.log(`Deleted ${d}!`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -24,9 +24,9 @@ fse.copySync(
|
||||
path.join(__dirname, "..", "dist", "api", "client_test")
|
||||
);
|
||||
fse.copySync(path.join(__dirname, "..", "..", "api", "locales"), path.join(__dirname, "..", "dist", "api", "locales"));
|
||||
dirs.forEach(a=>{
|
||||
fse.copySync("../"+a+"/src", "dist/"+a+"/src");
|
||||
if(verbose) console.log(`Copied ${"../"+a+"/dist"} -> ${"dist/"+a+"/src"}!`);
|
||||
dirs.forEach((a) => {
|
||||
fse.copySync("../" + a + "/src", "dist/" + a + "/src");
|
||||
if (verbose) console.log(`Copied ${"../" + a + "/dist"} -> ${"dist/" + a + "/src"}!`);
|
||||
});
|
||||
|
||||
console.log("Copying src files done");
|
||||
@ -34,10 +34,11 @@ console.log("Compiling src files ...");
|
||||
|
||||
console.log(
|
||||
execSync(
|
||||
"node \"" +
|
||||
'node "' +
|
||||
path.join(__dirname, "..", "node_modules", "typescript", "lib", "tsc.js") +
|
||||
"\" -p \"" +
|
||||
path.join(__dirname, "..") + "\"",
|
||||
'" -p "' +
|
||||
path.join(__dirname, "..") +
|
||||
'"',
|
||||
{
|
||||
cwd: path.join(__dirname, ".."),
|
||||
shell: true,
|
||||
|
@ -84,6 +84,9 @@ export class Member extends BaseClassWithoutId {
|
||||
@Column({ type: "simple-json" })
|
||||
settings: UserGuildSettings;
|
||||
|
||||
@Column({ nullable: true })
|
||||
last_message_id?: string;
|
||||
|
||||
// TODO: update
|
||||
// @Column({ type: "simple-json" })
|
||||
// read_state: ReadState;
|
||||
|
@ -84,7 +84,7 @@ export class Snowflake {
|
||||
}
|
||||
|
||||
static generate() {
|
||||
var time = BigInt(Date.now() - Snowflake.EPOCH) << 22n;
|
||||
var time = BigInt(Date.now() - Snowflake.EPOCH) << BigInt(22);
|
||||
var worker = Snowflake.workerId << 17n;
|
||||
var process = Snowflake.processId << 12n;
|
||||
var increment = Snowflake.INCREMENT++;
|
||||
|
Loading…
Reference in New Issue
Block a user