Refactor the hero section to a multi-card layout and adjust image processing parameters by changing `max_tokens` to `max_completion_tokens` and removing an unsupported `temperature` value. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 517dfa7b-26ac-463d-a6e1-a58c6df97188 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: dc1a7e29-d86e-41b6-8c1b-d753e4842371 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/517dfa7b-26ac-463d-a6e1-a58c6df97188/ls5p9ni Replit-Helium-Checkpoint-Created: true
113 lines
4.2 KiB
TypeScript
113 lines
4.2 KiB
TypeScript
import OpenAI from "openai";
|
|
import { db } from "./db";
|
|
import { dailyHoroscopes } from "@shared/schema";
|
|
import { eq, and } from "drizzle-orm";
|
|
|
|
const openai = new OpenAI({
|
|
apiKey: process.env.AI_INTEGRATIONS_OPENAI_API_KEY,
|
|
baseURL: process.env.AI_INTEGRATIONS_OPENAI_BASE_URL,
|
|
});
|
|
|
|
const SIGN_NAMES = [
|
|
"Widder", "Stier", "Zwillinge", "Krebs", "Löwe", "Jungfrau",
|
|
"Waage", "Skorpion", "Schütze", "Steinbock", "Wassermann", "Fische"
|
|
];
|
|
|
|
function getTodayStr(): string {
|
|
const d = new Date();
|
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
}
|
|
|
|
export async function getHoroscopesForToday(): Promise<any[]> {
|
|
const today = getTodayStr();
|
|
const existing = await db.select().from(dailyHoroscopes).where(eq(dailyHoroscopes.dateStr, today));
|
|
if (existing.length === 12) return existing;
|
|
return [];
|
|
}
|
|
|
|
export async function generateDailyHoroscopes(): Promise<void> {
|
|
const today = getTodayStr();
|
|
|
|
const existing = await db.select().from(dailyHoroscopes).where(eq(dailyHoroscopes.dateStr, today));
|
|
if (existing.length >= 12) {
|
|
console.log(`Horoscopes for ${today} already exist.`);
|
|
return;
|
|
}
|
|
|
|
console.log(`Generating horoscopes for ${today}...`);
|
|
|
|
for (let i = 0; i < SIGN_NAMES.length; i++) {
|
|
const signName = SIGN_NAMES[i];
|
|
|
|
const alreadyExists = existing.find(h => h.signIndex === i);
|
|
if (alreadyExists) continue;
|
|
|
|
try {
|
|
const response = await openai.chat.completions.create({
|
|
model: "gpt-5-mini",
|
|
messages: [
|
|
{
|
|
role: "system",
|
|
content: `Du bist ein erfahrener Astrologe, der tägliche Horoskope für eine deutschsprachige Volksmusik- und Schlager-Nachrichtenwebsite schreibt. Dein Stil ist warm, ermutigend und poetisch. Du beziehst manchmal Musik, Natur und alpine Kultur in deine Texte ein. Schreibe immer auf Deutsch. Das heutige Datum ist ${today}.`
|
|
},
|
|
{
|
|
role: "user",
|
|
content: `Erstelle ein ausführliches Tageshoroskop für das Sternzeichen ${signName} für heute (${today}).
|
|
|
|
Antworte NUR mit einem JSON-Objekt in diesem exakten Format (kein Markdown, keine Erklärung):
|
|
{
|
|
"general": "Ausführlicher allgemeiner Tagestext, mindestens 4-5 Sätze über die allgemeine Energie, Stimmung und Möglichkeiten des Tages.",
|
|
"love": "Ausführlicher Text über Liebe und Partnerschaft, mindestens 3-4 Sätze mit konkreten Ratschlägen für Singles und Paare.",
|
|
"career": "Ausführlicher Text über Beruf und Finanzen, mindestens 3-4 Sätze mit konkreten Tipps.",
|
|
"health": "Ausführlicher Text über Gesundheit und Wohlbefinden, mindestens 3-4 Sätze.",
|
|
"tip": "Ein konkreter, umsetzbarer Tipp des Tages in 1-2 Sätzen.",
|
|
"weekly": "Ausführliche Wochenvorschau, mindestens 4-5 Sätze mit Hinweisen für jeden Wochentag.",
|
|
"monthly": "Ausführliche Monatsvorschau, mindestens 4-5 Sätze über die wichtigsten Themen des Monats."
|
|
}`
|
|
}
|
|
],
|
|
max_completion_tokens: 2000,
|
|
});
|
|
|
|
const content = response.choices[0]?.message?.content || "";
|
|
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
if (!jsonMatch) {
|
|
console.error(`Failed to parse horoscope for ${signName}`);
|
|
continue;
|
|
}
|
|
|
|
const parsed = JSON.parse(jsonMatch[0]);
|
|
|
|
await db.insert(dailyHoroscopes).values({
|
|
signIndex: i,
|
|
signName,
|
|
dateStr: today,
|
|
general: parsed.general || "",
|
|
love: parsed.love || "",
|
|
career: parsed.career || "",
|
|
health: parsed.health || "",
|
|
tip: parsed.tip || "",
|
|
weekly: parsed.weekly || "",
|
|
monthly: parsed.monthly || "",
|
|
});
|
|
|
|
console.log(`Generated horoscope for ${signName}`);
|
|
} catch (err: any) {
|
|
console.error(`Error generating horoscope for ${signName}:`, err.message);
|
|
}
|
|
}
|
|
|
|
console.log(`Horoscope generation complete for ${today}.`);
|
|
}
|
|
|
|
export async function getOrGenerateHoroscope(signIndex: number): Promise<any | null> {
|
|
const today = getTodayStr();
|
|
|
|
const [existing] = await db.select().from(dailyHoroscopes)
|
|
.where(and(eq(dailyHoroscopes.dateStr, today), eq(dailyHoroscopes.signIndex, signIndex)));
|
|
|
|
if (existing) return existing;
|
|
|
|
return null;
|
|
}
|