Compare commits

...

4 Commits

Author SHA1 Message Date
114f022b8d Fix empty torrents returned as array in show episodes
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
The show episodes can handle undefined values themselves.
2020-04-10 17:09:43 +02:00
83d1894a25 Fix torrent search on every keystroke
Cleanup the search results when leaving the page.
2020-04-10 17:09:43 +02:00
c9ecdac4f2 Add the torrent URL in the torrent button
This allows us to copy the link without clicking on the button.
2020-04-10 17:09:43 +02:00
3bd51765b8 Update papi and polochon to use the new torrent API 2020-04-10 17:09:43 +02:00
16 changed files with 184 additions and 188 deletions

View File

@ -42,40 +42,51 @@ type episodeTorrentDB struct {
Updated time.Time `db:"updated_at"` Updated time.Time `db:"updated_at"`
} }
// NewTorrentFromEpisodeTorrentDB returns a polochon.Torrent from an // newTorrentFromEpisodeTorrentDB returns a polochon.Torrent from an
// episodeTorrentDB // EpisodeTorrentDB
func NewTorrentFromEpisodeTorrentDB(eDB *episodeTorrentDB) *polochon.Torrent { func newTorrentFromEpisodeTorrentDB(eDB *episodeTorrentDB) *polochon.Torrent {
q, _ := polochon.StringToQuality(eDB.Quality)
return &polochon.Torrent{ return &polochon.Torrent{
Quality: *q, ImdbID: eDB.ImdbID,
URL: eDB.URL, Type: polochon.TypeEpisode,
Seeders: eDB.Seeders, Season: eDB.Season,
Leechers: eDB.Leechers, Episode: eDB.Episode,
Source: eDB.Source, Quality: polochon.Quality(eDB.Quality),
UploadUser: eDB.UploadUser, Result: &polochon.TorrentResult{
Size: eDB.Size, URL: eDB.URL,
Seeders: eDB.Seeders,
Leechers: eDB.Leechers,
Source: eDB.Source,
UploadUser: eDB.UploadUser,
Size: eDB.Size,
},
} }
} }
// NewEpisodeTorrentDB returns an episodeTorrentDB ready to be put in DB from a // newEpisodeTorrentDB returns an episodeTorrentDB ready to be put in DB from a
// polochon.Torrent // polochon.Torrent
func NewEpisodeTorrentDB(t *polochon.Torrent, imdbID string, season, episode int) *episodeTorrentDB { func newEpisodeTorrentDB(t *polochon.Torrent) *episodeTorrentDB {
return &episodeTorrentDB{ e := &episodeTorrentDB{
ImdbID: imdbID, ImdbID: t.ImdbID,
Season: season, Quality: string(t.Quality),
Episode: episode, Season: t.Season,
URL: t.URL, Episode: t.Episode,
Source: t.Source,
Quality: string(t.Quality),
UploadUser: t.UploadUser,
Seeders: t.Seeders,
Leechers: t.Leechers,
Size: t.Size,
} }
if t.Result == nil {
return e
}
e.URL = t.Result.URL
e.Source = t.Result.Source
e.UploadUser = t.Result.UploadUser
e.Seeders = t.Result.Seeders
e.Leechers = t.Result.Leechers
e.Size = t.Result.Size
return e
} }
// GetEpisodeTorrents returns show episodes torrents from database // GetEpisodeTorrents returns show episodes torrents from database
func GetEpisodeTorrents(db *sqlx.DB, imdbID string, season, episode int) ([]polochon.Torrent, error) { func GetEpisodeTorrents(db *sqlx.DB, imdbID string, season, episode int) ([]*polochon.Torrent, error) {
var torrentsDB = []*episodeTorrentDB{} var torrentsDB = []*episodeTorrentDB{}
err := db.Select(&torrentsDB, getEpisodeTorrentQuery, imdbID, season, episode) err := db.Select(&torrentsDB, getEpisodeTorrentQuery, imdbID, season, episode)
if err != nil { if err != nil {
@ -86,19 +97,19 @@ func GetEpisodeTorrents(db *sqlx.DB, imdbID string, season, episode int) ([]polo
return nil, sql.ErrNoRows return nil, sql.ErrNoRows
} }
var torrents []polochon.Torrent var torrents []*polochon.Torrent
for _, torrentDB := range torrentsDB { for _, torrentDB := range torrentsDB {
torrent := NewTorrentFromEpisodeTorrentDB(torrentDB) torrent := newTorrentFromEpisodeTorrentDB(torrentDB)
torrents = append(torrents, *torrent) torrents = append(torrents, torrent)
} }
return torrents, nil return torrents, nil
} }
// UpsertEpisodeTorrent upserts an episode torrent from a polochon torrent // UpsertEpisodeTorrent upserts an episode torrent from a polochon torrent
func UpsertEpisodeTorrent(db *sqlx.DB, torrent *polochon.Torrent, imdbID string, season, episode int) error { func UpsertEpisodeTorrent(db *sqlx.DB, torrent *polochon.Torrent) error {
// Create the EpisodeTorrent ready to be put in db // Create the EpisodeTorrent ready to be put in db
eDB := NewEpisodeTorrentDB(torrent, imdbID, season, episode) eDB := newEpisodeTorrentDB(torrent)
r, err := db.NamedQuery(upsertEpisodeTorrentQuery, eDB) r, err := db.NamedQuery(upsertEpisodeTorrentQuery, eDB)
if err != nil { if err != nil {
return err return err

View File

@ -39,38 +39,47 @@ type movieTorrentDB struct {
Updated time.Time `db:"updated_at"` Updated time.Time `db:"updated_at"`
} }
// NewTorrentFromMovieTorrentDB creates a new polochon.Torrent from a // newTorrentFromMovieTorrentDB creates a new polochon.Torrent from a
// movieTorrentDB // movieTorrentDB
func NewTorrentFromMovieTorrentDB(mDB *movieTorrentDB) *polochon.Torrent { func newTorrentFromMovieTorrentDB(mDB *movieTorrentDB) *polochon.Torrent {
q, _ := polochon.StringToQuality(mDB.Quality)
return &polochon.Torrent{ return &polochon.Torrent{
Quality: *q, ImdbID: mDB.ImdbID,
URL: mDB.URL, Quality: polochon.Quality(mDB.Quality),
Seeders: mDB.Seeders, Type: polochon.TypeMovie,
Leechers: mDB.Leechers, Result: &polochon.TorrentResult{
Source: mDB.Source, URL: mDB.URL,
UploadUser: mDB.UploadUser, Seeders: mDB.Seeders,
Size: mDB.Size, Leechers: mDB.Leechers,
Source: mDB.Source,
UploadUser: mDB.UploadUser,
Size: mDB.Size,
},
} }
} }
// NewMovieTorrentDB returns a MovieTorrent ready to be put in DB from a // newMovieTorrentDB returns a MovieTorrent ready to be put in DB from a
// Torrent // Torrent
func NewMovieTorrentDB(t *polochon.Torrent, imdbID string) movieTorrentDB { func newMovieTorrentDB(t *polochon.Torrent) movieTorrentDB {
return movieTorrentDB{ m := movieTorrentDB{
ImdbID: imdbID, ImdbID: t.ImdbID,
URL: t.URL, Quality: string(t.Quality),
Source: t.Source,
Quality: string(t.Quality),
UploadUser: t.UploadUser,
Seeders: t.Seeders,
Leechers: t.Leechers,
Size: t.Size,
} }
if t.Result == nil {
return m
}
m.URL = t.Result.URL
m.Source = t.Result.Source
m.UploadUser = t.Result.UploadUser
m.Seeders = t.Result.Seeders
m.Leechers = t.Result.Leechers
m.Size = t.Result.Size
return m
} }
// GetMovieTorrents returns polochon.Torrents from the database // GetMovieTorrents returns polochon.Torrents from the database
func GetMovieTorrents(db *sqlx.DB, imdbID string) ([]polochon.Torrent, error) { func GetMovieTorrents(db *sqlx.DB, imdbID string) ([]*polochon.Torrent, error) {
var torrentsDB = []*movieTorrentDB{} var torrentsDB = []*movieTorrentDB{}
// Get the torrents from the DB // Get the torrents from the DB
err := db.Select(&torrentsDB, getMovieTorrentQueryByImdbID, imdbID) err := db.Select(&torrentsDB, getMovieTorrentQueryByImdbID, imdbID)
@ -83,18 +92,18 @@ func GetMovieTorrents(db *sqlx.DB, imdbID string) ([]polochon.Torrent, error) {
} }
// Create polochon Torrents from the movieTorrentDB // Create polochon Torrents from the movieTorrentDB
var torrents []polochon.Torrent var torrents []*polochon.Torrent
for _, torrentDB := range torrentsDB { for _, torrentDB := range torrentsDB {
torrent := NewTorrentFromMovieTorrentDB(torrentDB) torrent := newTorrentFromMovieTorrentDB(torrentDB)
torrents = append(torrents, *torrent) torrents = append(torrents, torrent)
} }
return torrents, nil return torrents, nil
} }
// UpsertMovieTorrent adds or updates MovieTorrent in db // UpsertMovieTorrent adds or updates MovieTorrent in db
func UpsertMovieTorrent(db *sqlx.DB, t *polochon.Torrent, imdbID string) error { func UpsertMovieTorrent(db *sqlx.DB, t *polochon.Torrent) error {
mDB := NewMovieTorrentDB(t, imdbID) mDB := newMovieTorrentDB(t)
r, err := db.NamedQuery(upsertMovieTorrentQuery, mDB) r, err := db.NamedQuery(upsertMovieTorrentQuery, mDB)
if err != nil { if err != nil {
return err return err

View File

@ -223,7 +223,7 @@ func (m *Movie) RefreshTorrents(env *web.Env, torrenters []polochon.Torrenter) e
// Update them in database // Update them in database
for _, t := range m.Movie.Torrents { for _, t := range m.Movie.Torrents {
err = models.UpsertMovieTorrent(env.Database, &t, m.ImdbID) err = models.UpsertMovieTorrent(env.Database, t)
if err != nil { if err != nil {
log.Error("error while adding torrent", err) log.Error("error while adding torrent", err)
continue continue

View File

@ -179,7 +179,7 @@ func RefreshTorrents(env *web.Env, showEpisode *polochon.ShowEpisode, torrenters
// Upsert all the torrents we got // Upsert all the torrents we got
for _, t := range showEpisode.Torrents { for _, t := range showEpisode.Torrents {
err = models.UpsertEpisodeTorrent(env.Database, &t, showEpisode.ShowImdbID, showEpisode.Season, showEpisode.Episode) err = models.UpsertEpisodeTorrent(env.Database, t)
if err != nil { if err != nil {
log.Errorf("error while adding torrent : %s", err) log.Errorf("error while adding torrent : %s", err)
continue continue

View File

@ -16,19 +16,12 @@ import (
// DownloadHandler downloads a movie via polochon // DownloadHandler downloads a movie via polochon
func DownloadHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error { func DownloadHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
var data struct { torrent := &papi.Torrent{}
URL string `json:"url"` err := json.NewDecoder(r.Body).Decode(torrent)
Metadata *papi.TorrentMetadata `json:"metadata"`
}
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil { if err != nil {
return env.RenderError(w, errors.New("failed to get the url")) return env.RenderError(w, errors.New("failed to get the url"))
} }
if data.URL == "" {
return env.RenderError(w, errors.New("no given url"))
}
user := auth.GetCurrentUser(r, env.Log) user := auth.GetCurrentUser(r, env.Log)
client, err := user.NewPapiClient(env.Database) client, err := user.NewPapiClient(env.Database)
@ -36,7 +29,7 @@ func DownloadHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error
return env.RenderError(w, err) return env.RenderError(w, err)
} }
err = client.AddTorrent(data.URL, data.Metadata) err = client.AddTorrent(torrent)
if err != nil { if err != nil {
return env.RenderError(w, err) return env.RenderError(w, err)
} }
@ -123,7 +116,15 @@ func SearchHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
// Sort by seeds // Sort by seeds
sort.Slice(results, func(i, j int) bool { sort.Slice(results, func(i, j int) bool {
return results[i].Seeders > results[j].Seeders // Let's avoid the panic while sorting
if results[i].Result == nil {
results[i].Result = &polochon.TorrentResult{}
}
if results[j].Result == nil {
results[j].Result = &polochon.TorrentResult{}
}
return results[i].Result.Seeders > results[j].Result.Seeders
}) })
return env.RenderJSON(w, results) return env.RenderJSON(w, results)

View File

@ -3,14 +3,9 @@ import { configureAxios, request } from "../requests";
import { addAlertOk } from "./alerts"; import { addAlertOk } from "./alerts";
export function addTorrent(torrent) { export function addTorrent(torrent) {
return request( return request("ADD_TORRENT", configureAxios().post("/torrents", torrent), [
"ADD_TORRENT", addAlertOk("Torrent added"),
configureAxios().post("/torrents", { ]);
url: torrent.url,
metadata: torrent.metadata,
}),
[addAlertOk("Torrent added")]
);
} }
export function removeTorrent(id) { export function removeTorrent(id) {
@ -27,6 +22,12 @@ export function searchTorrents(url) {
return request("TORRENTS_SEARCH", configureAxios().get(url)); return request("TORRENTS_SEARCH", configureAxios().get(url));
} }
export function clearTorrentSearch() {
return {
type: "TORRENTS_SEARCH_CLEAR",
};
}
export function setFetchedTorrents(torrents) { export function setFetchedTorrents(torrents) {
return { return {
type: "TORRENTS_FETCH_FULFILLED", type: "TORRENTS_FETCH_FULFILLED",

View File

@ -27,7 +27,7 @@ const buildMenuItems = (torrents) => {
entries.push({ entries.push({
type: "entry", type: "entry",
quality: torrent.quality, quality: torrent.quality,
size: torrent.size, size: torrent.result.size,
torrent: torrent, torrent: torrent,
}); });
}); });
@ -109,7 +109,11 @@ export const TorrentsButton = ({ torrents, search, searching, url }) => {
return ( return (
<Dropdown.Item <Dropdown.Item
key={index} key={index}
onClick={() => dispatch(addTorrent(e.torrent))} href={e.torrent.result.url}
onClick={(event) => {
event.preventDefault();
dispatch(addTorrent(e.torrent));
}}
> >
{e.quality} {e.quality}
{e.size !== 0 && ( {e.size !== 0 && (

View File

@ -19,10 +19,8 @@ export const EpisodeTorrentsButton = ({ season, episode }) => {
? state.show.show.seasons.get(season).get(episode).fetching ? state.show.show.seasons.get(season).get(episode).fetching
: false : false
); );
const torrents = useSelector((state) => const torrents = useSelector(
state.show.show.seasons.get(season).get(episode).torrents (state) => state.show.show.seasons.get(season).get(episode).torrents
? state.show.show.seasons.get(season).get(episode).torrents
: []
); );
const url = useSelector( const url = useSelector(

View File

@ -25,7 +25,11 @@ const AddTorrent = () => {
if (url === "") { if (url === "") {
return; return;
} }
dispatch(addTorrent({ url: url, metdata: null })); dispatch(
addTorrent({
result: { url: url },
})
);
setUrl(""); setUrl("");
}; };
@ -66,28 +70,28 @@ const Torrents = () => {
const Torrent = ({ torrent }) => { const Torrent = ({ torrent }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
var progressStyle = torrent.is_finished var progressStyle = torrent.status.is_finished
? "success" ? "success"
: "info progress-bar-striped progress-bar-animated"; : "info progress-bar-striped progress-bar-animated";
const progressBarClass = "progress-bar bg-" + progressStyle; const progressBarClass = "progress-bar bg-" + progressStyle;
var percentDone = torrent.percent_done; var percentDone = torrent.status.percent_done;
const started = percentDone !== 0; const started = percentDone !== 0;
if (started) { if (started) {
percentDone = Number(percentDone).toFixed(1) + "%"; percentDone = Number(percentDone).toFixed(1) + "%";
} }
// Pretty sizes // Pretty sizes
const downloadedSize = prettySize(torrent.downloaded_size); const downloadedSize = prettySize(torrent.status.downloaded_size);
const totalSize = prettySize(torrent.total_size); const totalSize = prettySize(torrent.status.total_size);
const downloadRate = prettySize(torrent.download_rate) + "/s"; const downloadRate = prettySize(torrent.status.download_rate) + "/s";
return ( return (
<div className="card w-100 mb-3"> <div className="card w-100 mb-3">
<h5 className="card-header"> <h5 className="card-header">
<span className="text text-break">{torrent.name}</span> <span className="text text-break">{torrent.status.name}</span>
<span <span
className="fa fa-trash clickable pull-right" className="fa fa-trash clickable pull-right"
onClick={() => dispatch(removeTorrent(torrent.id))} onClick={() => dispatch(removeTorrent(torrent.status.id))}
></span> ></span>
</h5> </h5>
<div className="card-body pb-0"> <div className="card-body pb-0">

View File

@ -1,40 +1,39 @@
import React, { useState, useEffect, useCallback } from "react"; import React, { useState, useEffect } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { addTorrent, searchTorrents } from "../../actions/torrents";
import Loader from "../loader/loader"; import Loader from "../loader/loader";
import { OverlayTrigger, Tooltip } from "react-bootstrap"; import { OverlayTrigger, Tooltip } from "react-bootstrap";
import { prettySize } from "../../utils"; import { prettySize } from "../../utils";
import {
addTorrent,
searchTorrents,
clearTorrentSearch,
} from "../../actions/torrents";
export const TorrentSearch = ({ history, match }) => { export const TorrentSearch = ({ history, match }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [search, setSearch] = useState(match.params.search || ""); const [search, setSearch] = useState(match.params.search || "");
const [type, setType] = useState(match.params.type || ""); const [type, setType] = useState(match.params.type || "");
const url = useCallback(() => { const searchFunc = (type = "") => {
if (search === "" || type === "") { if (search === "" || type === "") {
return "";
}
return `/torrents/search/${type}/${encodeURI(search)}`;
}, [type, search]);
const searchFunc = useCallback(() => {
const searchURL = url();
if (searchURL === "") {
return; return;
} }
dispatch(searchTorrents(searchURL)); const url = `/torrents/search/${type}/${encodeURI(search)}`;
history.push(searchURL); setType(type);
}, [dispatch, history, url]); dispatch(searchTorrents(url));
history.push(url);
};
useEffect(() => { useEffect(() => {
searchFunc(); searchFunc(type);
}, [searchFunc]); return () => dispatch(clearTorrentSearch());
}, []); // eslint-disable-line react-hooks/exhaustive-deps
return ( return (
<div className="row"> <div className="row">
@ -52,8 +51,7 @@ export const TorrentSearch = ({ history, match }) => {
type="movies" type="movies"
typeFromURL={type} typeFromURL={type}
handleClick={() => { handleClick={() => {
setType("movies"); searchFunc("movies");
searchFunc();
}} }}
/> />
<SearchButton <SearchButton
@ -61,14 +59,13 @@ export const TorrentSearch = ({ history, match }) => {
type="shows" type="shows"
typeFromURL={type} typeFromURL={type}
handleClick={() => { handleClick={() => {
setType("shows"); searchFunc("shows");
searchFunc();
}} }}
/> />
</div> </div>
</div> </div>
<div className="col-12"> <div className="col-12">
<TorrentList search={search} /> <TorrentList />
</div> </div>
</div> </div>
); );
@ -98,7 +95,7 @@ SearchButton.propTypes = {
handleClick: PropTypes.func.isRequired, handleClick: PropTypes.func.isRequired,
}; };
const TorrentList = ({ search }) => { const TorrentList = () => {
const searching = useSelector((state) => state.torrents.searching); const searching = useSelector((state) => state.torrents.searching);
const results = useSelector((state) => state.torrents.searchResults); const results = useSelector((state) => state.torrents.searchResults);
@ -106,10 +103,6 @@ const TorrentList = ({ search }) => {
return <Loader />; return <Loader />;
} }
if (search === "") {
return null;
}
if (results.size === 0) { if (results.size === 0) {
return ( return (
<div className="jumbotron"> <div className="jumbotron">
@ -126,9 +119,6 @@ const TorrentList = ({ search }) => {
</React.Fragment> </React.Fragment>
); );
}; };
TorrentList.propTypes = {
search: PropTypes.string,
};
const Torrent = ({ torrent }) => { const Torrent = ({ torrent }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -136,17 +126,17 @@ const Torrent = ({ torrent }) => {
return ( return (
<div className="alert d-flex border-bottom border-secondary align-items-center"> <div className="alert d-flex border-bottom border-secondary align-items-center">
<TorrentHealth <TorrentHealth
url={torrent.url} url={torrent.result.url}
seeders={torrent.seeders} seeders={torrent.result.seeders}
leechers={torrent.leechers} leechers={torrent.result.leechers}
/> />
<span className="mx-3 text text-start text-break flex-fill"> <span className="mx-3 text text-start text-break flex-fill">
{torrent.name} {torrent.result.name}
</span> </span>
<div> <div>
{torrent.size !== 0 && ( {torrent.result.size !== 0 && (
<span className="mx-1 badge badge-pill badge-warning"> <span className="mx-1 badge badge-pill badge-warning">
{prettySize(torrent.size)} {prettySize(torrent.result.size)}
</span> </span>
)} )}
@ -154,18 +144,16 @@ const Torrent = ({ torrent }) => {
{torrent.quality} {torrent.quality}
</span> </span>
<span className="mx-1 badge badge-pill badge-success"> <span className="mx-1 badge badge-pill badge-success">
{torrent.source} {torrent.result.source}
</span> </span>
<span className="mx-1 badge badge-pill badge-info"> <span className="mx-1 badge badge-pill badge-info">
{torrent.upload_user} {torrent.result.upload_user}
</span> </span>
</div> </div>
<div className="align-self-end ml-3"> <div className="align-self-end ml-3">
<i <i
className="fa fa-cloud-download clickable" className="fa fa-cloud-download clickable"
onClick={() => onClick={() => dispatch(addTorrent(torrent))}
dispatch(addTorrent({ url: torrent.url, metadata: null }))
}
></i> ></i>
</div> </div>
</div> </div>

View File

@ -1,5 +1,7 @@
import { produce } from "immer"; import { produce } from "immer";
import { formatTorrents } from "../utils";
const defaultState = { const defaultState = {
loading: false, loading: false,
movies: new Map(), movies: new Map(),
@ -8,29 +10,6 @@ const defaultState = {
exploreOptions: {}, exploreOptions: {},
}; };
const formatTorrents = (movie) => {
if (!movie.torrents || movie.torrents.length == 0) {
return undefined;
}
let torrentMap = new Map();
movie.torrents.forEach((torrent) => {
if (!torrentMap.has(torrent.source)) {
torrentMap.set(torrent.source, new Map());
}
torrent.metadata = {
type: "movie",
imdb_id: movie.imdb_id, // eslint-disable-line camelcase
quality: torrent.quality,
};
torrentMap.get(torrent.source).set(torrent.quality, torrent);
});
return torrentMap;
};
const formatMovie = (movie) => { const formatMovie = (movie) => {
movie.fetchingDetails = false; movie.fetchingDetails = false;
movie.fetchingSubtitles = false; movie.fetchingSubtitles = false;

View File

@ -1,35 +1,12 @@
import { produce } from "immer"; import { produce } from "immer";
import { formatTorrents } from "../utils";
const defaultState = { const defaultState = {
loading: false, loading: false,
show: {}, show: {},
}; };
const formatTorrents = (episode) => {
if (!episode.torrents || episode.torrents.length == 0) {
return undefined;
}
let torrentMap = new Map();
episode.torrents.forEach((torrent) => {
if (!torrentMap.has(torrent.source)) {
torrentMap.set(torrent.source, new Map());
}
torrent.metadata = {
type: "episode",
imdb_id: episode.show_imdb_id, // eslint-disable-line camelcase
quality: torrent.quality,
season: episode.season,
episode: episode.episode,
};
torrentMap.get(torrent.source).set(torrent.quality, torrent);
});
return torrentMap;
};
const formatEpisode = (episode) => { const formatEpisode = (episode) => {
// Format the episode's torrents // Format the episode's torrents
episode.torrents = formatTorrents(episode); episode.torrents = formatTorrents(episode);

View File

@ -28,6 +28,10 @@ export default (state = defaultState, action) =>
draft.searchResults = action.payload.response.data; draft.searchResults = action.payload.response.data;
break; break;
case "TORRENTS_SEARCH_CLEAR":
draft.searchResults = [];
break;
default: default:
return draft; return draft;
} }

View File

@ -31,3 +31,24 @@ export const prettySize = (fileSizeInBytes) => {
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i]; return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
}; };
export const formatTorrents = (input) => {
if (!input.torrents || input.torrents.length == 0) {
return undefined;
}
let torrentMap = new Map();
input.torrents.forEach((torrent) => {
if (!torrent.result || !torrent.result.source) {
return;
}
if (!torrentMap.has(torrent.result.source)) {
torrentMap.set(torrent.result.source, new Map());
}
torrentMap.get(torrent.result.source).set(torrent.quality, torrent);
});
return torrentMap;
};

4
go.mod
View File

@ -15,8 +15,8 @@ require (
github.com/mattn/go-sqlite3 v1.10.0 // indirect github.com/mattn/go-sqlite3 v1.10.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/odwrtw/errors v0.0.0-20170604160533-c747b9d17833 github.com/odwrtw/errors v0.0.0-20170604160533-c747b9d17833
github.com/odwrtw/papi v0.0.0-20200408160729-930e92b452fd github.com/odwrtw/papi v0.0.0-20200410143325-49e6f827259d
github.com/odwrtw/polochon v0.0.0-20200408160701-0455bb96acb0 github.com/odwrtw/polochon v0.0.0-20200410143337-006e3fb9fb55
github.com/phyber/negroni-gzip v0.0.0-20180113114010-ef6356a5d029 github.com/phyber/negroni-gzip v0.0.0-20180113114010-ef6356a5d029
github.com/pioz/tvdb v0.0.0-20190503215423-f45c687faba9 // indirect github.com/pioz/tvdb v0.0.0-20190503215423-f45c687faba9 // indirect
github.com/robfig/cron v1.1.0 github.com/robfig/cron v1.1.0

9
go.sum
View File

@ -133,12 +133,11 @@ github.com/odwrtw/guessit v0.0.0-20200131084001-f88613483547 h1:O0wEl/ORBHpPpZti
github.com/odwrtw/guessit v0.0.0-20200131084001-f88613483547/go.mod h1:W22g7wtc0AGczEARBAs+77gvBk8monDaM6U6i9Wa0vQ= github.com/odwrtw/guessit v0.0.0-20200131084001-f88613483547/go.mod h1:W22g7wtc0AGczEARBAs+77gvBk8monDaM6U6i9Wa0vQ=
github.com/odwrtw/imdb-watchlist v0.0.0-20190417175016-b7a9f7503d69 h1:ow6b/4Jj7J5iYwU678/rbijvaNUJrYkg13j9Nivkung= github.com/odwrtw/imdb-watchlist v0.0.0-20190417175016-b7a9f7503d69 h1:ow6b/4Jj7J5iYwU678/rbijvaNUJrYkg13j9Nivkung=
github.com/odwrtw/imdb-watchlist v0.0.0-20190417175016-b7a9f7503d69/go.mod h1:o2tLH95CtNdqhDb0aS2NbU+1I4PmaNsODpr33Ry0JC0= github.com/odwrtw/imdb-watchlist v0.0.0-20190417175016-b7a9f7503d69/go.mod h1:o2tLH95CtNdqhDb0aS2NbU+1I4PmaNsODpr33Ry0JC0=
github.com/odwrtw/papi v0.0.0-20190413103029-bd5bfea85ae6 h1:bF8XKFfYNY4quRdqJ5E9ERd+FdR26H1X1Z2fNRGePSk=
github.com/odwrtw/papi v0.0.0-20190413103029-bd5bfea85ae6/go.mod h1:CXotdtODLpW0/yuFV5XH8Rmrj0eAfPLvdMKykPM2WCk= github.com/odwrtw/papi v0.0.0-20190413103029-bd5bfea85ae6/go.mod h1:CXotdtODLpW0/yuFV5XH8Rmrj0eAfPLvdMKykPM2WCk=
github.com/odwrtw/papi v0.0.0-20200408160729-930e92b452fd h1:LsBK0gVXC8oRxyAwvkCg5fQWTD678Jl7n6a8MZpdUKo= github.com/odwrtw/papi v0.0.0-20200410143325-49e6f827259d h1:it4hnCveS8eFymg0ll9KRzO/iQm/olSW0sb8Ctm3gXI=
github.com/odwrtw/papi v0.0.0-20200408160729-930e92b452fd/go.mod h1:eY0skvVHJBwbSJ18uq2c1T4SvhdEV8R0XFSb0zKh5Yo= github.com/odwrtw/papi v0.0.0-20200410143325-49e6f827259d/go.mod h1:eY0skvVHJBwbSJ18uq2c1T4SvhdEV8R0XFSb0zKh5Yo=
github.com/odwrtw/polochon v0.0.0-20200408160701-0455bb96acb0 h1:p0pXoG89JVL/bZWJpqu2KRQwCU44yYnNnoP46SIPNPQ= github.com/odwrtw/polochon v0.0.0-20200410143337-006e3fb9fb55 h1:hcHBTi+HfYz5p6wgtvQCbrdog0uOB/7eVxPZA5Qff80=
github.com/odwrtw/polochon v0.0.0-20200408160701-0455bb96acb0/go.mod h1:sAYf/A5tDmins2GHZn2mEFarmYltAZv+bcmSKSxDUaI= github.com/odwrtw/polochon v0.0.0-20200410143337-006e3fb9fb55/go.mod h1:sAYf/A5tDmins2GHZn2mEFarmYltAZv+bcmSKSxDUaI=
github.com/odwrtw/tpb v0.0.0-20200130133144-c846aa382c6f h1:fwEIGT+o3e8+XkBqrwsE3/+9ketTQXflPhCkv3/w990= github.com/odwrtw/tpb v0.0.0-20200130133144-c846aa382c6f h1:fwEIGT+o3e8+XkBqrwsE3/+9ketTQXflPhCkv3/w990=
github.com/odwrtw/tpb v0.0.0-20200130133144-c846aa382c6f/go.mod h1:updLvMbQo2xHoz94MX9+GqmSoKhf6E8fs/J+wLvvu6A= github.com/odwrtw/tpb v0.0.0-20200130133144-c846aa382c6f/go.mod h1:updLvMbQo2xHoz94MX9+GqmSoKhf6E8fs/J+wLvvu6A=
github.com/odwrtw/trakttv v0.0.0-20200404161731-0d594827e4f9 h1:PuQLHO75MXUsJpf9BcTVxvR/FCkdn1MZnZt6h3o6cJI= github.com/odwrtw/trakttv v0.0.0-20200404161731-0d594827e4f9 h1:PuQLHO75MXUsJpf9BcTVxvR/FCkdn1MZnZt6h3o6cJI=