SYMBOL INDEX (461 symbols across 105 files) FILE: next.config.js method webpack (line 32) | webpack(config) { FILE: proxy.worker.js function handleRequest (line 7) | async function handleRequest(request) { function ensureProtocol (line 87) | function ensureProtocol(url, defaultProtocol) { function handleRedirect (line 94) | function handleRedirect(response, body) { function handleHtmlContent (line 108) | async function handleHtmlContent(response, protocol, host, actualUrlStr) { function replaceRelativePaths (line 122) | function replaceRelativePaths(text, protocol, host, origin) { function jsonResponse (line 128) | function jsonResponse(data, status) { function filterHeaders (line 138) | function filterHeaders(headers, filterFunc) { function setNoCacheHeaders (line 143) | function setNoCacheHeaders(headers) { function setCorsHeaders (line 148) | function setCorsHeaders(headers) { function getRootHtml (line 155) | function getRootHtml() { FILE: scripts/convert-changelog.js function parseChangelog (line 8) | function parseChangelog(content) { function generateTypeScript (line 89) | function generateTypeScript(changelogData) { function updateVersionFile (line 137) | function updateVersionFile(version) { function updateVersionTs (line 148) | function updateVersionTs(version) { function main (line 167) | function main() { FILE: src/app/admin/page.tsx type AlertModalProps (line 93) | interface AlertModalProps { type LoadingState (line 232) | interface LoadingState { type SiteConfig (line 259) | interface SiteConfig { type DataSource (line 274) | interface DataSource { type LiveDataSource (line 284) | interface LiveDataSource { type CustomCategory (line 296) | interface CustomCategory { type CollapsibleTabProps (line 305) | interface CollapsibleTabProps { type UserConfigProps (line 343) | interface UserConfigProps { type UserInfo (line 1089) | type UserInfo = (typeof config.UserConfig.Users)[number]; function AdminPageClient (line 4529) | function AdminPageClient() { function AdminPage (line 4836) | function AdminPage() { FILE: src/app/api/admin/category/route.ts type Action (line 12) | type Action = 'add' | 'disable' | 'enable' | 'delete' | 'sort'; type BaseBody (line 14) | interface BaseBody { function POST (line 18) | async function POST(request: NextRequest) { FILE: src/app/api/admin/config/route.ts function GET (line 11) | async function GET(request: NextRequest) { FILE: src/app/api/admin/config_file/route.ts function POST (line 11) | async function POST(request: NextRequest) { FILE: src/app/api/admin/config_subscription/fetch/route.ts function POST (line 9) | async function POST(request: NextRequest) { FILE: src/app/api/admin/data_migration/export/route.ts function POST (line 16) | async function POST(req: NextRequest) { function getUserPassword (line 122) | async function getUserPassword(username: string): Promise { FILE: src/app/api/admin/data_migration/import/route.ts function POST (line 16) | async function POST(req: NextRequest) { FILE: src/app/api/admin/live/refresh/route.ts function POST (line 12) | async function POST(request: NextRequest) { FILE: src/app/api/admin/live/route.ts function POST (line 12) | async function POST(request: NextRequest) { FILE: src/app/api/admin/reset/route.ts function GET (line 10) | async function GET(request: NextRequest) { FILE: src/app/api/admin/site/route.ts function POST (line 11) | async function POST(request: NextRequest) { FILE: src/app/api/admin/source/route.ts type Action (line 12) | type Action = 'add' | 'disable' | 'enable' | 'delete' | 'sort' | 'batch_... type BaseBody (line 14) | interface BaseBody { function POST (line 18) | async function POST(request: NextRequest) { FILE: src/app/api/admin/source/validate/route.ts function GET (line 11) | async function GET(request: NextRequest) { FILE: src/app/api/admin/user/route.ts constant ACTIONS (line 12) | const ACTIONS = [ function POST (line 26) | async function POST(request: NextRequest) { FILE: src/app/api/change-password/route.ts function POST (line 10) | async function POST(request: NextRequest) { FILE: src/app/api/cron/route.ts function GET (line 13) | async function GET(request: NextRequest) { function cronJob (line 40) | async function cronJob() { function refreshAllLiveChannels (line 46) | async function refreshAllLiveChannels() { function refreshConfig (line 69) | async function refreshConfig() { function refreshRecordAndFavorites (line 109) | async function refreshRecordAndFavorites() { FILE: src/app/api/detail/route.ts function GET (line 9) | async function GET(request: NextRequest) { FILE: src/app/api/douban/categories/route.ts type DoubanCategoryApiResponse (line 7) | interface DoubanCategoryApiResponse { function GET (line 25) | async function GET(request: Request) { FILE: src/app/api/douban/recommends/route.ts type DoubanRecommendApiResponse (line 9) | interface DoubanRecommendApiResponse { function GET (line 28) | async function GET(request: NextRequest) { FILE: src/app/api/douban/route.ts type DoubanApiResponse (line 7) | interface DoubanApiResponse { function GET (line 18) | async function GET(request: Request) { function handleTop250 (line 98) | function handleTop250(pageStart: number) { FILE: src/app/api/favorites/route.ts function GET (line 19) | async function GET(request: NextRequest) { function POST (line 73) | async function POST(request: NextRequest) { function DELETE (line 144) | async function DELETE(request: NextRequest) { FILE: src/app/api/image-proxy/route.ts function GET (line 6) | async function GET(request: Request) { FILE: src/app/api/live/channels/route.ts function GET (line 7) | async function GET(request: NextRequest) { FILE: src/app/api/live/epg/route.ts function GET (line 7) | async function GET(request: NextRequest) { FILE: src/app/api/live/precheck/route.ts function GET (line 9) | async function GET(request: NextRequest) { FILE: src/app/api/live/sources/route.ts function GET (line 9) | async function GET(request: NextRequest) { FILE: src/app/api/login/route.ts constant STORAGE_TYPE (line 10) | const STORAGE_TYPE = function generateSignature (line 19) | async function generateSignature( function generateAuthCookie (line 46) | async function generateAuthCookie( function POST (line 70) | async function POST(req: NextRequest) { FILE: src/app/api/logout/route.ts function POST (line 5) | async function POST() { FILE: src/app/api/playrecords/route.ts function GET (line 12) | async function GET(request: NextRequest) { function POST (line 45) | async function POST(request: NextRequest) { function DELETE (line 111) | async function DELETE(request: NextRequest) { FILE: src/app/api/proxy/key/route.ts function GET (line 9) | async function GET(request: Request) { FILE: src/app/api/proxy/logo/route.ts function GET (line 9) | async function GET(request: Request) { FILE: src/app/api/proxy/m3u8/route.ts function GET (line 10) | async function GET(request: Request) { function rewriteM3U8Content (line 97) | function rewriteM3U8Content(content: string, baseUrl: string, req: Reque... function rewriteMapUri (line 161) | function rewriteMapUri(line: string, baseUrl: string, proxyBase: string) { function rewriteKeyUri (line 172) | function rewriteKeyUri(line: string, baseUrl: string, proxyBase: string) { FILE: src/app/api/proxy/segment/route.ts function GET (line 9) | async function GET(request: Request) { FILE: src/app/api/search/one/route.ts function GET (line 11) | async function GET(request: NextRequest) { FILE: src/app/api/search/resources/route.ts function GET (line 11) | async function GET(request: NextRequest) { FILE: src/app/api/search/route.ts function GET (line 12) | async function GET(request: NextRequest) { FILE: src/app/api/search/suggestions/route.ts function GET (line 13) | async function GET(request: NextRequest) { function generateSuggestions (line 52) | async function generateSuggestions(config: AdminConfig, query: string, u... FILE: src/app/api/search/ws/route.ts function GET (line 12) | async function GET(request: NextRequest) { FILE: src/app/api/searchhistory/route.ts constant HISTORY_LIMIT (line 12) | const HISTORY_LIMIT = 20; function GET (line 18) | async function GET(request: NextRequest) { function POST (line 55) | async function POST(request: NextRequest) { function DELETE (line 107) | async function DELETE(request: NextRequest) { FILE: src/app/api/server-config/route.ts function GET (line 10) | async function GET(request: NextRequest) { FILE: src/app/api/skipconfigs/route.ts function GET (line 12) | async function GET(request: NextRequest) { function POST (line 55) | async function POST(request: NextRequest) { function DELETE (line 108) | async function DELETE(request: NextRequest) { FILE: src/app/douban/page.tsx function DoubanPageClient (line 24) | function DoubanPageClient() { function DoubanPage (line 824) | function DoubanPage() { FILE: src/app/layout.tsx function generateMetadata (line 18) | async function generateMetadata(): Promise { function RootLayout (line 37) | async function RootLayout({ FILE: src/app/live/page.tsx type HTMLVideoElement (line 25) | interface HTMLVideoElement { type LiveChannel (line 31) | interface LiveChannel { type LiveSource (line 41) | interface LiveSource { function LivePageClient (line 52) | function LivePageClient() { function LivePage (line 1606) | function LivePage() { function LivePageGuard (line 1614) | function LivePageGuard() { FILE: src/app/login/page.tsx function VersionDisplay (line 16) | function VersionDisplay() { function LoginPageClient (line 70) | function LoginPageClient() { function LoginPage (line 189) | function LoginPage() { FILE: src/app/page.tsx function HomeClient (line 30) | function HomeClient() { function Home (line 517) | function Home() { FILE: src/app/play/page.tsx type HTMLVideoElement (line 32) | interface HTMLVideoElement { type WakeLockSentinel (line 38) | interface WakeLockSentinel { function PlayPageClient (line 45) | function PlayPageClient() { function PlayPage (line 2092) | function PlayPage() { FILE: src/app/search/page.tsx function SearchPageClient (line 23) | function SearchPageClient() { function SearchPage (line 904) | function SearchPage() { FILE: src/app/warning/page.tsx function WarningPage (line 8) | function WarningPage() { FILE: src/components/BackButton.tsx function BackButton (line 3) | function BackButton() { FILE: src/components/CapsuleSwitch.tsx type CapsuleSwitchProps (line 5) | interface CapsuleSwitchProps { FILE: src/components/ContinueWatching.tsx type ContinueWatchingProps (line 16) | interface ContinueWatchingProps { function ContinueWatching (line 20) | function ContinueWatching({ className }: ContinueWatchingProps) { FILE: src/components/DataMigration.tsx type DataMigrationProps (line 8) | interface DataMigrationProps { type AlertModalProps (line 12) | interface AlertModalProps { FILE: src/components/DoubanCustomSelector.tsx type CustomCategory (line 7) | interface CustomCategory { type DoubanCustomSelectorProps (line 13) | interface DoubanCustomSelectorProps { FILE: src/components/DoubanSelector.tsx type SelectorOption (line 10) | interface SelectorOption { type DoubanSelectorProps (line 15) | interface DoubanSelectorProps { FILE: src/components/EpgScrollableRow.tsx type EpgProgram (line 8) | interface EpgProgram { type EpgScrollableRowProps (line 14) | interface EpgScrollableRowProps { function EpgScrollableRow (line 20) | function EpgScrollableRow({ FILE: src/components/EpisodeSelector.tsx type VideoInfo (line 16) | interface VideoInfo { type EpisodeSelectorProps (line 23) | interface EpisodeSelectorProps { FILE: src/components/GlobalErrorIndicator.tsx type ErrorInfo (line 5) | interface ErrorInfo { function GlobalErrorIndicator (line 11) | function GlobalErrorIndicator() { function triggerGlobalError (line 97) | function triggerGlobalError(message: string) { FILE: src/components/MobileActionSheet.tsx type ActionItem (line 5) | interface ActionItem { type MobileActionSheetProps (line 14) | interface MobileActionSheetProps { FILE: src/components/MobileBottomNav.tsx type MobileBottomNavProps (line 10) | interface MobileBottomNavProps { FILE: src/components/MobileHeader.tsx type MobileHeaderProps (line 10) | interface MobileHeaderProps { FILE: src/components/MultiLevelSelector.tsx type MultiLevelOption (line 6) | interface MultiLevelOption { type MultiLevelCategory (line 11) | interface MultiLevelCategory { type MultiLevelSelectorProps (line 18) | interface MultiLevelSelectorProps { FILE: src/components/PageLayout.tsx type PageLayoutProps (line 8) | interface PageLayoutProps { FILE: src/components/ScrollableRow.tsx type ScrollableRowProps (line 4) | interface ScrollableRowProps { function ScrollableRow (line 9) | function ScrollableRow({ FILE: src/components/SearchResultFilter.tsx type SearchFilterKey (line 7) | type SearchFilterKey = 'source' | 'title' | 'year' | 'yearOrder'; type SearchFilterOption (line 9) | interface SearchFilterOption { type SearchFilterCategory (line 14) | interface SearchFilterCategory { type SearchResultFilterProps (line 20) | interface SearchResultFilterProps { constant DEFAULTS (line 26) | const DEFAULTS: Record = { FILE: src/components/SearchSuggestions.tsx type SearchSuggestionsProps (line 5) | interface SearchSuggestionsProps { type SuggestionItem (line 13) | interface SuggestionItem { function SearchSuggestions (line 19) | function SearchSuggestions({ FILE: src/components/Sidebar.tsx type SidebarContextType (line 19) | interface SidebarContextType { type SidebarProps (line 44) | interface SidebarProps { type Window (line 51) | interface Window { FILE: src/components/SiteProvider.tsx function SiteProvider (line 14) | function SiteProvider({ FILE: src/components/ThemeProvider.tsx function ThemeProvider (line 7) | function ThemeProvider({ children, ...props }: ThemeProviderProps) { FILE: src/components/ThemeToggle.tsx function ThemeToggle (line 10) | function ThemeToggle() { FILE: src/components/UserMenu.tsx type AuthInfo (line 26) | interface AuthInfo { FILE: src/components/VersionPanel.tsx type VersionPanelProps (line 22) | interface VersionPanelProps { type RemoteChangelogEntry (line 27) | interface RemoteChangelogEntry { FILE: src/components/VideoCard.tsx type VideoCardProps (line 30) | interface VideoCardProps { type VideoCardHandle (line 52) | type VideoCardHandle = { FILE: src/components/VirtualGrid.tsx type VirtualGridProps (line 6) | interface VirtualGridProps { function VirtualGrid (line 25) | function VirtualGrid({ FILE: src/components/WeekdaySelector.tsx type WeekdaySelectorProps (line 7) | interface WeekdaySelectorProps { FILE: src/hooks/useLongPress.ts type UseLongPressOptions (line 3) | interface UseLongPressOptions { type TouchPosition (line 10) | interface TouchPosition { FILE: src/lib/admin.types.ts type AdminConfig (line 1) | interface AdminConfig { type AdminConfigResult (line 61) | interface AdminConfigResult { FILE: src/lib/auth.ts function getAuthInfoFromCookie (line 4) | function getAuthInfoFromCookie(request: NextRequest): { function getAuthInfoFromBrowserCookie (line 26) | function getAuthInfoFromBrowserCookie(): { FILE: src/lib/bangumi.client.ts type BangumiCalendarData (line 3) | interface BangumiCalendarData { function GetBangumiCalendarData (line 25) | async function GetBangumiCalendarData(): Promise { FILE: src/lib/changelog.ts type ChangelogEntry (line 4) | interface ChangelogEntry { FILE: src/lib/config.ts type ApiSite (line 7) | interface ApiSite { type LiveCfg (line 14) | interface LiveCfg { type ConfigFileStruct (line 21) | interface ConfigFileStruct { constant API_CONFIG (line 36) | const API_CONFIG = { function refineConfig (line 61) | function refineConfig(adminConfig: AdminConfig): AdminConfig { function getInitConfig (line 185) | async function getInitConfig(configFile: string, subConfig: { function getConfig (line 293) | async function getConfig(): Promise { function configSelfCheck (line 317) | function configSelfCheck(adminConfig: AdminConfig): AdminConfig { function resetConfig (line 398) | async function resetConfig() { function getCacheTime (line 415) | async function getCacheTime(): Promise { function getAvailableApiSites (line 420) | async function getAvailableApiSites(user?: string): Promise { function setCachedConfig (line 470) | async function setCachedConfig(config: AdminConfig) { FILE: src/lib/crypto.ts class SimpleCrypto (line 7) | class SimpleCrypto { method encrypt (line 14) | static encrypt(data: string, password: string): string { method decrypt (line 29) | static decrypt(encryptedData: string, password: string): string { method canDecrypt (line 50) | static canDecrypt(encryptedData: string, password: string): boolean { FILE: src/lib/db.client.ts function triggerGlobalError (line 21) | function triggerGlobalError(message: string) { type PlayRecord (line 32) | interface PlayRecord { type Favorite (line 46) | interface Favorite { type CacheData (line 58) | interface CacheData { type UserCacheStore (line 64) | interface UserCacheStore { constant PLAY_RECORDS_KEY (line 72) | const PLAY_RECORDS_KEY = 'moontv_play_records'; constant FAVORITES_KEY (line 73) | const FAVORITES_KEY = 'moontv_favorites'; constant SEARCH_HISTORY_KEY (line 74) | const SEARCH_HISTORY_KEY = 'moontv_search_history'; constant CACHE_PREFIX (line 77) | const CACHE_PREFIX = 'moontv_cache_'; constant CACHE_VERSION (line 78) | const CACHE_VERSION = '1.0.0'; constant CACHE_EXPIRE_TIME (line 79) | const CACHE_EXPIRE_TIME = 60 * 60 * 1000; constant STORAGE_TYPE (line 82) | const STORAGE_TYPE = (() => { constant SEARCH_HISTORY_LIMIT (line 97) | const SEARCH_HISTORY_LIMIT = 20; class HybridCacheManager (line 100) | class HybridCacheManager { method getInstance (line 103) | static getInstance(): HybridCacheManager { method getCurrentUsername (line 113) | private getCurrentUsername(): string | null { method getUserCacheKey (line 121) | private getUserCacheKey(username: string): string { method getUserCache (line 128) | private getUserCache(username: string): UserCacheStore { method saveUserCache (line 144) | private saveUserCache(username: string, cache: UserCacheStore): void { method cleanOldCache (line 178) | private cleanOldCache(cache: UserCacheStore): void { method clearAllCache (line 196) | private clearAllCache(): void { method isCacheValid (line 208) | private isCacheValid(cache: CacheData): boolean { method createCacheData (line 219) | private createCacheData(data: T): CacheData { method getCachedPlayRecords (line 230) | getCachedPlayRecords(): Record | null { method cachePlayRecords (line 247) | cachePlayRecords(data: Record): void { method getCachedFavorites (line 259) | getCachedFavorites(): Record | null { method cacheFavorites (line 276) | cacheFavorites(data: Record): void { method getCachedSearchHistory (line 288) | getCachedSearchHistory(): string[] | null { method cacheSearchHistory (line 305) | cacheSearchHistory(data: string[]): void { method getCachedSkipConfigs (line 317) | getCachedSkipConfigs(): Record | null { method cacheSkipConfigs (line 334) | cacheSkipConfigs(data: Record): void { method clearUserCache (line 346) | clearUserCache(username?: string): void { method clearExpiredCaches (line 361) | clearExpiredCaches(): void { function handleDatabaseOperationFailure (line 405) | async function handleDatabaseOperationFailure( function fetchWithAuth (line 459) | async function fetchWithAuth( function fetchFromApi (line 487) | async function fetchFromApi(path: string): Promise { function generateStorageKey (line 495) | function generateStorageKey(source: string, id: string): string { function getAllPlayRecords (line 505) | async function getAllPlayRecords(): Promise> { function savePlayRecord (line 569) | async function savePlayRecord( function deletePlayRecord (line 633) | async function deletePlayRecord( function getSearchHistory (line 694) | async function getSearchHistory(): Promise { function addSearchHistory (line 758) | async function addSearchHistory(keyword: string): Promise { function clearSearchHistory (line 821) | async function clearSearchHistory(): Promise { function deleteSearchHistory (line 859) | async function deleteSearchHistory(keyword: string): Promise { function getAllFavorites (line 915) | async function getAllFavorites(): Promise> { function saveFavorite (line 979) | async function saveFavorite( function deleteFavorite (line 1043) | async function deleteFavorite( function isFavorited (line 1102) | async function isFavorited( function clearAllPlayRecords (line 1158) | async function clearAllPlayRecords(): Promise { function clearAllFavorites (line 1199) | async function clearAllFavorites(): Promise { function clearUserCache (line 1242) | function clearUserCache(): void { function refreshAllCache (line 1252) | async function refreshAllCache(): Promise { function getCacheStatus (line 1310) | function getCacheStatus(): { type CacheUpdateEvent (line 1339) | type CacheUpdateEvent = function subscribeToDataUpdates (line 1356) | function subscribeToDataUpdates( function preloadUserData (line 1379) | async function preloadUserData(): Promise { function getSkipConfig (line 1406) | async function getSkipConfig( function saveSkipConfig (line 1475) | async function saveSkipConfig( function getAllSkipConfigs (line 1539) | async function getAllSkipConfigs(): Promise> { function deleteSkipConfig (line 1603) | async function deleteSkipConfig( FILE: src/lib/db.ts constant STORAGE_TYPE (line 10) | const STORAGE_TYPE = function createStorage (line 19) | function createStorage(): IStorage { function getStorage (line 36) | function getStorage(): IStorage { function generateStorageKey (line 44) | function generateStorageKey(source: string, id: string): string { class DbManager (line 49) | class DbManager { method constructor (line 53) | constructor() { method ensureMigrated (line 69) | private async ensureMigrated(): Promise { method getPlayRecord (line 77) | async getPlayRecord( method savePlayRecord (line 86) | async savePlayRecord( method getAllPlayRecords (line 96) | async getAllPlayRecords(userName: string): Promise<{ method deletePlayRecord (line 103) | async deletePlayRecord( method deleteAllPlayRecords (line 112) | async deleteAllPlayRecords(userName: string): Promise { method getFavorite (line 117) | async getFavorite( method saveFavorite (line 126) | async saveFavorite( method getAllFavorites (line 136) | async getAllFavorites( method deleteFavorite (line 143) | async deleteFavorite( method deleteAllFavorites (line 152) | async deleteAllFavorites(userName: string): Promise { method isFavorited (line 156) | async isFavorited( method registerUser (line 166) | async registerUser(userName: string, password: string): Promise { method verifyUser (line 170) | async verifyUser(userName: string, password: string): Promise { method checkUserExist (line 175) | async checkUserExist(userName: string): Promise { method changePassword (line 179) | async changePassword(userName: string, newPassword: string): Promise { method getSearchHistory (line 188) | async getSearchHistory(userName: string): Promise { method addSearchHistory (line 192) | async addSearchHistory(userName: string, keyword: string): Promise { method getAdminConfig (line 209) | async getAdminConfig(): Promise { method saveAdminConfig (line 216) | async saveAdminConfig(config: AdminConfig): Promise { method getSkipConfig (line 223) | async getSkipConfig( method setSkipConfig (line 234) | async setSkipConfig( method deleteSkipConfig (line 245) | async deleteSkipConfig( method getAllSkipConfigs (line 255) | async getAllSkipConfigs( method clearAllData (line 265) | async clearAllData(): Promise { FILE: src/lib/douban.client.ts type DoubanCategoriesParams (line 5) | interface DoubanCategoriesParams { type DoubanCategoryApiResponse (line 13) | interface DoubanCategoryApiResponse { type DoubanListApiResponse (line 29) | interface DoubanListApiResponse { type DoubanRecommendApiResponse (line 40) | interface DoubanRecommendApiResponse { function fetchWithTimeout (line 60) | async function fetchWithTimeout( function getDoubanProxyConfig (line 95) | function getDoubanProxyConfig(): { function fetchDoubanCategories (line 122) | async function fetchDoubanCategories( function getDoubanCategories (line 195) | async function getDoubanCategories( type DoubanListParams (line 221) | interface DoubanListParams { function getDoubanList (line 228) | async function getDoubanList( function fetchDoubanList (line 254) | async function fetchDoubanList( type DoubanRecommendsParams (line 324) | interface DoubanRecommendsParams { function getDoubanRecommends (line 337) | async function getDoubanRecommends( function fetchDoubanRecommends (line 374) | async function fetchDoubanRecommends( FILE: src/lib/douban.ts function fetchDoubanData (line 6) | async function fetchDoubanData(url: string): Promise { FILE: src/lib/downstream.ts type ApiSearchItem (line 8) | interface ApiSearchItem { function searchWithCache (line 24) | async function searchWithCache( function searchFromApi (line 138) | async function searchFromApi( constant M3U8_PATTERN (line 198) | const M3U8_PATTERN = /(https?:\/\/[^"'\s]+?\.m3u8)/g; function getDetailFromApi (line 200) | async function getDetailFromApi( function handleSpecialSourceDetail (line 289) | async function handleSpecialSourceDetail( FILE: src/lib/fetchVideoDetail.ts type FetchVideoDetailOptions (line 6) | interface FetchVideoDetailOptions { function fetchVideoDetail (line 17) | async function fetchVideoDetail({ FILE: src/lib/kvrocks.db.ts class KvrocksStorage (line 5) | class KvrocksStorage extends BaseRedisStorage { method constructor (line 6) | constructor() { FILE: src/lib/live.ts type LiveChannels (line 8) | interface LiveChannels { function deleteCachedLiveChannels (line 30) | function deleteCachedLiveChannels(key: string) { function getCachedLiveChannels (line 34) | async function getCachedLiveChannels(key: string): Promise RedisCl... function createRedisClient (line 76) | function createRedisClient(config: RedisConnectionConfig, globalSymbol: ... method constructor (line 149) | constructor(config: RedisConnectionConfig, globalSymbol: symbol) { method prHashKey (line 155) | private prHashKey(user: string) { method getPlayRecord (line 159) | async getPlayRecord( method setPlayRecord (line 169) | async setPlayRecord( method getAllPlayRecords (line 179) | async getAllPlayRecords( method deletePlayRecord (line 194) | async deletePlayRecord(userName: string, key: string): Promise { method deleteAllPlayRecords (line 200) | async deleteAllPlayRecords(userName: string): Promise { method favHashKey (line 205) | private favHashKey(user: string) { method getFavorite (line 209) | async getFavorite(userName: string, key: string): Promise { method deleteAllFavorites (line 245) | async deleteAllFavorites(userName: string): Promise { method userPwdKey (line 250) | private userPwdKey(user: string) { method registerUser (line 254) | async registerUser(userName: string, password: string): Promise { method verifyUser (line 261) | async verifyUser(userName: string, password: string): Promise { method checkUserExist (line 277) | async checkUserExist(userName: string): Promise { method changePassword (line 286) | async changePassword(userName: string, newPassword: string): Promise { method shKey (line 315) | private shKey(user: string) { method getSearchHistory (line 319) | async getSearchHistory(userName: string): Promise { method addSearchHistory (line 327) | async addSearchHistory(userName: string, keyword: string): Promise { method deleteSearchHistory (line 337) | async deleteSearchHistory(userName: string, keyword?: string): Promise { method adminConfigKey (line 357) | private adminConfigKey() { method getAdminConfig (line 361) | async getAdminConfig(): Promise { method setAdminConfig (line 366) | async setAdminConfig(config: AdminConfig): Promise { method skipHashKey (line 373) | private skipHashKey(user: string) { method skipField (line 377) | private skipField(source: string, id: string) { method getSkipConfig (line 381) | async getSkipConfig( method setSkipConfig (line 392) | async setSkipConfig( method deleteSkipConfig (line 407) | async deleteSkipConfig( method getAllSkipConfigs (line 417) | async getAllSkipConfigs( method migrationKey (line 433) | private migrationKey() { method migrateData (line 437) | async migrateData(): Promise { method pwdMigrationKey (line 545) | private pwdMigrationKey() { method migratePasswords (line 549) | async migratePasswords(): Promise { method clearAllData (line 579) | async clearAllData(): Promise { FILE: src/lib/redis.db.ts class RedisStorage (line 5) | class RedisStorage extends BaseRedisStorage { method constructor (line 6) | constructor() { FILE: src/lib/search-cache.ts type CachedPageStatus (line 4) | type CachedPageStatus = 'ok' | 'timeout' | 'forbidden'; type CachedPageEntry (line 7) | interface CachedPageEntry { constant SEARCH_CACHE_TTL_MS (line 15) | const SEARCH_CACHE_TTL_MS = 10 * 60 * 1000; constant CACHE_CLEANUP_INTERVAL_MS (line 16) | const CACHE_CLEANUP_INTERVAL_MS = 5 * 60 * 1000; constant MAX_CACHE_SIZE (line 17) | const MAX_CACHE_SIZE = 1000; constant SEARCH_CACHE (line 18) | const SEARCH_CACHE: Map = new Map(); function makeSearchCacheKey (line 27) | function makeSearchCacheKey(sourceKey: string, query: string, page: numb... function getCachedSearchPage (line 34) | function getCachedSearchPage( function setCachedSearchPage (line 55) | function setCachedSearchPage( function ensureAutoCleanupStarted (line 84) | function ensureAutoCleanupStarted(): void { function performCacheCleanup (line 93) | function performCacheCleanup(): { expired: number; total: number; sizeLi... function startAutoCleanup (line 133) | function startAutoCleanup(): void { FILE: src/lib/time.ts function parseCustomTimeFormat (line 5) | function parseCustomTimeFormat(timeStr: string): Date { function formatTimeToHHMM (line 30) | function formatTimeToHHMM(timeString: string): string { function isValidTime (line 49) | function isValidTime(timeString: string): boolean { FILE: src/lib/types.ts type PlayRecord (line 4) | interface PlayRecord { type Favorite (line 18) | interface Favorite { type IStorage (line 30) | interface IStorage { type SearchResult (line 97) | interface SearchResult { type DoubanItem (line 113) | interface DoubanItem { type DoubanResult (line 121) | interface DoubanResult { type SkipConfig (line 128) | interface SkipConfig { FILE: src/lib/upstash.db.ts constant SEARCH_HISTORY_LIMIT (line 10) | const SEARCH_HISTORY_LIMIT = 20; function ensureString (line 13) | function ensureString(value: any): string { function ensureStringArray (line 17) | function ensureStringArray(value: any[]): string[] { function withRetry (line 22) | async function withRetry( class UpstashRedisStorage (line 57) | class UpstashRedisStorage implements IStorage { method constructor (line 60) | constructor() { method prHashKey (line 65) | private prHashKey(user: string) { method getPlayRecord (line 69) | async getPlayRecord( method setPlayRecord (line 79) | async setPlayRecord( method getAllPlayRecords (line 89) | async getAllPlayRecords( method deletePlayRecord (line 105) | async deletePlayRecord(userName: string, key: string): Promise { method deleteAllPlayRecords (line 109) | async deleteAllPlayRecords(userName: string): Promise { method favHashKey (line 114) | private favHashKey(user: string) { method getFavorite (line 118) | async getFavorite(userName: string, key: string): Promise { method deleteAllFavorites (line 153) | async deleteAllFavorites(userName: string): Promise { method userPwdKey (line 158) | private userPwdKey(user: string) { method registerUser (line 162) | async registerUser(userName: string, password: string): Promise { method verifyUser (line 169) | async verifyUser(userName: string, password: string): Promise { method checkUserExist (line 185) | async checkUserExist(userName: string): Promise { method changePassword (line 194) | async changePassword(userName: string, newPassword: string): Promise { method shKey (line 223) | private shKey(user: string) { method getSearchHistory (line 227) | async getSearchHistory(userName: string): Promise { method addSearchHistory (line 235) | async addSearchHistory(userName: string, keyword: string): Promise { method adminConfigKey (line 265) | private adminConfigKey() { method getAdminConfig (line 269) | async getAdminConfig(): Promise { method setAdminConfig (line 274) | async setAdminConfig(config: AdminConfig): Promise { method skipHashKey (line 279) | private skipHashKey(user: string) { method skipField (line 283) | private skipField(source: string, id: string) { method getSkipConfig (line 287) | async getSkipConfig( method setSkipConfig (line 298) | async setSkipConfig( method deleteSkipConfig (line 311) | async deleteSkipConfig( method getAllSkipConfigs (line 321) | async getAllSkipConfigs( method migrationKey (line 338) | private migrationKey() { method migrateData (line 342) | async migrateData(): Promise { method pwdMigrationKey (line 450) | private pwdMigrationKey() { method migratePasswords (line 454) | async migratePasswords(): Promise { method clearAllData (line 484) | async clearAllData(): Promise { function getUpstashRedisClient (line 506) | function getUpstashRedisClient(): Redis { FILE: src/lib/utils.ts function getDoubanImageProxyConfig (line 5) | function getDoubanImageProxyConfig(): { function processImageUrl (line 34) | function processImageUrl(originalUrl: string): string { function getVideoResolutionFromM3u8 (line 68) | async function getVideoResolutionFromM3u8(m3u8Url: string): Promise<{ function cleanHtmlTags (line 219) | function cleanHtmlTags(text: string): string { FILE: src/lib/version.ts constant CURRENT_VERSION (line 3) | const CURRENT_VERSION = '100.1.2'; FILE: src/lib/version_check.ts type UpdateStatus (line 8) | enum UpdateStatus { constant VERSION_CHECK_URLS (line 15) | const VERSION_CHECK_URLS = [ function checkForUpdates (line 23) | async function checkForUpdates(): Promise { function fetchVersionFromUrl (line 50) | async function fetchVersionFromUrl(url: string): Promise { function compareVersions (line 88) | function compareVersions(remoteVersion: string): UpdateStatus { FILE: src/middleware.ts function middleware (line 7) | async function middleware(request: NextRequest) { function verifySignature (line 63) | async function verifySignature( function handleAuthFailure (line 101) | function handleAuthFailure( function shouldSkipAuth (line 119) | function shouldSkipAuth(pathname: string): boolean { FILE: start.js function generateManifest (line 8) | function generateManifest() { constant TARGET_URL (line 30) | const TARGET_URL = `http://${process.env.HOSTNAME || 'localhost'}:${proc... function executeCronJob (line 60) | function executeCronJob() {