diff --git a/src/client/actions/airdcpp.actions.tsx b/src/client/actions/airdcpp.actions.tsx new file mode 100644 index 0000000..9ddf8fe --- /dev/null +++ b/src/client/actions/airdcpp.actions.tsx @@ -0,0 +1,68 @@ +import SocketService from "../services/DcppSearchService"; +import { SearchQuery, SearchInstance, PriorityEnum } from "threetwo-ui-typings"; +import { + AIRDCPP_SEARCH_INSTANCE_CREATED, + AIRDCPP_SEARCH_RESULTS_RECEIVED, +} from "../constants/action-types"; + +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) => async (dispatch) => { + await SocketService.connect("admin", "password"); + const instance: SearchInstance = await SocketService.post("search"); + + dispatch({ + type: AIRDCPP_SEARCH_INSTANCE_CREATED, + searchInstance: instance, + }); + + const unsubscribe = await SocketService.addListener( + "search", + "search_hub_searches_sent", + (searchInfo) => { + onSearchSent(data, instance, unsubscribe, searchInfo); + }, + instance.id, + ); + + const searchQueueInfo = await SocketService.post( + `search/${instance.id}/hub_search`, + data, + ); + return searchQueueInfo; +}; + +const onSearchSent = + (item, instance, unsubscribe, searchInfo) => async (dispatch) => { + // Collect the results for 5 seconds + await sleep(5000); + + // Get only the first result (results are sorted by relevance) + const results = await SocketService.get( + `search/${instance.id}/results/0/100`, + ); + + if (results.length > 0) { + // We have results, download the best one + console.log("SASAAAA", results); + dispatch({ + type: AIRDCPP_SEARCH_RESULTS_RECEIVED, + results, + }); + // const result = results[0]; + // SocketService.post(`search/${instance.id}/results/${result.id}/download`, { + // priority: Utils.toApiPriority(item.priority), + // target_directory: item.target_directory, + // }); + } + // Remove listener for this search instance + unsubscribe(); + }; diff --git a/src/client/components/AcquisitionPanel.tsx b/src/client/components/AcquisitionPanel.tsx new file mode 100644 index 0000000..f2eee66 --- /dev/null +++ b/src/client/components/AcquisitionPanel.tsx @@ -0,0 +1,53 @@ +import React, { useState, useEffect, useCallback, ReactElement } from "react"; +import { search } from "../actions/airdcpp.actions"; +import { useDispatch, useSelector } from "react-redux"; +import { RootState } from "threetwo-ui-typings"; + +interface IAcquisitionPanelProps { + comicBookMetadata: any; +} + +export const AcquisitionPanel = ( + props: IAcquisitionPanelProps, +): ReactElement => { + const volumeName = + props.comicBookMetadata.sourcedMetadata.comicvine.volumeInformation.name; + const issueName = props.comicBookMetadata.sourcedMetadata.comicvine.name; + const airDCPPSearchResults = useSelector((state: RootState) => { + console.log(state); + }); + const dispatch = useDispatch(); + const getDCPPSearchResults = useCallback( + (searchQuery) => { + dispatch(search(searchQuery)); + }, + [dispatch], + ); + const dcppQuery = { + query: { + pattern: `${volumeName}`, + // file_type: "compressed", + extensions: ["cbz", "cbr"], + }, + hub_urls: [ + "adcs://novosibirsk.dc-dev.club:7111/?kp=SHA256/4XFHJFFBFEI2RS75FPRPPXPZMMKPXR764ABVVCC2QGJPQ34SDZGA", + "dc.fly-server.ru", + ], + priority: 1, + }; + return ( + <> + + + {/* results */} +
{JSON.stringify(airDCPPSearchResults)}
+ + ); +}; + +export default AcquisitionPanel; diff --git a/src/client/components/ComicDetail.tsx b/src/client/components/ComicDetail.tsx index 2be84cf..36a49ae 100644 --- a/src/client/components/ComicDetail.tsx +++ b/src/client/components/ComicDetail.tsx @@ -3,6 +3,7 @@ import { useParams } from "react-router-dom"; import Card from "./Carda"; import MatchResult from "./MatchResult"; import ComicVineSearchForm from "./ComicVineSearchForm"; +import AcquisitionPanel from "./AcquisitionPanel"; import { css } from "@emotion/react"; import PuffLoader from "react-spinners/PuffLoader"; @@ -143,6 +144,12 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => { name: "Other Metadata", content:
bastard
, }, + { + id: 3, + icon: , + name: "Acquisition", + content: , + }, ]; const MetadataTabGroup = () => { return ( diff --git a/src/client/components/Search.tsx b/src/client/components/Search.tsx index e5b4a99..eea457d 100644 --- a/src/client/components/Search.tsx +++ b/src/client/components/Search.tsx @@ -35,22 +35,6 @@ export const Search = ({}: ISearchProps): ReactElement => { [dispatch], ); - const getDCPPSearchResults = useCallback((searchQuery) => { - search(searchQuery); - }, []); - const dcppQuery = { - query: { - pattern: "Iron Man - V1 194", - // file_type: "compressed", - extensions: ["cbz", "cbr"], - }, - hub_urls: [ - "adcs://novosibirsk.dc-dev.club:7111/?kp=SHA256/4XFHJFFBFEI2RS75FPRPPXPZMMKPXR764ABVVCC2QGJPQ34SDZGA", - "dc.fly-server.ru", - ], - priority: 1, - }; - const addToLibrary = useCallback( (comicData) => dispatch(importToDB(comicData)), [], diff --git a/src/client/constants/action-types.ts b/src/client/constants/action-types.ts index 0edd903..bf8cc92 100644 --- a/src/client/constants/action-types.ts +++ b/src/client/constants/action-types.ts @@ -30,3 +30,9 @@ export const IMS_COMIC_BOOK_DB_OBJECT_CALL_IN_PROGRESS = "IMS_COMIC_BOOK_DB_OBJECT_CALL_IN_PROGRESS"; export const IMS_COMIC_BOOK_DB_OBJECT_CALL_FAILED = "IMS_COMIC_BOOK_DB_OBJECT_CALL_FAILED"; + +export const AIRDCPP_SEARCH_INSTANCE_CREATED = + "AIRDCPP_SEARCH_INSTANCE_CREATED"; +export const AIRDCPP_SEARCH_IN_PROGRESS = "AIRDCPP_SEARCH_IN_PROGRESS"; +export const AIRDCPP_SEARCH_RESULTS_RECEIVED = + "AIRDCPP_SEARCH_RESULTS_RECEIVED"; diff --git a/src/client/reducers/airdcpp.reducer.ts b/src/client/reducers/airdcpp.reducer.ts new file mode 100644 index 0000000..220b259 --- /dev/null +++ b/src/client/reducers/airdcpp.reducer.ts @@ -0,0 +1,34 @@ +import { + AIRDCPP_SEARCH_INSTANCE_CREATED, + AIRDCPP_SEARCH_IN_PROGRESS, + AIRDCPP_SEARCH_RESULTS_RECEIVED, +} from "../constants/action-types"; + +const initialState = { + isAirDCPPSearchInProgress: false, +}; + +function airdcppReducer(state = initialState, action) { + switch (action.type) { + case AIRDCPP_SEARCH_INSTANCE_CREATED: + return { + ...state, + searchInstance: action.searchInstance, + }; + + case AIRDCPP_SEARCH_IN_PROGRESS: + return { + ...state, + isAirDCPPSearchInProgress: true, + }; + + case AIRDCPP_SEARCH_RESULTS_RECEIVED: + return { + ...state, + isAirDCPPSearchInProgress: false, + results: action.results, + }; + } +} + +export default airdcppReducer; diff --git a/src/client/reducers/index.js b/src/client/reducers/index.js index 26cb46e..a93d21b 100644 --- a/src/client/reducers/index.js +++ b/src/client/reducers/index.js @@ -2,10 +2,14 @@ import { combineReducers } from "redux"; import { connectRouter } from "connected-react-router"; import comicinfoReducer from "../reducers/comicinfo.reducer"; import fileOpsReducer from "../reducers/fileops.reducer"; +import airdcppReducer from "./airdcpp.reducer"; export default (history) => combineReducers({ comicInfo: comicinfoReducer, fileOps: fileOpsReducer, + acquisition: { + airdcpp: airdcppReducer, + }, router: connectRouter(history), });