mirror of
https://github.com/spacebarchat/server.git
synced 2026-05-24 08:05:29 +00:00
Merge branch 'master' of https://github.com/fosscord/fosscord-server
This commit is contained in:
Vendored
+7
-7
@@ -1,8 +1,8 @@
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
user_id: any;
|
||||
token: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Express {
|
||||
interface Request {
|
||||
user_id: any;
|
||||
token: any;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ import express, { Request, Response, Application } from "express";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import fetch, { Response as FetchResponse } from "node-fetch";
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import { Config } from "@fosscord/util";
|
||||
|
||||
export default function TestClient(app: Application) {
|
||||
const agent = new ProxyAgent();
|
||||
const assetCache = new Map<string, { response: FetchResponse; buffer: Buffer }>();
|
||||
const indexHTML = fs.readFileSync(path.join(__dirname, "..", "..", "client_test", "index.html"), { encoding: "utf8" });
|
||||
|
||||
@@ -31,6 +33,7 @@ export default function TestClient(app: Application) {
|
||||
const cache = assetCache.get(req.params.file);
|
||||
if (!cache) {
|
||||
response = await fetch(`https://discord.com/assets/${req.params.file}`, {
|
||||
agent,
|
||||
// @ts-ignore
|
||||
headers: {
|
||||
...req.headers
|
||||
|
||||
@@ -9,7 +9,7 @@ router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// test that the database is alive & responding
|
||||
getConnection();
|
||||
return res.sendStatus(200);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
res.sendStatus(503);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// test that the database is alive & responding
|
||||
getConnection();
|
||||
return res.sendStatus(200);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
res.sendStatus(503);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
//const { exclude_consumed } = req.query;
|
||||
//const { exclude_consumed } = req.query;
|
||||
res.status(200).send([]);
|
||||
});
|
||||
|
||||
|
||||
@@ -6,25 +6,23 @@ const router = Router();
|
||||
router.post("/", route({ permission: "MANAGE_MESSAGES" }), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json({
|
||||
id: "",
|
||||
type: 0,
|
||||
content: "",
|
||||
channel_id: "",
|
||||
author: {id: "",
|
||||
username: "",
|
||||
avatar: "",
|
||||
discriminator: "", public_flags: 64},
|
||||
attachments: [],
|
||||
embeds: [],
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
pinned: false,
|
||||
mention_everyone: false,
|
||||
tts: false,
|
||||
timestamp: "",
|
||||
edited_timestamp: null,
|
||||
flags: 1, components: []}).status(200);
|
||||
id: "",
|
||||
type: 0,
|
||||
content: "",
|
||||
channel_id: "",
|
||||
author: { id: "", username: "", avatar: "", discriminator: "", public_flags: 64 },
|
||||
attachments: [],
|
||||
embeds: [],
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
pinned: false,
|
||||
mention_everyone: false,
|
||||
tts: false,
|
||||
timestamp: "",
|
||||
edited_timestamp: null,
|
||||
flags: 1,
|
||||
components: []
|
||||
}).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ router.post("/", route({ body: "BulkDeleteSchema" }), async (req: Request, res:
|
||||
if (messages.length < 2) throw new HTTPError("You must at least specify 2 messages to bulk delete");
|
||||
if (messages.length > maxBulkDelete) throw new HTTPError(`You cannot delete more than ${maxBulkDelete} messages`);
|
||||
|
||||
await Message.delete({ id: In(messages) });
|
||||
await Message.delete(messages.map((x) => ({ id: x })));
|
||||
|
||||
await emitEvent({
|
||||
event: "MESSAGE_DELETE_BULK",
|
||||
|
||||
@@ -119,7 +119,7 @@ router.get("/", async (req: Request, res: Response) => {
|
||||
x.attachments?.forEach((x) => {
|
||||
// dynamically set attachment proxy_url in case the endpoint changed
|
||||
const uri = x.proxy_url.startsWith("http") ? x.proxy_url : `https://example.org${x.proxy_url}`;
|
||||
x.proxy_url = `${endpoint == null ? "http://localhost:3003" : endpoint}${new URL(uri).pathname}`;
|
||||
x.proxy_url = `${endpoint == null ? "" : endpoint}${new URL(uri).pathname}`;
|
||||
});
|
||||
|
||||
return x;
|
||||
@@ -186,14 +186,13 @@ router.post(
|
||||
timestamp: new Date()
|
||||
});
|
||||
|
||||
message = await message.save();
|
||||
channel.last_message_id = message.id;
|
||||
|
||||
if (channel.isDm()) {
|
||||
const channel_dto = await DmChannelDTO.from(channel);
|
||||
|
||||
//Only one recipients should be closed here, since in group DMs the recipient is deleted not closed
|
||||
|
||||
await Promise.all(
|
||||
// Only one recipients should be closed here, since in group DMs the recipient is deleted not closed
|
||||
Promise.all(
|
||||
channel.recipients!.map((recipient) => {
|
||||
if (recipient.closed) {
|
||||
recipient.closed = false;
|
||||
@@ -211,9 +210,10 @@ router.post(
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
channel.assign({ last_message_id: message.id }).save(),
|
||||
message.save(),
|
||||
emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent),
|
||||
message.guild_id ? Member.update({ id: req.user_id, guild_id: message.guild_id }, { last_message_id: message.id }) : null,
|
||||
emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent)
|
||||
channel.save()
|
||||
]);
|
||||
|
||||
postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import { Request, Response, Router } from "express";
|
||||
import { Channel, ChannelRecipientAddEvent, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api"
|
||||
import {
|
||||
Channel,
|
||||
ChannelRecipientAddEvent,
|
||||
ChannelType,
|
||||
DiscordApiErrors,
|
||||
DmChannelDTO,
|
||||
emitEvent,
|
||||
PublicUserProjection,
|
||||
Recipient,
|
||||
User
|
||||
} from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@@ -9,20 +19,17 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => {
|
||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] });
|
||||
|
||||
if (channel.type !== ChannelType.GROUP_DM) {
|
||||
const recipients = [
|
||||
...channel.recipients!.map(r => r.user_id),
|
||||
user_id
|
||||
].unique()
|
||||
const recipients = [...channel.recipients!.map((r) => r.user_id), user_id].unique();
|
||||
|
||||
const new_channel = await Channel.createDMChannel(recipients, req.user_id)
|
||||
const new_channel = await Channel.createDMChannel(recipients, req.user_id);
|
||||
return res.status(201).json(new_channel);
|
||||
} else {
|
||||
if (channel.recipients!.map(r => r.user_id).includes(user_id)) {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT //TODO is this the right error?
|
||||
if (channel.recipients!.map((r) => r.user_id).includes(user_id)) {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
|
||||
}
|
||||
|
||||
channel.recipients!.push(new Recipient({ channel_id: channel_id, user_id: user_id }));
|
||||
await channel.save()
|
||||
await channel.save();
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_CREATE",
|
||||
@@ -31,10 +38,12 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => {
|
||||
});
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_RECIPIENT_ADD", data: {
|
||||
event: "CHANNEL_RECIPIENT_ADD",
|
||||
data: {
|
||||
channel_id: channel_id,
|
||||
user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection })
|
||||
}, channel_id: channel_id
|
||||
},
|
||||
channel_id: channel_id
|
||||
} as ChannelRecipientAddEvent);
|
||||
return res.sendStatus(204);
|
||||
}
|
||||
@@ -44,13 +53,13 @@ router.delete("/:user_id", route({}), async (req: Request, res: Response) => {
|
||||
const { channel_id, user_id } = req.params;
|
||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] });
|
||||
if (!(channel.type === ChannelType.GROUP_DM && (channel.owner_id === req.user_id || user_id === req.user_id)))
|
||||
throw DiscordApiErrors.MISSING_PERMISSIONS
|
||||
throw DiscordApiErrors.MISSING_PERMISSIONS;
|
||||
|
||||
if (!channel.recipients!.map(r => r.user_id).includes(user_id)) {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT //TODO is this the right error?
|
||||
if (!channel.recipients!.map((r) => r.user_id).includes(user_id)) {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
|
||||
}
|
||||
|
||||
await Channel.removeRecipientFromChannel(channel, user_id)
|
||||
await Channel.removeRecipientFromChannel(channel, user_id);
|
||||
|
||||
return res.sendStatus(204);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Guild, Config } from "@fosscord/util";
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
@@ -12,7 +11,9 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
// ! this only works using SQL querys
|
||||
// TODO: implement this with default typeorm query
|
||||
// const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) });
|
||||
const guilds = showAllGuilds ? await Guild.find({take: Math.abs(Number(limit || 20))}) : await Guild.find({ where: `"features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 20)) });
|
||||
const guilds = showAllGuilds
|
||||
? await Guild.find({ take: Math.abs(Number(limit || 20)) })
|
||||
: await Guild.find({ where: `"features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 20)) });
|
||||
res.send({ guilds: guilds });
|
||||
});
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ const router = Router();
|
||||
|
||||
router.get("/categories", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
//const { locale, primary_only } = req.query;
|
||||
//const { locale, primary_only } = req.query;
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface GatewayBotResponse {
|
||||
remaining: number;
|
||||
reset_after: number;
|
||||
max_concurrency: number;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const options: RouteOptions = {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import { route } from "@fosscord/api";
|
||||
import { getGifApiKey, parseGifResult } from "./trending";
|
||||
|
||||
@@ -10,8 +11,11 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { q, media_format, locale } = req.query;
|
||||
|
||||
const apiKey = getGifApiKey();
|
||||
|
||||
const agent = new ProxyAgent();
|
||||
|
||||
const response = await fetch(`https://g.tenor.com/v1/search?q=${q}&media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
|
||||
agent,
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" }
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import { route } from "@fosscord/api";
|
||||
import { getGifApiKey, parseGifResult } from "./trending";
|
||||
|
||||
@@ -10,8 +11,11 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { media_format, locale } = req.query;
|
||||
|
||||
const apiKey = getGifApiKey();
|
||||
|
||||
const agent = new ProxyAgent();
|
||||
|
||||
const response = await fetch(`https://g.tenor.com/v1/trending?media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
|
||||
agent,
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" }
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Router, Response, Request } from "express";
|
||||
import fetch from "node-fetch";
|
||||
import ProxyAgent from 'proxy-agent';
|
||||
import { route } from "@fosscord/api";
|
||||
import { Config } from "@fosscord/util";
|
||||
import { HTTPError } from "lambert-server";
|
||||
@@ -33,13 +34,17 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const { media_format, locale } = req.query;
|
||||
|
||||
const apiKey = getGifApiKey();
|
||||
|
||||
const agent = new ProxyAgent();
|
||||
|
||||
const [responseSource, trendGifSource] = await Promise.all([
|
||||
fetch(`https://g.tenor.com/v1/categories?locale=${locale}&key=${apiKey}`, {
|
||||
agent,
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" }
|
||||
}),
|
||||
fetch(`https://g.tenor.com/v1/trending?locale=${locale}&key=${apiKey}`, {
|
||||
agent,
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" }
|
||||
})
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Guild, Member, Snowflake } from "@fosscord/util";
|
||||
import { LessThan, IsNull } from "typeorm";
|
||||
import { route } from "@fosscord/api";
|
||||
const router = Router();
|
||||
|
||||
//Returns all inactive members, respecting role hierarchy
|
||||
export const inactiveMembers = async (guild_id: string, user_id: string, days: number, roles: string[] = []) => {
|
||||
var date = new Date();
|
||||
date.setDate(date.getDate() - days);
|
||||
//Snowflake should have `generateFromTime` method? Or similar?
|
||||
var minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
|
||||
|
||||
var members = await Member.find({
|
||||
where: [
|
||||
{
|
||||
guild_id,
|
||||
last_message_id: LessThan(minId.toString())
|
||||
},
|
||||
{
|
||||
last_message_id: IsNull()
|
||||
}
|
||||
],
|
||||
relations: ["roles"]
|
||||
});
|
||||
console.log(members);
|
||||
if (!members.length) return [];
|
||||
|
||||
//I'm sure I can do this in the above db query ( and it would probably be better to do so ), but oh well.
|
||||
if (roles.length && members.length) members = members.filter((user) => user.roles?.some((role) => roles.includes(role.id)));
|
||||
|
||||
const me = await Member.findOneOrFail({ id: user_id, guild_id }, { relations: ["roles"] });
|
||||
const myHighestRole = Math.max(...(me.roles?.map((x) => x.position) || []));
|
||||
|
||||
const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
|
||||
|
||||
members = members.filter(
|
||||
(member) =>
|
||||
member.id !== guild.owner_id && //can't kick owner
|
||||
member.roles?.some(
|
||||
(role) =>
|
||||
role.position < myHighestRole || //roles higher than me can't be kicked
|
||||
me.id === guild.owner_id //owner can kick anyone
|
||||
)
|
||||
);
|
||||
|
||||
return members;
|
||||
};
|
||||
|
||||
router.get("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => {
|
||||
const days = parseInt(req.query.days as string);
|
||||
|
||||
var roles = req.query.include_roles;
|
||||
if (typeof roles === "string") roles = [roles]; //express will return array otherwise
|
||||
|
||||
const members = await inactiveMembers(req.params.guild_id, req.user_id, days, roles as string[]);
|
||||
|
||||
res.send({ pruned: members.length });
|
||||
});
|
||||
|
||||
export interface PruneSchema {
|
||||
/**
|
||||
* @min 0
|
||||
*/
|
||||
days: number;
|
||||
}
|
||||
|
||||
router.post("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => {
|
||||
const days = parseInt(req.body.days);
|
||||
|
||||
var roles = req.query.include_roles;
|
||||
if (typeof roles === "string") roles = [roles];
|
||||
|
||||
const { guild_id } = req.params;
|
||||
const members = await inactiveMembers(guild_id, req.user_id, days, roles as string[]);
|
||||
|
||||
await Promise.all(members.map((x) => Member.removeFromGuild(x.id, guild_id)));
|
||||
|
||||
res.send({ purged: members.length });
|
||||
});
|
||||
|
||||
export default router;
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Guild, Member, Snowflake } from "@fosscord/util";
|
||||
import { LessThan, IsNull } from "typeorm";
|
||||
import { route } from "@fosscord/api";
|
||||
const router = Router();
|
||||
|
||||
//Returns all inactive members, respecting role hierarchy
|
||||
export const inactiveMembers = async (guild_id: string, user_id: string, days: number, roles: string[] = []) => {
|
||||
var date = new Date();
|
||||
date.setDate(date.getDate() - days);
|
||||
//Snowflake should have `generateFromTime` method? Or similar?
|
||||
var minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
|
||||
|
||||
var members = await Member.find({
|
||||
where: [
|
||||
{
|
||||
guild_id,
|
||||
last_message_id: LessThan(minId.toString())
|
||||
},
|
||||
{
|
||||
last_message_id: IsNull()
|
||||
}
|
||||
],
|
||||
relations: ["roles"]
|
||||
});
|
||||
console.log(members);
|
||||
if (!members.length) return [];
|
||||
|
||||
//I'm sure I can do this in the above db query ( and it would probably be better to do so ), but oh well.
|
||||
if (roles.length && members.length) members = members.filter((user) => user.roles?.some((role) => roles.includes(role.id)));
|
||||
|
||||
const me = await Member.findOneOrFail({ id: user_id, guild_id }, { relations: ["roles"] });
|
||||
const myHighestRole = Math.max(...(me.roles?.map((x) => x.position) || []));
|
||||
|
||||
const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
|
||||
|
||||
members = members.filter(
|
||||
(member) =>
|
||||
member.id !== guild.owner_id && //can't kick owner
|
||||
member.roles?.some(
|
||||
(role) =>
|
||||
role.position < myHighestRole || //roles higher than me can't be kicked
|
||||
me.id === guild.owner_id //owner can kick anyone
|
||||
)
|
||||
);
|
||||
|
||||
return members;
|
||||
};
|
||||
|
||||
router.get("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => {
|
||||
const days = parseInt(req.query.days as string);
|
||||
|
||||
var roles = req.query.include_roles;
|
||||
if (typeof roles === "string") roles = [roles]; //express will return array otherwise
|
||||
|
||||
const members = await inactiveMembers(req.params.guild_id, req.user_id, days, roles as string[]);
|
||||
|
||||
res.send({ pruned: members.length });
|
||||
});
|
||||
|
||||
export interface PruneSchema {
|
||||
/**
|
||||
* @min 0
|
||||
*/
|
||||
days: number;
|
||||
}
|
||||
|
||||
router.post("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => {
|
||||
const days = parseInt(req.body.days);
|
||||
|
||||
var roles = req.query.include_roles;
|
||||
if (typeof roles === "string") roles = [roles];
|
||||
|
||||
const { guild_id } = req.params;
|
||||
const members = await inactiveMembers(guild_id, req.user_id, days, roles as string[]);
|
||||
|
||||
await Promise.all(members.map((x) => Member.removeFromGuild(x.id, guild_id)));
|
||||
|
||||
res.send({ purged: members.length });
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -2,8 +2,8 @@ import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
const router = Router();
|
||||
|
||||
router.get("/",route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
res.json([]);
|
||||
});
|
||||
|
||||
|
||||
@@ -6,19 +6,20 @@ const router: Router = Router();
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
//TODO
|
||||
res.json([
|
||||
{
|
||||
id: "",
|
||||
name: "",
|
||||
interval: 1,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "",
|
||||
fallback_price: 499,
|
||||
fallback_currency: "eur",
|
||||
currency: "eur",
|
||||
price: 4199,
|
||||
price_tier: null
|
||||
}]).status(200);
|
||||
{
|
||||
id: "",
|
||||
name: "",
|
||||
interval: 1,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "",
|
||||
fallback_price: 499,
|
||||
fallback_currency: "eur",
|
||||
currency: "eur",
|
||||
price: 4199,
|
||||
price_tier: null
|
||||
}
|
||||
]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -4,17 +4,134 @@ import { route } from "@fosscord/api";
|
||||
const router: Router = Router();
|
||||
|
||||
const skus = new Map([
|
||||
["521842865731534868", [{"id": "511651856145973248", "name": "Premium Monthly (Legacy)", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "521842865731534868", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651860671627264", "name": "Premium Yearly (Legacy)", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "521842865731534868", "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
["521846918637420545", [{"id": "511651871736201216", "name": "Premium Classic Monthly", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "521846918637420545", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651876987469824", "name": "Premium Classic Yearly", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "521846918637420545", "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
["521847234246082599", [{"id": "642251038925127690", "name": "Premium Quarterly", "interval": 1, "interval_count": 3, "tax_inclusive": true, "sku_id": "521847234246082599", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651880837840896", "name": "Premium Monthly", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "521847234246082599", "currency": "usd", "price": 0, "price_tier": null}, {"id": "511651885459963904", "name": "Premium Yearly", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "521847234246082599", "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
["590663762298667008", [{"id": "590665532894740483", "name": "Server Boost Monthly", "interval": 1, "interval_count": 1, "tax_inclusive": true, "sku_id": "590663762298667008", "discount_price": 0, "currency": "usd", "price": 0, "price_tier": null}, {"id": "590665538238152709", "name": "Server Boost Yearly", "interval": 2, "interval_count": 1, "tax_inclusive": true, "sku_id": "590663762298667008", "discount_price": 0, "currency": "usd", "price": 0, "price_tier": null}]],
|
||||
[
|
||||
"521842865731534868",
|
||||
[
|
||||
{
|
||||
id: "511651856145973248",
|
||||
name: "Premium Monthly (Legacy)",
|
||||
interval: 1,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "521842865731534868",
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
},
|
||||
{
|
||||
id: "511651860671627264",
|
||||
name: "Premium Yearly (Legacy)",
|
||||
interval: 2,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "521842865731534868",
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
"521846918637420545",
|
||||
[
|
||||
{
|
||||
id: "511651871736201216",
|
||||
name: "Premium Classic Monthly",
|
||||
interval: 1,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "521846918637420545",
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
},
|
||||
{
|
||||
id: "511651876987469824",
|
||||
name: "Premium Classic Yearly",
|
||||
interval: 2,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "521846918637420545",
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
"521847234246082599",
|
||||
[
|
||||
{
|
||||
id: "642251038925127690",
|
||||
name: "Premium Quarterly",
|
||||
interval: 1,
|
||||
interval_count: 3,
|
||||
tax_inclusive: true,
|
||||
sku_id: "521847234246082599",
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
},
|
||||
{
|
||||
id: "511651880837840896",
|
||||
name: "Premium Monthly",
|
||||
interval: 1,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "521847234246082599",
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
},
|
||||
{
|
||||
id: "511651885459963904",
|
||||
name: "Premium Yearly",
|
||||
interval: 2,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "521847234246082599",
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
"590663762298667008",
|
||||
[
|
||||
{
|
||||
id: "590665532894740483",
|
||||
name: "Server Boost Monthly",
|
||||
interval: 1,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "590663762298667008",
|
||||
discount_price: 0,
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
},
|
||||
{
|
||||
id: "590665538238152709",
|
||||
name: "Server Boost Yearly",
|
||||
interval: 2,
|
||||
interval_count: 1,
|
||||
tax_inclusive: true,
|
||||
sku_id: "590663762298667008",
|
||||
discount_price: 0,
|
||||
currency: "usd",
|
||||
price: 0,
|
||||
price_tier: null
|
||||
}
|
||||
]
|
||||
]
|
||||
]);
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
// TODO: add the ability to add custom
|
||||
const { sku_id } = req.params;
|
||||
|
||||
if(!skus.has(sku_id)) {
|
||||
|
||||
if (!skus.has(sku_id)) {
|
||||
console.log(`Request for invalid SKU ${sku_id}! Please report this!`);
|
||||
res.sendStatus(404);
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,7 @@ const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json([]).status(200)
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -5,7 +5,7 @@ const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
res.json([]).status(200)
|
||||
res.json([]).status(200);
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -5,8 +5,11 @@ import { route } from "@fosscord/api";
|
||||
const router: Router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
const recipients = await Recipient.find({ where: { user_id: req.user_id, closed: false }, relations: ["channel", "channel.recipients"] });
|
||||
res.json(await Promise.all(recipients.map(r => DmChannelDTO.from(r.channel, [req.user_id]))));
|
||||
const recipients = await Recipient.find({
|
||||
where: { user_id: req.user_id, closed: false },
|
||||
relations: ["channel", "channel.recipients"]
|
||||
});
|
||||
res.json(await Promise.all(recipients.map((r) => DmChannelDTO.from(r.channel, [req.user_id]))));
|
||||
});
|
||||
|
||||
export interface DmChannelCreateSchema {
|
||||
|
||||
@@ -4,14 +4,15 @@ import { route } from "@fosscord/api";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), (req: Request, res: Response) => {
|
||||
// TODO:
|
||||
// TODO:
|
||||
res.json({
|
||||
categories: {
|
||||
social: true,
|
||||
communication: true,
|
||||
tips: false,
|
||||
updates_and_announcements: false,
|
||||
recommendations_and_events: false },
|
||||
categories: {
|
||||
social: true,
|
||||
communication: true,
|
||||
tips: false,
|
||||
updates_and_announcements: false,
|
||||
recommendations_and_events: false
|
||||
},
|
||||
initialized: false
|
||||
}).status(200);
|
||||
});
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ config();
|
||||
import { FosscordServer } from "./Server";
|
||||
import cluster from "cluster";
|
||||
import os from "os";
|
||||
const cores = Number(process.env.threads) || os.cpus().length;
|
||||
const cores = Number(process.env.THREADS) || os.cpus().length;
|
||||
|
||||
if (cluster.isMaster && process.env.NODE_ENV == "production") {
|
||||
console.log(`Primary ${process.pid} is running`);
|
||||
|
||||
@@ -33,7 +33,7 @@ const DEFAULT_FETCH_OPTIONS: any = {
|
||||
redirect: "follow",
|
||||
follow: 1,
|
||||
headers: {
|
||||
"user-agent": "Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)"
|
||||
"user-agent": "Mozilla/5.0 (compatible; Fosscord/1.0; +https://github.com/fosscord/fosscord)"
|
||||
},
|
||||
size: 1024 * 1024 * 1,
|
||||
compress: true,
|
||||
@@ -184,7 +184,7 @@ export async function sendMessage(opts: MessageOptions) {
|
||||
const message = await handleMessage({ ...opts, timestamp: new Date() });
|
||||
|
||||
await Promise.all([
|
||||
message.save(),
|
||||
Message.insert(message),
|
||||
emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data: message.toJSON() } as MessageCreateEvent)
|
||||
]);
|
||||
|
||||
|
||||
@@ -81,18 +81,15 @@ export function getIpAdress(req: Request): string {
|
||||
return req.headers[Config.get().security.forwadedFor] || req.socket.remoteAddress;
|
||||
}
|
||||
|
||||
|
||||
export function distanceBetweenLocations(loc1: any, loc2: any): number {
|
||||
return distanceBetweenCoords(loc1.latitude, loc1.longitude, loc2.latitude, loc2.longitude);
|
||||
}
|
||||
|
||||
//Haversine function
|
||||
function distanceBetweenCoords(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
const p = 0.017453292519943295; // Math.PI / 180
|
||||
const p = 0.017453292519943295; // Math.PI / 180
|
||||
const c = Math.cos;
|
||||
const a = 0.5 - c((lat2 - lat1) * p) / 2 +
|
||||
c(lat1 * p) * c(lat2 * p) *
|
||||
(1 - c((lon2 - lon1) * p)) / 2;
|
||||
const a = 0.5 - c((lat2 - lat1) * p) / 2 + (c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p))) / 2;
|
||||
|
||||
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user