mirror of
https://github.com/kjanat/livedash-node.git
synced 2026-01-16 06:12:09 +01:00
Major code quality overhaul addressing 58% of all linting issues: • Type Safety Improvements: - Replace all any types with proper TypeScript interfaces - Fix Map component shadowing (renamed to CountryMap) - Add comprehensive custom error classes system - Enhance API route type safety • Accessibility Enhancements: - Add explicit button types to all interactive elements - Implement useId() hooks for form element accessibility - Add SVG title attributes for screen readers - Fix static element interactions with keyboard handlers • React Best Practices: - Resolve exhaustive dependencies warnings with useCallback - Extract nested component definitions to top level - Fix array index keys with proper unique identifiers - Improve component organization and prop typing • Code Organization: - Automatic import organization and type import optimization - Fix unused function parameters and variables - Enhanced error handling with structured error responses - Improve component reusability and maintainability Results: 248 → 104 total issues (58% reduction) - Fixed all critical type safety and security issues - Enhanced accessibility compliance significantly - Improved code maintainability and performance
151 lines
3.5 KiB
TypeScript
151 lines
3.5 KiB
TypeScript
// Transcript fetching utility
|
|
import fetch from "node-fetch";
|
|
|
|
export interface TranscriptFetchResult {
|
|
success: boolean;
|
|
content?: string;
|
|
error?: string;
|
|
}
|
|
|
|
/**
|
|
* Fetch transcript content from a URL
|
|
* @param url The transcript URL
|
|
* @param username Optional username for authentication
|
|
* @param password Optional password for authentication
|
|
* @returns Promise with fetch result
|
|
*/
|
|
export async function fetchTranscriptContent(
|
|
url: string,
|
|
username?: string,
|
|
password?: string
|
|
): Promise<TranscriptFetchResult> {
|
|
try {
|
|
if (!url || !url.trim()) {
|
|
return {
|
|
success: false,
|
|
error: "No transcript URL provided",
|
|
};
|
|
}
|
|
|
|
// Prepare authentication header if credentials provided
|
|
const authHeader =
|
|
username && password
|
|
? `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`
|
|
: undefined;
|
|
|
|
const headers: Record<string, string> = {
|
|
"User-Agent": "LiveDash-Transcript-Fetcher/1.0",
|
|
};
|
|
|
|
if (authHeader) {
|
|
headers.Authorization = authHeader;
|
|
}
|
|
|
|
// Fetch the transcript with timeout
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
|
|
|
|
const response = await fetch(url, {
|
|
method: "GET",
|
|
headers,
|
|
signal: controller.signal,
|
|
});
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response.ok) {
|
|
return {
|
|
success: false,
|
|
error: `HTTP ${response.status}: ${response.statusText}`,
|
|
};
|
|
}
|
|
|
|
const content = await response.text();
|
|
|
|
if (!content || content.trim().length === 0) {
|
|
return {
|
|
success: false,
|
|
error: "Empty transcript content",
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
content: content.trim(),
|
|
};
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
|
|
// Handle common network errors
|
|
if (errorMessage.includes("ENOTFOUND")) {
|
|
return {
|
|
success: false,
|
|
error: "Domain not found",
|
|
};
|
|
}
|
|
|
|
if (errorMessage.includes("ECONNREFUSED")) {
|
|
return {
|
|
success: false,
|
|
error: "Connection refused",
|
|
};
|
|
}
|
|
|
|
if (errorMessage.includes("timeout")) {
|
|
return {
|
|
success: false,
|
|
error: "Request timeout",
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: false,
|
|
error: errorMessage,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate if a URL looks like a valid transcript URL
|
|
* @param url The URL to validate
|
|
* @returns boolean indicating if URL appears valid
|
|
*/
|
|
export function isValidTranscriptUrl(url: string): boolean {
|
|
if (!url || typeof url !== "string") {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const parsedUrl = new URL(url);
|
|
return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract session ID from transcript content if possible
|
|
* This is a helper function that can be enhanced based on transcript format
|
|
* @param content The transcript content
|
|
* @returns Extracted session ID or null
|
|
*/
|
|
export function extractSessionIdFromTranscript(content: string): string | null {
|
|
if (!content) return null;
|
|
|
|
// Look for common session ID patterns
|
|
const patterns = [
|
|
/session[_-]?id[:\s]*([a-zA-Z0-9-]+)/i,
|
|
/id[:\s]*([a-zA-Z0-9-]{8,})/i,
|
|
/^([a-zA-Z0-9-]{8,})/m, // First line might be session ID
|
|
];
|
|
|
|
for (const pattern of patterns) {
|
|
const match = content.match(pattern);
|
|
if (match?.[1]) {
|
|
return match[1].trim();
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|