feat: added rss
fc8c359e
4 file(s) · +90 −0
| 6 | 6 | "name": "steve-photo-svelte", |
|
| 7 | 7 | "dependencies": { |
|
| 8 | 8 | "exifr": "^7.1.3", |
|
| 9 | + | "feed": "^5.2.0", |
|
| 9 | 10 | "from": "^0.1.7", |
|
| 10 | 11 | "import": "^0.0.6", |
|
| 11 | 12 | }, |
|
| 300 | 301 | ||
| 301 | 302 | "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], |
|
| 302 | 303 | ||
| 304 | + | "feed": ["feed@5.2.0", "", { "dependencies": { "xml-js": "^1.6.11" } }, "sha512-hgH6CCb+7+0c8PBlakI2KubG6R+Rb1MhpNcdvqUXZTBwBHf32piwY255diAkAmkGZ6AWlywOU88AkOgP9q8Rdw=="], |
|
| 305 | + | ||
| 303 | 306 | "from": ["from@0.1.7", "", {}, "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g=="], |
|
| 304 | 307 | ||
| 305 | 308 | "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], |
|
| 372 | 375 | ||
| 373 | 376 | "sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="], |
|
| 374 | 377 | ||
| 378 | + | "sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="], |
|
| 379 | + | ||
| 375 | 380 | "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], |
|
| 376 | 381 | ||
| 377 | 382 | "set-cookie-parser": ["set-cookie-parser@2.7.2", "", {}, "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw=="], |
|
| 417 | 422 | "wrangler": ["wrangler@4.60.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.4.2", "@cloudflare/unenv-preset": "2.11.0", "blake3-wasm": "2.1.5", "esbuild": "0.27.0", "miniflare": "4.20260120.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260120.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20260120.0" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" } }, "sha512-n4kibm/xY0Qd5G2K/CbAQeVeOIlwPNVglmFjlDRCCYk3hZh8IggO/rg8AXt/vByK2Sxsugl5Z7yvgWxrUbmS6g=="], |
|
| 418 | 423 | ||
| 419 | 424 | "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], |
|
| 425 | + | ||
| 426 | + | "xml-js": ["xml-js@1.6.11", "", { "dependencies": { "sax": "^1.2.4" }, "bin": { "xml-js": "./bin/cli.js" } }, "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g=="], |
|
| 420 | 427 | ||
| 421 | 428 | "youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], |
|
| 422 | 429 | ||
| 26 | 26 | }, |
|
| 27 | 27 | "dependencies": { |
|
| 28 | 28 | "exifr": "^7.1.3", |
|
| 29 | + | "feed": "^5.2.0", |
|
| 29 | 30 | "from": "^0.1.7", |
|
| 30 | 31 | "import": "^0.0.6" |
|
| 31 | 32 | } |
| 1 | + | import type { ImageItem } from "$lib/types"; |
|
| 2 | + | ||
| 3 | + | const R2_BASE_URL = "https://r2.steve.photo"; |
|
| 4 | + | ||
| 5 | + | export async function getPhotos(platform: App.Platform | undefined): Promise<ImageItem[]> { |
|
| 6 | + | const db = platform?.env?.DB; |
|
| 7 | + | ||
| 8 | + | if (!db) { |
|
| 9 | + | return []; |
|
| 10 | + | } |
|
| 11 | + | ||
| 12 | + | const result = await db.prepare("SELECT * FROM photos ORDER BY date DESC").all(); |
|
| 13 | + | ||
| 14 | + | const photos: ImageItem[] = result.results.map((row: Record<string, unknown>) => ({ |
|
| 15 | + | slug: row.slug as string, |
|
| 16 | + | title: row.title as string, |
|
| 17 | + | date: row.date as string, |
|
| 18 | + | image: `${R2_BASE_URL}/${row.image_key}`, |
|
| 19 | + | thumb: `${R2_BASE_URL}/${row.thumb_key}`, |
|
| 20 | + | type: row.type as string, |
|
| 21 | + | camera: row.camera as string, |
|
| 22 | + | lens: row.lens as string, |
|
| 23 | + | aperture: row.aperture as string, |
|
| 24 | + | exposure: row.exposure as string, |
|
| 25 | + | focalLength: row.focal_length as string, |
|
| 26 | + | iso: row.iso as string, |
|
| 27 | + | make: row.make as string, |
|
| 28 | + | tags: [], |
|
| 29 | + | })); |
|
| 30 | + | ||
| 31 | + | return photos; |
|
| 32 | + | } |
| 1 | + | import { Feed } from "feed"; |
|
| 2 | + | import { getPhotos } from "$lib/feed"; |
|
| 3 | + | import type { RequestHandler } from "./$types"; |
|
| 4 | + | ||
| 5 | + | export const GET: RequestHandler = async ({ platform }) => { |
|
| 6 | + | const feed = new Feed({ |
|
| 7 | + | title: "steve.photo", |
|
| 8 | + | description: "Personal photography portolio of Steve Simkins", |
|
| 9 | + | id: "https://steve.photo", |
|
| 10 | + | link: "https://steve.photo/", |
|
| 11 | + | language: "en", |
|
| 12 | + | favicon: "https://steve.photo/favicon.ico", |
|
| 13 | + | copyright: `Copyright ${new Date().getFullYear().toString()}, Steve Simkins`, |
|
| 14 | + | feedLinks: { |
|
| 15 | + | rss: "https://steve.photo/rss.xml", |
|
| 16 | + | }, |
|
| 17 | + | author: { |
|
| 18 | + | name: "Steve Simkins", |
|
| 19 | + | email: "contact@stevedylan.dev", |
|
| 20 | + | link: "https://stevedylan.dev", |
|
| 21 | + | }, |
|
| 22 | + | ttl: 60, |
|
| 23 | + | }); |
|
| 24 | + | ||
| 25 | + | const photos = await getPhotos(platform); |
|
| 26 | + | ||
| 27 | + | for (const photo of photos) { |
|
| 28 | + | feed.addItem({ |
|
| 29 | + | title: photo.title, |
|
| 30 | + | id: `https://steve.photo/photo/${photo.slug}`, |
|
| 31 | + | link: `https://steve.photo/photo/${photo.slug}`, |
|
| 32 | + | date: new Date(photo.date), |
|
| 33 | + | image: photo.image, |
|
| 34 | + | author: [ |
|
| 35 | + | { |
|
| 36 | + | name: "Steve Simkins", |
|
| 37 | + | email: "contact@stevedylan.dev", |
|
| 38 | + | link: "https://stevedylan.dev", |
|
| 39 | + | }, |
|
| 40 | + | ], |
|
| 41 | + | content: `<img src="${photo.image}" alt="${photo.title}" /><p>Camera: ${photo.camera} | Lens: ${photo.lens} | ${photo.aperture} | ${photo.exposure} | ISO ${photo.iso}</p>`, |
|
| 42 | + | }); |
|
| 43 | + | } |
|
| 44 | + | ||
| 45 | + | return new Response(feed.rss2(), { |
|
| 46 | + | headers: { |
|
| 47 | + | "Content-Type": "application/xml; charset=utf-8", |
|
| 48 | + | }, |
|
| 49 | + | }); |
|
| 50 | + | }; |