This commit is contained in:
uurgothat
2021-10-24 18:13:51 +03:00
216 changed files with 10585 additions and 11466 deletions
+7 -7
View File
@@ -1,8 +1,8 @@
declare global {
namespace Express {
interface Request {
user_id: any;
token: any;
}
}
}
namespace Express {
interface Request {
user_id: any;
token: any;
}
}
}
+3
View File
@@ -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
+1 -1
View File
@@ -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);
}
});
+1 -1
View File
@@ -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 -2
View File
@@ -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 });
});
+1 -1
View File
@@ -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);
});
+1 -1
View File
@@ -12,7 +12,7 @@ export interface GatewayBotResponse {
remaining: number;
reset_after: number;
max_concurrency: number;
}
};
}
const options: RouteOptions = {
+4
View File
@@ -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" }
});
+4
View File
@@ -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" }
});
+5
View File
@@ -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" }
})
+82 -82
View File
@@ -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 -2
View File
@@ -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 -2
View File
@@ -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 {
+8 -7
View File
@@ -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
View File
@@ -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`);
+2 -2
View File
@@ -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)
]);
+3 -6
View File
@@ -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
}
}