eslint: arrow-body-style=as-needed

This commit is contained in:
Rory&
2026-04-19 22:45:37 +02:00
parent d096ea7580
commit af29e6b178
20 changed files with 150 additions and 206 deletions
+5
View File
@@ -51,6 +51,11 @@ export default defineConfig([
"no-constructor-return": "error",
"no-duplicate-imports": "error",
"no-promise-executor-return": ["error", { allowVoid: true }],
"no-self-compare": "error",
"no-template-curly-in-string": "error",
"no-unmodified-loop-condition": "error",
"no-unreachable-loop": "error",
"arrow-body-style": ["error", "as-needed"],
// unsure what the defaults are here, but we want them to error
"for-direction": "error",
"constructor-super": "error",
+4 -4
View File
@@ -38,8 +38,8 @@ router.post(
(req: Request, res: Response) => {
const { attachment_urls } = req.body as RefreshUrlsRequestSchema;
const refreshed_urls = attachment_urls.map((url) => {
return getUrlSignature(
const refreshed_urls = attachment_urls.map((url) =>
getUrlSignature(
new NewUrlSignatureData({
url: url,
ip: req.ip,
@@ -47,8 +47,8 @@ router.post(
}),
)
.applyToUrl(url)
.toString();
});
.toString(),
);
return res.status(200).json({
refreshed_urls,
+1 -3
View File
@@ -52,9 +52,7 @@ router.post(
}
await Email.sendVerifyEmail(user, user.email)
.then(() => {
return res.sendStatus(204);
})
.then(() => res.sendStatus(204))
.catch((e) => {
console.error(`Failed to send verification email to ${user.tag}: ${e}`);
throw new HTTPError("Failed to send verification email", 500);
@@ -86,14 +86,12 @@ router.post(
);
res.send({
attachments: attachments.map((a) => {
return {
id: a.userAttachmentId,
upload_filename: a.uploadFilename,
upload_url: `${cdnUrl}/attachments/${a.uploadFilename}`,
original_content_type: a.userOriginalContentType,
};
}),
attachments: attachments.map((a) => ({
id: a.userAttachmentId,
upload_filename: a.uploadFilename,
upload_url: `${cdnUrl}/attachments/${a.uploadFilename}`,
original_content_type: a.userOriginalContentType,
})),
} as UploadAttachmentResponseSchema);
},
);
+12 -14
View File
@@ -126,20 +126,18 @@ async function getWidgetJsonData(guild_id: string) {
const minLastSeen = Date.now() - 1000 * 60 * 5;
const onlineMembers = members.filter((m) => m.user.sessions.filter((s) => (s.last_seen?.getTime() ?? 0) > minLastSeen).length > 0);
const memberData = onlineMembers
.map((x) => {
return {
id: x.id,
username: x.user.username,
discriminator: x.user.discriminator,
avatar: null,
status: "online", // TODO
avatar_url: x.avatar
? `${Config.get().cdn.endpointPublic}/guilds/${guild_id}/users/${x.id}/avatars/${x.avatar}.png`
: x.user.avatar
? `${Config.get().cdn.endpointPublic}/avatars/${x.id}/${x.user.avatar}.png`
: `${Config.get().cdn.endpointPublic}/embed/avatars/${BigInt(x.id) % 6n}.png`,
};
})
.map((x) => ({
id: x.id,
username: x.user.username,
discriminator: x.user.discriminator,
avatar: null,
status: "online", // TODO
avatar_url: x.avatar
? `${Config.get().cdn.endpointPublic}/guilds/${guild_id}/users/${x.id}/avatars/${x.avatar}.png`
: x.user.avatar
? `${Config.get().cdn.endpointPublic}/avatars/${x.id}/${x.user.avatar}.png`
: `${Config.get().cdn.endpointPublic}/embed/avatars/${BigInt(x.id) % 6n}.png`,
}))
.sort((a, b) => Number(BigInt(a.id) - BigInt(b.id)));
// Construct object to respond with
+11 -13
View File
@@ -137,20 +137,18 @@ router.get(
},
take: limit,
})
).map((m) => {
return {
...m.toJSON(),
attachments: m.attachments?.map((attachment: Attachment) =>
Attachment.prototype.signUrls.call(
attachment,
new NewUrlUserSignatureData({
ip: req.ip,
userAgent: req.headers["user-agent"] as string,
}),
),
).map((m) => ({
...m.toJSON(),
attachments: m.attachments?.map((attachment: Attachment) =>
Attachment.prototype.signUrls.call(
attachment,
new NewUrlUserSignatureData({
ip: req.ip,
userAgent: req.headers["user-agent"] as string,
}),
),
};
});
),
}));
console.log(`[Inbox/mentions] User ${user.id} fetched full message data for ${finalMessages.length} messages in ${sw.elapsed().totalMilliseconds}ms`);
@@ -25,13 +25,8 @@ import { HTTPError } from "lambert-server";
import { CreateWebAuthnCredentialSchema, GenerateWebAuthnCredentialsSchema, WebAuthnPostSchema } from "@spacebar/schemas";
const router = Router({ mergeParams: true });
const isGenerateSchema = (body: WebAuthnPostSchema): body is GenerateWebAuthnCredentialsSchema => {
return "password" in body;
};
const isCreateSchema = (body: WebAuthnPostSchema): body is CreateWebAuthnCredentialSchema => {
return "credential" in body;
};
const isGenerateSchema = (body: WebAuthnPostSchema): body is GenerateWebAuthnCredentialsSchema => "password" in body;
const isCreateSchema = (body: WebAuthnPostSchema): body is CreateWebAuthnCredentialSchema => "credential" in body;
function toArrayBuffer(buf: Buffer) {
const ab = new ArrayBuffer(buf.length);
+6 -8
View File
@@ -64,8 +64,8 @@ router.put(
},
},
}),
async (req: Request, res: Response) => {
return await updateRelationship(
async (req: Request, res: Response) =>
await updateRelationship(
req,
res,
await User.findOneOrFail({
@@ -74,8 +74,7 @@ router.put(
select: userProjection,
}),
req.body.type ?? RelationshipType.friends,
);
},
),
);
router.patch(
@@ -130,8 +129,8 @@ router.post(
},
},
}),
async (req: Request, res: Response) => {
return await updateRelationship(
async (req: Request, res: Response) =>
await updateRelationship(
req,
res,
await User.findOneOrFail({
@@ -143,8 +142,7 @@ router.post(
},
}),
req.body.type,
);
},
),
);
router.delete(
+6 -35
View File
@@ -562,24 +562,9 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
/*message.mention_channels = mention_channel_ids.map((x) =>
Channel.create({ id: x }),
);*/
message.mention_roles = (
await Promise.all(
mention_role_ids.map((x) => {
return Role.findOne({ where: { id: x } });
}),
)
).filter((role) => role !== null);
message.mention_roles = (await Promise.all(mention_role_ids.map((x) => Role.findOne({ where: { id: x } })))).filter((role) => role !== null);
message.mentions = [
...message.mentions,
...(
await Promise.all(
mention_user_ids.map((x) => {
return User.findOne({ where: { id: x } });
}),
)
).filter((user) => user !== null),
];
message.mentions = [...message.mentions, ...(await Promise.all(mention_user_ids.map((x) => User.findOne({ where: { id: x } })))).filter((user) => user !== null)];
message.mention_everyone = mention_everyone;
async function fillInMissingIDs(ids: string[]) {
@@ -592,11 +577,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
if (!users.size) {
return;
}
return Promise.all(
[...users].map((user_id) => {
return ReadState.create({ user_id, channel_id: channel.id }).save();
}),
);
return Promise.all([...users].map((user_id) => ReadState.create({ user_id, channel_id: channel.id }).save()));
}
if (ephermal) {
const id = message.interaction_metadata?.user_id;
@@ -624,11 +605,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
const users = new Set<string>([
...(message.mention_roles.length
? await Member.find({
where: [
...message.mention_roles.map((role) => {
return { roles: { id: role.id } };
}),
],
where: [...message.mention_roles.map((role) => ({ roles: { id: role.id } }))],
})
: []
).map((member) => member.id),
@@ -647,11 +624,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
}
}
const attachmentIndices = new Map(
message.attachments?.map((attachment, index) => {
return [`attachment://${attachment.filename}`, index];
}),
);
const attachmentIndices = new Map(message.attachments?.map((attachment, index) => [`attachment://${attachment.filename}`, index]));
const attachmentsToRemove = new Set<number>();
function fetchAttachment(url: string | undefined): Attachment | undefined {
if (url == undefined) {
@@ -690,9 +663,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
author!.proxy_icon_url = authorAttachment.toJSON().proxy_url;
}
}
message.attachments = message.attachments?.filter((_, index) => {
return !attachmentsToRemove.has(index);
});
message.attachments = message.attachments?.filter((_, index) => !attachmentsToRemove.has(index));
// TODO: check and put it all in the body
+1 -3
View File
@@ -603,9 +603,7 @@ export async function getOrUpdateEmbedCache(urls: string[], cb?: (url: string, e
.filter((e) => e !== undefined),
);
const urlsToGenerate = urls.filter((url) => {
return !cachedEmbeds.some((e) => e.url == normalizeUrl(url));
});
const urlsToGenerate = urls.filter((url) => !cachedEmbeds.some((e) => e.url == normalizeUrl(url)));
if (urlsToGenerate.length > 0) console.log("[Embeds] Need to generate embeds for urls:", urlsToGenerate);
if (cachedEmbeds.length > 0)
+4 -4
View File
@@ -92,9 +92,9 @@ export class Server {
})),
socketStates: {
open: openConnections.length,
sessions: openConnections.map((x) => {
sessions: openConnections.map((x) =>
// console.log(x);
return useFullWsObj
useFullWsObj
? {
...x,
...{
@@ -132,8 +132,8 @@ export class Server {
large_threshold: x.large_threshold,
qos: x.qos,
session: x.session,
};
}),
},
),
},
},
(key, value) => {
+1 -3
View File
@@ -146,9 +146,7 @@ export async function Connection(this: WS.Server, socket: WebSocket, request: In
},
});
socket.readyTimeout = setTimeout(() => {
return socket.close(CLOSECODES.Session_timed_out);
}, 1000 * 30);
socket.readyTimeout = setTimeout(() => socket.close(CLOSECODES.Session_timed_out), 1000 * 30);
} catch (error) {
console.error(error);
return socket.close(CLOSECODES.Unknown_error);
+76 -79
View File
@@ -475,26 +475,24 @@ export async function onIdentify(this: WebSocket, data: Payload) {
}
// Generate merged_members
const merged_members = members.map((x) => {
return [
{
...x,
// filter out @everyone role
roles: x.roles.filter((r) => r.id !== x.guild.id).map((x) => x.id),
const merged_members = members.map((x) => [
{
...x,
// filter out @everyone role
roles: x.roles.filter((r) => r.id !== x.guild.id).map((x) => x.id),
// add back user, which we don't fetch from db
// TODO: For guild profiles, this may need to be changed.
// TODO: The only field required in the user prop is `id`,
// but our types are annoying so I didn't bother.
user: user.toPublicUser(),
// add back user, which we don't fetch from db
// TODO: For guild profiles, this may need to be changed.
// TODO: The only field required in the user prop is `id`,
// but our types are annoying so I didn't bother.
user: user.toPublicUser(),
guild: {
id: x.guild.id,
},
settings: undefined,
guild: {
id: x.guild.id,
},
];
});
settings: undefined,
},
]);
const mergedMembersTime = taskSw.getElapsedAndReset();
// Populated with guilds 'unavailable' currently
@@ -670,62 +668,63 @@ export async function onIdentify(this: WebSocket, data: Payload) {
}, 0);
// const d: ReadyEventData = {
const { result: d, elapsed: buildReadyEventDataTime } = timeFunction<ReadyEventData>(() => {
return {
v: 9,
application: application ? { id: application.id, flags: application.flags } : undefined,
user: user.toPrivateUser(["rights"]),
user_settings: user.settings,
user_settings_proto,
user_settings_proto_json,
guilds: remappedGuilds,
relationships: remappedRelationships,
read_state: {
entries: read_states,
partial: false,
version: 0, // TODO
},
user_guild_settings: {
entries: user_guild_settings_entries,
partial: false,
version: 0, // TODO
},
private_channels: channels,
presences: [], // TODO: Send actual data
session_id: this.session_id,
country_code: this.session?.last_seen_location_info?.country_code ?? user.settings!.locale,
users: Array.from(users),
merged_members: merged_members,
sessions: allSessions,
resume_gateway_url: Config.get().gateway.endpointPublic!,
// lol hack whatever
required_action: Config.get().login.requireVerification && !user.verified ? "REQUIRE_VERIFIED_EMAIL" : undefined,
consents: {
personalization: {
consented: false, // TODO
const { result: d, elapsed: buildReadyEventDataTime } = timeFunction<ReadyEventData>(
() =>
({
v: 9,
application: application ? { id: application.id, flags: application.flags } : undefined,
user: user.toPrivateUser(["rights"]),
user_settings: user.settings,
user_settings_proto,
user_settings_proto_json,
guilds: remappedGuilds,
relationships: remappedRelationships,
read_state: {
entries: read_states,
partial: false,
version: 0, // TODO
},
},
experiments: [],
guild_join_requests: [],
connected_accounts: [],
guild_experiments: [],
geo_ordered_rtc_regions: [],
api_code_version: 1,
friend_suggestion_count: 0,
analytics_token: "",
tutorial: null,
session_type: "normal", // TODO
auth_session_id_hash: this.session!.getDiscordDeviceInfo().id_hash,
notification_settings: {
// ????
flags: 0,
},
game_relationships: [],
} satisfies ReadyEventData;
});
user_guild_settings: {
entries: user_guild_settings_entries,
partial: false,
version: 0, // TODO
},
private_channels: channels,
presences: [], // TODO: Send actual data
session_id: this.session_id,
country_code: this.session?.last_seen_location_info?.country_code ?? user.settings!.locale,
users: Array.from(users),
merged_members: merged_members,
sessions: allSessions,
resume_gateway_url: Config.get().gateway.endpointPublic!,
// lol hack whatever
required_action: Config.get().login.requireVerification && !user.verified ? "REQUIRE_VERIFIED_EMAIL" : undefined,
consents: {
personalization: {
consented: false, // TODO
},
},
experiments: [],
guild_join_requests: [],
connected_accounts: [],
guild_experiments: [],
geo_ordered_rtc_regions: [],
api_code_version: 1,
friend_suggestion_count: 0,
analytics_token: "",
tutorial: null,
session_type: "normal", // TODO
auth_session_id_hash: this.session!.getDiscordDeviceInfo().id_hash,
notification_settings: {
// ????
flags: 0,
},
game_relationships: [],
}) satisfies ReadyEventData,
);
if (this.capabilities.has(Capabilities.FLAGS.AUTH_TOKEN_REFRESH) && tokenData.tokenVersion != CurrentTokenFormatVersion) {
d.auth_token = this.accessToken = (await generateToken(this.user_id))!;
@@ -848,13 +847,11 @@ export async function onIdentify(this: WebSocket, data: Payload) {
}),
);
const readySupplementalGuilds = (guilds.filter((guild) => !guild.unavailable) as Guild[]).map((guild) => {
return {
voice_states: guild.voice_states.map((state) => VoiceState.prototype.toPublicVoiceState.apply(state)),
id: guild.id,
embedded_activities: [],
};
});
const readySupplementalGuilds = (guilds.filter((guild) => !guild.unavailable) as Guild[]).map((guild) => ({
voice_states: guild.voice_states.map((state) => VoiceState.prototype.toPublicVoiceState.apply(state)),
id: guild.id,
embedded_activities: [],
}));
// TODO: ready supplemental
await Send(this, {
+1 -3
View File
@@ -23,7 +23,5 @@ import { WebSocket } from "./WebSocket";
export function setHeartbeat(socket: WebSocket) {
if (socket.heartbeatTimeout) clearTimeout(socket.heartbeatTimeout);
socket.heartbeatTimeout = setTimeout(() => {
return socket.close(CLOSECODES.Session_timed_out);
}, 1000 * 45);
socket.heartbeatTimeout = setTimeout(() => socket.close(CLOSECODES.Session_timed_out), 1000 * 45);
}
+4 -4
View File
@@ -43,12 +43,12 @@ export class DmChannelDTO {
await Promise.all(
channel.recipients
?.filter((r) => !excluded_recipients.includes(r.user_id))
.map((r) => {
return User.findOneOrFail({
.map((r) =>
User.findOneOrFail({
where: { id: r.user_id },
select: PublicUserProjection,
});
}) || [],
}),
) || [],
)
).map((u) => new MinimalPublicUserDTO(u));
return obj;
+1 -3
View File
@@ -36,9 +36,7 @@ export interface ReadyPrivateChannel {
export type GuildOrUnavailable = { id: string; unavailable: boolean } | (Guild & { joined_at?: Date; unavailable: undefined; threads: Channel[] });
const guildIsAvailable = (guild: GuildOrUnavailable): guild is Guild & { joined_at: Date; unavailable: false; threads: Channel[] } => {
return guild.unavailable != true;
};
const guildIsAvailable = (guild: GuildOrUnavailable): guild is Guild & { joined_at: Date; unavailable: false; threads: Channel[] } => guild.unavailable != true;
export interface IReadyGuildDTO {
application_command_counts?: { 1: number; 2: number; 3: number }; // ????????????
+5 -6
View File
@@ -124,16 +124,15 @@ export class Permissions extends BitField {
static channelPermission(overwrites: ChannelPermissionOverwrite[], init?: bigint) {
// TODO: do not deny any permissions if admin
return overwrites.reduce(
(permission, overwrite) => {
(permission, overwrite) =>
// apply disallowed permission
// * permission: current calculated permission (e.g. 010)
// * deny contains all denied permissions (e.g. 011)
// * allow contains all explicitly allowed permisions (e.g. 100)
return (permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow);
// ~ operator inverts deny (e.g. 011 -> 100)
// & operator only allows 1 for both ~deny and permission (e.g. 010 & 100 -> 000)
// | operators adds both together (e.g. 000 + 100 -> 100)
},
(permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow),
// ~ operator inverts deny (e.g. 011 -> 100)
// & operator only allows 1 for both ~deny and permission (e.g. 010 & 100 -> 000)
// | operators adds both together (e.g. 000 + 100 -> 100)
init || BigInt(0),
);
}
+1 -3
View File
@@ -30,9 +30,7 @@ export function getMostRelevantSession(sessions: Session[]) {
unknown: 5,
};
// sort sessions by relevance
sessions = sessions.sort((a, b) => {
return statusMap[a.status] - statusMap[b.status] + ((a.activities?.length ?? 0) - (b.activities?.length ?? 0)) * 2;
});
sessions = sessions.sort((a, b) => statusMap[a.status] - statusMap[b.status] + ((a.activities?.length ?? 0) - (b.activities?.length ?? 0)) * 2);
return sessions[0];
}
+2 -3
View File
@@ -67,8 +67,8 @@ export const checkToken = (
ipAddress?: string;
fingerprint?: string;
},
): Promise<UserTokenData> => {
return new Promise((resolve, reject) => {
): Promise<UserTokenData> =>
new Promise((resolve, reject) => {
token = token.replace("Bot ", ""); // there is no bot distinction in sb
token = token.replace("Bearer ", ""); // allow bearer tokens
@@ -155,7 +155,6 @@ export const checkToken = (
});
} else return void rejectAndLog(reject, 400, "Unsupported token algorithm: " + dec.header.alg);
});
};
export async function generateToken(id: string, isAdminSession: boolean = false): Promise<string | undefined> {
const iat = Math.floor(Date.now() / 1000);
+1 -3
View File
@@ -57,9 +57,7 @@ export async function Connection(this: WS.Server, socket: WebRtcWebSocket, reque
setHeartbeat(socket);
socket.readyTimeout = setTimeout(() => {
return socket.close(CLOSECODES.Session_timed_out);
}, 1000 * 30);
socket.readyTimeout = setTimeout(() => socket.close(CLOSECODES.Session_timed_out), 1000 * 30);
await Send(socket, {
op: VoiceOPCodes.HELLO,