import { useEffect, useState, useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; import { setFetchedTorrents } from "../actions/torrents"; import { newMovieEvent, getMovieDetails } from "../actions/movies"; import { newEpisodeEvent, getEpisodeDetails } from "../actions/shows"; export const WsHandler = () => { const dispatch = useDispatch(); const isLogged = useSelector((state) => state.user.isLogged); const [ws, setWs] = useState(null); const stop = useCallback(() => { if (!ws) { return; } ws.close(); setWs(null); }, [ws]); const connect = useCallback(() => { if (ws) { return; } if (!isLogged) { stop(); } const type = location.protocol === "https:" ? "wss" : "ws"; const socket = new WebSocket(type + ":" + location.host + "/events"); socket.onopen = () => { socket.send( JSON.stringify({ type: "subscribe", message: "torrents", }) ); socket.send( JSON.stringify({ type: "subscribe", message: "newVideo", }) ); }; socket.onmessage = (event) => { if (!event.data) { return; } const data = JSON.parse(event.data); if (!data.type) { return; } if (data.status !== "ok") { // TODO: handle this somehow return; } switch (data.type) { case "torrents": dispatch(setFetchedTorrents(data.message)); break; case "newVideo": if (data.message.type === "movie") { dispatch(newMovieEvent(data.message.data)); dispatch(getMovieDetails(data.message.data.imdb_id)); } else if (data.message.type === "episode") { dispatch(newEpisodeEvent(data.message.data)); dispatch( getEpisodeDetails( data.message.data.show_imdb_id, data.message.data.season, data.message.data.episode ) ); } break; } }; socket.onerror = () => { stop(); }; setWs(socket); }, [ws, isLogged, dispatch, stop]); useEffect(() => { const intervalID = setInterval(() => { if (!ws) { connect(); return; } if (ws.readyState === WebSocket.CLOSED) { stop(); } }, 10000); if (!ws) { connect(); } return () => { if (ws) { stop(); } clearInterval(intervalID); }; }, [ws, connect, stop]); return null; };