diff --git a/api/assets/schemas.json b/api/assets/schemas.json
index 03a2db07..5d78c602 100644
--- a/api/assets/schemas.json
+++ b/api/assets/schemas.json
@@ -2887,6 +2887,329 @@
},
"$schema": "http://json-schema.org/draft-07/schema#"
},
+ "EmojiListResponse": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "animated": {
+ "type": "boolean"
+ },
+ "available": {
+ "type": "boolean"
+ },
+ "id": {
+ "type": "string"
+ },
+ "managed": {
+ "type": "boolean"
+ },
+ "name": {
+ "type": "string"
+ },
+ "require_colons": {
+ "type": "boolean"
+ },
+ "guild_id": {
+ "type": "string"
+ },
+ "roles": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "animated",
+ "available",
+ "id",
+ "managed",
+ "name",
+ "require_colons"
+ ]
+ },
+ "definitions": {
+ "ChannelPermissionOverwriteType": {
+ "enum": [
+ 0,
+ 1
+ ],
+ "type": "number"
+ },
+ "Embed": {
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "type": {
+ "enum": [
+ "article",
+ "gifv",
+ "image",
+ "link",
+ "rich",
+ "video"
+ ],
+ "type": "string"
+ },
+ "description": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ },
+ "timestamp": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "color": {
+ "type": "integer"
+ },
+ "footer": {
+ "type": "object",
+ "properties": {
+ "text": {
+ "type": "string"
+ },
+ "icon_url": {
+ "type": "string"
+ },
+ "proxy_icon_url": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "text"
+ ]
+ },
+ "image": {
+ "$ref": "#/definitions/EmbedImage"
+ },
+ "thumbnail": {
+ "$ref": "#/definitions/EmbedImage"
+ },
+ "video": {
+ "$ref": "#/definitions/EmbedImage"
+ },
+ "provider": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ }
+ },
+ "author": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ },
+ "icon_url": {
+ "type": "string"
+ },
+ "proxy_icon_url": {
+ "type": "string"
+ }
+ }
+ },
+ "fields": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ },
+ "inline": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "name",
+ "value"
+ ]
+ }
+ }
+ }
+ },
+ "EmbedImage": {
+ "type": "object",
+ "properties": {
+ "url": {
+ "type": "string"
+ },
+ "proxy_url": {
+ "type": "string"
+ },
+ "height": {
+ "type": "integer"
+ },
+ "width": {
+ "type": "integer"
+ }
+ }
+ },
+ "ChannelModifySchema": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "maxLength": 100,
+ "type": "string"
+ },
+ "type": {
+ "enum": [
+ 0,
+ 1,
+ 10,
+ 11,
+ 12,
+ 13,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6
+ ],
+ "type": "number"
+ },
+ "topic": {
+ "type": "string"
+ },
+ "icon": {
+ "type": [
+ "null",
+ "string"
+ ]
+ },
+ "bitrate": {
+ "type": "integer"
+ },
+ "user_limit": {
+ "type": "integer"
+ },
+ "rate_limit_per_user": {
+ "type": "integer"
+ },
+ "position": {
+ "type": "integer"
+ },
+ "permission_overwrites": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "type": {
+ "$ref": "#/definitions/ChannelPermissionOverwriteType"
+ },
+ "allow": {
+ "type": "string"
+ },
+ "deny": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "allow",
+ "deny",
+ "id",
+ "type"
+ ]
+ }
+ },
+ "parent_id": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "nsfw": {
+ "type": "boolean"
+ },
+ "rtc_region": {
+ "type": "string"
+ },
+ "default_auto_archive_duration": {
+ "type": "integer"
+ }
+ }
+ },
+ "UserPublic": {
+ "type": "object",
+ "properties": {
+ "username": {
+ "type": "string"
+ },
+ "discriminator": {
+ "type": "string"
+ },
+ "id": {
+ "type": "string"
+ },
+ "public_flags": {
+ "type": "integer"
+ },
+ "avatar": {
+ "type": "string"
+ },
+ "accent_color": {
+ "type": "integer"
+ },
+ "banner": {
+ "type": "string"
+ },
+ "bio": {
+ "type": "string"
+ },
+ "bot": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "bio",
+ "bot",
+ "discriminator",
+ "id",
+ "public_flags",
+ "username"
+ ]
+ },
+ "PublicConnectedAccount": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "verifie": {
+ "type": "boolean"
+ }
+ },
+ "required": [
+ "name",
+ "type",
+ "verifie"
+ ]
+ }
+ },
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
"GuildCreateSchema": {
"type": "object",
"properties": {
diff --git a/api/package.json b/api/package.json
index 8fc55e94..4fee791c 100644
--- a/api/package.json
+++ b/api/package.json
@@ -6,6 +6,7 @@
"types": "dist/Server.d.ts",
"scripts": {
"test:only": "jest --coverage --verbose --forceExit ./tests",
+ "test:routes": "jest --coverage --verbose --forceExit ./routes.test.ts",
"test": "npm run build && npm run test:only",
"test:watch": "jest --watch",
"start": "npm run build && node dist/start",
diff --git a/api/src/Server.ts b/api/src/Server.ts
index 4a226d12..a16a61f8 100644
--- a/api/src/Server.ts
+++ b/api/src/Server.ts
@@ -1,4 +1,4 @@
-import { OptionsJson } from 'body-parser';
+import { OptionsJson } from "body-parser";
import "missing-native-js-functions";
import { Connection } from "mongoose";
import { Server, ServerOptions } from "lambert-server";
@@ -38,7 +38,6 @@ export class FosscordServer extends Server {
await Config.init();
await initEvent();
-
/*
DOCUMENTATION: uses LOG_REQUESTS environment variable
@@ -51,14 +50,16 @@ export class FosscordServer extends Server {
*/
let logRequests = process.env["LOG_REQUESTS"] != undefined;
- if(logRequests) {
- this.app.use(morgan("combined", {
- skip: (req, res) => {
- var skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false);
- if(process.env["LOG_REQUESTS"]?.charAt(0) == '-') skip = !skip;
- return skip;
- }
- }));
+ if (logRequests) {
+ this.app.use(
+ morgan("combined", {
+ skip: (req, res) => {
+ var skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false);
+ if (process.env["LOG_REQUESTS"]?.charAt(0) == "-") skip = !skip;
+ return skip;
+ }
+ })
+ );
}
this.app.use(CORS);
@@ -90,8 +91,10 @@ export class FosscordServer extends Server {
this.app.use(ErrorHandler);
TestClient(this.app);
- if(logRequests){
- console.log("Warning: Request logging is enabled! This will spam your console!\nTo disable this, unset the 'LOG_REQUESTS' environment variable!");
+ if (logRequests) {
+ console.log(
+ "Warning: Request logging is enabled! This will spam your console!\nTo disable this, unset the 'LOG_REQUESTS' environment variable!"
+ );
}
return super.start();
}
diff --git a/api/tests/routes.test.ts b/api/tests/routes.test.ts
index fcaa3124..ed391dfb 100644
--- a/api/tests/routes.test.ts
+++ b/api/tests/routes.test.ts
@@ -7,7 +7,7 @@ import fs from "fs";
import Ajv from "ajv";
import addFormats from "ajv-formats";
import fetch from "node-fetch";
-import { Event, User, events } from "@fosscord/util";
+import { Event, User, events, Guild, Channel } from "@fosscord/util";
const SchemaPath = join(__dirname, "..", "assets", "schemas.json");
const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" }));
@@ -25,11 +25,36 @@ addFormats(ajv);
var token: string;
var user: User;
+var guild: Guild;
+var channel: Channel;
+
+const request = async (path: string, opts: any = {}): Promise<any> => {
+ const response = await fetch(`http://localhost:3001/api${path}`, {
+ ...opts,
+ method: opts.method || opts.body ? "POST" : "GET",
+ body: opts.body && JSON.stringify(opts.body),
+ headers: {
+ authorization: token,
+ ...(opts.body ? { "content-type": "application/json" } : {}),
+ ...(opts.header || {})
+ }
+ });
+ if (response.status === 204) return;
+
+ var data = await response.text();
+ try {
+ data = JSON.stringify(data);
+ if (response.status >= 400) throw data;
+ return data;
+ } catch (error) {
+ throw data;
+ }
+};
+
beforeAll(async (done) => {
try {
- const response = await fetch("http://localhost:3001/api/auth/register", {
- method: "POST",
- body: JSON.stringify({
+ const response = await request("/auth/register", {
+ body: {
fingerprint: "805826570869932034.wR8vi8lGlFBJerErO9LG5NViJFw",
email: "test@example.com",
username: "tester",
@@ -39,18 +64,13 @@ beforeAll(async (done) => {
date_of_birth: "2000-01-01",
gift_code_sku_id: null,
captcha_key: null
- }),
- headers: {
- "content-type": "application/json"
}
});
- const json = await response.json();
- token = json.token;
- user = await (
- await fetch(`http://localhost:3001/api/users/@me`, {
- headers: { authorization: token }
- })
- ).json();
+ token = response.token;
+ user = await request(`/users/@me`);
+ const { id: guild_id } = await request("/guilds", { body: { name: "test server" } });
+ guild = await request(`/guilds/${guild_id}`);
+ channel = (await request(`/guilds/${guild_id}/channels`))[0];
done();
} catch (error) {
@@ -75,7 +95,8 @@ describe("Automatic unit tests with route description middleware", () => {
console.log(`${(route as any).file}\nrouter.${method} is missing the test property`);
return done();
}
- const urlPath = path.replace(":id", user.id) || route.test?.path;
+ const urlPath =
+ path.replace(":id", user.id).replace(":guild_id", guild.id).replace(":channel_id", channel.id) || route.test?.path;
var validate: any;
if (route.test.body) {
validate = ajv.getSchema(route.test.body);
diff --git a/bundle/.gitignore b/bundle/.gitignore
index 7d2cb508..cf073d9c 100644
--- a/bundle/.gitignore
+++ b/bundle/.gitignore
@@ -1 +1,2 @@
-files/
\ No newline at end of file
+files/
+.env
\ No newline at end of file
diff --git a/bundle/package-lock.json b/bundle/package-lock.json
index aaa0c1ee..090935f4 100644
--- a/bundle/package-lock.json
+++ b/bundle/package-lock.json
@@ -15,6 +15,7 @@
"@fosscord/gateway": "file:../gateway",
"@fosscord/util": "file:../util",
"async-exit-hook": "^2.0.1",
+ "dotenv": "^10.0.0",
"express": "^4.17.1",
"missing-native-js-functions": "^1.2.15",
"node-os-utils": "^1.3.5",
@@ -195,6 +196,9 @@
"ts-node-dev": "^1.1.6",
"ts-patch": "^1.4.4",
"typescript": "^4.2.3"
+ },
+ "optionalDependencies": {
+ "@yukikaze-bot/erlpack": "^1.0.1"
}
},
"../util": {
@@ -858,6 +862,14 @@
"node": ">=0.3.1"
}
},
+ "node_modules/dotenv": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -1810,6 +1822,7 @@
"@types/node-fetch": "^2.5.12",
"@types/uuid": "^8.3.0",
"@types/ws": "^7.4.0",
+ "@yukikaze-bot/erlpack": "^1.0.1",
"@zerollup/ts-transform-paths": "^1.7.18",
"ajv": "^8.5.0",
"amqplib": "^0.8.0",
@@ -2336,6 +2349,11 @@
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
},
+ "dotenv": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
+ },
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
diff --git a/bundle/package.json b/bundle/package.json
index fa6fe669..f68ff0bd 100644
--- a/bundle/package.json
+++ b/bundle/package.json
@@ -54,6 +54,7 @@
"@fosscord/gateway": "file:../gateway",
"@fosscord/util": "file:../util",
"async-exit-hook": "^2.0.1",
+ "dotenv": "^10.0.0",
"express": "^4.17.1",
"missing-native-js-functions": "^1.2.15",
"node-os-utils": "^1.3.5",
diff --git a/bundle/src/start.ts b/bundle/src/start.ts
index f68a65bf..be67a122 100644
--- a/bundle/src/start.ts
+++ b/bundle/src/start.ts
@@ -2,6 +2,8 @@
import cluster from "cluster";
import os from "os";
import { initStats } from "./stats";
+import { config } from "dotenv";
+config();
// TODO: add tcp socket event transmission
const cores = 1 || Number(process.env.threads) || os.cpus().length;
diff --git a/bundle/src/stats.ts b/bundle/src/stats.ts
index e6941db2..d5ceeff7 100644
--- a/bundle/src/stats.ts
+++ b/bundle/src/stats.ts
@@ -5,7 +5,6 @@ export function initStats() {
console.log(`[Path] running in ${__dirname}`);
console.log(`[CPU] ${osu.cpu.model()} Cores x${osu.cpu.count()}`);
console.log(`[System] ${os.platform()} ${os.arch()}`);
- console.log(`[Database] started`);
console.log(`[Process] running with pid: ${process.pid}`);
setInterval(async () => {
diff --git a/dashboard/README.md b/dashboard/README.md
index c94ae96c..df1157a1 100644
--- a/dashboard/README.md
+++ b/dashboard/README.md
@@ -1,8 +1,12 @@
# Fosscord-dashboard
+
A admin dashboard for fosscord-server
## (planned) Features
-- [ ] Overview usage (registered users, concurrent connections, voice usage, reports)
-- [ ] Reports
-- [ ] Member managment (edit (disable, delete, premium, username, discriminator))
-- [ ] Configuration ([Config.ts](https://github.com/fosscord/fosscord-server-util/blob/master/src/util/Config.ts))
+
+- [ ] Overview usage (registered users, concurrent connections, voice usage, reports)
+- [ ] Reports
+- [ ] Member managment (edit (disable, delete, premium, username, discriminator))
+- [ ] Configuration ([Config.ts](https://github.com/fosscord/fosscord-server-util/blob/master/src/util/Config.ts))
+
+port = 3005
diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts
index ab7c70c5..369a403c 100644
--- a/util/src/util/Database.ts
+++ b/util/src/util/Database.ts
@@ -1,6 +1,6 @@
import path from "path";
import "reflect-metadata";
-import { Connection, createConnection, ValueTransformer } from "typeorm";
+import { Connection, createConnection } from "typeorm";
import * as Models from "../entities";
// UUID extension option is only supported with postgres
@@ -8,18 +8,20 @@ import * as Models from "../entities";
var promise: Promise<any>;
var dbConnection: Connection | undefined;
+let dbConnectionString = process.env.DATABASE || path.join(process.cwd(), "database.db");
export function initDatabase() {
if (promise) return promise; // prevent initalizing multiple times
- console.log("[Database] connecting ...");
+ const type = dbConnectionString.includes(":") ? dbConnectionString.split(":")[0]?.replace("+srv", "") : "sqlite";
+ const isSqlite = type.includes("sqlite");
+
+ console.log(`[Database] connecting to ${type} db`);
// @ts-ignore
promise = createConnection({
- type: "sqlite",
- database: path.join(process.cwd(), "database.db"),
- // type: "postgres",
- // url: "postgres://fosscord:wb94SmuURM2Syv&@localhost/fosscord",
- //
+ type,
+ url: isSqlite ? undefined : dbConnectionString,
+ database: isSqlite ? dbConnectionString : undefined,
entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"),
synchronize: true,
logging: false,
|