SYMBOL INDEX (210 symbols across 19 files) FILE: api/proxy/[...path].mjs constant DEBUG_ENABLED (line 8) | const DEBUG_ENABLED = process.env.DEBUG === 'true'; constant CACHE_TTL (line 9) | const CACHE_TTL = parseInt(process.env.CACHE_TTL || '86400', 10); constant MAX_RECURSION (line 10) | const MAX_RECURSION = parseInt(process.env.MAX_RECURSION || '5', 10); constant USER_AGENTS (line 14) | let USER_AGENTS = [ constant FILTER_DISCONTINUITY (line 39) | const FILTER_DISCONTINUITY = false; function logDebug (line 44) | function logDebug(message) { function getTargetUrlFromPath (line 55) | function getTargetUrlFromPath(encodedPath) { function getBaseUrl (line 81) | function getBaseUrl(urlStr) { function resolveUrl (line 103) | function resolveUrl(baseUrl, relativeUrl) { function rewriteUrlToProxy (line 129) | function rewriteUrlToProxy(targetUrl) { function getRandomUserAgent (line 135) | function getRandomUserAgent() { function fetchContentWithType (line 139) | async function fetchContentWithType(targetUrl, requestHeaders) { function isM3u8Content (line 182) | function isM3u8Content(content, contentType) { function processKeyLine (line 189) | function processKeyLine(line, baseUrl) { function processMapLine (line 197) | function processMapLine(line, baseUrl) { function processMediaPlaylist (line 205) | function processMediaPlaylist(url, content) { function processM3u8Content (line 233) | async function processM3u8Content(targetUrl, content, recursionDepth = 0) { function processMasterPlaylist (line 243) | async function processMasterPlaylist(url, content, recursionDepth) { function validateAuth (line 306) | async function validateAuth(req) { function handler (line 339) | async function handler(req, res) { FILE: functions/_middleware.js function onRequest (line 3) | async function onRequest(context) { FILE: functions/proxy/[[path]].js constant MEDIA_FILE_EXTENSIONS (line 14) | const MEDIA_FILE_EXTENSIONS = [ constant MEDIA_CONTENT_TYPES (line 19) | const MEDIA_CONTENT_TYPES = ['video/', 'audio/', 'image/']; function onRequest (line 27) | async function onRequest(context) { function onOptions (line 582) | async function onOptions(context) { FILE: js/api.js function handleApiRequest (line 2) | async function handleApiRequest(url) { function handleCustomApiSpecialDetail (line 213) | async function handleCustomApiSpecialDetail(id, customApi) { function handleSpecialSourceDetail (line 280) | async function handleSpecialSourceDetail(id, sourceCode) { function handleAggregatedSearch (line 359) | async function handleAggregatedSearch(searchQuery) { function handleMultipleCustomSearch (line 472) | async function handleMultipleCustomSearch(searchQuery, customApiUrls) { function testSiteAvailability (line 615) | async function testSiteAvailability(apiUrl) { FILE: js/app.js function initAPICheckboxes (line 65) | function initAPICheckboxes() { function addAdultAPI (line 112) | function addAdultAPI() { function checkAdultAPIsSelected (line 159) | function checkAdultAPIsSelected() { function renderCustomAPIsList (line 210) | function renderCustomAPIsList() { function editCustomApi (line 255) | function editCustomApi(index) { function updateCustomApi (line 275) | function updateCustomApi(index) { function cancelEditCustomApi (line 309) | function cancelEditCustomApi() { function restoreAddCustomApiButtons (line 325) | function restoreAddCustomApiButtons() { function updateSelectedAPIs (line 335) | function updateSelectedAPIs() { function updateSelectedApiCount (line 357) | function updateSelectedApiCount() { function selectAllAPIs (line 365) | function selectAllAPIs(selectAll = true, excludeAdult = false) { function showAddCustomApiForm (line 381) | function showAddCustomApiForm() { function cancelAddCustomApi (line 389) | function cancelAddCustomApi() { function addCustomApi (line 405) | function addCustomApi() { function removeCustomApi (line 445) | function removeCustomApi(index) { function toggleSettings (line 483) | function toggleSettings(e) { function setupEventListeners (line 500) | function setupEventListeners() { function resetSearchArea (line 562) | function resetSearchArea() { function getCustomApiInfo (line 598) | function getCustomApiInfo(customApiIndex) { function search (line 607) | async function search() { function toggleClearButton (line 814) | function toggleClearButton() { function clearSearchInput (line 825) | function clearSearchInput() { function hookInput (line 833) | function hookInput() { function showDetails (line 858) | async function showDetails(id, vod_name, sourceCode) { function playVideo (line 990) | function playVideo(url, vod_name, sourceCode, episodeIndex = 0, vodId = ... function showVideoPlayer (line 1028) | function showVideoPlayer(url) { function closeVideoPlayer (line 1048) | function closeVideoPlayer(home = false) { function playPreviousEpisode (line 1071) | function playPreviousEpisode(sourceCode) { function playNextEpisode (line 1080) | function playNextEpisode(sourceCode) { function handlePlayerError (line 1089) | function handlePlayerError() { function renderEpisodes (line 1095) | function renderEpisodes(vodName, sourceCode, vodId) { function copyLinks (line 1110) | function copyLinks() { function toggleEpisodeOrder (line 1121) | function toggleEpisodeOrder(sourceCode, vodId) { function importConfigFromUrl (line 1141) | async function importConfigFromUrl() { function importConfig (line 1253) | async function importConfig() { function exportConfig (line 1295) | async function exportConfig() { function saveStringAsFile (line 1340) | function saveStringAsFile(content, fileName) { FILE: js/config.js constant PROXY_URL (line 2) | const PROXY_URL = '/proxy/'; constant SEARCH_HISTORY_KEY (line 4) | const SEARCH_HISTORY_KEY = 'videoSearchHistory'; constant MAX_HISTORY_ITEMS (line 5) | const MAX_HISTORY_ITEMS = 5; constant PASSWORD_CONFIG (line 9) | const PASSWORD_CONFIG = { constant SITE_CONFIG (line 15) | const SITE_CONFIG = { constant API_SITES (line 24) | const API_SITES = { function extendAPISites (line 34) | function extendAPISites(newSites) { constant AGGREGATED_SEARCH_CONFIG (line 44) | const AGGREGATED_SEARCH_CONFIG = { constant API_CONFIG (line 53) | const API_CONFIG = { constant M3U8_PATTERN (line 75) | const M3U8_PATTERN = /\$https?:\/\/[^"'\s]+?\.m3u8/g; constant CUSTOM_PLAYER_URL (line 78) | const CUSTOM_PLAYER_URL = 'player.html'; constant PLAYER_CONFIG (line 81) | const PLAYER_CONFIG = { constant ERROR_MESSAGES (line 94) | const ERROR_MESSAGES = { constant SECURITY_CONFIG (line 103) | const SECURITY_CONFIG = { constant CUSTOM_API_CONFIG (line 111) | const CUSTOM_API_CONFIG = { constant HIDE_BUILTIN_ADULT_APIS (line 123) | const HIDE_BUILTIN_ADULT_APIS = false; FILE: js/customer_site.js constant CUSTOMER_SITES (line 1) | const CUSTOMER_SITES = { FILE: js/douban.js function loadUserTags (line 12) | function loadUserTags() { function saveUserTags (line 41) | function saveUserTags() { function initDouban (line 57) | function initDouban() { function updateDoubanVisibility (line 116) | function updateDoubanVisibility() { function fillSearchInput (line 137) | function fillSearchInput(title) { function fillAndSearch (line 159) | function fillAndSearch(title) { function fillAndSearchWithDouban (line 192) | async function fillAndSearchWithDouban(title) { function renderDoubanMovieTvSwitch (line 259) | function renderDoubanMovieTvSwitch() { function renderDoubanTags (line 319) | function renderDoubanTags(tags) { function setupDoubanRefreshBtn (line 369) | function setupDoubanRefreshBtn() { function fetchDoubanTags (line 384) | function fetchDoubanTags() { function renderRecommend (line 410) | function renderRecommend(tag, pageLimit, pageStart) { function fetchDoubanData (line 444) | async function fetchDoubanData(url) { function renderDoubanCards (line 503) | function renderDoubanCards(data, container) { function resetToHome (line 574) | function resetToHome() { function showTagManageModal (line 583) | function showTagManageModal() { function addTag (line 696) | function addTag(tag) { function deleteTag (line 734) | function deleteTag(tag) { function resetTagsToDefault (line 770) | function resetTagsToDefault() { FILE: js/password.js function isPasswordProtected (line 7) | function isPasswordProtected() { function isPasswordRequired (line 20) | function isPasswordRequired() { function ensurePasswordProtection (line 28) | function ensurePasswordProtection() { function verifyPassword (line 46) | async function verifyPassword(password) { function isPasswordVerified (line 69) | function isPasswordVerified() { function sha256 (line 95) | async function sha256(message) { function showPasswordModal (line 112) | function showPasswordModal() { function hidePasswordModal (line 165) | function hidePasswordModal() { function showPasswordError (line 188) | function showPasswordError() { function hidePasswordError (line 198) | function hidePasswordError() { function handlePasswordSubmit (line 208) | async function handlePasswordSubmit() { function initPasswordProtection (line 228) | function initPasswordProtection() { FILE: js/player.js function goBack (line 5) | function goBack(event) { function initializePageContent (line 117) | function initializePageContent() { function handleKeyboardShortcuts (line 285) | function handleKeyboardShortcuts(e) { function showShortcutHint (line 363) | function showShortcutHint(text, direction) { function initPlayer (line 400) | function initPlayer(videoUrl) { class CustomHlsJsLoader (line 762) | class CustomHlsJsLoader extends Hls.DefaultConfig.loader { method constructor (line 763) | constructor(config) { function filterAdsFromM3U8 (line 786) | function filterAdsFromM3U8(m3u8Content, strictMode = false) { function showError (line 807) | function showError(message) { function updateEpisodeInfo (line 821) | function updateEpisodeInfo() { function updateButtonStates (line 830) | function updateButtonStates() { function renderEpisodes (line 858) | function renderEpisodes() { function playEpisode (line 888) | function playEpisode(index) { function playPreviousEpisode (line 954) | function playPreviousEpisode() { function playNextEpisode (line 961) | function playNextEpisode() { function copyLinks (line 968) | function copyLinks() { function toggleEpisodeOrder (line 982) | function toggleEpisodeOrder() { function updateOrderButton (line 996) | function updateOrderButton() { function setupProgressBarPreciseClicks (line 1007) | function setupProgressBarPreciseClicks() { function saveToHistory (line 1076) | function saveToHistory() { function showPositionRestoreHint (line 1175) | function showPositionRestoreHint(position) { function formatTime (line 1208) | function formatTime(seconds) { function startProgressSaveInterval (line 1218) | function startProgressSaveInterval() { function saveCurrentProgress (line 1229) | function saveCurrentProgress() { function setupLongPressSpeedControl (line 1274) | function setupLongPressSpeedControl() { function clearVideoProgress (line 1389) | function clearVideoProgress() { function getVideoId (line 1398) | function getVideoId() { function toggleControlsLock (line 1408) | function toggleControlsLock() { function closeEmbeddedPlayer (line 1420) | function closeEmbeddedPlayer() { function renderResourceInfoBar (line 1435) | function renderResourceInfoBar() { function testVideoSourceSpeed (line 1489) | async function testVideoSourceSpeed(sourceKey, vodId) { function formatSpeedDisplay (line 1575) | function formatSpeedDisplay(speedResult) { function showSwitchResourceModal (line 1596) | async function showSwitchResourceModal() { function switchToResource (line 1715) | async function switchToResource(sourceKey, vodId) { FILE: js/proxy-auth.js function getPasswordHash (line 12) | async function getPasswordHash() { function addAuthToProxyUrl (line 60) | async function addAuthToProxyUrl(url) { function validateProxyAuth (line 84) | function validateProxyAuth(authHash, serverPasswordHash, timestamp) { function clearAuthCache (line 109) | function clearAuthCache() { FILE: js/search.js function searchByAPIAndKeyWord (line 1) | async function searchByAPIAndKeyWord(apiId, query) { FILE: js/sha256.js function sha256 (line 1) | async function sha256(message) { FILE: js/ui.js function toggleSettings (line 2) | function toggleSettings(e) { function showToast (line 30) | function showToast(message, type = 'error') { function showNextToast (line 57) | function showNextToast() { function showLoading (line 99) | function showLoading(message = '加载中...') { function hideLoading (line 117) | function hideLoading() { function updateSiteStatus (line 128) | function updateSiteStatus(isAvailable) { function closeModal (line 137) | function closeModal() { function getSearchHistory (line 144) | function getSearchHistory() { function saveSearchHistory (line 168) | function saveSearchHistory(query) { function renderSearchHistory (line 217) | function renderSearchHistory() { function deleteSingleSearchHistory (line 275) | function deleteSingleSearchHistory(query) { function clearSearchHistory (line 290) | function clearSearchHistory() { function toggleHistory (line 309) | function toggleHistory(e) { function formatTimestamp (line 337) | function formatTimestamp(timestamp) { function getViewingHistory (line 371) | function getViewingHistory() { function loadViewingHistory (line 382) | function loadViewingHistory() { function formatPlaybackTime (line 471) | function formatPlaybackTime(seconds) { function deleteHistoryItem (line 481) | function deleteHistoryItem(encodedUrl) { function playFromHistory (line 507) | async function playFromHistory(url, title, episodeIndex, playbackPositio... function addToViewingHistory (line 684) | function addToViewingHistory(videoInfo) { function clearViewingHistory (line 769) | function clearViewingHistory() { function clearLocalStorage (line 811) | function clearLocalStorage() { function showImportBox (line 900) | function showImportBox(fun) { FILE: js/version-check.js function fetchVersion (line 21) | async function fetchVersion(url, errorMessage, options = {}) { function checkForUpdates (line 30) | async function checkForUpdates() { function formatVersion (line 88) | function formatVersion(versionString) { function createErrorVersionElement (line 112) | function createErrorVersionElement(errorMessage) { function addVersionInfoToFooter (line 121) | function addVersionInfoToFooter() { function displayVersionElement (line 171) | function displayVersionElement(element) { FILE: middleware.js function middleware (line 4) | async function middleware(request) { FILE: netlify/edge-functions/inject-env.js function sha256 (line 24) | async function sha256(message) { FILE: netlify/functions/proxy.mjs constant DEBUG_ENABLED (line 8) | const DEBUG_ENABLED = process.env.DEBUG === 'true'; constant CACHE_TTL (line 9) | const CACHE_TTL = parseInt(process.env.CACHE_TTL || '86400', 10); constant MAX_RECURSION (line 10) | const MAX_RECURSION = parseInt(process.env.MAX_RECURSION || '5', 10); constant USER_AGENTS (line 13) | let USER_AGENTS = [ constant FILTER_DISCONTINUITY (line 33) | const FILTER_DISCONTINUITY = false; function logDebug (line 37) | function logDebug(message) { function getTargetUrlFromPath (line 43) | function getTargetUrlFromPath(encodedPath) { function getBaseUrl (line 56) | function getBaseUrl(urlStr) { function resolveUrl (line 71) | function resolveUrl(baseUrl, relativeUrl) { function rewriteUrlToProxy (line 82) | function rewriteUrlToProxy(targetUrl) { function getRandomUserAgent (line 88) | function getRandomUserAgent() { return USER_AGENTS[Math.floor(Math.rando... function validateAuth (line 93) | function validateAuth(event) { function fetchContentWithType (line 126) | async function fetchContentWithType(targetUrl, requestHeaders) { function isM3u8Content (line 153) | function isM3u8Content(content, contentType) { function processKeyLine (line 158) | function processKeyLine(line, baseUrl) { return line.replace(/URI="([^"]... function processMapLine (line 159) | function processMapLine(line, baseUrl) { return line.replace(/URI="([^"]... function processMediaPlaylist (line 160) | function processMediaPlaylist(url, content) { function processM3u8Content (line 172) | async function processM3u8Content(targetUrl, content, recursionDepth = 0) { function processMasterPlaylist (line 176) | async function processMasterPlaylist(url, content, recursionDepth) { FILE: server.mjs function sha256Hash (line 47) | function sha256Hash(input) { function renderPage (line 55) | async function renderPage(filePath, password) { function isValidUrl (line 97) | function isValidUrl(urlString) { function validateProxyAuth (line 122) | function validateProxyAuth(req) {