diff options
| author | Yuval Adam <_@yuv.al> | 2025-09-24 12:44:27 +0200 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2025-09-24 12:44:27 +0200 |
| commit | 50d2992168223b32eeb90a6c9afc545136747b50 (patch) | |
| tree | 16aa098f4b6dcad08123113fa8747613573d45dc /src | |
| parent | 1076752caa8f2f3804c0d79c7db937e88ecdf205 (diff) | |
Add /imgs/ endpoint and fix type errors
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.ts | 2 | ||||
| -rw-r--r-- | src/functions/scheduled.ts | 22 | ||||
| -rw-r--r-- | src/pages/api/imgs.ts | 76 | ||||
| -rw-r--r-- | src/pages/api/update.ts | 29 |
4 files changed, 81 insertions, 48 deletions
diff --git a/src/config.ts b/src/config.ts index 615e6d4..8bce091 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,7 +7,7 @@ export const IMAGES_BASE_URL = PRODUCTION ? "https://imgs.geshem.space" : ""; export const MAPBOX_ACCESS_TOKEN = "pk.eyJ1IjoieXV2YWRtIiwiYSI6ImNpcnMxbzBuaTAwZWdoa25oczlzZmkwbHcifQ.UHtLngbKm9O8945pJm23Nw"; -export const IMAGE_COORDINATES: [number, number][] = [ +export const IMAGE_COORDINATES: [[number, number], [number, number], [number, number], [number, number]] = [ [31.7503896894, 34.4878044232], [37.8574239563, 34.5078463729], [37.7157066403, 29.4538271687], diff --git a/src/functions/scheduled.ts b/src/functions/scheduled.ts index 5aa3fa0..ae43469 100644 --- a/src/functions/scheduled.ts +++ b/src/functions/scheduled.ts @@ -8,9 +8,6 @@ interface Env { IMGS_BUCKET: R2Bucket; } -interface ImageData { - [key: string]: string[]; -} class GeshemUpdate { private bucket: R2Bucket; @@ -118,29 +115,10 @@ class GeshemUpdate { return `imgs/${d}/${t}/${res}.png`; } - private async generateJson(): Promise<void> { - const latestKeys = await this.getLatestBucketKeys(); - const keys = latestKeys - .filter(key => key.endsWith('280.png')) - .sort() - .slice(-10); - - const index: ImageData = { '280': keys }; - - await this.bucket.put('imgs.json', JSON.stringify(index), { - httpMetadata: { - contentType: 'application/json', - cacheControl: 'public, max-age=60' - } - }); - } async run(): Promise<string> { try { const updated = await this.fetchMissingImages(); - if (updated) { - await this.generateJson(); - } return `Updated: ${updated}`; } catch (error) { console.error('Error in GeshemUpdate.run():', error); diff --git a/src/pages/api/imgs.ts b/src/pages/api/imgs.ts new file mode 100644 index 0000000..378d36d --- /dev/null +++ b/src/pages/api/imgs.ts @@ -0,0 +1,76 @@ +import type { APIRoute } from 'astro'; + +export const prerender = false; + +interface CloudflareEnv { + IMGS_BUCKET: R2Bucket; +} + +export const GET: APIRoute = async ({ locals }) => { + try { + const env = (locals as any).runtime?.env; + + if (!env?.IMGS_BUCKET) { + return new Response('R2 bucket not configured', { status: 500 }); + } + + const bucket = env.IMGS_BUCKET; + + // Get the latest images from yesterday onwards + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); + const yesterdayStr = yesterday.toISOString().slice(0, 10).replace(/-/g, ''); + + const objects = await bucket.list({ + prefix: 'imgs/', + startAfter: `imgs/${yesterdayStr}` + }); + + // Filter for 280.png files and get the latest 10 + const imageKeys = objects.objects + .map((obj: any) => obj.key) + .filter((key: string) => key.endsWith('/280.png')) + .sort() + .slice(-10); + + // Transform keys to full URLs + const images = imageKeys.map((key: string) => { + // Extract date/time from path: imgs/20250622/0930/280.png + const pathParts = key.split('/'); + const date = pathParts[1]; + const time = pathParts[2]; + const filename = pathParts[3]; + + return { + path: key, + url: `https://imgs.geshem.space/${date}/${time}/${filename}`, + date: date, + time: time + }; + }); + + return new Response(JSON.stringify({ + images: images, + count: images.length, + timestamp: new Date().toISOString() + }), { + status: 200, + headers: { + 'Content-Type': 'application/json', + 'Cache-Control': 'public, max-age=60, s-maxage=60' + } + }); + + } catch (error) { + console.error('Error fetching images:', error); + return new Response(JSON.stringify({ + error: 'Failed to fetch images', + message: error instanceof Error ? error.message : 'Unknown error' + }), { + status: 500, + headers: { + 'Content-Type': 'application/json' + } + }); + } +};
\ No newline at end of file diff --git a/src/pages/api/update.ts b/src/pages/api/update.ts index 88dfa3c..ca60384 100644 --- a/src/pages/api/update.ts +++ b/src/pages/api/update.ts @@ -2,9 +2,6 @@ import type { APIRoute } from 'astro'; export const prerender = false; -interface ImageData { - [key: string]: string[]; -} interface CloudflareEnv { BASE_URL: string; @@ -12,6 +9,7 @@ interface CloudflareEnv { AUTH_PASS: string; BUCKET_NAME: string; SCHEDULED?: boolean; + [key: string]: any; } class GeshemUpdate { @@ -120,29 +118,10 @@ class GeshemUpdate { return `imgs/${d}/${t}/${res}.png`; } - private async generateJson(): Promise<void> { - const latestKeys = await this.getLatestBucketKeys(); - const keys = latestKeys - .filter(key => key.endsWith('280.png')) - .sort() - .slice(-10); - - const index: ImageData = { '280': keys }; - - await this.bucket.put('imgs.json', JSON.stringify(index), { - httpMetadata: { - contentType: 'application/json', - cacheControl: 'public, max-age=60' - } - }); - } async run(): Promise<string> { try { const updated = await this.fetchMissingImages(); - if (updated) { - await this.generateJson(); - } return `Updated: ${updated}`; } catch (error) { console.error('Error in GeshemUpdate.run():', error); @@ -151,7 +130,7 @@ class GeshemUpdate { } } -export const GET: APIRoute = async ({ platform, request }) => { +export const GET: APIRoute = async ({ locals, request }) => { // This endpoint should only be accessible via Cloudflare Cron const cron = request.headers.get('CF-Cron'); if (!cron) { @@ -159,14 +138,14 @@ export const GET: APIRoute = async ({ platform, request }) => { } try { - const env = platform?.env as unknown as CloudflareEnv; + const env = (locals as any).runtime?.env as unknown as CloudflareEnv; if (!env?.BASE_URL || !env?.AUTH_USER || !env?.AUTH_PASS) { return new Response('Missing environment variables', { status: 500 }); } // Get R2 bucket (this would be configured in your Cloudflare Workers environment) - const bucket = env.BUCKET_NAME ? platform?.env[env.BUCKET_NAME] as R2Bucket : null; + const bucket = env.BUCKET_NAME ? env[env.BUCKET_NAME] as R2Bucket : null; if (!bucket) { return new Response('R2 bucket not configured', { status: 500 }); |
