Files
at-mintel/packages/journaling/src/clients/serper.ts
Marc Mintel 3a1a88db89
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧹 Lint (push) Successful in 1m12s
Monorepo Pipeline / 🧪 Test (push) Successful in 2m59s
Monorepo Pipeline / 🏗️ Build (push) Successful in 6m52s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
🏥 Server Maintenance / 🧹 Prune & Clean (push) Failing after 4s
feat: content engine
2026-02-22 02:39:27 +01:00

129 lines
3.2 KiB
TypeScript

export interface SerperVideoResult {
title: string;
link: string;
snippet?: string;
date?: string;
duration?: string;
channel?: string;
}
export interface SerperVideoResponse {
searchParameters: any;
videos: SerperVideoResult[];
}
export interface SerperWebResult {
title: string;
link: string;
snippet: string;
date?: string;
sitelinks?: any[];
position: number;
}
export interface SerperWebResponse {
searchParameters: any;
organic: SerperWebResult[];
}
export class SerperClient {
private apiKey: string;
constructor(apiKey?: string) {
const key = apiKey || process.env.SERPER_API_KEY;
if (!key) {
console.warn("⚠️ SERPER_API_KEY is not defined. SerperClient will fail.");
}
this.apiKey = key || "";
}
/**
* Performs a video search via Serper (Google Video Search).
* Great for finding relevant YouTube videos.
*/
async searchVideos(
query: string,
num: number = 5,
): Promise<SerperVideoResult[]> {
if (!this.apiKey) {
console.error("❌ SERPER_API_KEY missing - cannot execute search.");
return [];
}
try {
console.log(`🔍 [Serper] Searching videos for: "${query}"`);
const response = await fetch("https://google.serper.dev/videos", {
method: "POST",
headers: {
"X-API-KEY": this.apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
q: query,
num: num,
gl: "de", // Germany for localized results
hl: "de", // German language
}),
});
if (!response.ok) {
console.error(
`❌ [Serper] API Error: ${response.status} ${response.statusText}`,
);
const text = await response.text();
console.error(text);
return [];
}
const data = (await response.json()) as SerperVideoResponse;
return data.videos || [];
} catch (e) {
console.error("❌ [Serper] Request failed", e);
return [];
}
}
/**
* Performs a standard web search via Serper.
* Crucial for B2B competitor analysis and context gathering.
*/
async searchWeb(query: string, num: number = 5): Promise<SerperWebResult[]> {
if (!this.apiKey) {
console.error("❌ SERPER_API_KEY missing - cannot execute web search.");
return [];
}
try {
console.log(`🔍 [Serper] Web Search for Competitor Insights: "${query}"`);
const response = await fetch("https://google.serper.dev/search", {
method: "POST",
headers: {
"X-API-KEY": this.apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
q: query,
num: num,
gl: "de", // Germany for localized results
hl: "de", // German language
}),
});
if (!response.ok) {
console.error(
`❌ [Serper] API Error: ${response.status} ${response.statusText}`,
);
const text = await response.text();
console.error(text);
return [];
}
const data = (await response.json()) as SerperWebResponse;
return data.organic || [];
} catch (e) {
console.error("❌ [Serper] Web Request failed", e);
return [];
}
}
}