diff --git a/src/api/Server.ts b/src/api/Server.ts
index 4660e6b1..0177be40 100644
--- a/src/api/Server.ts
+++ b/src/api/Server.ts
@@ -22,7 +22,7 @@ import { Authentication, CORS } from "./middlewares/";
import { Config, initDatabase, initEvent, Sentry } from "@fosscord/util";
import { ErrorHandler } from "./middlewares/ErrorHandler";
import { BodyParser } from "./middlewares/BodyParser";
-import { Router, Request, Response, NextFunction } from "express";
+import { Router, Request, Response } from "express";
import path from "path";
import { initRateLimits } from "./middlewares/RateLimit";
import TestClient from "./middlewares/TestClient";
@@ -32,12 +32,12 @@ import { initInstance } from "./util/handlers/Instance";
import { registerRoutes } from "@fosscord/util";
import { red } from "picocolors";
-export interface FosscordServerOptions extends ServerOptions {}
+export type FosscordServerOptions = ServerOptions;
declare global {
+ // eslint-disable-next-line @typescript-eslint/no-namespace
namespace Express {
interface Request {
- // @ts-ignore
server: FosscordServer;
}
}
@@ -47,6 +47,7 @@ export class FosscordServer extends Server {
public declare options: FosscordServerOptions;
constructor(opts?: Partial<FosscordServerOptions>) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
super({ ...opts, errorHandler: false, jsonBody: false });
}
@@ -58,12 +59,12 @@ export class FosscordServer extends Server {
await initInstance();
await Sentry.init(this.app);
- let logRequests = process.env["LOG_REQUESTS"] != undefined;
+ const logRequests = process.env["LOG_REQUESTS"] != undefined;
if (logRequests) {
this.app.use(
morgan("combined", {
skip: (req, res) => {
- var skip = !(
+ let skip = !(
process.env["LOG_REQUESTS"]?.includes(
res.statusCode.toString(),
) ?? false
@@ -80,7 +81,9 @@ export class FosscordServer extends Server {
this.app.use(BodyParser({ inflate: true, limit: "10mb" }));
const app = this.app;
- const api = Router(); // @ts-ignore
+ const api = Router();
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
this.app = api;
api.use(Authentication);
@@ -95,7 +98,7 @@ export class FosscordServer extends Server {
// 404 is not an error in express, so this should not be an error middleware
// this is a fine place to put the 404 handler because its after we register the routes
// and since its not an error middleware, our error handler below still works.
- api.use("*", (req: Request, res: Response, next: NextFunction) => {
+ api.use("*", (req: Request, res: Response) => {
res.status(404).json({
message: "404 endpoint not found",
code: 0,
diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts
index 208c54d6..8e0dcc7c 100644
--- a/src/api/middlewares/Authentication.ts
+++ b/src/api/middlewares/Authentication.ts
@@ -54,11 +54,12 @@ export const API_PREFIX = /^\/api(\/v\d+)?/;
export const API_PREFIX_TRAILING_SLASH = /^\/api(\/v\d+)?\//;
declare global {
+ // eslint-disable-next-line @typescript-eslint/no-namespace
namespace Express {
interface Request {
user_id: string;
user_bot: boolean;
- token: string;
+ token: { id: string; iat: number };
rights: Rights;
}
}
@@ -87,7 +88,7 @@ export async function Authentication(
try {
const { jwtSecret } = Config.get().security;
- const { decoded, user }: any = await checkToken(
+ const { decoded, user } = await checkToken(
req.headers.authorization,
jwtSecret,
);
@@ -97,7 +98,8 @@ export async function Authentication(
req.user_bot = user.bot;
req.rights = new Rights(Number(user.rights));
return next();
- } catch (error: any) {
- return next(new HTTPError(error?.toString(), 400));
+ } catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return next(new HTTPError(error!.toString(), 400));
}
}
diff --git a/src/api/middlewares/RateLimit.ts b/src/api/middlewares/RateLimit.ts
index ae102c94..1a28f356 100644
--- a/src/api/middlewares/RateLimit.ts
+++ b/src/api/middlewares/RateLimit.ts
@@ -42,7 +42,7 @@ type RateLimit = {
expires_at: Date;
};
-let Cache = new Map<string, RateLimit>();
+const Cache = new Map<string, RateLimit>();
const EventRateLimit = "RATELIMIT";
export default function rateLimit(opts: {
@@ -57,12 +57,8 @@ export default function rateLimit(opts: {
error?: boolean;
success?: boolean;
onlyIp?: boolean;
-}): any {
- return async (
- req: Request,
- res: Response,
- next: NextFunction,
- ): Promise<any> => {
+}) {
+ return async (req: Request, res: Response, next: NextFunction) => {
// exempt user? if so, immediately short circuit
if (req.user_id) {
const rights = await getRights(req.user_id);
@@ -85,7 +81,7 @@ export default function rateLimit(opts: {
)
max_hits = opts.MODIFY;
- let offender = Cache.get(executor_id + bucket_id);
+ const offender = Cache.get(executor_id + bucket_id);
if (offender) {
let reset = offender.expires_at.getTime();
diff --git a/src/api/routes/applications/#id/bot/index.ts b/src/api/routes/applications/#id/bot/index.ts
index 7d0a637e..9bc3c571 100644
--- a/src/api/routes/applications/#id/bot/index.ts
+++ b/src/api/routes/applications/#id/bot/index.ts
@@ -64,8 +64,8 @@ router.post("/", route({}), async (req: Request, res: Response) => {
});
router.post("/reset", route({}), async (req: Request, res: Response) => {
- let bot = await User.findOneOrFail({ where: { id: req.params.id } });
- let owner = await User.findOneOrFail({ where: { id: req.user_id } });
+ const bot = await User.findOneOrFail({ where: { id: req.params.id } });
+ const owner = await User.findOneOrFail({ where: { id: req.user_id } });
if (owner.id != req.user_id)
throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
@@ -80,7 +80,7 @@ router.post("/reset", route({}), async (req: Request, res: Response) => {
await bot.save();
- let token = await generateToken(bot.id);
+ const token = await generateToken(bot.id);
res.json({ token }).status(200);
});
diff --git a/src/api/routes/applications/#id/index.ts b/src/api/routes/applications/#id/index.ts
index 2b283880..59e90168 100644
--- a/src/api/routes/applications/#id/index.ts
+++ b/src/api/routes/applications/#id/index.ts
@@ -20,10 +20,8 @@ import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
import {
Application,
- OrmUtils,
DiscordApiErrors,
ApplicationModifySchema,
- User,
} from "@fosscord/util";
import { verifyToken } from "node-2fa";
import { HTTPError } from "lambert-server";
diff --git a/src/api/routes/applications/#id/skus.ts b/src/api/routes/applications/#id/skus.ts
index 23e6eb6b..5a3a479f 100644
--- a/src/api/routes/applications/#id/skus.ts
+++ b/src/api/routes/applications/#id/skus.ts
@@ -18,7 +18,6 @@
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
-import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
const router: Router = Router();
diff --git a/src/api/routes/applications/index.ts b/src/api/routes/applications/index.ts
index 6ea24870..859ee145 100644
--- a/src/api/routes/applications/index.ts
+++ b/src/api/routes/applications/index.ts
@@ -28,7 +28,7 @@ import {
const router: Router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
- let results = await Application.find({
+ const results = await Application.find({
where: { owner: { id: req.user_id } },
relations: ["owner", "bot"],
});
diff --git a/src/api/routes/auth/generate-registration-tokens.ts b/src/api/routes/auth/generate-registration-tokens.ts
index 64e3b0a6..c79d2a59 100644
--- a/src/api/routes/auth/generate-registration-tokens.ts
+++ b/src/api/routes/auth/generate-registration-tokens.ts
@@ -32,7 +32,7 @@ router.get(
? parseInt(req.query.length as string)
: 255;
- let tokens: ValidRegistrationToken[] = [];
+ const tokens: ValidRegistrationToken[] = [];
for (let i = 0; i < count; i++) {
const token = ValidRegistrationToken.create({
diff --git a/src/api/routes/auth/login.ts b/src/api/routes/auth/login.ts
index 5f1b7a14..4d367546 100644
--- a/src/api/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -74,7 +74,7 @@ router.post(
"totp_secret",
"mfa_enabled",
],
- }).catch((e) => {
+ }).catch(() => {
throw FieldErrors({
login: {
message: req.t("auth:login.INVALID_LOGIN"),
diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index 42485535..65cdd397 100644
--- a/src/api/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -27,8 +27,8 @@ router.post(
"/",
route({ body: "TotpSchema" }),
async (req: Request, res: Response) => {
- const { code, ticket, gift_code_sku_id, login_source } =
- req.body as TotpSchema;
+ // const { code, ticket, gift_code_sku_id, login_source } =
+ const { code, ticket } = req.body as TotpSchema;
const user = await User.findOneOrFail({
where: {
@@ -47,7 +47,7 @@ router.post(
});
if (!backup) {
- const ret = verifyToken(user.totp_secret!, code);
+ const ret = verifyToken(user.totp_secret || "", code);
if (!ret || ret.delta != 0)
throw new HTTPError(
req.t("auth:login.INVALID_TOTP_CODE"),
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index b98f17c5..0bf8efae 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -36,7 +36,7 @@ import {
} from "@fosscord/api";
import bcrypt from "bcrypt";
import { HTTPError } from "lambert-server";
-import { LessThan, MoreThan } from "typeorm";
+import { MoreThan } from "typeorm";
const router: Router = Router();
@@ -53,12 +53,12 @@ router.post(
let regTokenUsed = false;
if (req.get("Referrer") && req.get("Referrer")?.includes("token=")) {
// eg theyre on https://staging.fosscord.com/register?token=whatever
- const token = req.get("Referrer")!.split("token=")[1].split("&")[0];
+ const token = req.get("Referrer")?.split("token=")[1].split("&")[0];
if (token) {
- const regToken = await ValidRegistrationToken.findOne({
+ const regToken = await ValidRegistrationToken.findOneOrFail({
where: { token, expires_at: MoreThan(new Date()) },
});
- await ValidRegistrationToken.delete({ token });
+ await regToken.remove();
regTokenUsed = true;
console.log(
`[REGISTER] Registration token ${token} used for registration!`,
@@ -71,7 +71,7 @@ router.post(
}
// email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick
- let email = adjustEmail(body.email);
+ const email = adjustEmail(body.email);
// check if registration is allowed
if (!regTokenUsed && !register.allowNewRegistration) {
diff --git a/src/api/routes/channels/#channel_id/followers.ts b/src/api/routes/channels/#channel_id/followers.ts
index 0ff784df..a9d5d4ee 100644
--- a/src/api/routes/channels/#channel_id/followers.ts
+++ b/src/api/routes/channels/#channel_id/followers.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Router, Response, Request } from "express";
+import { Router } from "express";
const router: Router = Router();
// TODO:
diff --git a/src/api/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts
index 5bcd3a84..4a2023d2 100644
--- a/src/api/routes/channels/#channel_id/index.ts
+++ b/src/api/routes/channels/#channel_id/index.ts
@@ -92,7 +92,7 @@ router.patch(
"/",
route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }),
async (req: Request, res: Response) => {
- var payload = req.body as ChannelModifySchema;
+ const payload = req.body as ChannelModifySchema;
const { channel_id } = req.params;
if (payload.icon)
payload.icon = await handleFile(
diff --git a/src/api/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts
index b9105bea..49620aaf 100644
--- a/src/api/routes/channels/#channel_id/invites.ts
+++ b/src/api/routes/channels/#channel_id/invites.ts
@@ -86,7 +86,6 @@ router.get(
"/",
route({ permission: "MANAGE_CHANNELS" }),
async (req: Request, res: Response) => {
- const { user_id } = req;
const { channel_id } = req.params;
const channel = await Channel.findOneOrFail({
where: { id: channel_id },
diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
index 3d9a69be..9ea33340 100644
--- a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -30,7 +30,6 @@ import {
Snowflake,
uploadFile,
MessageCreateSchema,
- DiscordApiErrors,
} from "@fosscord/util";
import { Router, Response, Request } from "express";
import multer from "multer";
@@ -59,7 +58,7 @@ router.patch(
}),
async (req: Request, res: Response) => {
const { message_id, channel_id } = req.params;
- var body = req.body as MessageCreateSchema;
+ let body = req.body as MessageCreateSchema;
const message = await Message.findOneOrFail({
where: { id: message_id, channel_id },
@@ -85,6 +84,7 @@ router.patch(
const new_message = await handleMessage({
...message,
// TODO: should message_reference be overridable?
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
message_reference: message.message_reference,
...body,
@@ -127,7 +127,7 @@ router.put(
}),
async (req: Request, res: Response) => {
const { channel_id, message_id } = req.params;
- var body = req.body as MessageCreateSchema;
+ const body = req.body as MessageCreateSchema;
const attachments: Attachment[] = [];
const rights = await getRights(req.user_id);
@@ -171,7 +171,7 @@ router.put(
const embeds = body.embeds || [];
if (body.embed) embeds.push(body.embed);
- let message = await handleMessage({
+ const message = await handleMessage({
...body,
type: 0,
pinned: false,
@@ -197,7 +197,10 @@ router.put(
channel.save(),
]);
- postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error
+ // no await as it shouldnt block the message send function and silently catch error
+ postHandleMessage(message).catch((e) =>
+ console.error("[Message] post-message handler failed", e),
+ );
return res.json(message);
},
diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts
index bf6d43e5..c3598b24 100644
--- a/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts
@@ -165,13 +165,13 @@ router.put(
x.emoji.name === emoji.name,
);
- if (!already_added) req.permission!.hasThrow("ADD_REACTIONS");
+ if (!already_added) req.permission?.hasThrow("ADD_REACTIONS");
if (emoji.id) {
const external_emoji = await Emoji.findOneOrFail({
where: { id: emoji.id },
});
- if (!already_added) req.permission!.hasThrow("USE_EXTERNAL_EMOJIS");
+ if (!already_added) req.permission?.hasThrow("USE_EXTERNAL_EMOJIS");
emoji.animated = external_emoji.animated;
emoji.name = external_emoji.name;
}
@@ -214,7 +214,8 @@ router.delete(
"/:emoji/:user_id",
route({}),
async (req: Request, res: Response) => {
- var { message_id, channel_id, user_id } = req.params;
+ let { user_id } = req.params;
+ const { message_id, channel_id } = req.params;
const emoji = getEmoji(req.params.emoji);
diff --git a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
index ad5d24c8..ee039d3e 100644
--- a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
+++ b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
@@ -50,7 +50,7 @@ router.post(
const rights = await getRights(req.user_id);
rights.hasThrow("SELF_DELETE_MESSAGES");
- let superuser = rights.has("MANAGE_MESSAGES");
+ const superuser = rights.has("MANAGE_MESSAGES");
const permission = await getPermission(
req.user_id,
channel?.guild_id,
diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index 6e4f06a2..76f6a0dc 100644
--- a/src/api/routes/channels/#channel_id/messages/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -31,23 +31,16 @@ import {
Snowflake,
uploadFile,
Member,
- Role,
MessageCreateSchema,
ReadState,
- DiscordApiErrors,
- getRights,
Rights,
+ Reaction,
+ User,
} from "@fosscord/util";
import { HTTPError } from "lambert-server";
-import {
- handleMessage,
- postHandleMessage,
- route,
- getIpAdress,
-} from "@fosscord/api";
+import { handleMessage, postHandleMessage, route } from "@fosscord/api";
import multer from "multer";
-import { yellow } from "picocolors";
-import { FindManyOptions, LessThan, MoreThan } from "typeorm";
+import { FindManyOptions, FindOperator, LessThan, MoreThan } from "typeorm";
import { URL } from "url";
const router: Router = Router();
@@ -93,7 +86,7 @@ router.get("/", async (req: Request, res: Response) => {
if (limit < 1 || limit > 100)
throw new HTTPError("limit must be between 1 and 100", 422);
- var halfLimit = Math.floor(limit / 2);
+ const halfLimit = Math.floor(limit / 2);
const permissions = await getPermission(
req.user_id,
@@ -103,7 +96,9 @@ router.get("/", async (req: Request, res: Response) => {
permissions.hasThrow("VIEW_CHANNEL");
if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
- var query: FindManyOptions<Message> & { where: { id?: any } } = {
+ const query: FindManyOptions<Message> & {
+ where: { id?: FindOperator<string> | FindOperator<string>[] };
+ } = {
order: { timestamp: "DESC" },
take: limit,
where: { channel_id },
@@ -140,23 +135,21 @@ router.get("/", async (req: Request, res: Response) => {
const endpoint = Config.get().cdn.endpointPublic;
return res.json(
- messages.map((x: any) => {
- (x.reactions || []).forEach((x: any) => {
- // @ts-ignore
- if ((x.user_ids || []).includes(req.user_id)) x.me = true;
- // @ts-ignore
- delete x.user_ids;
+ messages.map((x: Partial<Message>) => {
+ (x.reactions || []).forEach((y: Partial<Reaction>) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore
+ if ((y.user_ids || []).includes(req.user_id)) y.me = true;
+ delete y.user_ids;
});
- // @ts-ignore
if (!x.author)
- x.author = {
+ x.author = User.create({
id: "4",
discriminator: "0000",
username: "Fosscord Ghost",
- public_flags: "0",
- avatar: null,
- };
- x.attachments?.forEach((y: any) => {
+ public_flags: 0,
+ });
+ x.attachments?.forEach((y: Attachment) => {
// dynamically set attachment proxy_url in case the endpoint changed
const uri = y.proxy_url.startsWith("http")
? y.proxy_url
@@ -168,7 +161,7 @@ router.get("/", async (req: Request, res: Response) => {
/**
Some clients ( discord.js ) only check if a property exists within the response,
- which causes erorrs when, say, the `application` property is `null`.
+ which causes errors when, say, the `application` property is `null`.
**/
// for (var curr in x) {
@@ -216,7 +209,7 @@ router.post(
}),
async (req: Request, res: Response) => {
const { channel_id } = req.params;
- var body = req.body as MessageCreateSchema;
+ const body = req.body as MessageCreateSchema;
const attachments: Attachment[] = [];
const channel = await Channel.findOneOrFail({
@@ -244,7 +237,7 @@ router.post(
}
if (!req.rights.has(Rights.FLAGS.BYPASS_RATE_LIMITS)) {
- var limits = Config.get().limits;
+ const limits = Config.get().limits;
if (limits.absoluteRate.register.enabled) {
const count = await Message.count({
where: {
@@ -269,7 +262,7 @@ router.post(
}
const files = (req.files as Express.Multer.File[]) ?? [];
- for (var currFile of files) {
+ for (const currFile of files) {
try {
const file = await uploadFile(
`/attachments/${channel.id}`,
@@ -279,13 +272,13 @@ router.post(
Attachment.create({ ...file, proxy_url: file.url }),
);
} catch (error) {
- return res.status(400).json({ message: error!.toString() });
+ return res.status(400).json({ message: error?.toString() });
}
}
const embeds = body.embeds || [];
if (body.embed) embeds.push(body.embed);
- let message = await handleMessage({
+ const message = await handleMessage({
...body,
type: 0,
pinned: false,
@@ -304,7 +297,7 @@ router.post(
// Only one recipients should be closed here, since in group DMs the recipient is deleted not closed
await Promise.all(
- channel.recipients!.map((recipient) => {
+ channel.recipients?.map((recipient) => {
if (recipient.closed) {
recipient.closed = false;
return Promise.all([
@@ -318,7 +311,7 @@ router.post(
}),
]);
}
- }),
+ }) || [],
);
}
@@ -332,6 +325,7 @@ router.post(
});
}
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
message.member.roles = message.member.roles
.filter((x) => x.id != x.guild_id)
@@ -362,7 +356,10 @@ router.post(
channel.save(),
]);
- postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error
+ // no await as it shouldnt block the message send function and silently catch error
+ postHandleMessage(message).catch((e) =>
+ console.error("[Message] post-message handler failed", e),
+ );
return res.json(message);
},
diff --git a/src/api/routes/channels/#channel_id/permissions.ts b/src/api/routes/channels/#channel_id/permissions.ts
index 7aa29700..da448678 100644
--- a/src/api/routes/channels/#channel_id/permissions.ts
+++ b/src/api/routes/channels/#channel_id/permissions.ts
@@ -43,7 +43,7 @@ router.put(
const { channel_id, overwrite_id } = req.params;
const body = req.body as ChannelPermissionOverwriteSchema;
- var channel = await Channel.findOneOrFail({
+ const channel = await Channel.findOneOrFail({
where: { id: channel_id },
});
if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
@@ -56,22 +56,24 @@ router.put(
throw new HTTPError("user not found", 404);
} else throw new HTTPError("type not supported", 501);
- //@ts-ignore
- var overwrite: ChannelPermissionOverwrite =
+ let overwrite: ChannelPermissionOverwrite | undefined =
channel.permission_overwrites?.find((x) => x.id === overwrite_id);
if (!overwrite) {
- // @ts-ignore
overwrite = {
id: overwrite_id,
type: body.type,
+ allow: "0",
+ deny: "0",
};
- channel.permission_overwrites!.push(overwrite);
+ channel.permission_overwrites?.push(overwrite);
}
overwrite.allow = String(
- req.permission!.bitfield & (BigInt(body.allow) || BigInt("0")),
+ (req.permission?.bitfield || 0n) &
+ (BigInt(body.allow) || BigInt("0")),
);
overwrite.deny = String(
- req.permission!.bitfield & (BigInt(body.deny) || BigInt("0")),
+ (req.permission?.bitfield || 0n) &
+ (BigInt(body.deny) || BigInt("0")),
);
await Promise.all([
@@ -99,7 +101,7 @@ router.delete(
});
if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
- channel.permission_overwrites = channel.permission_overwrites!.filter(
+ channel.permission_overwrites = channel.permission_overwrites?.filter(
(x) => x.id === overwrite_id,
);
diff --git a/src/api/routes/channels/#channel_id/pins.ts b/src/api/routes/channels/#channel_id/pins.ts
index f48e0ff5..28419383 100644
--- a/src/api/routes/channels/#channel_id/pins.ts
+++ b/src/api/routes/channels/#channel_id/pins.ts
@@ -21,13 +21,11 @@ import {
ChannelPinsUpdateEvent,
Config,
emitEvent,
- getPermission,
Message,
MessageUpdateEvent,
DiscordApiErrors,
} from "@fosscord/util";
import { Router, Request, Response } from "express";
-import { HTTPError } from "lambert-server";
import { route } from "@fosscord/api";
const router: Router = Router();
@@ -43,7 +41,7 @@ router.put(
});
// * in dm channels anyone can pin messages -> only check for guilds
- if (message.guild_id) req.permission!.hasThrow("MANAGE_MESSAGES");
+ if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
const pinned_count = await Message.count({
where: { channel: { id: channel_id }, pinned: true },
@@ -83,7 +81,7 @@ router.delete(
const channel = await Channel.findOneOrFail({
where: { id: channel_id },
});
- if (channel.guild_id) req.permission!.hasThrow("MANAGE_MESSAGES");
+ if (channel.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
const message = await Message.findOneOrFail({
where: { id: message_id },
@@ -120,7 +118,7 @@ router.get(
async (req: Request, res: Response) => {
const { channel_id } = req.params;
- let pins = await Message.find({
+ const pins = await Message.find({
where: { channel_id: channel_id, pinned: true },
});
diff --git a/src/api/routes/channels/#channel_id/purge.ts b/src/api/routes/channels/#channel_id/purge.ts
index 05660acf..04d8cfa2 100644
--- a/src/api/routes/channels/#channel_id/purge.ts
+++ b/src/api/routes/channels/#channel_id/purge.ts
@@ -19,10 +19,9 @@
import { HTTPError } from "lambert-server";
import { route } from "@fosscord/api";
import { isTextChannel } from "./messages";
-import { FindManyOptions, Between, Not } from "typeorm";
+import { FindManyOptions, Between, Not, FindOperator } from "typeorm";
import {
Channel,
- Config,
emitEvent,
getPermission,
getRights,
@@ -69,7 +68,9 @@ router.post(
// TODO: send the deletion event bite-by-bite to prevent client stress
- var query: FindManyOptions<Message> & { where: { id?: any } } = {
+ const query: FindManyOptions<Message> & {
+ where: { id?: FindOperator<string> };
+ } = {
order: { id: "ASC" },
// take: limit,
where: {
@@ -93,7 +94,6 @@ router.post(
};
const messages = await Message.find(query);
- const endpoint = Config.get().cdn.endpointPublic;
if (messages.length == 0) {
res.sendStatus(304);
diff --git a/src/api/routes/channels/#channel_id/recipients.ts b/src/api/routes/channels/#channel_id/recipients.ts
index 6928dd34..252a8ef0 100644
--- a/src/api/routes/channels/#channel_id/recipients.ts
+++ b/src/api/routes/channels/#channel_id/recipients.ts
@@ -41,7 +41,7 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => {
if (channel.type !== ChannelType.GROUP_DM) {
const recipients = [
- ...channel.recipients!.map((r) => r.user_id),
+ ...(channel.recipients?.map((r) => r.user_id) || []),
user_id,
].unique();
@@ -51,11 +51,11 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => {
);
return res.status(201).json(new_channel);
} else {
- if (channel.recipients!.map((r) => r.user_id).includes(user_id)) {
+ if (channel.recipients?.map((r) => r.user_id).includes(user_id)) {
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
}
- channel.recipients!.push(
+ channel.recipients?.push(
Recipient.create({ channel_id: channel_id, user_id: user_id }),
);
await channel.save();
@@ -95,7 +95,7 @@ router.delete("/:user_id", route({}), async (req: Request, res: Response) => {
)
throw DiscordApiErrors.MISSING_PERMISSIONS;
- if (!channel.recipients!.map((r) => r.user_id).includes(user_id)) {
+ if (!channel.recipients?.map((r) => r.user_id).includes(user_id)) {
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
}
diff --git a/src/api/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts
index 511933c3..31cae747 100644
--- a/src/api/routes/channels/#channel_id/webhooks.ts
+++ b/src/api/routes/channels/#channel_id/webhooks.ts
@@ -55,10 +55,10 @@ router.post(
const webhook_count = await Webhook.count({ where: { channel_id } });
const { maxWebhooks } = Config.get().limits.channel;
- if (webhook_count > maxWebhooks)
+ if (maxWebhooks && webhook_count > maxWebhooks)
throw DiscordApiErrors.MAXIMUM_WEBHOOKS.withParams(maxWebhooks);
- var { avatar, name } = req.body as WebhookCreateSchema;
+ let { avatar, name } = req.body as WebhookCreateSchema;
name = trimSpecial(name);
// TODO: move this
diff --git a/src/api/routes/discoverable-guilds.ts b/src/api/routes/discoverable-guilds.ts
index 522861eb..8f90d73c 100644
--- a/src/api/routes/discoverable-guilds.ts
+++ b/src/api/routes/discoverable-guilds.ts
@@ -26,8 +26,8 @@ const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
const { offset, limit, categories } = req.query;
- var showAllGuilds = Config.get().guild.discovery.showAllGuilds;
- var configLimit = Config.get().guild.discovery.limit;
+ const showAllGuilds = Config.get().guild.discovery.showAllGuilds;
+ const configLimit = Config.get().guild.discovery.limit;
let guilds;
if (categories == undefined) {
guilds = showAllGuilds
diff --git a/src/api/routes/discovery.ts b/src/api/routes/discovery.ts
index 411c3bc5..1414a617 100644
--- a/src/api/routes/discovery.ts
+++ b/src/api/routes/discovery.ts
@@ -26,7 +26,8 @@ router.get("/categories", route({}), async (req: Request, res: Response) => {
// TODO:
// Get locale instead
- const { locale, primary_only } = req.query;
+ // const { locale, primary_only } = req.query;
+ const { primary_only } = req.query;
const out = primary_only
? await Categories.find()
diff --git a/src/api/routes/download/index.ts b/src/api/routes/download.ts
index 246c8834..b6c03a48 100644
--- a/src/api/routes/download/index.ts
+++ b/src/api/routes/download.ts
@@ -22,11 +22,6 @@ import { FieldErrors, Release } from "@fosscord/util";
const router = Router();
-/*
- TODO: Putting the download route in /routes/download.ts doesn't register the route, for some reason
- But putting it here *does*
-*/
-
router.get("/", route({}), async (req: Request, res: Response) => {
const { platform } = req.query;
diff --git a/src/api/routes/gifs/search.ts b/src/api/routes/gifs/search.ts
index 02022004..ae63d643 100644
--- a/src/api/routes/gifs/search.ts
+++ b/src/api/routes/gifs/search.ts
@@ -41,7 +41,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
},
);
- const { results } = (await response.json()) as any; // TODO: types
+ const { results } = await response.json();
res.json(results.map(parseGifResult)).status(200);
});
diff --git a/src/api/routes/gifs/trending-gifs.ts b/src/api/routes/gifs/trending-gifs.ts
index d3fdb00a..d0698fa0 100644
--- a/src/api/routes/gifs/trending-gifs.ts
+++ b/src/api/routes/gifs/trending-gifs.ts
@@ -41,7 +41,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
},
);
- const { results } = (await response.json()) as any; // TODO: types
+ const { results } = await response.json();
res.json(results.map(parseGifResult)).status(200);
});
diff --git a/src/api/routes/gifs/trending.ts b/src/api/routes/gifs/trending.ts
index 5dc43e85..5c872df8 100644
--- a/src/api/routes/gifs/trending.ts
+++ b/src/api/routes/gifs/trending.ts
@@ -25,7 +25,57 @@ import { HTTPError } from "lambert-server";
const router = Router();
-export function parseGifResult(result: any) {
+// TODO: Move somewhere else
+enum TENOR_GIF_TYPES {
+ gif,
+ mediumgif,
+ tinygif,
+ nanogif,
+ mp4,
+ loopedmp4,
+ tinymp4,
+ nanomp4,
+ webm,
+ tinywebm,
+ nanowebm,
+}
+
+type TENOR_MEDIA = {
+ preview: string;
+ url: string;
+ dims: number[];
+ size: number;
+};
+
+type TENOR_GIF = {
+ created: number;
+ hasaudio: boolean;
+ id: string;
+ media: { [type in keyof typeof TENOR_GIF_TYPES]: TENOR_MEDIA }[];
+ tags: string[];
+ title: string;
+ itemurl: string;
+ hascaption: boolean;
+ url: string;
+};
+
+type TENOR_CATEGORY = {
+ searchterm: string;
+ path: string;
+ image: string;
+ name: string;
+};
+
+type TENOR_CATEGORIES_RESULTS = {
+ tags: TENOR_CATEGORY[];
+};
+
+type TENOR_TRENDING_RESULTS = {
+ next: string;
+ results: TENOR_GIF[];
+};
+
+export function parseGifResult(result: TENOR_GIF) {
return {
id: result.id,
title: result.title,
@@ -50,7 +100,8 @@ export function getGifApiKey() {
router.get("/", route({}), async (req: Request, res: Response) => {
// TODO: Custom providers
// TODO: return gifs as mp4
- const { media_format, locale } = req.query;
+ // const { media_format, locale } = req.query;
+ const { locale } = req.query;
const apiKey = getGifApiKey();
@@ -75,11 +126,11 @@ router.get("/", route({}), async (req: Request, res: Response) => {
),
]);
- const { tags } = (await responseSource.json()) as any; // TODO: types
- const { results } = (await trendGifSource.json()) as any; //TODO: types;
+ const { tags } = (await responseSource.json()) as TENOR_CATEGORIES_RESULTS;
+ const { results } = (await trendGifSource.json()) as TENOR_TRENDING_RESULTS;
res.json({
- categories: tags.map((x: any) => ({
+ categories: tags.map((x) => ({
name: x.searchterm,
src: x.image,
})),
diff --git a/src/api/routes/guild-recommendations.ts b/src/api/routes/guild-recommendations.ts
index 13c08734..ac2ad9e7 100644
--- a/src/api/routes/guild-recommendations.ts
+++ b/src/api/routes/guild-recommendations.ts
@@ -25,10 +25,11 @@ import { Like } from "typeorm";
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
- const { limit, personalization_disabled } = req.query;
- var showAllGuilds = Config.get().guild.discovery.showAllGuilds;
+ // const { limit, personalization_disabled } = req.query;
+ const { limit } = req.query;
+ const showAllGuilds = Config.get().guild.discovery.showAllGuilds;
- const genLoadId = (size: Number) =>
+ const genLoadId = (size: number) =>
[...Array(size)]
.map(() => Math.floor(Math.random() * 16).toString(16))
.join("");
diff --git a/src/api/routes/guilds/#guild_id/bans.ts b/src/api/routes/guilds/#guild_id/bans.ts
index efb06fa0..b044689f 100644
--- a/src/api/routes/guilds/#guild_id/bans.ts
+++ b/src/api/routes/guilds/#guild_id/bans.ts
@@ -41,8 +41,8 @@ router.get(
async (req: Request, res: Response) => {
const { guild_id } = req.params;
- let bans = await Ban.find({ where: { guild_id: guild_id } });
- let promisesToAwait: object[] = [];
+ const bans = await Ban.find({ where: { guild_id: guild_id } });
+ const promisesToAwait: object[] = [];
const bansObj: object[] = [];
bans.filter((ban) => ban.user_id !== ban.executor_id); // pretend self-bans don't exist to prevent victim chasing
@@ -104,14 +104,14 @@ router.put(
if (
req.user_id === banned_user_id &&
- banned_user_id === req.permission!.cache.guild?.owner_id
+ banned_user_id === req.permission?.cache.guild?.owner_id
)
throw new HTTPError(
"You are the guild owner, hence can't ban yourself",
403,
);
- if (req.permission!.cache.guild?.owner_id === banned_user_id)
+ if (req.permission?.cache.guild?.owner_id === banned_user_id)
throw new HTTPError("You can't ban the owner", 400);
const banned_user = await User.getPublicUser(banned_user_id);
@@ -149,7 +149,7 @@ router.put(
const banned_user = await User.getPublicUser(req.params.user_id);
- if (req.permission!.cache.guild?.owner_id === req.params.user_id)
+ if (req.permission?.cache.guild?.owner_id === req.params.user_id)
throw new HTTPError(
"You are the guild owner, hence can't ban yourself",
403,
@@ -186,7 +186,7 @@ router.delete(
async (req: Request, res: Response) => {
const { guild_id, user_id } = req.params;
- let ban = await Ban.findOneOrFail({
+ const ban = await Ban.findOneOrFail({
where: { guild_id: guild_id, user_id: user_id },
});
diff --git a/src/api/routes/guilds/#guild_id/channels.ts b/src/api/routes/guilds/#guild_id/channels.ts
index b72f5ddb..acdb5f19 100644
--- a/src/api/routes/guilds/#guild_id/channels.ts
+++ b/src/api/routes/guilds/#guild_id/channels.ts
@@ -68,7 +68,7 @@ router.patch(
400,
);
- const opts: any = {};
+ const opts: Partial<Channel> = {};
if (x.position != null) opts.position = x.position;
if (x.parent_id) {
diff --git a/src/api/routes/guilds/#guild_id/delete.ts b/src/api/routes/guilds/#guild_id/delete.ts
index 551c6829..9a13c9b4 100644
--- a/src/api/routes/guilds/#guild_id/delete.ts
+++ b/src/api/routes/guilds/#guild_id/delete.ts
@@ -16,17 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {
- Channel,
- emitEvent,
- GuildDeleteEvent,
- Guild,
- Member,
- Message,
- Role,
- Invite,
- Emoji,
-} from "@fosscord/util";
+import { emitEvent, GuildDeleteEvent, Guild } from "@fosscord/util";
import { Router, Request, Response } from "express";
import { HTTPError } from "lambert-server";
import { route } from "@fosscord/api";
@@ -36,7 +26,7 @@ const router = Router();
// discord prefixes this route with /delete instead of using the delete method
// docs are wrong https://discord.com/developers/docs/resources/guild#delete-guild
router.post("/", route({}), async (req: Request, res: Response) => {
- var { guild_id } = req.params;
+ const { guild_id } = req.params;
const guild = await Guild.findOneOrFail({
where: { id: guild_id },
diff --git a/src/api/routes/guilds/#guild_id/discovery-requirements.ts b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
index 11dcc33e..de2da6ee 100644
--- a/src/api/routes/guilds/#guild_id/discovery-requirements.ts
+++ b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
@@ -16,8 +16,6 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Guild, Config } from "@fosscord/util";
-
import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
diff --git a/src/api/routes/guilds/#guild_id/index.ts b/src/api/routes/guilds/#guild_id/index.ts
index 0df90f56..c262a088 100644
--- a/src/api/routes/guilds/#guild_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/index.ts
@@ -47,10 +47,10 @@ router.get("/", route({}), async (req: Request, res: Response) => {
401,
);
- // @ts-ignore
- guild.joined_at = member?.joined_at;
-
- return res.send(guild);
+ return res.send({
+ ...guild,
+ joined_at: member?.joined_at,
+ });
});
router.patch(
@@ -68,7 +68,7 @@ router.patch(
"MANAGE_GUILDS",
);
- var guild = await Guild.findOneOrFail({
+ const guild = await Guild.findOneOrFail({
where: { id: guild_id },
relations: ["emojis", "roles", "stickers"],
});
@@ -110,7 +110,7 @@ router.patch(
"DISCOVERABLE",
];
- for (var feature of diff) {
+ for (const feature of diff) {
if (MUTABLE_FEATURES.includes(feature)) continue;
throw FosscordApiErrors.FEATURE_IS_IMMUTABLE.withParams(
diff --git a/src/api/routes/guilds/#guild_id/invites.ts b/src/api/routes/guilds/#guild_id/invites.ts
index 6e9cc3e6..dd099992 100644
--- a/src/api/routes/guilds/#guild_id/invites.ts
+++ b/src/api/routes/guilds/#guild_id/invites.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { getPermission, Invite, PublicInviteRelation } from "@fosscord/util";
+import { Invite, PublicInviteRelation } from "@fosscord/util";
import { route } from "@fosscord/api";
import { Request, Response, Router } from "express";
diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
index 2cf7c08b..2daa7d9b 100644
--- a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
@@ -49,11 +49,12 @@ router.patch(
"/",
route({ body: "MemberChangeSchema" }),
async (req: Request, res: Response) => {
- let { guild_id, member_id } = req.params;
- if (member_id === "@me") member_id = req.user_id;
+ const { guild_id } = req.params;
+ const member_id =
+ req.params.member_id === "@me" ? req.user_id : req.params.member_id;
const body = req.body as MemberChangeSchema;
- let member = await Member.findOneOrFail({
+ const member = await Member.findOneOrFail({
where: { id: member_id, guild_id },
relations: ["roles", "user"],
});
@@ -101,7 +102,8 @@ router.put("/", route({}), async (req: Request, res: Response) => {
const rights = await getRights(req.user_id);
- let { guild_id, member_id } = req.params;
+ const { guild_id } = req.params;
+ let { member_id } = req.params;
if (member_id === "@me") {
member_id = req.user_id;
rights.hasThrow("JOIN_GUILDS");
@@ -109,19 +111,19 @@ router.put("/", route({}), async (req: Request, res: Response) => {
// TODO: join others by controller
}
- var guild = await Guild.findOneOrFail({
+ const guild = await Guild.findOneOrFail({
where: { id: guild_id },
});
- var emoji = await Emoji.find({
+ const emoji = await Emoji.find({
where: { guild_id: guild_id },
});
- var roles = await Role.find({
+ const roles = await Role.find({
where: { guild_id: guild_id },
});
- var stickers = await Sticker.find({
+ const stickers = await Sticker.find({
where: { guild_id: guild_id },
});
diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
index 619b66f7..c93eab08 100644
--- a/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
@@ -26,12 +26,12 @@ router.patch(
"/",
route({ body: "MemberNickChangeSchema" }),
async (req: Request, res: Response) => {
- var { guild_id, member_id } = req.params;
- var permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
- if (member_id === "@me") {
- member_id = req.user_id;
- permissionString = "CHANGE_NICKNAME";
- }
+ const { guild_id } = req.params;
+ let permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
+ const member_id =
+ req.params.member_id === "@me"
+ ? ((permissionString = "CHANGE_NICKNAME"), req.user_id)
+ : req.params.member_id;
const perms = await getPermission(req.user_id, guild_id);
perms.hasThrow(permissionString);
diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
index e64893b7..16c5e789 100644
--- a/src/api/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { getPermission, Member } from "@fosscord/util";
+import { Member } from "@fosscord/util";
import { route } from "@fosscord/api";
import { Request, Response, Router } from "express";
diff --git a/src/api/routes/guilds/#guild_id/members/index.ts b/src/api/routes/guilds/#guild_id/members/index.ts
index b96210f3..51e9eb1f 100644
--- a/src/api/routes/guilds/#guild_id/members/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/index.ts
@@ -17,7 +17,7 @@
*/
import { Request, Response, Router } from "express";
-import { Guild, Member, PublicMemberProjection } from "@fosscord/util";
+import { Member, PublicMemberProjection } from "@fosscord/util";
import { route } from "@fosscord/api";
import { MoreThan } from "typeorm";
import { HTTPError } from "lambert-server";
diff --git a/src/api/routes/guilds/#guild_id/messages/search.ts b/src/api/routes/guilds/#guild_id/messages/search.ts
index 7061b5f0..601167ee 100644
--- a/src/api/routes/guilds/#guild_id/messages/search.ts
+++ b/src/api/routes/guilds/#guild_id/messages/search.ts
@@ -16,6 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+
import { Request, Response, Router } from "express";
import { route } from "@fosscord/api";
import { getPermission, FieldErrors, Message, Channel } from "@fosscord/util";
@@ -28,10 +30,10 @@ router.get("/", route({}), async (req: Request, res: Response) => {
const {
channel_id,
content,
- include_nsfw, // TODO
+ // include_nsfw, // TODO
offset,
sort_order,
- sort_by, // TODO: Handle 'relevance'
+ // sort_by, // TODO: Handle 'relevance'
limit,
author_id,
} = req.query;
@@ -62,7 +64,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
if (!permissions.has("READ_MESSAGE_HISTORY"))
return res.json({ messages: [], total_results: 0 });
- var query: FindManyOptions<Message> = {
+ const query: FindManyOptions<Message> = {
order: {
timestamp: sort_order
? (sort_order.toUpperCase() as "ASC" | "DESC")
@@ -87,7 +89,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
skip: offset ? Number(offset) : 0,
};
//@ts-ignore
- if (channel_id) query.where!.channel = { id: channel_id };
+ if (channel_id) query.where.channel = { id: channel_id };
else {
// get all channel IDs that this user can access
const channels = await Channel.find({
@@ -96,7 +98,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
});
const ids = [];
- for (var channel of channels) {
+ for (const channel of channels) {
const perm = await getPermission(
req.user_id,
req.params.guild_id,
@@ -108,12 +110,12 @@ router.get("/", route({}), async (req: Request, res: Response) => {
}
//@ts-ignore
- query.where!.channel = { id: In(ids) };
+ query.where.channel = { id: In(ids) };
}
//@ts-ignore
- if (author_id) query.where!.author = { id: author_id };
+ if (author_id) query.where.author = { id: author_id };
//@ts-ignore
- if (content) query.where!.content = Like(`%${content}%`);
+ if (content) query.where.content = Like(`%${content}%`);
const messages: Message[] = await Message.find(query);
diff --git a/src/api/routes/guilds/#guild_id/profile/index.ts b/src/api/routes/guilds/#guild_id/profile/index.ts
index 5771fbf1..cbf0ff6a 100644
--- a/src/api/routes/guilds/#guild_id/profile/index.ts
+++ b/src/api/routes/guilds/#guild_id/profile/index.ts
@@ -33,8 +33,9 @@ router.patch(
"/:member_id",
route({ body: "MemberChangeProfileSchema" }),
async (req: Request, res: Response) => {
- let { guild_id, member_id } = req.params;
- if (member_id === "@me") member_id = req.user_id;
+ const { guild_id } = req.params;
+ // const member_id =
+ // req.params.member_id === "@me" ? req.user_id : req.params.member_id;
const body = req.body as MemberChangeProfileSchema;
let member = await Member.findOneOrFail({
diff --git a/src/api/routes/guilds/#guild_id/prune.ts b/src/api/routes/guilds/#guild_id/prune.ts
index 1199df54..37b70f63 100644
--- a/src/api/routes/guilds/#guild_id/prune.ts
+++ b/src/api/routes/guilds/#guild_id/prune.ts
@@ -29,16 +29,16 @@ export const inactiveMembers = async (
days: number,
roles: string[] = [],
) => {
- var date = new Date();
+ const date = new Date();
date.setDate(date.getDate() - days);
//Snowflake should have `generateFromTime` method? Or similar?
- var minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
+ const minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
/**
idea: ability to customise the cutoff variable
possible candidates: public read receipt, last presence, last VC leave
**/
- var members = await Member.find({
+ let members = await Member.find({
where: [
{
guild_id,
@@ -83,7 +83,7 @@ export const inactiveMembers = async (
router.get("/", route({}), async (req: Request, res: Response) => {
const days = parseInt(req.query.days as string);
- var roles = req.query.include_roles;
+ let roles = req.query.include_roles;
if (typeof roles === "string") roles = [roles]; //express will return array otherwise
const members = await inactiveMembers(
@@ -102,7 +102,7 @@ router.post(
async (req: Request, res: Response) => {
const days = parseInt(req.body.days);
- var roles = req.query.include_roles;
+ let roles = req.query.include_roles;
if (typeof roles === "string") roles = [roles];
const { guild_id } = req.params;
diff --git a/src/api/routes/guilds/#guild_id/regions.ts b/src/api/routes/guilds/#guild_id/regions.ts
index a9c04a39..61ba00bf 100644
--- a/src/api/routes/guilds/#guild_id/regions.ts
+++ b/src/api/routes/guilds/#guild_id/regions.ts
@@ -16,10 +16,9 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Config, Guild, Member } from "@fosscord/util";
+import { Guild } from "@fosscord/util";
import { Request, Response, Router } from "express";
-import { getVoiceRegions, route } from "@fosscord/api";
-import { getIpAdress } from "@fosscord/api";
+import { getVoiceRegions, route, getIpAdress } from "@fosscord/api";
const router = Router();
diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
index 22eb439a..48e77897 100644
--- a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
@@ -87,7 +87,8 @@ router.patch(
role.assign({
...body,
permissions: String(
- req.permission!.bitfield & BigInt(body.permissions || "0"),
+ (req.permission?.bitfield || 0n) &
+ BigInt(body.permissions || "0"),
),
});
diff --git a/src/api/routes/guilds/#guild_id/roles/index.ts b/src/api/routes/guilds/#guild_id/roles/index.ts
index feab84ef..54d4b12c 100644
--- a/src/api/routes/guilds/#guild_id/roles/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/index.ts
@@ -68,7 +68,8 @@ router.post(
guild_id: guild_id,
managed: false,
permissions: String(
- req.permission!.bitfield & BigInt(body.permissions || "0"),
+ (req.permission?.bitfield || 0n) &
+ BigInt(body.permissions || "0"),
),
tags: undefined,
icon: undefined,
diff --git a/src/api/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts
index f5244313..284bbccf 100644
--- a/src/api/routes/guilds/#guild_id/templates.ts
+++ b/src/api/routes/guilds/#guild_id/templates.ts
@@ -44,7 +44,7 @@ const TemplateGuildProjection: (keyof Guild)[] = [
router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- var templates = await Template.find({
+ const templates = await Template.find({
where: { source_guild_id: guild_id },
});
@@ -60,9 +60,9 @@ router.post(
where: { id: guild_id },
select: TemplateGuildProjection,
});
- const exists = await Template.findOneOrFail({
+ const exists = await Template.findOne({
where: { id: guild_id },
- }).catch((e) => {});
+ });
if (exists) throw new HTTPError("Template already exists", 400);
const template = await Template.create({
diff --git a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
index 9883ef0d..3577df17 100644
--- a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
@@ -37,8 +37,9 @@ router.patch(
route({ body: "VoiceStateUpdateSchema" }),
async (req: Request, res: Response) => {
const body = req.body as VoiceStateUpdateSchema;
- var { guild_id, user_id } = req.params;
- if (user_id === "@me") user_id = req.user_id;
+ const { guild_id } = req.params;
+ const user_id =
+ req.params.user_id === "@me" ? req.user_id : req.params.user_id;
const perms = await getPermission(
req.user_id,
diff --git a/src/api/routes/guilds/#guild_id/widget.json.ts b/src/api/routes/guilds/#guild_id/widget.json.ts
index 46b8aa8b..9319d058 100644
--- a/src/api/routes/guilds/#guild_id/widget.json.ts
+++ b/src/api/routes/guilds/#guild_id/widget.json.ts
@@ -17,14 +17,7 @@
*/
import { Request, Response, Router } from "express";
-import {
- Config,
- Permissions,
- Guild,
- Invite,
- Channel,
- Member,
-} from "@fosscord/util";
+import { Permissions, Guild, Invite, Channel, Member } from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { random, route } from "@fosscord/api";
@@ -46,7 +39,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
if (!guild.widget_enabled) throw new HTTPError("Widget Disabled", 404);
// Fetch existing widget invite for widget channel
- var invite = await Invite.findOne({
+ let invite = await Invite.findOne({
where: { channel_id: guild.widget_channel_id },
});
@@ -70,7 +63,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
}
// Fetch voice channels, and the @everyone permissions object
- const channels = [] as any[];
+ const channels: { id: string; name: string; position: number }[] = [];
(
await Channel.find({
@@ -88,15 +81,15 @@ router.get("/", route({}), async (req: Request, res: Response) => {
) {
channels.push({
id: doc.id,
- name: doc.name,
- position: doc.position,
+ name: doc.name ?? "Unknown channel",
+ position: doc.position ?? 0,
});
}
});
// Fetch members
// TODO: Understand how Discord's max 100 random member sample works, and apply to here (see top of this file)
- let members = await Member.find({ where: { guild_id: guild_id } });
+ const members = await Member.find({ where: { guild_id: guild_id } });
// Construct object to respond with
const data = {
diff --git a/src/api/routes/guilds/#guild_id/widget.png.ts b/src/api/routes/guilds/#guild_id/widget.png.ts
index 1c6a62ac..65de8978 100644
--- a/src/api/routes/guilds/#guild_id/widget.png.ts
+++ b/src/api/routes/guilds/#guild_id/widget.png.ts
@@ -16,6 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
import { Request, Response, Router } from "express";
import { Guild } from "@fosscord/util";
import { HTTPError } from "lambert-server";
@@ -161,8 +163,7 @@ async function drawIcon(
scale: number,
icon: string,
) {
- // @ts-ignore
- const img = new require("canvas").Image();
+ const img = new (require("canvas").Image)();
img.src = icon;
// Do some canvas clipping magic!
diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index 125d25b0..64af4bd1 100644
--- a/src/api/routes/guilds/index.ts
+++ b/src/api/routes/guilds/index.ts
@@ -18,7 +18,6 @@
import { Router, Request, Response } from "express";
import {
- Role,
Guild,
Config,
getRights,
@@ -52,6 +51,7 @@ router.post(
const { autoJoin } = Config.get().guild;
if (autoJoin.enabled && !autoJoin.guilds?.length) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
}
diff --git a/src/api/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index f3bb3ef1..a43337d8 100644
--- a/src/api/routes/guilds/templates/index.ts
+++ b/src/api/routes/guilds/templates/index.ts
@@ -86,8 +86,8 @@ router.post(
const {
enabled,
allowTemplateCreation,
- allowDiscordTemplates,
- allowRaws,
+ // allowDiscordTemplates,
+ // allowRaws,
} = Config.get().templates;
if (!enabled)
return res
@@ -121,7 +121,7 @@ router.post(
const guild_id = Snowflake.generate();
- const [guild, role] = await Promise.all([
+ const [guild] = await Promise.all([
Guild.create({
...body,
...template.serialized_source_guild,
diff --git a/src/api/routes/oauth2/authorize.ts b/src/api/routes/oauth2/authorize.ts
index be9b39b4..e238b72f 100644
--- a/src/api/routes/oauth2/authorize.ts
+++ b/src/api/routes/oauth2/authorize.ts
@@ -27,16 +27,14 @@ import {
Member,
Permissions,
User,
- getRights,
- Rights,
- MemberPrivateProjection,
} from "@fosscord/util";
const router = Router();
// TODO: scopes, other oauth types
router.get("/", route({}), async (req: Request, res: Response) => {
- const { client_id, scope, response_type, redirect_url } = req.query;
+ // const { client_id, scope, response_type, redirect_url } = req.query;
+ const { client_id } = req.query;
const app = await Application.findOne({
where: {
@@ -68,6 +66,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
},
},
relations: ["guild", "roles"],
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
// prettier-ignore
select: ["guild.id", "guild.name", "guild.icon", "guild.mfa_level", "guild.owner_id", "roles.id"],
@@ -139,7 +138,8 @@ router.post(
route({ body: "ApplicationAuthorizeSchema" }),
async (req: Request, res: Response) => {
const body = req.body as ApplicationAuthorizeSchema;
- const { client_id, scope, response_type, redirect_url } = req.query;
+ // const { client_id, scope, response_type, redirect_url } = req.query;
+ const { client_id } = req.query;
// TODO: captcha verification
// TODO: MFA verification
@@ -153,7 +153,7 @@ router.post(
// getPermission cache won't exist if we're owner
if (
Object.keys(perms.cache || {}).length > 0 &&
- perms.cache.member!.user.bot
+ perms.cache.member?.user.bot
)
throw DiscordApiErrors.UNAUTHORIZED;
perms.hasThrow("MANAGE_GUILD");
diff --git a/src/api/routes/partners/#guild_id/requirements.ts b/src/api/routes/partners/#guild_id/requirements.ts
index 11dcc33e..de2da6ee 100644
--- a/src/api/routes/partners/#guild_id/requirements.ts
+++ b/src/api/routes/partners/#guild_id/requirements.ts
@@ -16,8 +16,6 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Guild, Config } from "@fosscord/util";
-
import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
diff --git a/src/api/routes/policies/instance/domains.ts b/src/api/routes/policies/instance/domains.ts
index 929cf65c..33c06765 100644
--- a/src/api/routes/policies/instance/domains.ts
+++ b/src/api/routes/policies/instance/domains.ts
@@ -19,7 +19,6 @@
import { Router, Request, Response } from "express";
import { route } from "@fosscord/api";
import { Config } from "@fosscord/util";
-import { config } from "dotenv";
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
diff --git a/src/api/routes/store/published-listings/applications.ts b/src/api/routes/store/published-listings/applications.ts
index 16604960..ec9168b1 100644
--- a/src/api/routes/store/published-listings/applications.ts
+++ b/src/api/routes/store/published-listings/applications.ts
@@ -23,7 +23,7 @@ const router: Router = Router();
router.get("/:id", route({}), async (req: Request, res: Response) => {
//TODO
- const id = req.params.id;
+ // const id = req.params.id;
res.json({
id: "",
summary: "",
diff --git a/src/api/routes/store/published-listings/skus.ts b/src/api/routes/store/published-listings/skus.ts
index 16604960..ec9168b1 100644
--- a/src/api/routes/store/published-listings/skus.ts
+++ b/src/api/routes/store/published-listings/skus.ts
@@ -23,7 +23,7 @@ const router: Router = Router();
router.get("/:id", route({}), async (req: Request, res: Response) => {
//TODO
- const id = req.params.id;
+ // const id = req.params.id;
res.json({
id: "",
summary: "",
diff --git a/src/api/routes/updates.ts b/src/api/routes/updates.ts
index 5555fcda..5c237465 100644
--- a/src/api/routes/updates.ts
+++ b/src/api/routes/updates.ts
@@ -18,12 +18,11 @@
import { Router, Response, Request } from "express";
import { route } from "@fosscord/api";
-import { Config, FieldErrors, Release } from "@fosscord/util";
+import { FieldErrors, Release } from "@fosscord/util";
const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => {
- const { client } = Config.get();
const platform = req.query.platform;
if (!platform)
diff --git a/src/api/routes/users/#id/delete.ts b/src/api/routes/users/#id/delete.ts
index e7caeb05..9bc3f9f8 100644
--- a/src/api/routes/users/#id/delete.ts
+++ b/src/api/routes/users/#id/delete.ts
@@ -23,7 +23,6 @@ import {
PrivateUserProjection,
User,
UserDeleteEvent,
- UserDeleteSchema,
} from "@fosscord/util";
import { Request, Response, Router } from "express";
@@ -33,7 +32,7 @@ router.post(
"/",
route({ right: "MANAGE_USERS" }),
async (req: Request, res: Response) => {
- let user = await User.findOneOrFail({
+ await User.findOneOrFail({
where: { id: req.params.id },
select: [...PrivateUserProjection, "data"],
});
diff --git a/src/api/routes/users/#id/profile.ts b/src/api/routes/users/#id/profile.ts
index 1103bb48..dbf95a52 100644
--- a/src/api/routes/users/#id/profile.ts
+++ b/src/api/routes/users/#id/profile.ts
@@ -19,11 +19,9 @@
import { Router, Request, Response } from "express";
import {
PublicConnectedAccount,
- PublicUser,
User,
UserPublic,
Member,
- Guild,
UserProfileModifySchema,
handleFile,
PrivateUserProjection,
@@ -53,8 +51,8 @@ router.get(
relations: ["connected_accounts"],
});
- var mutual_guilds: object[] = [];
- var premium_guild_since;
+ const mutual_guilds: object[] = [];
+ let premium_guild_since;
if (with_mutual_guilds == "true") {
const requested_member = await Member.find({
@@ -169,7 +167,7 @@ router.patch(
`/banners/${req.user_id}`,
body.banner as string,
);
- let user = await User.findOneOrFail({
+ const user = await User.findOneOrFail({
where: { id: req.user_id },
select: [...PrivateUserProjection, "data"],
});
@@ -177,6 +175,7 @@ router.patch(
user.assign(body);
await user.save();
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
delete user.data;
diff --git a/src/api/routes/users/#id/relationships.ts b/src/api/routes/users/#id/relationships.ts
index aa36967a..e915e3ff 100644
--- a/src/api/routes/users/#id/relationships.ts
+++ b/src/api/routes/users/#id/relationships.ts
@@ -36,7 +36,7 @@ router.get(
"/",
route({ test: { response: { body: "UserRelationsResponse" } } }),
async (req: Request, res: Response) => {
- var mutual_relations: object[] = [];
+ const mutual_relations: object[] = [];
const requested_relations = await User.findOneOrFail({
where: { id: req.params.id },
relations: ["relationships"],
@@ -53,7 +53,7 @@ router.get(
rmem.type === 1 &&
rmem.to_id !== req.user_id
) {
- var relation_user = await User.getPublicUser(rmem.to_id);
+ const relation_user = await User.getPublicUser(rmem.to_id);
mutual_relations.push({
id: relation_user.id,
diff --git a/src/api/routes/users/@me/delete.ts b/src/api/routes/users/@me/delete.ts
index a6ae2d13..8043eae3 100644
--- a/src/api/routes/users/@me/delete.ts
+++ b/src/api/routes/users/@me/delete.ts
@@ -17,7 +17,7 @@
*/
import { Router, Request, Response } from "express";
-import { Guild, Member, User } from "@fosscord/util";
+import { Member, User } from "@fosscord/util";
import { route } from "@fosscord/api";
import bcrypt from "bcrypt";
import { HTTPError } from "lambert-server";
diff --git a/src/api/routes/users/@me/guilds/#guild_id/settings.ts b/src/api/routes/users/@me/guilds/#guild_id/settings.ts
index 0525bea2..72c95d6b 100644
--- a/src/api/routes/users/@me/guilds/#guild_id/settings.ts
+++ b/src/api/routes/users/@me/guilds/#guild_id/settings.ts
@@ -43,7 +43,7 @@ router.patch(
const body = req.body as UserGuildSettingsSchema;
if (body.channel_overrides) {
- for (var channel in body.channel_overrides) {
+ for (const channel in body.channel_overrides) {
Channel.findOneOrFail({ where: { id: channel } });
}
}
diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index 596e2575..0d3c3135 100644
--- a/src/api/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -55,7 +55,7 @@ router.patch(
});
// Populated on password change
- var newToken: string | undefined;
+ let newToken: string | undefined;
if (body.avatar)
body.avatar = await handleFile(
@@ -120,7 +120,7 @@ router.patch(
}
if (body.username) {
- var check_username = body?.username?.replace(/\s/g, "");
+ const check_username = body?.username?.replace(/\s/g, "");
if (!check_username) {
throw FieldErrors({
username: {
@@ -153,7 +153,8 @@ router.patch(
user.validate();
await user.save();
- // @ts-ignore
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore
delete user.data;
// TODO: send update member list event in gateway
diff --git a/src/api/routes/users/@me/mfa/codes-verification.ts b/src/api/routes/users/@me/mfa/codes-verification.ts
index ac16f7e7..24f018c9 100644
--- a/src/api/routes/users/@me/mfa/codes-verification.ts
+++ b/src/api/routes/users/@me/mfa/codes-verification.ts
@@ -23,6 +23,7 @@ import {
generateMfaBackupCodes,
User,
CodesVerificationSchema,
+ DiscordApiErrors,
} from "@fosscord/util";
const router = Router();
@@ -31,14 +32,17 @@ router.post(
"/",
route({ body: "CodesVerificationSchema" }),
async (req: Request, res: Response) => {
- const { key, nonce, regenerate } = req.body as CodesVerificationSchema;
+ // const { key, nonce, regenerate } = req.body as CodesVerificationSchema;
+ const { regenerate } = req.body as CodesVerificationSchema;
// TODO: We don't have email/etc etc, so can't send a verification code.
// Once that's done, this route can verify `key`
- const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ // const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ if ((await User.count({ where: { id: req.user_id } })) === 0)
+ throw DiscordApiErrors.UNKNOWN_USER;
- var codes: BackupCode[];
+ let codes: BackupCode[];
if (regenerate) {
await BackupCode.update(
{ user: { id: req.user_id } },
diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index 09b9b329..e2600400 100644
--- a/src/api/routes/users/@me/mfa/codes.ts
+++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -51,7 +51,7 @@ router.post(
});
}
- var codes: BackupCode[];
+ let codes: BackupCode[];
if (regenerate) {
await BackupCode.update(
{ user: { id: req.user_id } },
diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index c399ba33..e35691ae 100644
--- a/src/api/routes/users/@me/mfa/totp/disable.ts
+++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -42,7 +42,7 @@ router.post(
const backup = await BackupCode.findOne({ where: { code: body.code } });
if (!backup) {
- const ret = verifyToken(user.totp_secret!, body.code);
+ const ret = verifyToken(user.totp_secret || "", body.code);
if (!ret || ret.delta != 0)
throw new HTTPError(
req.t("auth:login.INVALID_TOTP_CODE"),
diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index a59983ac..f6519ad0 100644
--- a/src/api/routes/users/@me/mfa/totp/enable.ts
+++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -57,7 +57,7 @@ router.post(
if (verifyToken(body.secret, body.code)?.delta != 0)
throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- let backup_codes = generateMfaBackupCodes(req.user_id);
+ const backup_codes = generateMfaBackupCodes(req.user_id);
await Promise.all(backup_codes.map((x) => x.save()));
await User.update(
{ id: req.user_id },
diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index de684a34..4dfb4c33 100644
--- a/src/api/routes/users/@me/relationships.ts
+++ b/src/api/routes/users/@me/relationships.ts
@@ -175,7 +175,7 @@ async function updateRelationship(
select: userProjection,
});
- var relationship = user.relationships.find((x) => x.to_id === id);
+ let relationship = user.relationships.find((x) => x.to_id === id);
const friendRequest = friend.relationships.find(
(x) => x.to_id === req.user_id,
);
@@ -219,13 +219,13 @@ async function updateRelationship(
if (user.relationships.length >= maxFriends)
throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends);
- var incoming_relationship = Relationship.create({
+ let incoming_relationship = Relationship.create({
nickname: undefined,
type: RelationshipType.incoming,
to: user,
from: friend,
});
- var outgoing_relationship = Relationship.create({
+ let outgoing_relationship = Relationship.create({
nickname: undefined,
type: RelationshipType.outgoing,
to: friend,
diff --git a/src/api/routes/users/@me/settings.ts b/src/api/routes/users/@me/settings.ts
index ad922084..c883bb30 100644
--- a/src/api/routes/users/@me/settings.ts
+++ b/src/api/routes/users/@me/settings.ts
@@ -17,7 +17,7 @@
*/
import { Router, Response, Request } from "express";
-import { OrmUtils, User, UserSettingsSchema } from "@fosscord/util";
+import { User, UserSettingsSchema } from "@fosscord/util";
import { route } from "@fosscord/api";
const router = Router();
diff --git a/src/api/start.ts b/src/api/start.ts
index e80a7d4a..7975d085 100644
--- a/src/api/start.ts
+++ b/src/api/start.ts
@@ -26,7 +26,7 @@ config();
import { FosscordServer } from "./Server";
import cluster from "cluster";
import os from "os";
-var cores = 1;
+let cores = 1;
try {
cores = Number(process.env.THREADS) || os.cpus().length;
} catch {
@@ -41,16 +41,17 @@ if (cluster.isPrimary && process.env.NODE_ENV == "production") {
cluster.fork();
}
- cluster.on("exit", (worker, code, signal) => {
+ cluster.on("exit", (worker) => {
console.log(`worker ${worker.process.pid} died, restart worker`);
cluster.fork();
});
} else {
- var port = Number(process.env.PORT) || 3001;
+ const port = Number(process.env.PORT) || 3001;
const server = new FosscordServer({ port });
server.start().catch(console.error);
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
global.server = server;
}
diff --git a/src/api/util/handlers/Instance.ts b/src/api/util/handlers/Instance.ts
index acac1fb8..08157208 100644
--- a/src/api/util/handlers/Instance.ts
+++ b/src/api/util/handlers/Instance.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Config, Guild, Session } from "@fosscord/util";
+import { Session } from "@fosscord/util";
export async function initInstance() {
// TODO: clean up database and delete tombstone data
@@ -24,15 +24,14 @@ export async function initInstance() {
// create default guild and add it to auto join
// TODO: check if any current user is not part of autoJoinGuilds
- const { autoJoin } = Config.get().guild;
+ // const { autoJoin } = Config.get().guild;
- if (autoJoin.enabled && !autoJoin.guilds?.length) {
- let guild = await Guild.findOne({ where: {}, select: ["id"] });
- if (guild) {
- // @ts-ignore
- await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
- }
- }
+ // if (autoJoin.enabled && !autoJoin.guilds?.length) {
+ // const guild = await Guild.findOne({ where: {}, select: ["id"] });
+ // if (guild) {
+ // await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
+ // }
+ // }
// TODO: do no clear sessions for instance cluster
await Session.delete({});
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 2371358f..42325681 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -51,7 +51,7 @@ const allow_empty = false;
// TODO: embed gifs/videos/images
const LINK_REGEX =
- /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
+ /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g;
export async function handleMessage(opts: MessageOptions): Promise<Message> {
const channel = await Channel.findOneOrFail({
@@ -129,7 +129,6 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
}
/** Q: should be checked if the referenced message exists? ANSWER: NO
otherwise backfilling won't work **/
- // @ts-ignore
message.type = MessageType.REPLY;
}
@@ -144,29 +143,29 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
throw new HTTPError("Empty messages are not allowed", 50006);
}
- var content = opts.content;
- var mention_channel_ids = [] as string[];
- var mention_role_ids = [] as string[];
- var mention_user_ids = [] as string[];
- var mention_everyone = false;
+ let content = opts.content;
+ const mention_channel_ids = [] as string[];
+ const mention_role_ids = [] as string[];
+ const mention_user_ids = [] as string[];
+ let mention_everyone = false;
if (content) {
// TODO: explicit-only mentions
message.content = content.trim();
- content = content.replace(/ *\`[^)]*\` */g, ""); // remove codeblocks
- for (const [_, mention] of content.matchAll(CHANNEL_MENTION)) {
+ content = content.replace(/ *`[^)]*` */g, ""); // remove codeblocks
+ for (const [, mention] of content.matchAll(CHANNEL_MENTION)) {
if (!mention_channel_ids.includes(mention))
mention_channel_ids.push(mention);
}
- for (const [_, mention] of content.matchAll(USER_MENTION)) {
+ for (const [, mention] of content.matchAll(USER_MENTION)) {
if (!mention_user_ids.includes(mention))
mention_user_ids.push(mention);
}
await Promise.all(
Array.from(content.matchAll(ROLE_MENTION)).map(
- async ([_, mention]) => {
+ async ([, mention]) => {
const role = await Role.findOneOrFail({
where: { id: mention, guild_id: channel.guild_id },
});
@@ -198,8 +197,8 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
// TODO: cache link result in db
export async function postHandleMessage(message: Message) {
- const content = message.content?.replace(/ *\`[^)]*\` */g, ""); // remove markdown
- var links = content?.match(LINK_REGEX);
+ const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown
+ let links = content?.match(LINK_REGEX);
if (!links) return;
const data = { ...message };
@@ -232,8 +231,8 @@ export async function postHandleMessage(message: Message) {
// tried to use shorthand but types didn't like me L
if (!Array.isArray(res)) res = [res];
- for (var embed of res) {
- var cache = EmbedCache.create({
+ for (const embed of res) {
+ const cache = EmbedCache.create({
url: link,
embed: embed,
});
@@ -279,7 +278,10 @@ export async function sendMessage(opts: MessageOptions) {
} as MessageCreateEvent),
]);
- postHandleMessage(message).catch((e) => {}); // no await as it should catch error non-blockingly
+ // no await as it should catch error non-blockingly
+ postHandleMessage(message).catch((e) =>
+ console.error("[Message] post-message handler failed", e),
+ );
return message;
}
diff --git a/src/api/util/handlers/Voice.ts b/src/api/util/handlers/Voice.ts
index d8d5c279..24bfa7b3 100644
--- a/src/api/util/handlers/Voice.ts
+++ b/src/api/util/handlers/Voice.ts
@@ -31,7 +31,7 @@ export async function getVoiceRegions(ipAddress: string, vip: boolean) {
let min = Number.POSITIVE_INFINITY;
- for (let ar of availableRegions) {
+ for (const ar of availableRegions) {
//TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call
const dist = distanceBetweenLocations(
clientIpAnalysis,
diff --git a/src/api/util/handlers/route.ts b/src/api/util/handlers/route.ts
index 6fcc6c73..cb160637 100644
--- a/src/api/util/handlers/route.ts
+++ b/src/api/util/handlers/route.ts
@@ -34,6 +34,8 @@ import { NextFunction, Request, Response } from "express";
import { AnyValidateFunction } from "ajv/dist/core";
declare global {
+ // TODO: fix this
+ // eslint-disable-next-line @typescript-eslint/no-namespace
namespace Express {
interface Request {
permission?: Permissions;
@@ -53,7 +55,7 @@ export interface RouteOptions {
body?: `${string}Schema`; // typescript interface name
test?: {
response?: RouteResponse;
- body?: any;
+ body?: unknown;
path?: string;
event?: EVENT | EVENT[];
headers?: Record<string, string>;
@@ -61,7 +63,7 @@ export interface RouteOptions {
}
export function route(opts: RouteOptions) {
- var validate: AnyValidateFunction<any> | undefined;
+ let validate: AnyValidateFunction | undefined;
if (opts.body) {
validate = ajv.getSchema(opts.body);
if (!validate) throw new Error(`Body schema ${opts.body} not found`);
diff --git a/src/api/util/utility/EmbedHandlers.ts b/src/api/util/utility/EmbedHandlers.ts
index 522ff82b..8466a374 100644
--- a/src/api/util/utility/EmbedHandlers.ts
+++ b/src/api/util/utility/EmbedHandlers.ts
@@ -17,13 +17,13 @@
*/
import { Config, Embed, EmbedType } from "@fosscord/util";
-import fetch, { Response } from "node-fetch";
+import fetch, { RequestInit } from "node-fetch";
import * as cheerio from "cheerio";
import probe from "probe-image-size";
import crypto from "crypto";
import { yellow } from "picocolors";
-export const DEFAULT_FETCH_OPTIONS: any = {
+export const DEFAULT_FETCH_OPTIONS: RequestInit = {
redirect: "follow",
follow: 1,
headers: {
@@ -50,7 +50,7 @@ export const getProxyUrl = (
// Imagor
if (imagorServerUrl) {
- let path = `${width}x${height}/${url.host}${url.pathname}`;
+ const path = `${width}x${height}/${url.host}${url.pathname}`;
const hash = crypto
.createHmac("sha1", secret)
@@ -92,8 +92,8 @@ export const getMetaDescriptions = (text: string) => {
image: getMeta($, "og:image") || getMeta($, "twitter:image"),
image_fallback: $(`image`).attr("src"),
video_fallback: $(`video`).attr("src"),
- width: parseInt(getMeta($, "og:image:width")!) || 0,
- height: parseInt(getMeta($, "og:image:height")!) || 0,
+ width: parseInt(getMeta($, "og:image:width") || "0"),
+ height: parseInt(getMeta($, "og:image:height") || "0"),
url: getMeta($, "og:url"),
youtube_embed: getMeta($, "og:video:secure_url"),
};
@@ -192,8 +192,8 @@ export const EmbedHandlers: {
proxy_url: metas.image
? getProxyUrl(
new URL(metas.image),
- metas.width!,
- metas.height!,
+ metas.width,
+ metas.height,
)
: undefined,
},
@@ -239,9 +239,9 @@ export const EmbedHandlers: {
const text = json.data.text;
const created_at = new Date(json.data.created_at);
const metrics = json.data.public_metrics;
- let media = json.includes.media?.filter(
- (x: any) => x.type == "photo",
- ) as any[]; // TODO: video
+ const media = json.includes.media?.filter(
+ (x: { type: string }) => x.type == "photo",
+ );
const embed: Embed = {
type: EmbedType.rich,
@@ -334,7 +334,7 @@ export const EmbedHandlers: {
width: 640,
height: 640,
proxy_url: metas.image
- ? getProxyUrl(new URL(metas.image!), 640, 640)
+ ? getProxyUrl(new URL(metas.image), 640, 640)
: undefined,
url: metas.image,
},
@@ -365,9 +365,9 @@ export const EmbedHandlers: {
url: url.href,
proxy_url: metas.image
? getProxyUrl(
- new URL(metas.image!),
- metas.width!,
- metas.height!,
+ new URL(metas.image),
+ metas.width,
+ metas.height,
)
: undefined,
},
@@ -395,7 +395,7 @@ export const EmbedHandlers: {
height: 215,
url: metas.image,
proxy_url: metas.image
- ? getProxyUrl(new URL(metas.image!), 460, 215)
+ ? getProxyUrl(new URL(metas.image), 460, 215)
: undefined,
},
provider: {
@@ -436,7 +436,7 @@ export const EmbedHandlers: {
// TODO: does this adjust with aspect ratio?
width: metas.width,
height: metas.height,
- url: metas.youtube_embed!,
+ url: metas.youtube_embed,
},
url: url.href,
type: EmbedType.video,
@@ -447,9 +447,9 @@ export const EmbedHandlers: {
url: metas.image,
proxy_url: metas.image
? getProxyUrl(
- new URL(metas.image!),
- metas.width!,
- metas.height!,
+ new URL(metas.image),
+ metas.width,
+ metas.height,
)
: undefined,
},
diff --git a/src/api/util/utility/RandomInviteID.ts b/src/api/util/utility/RandomInviteID.ts
index e95b4d1d..7ce54ad2 100644
--- a/src/api/util/utility/RandomInviteID.ts
+++ b/src/api/util/utility/RandomInviteID.ts
@@ -24,7 +24,7 @@ import crypto from "crypto";
export function random(length = 6) {
// Declare all characters
- let chars =
+ const chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// Pick characers randomly
@@ -38,14 +38,14 @@ export function random(length = 6) {
export function snowflakeBasedInvite() {
// Declare all characters
- let chars =
+ const chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- let base = BigInt(chars.length);
+ const base = BigInt(chars.length);
let snowflake = Snowflake.generateWorkerProcess();
// snowflakes hold ~10.75 characters worth of entropy;
// safe to generate a 8-char invite out of them
- let str = "";
+ const str = "";
for (let i = 0; i < 10; i++) {
str.concat(chars.charAt(Number(snowflake % base)));
snowflake = snowflake / base;
diff --git a/src/api/util/utility/captcha.ts b/src/api/util/utility/captcha.ts
index 2d31f891..bd05582f 100644
--- a/src/api/util/utility/captcha.ts
+++ b/src/api/util/utility/captcha.ts
@@ -47,7 +47,10 @@ export async function verifyCaptcha(response: string, ip?: string) {
const { security } = Config.get();
const { service, secret, sitekey } = security.captcha;
- if (!service) throw new Error("Cannot verify captcha without service");
+ if (!service || !secret || !sitekey)
+ throw new Error(
+ "CAPTCHA is not configured correctly. https://docs.fosscord.com/setup/server/security/captcha/",
+ );
const res = await fetch(verifyEndpoints[service], {
method: "POST",
@@ -56,9 +59,9 @@ export async function verifyCaptcha(response: string, ip?: string) {
},
body:
`response=${encodeURIComponent(response)}` +
- `&secret=${encodeURIComponent(secret!)}` +
- `&sitekey=${encodeURIComponent(sitekey!)}` +
- (ip ? `&remoteip=${encodeURIComponent(ip!)}` : ""),
+ `&secret=${encodeURIComponent(secret)}` +
+ `&sitekey=${encodeURIComponent(sitekey)}` +
+ (ip ? `&remoteip=${encodeURIComponent(ip)}` : ""),
});
return (await res.json()) as hcaptchaResponse | recaptchaResponse;
diff --git a/src/api/util/utility/ipAddress.ts b/src/api/util/utility/ipAddress.ts
index 785844ce..71a48682 100644
--- a/src/api/util/utility/ipAddress.ts
+++ b/src/api/util/utility/ipAddress.ts
@@ -85,7 +85,7 @@ export async function IPAnalysis(ip: string): Promise<typeof exampleData> {
return (
await fetch(`https://api.ipdata.co/${ip}?api-key=${ipdataApiKey}`)
- ).json() as any; // TODO: types
+ ).json();
}
export function isProxy(data: typeof exampleData) {
@@ -97,14 +97,21 @@ export function isProxy(data: typeof exampleData) {
}
export function getIpAdress(req: Request): string {
+ // TODO: express can do this (trustProxies: true)?
+
return (
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
req.headers[Config.get().security.forwadedFor] ||
req.socket.remoteAddress
);
}
-export function distanceBetweenLocations(loc1: any, loc2: any): number {
+type Location = { latitude: number; longitude: number };
+export function distanceBetweenLocations(
+ loc1: Location,
+ loc2: Location,
+): number {
return distanceBetweenCoords(
loc1.latitude,
loc1.longitude,
diff --git a/src/api/util/utility/passwordStrength.ts b/src/api/util/utility/passwordStrength.ts
index c4dcd509..b293b856 100644
--- a/src/api/util/utility/passwordStrength.ts
+++ b/src/api/util/utility/passwordStrength.ts
@@ -23,7 +23,7 @@ const reNUMBER = /[0-9]/g;
const reUPPERCASELETTER = /[A-Z]/g;
const reSYMBOLS = /[A-Z,a-z,0-9]/g;
-const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored in db
+// const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored in db
/*
* https://en.wikipedia.org/wiki/Password_policy
* password must meet following criteria, to be perfect:
@@ -38,7 +38,7 @@ const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored
export function checkPassword(password: string): number {
const { minLength, minNumbers, minUpperCase, minSymbols } =
Config.get().register.password;
- var strength = 0;
+ let strength = 0;
// checks for total password len
if (password.length >= minLength - 1) {
@@ -68,13 +68,13 @@ export function checkPassword(password: string): number {
strength = 0;
}
- let entropyMap: { [key: string]: number } = {};
+ const entropyMap: { [key: string]: number } = {};
for (let i = 0; i < password.length; i++) {
if (entropyMap[password[i]]) entropyMap[password[i]]++;
else entropyMap[password[i]] = 1;
}
- let entropies = Object.values(entropyMap);
+ const entropies = Object.values(entropyMap);
entropies.map((x) => x / entropyMap.length);
strength +=
diff --git a/src/bundle/Server.ts b/src/bundle/Server.ts
index a5f96c3a..96f6a149 100644
--- a/src/bundle/Server.ts
+++ b/src/bundle/Server.ts
@@ -24,7 +24,7 @@ import * as Api from "@fosscord/api";
import * as Gateway from "@fosscord/gateway";
import { CDNServer } from "@fosscord/cdn";
import express from "express";
-import { green, bold, yellow } from "picocolors";
+import { green, bold } from "picocolors";
import { Config, initDatabase, Sentry } from "@fosscord/util";
const app = express();
diff --git a/src/bundle/start.ts b/src/bundle/start.ts
index 10fb7c36..8da3cc20 100644
--- a/src/bundle/start.ts
+++ b/src/bundle/start.ts
@@ -29,14 +29,15 @@ import { execSync } from "child_process";
const cores = process.env.THREADS ? parseInt(process.env.THREADS) : 1;
-if (cluster.isPrimary) {
- function getCommitOrFail() {
- try {
- return execSync("git rev-parse HEAD").toString().trim();
- } catch (e) {
- return null;
- }
+function getCommitOrFail() {
+ try {
+ return execSync("git rev-parse HEAD").toString().trim();
+ } catch (e) {
+ return null;
}
+}
+
+if (cluster.isPrimary) {
const commit = getCommitOrFail();
console.log(
@@ -81,14 +82,14 @@ Cores: ${cyan(os.cpus().length)} (Using ${cores} thread(s).)
// Fork workers.
for (let i = 0; i < cores; i++) {
// Delay each worker start if using sqlite database to prevent locking it
- let delay = process.env.DATABASE?.includes("://") ? 0 : i * 1000;
+ const delay = process.env.DATABASE?.includes("://") ? 0 : i * 1000;
setTimeout(() => {
cluster.fork();
console.log(`[Process] worker ${cyan(i)} started.`);
}, delay);
}
- cluster.on("message", (sender: Worker, message: any) => {
+ cluster.on("message", (sender: Worker, message) => {
for (const id in cluster.workers) {
const worker = cluster.workers[id];
if (worker === sender || !worker) continue;
@@ -96,7 +97,7 @@ Cores: ${cyan(os.cpus().length)} (Using ${cores} thread(s).)
}
});
- cluster.on("exit", (worker: any, code: any, signal: any) => {
+ cluster.on("exit", (worker) => {
console.log(
`[Worker] ${red(
`died with PID: ${worker.process.pid} , restarting ...`,
diff --git a/src/cdn/Server.ts b/src/cdn/Server.ts
index bb7c9edf..37317bff 100644
--- a/src/cdn/Server.ts
+++ b/src/cdn/Server.ts
@@ -24,7 +24,7 @@ import guildProfilesRoute from "./routes/guild-profiles";
import iconsRoute from "./routes/role-icons";
import bodyParser from "body-parser";
-export interface CDNServerOptions extends ServerOptions {}
+export type CDNServerOptions = ServerOptions;
export class CDNServer extends Server {
public declare options: CDNServerOptions;
diff --git a/src/cdn/routes/attachments.ts b/src/cdn/routes/attachments.ts
index 76824925..d7764bd7 100644
--- a/src/cdn/routes/attachments.ts
+++ b/src/cdn/routes/attachments.ts
@@ -41,7 +41,7 @@ router.post(
throw new HTTPError("Invalid request signature");
if (!req.file) throw new HTTPError("file missing");
- const { buffer, mimetype, size, originalname, fieldname } = req.file;
+ const { buffer, mimetype, size, originalname } = req.file;
const { channel_id } = req.params;
const filename = originalname
.replaceAll(" ", "_")
@@ -53,8 +53,8 @@ router.post(
Config.get()?.cdn.endpointPublic || "http://localhost:3003";
await storage.set(path, buffer);
- var width;
- var height;
+ let width;
+ let height;
if (mimetype.includes("image")) {
const dimensions = imageSize(buffer);
if (dimensions) {
@@ -81,10 +81,10 @@ router.get(
"/:channel_id/:id/:filename",
async (req: Request, res: Response) => {
const { channel_id, id, filename } = req.params;
- const { format } = req.query;
+ // const { format } = req.query;
const path = `attachments/${channel_id}/${id}/${filename}`;
- let file = await storage.get(path);
+ const file = await storage.get(path);
if (!file) throw new HTTPError("File not found");
const type = await FileType.fromBuffer(file);
let content_type = type?.mime || "application/octet-stream";
diff --git a/src/cdn/routes/avatars.ts b/src/cdn/routes/avatars.ts
index e2d80d11..2c078c29 100644
--- a/src/cdn/routes/avatars.ts
+++ b/src/cdn/routes/avatars.ts
@@ -48,10 +48,10 @@ router.post(
if (req.headers.signature !== Config.get().security.requestSignature)
throw new HTTPError("Invalid request signature");
if (!req.file) throw new HTTPError("Missing file");
- const { buffer, mimetype, size, originalname, fieldname } = req.file;
+ const { buffer, size } = req.file;
const { user_id } = req.params;
- var hash = crypto
+ let hash = crypto
.createHash("md5")
.update(Snowflake.generate())
.digest("hex");
@@ -77,7 +77,7 @@ router.post(
);
router.get("/:user_id", async (req: Request, res: Response) => {
- var { user_id } = req.params;
+ let { user_id } = req.params;
user_id = user_id.split(".")[0]; // remove .file extension
const path = `avatars/${user_id}`;
@@ -92,7 +92,8 @@ router.get("/:user_id", async (req: Request, res: Response) => {
});
export const getAvatar = async (req: Request, res: Response) => {
- var { user_id, hash } = req.params;
+ const { user_id } = req.params;
+ let { hash } = req.params;
hash = hash.split(".")[0]; // remove .file extension
const path = `avatars/${user_id}/${hash}`;
diff --git a/src/cdn/routes/guild-profiles.ts b/src/cdn/routes/guild-profiles.ts
index 517550b7..a02d152c 100644
--- a/src/cdn/routes/guild-profiles.ts
+++ b/src/cdn/routes/guild-profiles.ts
@@ -45,7 +45,7 @@ router.post("/", multer.single("file"), async (req: Request, res: Response) => {
if (req.headers.signature !== Config.get().security.requestSignature)
throw new HTTPError("Invalid request signature");
if (!req.file) throw new HTTPError("Missing file");
- const { buffer, mimetype, size, originalname, fieldname } = req.file;
+ const { buffer, size } = req.file;
const { guild_id, user_id } = req.params;
let hash = crypto
@@ -72,7 +72,8 @@ router.post("/", multer.single("file"), async (req: Request, res: Response) => {
});
router.get("/", async (req: Request, res: Response) => {
- let { guild_id, user_id } = req.params;
+ const { guild_id } = req.params;
+ let { user_id } = req.params;
user_id = user_id.split(".")[0]; // remove .file extension
const path = `guilds/${guild_id}/users/${user_id}/avatars`;
@@ -87,7 +88,8 @@ router.get("/", async (req: Request, res: Response) => {
});
router.get("/:hash", async (req: Request, res: Response) => {
- let { guild_id, user_id, hash } = req.params;
+ const { guild_id, user_id } = req.params;
+ let { hash } = req.params;
hash = hash.split(".")[0]; // remove .file extension
const path = `guilds/${guild_id}/users/${user_id}/avatars/${hash}`;
diff --git a/src/cdn/routes/role-icons.ts b/src/cdn/routes/role-icons.ts
index b6e6812e..c3ad51c1 100644
--- a/src/cdn/routes/role-icons.ts
+++ b/src/cdn/routes/role-icons.ts
@@ -48,10 +48,10 @@ router.post(
if (req.headers.signature !== Config.get().security.requestSignature)
throw new HTTPError("Invalid request signature");
if (!req.file) throw new HTTPError("Missing file");
- const { buffer, mimetype, size, originalname, fieldname } = req.file;
+ const { buffer, size } = req.file;
const { role_id } = req.params;
- var hash = crypto
+ const hash = crypto
.createHash("md5")
.update(Snowflake.generate())
.digest("hex");
@@ -76,7 +76,7 @@ router.post(
);
router.get("/:role_id", async (req: Request, res: Response) => {
- var { role_id } = req.params;
+ const { role_id } = req.params;
//role_id = role_id.split(".")[0]; // remove .file extension
const path = `role-icons/${role_id}`;
@@ -91,7 +91,7 @@ router.get("/:role_id", async (req: Request, res: Response) => {
});
router.get("/:role_id/:hash", async (req: Request, res: Response) => {
- var { role_id, hash } = req.params;
+ const { role_id, hash } = req.params;
//hash = hash.split(".")[0]; // remove .file extension
const path = `role-icons/${role_id}/${hash}`;
diff --git a/src/cdn/util/FileStorage.ts b/src/cdn/util/FileStorage.ts
index c8473e30..ee087c85 100644
--- a/src/cdn/util/FileStorage.ts
+++ b/src/cdn/util/FileStorage.ts
@@ -28,7 +28,7 @@ import ExifTransformer from "exif-be-gone";
function getPath(path: string) {
// STORAGE_LOCATION has a default value in start.ts
const root = process.env.STORAGE_LOCATION || "../";
- var filename = join(root, path);
+ const filename = join(root, path);
if (path.indexOf("\0") !== -1 || !filename.startsWith(root))
throw new Error("invalid path");
@@ -51,15 +51,15 @@ export class FileStorage implements Storage {
}
}
- async set(path: string, value: any) {
+ async set(path: string, value: Buffer) {
path = getPath(path);
if (!fs.existsSync(dirname(path)))
fs.mkdirSync(dirname(path), { recursive: true });
- value = Readable.from(value);
+ const ret = Readable.from(value);
const cleaned_file = fs.createWriteStream(path);
- return value.pipe(new ExifTransformer()).pipe(cleaned_file);
+ ret.pipe(new ExifTransformer()).pipe(cleaned_file);
}
async delete(path: string) {
diff --git a/src/cdn/util/Storage.ts b/src/cdn/util/Storage.ts
index ee4ae889..0d55bbd0 100644
--- a/src/cdn/util/Storage.ts
+++ b/src/cdn/util/Storage.ts
@@ -19,7 +19,6 @@
import { FileStorage } from "./FileStorage";
import path from "path";
import fs from "fs";
-import { bgCyan, black } from "picocolors";
import { S3 } from "@aws-sdk/client-s3";
import { S3Storage } from "./S3Storage";
process.cwd();
diff --git a/src/gateway/Server.ts b/src/gateway/Server.ts
index f1ef7a27..81e4b7f4 100644
--- a/src/gateway/Server.ts
+++ b/src/gateway/Server.ts
@@ -56,7 +56,6 @@ export class Server {
}
this.server.on("upgrade", (request, socket, head) => {
- // @ts-ignore
this.ws.handleUpgrade(request, socket, head, (socket) => {
this.ws.emit("connection", socket, request);
});
diff --git a/src/gateway/events/Close.ts b/src/gateway/events/Close.ts
index 6b069d0b..296ab5ee 100644
--- a/src/gateway/events/Close.ts
+++ b/src/gateway/events/Close.ts
@@ -26,7 +26,7 @@ import {
User,
} from "@fosscord/util";
-export async function Close(this: WebSocket, code: number, reason: string) {
+export async function Close(this: WebSocket, code: number, reason: Buffer) {
console.log("[WebSocket] closed", code, reason.toString());
if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout);
if (this.readyTimeout) clearTimeout(this.readyTimeout);
diff --git a/src/gateway/events/Connection.ts b/src/gateway/events/Connection.ts
index 85ffb1ed..82081266 100644
--- a/src/gateway/events/Connection.ts
+++ b/src/gateway/events/Connection.ts
@@ -16,6 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/* eslint-disable @typescript-eslint/ban-ts-comment */
import WS from "ws";
import { genSessionId, WebSocket } from "@fosscord/gateway";
import { Send } from "../util/Send";
@@ -27,10 +28,12 @@ import { Message } from "./Message";
import { Deflate, Inflate } from "fast-zlib";
import { URL } from "url";
import { Config } from "@fosscord/util";
-var erlpack: any;
+let erlpack: unknown;
try {
erlpack = require("@yukikaze-bot/erlpack");
-} catch (error) {}
+} catch (error) {
+ /* empty */
+}
// TODO: check rate limit
// TODO: specify rate limit in config
diff --git a/src/gateway/events/Message.ts b/src/gateway/events/Message.ts
index 57899a23..b949f273 100644
--- a/src/gateway/events/Message.ts
+++ b/src/gateway/events/Message.ts
@@ -27,14 +27,16 @@ import path from "path";
import fs from "fs/promises";
const bigIntJson = BigIntJson({ storeAsString: true });
-var erlpack: any;
+let erlpack: { unpack: (buffer: Buffer) => Payload };
try {
erlpack = require("@yukikaze-bot/erlpack");
-} catch (error) {}
+} catch (error) {
+ /* empty */
+}
export async function Message(this: WebSocket, buffer: WS.Data) {
// TODO: compression
- var data: Payload;
+ let data: Payload;
if (
(buffer instanceof Buffer && buffer[0] === 123) || // ASCII 123 = `{`. Bad check for JSON
@@ -44,9 +46,9 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
} else if (this.encoding === "json" && buffer instanceof Buffer) {
if (this.inflate) {
try {
- buffer = this.inflate.process(buffer) as any;
+ buffer = this.inflate.process(buffer);
} catch {
- buffer = buffer.toString() as any;
+ buffer = buffer.toString();
}
}
data = bigIntJson.parse(buffer as string);
@@ -78,7 +80,6 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
check.call(this, PayloadSchema, data);
- // @ts-ignore
const OPCodeHandler = OPCodeHandlers[data.op];
if (!OPCodeHandler) {
console.error("[Gateway] Unkown opcode " + data.op);
@@ -100,7 +101,7 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
: undefined;
try {
- var ret = await OPCodeHandler.call(this, data);
+ const ret = await OPCodeHandler.call(this, data);
Sentry.withScope((scope) => {
scope.setSpan(transaction);
scope.setUser({ id: this.user_id });
diff --git a/src/gateway/listener/listener.ts b/src/gateway/listener/listener.ts
index 9bdee86a..824341f9 100644
--- a/src/gateway/listener/listener.ts
+++ b/src/gateway/listener/listener.ts
@@ -79,7 +79,10 @@ export async function setupListener(this: WebSocket) {
const guilds = members.map((x) => x.guild);
const dm_channels = recipients.map((x) => x.channel);
- const opts: { acknowledge: boolean; channel?: AMQChannel } = {
+ const opts: {
+ acknowledge: boolean;
+ channel?: AMQChannel & { queues?: unknown };
+ } = {
acknowledge: true,
};
this.listen_options = opts;
@@ -87,7 +90,6 @@ export async function setupListener(this: WebSocket) {
if (RabbitMQ.connection) {
opts.channel = await RabbitMQ.connection.createChannel();
- // @ts-ignore
opts.channel.queues = {};
}
@@ -113,7 +115,7 @@ export async function setupListener(this: WebSocket) {
guild.channels.forEach(async (channel) => {
if (
permission
- .overwriteChannel(channel.permission_overwrites!)
+ .overwriteChannel(channel.permission_overwrites ?? [])
.has("VIEW_CHANNEL")
) {
this.events[channel.id] = await listenEvent(
@@ -128,7 +130,7 @@ export async function setupListener(this: WebSocket) {
this.once("close", () => {
if (opts.channel) opts.channel.close();
else {
- Object.values(this.events).forEach((x) => x());
+ Object.values(this.events).forEach((x) => x?.());
Object.values(this.member_events).forEach((x) => x());
}
});
@@ -137,7 +139,7 @@ export async function setupListener(this: WebSocket) {
// TODO: only subscribe for events that are in the connection intents
async function consume(this: WebSocket, opts: EventOpts) {
const { data, event } = opts;
- let id = data.id as string;
+ const id = data.id as string;
const permission = this.permissions[id] || new Permissions("ADMINISTRATOR"); // default permission for dm
const consumer = consume.bind(this);
@@ -150,6 +152,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
case "GUILD_MEMBER_REMOVE":
this.member_events[data.user.id]?.();
delete this.member_events[data.user.id];
+ break;
case "GUILD_MEMBER_ADD":
if (this.member_events[data.user.id]) break; // already subscribed
this.member_events[data.user.id] = await listenEvent(
@@ -158,7 +161,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
this.listen_options,
);
break;
- case "GUILD_MEMBER_REMOVE":
+ case "GUILD_MEMBER_UPDATE":
if (!this.member_events[data.user.id]) break;
this.member_events[data.user.id]();
break;
@@ -188,9 +191,8 @@ async function consume(this: WebSocket, opts: EventOpts) {
case "GUILD_CREATE":
this.events[id] = await listenEvent(id, consumer, listenOpts);
break;
- case "CHANNEL_UPDATE":
+ case "CHANNEL_UPDATE": {
const exists = this.events[id];
- // @ts-ignore
if (
permission
.overwriteChannel(data.permission_overwrites)
@@ -204,6 +206,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
delete this.events[id];
}
break;
+ }
}
// permission checking
@@ -218,8 +221,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
break;
case "GUILD_MEMBER_ADD":
case "GUILD_MEMBER_REMOVE":
- case "GUILD_MEMBER_UPDATE":
- // only send them, if the user subscribed for this part of the member list, or is a bot
+ case "GUILD_MEMBER_UPDATE": // only send them, if the user subscribed for this part of the member list, or is a bot
case "PRESENCE_UPDATE": // exception if user is friend
break;
case "GUILD_BAN_ADD":
diff --git a/src/gateway/opcodes/Heartbeat.ts b/src/gateway/opcodes/Heartbeat.ts
index b7f21a56..77c8671f 100644
--- a/src/gateway/opcodes/Heartbeat.ts
+++ b/src/gateway/opcodes/Heartbeat.ts
@@ -16,11 +16,11 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Payload, WebSocket } from "@fosscord/gateway";
+import { WebSocket } from "@fosscord/gateway";
import { setHeartbeat } from "../util/Heartbeat";
import { Send } from "../util/Send";
-export async function onHeartbeat(this: WebSocket, data: Payload) {
+export async function onHeartbeat(this: WebSocket) {
// TODO: validate payload
setHeartbeat(this);
diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts
index 8d762967..030ca66e 100644
--- a/src/gateway/opcodes/Identify.ts
+++ b/src/gateway/opcodes/Identify.ts
@@ -42,13 +42,13 @@ import {
UserGuildSettings,
ReadyGuildDTO,
Guild,
+ UserTokenData,
} from "@fosscord/util";
import { Send } from "../util/Send";
import { CLOSECODES, OPCODES } from "../util/Constants";
-import { genSessionId } from "../util/SessionUtils";
import { setupListener } from "../listener/listener";
// import experiments from "./experiments.json";
-const experiments: any = [];
+const experiments: unknown[] = [];
import { check } from "./instanceOf";
import { Recipient } from "@fosscord/util";
@@ -56,6 +56,8 @@ import { Recipient } from "@fosscord/util";
// TODO: check privileged intents, if defined in the config
// TODO: check if already identified
+// TODO: Refactor identify ( and lazyrequest, tbh )
+
export async function onIdentify(this: WebSocket, data: Payload) {
clearTimeout(this.readyTimeout);
// TODO: is this needed now that we use `json-bigint`?
@@ -65,15 +67,16 @@ export async function onIdentify(this: WebSocket, data: Payload) {
const identify: IdentifySchema = data.d;
+ let decoded: UserTokenData["decoded"];
try {
const { jwtSecret } = Config.get().security;
- var { decoded } = await checkToken(identify.token, jwtSecret); // will throw an error if invalid
+ decoded = (await checkToken(identify.token, jwtSecret)).decoded; // will throw an error if invalid
} catch (error) {
console.error("invalid token", error);
return this.close(CLOSECODES.Authentication_failed);
}
this.user_id = decoded.id;
- let session_id = this.session_id;
+ const session_id = this.session_id;
const [user, read_states, members, recipients, session, application] =
await Promise.all([
@@ -144,7 +147,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
return this.close(CLOSECODES.Invalid_shard);
}
}
- var users: PublicUser[] = [];
+ let users: PublicUser[] = [];
const merged_members = members.map((x: Member) => {
return [
@@ -156,18 +159,18 @@ export async function onIdentify(this: WebSocket, data: Payload) {
},
];
}) as PublicMember[][];
- let guilds = members.map((x) => ({ ...x.guild, joined_at: x.joined_at }));
+ // TODO: This type is bad.
+ let guilds: Partial<Guild>[] = members.map((x) => ({
+ ...x.guild,
+ joined_at: x.joined_at,
+ }));
const pending_guilds: typeof guilds = [];
- // @ts-ignore
- guilds = guilds.map((guild) => {
- if (user.bot) {
+ if (user.bot)
+ guilds = guilds.map((guild) => {
pending_guilds.push(guild);
return { id: guild.id, unavailable: true };
- }
-
- return guild;
- });
+ });
// TODO: Rewrite this. Perhaps a DTO?
const user_guild_settings_entries = members.map((x) => ({
@@ -180,24 +183,25 @@ export async function onIdentify(this: WebSocket, data: Payload) {
...y[1],
channel_id: y[0],
})),
- })) as any as UserGuildSettings[];
+ })) as unknown as UserGuildSettings[];
const channels = recipients.map((x) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
- x.channel.recipients = x.channel.recipients?.map((x) =>
+ x.channel.recipients = x.channel.recipients.map((x) =>
x.user.toPublicUser(),
);
//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 as unknown as User[]);
if (x.channel.isDm()) {
- x.channel.recipients = x.channel.recipients!.filter(
+ x.channel.recipients = x.channel.recipients?.filter(
(x) => x.id !== this.user_id,
);
}
return x.channel;
});
- for (let relation of user.relationships) {
+ for (const relation of user.relationships) {
const related_user = relation.to;
const public_related_user = {
username: related_user.username,
@@ -236,7 +240,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
} as PresenceUpdateEvent);
});
- read_states.forEach((s: any) => {
+ read_states.forEach((s: Partial<ReadState>) => {
s.id = s.channel_id;
delete s.user_id;
delete s.channel_id;
@@ -275,10 +279,11 @@ export async function onIdentify(this: WebSocket, data: Payload) {
}, //TODO: check this code!
user: privateUser,
user_settings: user.settings,
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
- guilds: guilds.map((x) => {
+ guilds: guilds.map((x: Guild & { joined_at: Date }) => {
return {
- ...new ReadyGuildDTO(x as Guild & { joined_at: Date }).toJSON(),
+ ...new ReadyGuildDTO(x).toJSON(),
guild_hashes: {},
joined_at: x.joined_at,
};
@@ -307,6 +312,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
},
country_code: user.settings.locale,
friend_suggestion_count: 0, // TODO
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
experiments: experiments, // TODO
guild_join_requests: [], // TODO what is this?
diff --git a/src/gateway/opcodes/LazyRequest.ts b/src/gateway/opcodes/LazyRequest.ts
index d4b612b8..93524058 100644
--- a/src/gateway/opcodes/LazyRequest.ts
+++ b/src/gateway/opcodes/LazyRequest.ts
@@ -46,24 +46,25 @@ async function getMembers(guild_id: string, range: [number, number]) {
let members: Member[] = [];
try {
- members = await getDatabase()!
- .getRepository(Member)
- .createQueryBuilder("member")
- .where("member.guild_id = :guild_id", { guild_id })
- .leftJoinAndSelect("member.roles", "role")
- .leftJoinAndSelect("member.user", "user")
- .leftJoinAndSelect("user.sessions", "session")
- .addSelect("user.settings")
- .addSelect(
- "CASE WHEN session.status = 'offline' THEN 0 ELSE 1 END",
- "_status",
- )
- .orderBy("role.position", "DESC")
- .addOrderBy("_status", "DESC")
- .addOrderBy("user.username", "ASC")
- .offset(Number(range[0]) || 0)
- .limit(Number(range[1]) || 100)
- .getMany();
+ members =
+ (await getDatabase()
+ ?.getRepository(Member)
+ .createQueryBuilder("member")
+ .where("member.guild_id = :guild_id", { guild_id })
+ .leftJoinAndSelect("member.roles", "role")
+ .leftJoinAndSelect("member.user", "user")
+ .leftJoinAndSelect("user.sessions", "session")
+ .addSelect("user.settings")
+ .addSelect(
+ "CASE WHEN session.status = 'offline' THEN 0 ELSE 1 END",
+ "_status",
+ )
+ .orderBy("role.position", "DESC")
+ .addOrderBy("_status", "DESC")
+ .addOrderBy("user.username", "ASC")
+ .offset(Number(range[0]) || 0)
+ .limit(Number(range[1]) || 100)
+ .getMany()) ?? [];
} catch (e) {
console.error(`LazyRequest`, e);
}
@@ -77,7 +78,7 @@ async function getMembers(guild_id: string, range: [number, number]) {
};
}
- const groups = [] as any[];
+ const groups = [];
const items = [];
const member_roles = members
.map((m) => m.roles)
@@ -93,10 +94,9 @@ async function getMembers(guild_id: string, range: [number, number]) {
const offlineItems = [];
for (const role of member_roles) {
- // @ts-ignore
- const [role_members, other_members]: Member[][] = partition(
+ const [role_members, other_members] = partition(
members,
- (m: Member) => m.roles.find((r) => r.id === role.id),
+ (m: Member) => !!m.roles.find((r) => r.id === role.id),
);
const group = {
count: role_members.length,
@@ -126,7 +126,7 @@ async function getMembers(guild_id: string, range: [number, number]) {
(a.activities.length - b.activities.length) * 2
);
});
- var session: Session | undefined = sessions.first();
+ const session: Session | undefined = sessions.first();
if (session?.status == "offline") {
session.status = member?.user?.settings?.status || "online";
@@ -189,7 +189,9 @@ async function getMembers(guild_id: string, range: [number, number]) {
export async function onLazyRequest(this: WebSocket, { d }: Payload) {
// TODO: check data
check.call(this, LazyRequestSchema, d);
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { guild_id, typing, channels, activities } = d as LazyRequestSchema;
+ if (!channels) throw new Error("Must provide channel ranges");
const channel_id = Object.keys(channels || {}).first();
if (!channel_id) return;
@@ -197,7 +199,7 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
const permissions = await getPermission(this.user_id, guild_id, channel_id);
permissions.hasThrow("VIEW_CHANNEL");
- const ranges = channels![channel_id];
+ const ranges = channels[channel_id];
if (!Array.isArray(ranges)) throw new Error("Not a valid Array");
const member_count = await Member.count({ where: { guild_id } });
@@ -244,15 +246,10 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
});
}
-function partition<T>(array: T[], isValid: Function) {
- // @ts-ignore
- return array.reduce(
- // @ts-ignore
- ([pass, fail], elem) => {
- return isValid(elem)
- ? [[...pass, elem], fail]
- : [pass, [...fail, elem]];
- },
- [[], []],
- );
+/* https://stackoverflow.com/a/50636286 */
+function partition<T>(array: T[], filter: (elem: T) => boolean) {
+ const pass: T[] = [],
+ fail: T[] = [];
+ array.forEach((e) => (filter(e) ? pass : fail).push(e));
+ return [pass, fail];
}
diff --git a/src/gateway/opcodes/RequestGuildMembers.ts b/src/gateway/opcodes/RequestGuildMembers.ts
index d669b30e..7822813b 100644
--- a/src/gateway/opcodes/RequestGuildMembers.ts
+++ b/src/gateway/opcodes/RequestGuildMembers.ts
@@ -16,8 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Payload, WebSocket } from "@fosscord/gateway";
+import { WebSocket } from "@fosscord/gateway";
-export function onRequestGuildMembers(this: WebSocket, data: Payload) {
+export function onRequestGuildMembers(this: WebSocket) {
// return this.close(CLOSECODES.Unknown_error);
}
diff --git a/src/gateway/opcodes/Resume.ts b/src/gateway/opcodes/Resume.ts
index d4bd5320..a8650cc4 100644
--- a/src/gateway/opcodes/Resume.ts
+++ b/src/gateway/opcodes/Resume.ts
@@ -16,10 +16,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { WebSocket, Payload } from "@fosscord/gateway";
+import { WebSocket } from "@fosscord/gateway";
import { Send } from "../util/Send";
-export async function onResume(this: WebSocket, data: Payload) {
+export async function onResume(this: WebSocket) {
console.log("Got Resume -> cancel not implemented");
await Send(this, {
op: 9,
diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts
index 5ee02e82..d300d7b7 100644
--- a/src/gateway/opcodes/VoiceStateUpdate.ts
+++ b/src/gateway/opcodes/VoiceStateUpdate.ts
@@ -99,6 +99,7 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
voiceState.token = genVoiceToken();
voiceState.session_id = this.session_id;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { id, ...newObj } = voiceState;
await Promise.all([
diff --git a/src/gateway/opcodes/index.ts b/src/gateway/opcodes/index.ts
index 05e8964b..1e32f1e6 100644
--- a/src/gateway/opcodes/index.ts
+++ b/src/gateway/opcodes/index.ts
@@ -25,7 +25,7 @@ import { onRequestGuildMembers } from "./RequestGuildMembers";
import { onResume } from "./Resume";
import { onVoiceStateUpdate } from "./VoiceStateUpdate";
-export type OPCodeHandler = (this: WebSocket, data: Payload) => any;
+export type OPCodeHandler = (this: WebSocket, data: Payload) => unknown;
export default {
1: onHeartbeat,
@@ -40,4 +40,4 @@ export default {
// 10: Hello
// 13: Dm_update
14: onLazyRequest,
-};
+} as { [key: number]: OPCodeHandler };
diff --git a/src/gateway/opcodes/instanceOf.ts b/src/gateway/opcodes/instanceOf.ts
index 17de0a67..6c23cb08 100644
--- a/src/gateway/opcodes/instanceOf.ts
+++ b/src/gateway/opcodes/instanceOf.ts
@@ -20,7 +20,7 @@ import { instanceOf } from "lambert-server";
import { WebSocket } from "@fosscord/gateway";
import { CLOSECODES } from "../util/Constants";
-export function check(this: WebSocket, schema: any, data: any) {
+export function check(this: WebSocket, schema: unknown, data: unknown) {
try {
const error = instanceOf(schema, data, { path: "body" });
if (error !== true) {
diff --git a/src/gateway/start.ts b/src/gateway/start.ts
index b86c3eca..79448f91 100644
--- a/src/gateway/start.ts
+++ b/src/gateway/start.ts
@@ -24,7 +24,7 @@ import { Server } from "./Server";
import { config } from "dotenv";
config();
-var port = Number(process.env.PORT);
+let port = Number(process.env.PORT);
if (isNaN(port)) port = 3002;
const server = new Server({
diff --git a/src/gateway/util/Constants.ts b/src/gateway/util/Constants.ts
index cc67ed0f..cb60005c 100644
--- a/src/gateway/util/Constants.ts
+++ b/src/gateway/util/Constants.ts
@@ -64,6 +64,7 @@ export enum CLOSECODES {
export interface Payload {
op: OPCODES /* | VoiceOPCodes */;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
d?: any;
s?: number;
t?: string;
diff --git a/src/gateway/util/Send.ts b/src/gateway/util/Send.ts
index 1ca143b6..a89d92d7 100644
--- a/src/gateway/util/Send.ts
+++ b/src/gateway/util/Send.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-var erlpack: any;
+let erlpack: { pack: (data: Payload) => Buffer };
try {
erlpack = require("@yukikaze-bot/erlpack");
} catch (error) {
@@ -63,7 +63,7 @@ export function Send(socket: WebSocket, data: Payload) {
return;
}
- socket.send(buffer, (err: any) => {
+ socket.send(buffer, (err) => {
if (err) return rej(err);
return res(null);
});
diff --git a/src/gateway/util/WebSocket.ts b/src/gateway/util/WebSocket.ts
index d4a4b8b3..14917f21 100644
--- a/src/gateway/util/WebSocket.ts
+++ b/src/gateway/util/WebSocket.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Intents, Permissions } from "@fosscord/util";
+import { Intents, ListenEventOpts, Permissions } from "@fosscord/util";
import WS from "ws";
import { Deflate, Inflate } from "fast-zlib";
// import { Client } from "@fosscord/webrtc";
@@ -37,8 +37,8 @@ export interface WebSocket extends WS {
intents: Intents;
sequence: number;
permissions: Record<string, Permissions>;
- events: Record<string, Function>;
- member_events: Record<string, Function>;
- listen_options: any;
+ events: Record<string, undefined | (() => unknown)>;
+ member_events: Record<string, () => unknown>;
+ listen_options: ListenEventOpts;
// client?: Client;
}
diff --git a/src/util/config/types/GifConfiguration.ts b/src/util/config/types/GifConfiguration.ts
index a623448c..0e5583fa 100644
--- a/src/util/config/types/GifConfiguration.ts
+++ b/src/util/config/types/GifConfiguration.ts
@@ -18,6 +18,6 @@
export class GifConfiguration {
enabled: boolean = true;
- provider: "tenor" = "tenor"; // more coming soon
+ provider = "tenor" as const; // more coming soon
apiKey?: string = "LIVDSRZULELA";
}
diff --git a/src/util/dtos/DmChannelDTO.ts b/src/util/dtos/DmChannelDTO.ts
index 9d4d8dc3..02f7e8f3 100644
--- a/src/util/dtos/DmChannelDTO.ts
+++ b/src/util/dtos/DmChannelDTO.ts
@@ -44,16 +44,14 @@ export class DmChannelDTO {
obj.type = channel.type;
obj.recipients = (
await Promise.all(
- channel
- .recipients!.filter(
- (r) => !excluded_recipients.includes(r.user_id),
- )
+ channel.recipients
+ ?.filter((r) => !excluded_recipients.includes(r.user_id))
.map(async (r) => {
return await User.findOneOrFail({
where: { id: r.user_id },
select: PublicUserProjection,
});
- }),
+ }) || [],
)
).map((u) => new MinimalPublicUserDTO(u));
return obj;
diff --git a/src/util/dtos/ReadyGuildDTO.ts b/src/util/dtos/ReadyGuildDTO.ts
index 38303aed..97e6931f 100644
--- a/src/util/dtos/ReadyGuildDTO.ts
+++ b/src/util/dtos/ReadyGuildDTO.ts
@@ -23,7 +23,7 @@ export interface IReadyGuildDTO {
channels: Channel[];
data_mode: string; // what is this
emojis: Emoji[];
- guild_scheduled_events: any[];
+ guild_scheduled_events: unknown[]; // TODO
id: string;
large: boolean | undefined;
lazy: boolean;
@@ -57,12 +57,12 @@ export interface IReadyGuildDTO {
max_video_channel_users: number | undefined;
max_members: number | undefined;
nsfw_level: number | undefined;
- hub_type?: any | null; // ????
+ hub_type?: unknown | null; // ????
};
roles: Role[];
- stage_instances: any[];
+ stage_instances: unknown[];
stickers: Sticker[];
- threads: any[];
+ threads: unknown[];
version: string;
}
@@ -71,7 +71,7 @@ export class ReadyGuildDTO implements IReadyGuildDTO {
channels: Channel[];
data_mode: string; // what is this
emojis: Emoji[];
- guild_scheduled_events: any[];
+ guild_scheduled_events: unknown[];
id: string;
large: boolean | undefined;
lazy: boolean;
@@ -105,12 +105,12 @@ export class ReadyGuildDTO implements IReadyGuildDTO {
max_video_channel_users: number | undefined;
max_members: number | undefined;
nsfw_level: number | undefined;
- hub_type?: any | null; // ????
+ hub_type?: unknown | null; // ????
};
roles: Role[];
- stage_instances: any[];
+ stage_instances: unknown[];
stickers: Sticker[];
- threads: any[];
+ threads: unknown[];
version: string;
constructor(guild: Guild) {
diff --git a/src/util/entities/Application.ts b/src/util/entities/Application.ts
index 94a015e9..94709320 100644
--- a/src/util/entities/Application.ts
+++ b/src/util/entities/Application.ts
@@ -16,16 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {
- Column,
- Entity,
- JoinColumn,
- ManyToOne,
- OneToOne,
- RelationId,
-} from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, OneToOne } from "typeorm";
import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
import { Team } from "./Team";
import { User } from "./User";
@@ -44,7 +36,7 @@ export class Application extends BaseClass {
summary: string = "";
@Column({ type: "simple-json", nullable: true })
- type?: any;
+ type?: object; // TODO: this type is bad
@Column()
hook: boolean = true;
@@ -176,6 +168,6 @@ export interface ApplicationCommandInteractionData {
export interface ApplicationCommandInteractionDataOption {
name: string;
- value?: any;
+ value?: unknown;
options?: ApplicationCommandInteractionDataOption[];
}
diff --git a/src/util/entities/AuditLog.ts b/src/util/entities/AuditLog.ts
index 68893ea8..0cc2fc04 100644
--- a/src/util/entities/AuditLog.ts
+++ b/src/util/entities/AuditLog.ts
@@ -173,8 +173,8 @@ export interface AuditLogChangeValue {
explicit_content_filter?: number;
default_message_notifications?: number;
vanity_url_code?: string;
- $add?: {}[];
- $remove?: {}[];
+ $add?: object[]; // TODO: These types are bad.
+ $remove?: object[];
prune_delete_days?: number;
widget_enabled?: boolean;
widget_channel_id?: string;
diff --git a/src/util/entities/BackupCodes.ts b/src/util/entities/BackupCodes.ts
index 1245ecd1..467e1fe3 100644
--- a/src/util/entities/BackupCodes.ts
+++ b/src/util/entities/BackupCodes.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
import { BaseClass } from "./BaseClass";
import { User } from "./User";
import crypto from "crypto";
@@ -38,7 +38,7 @@ export class BackupCode extends BaseClass {
}
export function generateMfaBackupCodes(user_id: string) {
- let backup_codes: BackupCode[] = [];
+ const backup_codes: BackupCode[] = [];
for (let i = 0; i < 10; i++) {
const code = BackupCode.create({
user: { id: user_id },
diff --git a/src/util/entities/BaseClass.ts b/src/util/entities/BaseClass.ts
index e3df5ad4..445b3fc9 100644
--- a/src/util/entities/BaseClass.ts
+++ b/src/util/entities/BaseClass.ts
@@ -29,7 +29,7 @@ import { getDatabase } from "../util/Database";
import { OrmUtils } from "../imports/OrmUtils";
export class BaseClassWithoutId extends BaseEntity {
- private get construct(): any {
+ private get construct() {
return this.constructor;
}
@@ -37,19 +37,24 @@ export class BaseClassWithoutId extends BaseEntity {
return getDatabase()?.getMetadata(this.construct);
}
- assign(props: any) {
+ assign(props: object) {
OrmUtils.mergeDeep(this, props);
return this;
}
+ // TODO: fix eslint
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
toJSON(): any {
return Object.fromEntries(
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/no-non-null-assertion
this.metadata!.columns // @ts-ignore
.map((x) => [x.propertyName, this[x.propertyName]])
.concat(
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.metadata.relations.map((x) => [
x.propertyName,
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this[x.propertyName],
]),
diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts
index 2e5f030c..1f128713 100644
--- a/src/util/entities/Channel.ts
+++ b/src/util/entities/Channel.ts
@@ -35,7 +35,6 @@ import {
Snowflake,
trimSpecial,
InvisibleCharacters,
- ChannelTypes,
} from "../util";
import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
import { Recipient } from "./Recipient";
@@ -219,7 +218,7 @@ export class Channel extends BaseClass {
!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") &&
channel.name
) {
- for (var character of InvisibleCharacters)
+ for (const character of InvisibleCharacters)
if (channel.name.includes(character))
throw new HTTPError(
"Channel name cannot include invalid characters",
@@ -237,7 +236,7 @@ export class Channel extends BaseClass {
403,
);
- if (channel.name.match(/\-\-+/g))
+ if (channel.name.match(/--+/g))
throw new HTTPError(
"Channel name cannot include multiple adjacent dashes.",
403,
@@ -344,8 +343,9 @@ export class Channel extends BaseClass {
relations: ["channel", "channel.recipients"],
});
- for (let ur of userRecipients) {
- let re = ur.channel.recipients!.map((r) => r.user_id);
+ for (const ur of userRecipients) {
+ if (!ur.channel.recipients) continue;
+ const re = ur.channel.recipients.map((r) => r.user_id);
if (re.length === channelRecipients.length) {
if (containsAll(re, channelRecipients)) {
if (channel == null) {
@@ -380,8 +380,8 @@ export class Channel extends BaseClass {
const channel_dto = await DmChannelDTO.from(channel);
- if (type === ChannelType.GROUP_DM) {
- for (let recipient of channel.recipients!) {
+ if (type === ChannelType.GROUP_DM && channel.recipients) {
+ for (const recipient of channel.recipients) {
await emitEvent({
event: "CHANNEL_CREATE",
data: channel_dto.excludedRecipients([recipient.user_id]),
diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts
index 1d0d0586..9f0ce35e 100644
--- a/src/util/entities/ConnectedAccount.ts
+++ b/src/util/entities/ConnectedAccount.ts
@@ -20,8 +20,10 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { User } from "./User";
-export interface PublicConnectedAccount
- extends Pick<ConnectedAccount, "name" | "type" | "verified"> {}
+export type PublicConnectedAccount = Pick<
+ ConnectedAccount,
+ "name" | "type" | "verified"
+>;
@Entity("connected_accounts")
export class ConnectedAccount extends BaseClass {
diff --git a/src/util/entities/Emoji.ts b/src/util/entities/Emoji.ts
index 95a641f1..94ce3d54 100644
--- a/src/util/entities/Emoji.ts
+++ b/src/util/entities/Emoji.ts
@@ -20,7 +20,6 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { User } from ".";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
-import { Role } from "./Role";
@Entity("emojis")
export class Emoji extends BaseClass {
diff --git a/src/util/entities/Encryption.ts b/src/util/entities/Encryption.ts
index db9d0983..016b4331 100644
--- a/src/util/entities/Encryption.ts
+++ b/src/util/entities/Encryption.ts
@@ -16,32 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {
- Column,
- Entity,
- JoinColumn,
- ManyToOne,
- OneToMany,
- RelationId,
-} from "typeorm";
+import { Column, Entity } from "typeorm";
import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { PublicUserProjection, User } from "./User";
-import { HTTPError } from "lambert-server";
-import {
- containsAll,
- emitEvent,
- getPermission,
- Snowflake,
- trimSpecial,
- InvisibleCharacters,
-} from "../util";
-import { BitField, BitFieldResolvable, BitFlag } from "../util/BitField";
-import { Recipient } from "./Recipient";
-import { Message } from "./Message";
-import { ReadState } from "./ReadState";
-import { Invite } from "./Invite";
-import { DmChannelDTO } from "../dtos";
@Entity("security_settings")
export class SecuritySettings extends BaseClass {
diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts
index 9f300334..c835f5fc 100644
--- a/src/util/entities/Guild.ts
+++ b/src/util/entities/Guild.ts
@@ -20,10 +20,8 @@ import {
Column,
Entity,
JoinColumn,
- ManyToMany,
ManyToOne,
OneToMany,
- OneToOne,
RelationId,
} from "typeorm";
import { Config, handleFile, Snowflake } from "..";
@@ -370,12 +368,12 @@ export class Guild extends BaseClass {
}
});
- for (const channel of body.channels?.sort((a, b) =>
+ for (const channel of body.channels.sort((a) =>
a.parent_id ? 1 : -1,
)) {
- var id = ids.get(channel.id) || Snowflake.generate();
+ const id = ids.get(channel.id) || Snowflake.generate();
- var parent_id = ids.get(channel.parent_id);
+ const parent_id = ids.get(channel.parent_id);
await Channel.createChannel(
{ ...channel, guild_id, id, parent_id },
diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts
index 801b5738..c68fe215 100644
--- a/src/util/entities/Member.ts
+++ b/src/util/entities/Member.ts
@@ -33,7 +33,7 @@ import {
RelationId,
} from "typeorm";
import { Guild } from "./Guild";
-import { Config, emitEvent, FieldErrors } from "../util";
+import { Config, emitEvent } from "../util";
import {
GuildCreateEvent,
GuildDeleteEvent,
@@ -212,12 +212,16 @@ export class Member extends BaseClassWithoutId {
}
static async addRole(user_id: string, guild_id: string, role_id: string) {
- const [member, role] = await Promise.all([
+ const [member] = await Promise.all([
Member.findOneOrFail({
where: { id: user_id, guild_id },
relations: ["user", "roles"], // we don't want to load the role objects just the ids
- //@ts-ignore
- select: ["index", "roles.id"], // TODO fix type
+ select: {
+ index: true,
+ roles: {
+ id: true,
+ },
+ },
}),
Role.findOneOrFail({
where: { id: role_id, guild_id },
@@ -249,8 +253,12 @@ export class Member extends BaseClassWithoutId {
Member.findOneOrFail({
where: { id: user_id, guild_id },
relations: ["user", "roles"], // we don't want to load the role objects just the ids
- //@ts-ignore
- select: ["roles.id", "index"], // TODO: fix type
+ select: {
+ index: true,
+ roles: {
+ id: true,
+ },
+ },
}),
await Role.findOneOrFail({ where: { id: role_id, guild_id } }),
]);
@@ -327,7 +335,7 @@ export class Member extends BaseClassWithoutId {
guild_id,
user: {
sessions: {
- status: Not("invisible" as "invisible"), // lol typescript?
+ status: Not("invisible" as const), // lol typescript?
},
},
},
@@ -506,8 +514,7 @@ export const PublicMemberProjection: PublicMemberKeys[] = [
"premium_since",
];
-// @ts-ignore
-export type PublicMember = Pick<Member, Omit<PublicMemberKeys, "roles">> & {
+export type PublicMember = Omit<Pick<Member, PublicMemberKeys>, "roles"> & {
user: PublicUser;
roles: string[]; // only role ids not objects
};
diff --git a/src/util/entities/ReadState.ts b/src/util/entities/ReadState.ts
index a907b701..825beb03 100644
--- a/src/util/entities/ReadState.ts
+++ b/src/util/entities/ReadState.ts
@@ -26,7 +26,6 @@ import {
} from "typeorm";
import { BaseClass } from "./BaseClass";
import { Channel } from "./Channel";
-import { Message } from "./Message";
import { User } from "./User";
// for read receipts
diff --git a/src/util/entities/StickerPack.ts b/src/util/entities/StickerPack.ts
index 911d8d05..ce8d5e87 100644
--- a/src/util/entities/StickerPack.ts
+++ b/src/util/entities/StickerPack.ts
@@ -22,7 +22,6 @@ import {
JoinColumn,
ManyToOne,
OneToMany,
- OneToOne,
RelationId,
} from "typeorm";
import { Sticker } from ".";
diff --git a/src/util/entities/Team.ts b/src/util/entities/Team.ts
index 730ff75f..82859409 100644
--- a/src/util/entities/Team.ts
+++ b/src/util/entities/Team.ts
@@ -20,7 +20,6 @@ import {
Column,
Entity,
JoinColumn,
- ManyToMany,
ManyToOne,
OneToMany,
RelationId,
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index ed9e3884..658584c3 100644
--- a/src/util/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -17,8 +17,6 @@
*/
import {
- BeforeInsert,
- BeforeUpdate,
Column,
Entity,
FindOneOptions,
@@ -34,6 +32,7 @@ import { Member } from "./Member";
import { UserSettings } from "./UserSettings";
import { Session } from "./Session";
import { Config, FieldErrors, Snowflake, trimSpecial, adjustEmail } from "..";
+import { Request } from "express";
export enum PublicUserEnum {
username,
@@ -80,7 +79,7 @@ export const PrivateUserProjection = [
// Private user data that should never get sent to the client
export type PublicUser = Pick<User, PublicUserKeys>;
-export interface UserPublic extends Pick<User, PublicUserKeys> {}
+export type UserPublic = Pick<User, PublicUserKeys>;
export interface UserPrivate extends Pick<User, PrivateUserKeys> {
locale: string;
@@ -266,6 +265,7 @@ export class User extends BaseClass {
}
toPublicUser() {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const user: any = {};
PublicUserProjection.forEach((x) => {
user[x] = this[x];
@@ -277,6 +277,7 @@ export class User extends BaseClass {
return await User.findOneOrFail({
where: { id: user_id },
...opts,
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
select: [...PublicUserProjection, ...(opts?.select || [])], // TODO: fix
});
@@ -328,7 +329,6 @@ export class User extends BaseClass {
email,
username,
password,
- date_of_birth,
id,
req,
}: {
@@ -337,7 +337,7 @@ export class User extends BaseClass {
email?: string;
date_of_birth?: Date; // "2000-04-03"
id?: string;
- req?: any;
+ req?: Request;
}) {
// trim special uf8 control characters -> Backspace, Newline, ...
username = trimSpecial(username);
@@ -348,7 +348,8 @@ export class User extends BaseClass {
throw FieldErrors({
username: {
code: "USERNAME_TOO_MANY_USERS",
- message: req.t("auth:register.USERNAME_TOO_MANY_USERS"),
+ message:
+ req?.t("auth:register.USERNAME_TOO_MANY_USERS") || "",
},
});
}
@@ -357,7 +358,7 @@ export class User extends BaseClass {
// appearently discord doesn't save the date of birth and just calculate if nsfw is allowed
// if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false
const language =
- req.language === "en" ? "en-US" : req.language || "en-US";
+ req?.language === "en" ? "en-US" : req?.language || "en-US";
const settings = UserSettings.create({
locale: language,
@@ -386,7 +387,9 @@ export class User extends BaseClass {
setImmediate(async () => {
if (Config.get().guild.autoJoin.enabled) {
for (const guild of Config.get().guild.autoJoin.guilds || []) {
- await Member.addToGuild(user.id, guild).catch((e) => {});
+ await Member.addToGuild(user.id, guild).catch((e) =>
+ console.error("[Autojoin]", e),
+ );
}
}
});
diff --git a/src/util/imports/OrmUtils.ts b/src/util/imports/OrmUtils.ts
index e6551471..039c81fe 100644
--- a/src/util/imports/OrmUtils.ts
+++ b/src/util/imports/OrmUtils.ts
@@ -1,25 +1,10 @@
-/*
- Fosscord: A FOSS re-implementation and extension of the Discord.com backend.
- Copyright (C) 2023 Fosscord and Fosscord Contributors
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
-*/
-
-//source: https://github.com/typeorm/typeorm/blob/master/src/util/OrmUtils.ts
+// source: https://github.com/typeorm/typeorm/blob/master/src/util/OrmUtils.ts
+// Copyright (c) 2015-2022 TypeORM. http://typeorm.github.io
+/* eslint-disable @typescript-eslint/no-explicit-any */
+// @fc-license-skip
export class OrmUtils {
// Checks if it's an object made by Object.create(null), {} or new Object()
- private static isPlainObject(item: any) {
+ private static isPlainObject(item: unknown) {
if (item === null || item === undefined) {
return false;
}
diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts
index e902cdf3..c3bfbf9b 100644
--- a/src/util/interfaces/Event.ts
+++ b/src/util/interfaces/Event.ts
@@ -39,6 +39,7 @@ import {
Presence,
UserSettings,
IReadyGuildDTO,
+ ReadState,
} from "@fosscord/util";
export interface Event {
@@ -47,6 +48,7 @@ export interface Event {
channel_id?: string;
created_at?: Date;
event: EVENT;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any;
}
@@ -103,12 +105,12 @@ export interface ReadyEventData {
[number, [[number, [number, number]]]],
{ b: number; k: bigint[] }[],
][];
- guild_join_requests?: any[]; // ? what is this? this is new
+ guild_join_requests?: unknown[]; // ? what is this? this is new
shard?: [number, number];
user_settings?: UserSettings;
relationships?: PublicRelationship[]; // TODO
read_state: {
- entries: any[]; // TODO
+ entries: ReadState[]; // TODO
partial: boolean;
version: number;
};
@@ -124,7 +126,7 @@ export interface ReadyEventData {
merged_members?: PublicMember[][];
// probably all users who the user is in contact with
users?: PublicUser[];
- sessions: any[];
+ sessions: unknown[];
}
export interface ReadyEvent extends Event {
@@ -178,7 +180,7 @@ export interface GuildCreateEvent extends Event {
joined_at: Date;
// TODO: add them to guild
guild_scheduled_events: never[];
- guild_hashes: {};
+ guild_hashes: unknown;
presences: never[];
stage_instances: never[];
threads: never[];
@@ -408,7 +410,7 @@ export interface TypingStartEvent extends Event {
export interface UserUpdateEvent extends Event {
event: "USER_UPDATE";
- data: User;
+ data: Omit<User, "data">;
}
export interface UserDeleteEvent extends Event {
diff --git a/src/util/interfaces/Interaction.ts b/src/util/interfaces/Interaction.ts
index 8695fca9..4158eda1 100644
--- a/src/util/interfaces/Interaction.ts
+++ b/src/util/interfaces/Interaction.ts
@@ -21,7 +21,7 @@ import { AllowedMentions, Embed } from "../entities/Message";
export interface Interaction {
id: string;
type: InteractionType;
- data?: {};
+ data?: object; // TODO typing
guild_id: string;
channel_id: string;
member_id: string;
diff --git a/src/util/schemas/ChannelPermissionOverwriteSchema.ts b/src/util/schemas/ChannelPermissionOverwriteSchema.ts
index 97fe9dee..62d0ad14 100644
--- a/src/util/schemas/ChannelPermissionOverwriteSchema.ts
+++ b/src/util/schemas/ChannelPermissionOverwriteSchema.ts
@@ -18,5 +18,4 @@
import { ChannelPermissionOverwrite } from "@fosscord/util";
-export interface ChannelPermissionOverwriteSchema
- extends ChannelPermissionOverwrite {}
+export type ChannelPermissionOverwriteSchema = ChannelPermissionOverwrite;
diff --git a/src/util/schemas/IdentifySchema.ts b/src/util/schemas/IdentifySchema.ts
index 18ab2b49..9bb14ca3 100644
--- a/src/util/schemas/IdentifySchema.ts
+++ b/src/util/schemas/IdentifySchema.ts
@@ -18,6 +18,8 @@
import { ActivitySchema } from "@fosscord/util";
+// TODO: Need a way to allow camalCase and pascal_case without just duplicating the schema
+
export const IdentifySchema = {
token: String,
$intents: BigInt, // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
@@ -98,7 +100,7 @@ export interface IdentifySchema {
referring_domain_current?: string;
release_channel?: "stable" | "dev" | "ptb" | "canary";
client_build_number?: number;
- client_event_source?: any;
+ client_event_source?: string;
client_version?: string;
system_locale?: string;
};
@@ -111,23 +113,23 @@ export interface IdentifySchema {
guild_subscriptions?: boolean;
capabilities?: number;
client_state?: {
- guild_hashes?: any;
+ guild_hashes?: unknown;
highest_last_message_id?: string | number;
read_state_version?: number;
user_guild_settings_version?: number;
user_settings_version?: number;
useruser_guild_settings_version?: number;
private_channels_version?: number;
- guild_versions?: any;
+ guild_versions?: unknown;
api_code_version?: number;
};
clientState?: {
- guildHashes?: any;
+ guildHashes?: unknown;
highestLastMessageId?: string | number;
readStateVersion?: number;
userGuildSettingsVersion?: number;
useruserGuildSettingsVersion?: number;
- guildVersions?: any;
+ guildVersions?: unknown;
apiCodeVersion?: number;
};
v?: number;
diff --git a/src/util/schemas/LazyRequestSchema.ts b/src/util/schemas/LazyRequestSchema.ts
index 02fe0d8b..7cf3fd36 100644
--- a/src/util/schemas/LazyRequestSchema.ts
+++ b/src/util/schemas/LazyRequestSchema.ts
@@ -22,8 +22,8 @@ export interface LazyRequestSchema {
activities?: boolean;
threads?: boolean;
typing?: true;
- members?: any[];
- thread_member_lists?: any[];
+ members?: unknown[];
+ thread_member_lists?: unknown[];
}
export const LazyRequestSchema = {
@@ -32,6 +32,6 @@ export const LazyRequestSchema = {
$channels: Object,
$typing: Boolean,
$threads: Boolean,
- $members: [] as any[],
- $thread_member_lists: [] as any[],
+ $members: [] as unknown[],
+ $thread_member_lists: [] as unknown[],
};
diff --git a/src/util/schemas/MessageCreateSchema.ts b/src/util/schemas/MessageCreateSchema.ts
index 1dd5d32c..4ee6e738 100644
--- a/src/util/schemas/MessageCreateSchema.ts
+++ b/src/util/schemas/MessageCreateSchema.ts
@@ -18,6 +18,11 @@
import { Embed } from "@fosscord/util";
+type Attachment = {
+ id: string;
+ filename: string;
+};
+
export interface MessageCreateSchema {
type?: number;
content?: string;
@@ -41,11 +46,11 @@ export interface MessageCreateSchema {
fail_if_not_exists?: boolean;
};
payload_json?: string;
- file?: any;
+ file?: { filename: string };
/**
TODO: we should create an interface for attachments
TODO: OpenWAAO<-->attachment-style metadata conversion
**/
- attachments?: any[];
+ attachments?: Attachment[];
sticker_ids?: string[];
}
diff --git a/src/util/schemas/UserSettingsSchema.ts b/src/util/schemas/UserSettingsSchema.ts
index e25588c4..5a590b02 100644
--- a/src/util/schemas/UserSettingsSchema.ts
+++ b/src/util/schemas/UserSettingsSchema.ts
@@ -18,4 +18,4 @@
import { UserSettings } from "@fosscord/util";
-export interface UserSettingsSchema extends Partial<UserSettings> {}
+export type UserSettingsSchema = Partial<UserSettings>;
diff --git a/src/util/schemas/Validator.ts b/src/util/schemas/Validator.ts
index 26a88ef9..3190dd05 100644
--- a/src/util/schemas/Validator.ts
+++ b/src/util/schemas/Validator.ts
@@ -45,7 +45,7 @@ export const ajv = new Ajv({
addFormats(ajv);
-export function validateSchema<G>(schema: string, data: G): G {
+export function validateSchema<G extends object>(schema: string, data: G): G {
const valid = ajv.validate(schema, normalizeBody(data));
if (!valid) throw ajv.errors;
return data;
@@ -55,13 +55,13 @@ export function validateSchema<G>(schema: string, data: G): G {
// this removes null values as ajv doesn't treat them as undefined
// normalizeBody allows to handle circular structures without issues
// taken from https://github.com/serverless/serverless/blob/master/lib/classes/ConfigSchemaHandler/index.js#L30 (MIT license)
-export const normalizeBody = (body: any = {}) => {
+export const normalizeBody = (body: object = {}) => {
const normalizedObjectsSet = new WeakSet();
- const normalizeObject = (object: any) => {
+ const normalizeObject = (object: object) => {
if (normalizedObjectsSet.has(object)) return;
normalizedObjectsSet.add(object);
if (Array.isArray(object)) {
- for (const [index, value] of object.entries()) {
+ for (const [, value] of object.entries()) {
if (typeof value === "object") normalizeObject(value);
}
} else {
@@ -75,6 +75,8 @@ export const normalizeBody = (body: any = {}) => {
key === "discovery_splash"
)
continue;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore
delete object[key];
} else if (typeof value === "object") {
normalizeObject(value);
diff --git a/src/util/util/Array.ts b/src/util/util/Array.ts
index 1935fa7a..dbc75b85 100644
--- a/src/util/util/Array.ts
+++ b/src/util/util/Array.ts
@@ -16,6 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-export function containsAll(arr: any[], target: any[]) {
+// TODO: remove this function.
+
+export function containsAll(arr: unknown[], target: unknown[]) {
return target.every((v) => arr.includes(v));
}
diff --git a/src/util/util/AutoUpdate.ts b/src/util/util/AutoUpdate.ts
index 08836ea2..a4a97f3f 100644
--- a/src/util/util/AutoUpdate.ts
+++ b/src/util/util/AutoUpdate.ts
@@ -36,7 +36,7 @@ export function enableAutoUpdate(opts: {
downloadType?: "zip";
}) {
if (!opts.checkInterval) return;
- var interval = 1000 * 60 * 60 * 24;
+ const interval = 1000 * 60 * 60 * 24;
if (typeof opts.checkInterval === "number")
opts.checkInterval = 1000 * interval;
@@ -70,6 +70,7 @@ export function enableAutoUpdate(opts: {
});
}
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
async function download(url: string, dir: string) {
try {
// TODO: use file stream instead of buffer (to prevent crash because of high memory usage for big files)
@@ -99,7 +100,7 @@ async function getLatestVersion(url: string) {
try {
const agent = new ProxyAgent();
const response = await fetch(url, { agent });
- const content = (await response.json()) as any; // TODO: types
+ const content = await response.json();
return content.version;
} catch (error) {
throw new Error("[Auto update] check failed for " + url);
diff --git a/src/util/util/BitField.ts b/src/util/util/BitField.ts
index 62bc3c46..d8758327 100644
--- a/src/util/util/BitField.ts
+++ b/src/util/util/BitField.ts
@@ -6,7 +6,7 @@
export type BitFieldResolvable =
| number
- | BigInt
+ | bigint
| BitField
| string
| BitFieldResolvable[];
@@ -135,6 +135,7 @@ export class BitField {
* @returns {number}
*/
static resolve(bit: BitFieldResolvable = BigInt(0)): bigint {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const FLAGS = this.FLAGS || this.constructor?.FLAGS;
@@ -152,6 +153,7 @@ export class BitField {
if (bit instanceof BitField) return bit.bitfield;
if (Array.isArray(bit)) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const resolve = this.constructor?.resolve || this.resolve;
return bit
diff --git a/src/util/util/Config.ts b/src/util/util/Config.ts
index 4b2dbb0d..b83f1d7b 100644
--- a/src/util/util/Config.ts
+++ b/src/util/util/Config.ts
@@ -24,8 +24,8 @@ import { ConfigValue } from "../config";
// TODO: yaml instead of json
const overridePath = process.env.CONFIG_PATH ?? "";
-var config: ConfigValue;
-var pairs: ConfigEntity[];
+let config: ConfigValue;
+let pairs: ConfigEntity[];
// TODO: use events to inform about config updates
// Config keys are separated with _
@@ -84,6 +84,8 @@ export const Config = {
};
function applyConfig(val: ConfigValue) {
+ // TODO: typings
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
async function apply(obj: any, key = ""): Promise<any> {
if (typeof obj === "object" && obj !== null)
return Promise.all(
@@ -107,7 +109,9 @@ function applyConfig(val: ConfigValue) {
}
function pairsToConfig(pairs: ConfigEntity[]) {
- var value: any = {};
+ // TODO: typings
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const value: any = {};
pairs.forEach((p) => {
const keys = p.key.split("_");
diff --git a/src/util/util/Constants.ts b/src/util/util/Constants.ts
index d65fda58..1afdce49 100644
--- a/src/util/util/Constants.ts
+++ b/src/util/util/Constants.ts
@@ -1125,7 +1125,7 @@ export const MembershipStates = ["INSERTED", "INVITED", "ACCEPTED"];
export const WebhookTypes = ["Custom", "Incoming", "Channel Follower"];
function keyMirror(arr: string[]) {
- let tmp = Object.create(null);
+ const tmp = Object.create(null);
for (const value of arr) tmp[value] = value;
return tmp;
}
diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts
index 38011b9c..e1a4003f 100644
--- a/src/util/util/Database.ts
+++ b/src/util/util/Database.ts
@@ -25,14 +25,14 @@ import path from "path";
// UUID extension option is only supported with postgres
// We want to generate all id's with Snowflakes that's why we have our own BaseEntity class
-var dbConnection: DataSource | undefined;
+let dbConnection: DataSource | undefined;
// For typeorm cli
if (!process.env) {
config();
}
-let dbConnectionString =
+const dbConnectionString =
process.env.DATABASE || path.join(process.cwd(), "database.db");
const DatabaseType = dbConnectionString.includes("://")
@@ -41,6 +41,7 @@ const DatabaseType = dbConnectionString.includes("://")
const isSqlite = DatabaseType.includes("sqlite");
const DataSourceOptions = new DataSource({
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore type 'string' is not 'mysql' | 'sqlite' | 'mariadb' | etc etc
type: DatabaseType,
charset: "utf8mb4",
diff --git a/src/util/util/Email.ts b/src/util/util/Email.ts
index f45728fc..48d8cae1 100644
--- a/src/util/util/Email.ts
+++ b/src/util/util/Email.ts
@@ -17,27 +17,29 @@
*/
export const EMAIL_REGEX =
- /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+ /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export function adjustEmail(email?: string): string | undefined {
if (!email) return email;
// body parser already checked if it is a valid email
const parts = <RegExpMatchArray>email.match(EMAIL_REGEX);
- // @ts-ignore
if (!parts || parts.length < 5) return undefined;
- const domain = parts[5];
- const user = parts[1];
- // TODO: check accounts with uncommon email domains
- if (domain === "gmail.com" || domain === "googlemail.com") {
- // replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator
- let v = user.replace(/[.]|(\+.*)/g, "") + "@gmail.com";
- }
+ return email;
+ // // TODO: The below code doesn't actually do anything.
+ // const domain = parts[5];
+ // const user = parts[1];
- if (domain === "google.com") {
- // replace .dots and +alternatives -> Google Staff GMail Dot Trick
- let v = user.replace(/[.]|(\+.*)/g, "") + "@google.com";
- }
+ // // TODO: check accounts with uncommon email domains
+ // if (domain === "gmail.com" || domain === "googlemail.com") {
+ // // replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator
+ // const v = user.replace(/[.]|(\+.*)/g, "") + "@gmail.com";
+ // }
- return email;
+ // if (domain === "google.com") {
+ // // replace .dots and +alternatives -> Google Staff GMail Dot Trick
+ // const v = user.replace(/[.]|(\+.*)/g, "") + "@google.com";
+ // }
+
+ // return email;
}
diff --git a/src/util/util/Event.ts b/src/util/util/Event.ts
index 5e01e644..79be1a10 100644
--- a/src/util/util/Event.ts
+++ b/src/util/util/Event.ts
@@ -55,6 +55,7 @@ export async function emitEvent(payload: Omit<Event, "created_at">) {
export async function initEvent() {
await RabbitMQ.init(); // does nothing if rabbitmq is not setup
if (RabbitMQ.connection) {
+ // empty on purpose?
} else {
// use event emitter
// use process messages
@@ -62,9 +63,9 @@ export async function initEvent() {
}
export interface EventOpts extends Event {
- acknowledge?: Function;
+ acknowledge?: () => unknown;
channel?: Channel;
- cancel: Function;
+ cancel: (id?: string) => unknown;
}
export interface ListenEventOpts {
@@ -80,17 +81,18 @@ export interface ProcessEvent {
export async function listenEvent(
event: string,
- callback: (event: EventOpts) => any,
+ callback: (event: EventOpts) => unknown,
opts?: ListenEventOpts,
) {
if (RabbitMQ.connection) {
- return await rabbitListen(
- // @ts-ignore
- opts?.channel || RabbitMQ.channel,
- event,
- callback,
- { acknowledge: opts?.acknowledge },
- );
+ const channel = opts?.channel || RabbitMQ.channel;
+ if (!channel)
+ throw new Error(
+ "[Events] An event was sent without an associated channel",
+ );
+ return await rabbitListen(channel, event, callback, {
+ acknowledge: opts?.acknowledge,
+ });
} else if (process.env.EVENT_TRANSMISSION === "process") {
const cancel = async () => {
process.removeListener("message", listener);
@@ -103,13 +105,13 @@ export async function listenEvent(
callback({ ...msg.event, cancel });
};
- //@ts-ignore apparently theres no function addListener with this signature
- process.addListener("message", listener);
+ // TODO: assert the type is correct?
+ process.addListener("message", (msg) => listener(msg as ProcessEvent));
process.setMaxListeners(process.getMaxListeners() + 1);
return cancel;
} else {
- const listener = (opts: any) => callback({ ...opts, cancel });
+ const listener = (opts: EventOpts) => callback({ ...opts, cancel });
const cancel = async () => {
events.removeListener(event, listener);
events.setMaxListeners(events.getMaxListeners() - 1);
@@ -124,7 +126,7 @@ export async function listenEvent(
async function rabbitListen(
channel: Channel,
id: string,
- callback: (event: EventOpts) => any,
+ callback: (event: EventOpts) => unknown,
opts?: { acknowledge?: boolean },
) {
await channel.assertExchange(id, "fanout", { durable: false });
diff --git a/src/util/util/FieldError.ts b/src/util/util/FieldError.ts
index 69df6f8e..eff793a8 100644
--- a/src/util/util/FieldError.ts
+++ b/src/util/util/FieldError.ts
@@ -42,7 +42,7 @@ export class FieldError extends Error {
constructor(
public code: string | number,
public message: string,
- public errors?: any,
+ public errors?: object, // TODO: I don't like this typing.
) {
super(message);
}
diff --git a/src/util/util/Permissions.ts b/src/util/util/Permissions.ts
index 19614640..996c72ea 100644
--- a/src/util/util/Permissions.ts
+++ b/src/util/util/Permissions.ts
@@ -12,14 +12,7 @@ import {
import { BitField } from "./BitField";
import "missing-native-js-functions";
import { BitFieldResolvable, BitFlag } from "./BitField";
-
-var HTTPError: any;
-
-try {
- HTTPError = require("lambert-server").HTTPError;
-} catch (e) {
- HTTPError = Error;
-}
+import { HTTPError } from "lambert-server";
export type PermissionResolvable =
| bigint
@@ -31,7 +24,7 @@ export type PermissionResolvable =
type PermissionString = keyof typeof Permissions.FLAGS;
// BigInt doesn't have a bit limit (https://stackoverflow.com/questions/53335545/whats-the-biggest-bigint-value-in-js-as-per-spec)
-const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(64); // 27 permission bits left for discord to add new ones
+// const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(64); // 27 permission bits left for discord to add new ones
export class Permissions extends BitField {
cache: PermissionCache = {};
@@ -114,7 +107,6 @@ export class Permissions extends BitField {
*/
hasThrow(permission: PermissionResolvable) {
if (this.has(permission) && this.has("VIEW_CHANNEL")) return true;
- // @ts-ignore
throw new HTTPError(
`You are missing the following permissions ${permission}`,
403,
@@ -177,11 +169,11 @@ export class Permissions extends BitField {
}) {
if (user.id === "0") return new Permissions("ADMINISTRATOR"); // system user id
- let roles = guild.roles.filter((x) => user.roles.includes(x.id));
+ const roles = guild.roles.filter((x) => user.roles.includes(x.id));
let permission = Permissions.rolePermission(roles);
if (channel?.overwrites) {
- let overwrites = channel.overwrites.filter((x) => {
+ const overwrites = channel.overwrites.filter((x) => {
if (x.type === 0 && user.roles.includes(x.id)) return true;
if (x.type === 1 && x.id == user.id) return true;
return false;
@@ -244,9 +236,9 @@ export async function getPermission(
} = {},
) {
if (!user_id) throw new HTTPError("User not found");
- var channel: Channel | undefined;
- var member: Member | undefined;
- var guild: Guild | undefined;
+ let channel: Channel | undefined;
+ let member: Member | undefined;
+ let guild: Guild | undefined;
if (channel_id) {
channel = await Channel.findOneOrFail({
@@ -258,7 +250,6 @@ export async function getPermission(
"permission_overwrites",
"owner_id",
"guild_id",
- // @ts-ignore
...(opts.channel_select || []),
],
});
@@ -268,12 +259,7 @@ export async function getPermission(
if (guild_id) {
guild = await Guild.findOneOrFail({
where: { id: guild_id },
- select: [
- "id",
- "owner_id",
- // @ts-ignore
- ...(opts.guild_select || []),
- ],
+ select: ["id", "owner_id", ...(opts.guild_select || [])],
relations: opts.guild_relations,
});
if (guild.owner_id === user_id)
@@ -285,17 +271,16 @@ export async function getPermission(
// select: [
// "id", // TODO: Bug in typeorm? adding these selects breaks the query.
// "roles",
- // @ts-ignore
// ...(opts.member_select || []),
// ],
});
}
- let recipient_ids: any = channel?.recipients?.map((x) => x.user_id);
- if (!recipient_ids?.length) recipient_ids = null;
+ let recipient_ids = channel?.recipients?.map((x) => x.user_id);
+ if (!recipient_ids?.length) recipient_ids = undefined;
// TODO: remove guild.roles and convert recipient_ids to recipients
- var permission = Permissions.finalPermission({
+ const permission = Permissions.finalPermission({
user: {
id: user_id,
roles: member?.roles.map((x) => x.id) || [],
diff --git a/src/util/util/Rights.ts b/src/util/util/Rights.ts
index 4d437956..b48477ed 100644
--- a/src/util/util/Rights.ts
+++ b/src/util/util/Rights.ts
@@ -20,14 +20,7 @@ import { BitField } from "./BitField";
import "missing-native-js-functions";
import { BitFieldResolvable, BitFlag } from "./BitField";
import { User } from "../entities";
-
-var HTTPError: any;
-
-try {
- HTTPError = require("lambert-server").HTTPError;
-} catch (e) {
- HTTPError = Error;
-}
+import { HTTPError } from "lambert-server";
export type RightResolvable =
| bigint
@@ -118,7 +111,6 @@ export class Rights extends BitField {
hasThrow(permission: RightResolvable) {
if (this.has(permission)) return true;
- // @ts-ignore
throw new HTTPError(
`You are missing the following rights ${permission}`,
403,
@@ -137,6 +129,6 @@ export async function getRights(
in_behalf?: (keyof User)[];
} = {} **/
) {
- let user = await User.findOneOrFail({ where: { id: user_id } });
+ const user = await User.findOneOrFail({ where: { id: user_id } });
return new Rights(user.rights);
}
diff --git a/src/util/util/Sentry.ts b/src/util/util/Sentry.ts
index b0eee169..e1248353 100644
--- a/src/util/util/Sentry.ts
+++ b/src/util/util/Sentry.ts
@@ -34,7 +34,7 @@ export const Sentry = {
Config.get().sentry;
if (!enabled) return;
- if (!!SentryNode.getCurrentHub().getClient()) return; // we've already initialised sentry
+ if (SentryNode.getCurrentHub().getClient()) return; // we've already initialised sentry
console.log("[Sentry] Enabling sentry...");
@@ -60,7 +60,7 @@ export const Sentry = {
environment,
});
- SentryNode.addGlobalEventProcessor((event, hint) => {
+ SentryNode.addGlobalEventProcessor((event) => {
if (event.transaction) {
// Rewrite things that look like IDs to `:id` for sentry
event.transaction = event.transaction
@@ -112,6 +112,8 @@ export const Sentry = {
errorHandlersUsed = true;
app.use(SentryNode.Handlers.errorHandler());
+ // The typings for this are broken?
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
app.use(function onError(err: any, req: any, res: any, next: any) {
res.statusCode = 500;
res.end(res.sentry + "\n");
diff --git a/src/util/util/Snowflake.ts b/src/util/util/Snowflake.ts
index 65546958..93898fbb 100644
--- a/src/util/util/Snowflake.ts
+++ b/src/util/util/Snowflake.ts
@@ -1,3 +1,4 @@
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import * as cluster from "cluster";
@@ -87,10 +88,10 @@ export class Snowflake {
static generateWorkerProcess() {
// worker process - returns a number
- var time = BigInt(Date.now() - Snowflake.EPOCH) << BigInt(22);
- var worker = Snowflake.workerId << 17n;
- var process = Snowflake.processId << 12n;
- var increment = Snowflake.INCREMENT++;
+ const time = BigInt(Date.now() - Snowflake.EPOCH) << BigInt(22);
+ const worker = Snowflake.workerId << 17n;
+ const process = Snowflake.processId << 12n;
+ const increment = Snowflake.INCREMENT++;
return BigInt(time | worker | process | increment);
}
diff --git a/src/util/util/String.ts b/src/util/util/String.ts
index 7addd49a..74fd0295 100644
--- a/src/util/util/String.ts
+++ b/src/util/util/String.ts
@@ -19,7 +19,6 @@
import { SPECIAL_CHAR } from "./Regex";
export function trimSpecial(str?: string): string {
- // @ts-ignore
- if (!str) return;
+ if (!str) return "";
return str.replace(SPECIAL_CHAR, "").trim();
}
diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts
index c00142bb..ca81eaaa 100644
--- a/src/util/util/Token.ts
+++ b/src/util/util/Token.ts
@@ -22,7 +22,15 @@ import { User } from "../entities";
export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] };
-export function checkToken(token: string, jwtSecret: string): Promise<any> {
+export type UserTokenData = {
+ user: User;
+ decoded: { id: string; iat: number };
+};
+
+export function checkToken(
+ token: string,
+ jwtSecret: string,
+): Promise<UserTokenData> {
return new Promise((res, rej) => {
token = token.replace("Bot ", "");
token = token.replace("Bearer ", "");
@@ -31,24 +39,35 @@ export function checkToken(token: string, jwtSecret: string): Promise<any> {
as we don't really have separate pathways for bots
**/
- jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded: any) => {
+ jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded) => {
if (err || !decoded) return rej("Invalid Token");
+ if (
+ typeof decoded == "string" ||
+ !("id" in decoded) ||
+ !decoded.iat
+ )
+ return rej("Invalid Token"); // will never happen, just for typings.
const user = await User.findOne({
where: { id: decoded.id },
select: ["data", "bot", "disabled", "deleted", "rights"],
});
+
if (!user) return rej("Invalid Token");
+
// we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds
if (
decoded.iat * 1000 <
new Date(user.data.valid_tokens_since).setSeconds(0, 0)
)
return rej("Invalid Token");
+
if (user.disabled) return rej("User disabled");
if (user.deleted) return rej("User not found");
- return res({ decoded, user });
+ // Using as here because we assert `id` and `iat` are in decoded.
+ // TS just doesn't want to assume its there, though.
+ return res({ decoded, user } as UserTokenData);
});
});
}
diff --git a/src/util/util/TraverseDirectory.ts b/src/util/util/TraverseDirectory.ts
index 0cc48d4a..223e3ee0 100644
--- a/src/util/util/TraverseDirectory.ts
+++ b/src/util/util/TraverseDirectory.ts
@@ -22,7 +22,7 @@ import { Server, traverseDirectory } from "lambert-server";
const extension =
Symbol.for("ts-node.register.instance") in process ? "ts" : "js";
-const DEFAULT_FILTER = new RegExp("^([^.].*)(?<!\.d).(" + extension + ")$");
+const DEFAULT_FILTER = new RegExp("^([^.].*)(?<!\\.d).(" + extension + ")$");
export function registerRoutes(server: Server, root: string) {
return traverseDirectory(
diff --git a/src/util/util/cdn.ts b/src/util/util/cdn.ts
index 6d2fd0f1..7f447c53 100644
--- a/src/util/util/cdn.ts
+++ b/src/util/util/cdn.ts
@@ -24,7 +24,8 @@ import { Config } from "./Config";
export async function uploadFile(
path: string,
- file?: Express.Multer.File,
+ // These are the only props we use, don't need to enforce the full type.
+ file?: Pick<Express.Multer.File, "mimetype" | "originalname" | "buffer">,
): Promise<Attachment> {
if (!file?.buffer) throw new HTTPError("Missing file in body");
@@ -60,7 +61,6 @@ export async function handleFile(
const mimetype = body.split(":")[1].split(";")[0];
const buffer = Buffer.from(body.split(",")[1], "base64");
- // @ts-ignore
const { id } = await uploadFile(path, {
buffer,
mimetype,
|