feat: migrate to bun runtime and update dependencies
This commit is contained in:
@ -14,6 +14,10 @@
|
|||||||
"typescript": "^4.0.0",
|
"typescript": "^4.0.0",
|
||||||
"@types/react": "^18.0.0",
|
"@types/react": "^18.0.0",
|
||||||
"@types/react-dom": "^18.0.0",
|
"@types/react-dom": "^18.0.0",
|
||||||
"bun-types": "^0.1.0"
|
"bun-types": "^0.1.0",
|
||||||
}
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"module": "src/index.tsx",
|
||||||
|
"type": "module",
|
||||||
|
"private": true
|
||||||
}
|
}
|
||||||
|
17
package.json
17
package.json
@ -5,11 +5,16 @@
|
|||||||
"start": "bun run server.ts"
|
"start": "bun run server.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"rss-parser": "^3.12.0",
|
"@aws-sdk/client-polly": "^3.823.0",
|
||||||
"openai": "^4.0.0",
|
"openai": "^4.104.0",
|
||||||
"@aws-sdk/client-polly": "^3.0.0",
|
"rss-parser": "^3.13.0"
|
||||||
"better-sqlite3": "^8.0.0",
|
|
||||||
"bun-router": "^0.1.0"
|
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bun": "latest"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,7 @@ interface FeedItem {
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const parser = new Parser<FeedItem>();
|
const parser = new Parser<FeedItem>();
|
||||||
const feedUrls = [
|
const feedUrls = ["https://example.com/feed1.rss"];
|
||||||
"https://example.com/feed1.rss",
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const url of feedUrls) {
|
for (const url of feedUrls) {
|
||||||
const feed = await parser.parseURL(url);
|
const feed = await parser.parseURL(url);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Database from "better-sqlite3";
|
import { Database } from "bun:sqlite";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
const dbPath = path.join(__dirname, "../data/podcast.db");
|
const dbPath = path.join(__dirname, "../data/podcast.db");
|
||||||
@ -28,17 +28,26 @@ export interface Episode {
|
|||||||
sourceLink: string;
|
sourceLink: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function markAsProcessed(feedUrl: string, itemId: string): Promise<boolean> {
|
export async function markAsProcessed(
|
||||||
const stmt = db.prepare("SELECT 1 FROM processed_feed_items WHERE feed_url = ? AND item_id = ?");
|
feedUrl: string,
|
||||||
|
itemId: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const stmt = db.prepare(
|
||||||
|
"SELECT 1 FROM processed_feed_items WHERE feed_url = ? AND item_id = ?",
|
||||||
|
);
|
||||||
const row = stmt.get(feedUrl, itemId);
|
const row = stmt.get(feedUrl, itemId);
|
||||||
if (row) return true;
|
if (row) return true;
|
||||||
const insert = db.prepare("INSERT INTO processed_feed_items (feed_url, item_id, processed_at) VALUES (?, ?, ?)");
|
const insert = db.prepare(
|
||||||
|
"INSERT INTO processed_feed_items (feed_url, item_id, processed_at) VALUES (?, ?, ?)",
|
||||||
|
);
|
||||||
insert.run(feedUrl, itemId, new Date().toISOString());
|
insert.run(feedUrl, itemId, new Date().toISOString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveEpisode(ep: Episode): Promise<void> {
|
export async function saveEpisode(ep: Episode): Promise<void> {
|
||||||
const stmt = db.prepare("INSERT OR IGNORE INTO episodes (id, title, pubDate, audioPath, sourceLink) VALUES (?, ?, ?, ?, ?)");
|
const stmt = db.prepare(
|
||||||
|
"INSERT OR IGNORE INTO episodes (id, title, pubDate, audioPath, sourceLink) VALUES (?, ?, ?, ?, ?)",
|
||||||
|
);
|
||||||
stmt.run(ep.id, ep.title, ep.pubDate, ep.audioPath, ep.sourceLink);
|
stmt.run(ep.id, ep.title, ep.pubDate, ep.audioPath, ep.sourceLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,13 +7,14 @@ export async function updatePodcastRSS() {
|
|||||||
|
|
||||||
const channelTitle = "自動生成ポッドキャスト";
|
const channelTitle = "自動生成ポッドキャスト";
|
||||||
const channelLink = "https://your-domain.com/podcast";
|
const channelLink = "https://your-domain.com/podcast";
|
||||||
const channelDescription = "RSSフィードから自動生成されたポッドキャストです。";
|
const channelDescription =
|
||||||
|
"RSSフィードから自動生成されたポッドキャストです。";
|
||||||
const lastBuildDate = new Date().toUTCString();
|
const lastBuildDate = new Date().toUTCString();
|
||||||
|
|
||||||
let itemsXml = "";
|
let itemsXml = "";
|
||||||
for (const ep of episodes) {
|
for (const ep of episodes) {
|
||||||
const fileUrl = `https://your-domain.com/podcast_audio/${path.basename(
|
const fileUrl = `https://your-domain.com/podcast_audio/${path.basename(
|
||||||
ep.audioPath
|
ep.audioPath,
|
||||||
)}`;
|
)}`;
|
||||||
const pubDate = new Date(ep.pubDate).toUTCString();
|
const pubDate = new Date(ep.pubDate).toUTCString();
|
||||||
itemsXml += `
|
itemsXml += `
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import {
|
import { PollyClient, SynthesizeSpeechCommand } from "@aws-sdk/client-polly";
|
||||||
PollyClient,
|
|
||||||
SynthesizeSpeechCommand,
|
|
||||||
} from "@aws-sdk/client-polly";
|
|
||||||
|
|
||||||
const polly = new PollyClient({ region: "ap-northeast-1" });
|
const polly = new PollyClient({ region: "ap-northeast-1" });
|
||||||
|
|
||||||
export async function generateTTS(
|
export async function generateTTS(
|
||||||
itemId: string,
|
itemId: string,
|
||||||
scriptText: string
|
scriptText: string,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const params = {
|
const params = {
|
||||||
OutputFormat: "mp3",
|
OutputFormat: "mp3",
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2020",
|
// Environment setup & latest features
|
||||||
"module": "ESNext",
|
"lib": ["ESNext"],
|
||||||
"moduleResolution": "Node",
|
"target": "ESNext",
|
||||||
|
"module": "Preserve",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": true,
|
||||||
|
|
||||||
|
// Bundler mode
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
// Best practices
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"esModuleInterop": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"outDir": "dist"
|
"noFallthroughCasesInSwitch": true,
|
||||||
},
|
"noUncheckedIndexedAccess": true,
|
||||||
"include": ["scripts", "services", "server.ts"]
|
"noImplicitOverride": true,
|
||||||
|
|
||||||
|
// Some stricter flags (disabled by default)
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"noPropertyAccessFromIndexSignature": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user