Compare commits
7 Commits
e0eceffeb3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
26bef47403
|
|||
|
47df3dc55f
|
|||
|
994a7a7a58
|
|||
|
2ca8cc163d
|
|||
|
8e34e2ce24
|
|||
|
7352d0bb43
|
|||
|
291afd5eaa
|
@@ -5,6 +5,13 @@ jobs:
|
|||||||
Test-Build-Deploy:
|
Test-Build-Deploy:
|
||||||
name: Test, Build, and Deploy
|
name: Test, Build, and Deploy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
env:
|
||||||
|
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
CLOUDFLARE_PROJECT_NAME: ${{ vars.CLOUDFLARE_PROJECT_NAME }}
|
||||||
|
COMMIT_SHA: ${{ gitea.sha }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||||
@@ -26,14 +33,28 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Set Version as Var
|
||||||
|
run: |
|
||||||
|
curl https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$CLOUDFLARE_PROJECT_NAME \
|
||||||
|
-X PATCH \
|
||||||
|
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"deployment_configs": {
|
||||||
|
"production": {
|
||||||
|
"env_vars": {
|
||||||
|
"COMMIT_SHA": {
|
||||||
|
"type": "plain_text",
|
||||||
|
"value": "'"$COMMIT_SHA"'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
run: wrangler pages deploy public --project-name $CLOUDFLARE_PROJECT_NAME
|
run: wrangler pages deploy public --project-name $CLOUDFLARE_PROJECT_NAME
|
||||||
|
|
||||||
env:
|
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
CLOUDFLARE_PROJECT_NAME: ${{ vars.CLOUDFLARE_PROJECT_NAME }}
|
|
||||||
|
|
||||||
Sentry-Release:
|
Sentry-Release:
|
||||||
name: Create Sentry Release
|
name: Create Sentry Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -16,10 +16,18 @@ Sentry.init({
|
|||||||
useLocation,
|
useLocation,
|
||||||
useMatches,
|
useMatches,
|
||||||
}),
|
}),
|
||||||
Sentry.replayIntegration(),
|
Sentry.replayIntegration({
|
||||||
|
blockAllMedia: false,
|
||||||
|
maskAllInputs: false,
|
||||||
|
maskAllText: false,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
replaysOnErrorSampleRate: 1,
|
replaysOnErrorSampleRate: 1,
|
||||||
replaysSessionSampleRate: 0.02,
|
replaysSessionSampleRate: 0.02,
|
||||||
|
release:
|
||||||
|
document
|
||||||
|
.querySelector("meta[name='commit_sha']")
|
||||||
|
?.getAttribute("content") ?? undefined,
|
||||||
sendDefaultPii: true,
|
sendDefaultPii: true,
|
||||||
tracesSampleRate: 0.1,
|
tracesSampleRate: 0.1,
|
||||||
tunnel: "/api/st",
|
tunnel: "/api/st",
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ export async function loader({
|
|||||||
}): Promise<{ [k: string]: any }> {
|
}): Promise<{ [k: string]: any }> {
|
||||||
let data: { [k: string]: string } = {};
|
let data: { [k: string]: string } = {};
|
||||||
|
|
||||||
|
if (context.env.COMMIT_SHA) data.commit_sha = context.env.COMMIT_SHA;
|
||||||
if (context.data.current_user) data = { ...context.data.current_user };
|
if (context.data.current_user) data = { ...context.data.current_user };
|
||||||
if (context.env.REMIX_DSN) data.dsn = context.env.REMIX_DSN;
|
if (context.env.REMIX_DSN) data.dsn = context.env.REMIX_DSN;
|
||||||
if (context.data.nonce) data.nonce = context.data.nonce;
|
if (context.data.nonce) data.nonce = context.data.nonce;
|
||||||
@@ -202,6 +203,9 @@ function DocumentWrapper(props: {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<meta charSet="UTF-8" />
|
<meta charSet="UTF-8" />
|
||||||
|
{loaderData.commit_sha ? (
|
||||||
|
<meta name="commit_sha" content={loaderData.commit_sha} />
|
||||||
|
) : null}
|
||||||
{loaderData.dsn ? (
|
{loaderData.dsn ? (
|
||||||
<meta name="dsn" content={loaderData.dsn} />
|
<meta name="dsn" content={loaderData.dsn} />
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -35,29 +35,24 @@ export async function loader({ context }: { context: RequestContext }) {
|
|||||||
month = 12;
|
month = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventMemberQuery = await context.env.D1.prepare(
|
const batchStatements: D1Result<Record<string, any>>[] =
|
||||||
"SELECT id, name, roblox_id FROM et_members;",
|
await context.env.D1.batch([
|
||||||
).all();
|
context.env.D1.prepare("SELECT id, name, roblox_id FROM et_members;"),
|
||||||
const inactivityQuery: D1Result<Record<string, any>> =
|
context.env.D1.prepare(
|
||||||
await context.env.D1.prepare(
|
"SELECT decisions, json_extract(user, '$.id') AS uid FROM inactivity_notices WHERE (end BETWEEN DATE('now', 'start of month', '-1 month') AND DATE('now', 'start of month', '-1 day')) OR (start BETWEEN DATE('now', 'start of month', '-1 month') AND DATE('now', 'start of month', '-1 day'));",
|
||||||
"SELECT decisions, json_extract(user, '$.id') AS uid FROM inactivity_notices WHERE (end BETWEEN DATE('now', 'start of month', '-1 month') AND DATE('now', 'start of month', '-1 day')) OR (start BETWEEN DATE('now', 'start of month', '-1 month') AND DATE('now', 'start of month', '-1 day'));",
|
),
|
||||||
).all();
|
context.env.D1.prepare(
|
||||||
|
"SELECT approved, answered_at, created_by, performed_at, reached_minimum_player_count, type FROM events WHERE month = ? AND year = ?;",
|
||||||
|
).bind(month, year),
|
||||||
|
]);
|
||||||
|
|
||||||
const eventsQuery = await context.env.D1.prepare(
|
|
||||||
"SELECT approved, answered_at, created_by, performed_at, reached_minimum_player_count, type FROM events WHERE month = ? AND year = ?;",
|
|
||||||
)
|
|
||||||
.bind(month, year)
|
|
||||||
.all();
|
|
||||||
const memberMap = Object.fromEntries(
|
const memberMap = Object.fromEntries(
|
||||||
eventMemberQuery.results.map((entry) => {
|
batchStatements[0].results.map((e) => {
|
||||||
return [
|
return [e.id, { name: e.name, points: 0, roblox_id: e.roblox_id }];
|
||||||
entry.id,
|
|
||||||
{ name: entry.name, points: 0, roblox_id: entry.roblox_id },
|
|
||||||
];
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const event of eventsQuery.results as {
|
for (const event of batchStatements[2].results as {
|
||||||
approved: number;
|
approved: number;
|
||||||
answered_at: number;
|
answered_at: number;
|
||||||
created_by: string;
|
created_by: string;
|
||||||
@@ -77,10 +72,10 @@ export async function loader({ context }: { context: RequestContext }) {
|
|||||||
for (const member of Object.keys(memberMap))
|
for (const member of Object.keys(memberMap))
|
||||||
if (
|
if (
|
||||||
(memberMap[member].points < 50 ||
|
(memberMap[member].points < 50 ||
|
||||||
eventsQuery.results.filter(
|
batchStatements[2].results.filter(
|
||||||
(e) => e.type === "gamenight" && e.created_by === member,
|
(e) => e.type === "gamenight" && e.created_by === member,
|
||||||
).length === 0) &&
|
).length === 0) &&
|
||||||
!inactivityQuery.results.find(
|
!batchStatements[1].results.find(
|
||||||
(i) => i.uid === member && JSON.parse(i.decisions).et,
|
(i) => i.uid === member && JSON.parse(i.decisions).et,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -33,37 +33,31 @@ export async function loader({ context }: { context: RequestContext }) {
|
|||||||
|
|
||||||
if (!currentUser) throw new Response(null, { status: 401 });
|
if (!currentUser) throw new Response(null, { status: 401 });
|
||||||
|
|
||||||
const d1Promises = [];
|
const batchStatements = [];
|
||||||
|
|
||||||
for (const itemType of ["appeals", "inactivity_notices", "reports"])
|
for (const itemType of ["appeals", "inactivity_notices", "reports"]) {
|
||||||
d1Promises.push(
|
batchStatements.push(
|
||||||
context.env.D1.prepare(
|
context.env.D1.prepare(
|
||||||
`SELECT *
|
`SELECT * FROM ${itemType} WHERE json_extract(user, '$.id') = ? ORDER BY created_at DESC;`,
|
||||||
FROM ${itemType}
|
).bind(currentUser.id),
|
||||||
WHERE json_extract(user, '$.id') = ?
|
|
||||||
ORDER BY created_at DESC;`,
|
|
||||||
)
|
|
||||||
.bind(currentUser.id)
|
|
||||||
.all(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const settledPromises = await Promise.allSettled(d1Promises);
|
|
||||||
let etData: { [k: string]: any } | null = null;
|
|
||||||
|
|
||||||
if (currentUser.permissions & (1 << 3)) {
|
|
||||||
etData = await context.env.D1.prepare(
|
|
||||||
"SELECT name, points, roblox_id FROM et_members WHERE id = ?;",
|
|
||||||
)
|
|
||||||
.bind(currentUser.id)
|
|
||||||
.first();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
if (currentUser.permissions & (1 << 3))
|
||||||
etData,
|
batchStatements.push(
|
||||||
items: settledPromises.map((p) => {
|
context.env.D1.prepare(
|
||||||
if (p.status === "fulfilled") return p.value.results;
|
"SELECT name, points, roblox_id FROM et_members WHERE id = ? LIMIT 1;",
|
||||||
|
).bind(currentUser.id),
|
||||||
|
);
|
||||||
|
|
||||||
return null;
|
const batchResults = await context.env.D1.batch(batchStatements);
|
||||||
|
|
||||||
|
return {
|
||||||
|
etData: batchResults.at(3)?.results?.at(0) as { [k: string]: any } | null,
|
||||||
|
items: batchResults.map((r) => {
|
||||||
|
if (r.success) return r.results;
|
||||||
|
|
||||||
|
return [];
|
||||||
}) as any as ({ [k: string]: any }[] | null)[],
|
}) as any as ({ [k: string]: any }[] | null)[],
|
||||||
permissions: currentUser.permissions as number,
|
permissions: currentUser.permissions as number,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -383,6 +383,7 @@ async function setTheme(context: RequestContext) {
|
|||||||
export const onRequest = [
|
export const onRequest = [
|
||||||
Sentry.sentryPagesPlugin((context: RequestContext) => ({
|
Sentry.sentryPagesPlugin((context: RequestContext) => ({
|
||||||
dsn: context.env.FUNCTIONS_DSN,
|
dsn: context.env.FUNCTIONS_DSN,
|
||||||
|
release: context.env.COMMIT_SHA,
|
||||||
sendDefaultPii: true,
|
sendDefaultPii: true,
|
||||||
})),
|
})),
|
||||||
setAuth,
|
setAuth,
|
||||||
|
|||||||
@@ -194,8 +194,7 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
|
|
||||||
const reportId = `${Date.now()}${context.request.headers
|
const reportId = `${Date.now()}${context.request.headers
|
||||||
.get("cf-ray")
|
.get("cf-ray")
|
||||||
?.split("-")
|
?.replace("-", "")}${crypto.randomUUID().replaceAll("-", "")}`;
|
||||||
?.at(0)}${crypto.randomUUID().replaceAll("-", "")}`;
|
|
||||||
|
|
||||||
const { current_user: currentUser } = context.data;
|
const { current_user: currentUser } = context.data;
|
||||||
if (filesToProcess.length)
|
if (filesToProcess.length)
|
||||||
|
|||||||
@@ -12,18 +12,24 @@ export async function onRequestPost(context: RequestContext) {
|
|||||||
|
|
||||||
const sentryUrl = new URL(dsn);
|
const sentryUrl = new URL(dsn);
|
||||||
|
|
||||||
await fetch(`https://${sentryUrl.host}/api${sentryUrl.pathname}/envelope`, {
|
const resp = await fetch(
|
||||||
body: clonedRequest.body,
|
`https://${sentryUrl.host}/api${sentryUrl.pathname}/envelope/`,
|
||||||
headers: {
|
{
|
||||||
"content-type": "application/x-sentry-envelope",
|
body: clonedRequest.body,
|
||||||
"x-forwarded-for": context.request.headers.get(
|
headers: {
|
||||||
"cf-connecting-ip",
|
"content-type": "application/x-sentry-envelope",
|
||||||
) as string,
|
"x-forwarded-for": context.request.headers.get(
|
||||||
|
"cf-connecting-ip",
|
||||||
|
) as string,
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
},
|
},
|
||||||
method: "POST",
|
);
|
||||||
});
|
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(await resp.text(), {
|
||||||
status: 204,
|
headers: {
|
||||||
|
"content-type": resp.headers.get("content-type") || "text/plain",
|
||||||
|
},
|
||||||
|
status: resp.status,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user