Move to some etension methods
This commit is contained in:
parent
0d907af72f
commit
bd9a75f919
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
// process.env.MONGOMS_DEBUG = "true";
|
// process.env.MONGOMS_DEBUG = "true";
|
||||||
import moduleAlias from "module-alias";
|
import moduleAlias from "module-alias";
|
||||||
|
|
||||||
moduleAlias(__dirname + "../../../package.json");
|
moduleAlias(__dirname + "../../../package.json");
|
||||||
|
|
||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
|
|||||||
@ -566,7 +566,7 @@ export class Channel extends BaseClass {
|
|||||||
let userPerms = new Permissions(new BitField(0).add(roles.map(r => r.permissions)));
|
let userPerms = new Permissions(new BitField(0).add(roles.map(r => r.permissions)));
|
||||||
|
|
||||||
// TODO: do we want to have an instance-wide opt out of this behavior? It would just be an extra if statement here
|
// TODO: do we want to have an instance-wide opt out of this behavior? It would just be an extra if statement here
|
||||||
if (userPerms.has(Permissions.FLAGS.ADMINISTRATOR)) return true;
|
if (userPerms.has(Permissions.FLAGS.ADMINISTRATOR)) return userPerms;
|
||||||
|
|
||||||
// apply channel overrides
|
// apply channel overrides
|
||||||
if (this.permission_overwrites) {
|
if (this.permission_overwrites) {
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
|
|
||||||
Copyright (C) 2023 Spacebar and Spacebar 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: remove this function.
|
|
||||||
|
|
||||||
export function containsAll(arr: unknown[], target: unknown[]) {
|
|
||||||
return target.every((v) => arr.includes(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://stackoverflow.com/a/50636286 */
|
|
||||||
export 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];
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* Normalize a URL by:
|
|
||||||
* - Removing trailing slashes (except root path)
|
|
||||||
* - Sorting query params alphabetically
|
|
||||||
* - Removing empty query strings
|
|
||||||
* - Removing fragments
|
|
||||||
*/
|
|
||||||
export function normalizeUrl(input: string): string {
|
|
||||||
try {
|
|
||||||
const u = new URL(input);
|
|
||||||
// Remove fragment
|
|
||||||
u.hash = "";
|
|
||||||
// Normalize pathname - remove trailing slash except for root "/"
|
|
||||||
if (u.pathname !== "/" && u.pathname.endsWith("/")) {
|
|
||||||
u.pathname = u.pathname.slice(0, -1);
|
|
||||||
}
|
|
||||||
// Normalize query params: sort by key
|
|
||||||
if (u.search) {
|
|
||||||
const params = Array.from(u.searchParams.entries());
|
|
||||||
params.sort(([a], [b]) => a.localeCompare(b));
|
|
||||||
u.search = params.length
|
|
||||||
? "?" + params.map(([k, v]) => `${k}=${v}`).join("&")
|
|
||||||
: "";
|
|
||||||
} else {
|
|
||||||
// Ensure no empty search string
|
|
||||||
u.search = "";
|
|
||||||
}
|
|
||||||
return u.toString();
|
|
||||||
} catch (e) {
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
58
src/util/util/extensions/Array.ts
Normal file
58
src/util/util/extensions/Array.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
|
||||||
|
Copyright (C) 2025 Spacebar and Spacebar 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Array<T> {
|
||||||
|
containsAll(target: T[]): boolean;
|
||||||
|
partition(filter: (elem: T) => boolean): [T[], T[]];
|
||||||
|
single(filter: (elem: T) => boolean): T | null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function containsAll<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[]] {
|
||||||
|
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 {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
// register extensions
|
||||||
|
if (!Array.prototype.containsAll)
|
||||||
|
Array.prototype.containsAll = function <T>(this: T[], target: T[]) {
|
||||||
|
return containsAll(this, target);
|
||||||
|
};
|
||||||
|
if (!Array.prototype.partition)
|
||||||
|
Array.prototype.partition = function <T>(this: T[], filter: (elem: T) => boolean) {
|
||||||
|
return partition(this, filter);
|
||||||
|
};
|
||||||
|
if (!Array.prototype.single)
|
||||||
|
Array.prototype.single = function <T>(this: T[], filter: (elem: T) => boolean) {
|
||||||
|
return single(this, filter);
|
||||||
|
};
|
||||||
0
src/util/util/extensions/Url.d.ts
vendored
Normal file
0
src/util/util/extensions/Url.d.ts
vendored
Normal file
60
src/util/util/extensions/Url.ts
Normal file
60
src/util/util/extensions/Url.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
|
||||||
|
Copyright (C) 2025 Spacebar and Spacebar 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module "url" {
|
||||||
|
interface URL {
|
||||||
|
normalize(): string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a URL by:
|
||||||
|
* - Removing trailing slashes (except root path)
|
||||||
|
* - Sorting query params alphabetically
|
||||||
|
* - Removing empty query strings
|
||||||
|
* - Removing fragments
|
||||||
|
*/
|
||||||
|
export function normalizeUrl(input: string): string {
|
||||||
|
try {
|
||||||
|
const u = new URL(input);
|
||||||
|
// Remove fragment
|
||||||
|
u.hash = "";
|
||||||
|
// Normalize pathname - remove trailing slash except for root "/"
|
||||||
|
if (u.pathname !== "/" && u.pathname.endsWith("/")) {
|
||||||
|
u.pathname = u.pathname.slice(0, -1);
|
||||||
|
}
|
||||||
|
// Normalize query params: sort by key
|
||||||
|
if (u.search) {
|
||||||
|
const params = Array.from(u.searchParams.entries());
|
||||||
|
params.sort(([a], [b]) => a.localeCompare(b));
|
||||||
|
u.search = params.length ? "?" + params.map(([k, v]) => `${k}=${v}`).join("&") : "";
|
||||||
|
} else {
|
||||||
|
// Ensure no empty search string
|
||||||
|
u.search = "";
|
||||||
|
}
|
||||||
|
return u.toString();
|
||||||
|
} catch (e) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// register extensions
|
||||||
|
if (!URL.prototype.normalize)
|
||||||
|
URL.prototype.normalize = function () {
|
||||||
|
return normalizeUrl(this.toString());
|
||||||
|
};
|
||||||
2
src/util/util/extensions/index.ts
Normal file
2
src/util/util/extensions/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from "./Array";
|
||||||
|
export * from "./Url";
|
||||||
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from "./ApiError";
|
export * from "./ApiError";
|
||||||
export * from "./Array";
|
export * from "./extensions/Array";
|
||||||
export * from "./BitField";
|
export * from "./BitField";
|
||||||
//export * from "./Categories";
|
//export * from "./Categories";
|
||||||
export * from "./cdn";
|
export * from "./cdn";
|
||||||
@ -44,8 +44,8 @@ export * from "./String";
|
|||||||
export * from "./Token";
|
export * from "./Token";
|
||||||
export * from "./TraverseDirectory";
|
export * from "./TraverseDirectory";
|
||||||
export * from "./WebAuthn";
|
export * from "./WebAuthn";
|
||||||
export * from "./Url";
|
|
||||||
export * from "./Gifs";
|
export * from "./Gifs";
|
||||||
export * from "./Application";
|
export * from "./Application";
|
||||||
export * from "./NameValidation";
|
export * from "./NameValidation";
|
||||||
export * from "./HelperTypes";
|
export * from "./HelperTypes";
|
||||||
|
export * from "./extensions";
|
||||||
|
|||||||
@ -55,8 +55,8 @@
|
|||||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||||
|
|
||||||
/* Emit */
|
/* Emit */
|
||||||
"declaration": false /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
|
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
|
||||||
"declarationMap": false /* Create sourcemaps for d.ts files. */,
|
"declarationMap": true /* Create sourcemaps for d.ts files. */,
|
||||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
"sourceMap": true /* Create source map files for emitted JavaScript files. */,
|
"sourceMap": true /* Create source map files for emitted JavaScript files. */,
|
||||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||||
|
|||||||
Reference in New Issue
Block a user