joel behöver en python

This commit is contained in:
eric
2026-03-12 21:43:21 +01:00
parent 3f2dadeb5e
commit 988de13e1e
7 changed files with 226 additions and 16 deletions

View File

@@ -31,6 +31,23 @@ const logger = createLogger("Web");
const pendingStates = new Map<string, { createdAt: number }>();
const STATE_EXPIRY_MS = 5 * 60 * 1000;
function getErrorMessage(error: unknown): string {
if (error instanceof Error) {
return error.message;
}
return typeof error === "string" ? error : "Unknown error";
}
function escapeHtml(value: string): string {
return value
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll("\"", "&quot;")
.replaceAll("'", "&#39;");
}
export function createWebServer(client: BotClient) {
return new Elysia()
.use(html())
@@ -113,8 +130,16 @@ export function createWebServer(client: BotClient) {
return new Response(null, { status: 302, headers });
} catch (err) {
logger.error("OAuth callback failed", err);
return htmlResponse("<h1>Authentication failed</h1>", 500);
const errorMessage = getErrorMessage(err);
logger.error("OAuth callback failed", {
codePresent: !!code,
errorMessage,
state,
});
return htmlResponse(
`<h1>Authentication failed</h1><p>${escapeHtml(errorMessage)}</p>`,
500
);
}
})
.post("/auth/logout", async ({ request }) => {

View File

@@ -19,6 +19,12 @@ const userGuildsCache = new Map<string, CacheEntry<DiscordGuild[]>>();
const inFlightUserRequests = new Map<string, Promise<DiscordUser>>();
const inFlightGuildRequests = new Map<string, Promise<DiscordGuild[]>>();
async function throwDiscordApiError(action: string, response: Response): Promise<never> {
const bodyText = (await response.text()).slice(0, 500);
const detail = bodyText ? ` ${bodyText}` : "";
throw new Error(`${action} failed (${response.status} ${response.statusText}).${detail}`);
}
function getFromCache<T>(cache: Map<string, CacheEntry<T>>, key: string): T | null {
const entry = cache.get(key);
if (!entry) {
@@ -91,7 +97,7 @@ export async function exchangeCode(code: string): Promise<TokenResponse> {
});
if (!response.ok) {
throw new Error(`Failed to exchange code: ${response.statusText}`);
await throwDiscordApiError("OAuth code exchange", response);
}
return response.json();
@@ -112,7 +118,7 @@ export async function refreshToken(refreshToken: string): Promise<TokenResponse>
});
if (!response.ok) {
throw new Error(`Failed to refresh token: ${response.statusText}`);
await throwDiscordApiError("OAuth token refresh", response);
}
return response.json();
@@ -137,7 +143,7 @@ export async function getUser(accessToken: string): Promise<DiscordUser> {
});
if (!response.ok) {
throw new Error(`Failed to get user: ${response.statusText}`);
await throwDiscordApiError("Discord get user", response);
}
const user = await response.json();
@@ -173,7 +179,7 @@ export async function getUserGuilds(accessToken: string): Promise<DiscordGuild[]
});
if (!response.ok) {
throw new Error(`Failed to get user guilds: ${response.statusText}`);
await throwDiscordApiError("Discord get user guilds", response);
}
const guilds = await response.json();