diff options
Diffstat (limited to 'src/pages')
| -rw-r--r-- | src/pages/404.astro | 67 | ||||
| -rw-r--r-- | src/pages/api/update.ts | 200 | ||||
| -rw-r--r-- | src/pages/history/[date].astro | 13 | ||||
| -rw-r--r-- | src/pages/index.astro | 11 | ||||
| -rw-r--r-- | src/pages/privacy.astro | 40 |
5 files changed, 0 insertions, 331 deletions
diff --git a/src/pages/404.astro b/src/pages/404.astro deleted file mode 100644 index 4db6121..0000000 --- a/src/pages/404.astro +++ /dev/null @@ -1,67 +0,0 @@ ---- ---- - -<html lang="en"> - <head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="shortcut icon" href="/favicon.ico"> - <title>404 - Page Not Found | geshem.space</title> - <style> - body { - margin: 0; - padding: 0; - background-color: #1a1a1a; - color: white; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - text-align: center; - } - - .container { - max-width: 500px; - } - - h1 { - font-size: 6rem; - margin: 0; - font-weight: bold; - opacity: 0.8; - } - - h2 { - font-size: 1.5rem; - margin: 1rem 0; - font-weight: normal; - } - - p { - margin: 1rem 0; - opacity: 0.7; - line-height: 1.5; - } - - a { - color: #3498db; - text-decoration: none; - font-weight: 500; - } - - a:hover { - text-decoration: underline; - } - </style> - </head> - <body> - <div class="container"> - <h1>404</h1> - <h2>Page Not Found</h2> - <p>The page you're looking for doesn't exist.</p> - <p><a href="/">← Back to Rain Radar</a></p> - </div> - </body> -</html>
\ No newline at end of file diff --git a/src/pages/api/update.ts b/src/pages/api/update.ts deleted file mode 100644 index 88dfa3c..0000000 --- a/src/pages/api/update.ts +++ /dev/null @@ -1,200 +0,0 @@ -import type { APIRoute } from 'astro'; - -export const prerender = false; - -interface ImageData { - [key: string]: string[]; -} - -interface CloudflareEnv { - BASE_URL: string; - AUTH_USER: string; - AUTH_PASS: string; - BUCKET_NAME: string; - SCHEDULED?: boolean; -} - -class GeshemUpdate { - private bucket: R2Bucket; - private env: CloudflareEnv; - - constructor(bucket: R2Bucket, env: CloudflareEnv) { - this.bucket = bucket; - this.env = env; - } - - private async authenticate(request: Request): Promise<Request> { - const headers = new Headers(request.headers); - const credentials = btoa(`${this.env.AUTH_USER}:${this.env.AUTH_PASS}`); - headers.set('Authorization', `Basic ${credentials}`); - - return new Request(request.url, { - method: request.method, - headers, - body: request.body - }); - } - - private async getLatestImages(): Promise<string[]> { - const authenticatedRequest = await this.authenticate(new Request(this.env.BASE_URL)); - const response = await fetch(authenticatedRequest); - const html = await response.text(); - - const regex = /radar280comp_\d+\.png/g; - const matches = html.match(regex) || []; - const uniqueImages = [...new Set(matches)]; - - return uniqueImages.sort().slice(-10); - } - - private async getLatestBucketKeys(): Promise<string[]> { - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); - const yesterdayStr = yesterday.toISOString().slice(0, 10).replace(/-/g, ''); - - try { - const objects = await this.bucket.list({ - prefix: 'imgs/', - startAfter: `imgs/${yesterdayStr}` - }); - - return objects.objects.map(obj => obj.key); - } catch (error) { - console.error('Error listing bucket objects:', error); - return []; - } - } - - private async fetchMissingImages(): Promise<boolean> { - const images = await this.getLatestImages(); - const s3Images = await this.getLatestBucketKeys(); - let updated = false; - - for (const img of images) { - const key = this.keyFromFilename(img); - if (!s3Images.includes(key)) { - await this.fetchImage(img, key); - updated = true; - } - } - - return updated; - } - - private async fetchImage(imgName: string, key: string): Promise<void> { - console.log(`Downloading ${imgName} from web server`); - - const imageUrl = `${this.env.BASE_URL}/${imgName}`; - const authenticatedRequest = await this.authenticate(new Request(imageUrl)); - const response = await fetch(authenticatedRequest); - - if (!response.ok) { - throw new Error(`Failed to fetch image: ${response.statusText}`); - } - - const imageData = await response.arrayBuffer(); - - console.log(`Uploading to ${key}`); - await this.bucket.put(key, imageData, { - httpMetadata: { - contentType: 'image/png', - cacheControl: 'public, max-age=31536000' - } - }); - } - - private keyFromFilename(filename: string): string { - const [name, dateStr] = filename.split('.')[0].split('_'); - const res = 280; - - // Parse date: YYYYMMDDHHMM - const year = dateStr.slice(0, 4); - const month = dateStr.slice(4, 6); - const day = dateStr.slice(6, 8); - const hour = dateStr.slice(8, 10); - const minute = dateStr.slice(10, 12); - - const d = `${year}${month}${day}`; - const t = `${hour}${minute}`; - - 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); - throw error; - } - } -} - -export const GET: APIRoute = async ({ platform, request }) => { - // This endpoint should only be accessible via Cloudflare Cron - const cron = request.headers.get('CF-Cron'); - if (!cron) { - return new Response('Unauthorized', { status: 401 }); - } - - try { - const env = platform?.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; - - if (!bucket) { - return new Response('R2 bucket not configured', { status: 500 }); - } - - const updater = new GeshemUpdate(bucket, env); - const result = await updater.run(); - - return new Response(JSON.stringify({ - message: `SUCCESS: ${result}`, - timestamp: new Date().toISOString() - }), { - status: 200, - headers: { - 'Content-Type': 'application/json' - } - }); - - } catch (error) { - console.error('Error in update handler:', error); - return new Response(JSON.stringify({ - message: 'ERROR', - error: 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/history/[date].astro b/src/pages/history/[date].astro deleted file mode 100644 index 0a78f9f..0000000 --- a/src/pages/history/[date].astro +++ /dev/null @@ -1,13 +0,0 @@ ---- -import Layout from '../../layouts/Layout.astro'; -import { Geshem } from '../../components/Geshem'; -import '../../styles/global.css'; - -export const prerender = false; - -const { date } = Astro.params; ---- - -<Layout title="Geshem - Rain Radar History" description="Israel Rain Radar History"> - <Geshem client:load date={date} /> -</Layout>
\ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro deleted file mode 100644 index 5b08f18..0000000 --- a/src/pages/index.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -import Layout from "../layouts/Layout.astro"; -import { Geshem } from "../components/Geshem"; -import "../styles/global.css"; - -const { date } = Astro.params; ---- - -<Layout> - <Geshem client:load date={date} /> -</Layout> diff --git a/src/pages/privacy.astro b/src/pages/privacy.astro deleted file mode 100644 index d01a26b..0000000 --- a/src/pages/privacy.astro +++ /dev/null @@ -1,40 +0,0 @@ ---- - ---- - -<html lang="en"> - <head> - <meta charset="utf-8" /> - <meta - name="viewport" - content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" - /> - <meta name="apple-mobile-web-app-title" content="Geshem" /> - <meta name="apple-mobile-web-app-capable" content="yes" /> - <meta name="theme-color" content="#000000" /> - <link rel="shortcut icon" href="/favicon.ico" /> - <link rel="apple-touch-icon" href="/apple-touch-icon.png" /> - <link rel="manifest" href="/manifest.json" /> - <title>Privacy Policy | geshem.space</title> - <script src="https://cdn.usefathom.com/script.js" data-site="MBXPLVRM" defer - ></script> - <style> - body { - overflow: hidden; - position: absolute; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - font-family: sans-serif; - background-color: #1a1a1a; - color: white; - margin: 0; - } - </style> - </head> - <body> - <h1>We do not collect any data.</h1> - </body> -</html> |
