import SocketService from "../services/DcppSearchService"; import { SearchQuery, SearchInstance, PriorityEnum, SearchResponse, } from "threetwo-ui-typings"; import { LIBRARY_SERVICE_BASE_URI } from "../constants/endpoints"; import { AIRDCPP_SEARCH_RESULTS_ADDED, AIRDCPP_SEARCH_RESULTS_UPDATED, AIRDCPP_HUB_SEARCHES_SENT, AIRDCPP_RESULT_DOWNLOAD_INITIATED, AIRDCPP_DOWNLOAD_PROGRESS_TICK, AIRDCPP_BUNDLES_FETCHED, AIRDCPP_SEARCH_IN_PROGRESS, AIRDCPP_FILE_DOWNLOAD_COMPLETED, LS_SINGLE_IMPORT, IMS_COMIC_BOOK_DB_OBJECT_FETCHED, } from "../constants/action-types"; import { isNil } from "lodash"; import axios from "axios"; interface SearchData { query: Pick & Partial>; hub_urls: string[] | undefined | null; priority: PriorityEnum; } function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } export const search = (data: SearchData, ADCPPSocket: any, credentials: any) => async (dispatch) => { try { if (!ADCPPSocket.isConnected()) { await ADCPPSocket.connect( credentials.username, credentials.password, true, ); } const instance: SearchInstance = await ADCPPSocket.post("search"); dispatch({ type: AIRDCPP_SEARCH_IN_PROGRESS, }); // We want to get notified about every new result in order to make the user experience better await ADCPPSocket.addListener( `search`, "search_result_added", async (groupedResult) => { // ...add the received result in the UI // (it's probably a good idea to have some kind of throttling for the UI updates as there can be thousands of results) dispatch({ type: AIRDCPP_SEARCH_RESULTS_ADDED, groupedResult, }); }, instance.id, ); // We also want to update the existing items in our list when new hits arrive for the previously listed files/directories await ADCPPSocket.addListener( `search`, "search_result_updated", async (groupedResult) => { // ...update properties of the existing result in the UI dispatch({ type: AIRDCPP_SEARCH_RESULTS_UPDATED, groupedResult, }); }, instance.id, ); // We need to show something to the user in case the search won't yield any results so that he won't be waiting forever) // Wait for 5 seconds for any results to arrive after the searches were sent to the hubs await ADCPPSocket.addListener( `search`, "search_hub_searches_sent", async (searchInfo) => { await sleep(5000); // Check the number of received results (in real use cases we should know that even without calling the API) const currentInstance = await ADCPPSocket.get( `search/${instance.id}`, ); if (currentInstance.result_count === 0) { // ...nothing was received, show an informative message to the user console.log("No more search results."); } // The search can now be considered to be "complete" // If there's an "in progress" indicator in the UI, that could also be disabled here dispatch({ type: AIRDCPP_HUB_SEARCHES_SENT, searchInfo, instance, }); }, instance.id, ); // Finally, perform the actual search await ADCPPSocket.post(`search/${instance.id}/hub_search`, data); } catch (error) { console.log(error); throw error; } }; export const downloadAirDCPPItem = ( instanceId: string, resultId: string, comicObjectId: string, comicObject: any, ADCPPSocket: any, credentials: any, ): void => async (dispatch) => { try { if (!ADCPPSocket.isConnected()) { await ADCPPSocket.connect( `${credentials.username}`, `${credentials.password}`, true, ); } console.log(comicObject); let bundleDBImportResult = {}; const downloadResult = await ADCPPSocket.post( `search/${instanceId}/results/${resultId}/download`, ); let downloadStatus = undefined; let count = 0; // download status check await ADCPPSocket.addListener(`queue`, "queue_file_status", (status) => { if (status.status.completed) { downloadStatus = status; if (count === 0) { dispatch({ type: LS_SINGLE_IMPORT, meta: { remote: true }, data: { downloadStatus, comicObjectId, comicObject }, }); } count += 1; } }); let bundleId; let directoryIds; if (!isNil(downloadResult.bundle_info)) { bundleId = downloadResult.bundle_info.id; } if (!isNil(downloadResult.directory_download_ids)) { directoryIds = downloadResult.directory_download_ids.map( (item) => item.id, ); } if (!isNil(downloadResult)) { bundleDBImportResult = await axios({ method: "POST", url: `${LIBRARY_SERVICE_BASE_URI}/applyAirDCPPDownloadMetadata`, headers: { "Content-Type": "application/json; charset=utf-8", }, data: { resultId, comicObjectId, searchInstanceId: instanceId, bundleId, directoryIds, }, }); dispatch({ type: AIRDCPP_RESULT_DOWNLOAD_INITIATED, downloadResult: downloadResult, bundleDBImportResult, }); dispatch({ type: IMS_COMIC_BOOK_DB_OBJECT_FETCHED, comicBookDetail: bundleDBImportResult.data, IMS_inProgress: false, }); } } catch (error) { throw error; } }; export const getDownloadProgress = (comicObjectId: string, ADCPPSocket: any, credentials: any): void => async (dispatch) => { try { if (!ADCPPSocket.isConnected()) { await ADCPPSocket.connect( `${credentials.username}`, `${credentials.password}`, true, ); } await ADCPPSocket.addListener( `queue`, "queue_bundle_tick", async (downloadProgressData) => { dispatch({ type: AIRDCPP_DOWNLOAD_PROGRESS_TICK, downloadProgressData, }); }, ); } catch (error) { throw error; } }; export const getBundlesForComic = (comicObjectId: string, ADCPPSocket: any, credentials: any) => async (dispatch) => { try { if (!ADCPPSocket.isConnected()) { await ADCPPSocket.connect( `${credentials.username}`, `${credentials.password}`, true, ); } const comicObject = await axios({ method: "POST", url: `${LIBRARY_SERVICE_BASE_URI}/getComicBookById`, headers: { "Content-Type": "application/json; charset=utf-8", }, data: { id: `${comicObjectId}`, }, }); // get only the bundles applicable for the comic const filteredBundles = comicObject.data.acquisition.directconnect.map( async ({ bundleId }) => { return await ADCPPSocket.get(`queue/bundles/${bundleId}`); }, ); dispatch({ type: AIRDCPP_BUNDLES_FETCHED, bundles: await Promise.all(filteredBundles), }); } catch (error) { throw error; } }; export const getTransfers = (ADCPPSocket: any, credentials: any) => async (dispatch) => { try { if (!ADCPPSocket.isConnected()) { await ADCPPSocket.connect( `${credentials.username}`, `${credentials.password}`, true, ); } const foo = await ADCPPSocket.get("queue/bundles/1/50", {}); console.log(foo); } catch (err) { throw err; } };