Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions programmerbar-cms/sanity-typegen.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"path": "../www/src/**/*.{ts,tsx,js,jsx}",
"path": "../programmerbar-web/src/**/*.{ts,tsx,js,jsx}",
"schema": "schema.json",
"generates": "../www/sanity.types.ts"
}
"generates": "../programmerbar-web/sanity.types.ts"
}
4 changes: 4 additions & 0 deletions programmerbar-web/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ FEIDE_CLIENT_ID=""
FEIDE_CLIENT_SECRET=""
FEIDE_REDIRECT_URI="http://localhost:5173/auth/feide/callback"

# -- Slack
SLACK_VERIFICATION_TOKEN=""
SLACK_CHANNEL_ID=""

# -- API
PUBLIC_API_URL=http://localhost:8000
ADMIN_KEY=foobar
26 changes: 13 additions & 13 deletions programmerbar-web/sanity.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,24 +240,24 @@ export type AllSanitySchemaTypes =
| Slug
| SanityAssetSourceData;
export declare const internalGroqTypeReferenceTo: unique symbol;
// Source: ../www/src/lib/api/sanity/events.ts
// Source: ../programmerbar-web/src/lib/api/sanity/events.ts
// Variable: getEventsQuery
// Query: *[ _type == "happening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && date >= now()] | order(date asc) { _id, title, "slug": slug.current, date, registrationStart, body}[0...6]
// Query: *[ _type == "happening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && date >= now()] | order(date asc) { _id, title, "slug": slug.current, date, registrationStart, _createdAt, body}[0...6]
export type GetEventsQueryResult = Array<never>;
// Variable: getUpcomingEventsQuery
// Query: *[ _type == "happening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && date > now()] | order(date asc) { _id, title, "slug": slug.current, date, registrationStart, body}
// Query: *[ _type == "happening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && date > now()] | order(date asc) { _id, title, "slug": slug.current, date, registrationStart, _createdAt, body}
export type GetUpcomingEventsQueryResult = Array<never>;
// Variable: getEventBySlugQuery
// Query: *[ _type == "happening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && slug.current == $slug] { _id, title, "slug": slug.current, date, registrationStart, body}[0]
// Query: *[ _type == "happening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && slug.current == $slug] { _id, title, "slug": slug.current, date, registrationStart, _createdAt, body}[0]
export type GetEventBySlugQueryResult = null;
// Variable: getRepeatingEventsQuery
// Query: *[ _type == "repeatingHappening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current] | order(date asc) { _id, title, dayOfWeek, startTime, endTime, startDate, ignoredDates, endDate, interval, "slug": slug.current, body}
// Query: *[ _type == "repeatingHappening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current] | order(date asc) { _id, title, dayOfWeek, startTime, endTime, startDate, ignoredDates, endDate, interval, _createdAt, "slug": slug.current, body}
export type GetRepeatingEventsQueryResult = Array<never>;
// Variable: getRepeatingEventBySlugQuery
// Query: *[ _type == "repeatingHappening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && slug.current == $slug] { _id, title, dayOfWeek, startTime, endTime, startDate, ignoredDates, endDate, interval, "slug": slug.current, body}[0]
// Query: *[ _type == "repeatingHappening" && !(_id in path("drafts.**")) && "programmerbar" in organizers[]->slug.current && slug.current == $slug] { _id, title, dayOfWeek, startTime, endTime, startDate, ignoredDates, endDate, interval, _createdAt, "slug": slug.current, body}[0]
export type GetRepeatingEventBySlugQueryResult = null;

// Source: ../www/src/lib/api/sanity/products.ts
// Source: ../programmerbar-web/src/lib/api/sanity/products.ts
// Variable: getProductsQuery
// Query: *[_type == "product" && !(_id in path("drafts.**"))] { _id, sku, name, description, "productTypes": productType[]->{ _id, title }, isSoldOut, priceList, image, "producer": producer->name, volume, alcoholContent, variants,}
export type GetProductsQueryResult = Array<{
Expand Down Expand Up @@ -319,7 +319,7 @@ export type GetProductByIdQueryResult = {
variants: Array<string> | null;
} | null;

// Source: ../www/src/lib/api/sanity/programmerbar.ts
// Source: ../programmerbar-web/src/lib/api/sanity/programmerbar.ts
// Variable: query
// Query: *[_type == "studentGroup" && slug.current == $slug && !(_id in path('drafts.**'))] { _id, _createdAt, _updatedAt, name, groupType, "slug": slug.current, description, image, "members": members[] { role, "profile": profile->{ _id, name, picture, socials, }, }, "socials": socials { facebook, instagram, linkedin, email, } }[0]
export type QueryResult = null;
Expand All @@ -328,11 +328,11 @@ export type QueryResult = null;
import '@sanity/client';
declare module '@sanity/client' {
interface SanityQueries {
'*[\n\t_type == "happening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tdate >= now()\n] | order(date asc) {\n\t_id,\n\ttitle,\n\t"slug": slug.current,\n\tdate,\n\tregistrationStart,\n\tbody\n}[0...6]': GetEventsQueryResult;
'*[\n\t_type == "happening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tdate > now()\n] | order(date asc) {\n\t_id,\n\ttitle,\n\t"slug": slug.current,\n\tdate,\n\tregistrationStart,\n\tbody\n}': GetUpcomingEventsQueryResult;
'*[\n\t_type == "happening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tslug.current == $slug\n] {\n\t_id,\n\ttitle,\n\t"slug": slug.current,\n\tdate,\n\tregistrationStart,\n\tbody\n}[0]': GetEventBySlugQueryResult;
'*[\n\t_type == "repeatingHappening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current\n] | order(date asc) {\n\t_id,\n\ttitle,\n\tdayOfWeek,\n\tstartTime,\n\tendTime,\n\tstartDate,\n\tignoredDates,\n\tendDate,\n\tinterval,\n\t"slug": slug.current,\n\tbody\n}': GetRepeatingEventsQueryResult;
'*[\n\t_type == "repeatingHappening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tslug.current == $slug\n] {\n\t_id,\n\ttitle,\n\tdayOfWeek,\n\tstartTime,\n\tendTime,\n\tstartDate,\n\tignoredDates,\n\tendDate,\n\tinterval,\n\t"slug": slug.current,\n\tbody\n}[0]': GetRepeatingEventBySlugQueryResult;
'*[\n\t_type == "happening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tdate >= now()\n] | order(date asc) {\n\t_id,\n\ttitle,\n\t"slug": slug.current,\n\tdate,\n\tregistrationStart,\n\t_createdAt,\n\tbody\n}[0...6]': GetEventsQueryResult;
'*[\n\t_type == "happening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tdate > now()\n] | order(date asc) {\n\t_id,\n\ttitle,\n\t"slug": slug.current,\n\tdate,\n\tregistrationStart,\n\t_createdAt,\n\tbody\n}': GetUpcomingEventsQueryResult;
'*[\n\t_type == "happening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tslug.current == $slug\n] {\n\t_id,\n\ttitle,\n\t"slug": slug.current,\n\tdate,\n\tregistrationStart,\n\t_createdAt,\n\tbody\n}[0]': GetEventBySlugQueryResult;
'*[\n\t_type == "repeatingHappening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current\n] | order(date asc) {\n\t_id,\n\ttitle,\n\tdayOfWeek,\n\tstartTime,\n\tendTime,\n\tstartDate,\n\tignoredDates,\n\tendDate,\n\tinterval,\n\t_createdAt,\n\t"slug": slug.current,\n\tbody\n}': GetRepeatingEventsQueryResult;
'*[\n\t_type == "repeatingHappening" &&\n\t!(_id in path("drafts.**")) &&\n\t"programmerbar" in organizers[]->slug.current &&\n\tslug.current == $slug\n] {\n\t_id,\n\ttitle,\n\tdayOfWeek,\n\tstartTime,\n\tendTime,\n\tstartDate,\n\tignoredDates,\n\tendDate,\n\tinterval,\n\t_createdAt,\n\t"slug": slug.current,\n\tbody\n}[0]': GetRepeatingEventBySlugQueryResult;
'*[_type == "product" && !(_id in path("drafts.**"))] {\n _id,\n sku,\n name,\n description,\n "productTypes": productType[]->{\n _id,\n title\n },\n isSoldOut,\n priceList,\n image,\n "producer": producer->name,\n volume,\n alcoholContent,\n variants,\n}': GetProductsQueryResult;
'*[_type == "product" && _id == $id && !(_id in path("drafts.**"))] {\n _id,\n sku,\n name,\n description,\n "productTypes": productType[]->{\n _id,\n title\n },\n isSoldOut,\n priceList,\n image,\n "producer": producer->name,\n volume,\n alcoholContent,\n variants,\n}[0]': GetProductByIdQueryResult;
'*[_type == "studentGroup"\n && slug.current == $slug\n && !(_id in path(\'drafts.**\'))] {\n _id,\n _createdAt,\n _updatedAt,\n name,\n groupType,\n "slug": slug.current,\n description,\n image,\n "members": members[] {\n role,\n "profile": profile->{\n _id,\n name,\n picture,\n socials,\n },\n },\n "socials": socials {\n facebook,\n instagram,\n linkedin,\n email,\n }\n }[0]': QueryResult;
Expand Down
65 changes: 65 additions & 0 deletions programmerbar-web/src/routes/(app)/slack-command/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { env } from '$env/dynamic/private';
import { STATUS, StatusService } from '$lib/services/status.service';
import type { RequestHandler } from './$types';

type Command = (typeof COMMAND)[keyof typeof COMMAND];

const COMMAND = {
OPEN: '/åpent',
CLOSED: '/stengt',
PRIVATE: '/privat',
STATUS: '/skjer'
} as const;

const getStatusNumber = (command: Command) => {
switch (command) {
case COMMAND.OPEN:
return STATUS.OPEN;
case COMMAND.CLOSED:
return STATUS.CLOSED;
case COMMAND.PRIVATE:
return STATUS.PRIVATE;
default:
return STATUS.PRIVATE;
}
};

const isCommand = (command: string | null): command is Command =>
Object.values(COMMAND).includes(command as Command);

export const POST: RequestHandler = async ({ locals, request }) => {
const formData = await request.formData();
const command = formData.get('command') as string;

if (!isCommand(command)) {
return new Response('Invalid command', { status: 400 });
}

if (command === COMMAND.STATUS) {
const status = await locals.statusService.get();
const text = StatusService.getMessage(status);

return Response.json({
response_type: 'in_channel',
text
});
}

if (formData.get('token') !== env.SLACK_VERIFICATION_TOKEN) {
return new Response('Invalid token', { status: 403 });
}

if (formData.get('channel_id') !== env.SLACK_CHANNEL_ID) {
return new Response('Invalid channel', { status: 403 });
}

const status = getStatusNumber(command);
await locals.statusService.set(status);

const text = StatusService.getMessage(status);

return Response.json({
response_type: 'in_channel',
text
});
};
11 changes: 9 additions & 2 deletions programmerbar-web/src/worker-configuration.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable */
// Generated by Wrangler by running `wrangler types` (hash: 68cec6a8a697c1b92839bb21378557b2)
// Generated by Wrangler by running `wrangler types` (hash: f0da2bcbcf1a9ec47f8a610cea1b9e63)
// Runtime types generated with workerd@1.20250816.0 2025-08-19 nodejs_compat
declare namespace Cloudflare {
interface Env {
Expand All @@ -8,6 +8,8 @@ declare namespace Cloudflare {
FEIDE_CLIENT_ID: string;
FEIDE_CLIENT_SECRET: string;
FEIDE_REDIRECT_URI: string;
PUBLIC_API_URL: string;
ADMIN_KEY: string;
BUCKET: R2Bucket;
DB: D1Database;
ASSETS: Fetcher;
Expand All @@ -22,7 +24,12 @@ declare namespace NodeJS {
extends StringifyValues<
Pick<
Cloudflare.Env,
'RESEND_API_KEY' | 'FEIDE_CLIENT_ID' | 'FEIDE_CLIENT_SECRET' | 'FEIDE_REDIRECT_URI'
| 'RESEND_API_KEY'
| 'FEIDE_CLIENT_ID'
| 'FEIDE_CLIENT_SECRET'
| 'FEIDE_REDIRECT_URI'
| 'PUBLIC_API_URL'
| 'ADMIN_KEY'
>
> {}
}
Expand Down