migrate to deno 2.0 serve

This commit is contained in:
Ean Milligan 2025-04-26 14:27:36 -04:00
parent 8d4e21056c
commit d2a7c25879
12 changed files with 227 additions and 284 deletions

View File

@ -17,7 +17,6 @@ import stdResp from './endpoints/stdResponses.ts';
// start() returns nothing // start() returns nothing
// start initializes and runs the entire API for the bot // start initializes and runs the entire API for the bot
const start = async (): Promise<void> => { const start = async (): Promise<void> => {
const server = Deno.listen({ port: config.api.port });
log(LT.INFO, `HTTP api running at: http://localhost:${config.api.port}/`); log(LT.INFO, `HTTP api running at: http://localhost:${config.api.port}/`);
// rateLimitTime holds all users with the last time they started a rate limit timer // rateLimitTime holds all users with the last time they started a rate limit timer
@ -26,11 +25,7 @@ const start = async (): Promise<void> => {
const rateLimitCnt = new Map<string, number>(); const rateLimitCnt = new Map<string, number>();
// Catching every request made to the server // Catching every request made to the server
for await (const conn of server) { Deno.serve({ port: config.api.port }, async (request) => {
(async () => {
const httpConn = Deno.serveHttp(conn);
for await (const requestEvent of httpConn) {
const request = requestEvent.request;
log(LT.LOG, `Handling request: ${JSON.stringify(request.headers)} | ${JSON.stringify(request.method)} | ${JSON.stringify(request.url)}`); log(LT.LOG, `Handling request: ${JSON.stringify(request.headers)} | ${JSON.stringify(request.method)} | ${JSON.stringify(request.url)}`);
// Check if user is authenticated to be using this API // Check if user is authenticated to be using this API
let authenticated = false; let authenticated = false;
@ -95,38 +90,38 @@ const start = async (): Promise<void> => {
if (path) { if (path) {
if (authenticated) { if (authenticated) {
// Update rate limit details
if (updateRateLimitTime) {
const apiTimeNow = new Date().getTime();
rateLimitTime.set(apiUseridStr, apiTimeNow);
}
// Handle the authenticated request // Handle the authenticated request
switch (request.method) { switch (request.method) {
case 'GET': case 'GET':
switch (path.toLowerCase()) { switch (path.toLowerCase()) {
case '/key': case '/key':
case '/key/': case '/key/':
endpoints.get.apiKeyAdmin(requestEvent, query, apiUserid); return await endpoints.get.apiKeyAdmin(query, apiUserid);
break;
case '/channel': case '/channel':
case '/channel/': case '/channel/':
endpoints.get.apiChannel(requestEvent, query, apiUserid); return await endpoints.get.apiChannel(query, apiUserid);
break;
case '/roll': case '/roll':
case '/roll/': case '/roll/':
endpoints.get.apiRoll(requestEvent, query, apiUserid); return await endpoints.get.apiRoll(query, apiUserid, request);
break;
default: default:
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.NotFound('Auth Get')); return stdResp.NotFound('Auth Get');
break;
} }
break; break;
case 'POST': case 'POST':
switch (path.toLowerCase()) { switch (path.toLowerCase()) {
case '/channel/add': case '/channel/add':
case '/channel/add/': case '/channel/add/':
endpoints.post.apiChannelAdd(requestEvent, query, apiUserid); return await endpoints.post.apiChannelAdd(query, apiUserid);
break;
default: default:
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.NotFound('Auth Post')); return stdResp.NotFound('Auth Post');
break;
} }
break; break;
case 'PUT': case 'PUT':
@ -139,48 +134,35 @@ const start = async (): Promise<void> => {
case '/key/activate/': case '/key/activate/':
case '/key/deactivate': case '/key/deactivate':
case '/key/deactivate/': case '/key/deactivate/':
endpoints.put.apiKeyManage(requestEvent, query, apiUserid, path); return await endpoints.put.apiKeyManage(query, apiUserid, path);
break;
case '/channel/ban': case '/channel/ban':
case '/channel/ban/': case '/channel/ban/':
case '/channel/unban': case '/channel/unban':
case '/channel/unban/': case '/channel/unban/':
endpoints.put.apiChannelManageBan(requestEvent, query, apiUserid, path); return await endpoints.put.apiChannelManageBan(query, apiUserid, path);
break;
case '/channel/activate': case '/channel/activate':
case '/channel/activate/': case '/channel/activate/':
case '/channel/deactivate': case '/channel/deactivate':
case '/channel/deactivate/': case '/channel/deactivate/':
endpoints.put.apiChannelManageActive(requestEvent, query, apiUserid, path); return await endpoints.put.apiChannelManageActive(query, apiUserid, path);
break;
default: default:
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.NotFound('Auth Put')); return stdResp.NotFound('Auth Put');
break;
} }
break; break;
case 'DELETE': case 'DELETE':
switch (path.toLowerCase()) { switch (path.toLowerCase()) {
case '/key/delete': case '/key/delete':
case '/key/delete/': case '/key/delete/':
endpoints.delete.apiKeyDelete(requestEvent, query, apiUserid, apiUserEmail, apiUserDelCode); return await endpoints.delete.apiKeyDelete(query, apiUserid, apiUserEmail, apiUserDelCode);
break;
default: default:
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.NotFound('Auth Del')); return stdResp.NotFound('Auth Del');
break;
} }
break; break;
default: default:
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.MethodNotAllowed('Auth')); return stdResp.MethodNotAllowed('Auth');
break;
}
// Update rate limit details
if (updateRateLimitTime) {
const apiTimeNow = new Date().getTime();
rateLimitTime.set(apiUseridStr, apiTimeNow);
} }
} else if (!authenticated) { } else if (!authenticated) {
// Handle the unathenticated request // Handle the unathenticated request
@ -189,36 +171,30 @@ const start = async (): Promise<void> => {
switch (path.toLowerCase()) { switch (path.toLowerCase()) {
case '/key': case '/key':
case '/key/': case '/key/':
endpoints.get.apiKey(requestEvent, query); return await endpoints.get.apiKey(query);
break;
case '/heatmap.png': case '/heatmap.png':
endpoints.get.heatmapPng(requestEvent); return endpoints.get.heatmapPng();
break;
default: default:
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.NotFound('NoAuth Get')); return stdResp.NotFound('NoAuth Get');
break;
} }
break; break;
default: default:
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.MethodNotAllowed('NoAuth')); return stdResp.MethodNotAllowed('NoAuth');
break;
} }
} }
} else { } else {
requestEvent.respondWith(stdResp.Forbidden('What are you trying to do?')); return stdResp.Forbidden('What are you trying to do?');
} }
} else if (authenticated && rateLimited) { } else if (authenticated && rateLimited) {
// Alert API user that they are doing this too often // Alert API user that they are doing this too often
requestEvent.respondWith(stdResp.TooManyRequests('Slow down, servers are expensive and this bot is free to use.')); return stdResp.TooManyRequests('Slow down, servers are expensive and this bot is free to use.');
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden('Why are you here?')); return stdResp.Forbidden('Why are you here?');
}
}
})();
} }
});
}; };
export default { start }; export default { start };

View File

@ -10,13 +10,7 @@ import { generateApiDeleteEmail } from '../../commandUtils.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
export const apiKeyDelete = async ( export const apiKeyDelete = async (query: Map<string, string>, apiUserid: bigint, apiUserEmail: string, apiUserDelCode: string): Promise<Response> => {
requestEvent: Deno.RequestEvent,
query: Map<string, string>,
apiUserid: BigInt,
apiUserEmail: string,
apiUserDelCode: string,
) => {
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) { if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0') && apiUserEmail === query.get('email')) { if (apiUserid === BigInt(query.get('user') || '0') && apiUserEmail === query.get('email')) {
if (query.has('code') && (query.get('code') || '').length > 0) { if (query.has('code') && (query.get('code') || '').length > 0) {
@ -26,28 +20,25 @@ export const apiKeyDelete = async (
await dbClient.execute('DELETE FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => { await dbClient.execute('DELETE FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
utils.commonLoggers.dbError('apiKeyDelete.ts:25', 'insert into', e); utils.commonLoggers.dbError('apiKeyDelete.ts:25', 'insert into', e);
requestEvent.respondWith(stdResp.InternalServerError('Channel Clean Failed.'));
erroredOut = true; erroredOut = true;
}); });
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Channel Clean Failed.');
} }
await dbClient.execute('DELETE FROM all_keys WHERE userid = ?', [apiUserid]).catch((e) => { await dbClient.execute('DELETE FROM all_keys WHERE userid = ?', [apiUserid]).catch((e) => {
utils.commonLoggers.dbError('apiKeyDelete.ts:34', 'delete from', e); utils.commonLoggers.dbError('apiKeyDelete.ts:34', 'delete from', e);
requestEvent.respondWith(stdResp.InternalServerError('Delete Key Failed.'));
erroredOut = true; erroredOut = true;
}); });
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Delete Key Failed.');
} else { } else {
// Send OK as response to indicate key deletion was successful // Send OK as response to indicate key deletion was successful
requestEvent.respondWith(stdResp.OK('You have been removed from the DB, Goodbye.')); return stdResp.OK('You have been removed from the DB, Goodbye.');
return;
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden('Invalid Delete Code.')); return stdResp.Forbidden('Invalid Delete Code.');
} }
} else { } else {
// User does not have their delete code yet, so we need to generate one and email it to them // User does not have their delete code yet, so we need to generate one and email it to them
@ -58,32 +49,29 @@ export const apiKeyDelete = async (
// Execute the DB modification // Execute the DB modification
await dbClient.execute('UPDATE all_keys SET deleteCode = ? WHERE userid = ?', [deleteCode, apiUserid]).catch((e) => { await dbClient.execute('UPDATE all_keys SET deleteCode = ? WHERE userid = ?', [deleteCode, apiUserid]).catch((e) => {
utils.commonLoggers.dbError('apiKeyDelete.ts:57', 'update', e); utils.commonLoggers.dbError('apiKeyDelete.ts:57', 'update', e);
requestEvent.respondWith(stdResp.InternalServerError('Delete Code Failed'));
erroredOut = true; erroredOut = true;
}); });
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Delete Code Failed');
} }
// "Send" the email // "Send" the email
await sendMessage(config.api.email, generateApiDeleteEmail(apiUserEmail, deleteCode)).catch(() => { await sendMessage(config.api.email, generateApiDeleteEmail(apiUserEmail, deleteCode)).catch(() => {
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
erroredOut = true; erroredOut = true;
}); });
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to send email.');
} else { } else {
// Send API key as response // Send API key as response
requestEvent.respondWith(stdResp.FailedDependency('Please look for an email containing a Delete Key and run this query again with said key.')); return stdResp.FailedDependency('Please look for an email containing a Delete Key and run this query again with said key.');
return;
} }
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden('You can only delete your own key.')); return stdResp.Forbidden('You can only delete your own key.');
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -2,7 +2,7 @@ import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiChannel = async (query: Map<string, string>, apiUserid: bigint): Promise<Response> => {
if (query.has('user') && (query.get('user') || '').length > 0) { if (query.has('user') && (query.get('user') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0')) { if (apiUserid === BigInt(query.get('user') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
@ -11,25 +11,23 @@ export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<str
// Get all channels userid has authorized // Get all channels userid has authorized
const dbAllowedChannelQuery = await dbClient.query('SELECT * FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => { const dbAllowedChannelQuery = await dbClient.query('SELECT * FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
utils.commonLoggers.dbError('apiChannel.ts', 'query', e); utils.commonLoggers.dbError('apiChannel.ts', 'query', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to get channels.'));
erroredOut = true; erroredOut = true;
}); });
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to get channels.');
} else { } else {
// Customized strinification to handle BigInts correctly // Customized strinification to handle BigInts correctly
const returnChannels = JSON.stringify(dbAllowedChannelQuery, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)); const returnChannels = JSON.stringify(dbAllowedChannelQuery, (_key, value) => (typeof value === 'bigint' ? value.toString() : value));
// Send channel list as response // Send channel list as response
requestEvent.respondWith(stdResp.OK(returnChannels)); return stdResp.OK(returnChannels);
return;
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden('You can only view your own channels.')); return stdResp.Forbidden('You can only view your own channels.');
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -10,7 +10,7 @@ import { generateApiKeyEmail } from '../../commandUtils.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string, string>) => { export const apiKey = async (query: Map<string, string>): Promise<Response> => {
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) { if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) {
// Generate new secure key // Generate new secure key
const newKey = await nanoid(25); const newKey = await nanoid(25);
@ -23,30 +23,27 @@ export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string,
.execute('INSERT INTO all_keys(userid,apiKey,email) values(?,?,?)', [BigInt(query.get('user') || '0'), newKey, (query.get('email') || '').toLowerCase()]) .execute('INSERT INTO all_keys(userid,apiKey,email) values(?,?,?)', [BigInt(query.get('user') || '0'), newKey, (query.get('email') || '').toLowerCase()])
.catch((e) => { .catch((e) => {
utils.commonLoggers.dbError('apiKey.ts:27', 'insert into', e); utils.commonLoggers.dbError('apiKey.ts:27', 'insert into', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
erroredOut = true; erroredOut = true;
}); });
// Exit this case now if catch errored // Exit this case now if catch errored
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to store key.');
} }
// "Send" the email // "Send" the email
await sendMessage(config.api.email, generateApiKeyEmail(query.get('email') || 'no email', newKey)).catch(() => { await sendMessage(config.api.email, generateApiKeyEmail(query.get('email') || 'no email', newKey)).catch(() => {
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
erroredOut = true; erroredOut = true;
}); });
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to send email.');
} else { } else {
// Send basic OK to indicate key has been sent // Send basic OK to indicate key has been sent
requestEvent.respondWith(stdResp.OK('Email Sent.')); return stdResp.OK('Email Sent.');
return;
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -7,7 +7,7 @@ import {
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiKeyAdmin = async (query: Map<string, string>, apiUserid: bigint): Promise<Response> => {
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('a') && (query.get('a') || '').length > 0) { if (query.has('user') && (query.get('user') || '').length > 0 && query.has('a') && (query.get('a') || '').length > 0) {
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) { if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
// Generate new secure key // Generate new secure key
@ -19,24 +19,22 @@ export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<st
// Insert new key/user pair into the db // Insert new key/user pair into the db
await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [apiUserid, newKey]).catch((e) => { await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [apiUserid, newKey]).catch((e) => {
utils.commonLoggers.dbError('apiKeyAdmin.ts:24', 'insert into', e); utils.commonLoggers.dbError('apiKeyAdmin.ts:24', 'insert into', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
erroredOut = true; erroredOut = true;
}); });
// Exit this case now if catch errored // Exit this case now if catch errored
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to store key.');
} else { } else {
// Send API key as response // Send API key as response
requestEvent.respondWith(stdResp.OK(JSON.stringify({ key: newKey, userid: query.get('user') }))); return stdResp.OK(JSON.stringify({ key: newKey, userid: query.get('user') }));
return;
} }
} else { } else {
// Only allow the db admin to use this API // Only allow the db admin to use this API
requestEvent.respondWith(stdResp.Forbidden(stdResp.Strings.restricted)); return stdResp.Forbidden(stdResp.Strings.restricted);
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -1,5 +1,6 @@
import config from '../../../config.ts'; import config from '../../../config.ts';
import dbClient from '../../db/client.ts'; import dbClient from '../../db/client.ts';
import { queries } from '../../db/common.ts';
import { import {
// Discordeno deps // Discordeno deps
cache, cache,
@ -14,7 +15,7 @@ import stdResp from '../stdResponses.ts';
const apiWarning = `The following roll was conducted using my built in API. If someone in this channel did not request this roll, please report API abuse here: <${config.api.supportURL}>`; const apiWarning = `The following roll was conducted using my built in API. If someone in this channel did not request this roll, please report API abuse here: <${config.api.supportURL}>`;
export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiRoll = async (query: Map<string, string>, apiUserid: bigint, request: Request): Promise<Response> => {
// Make sure query contains all the needed parts // Make sure query contains all the needed parts
if ( if (
query.has('rollstr') && query.has('rollstr') &&
@ -26,8 +27,7 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
) { ) {
if (query.has('n') && query.has('m')) { if (query.has('n') && query.has('m')) {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.BadRequest("Cannot have both 'n' and 'm'.")); return stdResp.BadRequest("Cannot have both 'n' and 'm'.");
return;
} }
// Check if user is authenticated to use this endpoint // Check if user is authenticated to use this endpoint
@ -64,25 +64,23 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
const originalCommand = query.get('rollstr'); const originalCommand = query.get('rollstr');
if (rollCmd.length === 0) { if (rollCmd.length === 0) {
// Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest('rollCmd is required.'));
// Always log API rolls for abuse detection // Always log API rolls for abuse detection
dbClient dbClient
.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'EmptyInput', null]) .execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'EmptyInput', null])
.catch((e) => utils.commonLoggers.dbError('apiRoll.ts:65', 'insert', e)); .catch((e) => utils.commonLoggers.dbError('apiRoll.ts:65', 'insert', e));
return;
// Alert API user that they messed up
return stdResp.BadRequest('rollCmd is required.');
} }
if (query.has('o') && query.get('o')?.toLowerCase() !== 'd' && query.get('o')?.toLowerCase() !== 'a') { if (query.has('o') && query.get('o')?.toLowerCase() !== 'd' && query.get('o')?.toLowerCase() !== 'a') {
// Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest("Order must be set to 'a' or 'd'."));
// Always log API rolls for abuse detection // Always log API rolls for abuse detection
dbClient dbClient
.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'BadOrder', null]) .execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'BadOrder', null])
.catch((e) => utils.commonLoggers.dbError('apiRoll.ts:66', 'insert', e)); .catch((e) => utils.commonLoggers.dbError('apiRoll.ts:66', 'insert', e));
return;
// Alert API user that they messed up
return stdResp.BadRequest("Order must be set to 'a' or 'd'.");
} }
// Clip off the leading prefix. API calls must be formatted with a prefix at the start to match how commands are sent in Discord // Clip off the leading prefix. API calls must be formatted with a prefix at the start to match how commands are sent in Discord
@ -106,7 +104,7 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
await queueRoll( await queueRoll(
<QueuedRoll> { <QueuedRoll> {
apiRoll: true, apiRoll: true,
api: { requestEvent, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') }, api: { request, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') },
rollCmd, rollCmd,
modifiers, modifiers,
originalCommand, originalCommand,
@ -115,18 +113,16 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
} catch (err) { } catch (err) {
// Handle any errors we missed // Handle any errors we missed
log(LT.ERROR, `Unhandled Error: ${JSON.stringify(err)}`); log(LT.ERROR, `Unhandled Error: ${JSON.stringify(err)}`);
requestEvent.respondWith(stdResp.InternalServerError('Something went wrong.')); return stdResp.InternalServerError('Something went wrong.');
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith( return stdResp.Forbidden(
stdResp.Forbidden(
`Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`, `Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`,
),
); );
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -4,16 +4,14 @@ import {
STATUS_TEXT, STATUS_TEXT,
} from '../../../deps.ts'; } from '../../../deps.ts';
export const heatmapPng = async (requestEvent: Deno.RequestEvent) => { export const heatmapPng = (): Response => {
const file = Deno.readFileSync('./src/endpoints/gets/heatmap.png'); const file = Deno.readFileSync('./src/endpoints/gets/heatmap.png');
const imageHeaders = new Headers(); const imageHeaders = new Headers();
imageHeaders.append('Content-Type', 'image/png'); imageHeaders.append('Content-Type', 'image/png');
// Send basic OK to indicate key has been sent // Send basic OK to indicate key has been sent
requestEvent.respondWith( return new Response(file, {
new Response(file, {
status: STATUS_CODE.OK, status: STATUS_CODE.OK,
statusText: STATUS_TEXT[STATUS_CODE.OK], statusText: STATUS_TEXT[STATUS_CODE.OK],
headers: imageHeaders, headers: imageHeaders,
}), });
);
}; };

View File

@ -2,7 +2,7 @@ import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => { export const apiChannelAdd = async (query: Map<string, string>, apiUserid: bigint): Promise<Response> => {
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('channel') && (query.get('channel') || '').length > 0) { if (query.has('user') && (query.get('user') || '').length > 0 && query.has('channel') && (query.get('channel') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0')) { if (apiUserid === BigInt(query.get('user') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
@ -11,24 +11,22 @@ export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<
// Insert new user/channel pair into the db // Insert new user/channel pair into the db
await dbClient.execute('INSERT INTO allowed_channels(userid,channelid) values(?,?)', [apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => { await dbClient.execute('INSERT INTO allowed_channels(userid,channelid) values(?,?)', [apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
utils.commonLoggers.dbError('apiChannelAdd.ts:17', 'insert into', e); utils.commonLoggers.dbError('apiChannelAdd.ts:17', 'insert into', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to store channel.'));
erroredOut = true; erroredOut = true;
}); });
// Exit this case now if catch errored // Exit this case now if catch errored
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to store channel.');
} else { } else {
// Send OK to indicate modification was successful // Send OK to indicate modification was successful
requestEvent.respondWith(stdResp.OK('Successfully added channel.')); return stdResp.OK('Successfully added channel.');
return;
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden('You can only add channels to your key.')); return stdResp.Forbidden('You can only add channels to your key.');
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -2,7 +2,7 @@ import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => { export const apiChannelManageActive = async (query: Map<string, string>, apiUserid: bigint, path: string): Promise<Response> => {
if (query.has('channel') && (query.get('channel') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) { if (query.has('channel') && (query.get('channel') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) {
if (apiUserid === BigInt(query.get('user') || '0')) { if (apiUserid === BigInt(query.get('user') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
@ -21,24 +21,22 @@ export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, qu
.execute('UPDATE allowed_channels SET active = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]) .execute('UPDATE allowed_channels SET active = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')])
.catch((e) => { .catch((e) => {
utils.commonLoggers.dbError('apiChannelManageActive.ts:25', 'update', e); utils.commonLoggers.dbError('apiChannelManageActive.ts:25', 'update', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
erroredOut = true; erroredOut = true;
}); });
// Exit this case now if catch errored // Exit this case now if catch errored
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to update channel.');
} else { } else {
// Send API key as response // Send API key as response
requestEvent.respondWith(stdResp.OK(`Successfully active to ${value}.`)); return stdResp.OK(`Successfully active to ${value}.`);
return;
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden('You can only manage your own channels.')); return stdResp.Forbidden('You can only manage your own channels.');
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -3,7 +3,7 @@ import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => { export const apiChannelManageBan = async (query: Map<string, string>, apiUserid: bigint, path: string): Promise<Response> => {
if ( if (
query.has('a') && query.has('a') &&
(query.get('a') || '').length > 0 && (query.get('a') || '').length > 0 &&
@ -29,24 +29,22 @@ export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query
.execute('UPDATE allowed_channels SET banned = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]) .execute('UPDATE allowed_channels SET banned = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')])
.catch((e) => { .catch((e) => {
utils.commonLoggers.dbError('apiChannelManageBan.ts:28', 'update', e); utils.commonLoggers.dbError('apiChannelManageBan.ts:28', 'update', e);
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
erroredOut = true; erroredOut = true;
}); });
// Exit this case now if catch errored // Exit this case now if catch errored
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError('Failed to update channel.');
} else { } else {
// Send OK to indicate modification was successful // Send OK to indicate modification was successful
requestEvent.respondWith(stdResp.OK(`Successfully active to ${value}.`)); return stdResp.OK(`Successfully active to ${value}.`);
return;
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden(stdResp.Strings.restricted)); return stdResp.Forbidden(stdResp.Strings.restricted);
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

View File

@ -3,7 +3,7 @@ import dbClient from '../../db/client.ts';
import stdResp from '../stdResponses.ts'; import stdResp from '../stdResponses.ts';
import utils from '../../utils.ts'; import utils from '../../utils.ts';
export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => { export const apiKeyManage = async (query: Map<string, string>, apiUserid: bigint, path: string): Promise<Response> => {
if (query.has('a') && (query.get('a') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) { if (query.has('a') && (query.get('a') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) {
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) { if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
// Flag to see if there is an error inside the catch // Flag to see if there is an error inside the catch
@ -28,24 +28,22 @@ export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<s
// Execute the DB modification // Execute the DB modification
await dbClient.execute('UPDATE all_keys SET ?? = ? WHERE userid = ?', [key, value, apiUserid]).catch((e) => { await dbClient.execute('UPDATE all_keys SET ?? = ? WHERE userid = ?', [key, value, apiUserid]).catch((e) => {
utils.commonLoggers.dbError('apiKeyManage.ts', 'update', e); utils.commonLoggers.dbError('apiKeyManage.ts', 'update', e);
requestEvent.respondWith(stdResp.InternalServerError(`Failed to ${key} to ${value}.`));
erroredOut = true; erroredOut = true;
}); });
// Exit this case now if catch errored // Exit this case now if catch errored
if (erroredOut) { if (erroredOut) {
return; return stdResp.InternalServerError(`Failed to ${key} to ${value}.`);
} else { } else {
// Send OK as response to indicate modification was successful // Send OK as response to indicate modification was successful
requestEvent.respondWith(stdResp.OK(`Successfully ${key} to ${value}.`)); return stdResp.OK(`Successfully ${key} to ${value}.`);
return;
} }
} else { } else {
// Alert API user that they shouldn't be doing this // Alert API user that they shouldn't be doing this
requestEvent.respondWith(stdResp.Forbidden('You can only manage your own key.')); return stdResp.Forbidden('You can only manage your own key.');
} }
} else { } else {
// Alert API user that they messed up // Alert API user that they messed up
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams)); return stdResp.BadRequest(stdResp.Strings.missingParams);
} }
}; };

2
src/mod.d.ts vendored
View File

@ -29,7 +29,7 @@ export type RollModifiers = {
export type QueuedRoll = { export type QueuedRoll = {
apiRoll: boolean; apiRoll: boolean;
api: { api: {
requestEvent: Deno.RequestEvent; request: Request;
channelId: bigint; channelId: bigint;
userId: bigint; userId: bigint;
}; };