/** * Reddit API client with built-in error handling and retries */ import { RedditPost, RedditComment, RedditUser, RedditSubreddit, RedditListing } from '../types/reddit.types.js'; import { AuthManager } from '../core/auth.js'; import { RateLimiter } from '../core/rate-limiter.js'; import { CacheManager } from '../core/cache.js'; export interface RedditAPIOptions { authManager: AuthManager; rateLimiter: RateLimiter; cacheManager: CacheManager; timeout?: number; } /** * Sentinel for engagement metrics that RSS feeds don't provide. * -1 is unambiguous (real Reddit scores can be negative but never below the * post's own downvotes; num_comments is never negative), so the tools layer * can detect "unknown" and decide how to present it to the LLM. */ export declare const RSS_UNKNOWN_SCORE = -1; export declare class RedditAPI { private auth; private rateLimiter; private cache; private timeout; private baseUrl; private oauthUrl; private inFlightRequests; private inFlightRequestTimestamps; private readonly IN_FLIGHT_REQUEST_TTL_MS; private readonly MAX_BACKOFF_MS; private readonly INITIAL_BACKOFF_MS; private readonly BACKOFF_MULTIPLIER; private anonJsonBlockedUntil; private readonly ANON_JSON_BLOCK_TTL_MS; constructor(options: RedditAPIOptions); /** * Browse a subreddit */ browseSubreddit(subreddit: string, sort?: 'hot' | 'new' | 'top' | 'rising' | 'controversial', options?: { limit?: number; time?: 'hour' | 'day' | 'week' | 'month' | 'year' | 'all'; after?: string; }): Promise>; /** * Browse a subreddit via Reddit's public Atom (RSS) feed. * Credential-free fallback used when the unauthenticated JSON API is blocked. * NOTE: RSS lacks engagement metrics (score, num_comments, upvote_ratio). */ private browseSubredditViaRSS; /** * Private: Decode XML/HTML entities found in Atom feed text. */ private decodeEntities; /** * Private: Parse a Reddit Atom feed into the same RedditListing * shape the rest of the pipeline expects. Engagement fields are unknown from * RSS and are left at sentinel values (see RSS_UNKNOWN_SCORE) for the tools * layer to represent to the LLM. */ private parseAtomFeed; /** * Private: Fetch a Reddit RSS/Atom endpoint and return the raw XML text. * Uses the same rate limiter and timeout as the JSON path. */ private getRSS; /** * Get post details with comments */ getPost(postId: string, options?: { limit?: number; sort?: 'best' | 'top' | 'new' | 'controversial' | 'qa'; depth?: number; }): Promise<[RedditListing, RedditListing]>; /** * Search Reddit */ search(query: string, options?: { subreddit?: string; sort?: 'relevance' | 'hot' | 'top' | 'new' | 'comments'; time?: 'hour' | 'day' | 'week' | 'month' | 'year' | 'all'; limit?: number; after?: string; restrictSr?: boolean; }): Promise>; /** * Get user information */ getUser(username: string): Promise; /** * Get user's recent posts */ getUserPosts(username: string, type?: 'submitted' | 'comments', options?: { sort?: 'new' | 'top' | 'hot'; time?: 'hour' | 'day' | 'week' | 'month' | 'year' | 'all'; limit?: number; }): Promise>; /** * Get subreddit information */ getSubreddit(name: string): Promise; /** * Get trending subreddits */ getTrending(): Promise; /** * Private: Error carrying the HTTP status that caused it, so callers can * distinguish failure classes (e.g. the anonymous 403 IP-block) without * parsing message text. */ private httpError; /** * Private: Calculate exponential backoff with jitter */ private calculateBackoff; /** * Private: Extract retry-after delay from response headers */ private getRetryAfterDelay; /** * Private: Delay until the rate-limit window resets, from Reddit's * x-ratelimit-reset header (seconds until reset). The logged-out .rss * endpoint sends this on 429s where Retry-After may be absent. */ private getRateLimitResetDelay; /** * Private: Clean up stale in-flight requests to prevent memory leaks */ private cleanupStaleInFlightRequests; /** * Private: Make GET request to Reddit API with retry logic and deduplication */ private get; /** * Private: Implementation of GET request with retry logic */ private getImpl; } //# sourceMappingURL=reddit-api.d.ts.map