555 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			555 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import config from "@/config.json";
 | |
| 
 | |
| const SEASONED_URL = config.SEASONED_URL || window.location.origin;
 | |
| const ELASTIC_URL = config.ELASTIC_URL;
 | |
| const ELASTIC_INDEX = config.ELASTIC_INDEX;
 | |
| 
 | |
| // TODO
 | |
| //  - Move autorization token and errors here?
 | |
| 
 | |
| const checkStatusAndReturnJson = response => {
 | |
|   if (!response.ok) {
 | |
|     throw resp;
 | |
|   }
 | |
|   return response.json();
 | |
| };
 | |
| 
 | |
| // - - - TMDB - - -
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb movie by id. Can optionally include cast credits in result object.
 | |
|  * @param {number} id
 | |
|  * @param {boolean} [credits=false] Include credits
 | |
|  * @returns {object} Tmdb response
 | |
|  */
 | |
| const getMovie = (
 | |
|   id,
 | |
|   checkExistance = false,
 | |
|   credits = false,
 | |
|   release_dates = false
 | |
| ) => {
 | |
|   const url = new URL("/api/v2/movie", SEASONED_URL);
 | |
|   url.pathname = `${url.pathname}/${id.toString()}`;
 | |
|   if (checkExistance) {
 | |
|     url.searchParams.append("check_existance", true);
 | |
|   }
 | |
|   if (credits) {
 | |
|     url.searchParams.append("credits", true);
 | |
|   }
 | |
|   if (release_dates) {
 | |
|     url.searchParams.append("release_dates", true);
 | |
|   }
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error getting movie: ${id}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb show by id. Can optionally include cast credits in result object.
 | |
|  * @param {number} id
 | |
|  * @param {boolean} [credits=false] Include credits
 | |
|  * @returns {object} Tmdb response
 | |
|  */
 | |
| const getShow = (id, checkExistance = false, credits = false) => {
 | |
|   const url = new URL("/api/v2/show", SEASONED_URL);
 | |
|   url.pathname = `${url.pathname}/${id.toString()}`;
 | |
|   if (checkExistance) {
 | |
|     url.searchParams.append("check_existance", true);
 | |
|   }
 | |
|   if (credits) {
 | |
|     url.searchParams.append("credits", true);
 | |
|   }
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error getting show: ${id}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb person by id. Can optionally include cast credits in result object.
 | |
|  * @param {number} id
 | |
|  * @param {boolean} [credits=false] Include credits
 | |
|  * @returns {object} Tmdb response
 | |
|  */
 | |
| const getPerson = (id, credits = false) => {
 | |
|   const url = new URL("/api/v2/person", SEASONED_URL);
 | |
|   url.pathname = `${url.pathname}/${id.toString()}`;
 | |
|   if (credits) {
 | |
|     url.searchParams.append("credits", true);
 | |
|   }
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error getting person: ${id}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| const getCredits = (type, id) => {
 | |
|   if (type === "movie") {
 | |
|     return getMovieCredits(id);
 | |
|   } else if (type === "show") {
 | |
|     return getShowCredits(id);
 | |
|   } else if (type === "person") {
 | |
|     return getPersonCredits(id);
 | |
|   }
 | |
| 
 | |
|   return [];
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb movie credits by id.
 | |
|  * @param {number} id
 | |
|  * @returns {object} Tmdb response
 | |
|  */
 | |
| const getMovieCredits = id => {
 | |
|   const url = new URL("/api/v2/movie", SEASONED_URL);
 | |
|   url.pathname = `${url.pathname}/${id.toString()}/credits`;
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error getting movie: ${id}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb show credits by id.
 | |
|  * @param {number} id
 | |
|  * @returns {object} Tmdb response
 | |
|  */
 | |
| const getShowCredits = id => {
 | |
|   const url = new URL("/api/v2/show", SEASONED_URL);
 | |
|   url.pathname = `${url.pathname}/${id.toString()}/credits`;
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error getting show: ${id}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb person credits by id.
 | |
|  * @param {number} id
 | |
|  * @returns {object} Tmdb response
 | |
|  */
 | |
| const getPersonCredits = id => {
 | |
|   const url = new URL("/api/v2/person", SEASONED_URL);
 | |
|   url.pathname = `${url.pathname}/${id.toString()}/credits`;
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error getting person: ${id}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb list by name.
 | |
|  * @param {string} name List the fetch
 | |
|  * @param {number} [page=1]
 | |
|  * @returns {object} Tmdb list response
 | |
|  */
 | |
| const getTmdbMovieListByName = (name, page = 1) => {
 | |
|   const url = new URL("/api/v2/movie/" + name, SEASONED_URL);
 | |
|   url.searchParams.append("page", page);
 | |
| 
 | |
|   return fetch(url.href).then(resp => resp.json());
 | |
|   // .catch(error => { console.error(`api error getting list: ${name}, page: ${page}`); throw error })
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches requested items.
 | |
|  * @param {number} [page=1]
 | |
|  * @returns {object} Request response
 | |
|  */
 | |
| const getRequests = (page = 1) => {
 | |
|   const url = new URL("/api/v2/request", SEASONED_URL);
 | |
|   url.searchParams.append("page", page);
 | |
| 
 | |
|   return fetch(url.href).then(resp => resp.json());
 | |
|   // .catch(error => { console.error(`api error getting list: ${name}, page: ${page}`); throw error })
 | |
| };
 | |
| 
 | |
| const getUserRequests = (page = 1) => {
 | |
|   const url = new URL("/api/v1/user/requests", SEASONED_URL);
 | |
|   url.searchParams.append("page", page);
 | |
| 
 | |
|   return fetch(url.href).then(resp => resp.json());
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Fetches tmdb movies and shows by query.
 | |
|  * @param {string} query
 | |
|  * @param {number} [page=1]
 | |
|  * @returns {object} Tmdb response
 | |
|  */
 | |
| const searchTmdb = (query, page = 1, adult = false, mediaType = null) => {
 | |
|   const url = new URL("/api/v2/search", SEASONED_URL);
 | |
|   if (mediaType != null && ["movie", "show", "person"].includes(mediaType)) {
 | |
|     url.pathname += `/${mediaType}`;
 | |
|   }
 | |
| 
 | |
|   url.searchParams.append("query", query);
 | |
|   url.searchParams.append("page", page);
 | |
|   url.searchParams.append("adult", adult);
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error searching: ${query}, page: ${page}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| // - - - Torrents - - -
 | |
| 
 | |
| /**
 | |
|  * Search for torrents by query
 | |
|  * @param {string} query
 | |
|  * @param {boolean} credits Include credits
 | |
|  * @returns {object} Torrent response
 | |
|  */
 | |
| const searchTorrents = query => {
 | |
|   const url = new URL("/api/v1/pirate/search", SEASONED_URL);
 | |
|   url.searchParams.append("query", query);
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error searching torrents: ${query}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Add magnet to download queue.
 | |
|  * @param {string} magnet Magnet link
 | |
|  * @param {boolean} name Name of torrent
 | |
|  * @param {boolean} tmdb_id
 | |
|  * @returns {object} Success/Failure response
 | |
|  */
 | |
| const addMagnet = (magnet, name, tmdb_id) => {
 | |
|   const url = new URL("/api/v1/pirate/add", SEASONED_URL);
 | |
| 
 | |
|   const options = {
 | |
|     method: "POST",
 | |
|     headers: { "Content-Type": "application/json" },
 | |
|     body: JSON.stringify({
 | |
|       magnet: magnet,
 | |
|       name: name,
 | |
|       tmdb_id: tmdb_id
 | |
|     })
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error adding magnet: ${name} ${error}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| // - - - Plex/Request - - -
 | |
| 
 | |
| /**
 | |
|  * Request a movie or show from id. If authorization token is included the user will be linked
 | |
|  * to the requested item.
 | |
|  * @param {number} id Movie or show id
 | |
|  * @param {string} type Movie or show type
 | |
|  * @returns {object} Success/Failure response
 | |
|  */
 | |
| const request = (id, type) => {
 | |
|   const url = new URL("/api/v2/request", SEASONED_URL);
 | |
| 
 | |
|   const options = {
 | |
|     method: "POST",
 | |
|     headers: { "Content-Type": "application/json" },
 | |
|     body: JSON.stringify({ id, type })
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error requesting: ${id}, type: ${type}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Check request status by tmdb id and type
 | |
|  * @param {number} tmdb id
 | |
|  * @param {string} type
 | |
|  * @returns {object} Success/Failure response
 | |
|  */
 | |
| const getRequestStatus = (id, type = undefined) => {
 | |
|   const url = new URL("/api/v2/request", SEASONED_URL);
 | |
|   url.pathname = `${url.pathname}/${id.toString()}`;
 | |
|   url.searchParams.append("type", type);
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => {
 | |
|       const status = resp.status;
 | |
|       if (status === 200) {
 | |
|         return true;
 | |
|       } else if (status === 404) {
 | |
|         return false;
 | |
|       } else {
 | |
|         console.error(
 | |
|           `api error getting request status for id ${id} and type ${type}`
 | |
|         );
 | |
|       }
 | |
|     })
 | |
|     .catch(err => Promise.reject(err));
 | |
| };
 | |
| 
 | |
| const watchLink = (title, year) => {
 | |
|   const url = new URL("/api/v1/plex/watch-link", SEASONED_URL);
 | |
|   url.searchParams.append("title", title);
 | |
|   url.searchParams.append("year", year);
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .then(response => response.link);
 | |
| };
 | |
| 
 | |
| const movieImages = id => {
 | |
|   const url = new URL(`v2/movie/${id}/images`, SEASONED_URL);
 | |
| 
 | |
|   return fetch(url.href).then(resp => resp.json());
 | |
| };
 | |
| 
 | |
| // - - - Seasoned user endpoints - - -
 | |
| 
 | |
| const register = (username, password) => {
 | |
|   const url = new URL("/api/v1/user", SEASONED_URL);
 | |
|   const options = {
 | |
|     method: "POST",
 | |
|     headers: { "Content-Type": "application/json" },
 | |
|     body: JSON.stringify({ username, password })
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(
 | |
|         "Unexpected error occured before receiving response. Error:",
 | |
|         error
 | |
|       );
 | |
|       // TODO log to sentry the issue here
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| const login = (username, password, throwError = false) => {
 | |
|   const url = new URL("/api/v1/user/login", SEASONED_URL);
 | |
|   const options = {
 | |
|     method: "POST",
 | |
|     headers: { "Content-Type": "application/json" },
 | |
|     body: JSON.stringify({ username, password })
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options).then(resp => {
 | |
|     if (resp.status == 200) return resp.json();
 | |
| 
 | |
|     if (throwError) throw resp;
 | |
|     else console.error("Error occured when trying to sign in.\nError:", resp);
 | |
|   });
 | |
| };
 | |
| 
 | |
| const logout = () => {
 | |
|   const url = new URL("/api/v1/user/logout", SEASONED_URL);
 | |
|   const options = { method: "POST" };
 | |
| 
 | |
|   return fetch(url.href, options).then(resp => {
 | |
|     if (resp.status == 200) return resp.json();
 | |
| 
 | |
|     if (throwError) throw resp;
 | |
|     else console.error("Error occured when trying to log out.\nError:", resp);
 | |
|   });
 | |
| };
 | |
| 
 | |
| const getSettings = () => {
 | |
|   const url = new URL("/api/v1/user/settings", SEASONED_URL);
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.log("api error getting user settings");
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| const updateSettings = settings => {
 | |
|   const url = new URL("/api/v1/user/settings", SEASONED_URL);
 | |
| 
 | |
|   const options = {
 | |
|     method: "PUT",
 | |
|     headers: { "Content-Type": "application/json" },
 | |
|     body: JSON.stringify(settings)
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.log("api error updating user settings");
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| // - - - Authenticate with plex - - -
 | |
| 
 | |
| const linkPlexAccount = (username, password) => {
 | |
|   const url = new URL("/api/v1/user/link_plex", SEASONED_URL);
 | |
|   const body = { username, password };
 | |
| 
 | |
|   const options = {
 | |
|     method: "POST",
 | |
|     headers: { "Content-Type": "application/json" },
 | |
|     body: JSON.stringify(body)
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error linking plex account: ${username}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| const unlinkPlexAccount = (username, password) => {
 | |
|   const url = new URL("/api/v1/user/unlink_plex", SEASONED_URL);
 | |
| 
 | |
|   const options = {
 | |
|     method: "POST",
 | |
|     headers: { "Content-Type": "application/json" }
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error(`api error unlinking plex account: ${username}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| // - - - User graphs - - -
 | |
| 
 | |
| const fetchChart = (urlPath, days, chartType) => {
 | |
|   const url = new URL("/api/v1/user" + urlPath, SEASONED_URL);
 | |
|   url.searchParams.append("days", days);
 | |
|   url.searchParams.append("y_axis", chartType);
 | |
| 
 | |
|   return fetch(url.href).then(resp => {
 | |
|     if (!resp.ok) {
 | |
|       console.log("DAMN WE FAILED!", resp);
 | |
|       throw Error(resp.statusText);
 | |
|     }
 | |
| 
 | |
|     return resp.json();
 | |
|   });
 | |
| };
 | |
| 
 | |
| // - - - Random emoji - - -
 | |
| 
 | |
| const getEmoji = () => {
 | |
|   const url = new URL("/api/v1/emoji", SEASONED_URL);
 | |
| 
 | |
|   return fetch(url.href)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.log("api error getting emoji");
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| // - - - ELASTIC SEARCH - - -
 | |
| // This elastic index contains titles mapped to ids. Lightning search
 | |
| // used for autocomplete
 | |
| 
 | |
| /**
 | |
|  * Search elastic indexes movies and shows by query. Doc includes Tmdb daily export of Movies and
 | |
|  * Tv Shows. See tmdb docs for more info: https://developers.themoviedb.org/3/getting-started/daily-file-exports
 | |
|  * @param {string} query
 | |
|  * @returns {object} List of movies and shows matching query
 | |
|  */
 | |
| const elasticSearchMoviesAndShows = (query, count = 22) => {
 | |
|   const url = new URL(`${ELASTIC_INDEX}/_search`, ELASTIC_URL);
 | |
| 
 | |
|   const body = {
 | |
|     sort: [{ popularity: { order: "desc" } }, "_score"],
 | |
|     query: {
 | |
|       bool: {
 | |
|         should: [
 | |
|           {
 | |
|             match_phrase_prefix: {
 | |
|               original_name: query
 | |
|             }
 | |
|           },
 | |
|           {
 | |
|             match_phrase_prefix: {
 | |
|               original_title: query
 | |
|             }
 | |
|           }
 | |
|         ]
 | |
|       }
 | |
|     },
 | |
|     size: count
 | |
|   };
 | |
| 
 | |
|   const options = {
 | |
|     method: "POST",
 | |
|     headers: { "Content-Type": "application/json" },
 | |
|     body: JSON.stringify(body)
 | |
|   };
 | |
| 
 | |
|   return fetch(url.href, options)
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => {
 | |
|       console.log(`api error searching elasticsearch: ${query}`);
 | |
|       throw error;
 | |
|     });
 | |
| };
 | |
| 
 | |
| export {
 | |
|   getMovie,
 | |
|   getShow,
 | |
|   getPerson,
 | |
|   getMovieCredits,
 | |
|   getShowCredits,
 | |
|   getPersonCredits,
 | |
|   getCredits,
 | |
|   getTmdbMovieListByName,
 | |
|   searchTmdb,
 | |
|   getUserRequests,
 | |
|   getRequests,
 | |
|   searchTorrents,
 | |
|   addMagnet,
 | |
|   request,
 | |
|   watchLink,
 | |
|   movieImages,
 | |
|   getRequestStatus,
 | |
|   linkPlexAccount,
 | |
|   unlinkPlexAccount,
 | |
|   register,
 | |
|   login,
 | |
|   logout,
 | |
|   getSettings,
 | |
|   updateSettings,
 | |
|   fetchChart,
 | |
|   getEmoji,
 | |
|   elasticSearchMoviesAndShows
 | |
| };
 |