{"version":3,"sources":["jsdelivr-header.js","/npm/subdb-downloader@1.0.2/lib/index.js"],"names":[],"mappings":"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","file":"/npm/subdb-downloader@1.0.2/lib/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/subdb-downloader@1.0.2/lib/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const fs             = require('fs');\nconst path           = require('path');\nconst md5            = require('md5');\nconst axios          = require('axios');\nconst find           = require('find');\nconst chokidar       = require('chokidar');\nconst detectEncoding = require('detect-character-encoding');\nconst { Observable } = require('rxjs');\n\nconst regList = {\n    video: /\\.(mp4|avi|mkv|mpeg)$/i,\n    videoTorrent: /\\.(mp4|avi|mkv|mpeg)\\.part$/i,\n    sub: /\\.srt$/i,\n};\nconst hashList = {};\n\nconst instance = axios.create(\n    {\n        // baseURL: 'http://sandbox.thesubdb.com/',\n        baseURL: 'http://api.thesubdb.com/',\n        headers: { 'User-Agent': 'SubDB/1.0 (NodeSubDownloader/1.0.0; https://github.com/EltonFaust/node-subdb-downloader)' },\n    }\n);\n\nconst getDirFiles = (dir, exts) => {\n    let files = find.fileSync(regList[exts], dir);\n\n    return files.map(file => path.resolve(file)).filter((v, i, a) => a.indexOf(v) === i).sort();\n};\n\nconst getDirVideoFiles = (dir) => {\n    return getDirFiles(dir, 'video');\n    // return getDirFiles(dir, ['mp4', 'avi', 'mkv', 'mpeg']);\n};\n\nconst getDirSubFiles = (dir) => {\n    return getDirFiles(dir, 'sub');\n    // return getDirFiles(dir, ['srt']);\n};\n\nconst parseToTime = (value, hasOp) => {\n    const match = /^(?<op>\\+|\\-|)(?<hour>\\d{1,2}):(?<min>\\d{1,2}):(?<sec>\\d{1,2})(\\,|\\.)(?<mils>\\d{1,3})/.exec(value);\n\n    if (!match) {\n        return false;\n    }\n\n    const { op, min, sec, mils, hour } = match.groups;\n\n    const time = Date.parse(`1970-01-01T${('0' + hour).substr(-2)}:${('0' + min).substr(-2)}:${('0' + sec).substr(-2)}.${('00' + mils).substr(-3)}+00:00`);\n\n    if (hasOp && op == '-') {\n        return -time;\n    }\n\n    return time;\n};\n\n// hash = md5 -> first 64 bytes + last 64 bytes\nconst fileHash = (fileName) => {\n    const resolvedFileName = path.resolve(fileName);\n\n    if (typeof hashList[resolvedFileName] !== 'undefined') {\n        return hashList[resolvedFileName];\n    }\n\n    try {\n        const fd = fs.openSync(resolvedFileName, 'r');\n\n        const readsize = 64 * 1024;\n        const stats = fs.statSync(resolvedFileName);\n\n        const bufferInitial = Buffer.alloc(readsize);\n        const bufferfinal = Buffer.alloc(readsize);\n\n        fs.readSync(fd, bufferInitial, 0, readsize, 0);\n        fs.readSync(fd, bufferfinal, 0, readsize, stats.size - readsize);\n\n        hashList[resolvedFileName] = md5(Buffer.concat([ bufferInitial, bufferfinal ], readsize * 2));\n\n        fs.closeSync(fd);\n    } catch(e) {\n        hashList[resolvedFileName] = false;\n    }\n\n    return hashList[resolvedFileName];\n};\n\n// console.log(fileHash('./dexter.mp4'))\n// ffd8d4aa68033dc03d1c8ef373b9028c\n// process.exit(0);\n\nconst dirFilesHash = (dir) => {\n    return getDirVideoFiles(dir).map(file => ({ hash: fileHash(file), fileBaseName: path.basename(file) }));\n};\n\nconst fetchLangs = () => {\n    return new Promise((resolve, reject) => {\n        instance.get('', { params: { action: 'languages' } }).then(({ data }) => {\n            resolve(data.split(','));\n        }).catch(() => {\n            reject(new Error('Can\\'t fetch SubDB languages'));\n        });\n    });\n};\n\nconst fetchLangsForFile = (file) => {\n    return new Promise((resolve, reject) => {\n        const hash = fileHash(file);\n\n        instance.get('', { params: { action: 'search', hash } }).then(({ data }) => {\n            resolve({ hash, langs: data.split(',') });\n            // console.log(data.split(',').map(lang => ` - ${lang}`).join(\"\\n\"));\n        }).catch(() => {\n            reject(new Error('Not found'));\n        });\n    });\n};\n\nconst downloadForFile = (fileName, language) => {\n    return new Promise((resolve, reject) => {\n        const file = path.resolve(fileName);\n        const hash = fileHash(file);\n\n        if (hash === false) {\n            reject(new Error('Invalid hash'));\n            return;\n        }\n\n        instance.get(\n            '',\n            {\n                params: { action: 'download', hash, language },\n                responseType: 'arraybuffer',\n                responseEncoding: 'binary',\n            }\n        ).then(({ data, headers }) => {\n            fs.writeFileSync(file.replace(/\\.[a-z0-9]+$/, '.srt'), data.toString('binary'));\n            resolve({ hash, file, fileBaseName: path.basename(file) });\n        }).catch(() => {\n            reject(new Error(`Subtitle not found for ${hash}`));\n        });\n    });\n};\n\nconst downloadMissingIn = (dir, lang) => {\n    return new Promise((resolve) => {\n        const allVideo = getDirVideoFiles(dir);\n        const allSub = getDirSubFiles(dir).map(file => file.replace(regList.sub, ''));\n\n        const allVideoNoSub = allVideo.filter((file) => {\n            return allSub.indexOf(file.replace(/\\.[a-z0-9]+$/, '')) === -1;\n        });\n\n        const data = {\n            success: [],\n            failed: [],\n        };\n\n        const processItem = () => {\n            const file = allVideoNoSub.shift();\n\n            if (typeof file === 'undefined') {\n                resolve(data);\n                return;\n            }\n\n            downloadForFile(file, lang).then((info) => {\n                data.success.push(info);\n                processItem();\n            }).catch((e) => {\n                data.failed.push({ file, fileBaseName: path.basename(file), message: e.message });\n                processItem();\n            });\n        };\n\n        processItem();\n    });\n};\n\nconst watchDir = (baseDir, lang) => {\n    return Observable.create((observer) => {\n        const fileTimer = {};\n        const torrentFiles = [];\n        const dir = path.resolve(baseDir);\n\n        const processFile = (event, filename) => {\n            if (!regList.video.test(filename)) {\n                if (regList.videoTorrent.test(filename)) {\n                    // torrent file being downloaded\n                    torrentFiles.push(filename.replace(/\\.[a-z0-9]+$/i, ''));\n                }\n\n                return;\n            }\n\n            if (event == 'add' && torrentFiles.indexOf(filename) === -1 && fs.existsSync(filename.replace(/\\.[a-z0-9]+$/i, '.srt'))) {\n                // event \"add\" is called on initialized, ignore if already have a subtitle file\n                return;\n            }\n\n            const fileBaseName = path.basename(filename);\n\n            observer.next({ type: 'changed', filename, fileBaseName });\n\n            if (typeof fileTimer[filename] !== 'undefined') {\n                clearTimeout(fileTimer[filename]);\n            }\n\n            fileTimer[filename] = setTimeout(\n                () => {\n                    delete fileTimer[filename];\n                    delete hashList[filename];\n\n                    downloadForFile(filename, lang).then(({ hash, fileBaseName }) => {\n                        observer.next({ type: 'downloaded', filename, fileBaseName, hash });\n                    }).catch((e) => {\n                        observer.next({ type: 'error', filename, fileBaseName, message: e.message });\n                    });\n                },\n                2000\n            );\n        };\n\n        chokidar.watch(dir, { ignored: /(^|[\\/\\\\])\\..|\\.srt/, persistent: true })\n            .on('add', (filename) => processFile('add', filename))\n            .on('change', (filename) => processFile('add', filename));\n    })\n};\n\nconst ajustFiles = (files, value) => {\n    return new Promise((resolve, reject) => {\n        const filesList = files.map((file) => {\n            if (regList.video.test(file)) {\n                return path.resolve(file).replace(/\\.[a-z0-9]+$/, '.srt');\n            }\n\n            return path.resolve(file);\n        });\n\n        const notFound = filesList.filter(file => !fs.existsSync(file));\n\n        if (notFound.length > 0) {\n            reject(new Error(`Files not found:\\n${notFound.map(file => ` - ${file}`).join(\"\\n\")}`));\n            return;\n        }\n\n        const inc = parseToTime(value, true);\n\n        if (inc === false || inc === 0) {\n            reject(new Error('Invalid incremental value'));\n            return;\n        }\n\n        const finalList = [];\n\n        filesList.forEach((file) => {\n            let content = fs.readFileSync(file);\n            const encoding = detectEncoding(content).encoding == 'ISO-8859-1' ? 'latin1' : 'utf8';\n            content = fs.readFileSync(file, encoding).toString();\n\n            finalList.push(\n                {\n                    file,\n                    fileBaseName: path.basename(file),\n                    encoding,\n                }\n            );\n\n            fs.renameSync(file, file.replace(regList.sub, `.srt_${Date.now()}`));\n\n            const matchAll = content.match(/\\d{2}\\:\\d{2}\\:\\d{2}\\,\\d{3} \\-\\-> \\d{2}\\:\\d{2}\\:\\d{2}\\,\\d{3}/g);\n\n            if (inc > 0) {\n                matchAll.reverse();\n            }\n\n            matchAll.forEach((item) => {\n                const { initial, final } = /(?<initial>.*) \\-\\-> (?<final>.*)/.exec(item).groups;\n\n                const initialStr = (new Date(Math.max(0, parseToTime(initial) + inc))).toISOString().substr(11, 12).replace(/\\./, ',');\n                const finalStr = (new Date(Math.max(0, parseToTime(final) + inc))).toISOString().substr(11, 12).replace(/\\./, ',');\n\n                content = content.replace(new RegExp(item), `${initialStr} --> ${finalStr}`);\n            });\n\n            fs.writeFileSync(file, content, { encoding });\n        });\n\n        resolve(finalList);\n    });\n};\n\nconst ajustFilesIn = (dir, value) => {\n    return ajustFiles(getDirSubFiles(dir), value);\n};\n\nmodule.exports = {\n    fileHash,\n    dirFilesHash,\n    fetchLangs,\n    fetchLangsForFile,\n    downloadForFile,\n    downloadMissingIn,\n    watchDir,\n    ajustFiles,\n    ajustFilesIn,\n};\n"]}