Clean up array extensions
This commit is contained in:
parent
8bd0d5c06b
commit
a25393e806
@ -118,7 +118,7 @@
|
||||
"@spacebar/gateway": "dist/gateway",
|
||||
"@spacebar/util": "dist/util",
|
||||
"@spacebar/webrtc": "dist/webrtc",
|
||||
"lambert-server": "dist/util/util/lambert-server"
|
||||
"lambert-server": "dist/util/util/lambert-server"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@sendgrid/mail": "^8.1.6",
|
||||
|
||||
@ -51,7 +51,7 @@ router.put(
|
||||
const recipients = [
|
||||
...(channel.recipients?.map((r) => r.user_id) || []),
|
||||
user_id,
|
||||
].unique();
|
||||
].distinct();
|
||||
|
||||
const new_channel = await Channel.createDMChannel(
|
||||
recipients,
|
||||
|
||||
@ -35,7 +35,7 @@ router.post(
|
||||
async (req: Request, res: Response) => {
|
||||
const { channel_id } = req.params;
|
||||
const user_id = req.user_id;
|
||||
const timestamp = Date.nowSeconds();
|
||||
const timestamp = Math.floor(Date.now() / 1000);
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: channel_id },
|
||||
});
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import { Router, Request, Response } from "express";
|
||||
import { DiscordApiErrors, Member, partition } from "@spacebar/util";
|
||||
import { DiscordApiErrors, Member } from "@spacebar/util";
|
||||
import { route } from "@spacebar/api";
|
||||
|
||||
const router = Router({ mergeParams: true });
|
||||
@ -38,8 +38,7 @@ router.patch(
|
||||
relations: ["roles"],
|
||||
});
|
||||
|
||||
const [add, remove] = partition(
|
||||
members,
|
||||
const [add, remove] = members.partition(
|
||||
(member) =>
|
||||
member_ids.includes(member.id) &&
|
||||
!member.roles.map((role) => role.id).includes(role_id),
|
||||
|
||||
@ -20,7 +20,7 @@ import { Config } from "@spacebar/util";
|
||||
|
||||
const reNUMBER = /[0-9]/g;
|
||||
const reUPPERCASELETTER = /[A-Z]/g;
|
||||
const reSYMBOLS = /[A-Z,a-z,0-9]/g;
|
||||
const reSYMBOLS = /[A-Za-z0-9]/g;
|
||||
|
||||
// const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored in db
|
||||
/*
|
||||
@ -45,12 +45,12 @@ export function checkPassword(password: string): number {
|
||||
}
|
||||
|
||||
// checks for amount of Numbers
|
||||
if (password.count(reNUMBER) >= minNumbers - 1) {
|
||||
if (password.match(reNUMBER)?.length ?? 0 >= minNumbers - 1) {
|
||||
strength += 0.05;
|
||||
}
|
||||
|
||||
// checks for amount of Uppercase Letters
|
||||
if (password.count(reUPPERCASELETTER) >= minUpperCase - 1) {
|
||||
if (password.match(reUPPERCASELETTER)?.length ?? 0 >= minUpperCase - 1) {
|
||||
strength += 0.05;
|
||||
}
|
||||
|
||||
@ -61,8 +61,8 @@ export function checkPassword(password: string): number {
|
||||
|
||||
// checks if password only consists of numbers or only consists of chars
|
||||
if (
|
||||
password.length == password.count(reNUMBER) ||
|
||||
password.length === password.count(reUPPERCASELETTER)
|
||||
password.length == password.match(reNUMBER)?.length ||
|
||||
password.length === password.match(reUPPERCASELETTER)?.length
|
||||
) {
|
||||
strength = 0;
|
||||
}
|
||||
|
||||
@ -26,7 +26,6 @@ import {
|
||||
LazyRequestSchema,
|
||||
User,
|
||||
Presence,
|
||||
partition,
|
||||
Channel,
|
||||
Permissions,
|
||||
} from "@spacebar/util";
|
||||
@ -108,7 +107,7 @@ async function getMembers(guild_id: string, range: [number, number]) {
|
||||
const member_roles = members
|
||||
.map((m) => m.roles)
|
||||
.flat()
|
||||
.unique((r: Role) => r.id);
|
||||
.distinctBy((r: Role) => r.id);
|
||||
member_roles.push(
|
||||
member_roles.splice(
|
||||
member_roles.findIndex((x) => x.id === x.guild_id),
|
||||
@ -119,8 +118,7 @@ async function getMembers(guild_id: string, range: [number, number]) {
|
||||
const offlineItems = [];
|
||||
|
||||
for (const role of member_roles) {
|
||||
const [role_members, other_members] = partition(
|
||||
members,
|
||||
const [role_members, other_members] = members.partition(
|
||||
(m: Member) => !!m.roles.find((r) => r.id === role.id),
|
||||
);
|
||||
const group = {
|
||||
@ -284,9 +282,9 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
|
||||
channel.permission_overwrites.forEach((overwrite) => {
|
||||
const { id, allow, deny } = overwrite;
|
||||
|
||||
if (allow.toBigInt() & Permissions.FLAGS.VIEW_CHANNEL)
|
||||
if (BigInt(allow) & Permissions.FLAGS.VIEW_CHANNEL)
|
||||
perms.push(`allow:${id}`);
|
||||
else if (deny.toBigInt() & Permissions.FLAGS.VIEW_CHANNEL)
|
||||
else if (BigInt(deny) & Permissions.FLAGS.VIEW_CHANNEL)
|
||||
perms.push(`deny:${id}`);
|
||||
});
|
||||
|
||||
@ -307,7 +305,7 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
|
||||
const groups = ops
|
||||
.map((x) => x.groups)
|
||||
.flat()
|
||||
.unique();
|
||||
.distinct();
|
||||
|
||||
await Send(this, {
|
||||
op: OPCODES.Dispatch,
|
||||
|
||||
@ -27,7 +27,7 @@ import {
|
||||
} from "typeorm";
|
||||
import { DmChannelDTO } from "../dtos";
|
||||
import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
|
||||
import { InvisibleCharacters, Snowflake, containsAll, emitEvent, getPermission, trimSpecial, Permissions, BitField } from "../util";
|
||||
import { InvisibleCharacters, Snowflake, emitEvent, getPermission, trimSpecial, Permissions, BitField } from "../util";
|
||||
import { BaseClass } from "./BaseClass";
|
||||
import { Guild } from "./Guild";
|
||||
import { Invite } from "./Invite";
|
||||
@ -328,7 +328,7 @@ export class Channel extends BaseClass {
|
||||
creator_user_id: string,
|
||||
name?: string,
|
||||
) {
|
||||
recipients = recipients.unique().filter((x) => x !== creator_user_id);
|
||||
recipients = recipients.distinct().filter((x) => x !== creator_user_id);
|
||||
// TODO: check config for max number of recipients
|
||||
/** if you want to disallow note to self channels, uncomment the conditional below
|
||||
|
||||
@ -354,7 +354,7 @@ export class Channel extends BaseClass {
|
||||
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 (re.containsAll(channelRecipients)) {
|
||||
if (channel == null) {
|
||||
channel = ur.channel;
|
||||
await ur.assign({ closed: false }).save();
|
||||
|
||||
@ -56,9 +56,9 @@ export function enableAutoUpdate(opts: {
|
||||
const latestVersion = await getLatestVersion(opts.packageJsonLink);
|
||||
if (currentVersion !== latestVersion) {
|
||||
rl.question(
|
||||
`[Auto Update] Current version (${currentVersion}) is out of date, would you like to update? (yes/no)`,
|
||||
`[Auto Update] Current version (${currentVersion}) is out of date, would you like to update? (Y/n)`,
|
||||
(answer) => {
|
||||
if (answer.toBoolean()) {
|
||||
if (answer === "" || answer.toLowerCase() === "y") {
|
||||
console.log(`[Auto update] updating ...`);
|
||||
download(opts.downloadUrl, opts.path);
|
||||
} else {
|
||||
|
||||
@ -23,7 +23,7 @@ export function FieldErrors(
|
||||
return new FieldError(
|
||||
50035,
|
||||
"Invalid Form Body",
|
||||
fields.map(({ message, code }) => ({
|
||||
(fields as Object).map(({ message, code }) => ({
|
||||
_errors: [
|
||||
{
|
||||
message,
|
||||
|
||||
@ -23,57 +23,102 @@ declare global {
|
||||
single(filter: (elem: T) => boolean): T | null;
|
||||
forEachAsync(callback: (elem: T, index: number, array: T[]) => Promise<void>): Promise<void>;
|
||||
remove(item: T): void;
|
||||
first(): T | undefined;
|
||||
last(): T | undefined;
|
||||
distinct(): T[];
|
||||
distinctBy<K>(key: (elem: T) => K): T[];
|
||||
}
|
||||
}
|
||||
|
||||
export function containsAll<T>(arr: T[], target: T[]) {
|
||||
export function arrayContainsAll<T>(arr: T[], target: T[]) {
|
||||
return target.every((v) => arr.includes(v));
|
||||
}
|
||||
|
||||
/* https://stackoverflow.com/a/50636286 */
|
||||
export function partition<T>(array: T[], filter: (elem: T) => boolean): [T[], T[]] {
|
||||
export function arrayPartition<T>(array: T[], filter: (elem: T) => boolean): [T[], T[]] {
|
||||
const pass: T[] = [],
|
||||
fail: T[] = [];
|
||||
array.forEach((e) => (filter(e) ? pass : fail).push(e));
|
||||
return [pass, fail];
|
||||
}
|
||||
|
||||
export function single<T>(array: T[], filter: (elem: T) => boolean): T | null {
|
||||
export function arraySingle<T>(array: T[], filter: (elem: T) => boolean): T | null {
|
||||
const results = array.filter(filter);
|
||||
if (results.length > 1) throw new Error("Array contains more than one matching element");
|
||||
if (results.length === 0) return null;
|
||||
return results[0];
|
||||
}
|
||||
|
||||
export async function forEachAsync<T>(array: T[], callback: (elem: T, index: number, array: T[]) => Promise<void>): Promise<void> {
|
||||
export async function arrayForEachAsync<T>(array: T[], callback: (elem: T, index: number, array: T[]) => Promise<void>): Promise<void> {
|
||||
await Promise.all(array.map(callback));
|
||||
}
|
||||
|
||||
export function remove<T>(this: T[], item: T): void {
|
||||
export function arrayRemove<T>(this: T[], item: T): void {
|
||||
const index = this.indexOf(item);
|
||||
if (index > -1) {
|
||||
this.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
export function arrayFirst<T>(this: T[]): T | undefined {
|
||||
return this[0];
|
||||
}
|
||||
|
||||
export function arrayLast<T>(this: T[]): T | undefined {
|
||||
return this[this.length - 1];
|
||||
}
|
||||
|
||||
export function arrayDistinct<T>(this: T[]): T[] {
|
||||
return Array.from(new Set(this));
|
||||
}
|
||||
|
||||
export function arrayDistinctBy<T, K>(this: T[], key: (elem: T) => K): T[] {
|
||||
const seen = new Set<K>();
|
||||
return this.filter((item) => {
|
||||
const k = key(item);
|
||||
if (seen.has(k)) {
|
||||
return false;
|
||||
} else {
|
||||
seen.add(k);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// register extensions
|
||||
if (!Array.prototype.containsAll)
|
||||
Array.prototype.containsAll = function <T>(this: T[], target: T[]) {
|
||||
return containsAll(this, target);
|
||||
return arrayContainsAll(this, target);
|
||||
};
|
||||
if (!Array.prototype.partition)
|
||||
Array.prototype.partition = function <T>(this: T[], filter: (elem: T) => boolean) {
|
||||
return partition(this, filter);
|
||||
return arrayPartition(this, filter);
|
||||
};
|
||||
if (!Array.prototype.single)
|
||||
Array.prototype.single = function <T>(this: T[], filter: (elem: T) => boolean) {
|
||||
return single(this, filter);
|
||||
return arraySingle(this, filter);
|
||||
};
|
||||
if (!Array.prototype.forEachAsync)
|
||||
Array.prototype.forEachAsync = function <T>(this: T[], callback: (elem: T, index: number, array: T[]) => Promise<void>) {
|
||||
return forEachAsync(this, callback);
|
||||
return arrayForEachAsync(this, callback);
|
||||
};
|
||||
if (!Array.prototype.remove)
|
||||
Array.prototype.remove = function <T>(this: T[], item: T) {
|
||||
return remove.call(this, item);
|
||||
return arrayRemove.call(this, item);
|
||||
};
|
||||
if (!Array.prototype.first)
|
||||
Array.prototype.first = function <T>(this: T[]) {
|
||||
return arrayFirst.call(this);
|
||||
};
|
||||
if (!Array.prototype.last)
|
||||
Array.prototype.last = function <T>(this: T[]) {
|
||||
return arrayLast.call(this);
|
||||
};
|
||||
if (!Array.prototype.distinct)
|
||||
Array.prototype.distinct = function <T>(this: T[]) {
|
||||
return arrayDistinct.call(this);
|
||||
};
|
||||
if (!Array.prototype.distinctBy)
|
||||
Array.prototype.distinctBy = function <T, K>(this: T[], key: (elem: T) => K) {
|
||||
return arrayDistinctBy.call(this, key as ((elem: unknown) => unknown));
|
||||
};
|
||||
Reference in New Issue
Block a user