import axios from 'axios'; import JSZip from 'jszip'; import * as FileSystem from 'expo-file-system'; import { Platform } from 'react-native'; import translator from '@/constants/module/translator'; import Storage from '@/constants/module/storages/storage'; import ComicStorage from '@/constants/module/storages/comic_storage'; import ImageCacheStorage from '@/constants/module/storages/image_cache_storage'; import ChapterStorage from '@/constants/module/storages/chapter_storage'; import ChapterDataStorage from '@/constants/module/storages/chapter_data_storage'; import CoverStorage from '@/constants/module/storages/cover_storage'; import {blobToBase64} from '@/constants/module/file_manager'; import { getImageLayout } from '@/constants/module/file_manager'; export const get = async (setShowCloudflareTurnstile:any,setIsLoading:any,signal:AbortSignal,translate:any,setFeedBack:any,source:any,id:any,SET_CONTENT:any) => { const API_BASE = await Storage.get("IN_USE_API_BASE") axios({ method: 'post', url: `${API_BASE}/api/web_scrap/get/`, headers: { 'X-CLOUDFLARE-TURNSTILE-TOKEN': await Storage.get("cloudflare-turnstile-token") }, data: { id:id, source:source, }, timeout: 60000, signal:signal, }).then((response) => {(async () =>{ const DATA = response.data console.log("EEE",response) if (Object.keys(DATA).length) setFeedBack("") else{ setFeedBack("No content found!") return } DATA["cover"] = {uri:`${API_BASE}${DATA.cover}`} DATA["category"] = DATA.category.join(" | ") if (translate.state){ DATA["title"] = await translator(translate.from,translate.to,DATA.title) DATA["author"] = await translator(translate.from,translate.to,DATA.author) DATA["status"] = await translator(translate.from,translate.to,DATA.status) DATA["category"] = await translator(translate.from,translate.to,DATA.category) DATA["synopsis"] = await translator(translate.from,translate.to,DATA.synopsis) SET_CONTENT(DATA) } else { SET_CONTENT(DATA) } // Store in local if bookmarked. const stored_comic = await ComicStorage.getByID(source,DATA.id) if (stored_comic) { await ComicStorage.updateInfo(source,DATA.id, { title:DATA.title, author:DATA.author, category:DATA.category, status:DATA.status, synopsis:DATA.synopsis, updated:DATA.updated, }) await store_comic_cover(setShowCloudflareTurnstile,signal,source,id,DATA) for (const chapter of DATA.chapters) { const stored_chapter = await ChapterStorage.get(`${source}-${DATA.id}`,chapter.id) if (!stored_chapter) await ChapterStorage.add(`${source}-${DATA.id}`, chapter.idx, chapter.id, chapter.title, {}); } } setIsLoading(false) })()}).catch((error) => { console.log(error) if (error.status === 511) setShowCloudflareTurnstile(true) setFeedBack("Error unable to fetch data! Try request again.") setIsLoading(false) }) } export const store_comic_cover = async ( setShowCloudflareTurnstile:any, signal:any, source:string | string[], comic_id:string| string[], CONTENT:any ) => { const result = await ImageCacheStorage.get(setShowCloudflareTurnstile,CONTENT.cover.uri,signal); if (result.type === "file_path"){ const from_path = result.data const storage_dir = FileSystem.documentDirectory + "ComicMTL/" + `${source}/` + `${comic_id}/`; try{ const dirInfo = await FileSystem.getInfoAsync(storage_dir); if (!dirInfo.exists) await FileSystem.makeDirectoryAsync(storage_dir, { intermediates: true }); await FileSystem.copyAsync({ from: from_path, to: storage_dir + "cover.png", }); }catch (error: any) { console.log("store_comic_cover: ", error) } }else { CoverStorage.store(`${source}-${comic_id}`,result) // return result } } export const get_requested_info = async ( setShowCloudflareTurnstile:any, chapter_requested:any, chapter_to_download:any, signal:any, source:any, comic_id:any, ) => { const API_BASE = await Storage.get("IN_USE_API_BASE") const socket_info = await Storage.get("SOCKET_INFO") const stored_comic = await ComicStorage.getByID(source,comic_id) await axios({ method: 'post', url: `${API_BASE}/api/queue/request_info/`, headers: { 'X-CLOUDFLARE-TURNSTILE-TOKEN': await Storage.get("cloudflare-turnstile-token") }, data: { socket_id: socket_info.id, source:source, comic_id:comic_id, chapter_requested:stored_comic.chapter_requested, }, timeout: 30000, signal:signal, }).then((response) => { const DATA = response.data chapter_requested.current = DATA const new_obj:any = {} for (const [key, value] of Object.entries(DATA) as any) { if (value.state === "ready") { new_obj[key] = { chapter_idx: value.chapter_idx, options: value.options, state: chapter_to_download.current[key]?.state, } } } chapter_to_download.current = new_obj }).catch((error) => { console.log(error) if (error.status === 511) setShowCloudflareTurnstile(true) }) } export const download_chapter = async ( setShowCloudflareTurnstile:any, isDownloading:any, source:string | string[], comic_id:string | string[], chapter_requested:any, chapter_to_download:any, download_progress:any, signal:any ) => { const API_BASE = await Storage.get("IN_USE_API_BASE") const [chapter_id, request_info]:any = Object.entries(chapter_to_download.current)[0]; const stored_chapter = await ChapterStorage.get(`${source}-${comic_id}`,chapter_id) if (stored_chapter.data_state === "completed") { const stored_chapter_requested = (await ComicStorage.getByID(source,comic_id)).chapter_requested const new_chapter_requested = stored_chapter_requested.filter((item:any) => item.chapter_id !== chapter_id); await ComicStorage.updateChapterQueue(source,comic_id,new_chapter_requested) delete chapter_requested.current[chapter_id] delete chapter_to_download.current[chapter_id] delete download_progress.current[chapter_id] isDownloading.current = false return } var progress_lenth:number = 0 var total_length:number = 0 await axios({ method: 'post', url: `${API_BASE}/api/stream_file/download_chapter/`, responseType: 'blob', headers: { 'X-CLOUDFLARE-TURNSTILE-TOKEN': await Storage.get("cloudflare-turnstile-token") }, data: { source:source, comic_id:comic_id, chapter_id:chapter_id, chapter_idx:request_info.chapter_idx, options:request_info.options, }, onDownloadProgress: (progressEvent) => { const _total_length = progressEvent.total if (total_length !== undefined && progressEvent.loaded !== progress_lenth) { total_length = (_total_length as number) + (_total_length as number)*0.25 if (progress_lenth === 0) { download_progress.current = { ...download_progress.current, [chapter_id]:{progress:progress_lenth, total:total_length }} chapter_to_download.current = { ...chapter_to_download.current, [chapter_id]:{...chapter_to_download.current[chapter_id], state:"downloading" }} progress_lenth = progressEvent.loaded; }else{ progress_lenth = progressEvent.loaded; download_progress.current = {...download_progress.current, [chapter_id]:{progress:progress_lenth, total:total_length}} } } }, timeout: 600000, signal:signal, }).then(async (response) => { const DATA = response.data if (Platform.OS === "web"){ const zip = new JSZip(); const zipContent = await zip.loadAsync(DATA); const MAX_PAGE = Object.keys(zipContent.files).length let page = 0; for (const fileName of Object.keys(zipContent.files).sort((a,b) => parseInt(a, 10) - parseInt(b, 10))) { if (zipContent.files[fileName].dir) { continue; // Skip directories } page += 1 const fileData = await zipContent.files[fileName].async('blob'); const layout = await getImageLayout(await blobToBase64(fileData, "image/png")); await ChapterDataStorage.store(`${source}-${comic_id}-${request_info.chapter_idx}-${page}`,comic_id,request_info.chapter_idx, fileData, layout) const current_progress = progress_lenth + ((total_length-progress_lenth)*page)/MAX_PAGE download_progress.current = {...download_progress.current, [chapter_id]:{progress:current_progress, total:total_length}} } await ChapterStorage.update(`${source}-${comic_id}`,chapter_id, "completed", page) }else{ // const chapter_dir = FileSystem.documentDirectory + "ComicMTL/" + `${source}/` + `${comic_id}/` + `chapters/`; // const dirInfo = await FileSystem.getInfoAsync(chapter_dir); // if (!dirInfo.exists) await FileSystem.makeDirectoryAsync(chapter_dir, { intermediates: true }); // await FileSystem.writeAsStringAsync(chapter_dir + `${request_info.chapter_idx}.zip`, (await blobToBase64(DATA)).split(',')[1], { // encoding: FileSystem.EncodingType.Base64, // }); // await ChapterStorage.update(`${source}-${comic_id}`,chapter_id,{type:"file_path", value:chapter_dir + `${request_info.chapter_idx}.zip`}, "completed") } // download_progress.current = {...download_progress.current, [chapter_id]:{progress:total_length, total:total_length}} }).catch(async (error) => { console.log(error) if (error.status === 511) setShowCloudflareTurnstile(true) else { delete chapter_requested.current[chapter_id] delete chapter_to_download.current[chapter_id] const stored_chapter_requested = (await ComicStorage.getByID(source,comic_id)).chapter_requested const new_chapter_requested = stored_chapter_requested.filter((item:any) => item.chapter_id !== chapter_id); await ComicStorage.updateChapterQueue(source,comic_id,new_chapter_requested) isDownloading.current = false } }) }