diff --git a/src/app.css b/src/app.css index a7f6844..89f75e8 100644 --- a/src/app.css +++ b/src/app.css @@ -7,20 +7,12 @@ src: url('/fonts/inter-v18-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ } -* { - --color-primary-a0: #ffffff; - --color-primary-a10: #e1e6fe; - --color-primary-a20: #c2cdfd; - --color-primary-a30: #a1b5fb; - --color-primary-a40: #7d9df9; - --color-primary-a50: #5087f6; - --color-primary-a60: #436bc0; - --color-primary-a70: #364f8c; - --color-primary-a80: #28365c; - --color-primary-a90: #191e2f; - --color-primary-a100: #000000; - --text-color: black; +pre { + max-width: 100%; + overflow: scroll; +} +* { box-sizing: border-box; font-size: inherit; } @@ -29,13 +21,13 @@ html, body { position: relative; margin: 0; padding: 0; - background-color: white; font-size: 1rem; + background-color: var(--tg-theme-bg-color); } p, a, h1, h2, h3, h4, h5, h6 { font-family: Inter, Arial, sans-serif; - color: var(--text-color); + color: var(--tg-theme-text-color); } h1, h2, h3, h4, h5, h6 { @@ -58,3 +50,29 @@ svg { max-width: 100%; height: auto; } + +a { + color: var(--tg-theme-link-color); +} + +button { + padding: 0.45rem 0.65rem; + + background-color: var(--tg-theme-button-color); + color: var(--tg-theme-button-text-color); + font-size: 1.35rem; + border: none; + + &:disabled { + filter: grayscale(1.0); + } +} + +label { + color: var(--tg-theme-text-color); +} + +input { + color: var(--tg-theme-text-color); + background-color: var(--tg-theme-secondary-bg-color); +} \ No newline at end of file diff --git a/src/hooks.client.js b/src/hooks.client.js index 51625bf..d91fbfc 100644 --- a/src/hooks.client.js +++ b/src/hooks.client.js @@ -1,4 +1,4 @@ -import {initializePocketBase} from "$lib/pocketbase.js"; +import { initializePocketBase } from "$lib/pocketbase.js"; export const init = async () => { initializePocketBase() diff --git a/src/lib/components/ContainerGridSingle.svelte b/src/lib/components/ContainerGridSingle.svelte index d8dc5db..3cce760 100644 --- a/src/lib/components/ContainerGridSingle.svelte +++ b/src/lib/components/ContainerGridSingle.svelte @@ -13,6 +13,8 @@ diff --git a/src/lib/components/EventList.svelte b/src/lib/components/EventList.svelte index 1cf288e..18e1381 100644 --- a/src/lib/components/EventList.svelte +++ b/src/lib/components/EventList.svelte @@ -20,8 +20,6 @@ diff --git a/src/lib/components/EventRegisterButton.svelte b/src/lib/components/EventRegisterButton.svelte index e69de29..762d1a8 100644 --- a/src/lib/components/EventRegisterButton.svelte +++ b/src/lib/components/EventRegisterButton.svelte @@ -0,0 +1,39 @@ + + +{#if eventId} + {#if telegram?.initData} +
+ + +
+ +
+
+ +
+
+ +
+
+ {:else} +

Bitte öffne diese Mini App im Telegram Bot um dich anzumelden! Öffnen

+ {/if} +{:else} +

Invalide Event-ID

+{/if} + + \ No newline at end of file diff --git a/src/lib/components/FooterNavigation.svelte b/src/lib/components/FooterNavigation.svelte index b578873..4320b33 100644 --- a/src/lib/components/FooterNavigation.svelte +++ b/src/lib/components/FooterNavigation.svelte @@ -7,12 +7,15 @@
  • Start
  • -
  • +
  • Events
  • Regeln
  • + @@ -29,15 +32,17 @@ li { transition: border-bottom-color linear 0.2s; padding: 0.6rem 0.45rem; - border-bottom: 3px var(--color-primary-a80) solid; + border-bottom: 3px var(--tg-theme-button-color) solid; + filter: grayscale(0.8); &.selected { - border-bottom: 3px var(--color-primary-a40) solid; + filter: none; + border-bottom: 3px var(--tg-theme-button-color) solid; } } a { - font-size: 1.5rem; + font-size: 1.35rem; text-decoration: none; } \ No newline at end of file diff --git a/src/lib/telegram.svelte.js b/src/lib/telegram.svelte.js index e69de29..d44c383 100644 --- a/src/lib/telegram.svelte.js +++ b/src/lib/telegram.svelte.js @@ -0,0 +1,34 @@ +const telegram = $state({user: null, initData: null}) +let checkCount = $state(0); + +export function useTelegram() { + const checkTelegramUser = () => { + checkCount = checkCount+1; + if (typeof window === 'undefined') { + setTimeout(checkTelegramUser, 100); + return; + } + telegram.initData = Telegram?.WebApp?.initData; + console.log(Telegram?.WebApp); + if (!telegram.initData) { + setTimeout(checkTelegramUser, 100); + console.warn("initData could not be loaded"); + return; + } + const searchParams = new URLSearchParams(telegram.initData); + const tempUser = searchParams.get('user'); + if (!tempUser) { + console.warn("User could not be loaded"); + return; + } + telegram.user = JSON.parse(tempUser); + } + + $effect(() => { + setTimeout(checkTelegramUser, 100); + }); + + return telegram +} + + diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 728b816..f95c60d 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -3,12 +3,6 @@ import FooterNavigation from "$lib/components/FooterNavigation.svelte"; import ContainerGridSingle from "$lib/components/ContainerGridSingle.svelte"; const { children } = $props(); - - $effect(() => { - Telegram?.WebApp?.ready(); - Telegram?.WebApp?.setBackgroundColor('FFFFFF'); - }); - @@ -23,5 +17,6 @@ diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 4d6d804..e792fc2 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,25 +1,19 @@
    - {#if user} + {#if telegram && telegram?.user} + {@const user = telegram.user} -

    Hallo {user.first_name}!

    +

    Hallo {user?.first_name}!

    {:else}

    Hallo Besucher!

    {/if} -

    Du befinest dich auf der Anmeldeseite des Kölner Stammtischs. Schau dir die unteren Menüpunkte an, falls du mehr erfahren möchtest.

    +

    Du befindest dich auf der Mini App des Kölner Stammtischs. Schau dir die unteren Menüpunkte an, falls du mehr erfahren möchtest.

    diff --git a/src/routes/debug/+page.svelte b/src/routes/debug/+page.svelte index e69de29..cfc1bcf 100644 --- a/src/routes/debug/+page.svelte +++ b/src/routes/debug/+page.svelte @@ -0,0 +1,8 @@ + + +
    +    {JSON.stringify(telegram.user, null, 4)}
    +
    \ No newline at end of file diff --git a/src/routes/events/[slug]/+page.server.js b/src/routes/events/[slug]/+page.server.js index e69de29..30bd42a 100644 --- a/src/routes/events/[slug]/+page.server.js +++ b/src/routes/events/[slug]/+page.server.js @@ -0,0 +1,34 @@ +import { subtle } from 'node:crypto'; +import {PRIVATE_TELEGRAM_BOT_ID, PRIVATE_TELEGRAM_PUBLIC_KEY} from "$env/static/private"; + +export const actions = { + register: async ({ request }) => { + const formData = await request.formData(); + if (!formData) return { success: false, error: "No valid form data was provided" }; + + const initDataUrlEncoded = formData.get('init-data'); + if (!initDataUrlEncoded) return { success: false, error: "No valid form data was provided" }; + + const eventId = formData.get('event-id'); + if (!eventId) return { success: false, error: "Missing event-id" }; + + const dataArrayParams = new URLSearchParams(initDataUrlEncoded) + const initDataArray = [...dataArrayParams]; + const signature = dataArrayParams.get('signature'); + if (!signature) return { success: false, error: "No signature was provided" }; + initDataArray.sort((d1, d2) => d1[0].charCodeAt(0) - d2[0].charCodeAt(0)); + + const checkString = initDataArray.reduce((acc, currentValue) => { + if (['signature', 'hash'].includes(currentValue[0])) return acc; + acc.push(currentValue.join("=")) + return acc; + }, [`${PRIVATE_TELEGRAM_BOT_ID}:WebAppData`]).join("\n") + + const algo = 'Ed25519'; + const key = await subtle.importKey("raw", Buffer.from(PRIVATE_TELEGRAM_PUBLIC_KEY, 'hex'), algo, false, ['verify']); + const validSignature = await subtle.verify(algo, key, Buffer.from(signature, 'base64url'), Buffer.from(checkString)); + if (!validSignature) return { success: false, error: "Invalid signature" } + + return { success: true, error: null } + } +} \ No newline at end of file diff --git a/src/routes/events/[slug]/+page.svelte b/src/routes/events/[slug]/+page.svelte index 782584f..e17578e 100644 --- a/src/routes/events/[slug]/+page.svelte +++ b/src/routes/events/[slug]/+page.svelte @@ -5,9 +5,12 @@ import {Tile} from 'ol/layer'; import {useGeographic} from "ol/proj"; import {onMount} from "svelte"; + import EventRegisterButton from "$lib/components/EventRegisterButton.svelte"; + import {useTelegram} from "$lib/telegram.svelte.js"; const { data } = $props(); const { event } = data; + const telegram = useTelegram(); let mapRef; @@ -43,14 +46,36 @@

    {event?.description ?? "No description"}

    {/if} + {#if event?.start} + {@const date = new Date(event.start)} +
    +

    Wann?

    + {#if telegram?.user?.language_code} +

    {date.toLocaleDateString(telegram.user.language_code, {dateStyle: 'long'})}
    + {date.toLocaleTimeString(telegram.user.language_code, {timeStyle: 'long'})}

    + {:else} +

    {date.toLocaleDateString('en', {dateStyle: 'long'})}
    + {date.toLocaleTimeString('en', {timeStyle: 'long'})}

    + {/if} +
    + {/if} +
    -

    Location

    +

    Wo?

    {event?.expand?.location?.name}
    - {event?.expand?.location?.address} + {#each event?.expand?.location?.address.split(', ') as part} + {part}
    + {/each}

    + + + +
    +

    Anmeldung

    +
    \ No newline at end of file diff --git a/src/routes/rules/+page.svelte b/src/routes/rules/+page.svelte index 197d9ac..d0d47de 100644 --- a/src/routes/rules/+page.svelte +++ b/src/routes/rules/+page.svelte @@ -5,6 +5,7 @@