diff --git a/src/App.vue b/src/App.vue index b3ee099..e005bb0 100644 --- a/src/App.vue +++ b/src/App.vue @@ -46,18 +46,13 @@ - + @@ -126,7 +90,8 @@ body { transition: background-color 0.5s ease, color 0.5s ease; * { - transition: background-color 0.5s ease, color 0.5s ease; + transition: background-color 0.5s ease, color 0.5s ease, + border-color 0.5s ease; } &.hidden { @@ -158,20 +123,6 @@ img { .wrapper { position: relative; } -// .header { -// position: fixed; -// z-index: 15; -// display: flex; -// flex-direction: column; - -// @include tablet-min { -// width: calc(100% - 170px); -// margin-left: 95px; -// border-top: 0; -// border-bottom: 0; -// top: 0; -// } -// } // router view transition .fade-enter-active, diff --git a/src/api.js b/src/api.js index d36b6c5..da86d0c 100644 --- a/src/api.js +++ b/src/api.js @@ -1,24 +1,34 @@ -import axios from 'axios' -import storage from '@/storage' -import config from '@/config.json' -import path from 'path' -import store from '@/store' +import axios from "axios"; +import storage from "@/storage"; +import config from "@/config.json"; +import path from "path"; +import store from "@/store"; -const SEASONED_URL = config.SEASONED_URL -const ELASTIC_URL = config.ELASTIC_URL -const ELASTIC_INDEX = config.ELASTIC_INDEX +const token = () => store.getters["user/token"]; +const plexId = () => store.getters["user/plexId"]; + +const AUTHORIZATION_HEADERS = () => { + return { + Authorization: token(), + "Content-Type": "application/json" + }; +}; + +const SEASONED_URL = config.SEASONED_URL; +const ELASTIC_URL = config.ELASTIC_URL; +const ELASTIC_INDEX = config.ELASTIC_INDEX; // TODO // - Move autorization token and errors here? -const checkStatusAndReturnJson = (response) => { +const checkStatusAndReturnJson = response => { if (!response.ok) { - throw resp + throw resp; } - return response.json() -} + return response.json(); +}; -// - - - TMDB - - - +// - - - TMDB - - - /** * Fetches tmdb movie by id. Can optionally include cast credits in result object. @@ -26,23 +36,31 @@ const checkStatusAndReturnJson = (response) => { * @param {boolean} [credits=false] Include credits * @returns {object} Tmdb response */ -const getMovie = (id, checkExistance=false, credits=false, release_dates=false) => { - const url = new URL('v2/movie', SEASONED_URL) - url.pathname = path.join(url.pathname, id.toString()) +const getMovie = ( + id, + checkExistance = false, + credits = false, + release_dates = false +) => { + const url = new URL("v2/movie", SEASONED_URL); + url.pathname = path.join(url.pathname, id.toString()); if (checkExistance) { - url.searchParams.append('check_existance', true) + url.searchParams.append("check_existance", true); } if (credits) { - url.searchParams.append('credits', true) + url.searchParams.append("credits", true); } - if(release_dates) { - url.searchParams.append('release_dates', true) + if (release_dates) { + url.searchParams.append("release_dates", true); } - return fetch(url.href) + return fetch(url.href, { headers: AUTHORIZATION_HEADERS() }) .then(resp => resp.json()) - .catch(error => { console.error(`api error getting movie: ${id}`); throw error }) -} + .catch(error => { + console.error(`api error getting movie: ${id}`); + throw error; + }); +}; /** * Fetches tmdb show by id. Can optionally include cast credits in result object. @@ -50,20 +68,23 @@ const getMovie = (id, checkExistance=false, credits=false, release_dates=false) * @param {boolean} [credits=false] Include credits * @returns {object} Tmdb response */ -const getShow = (id, checkExistance=false, credits=false) => { - const url = new URL('v2/show', SEASONED_URL) - url.pathname = path.join(url.pathname, id.toString()) +const getShow = (id, checkExistance = false, credits = false) => { + const url = new URL("v2/show", SEASONED_URL); + url.pathname = path.join(url.pathname, id.toString()); if (checkExistance) { - url.searchParams.append('check_existance', true) + url.searchParams.append("check_existance", true); } if (credits) { - url.searchParams.append('credits', true) + url.searchParams.append("credits", true); } - return fetch(url.href) + return fetch(url.href, { headers: AUTHORIZATION_HEADERS() }) .then(resp => resp.json()) - .catch(error => { console.error(`api error getting show: ${id}`); throw error }) -} + .catch(error => { + console.error(`api error getting show: ${id}`); + throw error; + }); +}; /** * Fetches tmdb person by id. Can optionally include cast credits in result object. @@ -71,17 +92,20 @@ const getShow = (id, checkExistance=false, credits=false) => { * @param {boolean} [credits=false] Include credits * @returns {object} Tmdb response */ -const getPerson = (id, credits=false) => { - const url = new URL('v2/person', SEASONED_URL) - url.pathname = path.join(url.pathname, id.toString()) +const getPerson = (id, credits = false) => { + const url = new URL("v2/person", SEASONED_URL); + url.pathname = path.join(url.pathname, id.toString()); if (credits) { - url.searchParams.append('credits', true) + url.searchParams.append("credits", true); } return fetch(url.href) .then(resp => resp.json()) - .catch(error => { console.error(`api error getting person: ${id}`); throw error }) -} + .catch(error => { + console.error(`api error getting person: ${id}`); + throw error; + }); +}; /** * Fetches tmdb list by name. @@ -89,41 +113,39 @@ const getPerson = (id, credits=false) => { * @param {number} [page=1] * @returns {object} Tmdb list response */ -const getTmdbMovieListByName = (name, page=1) => { - const url = new URL('v2/movie/' + name, SEASONED_URL) - url.searchParams.append('page', page) - const headers = { authorization: storage.token } +const getTmdbMovieListByName = (name, page = 1) => { + const url = new URL("v2/movie/" + name, SEASONED_URL); + url.searchParams.append("page", page); - return fetch(url.href, { headers: headers }) - .then(resp => resp.json()) - // .catch(error => { console.error(`api error getting list: ${name}, page: ${page}`); throw error }) -} + return fetch(url.href, { headers: AUTHORIZATION_HEADERS() }).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('v2/request', SEASONED_URL) - url.searchParams.append('page', page) - const headers = { authorization: storage.token } +const getRequests = (page = 1) => { + const url = new URL("v2/request", SEASONED_URL); + url.searchParams.append("page", page); - return fetch(url.href, { headers: headers }) - .then(resp => resp.json()) - // .catch(error => { console.error(`api error getting list: ${name}, page: ${page}`); throw error }) -} + return fetch(url.href, { + headers: AUTHORIZATION_HEADERS() + }).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("v1/user/requests", SEASONED_URL); + url.searchParams.append("page", page); -const getUserRequests = (page=1) => { - const url = new URL('v1/user/requests', SEASONED_URL) - url.searchParams.append('page', page) - - const headers = { authorization: localStorage.getItem('token') } - - return fetch(url.href, { headers }) - .then(resp => resp.json()) -} + return fetch(url.href, { + headers: AUTHORIZATION_HEADERS() + }).then(resp => resp.json()); +}; /** * Fetches tmdb movies and shows by query. @@ -131,24 +153,27 @@ const getUserRequests = (page=1) => { * @param {number} [page=1] * @returns {object} Tmdb response */ -const searchTmdb = (query, page=1, adult=false, mediaType=null) => { - const url = new URL('v2/search', SEASONED_URL) - if (mediaType != null && ['movie', 'show', 'person'].includes(mediaType)) { - url.pathname += `/${mediaType}` +const searchTmdb = (query, page = 1, adult = false, mediaType = null) => { + const url = new URL("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) + url.searchParams.append("query", query); + url.searchParams.append("page", page); + url.searchParams.append("adult", adult); - const headers = { authorization: localStorage.getItem('token') } - - return fetch(url.href, { headers }) + return fetch(url.href, { + headers: AUTHORIZATION_HEADERS() + }) .then(resp => resp.json()) - .catch(error => { console.error(`api error searching: ${query}, page: ${page}`); throw error }) -} + .catch(error => { + console.error(`api error searching: ${query}, page: ${page}`); + throw error; + }); +}; -// - - - Torrents - - - +// - - - Torrents - - - /** * Search for torrents by query @@ -157,15 +182,18 @@ const searchTmdb = (query, page=1, adult=false, mediaType=null) => { * @returns {object} Torrent response */ const searchTorrents = (query, authorization_token) => { - const url = new URL('/api/v1/pirate/search', SEASONED_URL) - url.searchParams.append('query', query) + const url = new URL("/api/v1/pirate/search", SEASONED_URL); + url.searchParams.append("query", query); - const headers = { authorization: storage.token } - - return fetch(url.href, { headers: headers }) + return fetch(url.href, { + headers: AUTHORIZATION_HEADERS() + }) .then(resp => resp.json()) - .catch(error => { console.error(`api error searching torrents: ${query}`); throw error }) -} + .catch(error => { + console.error(`api error searching torrents: ${query}`); + throw error; + }); +}; /** * Add magnet to download queue. @@ -175,28 +203,27 @@ const searchTorrents = (query, authorization_token) => { * @returns {object} Success/Failure response */ const addMagnet = (magnet, name, tmdb_id) => { - const url = new URL('v1/pirate/add', SEASONED_URL) + const url = new URL("v1/pirate/add", SEASONED_URL); const body = JSON.stringify({ magnet: magnet, name: name, tmdb_id: tmdb_id - }) - const headers = { - 'Content-Type': 'application/json', - authorization: storage.token - } + }); return fetch(url.href, { - method: 'POST', - headers, - body - }) + method: "POST", + headers: AUTHORIZATION_HEADERS(), + body + }) .then(resp => resp.json()) - .catch(error => { console.error(`api error adding magnet: ${name} ${error}`); throw error }) -} + .catch(error => { + console.error(`api error adding magnet: ${name} ${error}`); + throw error; + }); +}; -// - - - Plex/Request - - - +// - - - Plex/Request - - - /** * Request a movie or show from id. If authorization token is included the user will be linked @@ -206,28 +233,19 @@ const addMagnet = (magnet, name, tmdb_id) => { * @param {string} [authorization_token] To identify the requesting user * @returns {object} Success/Failure response */ -const request = (id, type, authorization_token=undefined) => { - const url = new URL('v2/request', SEASONED_URL) -// url.pathname = path.join(url.pathname, id.toString()) -// url.searchParams.append('type', type) - - const headers = { - 'Authorization': authorization_token, - 'Content-Type': 'application/json' - } - const body = { - id: id, - type: type - } - +const request = (id, type) => { + const url = new URL("v2/request", SEASONED_URL); return fetch(url.href, { - method: 'POST', - headers: headers, - body: JSON.stringify(body) + method: "POST", + headers: AUTHORIZATION_HEADERS(), + body: JSON.stringify({ id, type }) }) - .then(resp => resp.json()) - .catch(error => { console.error(`api error requesting: ${id}, type: ${type}`); throw error }) -} + .then(resp => resp.json()) + .catch(error => { + console.error(`api error requesting: ${id}, type: ${type}`); + throw error; + }); +}; /** * Check request status by tmdb id and type @@ -235,186 +253,182 @@ const request = (id, type, authorization_token=undefined) => { * @param {string} type * @returns {object} Success/Failure response */ -const getRequestStatus = (id, type, authorization_token=undefined) => { - const url = new URL('v2/request', SEASONED_URL) - url.pathname = path.join(url.pathname, id.toString()) - url.searchParams.append('type', type) +const getRequestStatus = (id, type, authorization_token = undefined) => { + const url = new URL("v2/request", SEASONED_URL); + url.pathname = path.join(url.pathname, id.toString()); + url.searchParams.append("type", type); - return fetch(url.href) + return fetch(url.href, { headers: AUTHORIZATION_HEADERS() }) .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}`) + 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)) -} + .catch(err => Promise.reject(err)); +}; -const watchLink = (title, year, authorization_token=undefined) => { - const url = new URL('v1/plex/watch-link', SEASONED_URL) - url.searchParams.append('title', title) - url.searchParams.append('year', year) +const watchLink = (title, year) => { + const url = new URL("v1/plex/watch-link", SEASONED_URL); + url.searchParams.append("title", title); + url.searchParams.append("year", year); + + return fetch(url.href, { headers: AUTHORIZATION_HEADERS() }) + .then(resp => resp.json()) + .then(response => response.link); +}; + +const movieImages = id => { + const url = new URL(`v2/movie/${id}/images`, SEASONED_URL); const headers = { - 'Authorization': authorization_token, - 'Content-Type': 'application/json' - } + "Content-Type": "application/json" + }; - return fetch(url.href, { headers }) - .then(resp => resp.json()) - .then(response => response.link) -} + return fetch(url.href, { headers }).then(resp => resp.json()); +}; // - - - Seasoned user endpoints - - - const register = (username, password) => { - const url = new URL('v1/user', SEASONED_URL) + const url = new URL("v1/user", SEASONED_URL); const options = { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, + method: "POST", + headers: AUTHORIZATION_HEADERS(), 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) + console.error( + "Unexpected error occured before receiving response. Error:", + error + ); // TODO log to sentry the issue here - throw error - }) -} + throw error; + }); +}; -const login = (username, password, throwError=false) => { - const url = new URL('v1/user/login', SEASONED_URL) +const login = (username, password, throwError = false) => { + const url = new URL("v1/user/login", SEASONED_URL); const options = { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, + 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(); + 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); - }) -} + if (throwError) throw resp; + else console.error("Error occured when trying to sign in.\nError:", resp); + }); +}; const getSettings = () => { - const settingsExists = (value) => { - if (value instanceof Object && value.hasOwnProperty('settings')) + const settingsExists = value => { + if (value instanceof Object && value.hasOwnProperty("settings")) return value; throw "Settings does not exist in response object."; - } - const commitSettingsToStore = (response) => { - store.dispatch('userModule/setSettings', response.settings) - return response - } + }; + const commitSettingsToStore = response => { + store.dispatch("user/setSettings", response.settings); + return response; + }; - const url = new URL('v1/user/settings', SEASONED_URL) + const url = new URL("v1/user/settings", SEASONED_URL); - const authorization_token = localStorage.getItem('token') - const headers = authorization_token ? { - 'Authorization': authorization_token, - 'Content-Type': 'application/json' - } : {} - - return fetch(url.href, { headers }) + return fetch(url.href, { headers: AUTHORIZATION_HEADERS() }) .then(resp => resp.json()) .then(settingsExists) .then(commitSettingsToStore) .then(response => response.settings) - .catch(error => { console.log('api error getting user settings'); throw error }) -} - -const updateSettings = (settings) => { - const url = new URL('v1/user/settings', SEASONED_URL) - - const authorization_token = localStorage.getItem('token') - const headers = authorization_token ? { - 'Authorization': authorization_token, - 'Content-Type': 'application/json' - } : {} + .catch(error => { + console.log("api error getting user settings"); + throw error; + }); +}; +const updateSettings = settings => { + const url = new URL("v1/user/settings", SEASONED_URL); return fetch(url.href, { - method: 'PUT', - headers, - body: JSON.stringify(settings) - }) + method: "PUT", + headers: AUTHORIZATION_HEADERS(), + body: JSON.stringify(settings) + }) .then(resp => resp.json()) - .catch(error => { console.log('api error updating user settings'); throw error }) -} + .catch(error => { + console.log("api error updating user settings"); + throw error; + }); +}; // - - - Authenticate with plex - - - const linkPlexAccount = (username, password) => { - const url = new URL('v1/user/link_plex', SEASONED_URL) - const body = { username, password } - const headers = { - 'Content-Type': 'application/json', - authorization: storage.token - } + const url = new URL("v1/user/link_plex", SEASONED_URL); + const body = { username, password }; return fetch(url.href, { - method: 'POST', - headers, + method: "POST", + headers: AUTHORIZATION_HEADERS(), body: JSON.stringify(body) }) - .then(resp => resp.json()) - .catch(error => { console.error(`api error linking plex account: ${username}`); throw error }) -} + .then(resp => resp.json()) + .catch(error => { + console.error(`api error linking plex account: ${username}`); + throw error; + }); +}; const unlinkPlexAccount = (username, password) => { - const url = new URL('v1/user/unlink_plex', SEASONED_URL) - const headers = { - 'Content-Type': 'application/json', - authorization: storage.token - } + const url = new URL("v1/user/unlink_plex", SEASONED_URL); return fetch(url.href, { - method: 'POST', - headers + method: "POST", + headers: AUTHORIZATION_HEADERS() }) - .then(resp => resp.json()) - .catch(error => { console.error(`api error unlinking plex account: ${username}`); throw error }) -} - + .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('v1/user' + urlPath, SEASONED_URL) - url.searchParams.append('days', days) - url.searchParams.append('y_axis', chartType) + const url = new URL("v1/user" + urlPath, SEASONED_URL); + url.searchParams.append("days", days); + url.searchParams.append("y_axis", chartType); - const authorization_token = localStorage.getItem('token') - const headers = authorization_token ? { - 'Authorization': authorization_token, - 'Content-Type': 'application/json' - } : {} - - return fetch(url.href, { headers }) + return fetch(url.href, { headers: AUTHORIZATION_HEADERS() }) .then(resp => resp.json()) - .catch(error => { console.log('api error fetching chart'); throw error }) -} - + .catch(error => { + console.log("api error fetching chart"); + throw error; + }); +}; // - - - Random emoji - - - const getEmoji = () => { - const url = new URL('v1/emoji', SEASONED_URL) + const url = new URL("v1/emoji", SEASONED_URL); return fetch(url.href) .then(resp => resp.json()) - .catch(error => { console.log('api error getting emoji'); throw error }) -} - + .catch(error => { + console.log("api error getting emoji"); + throw error; + }); +}; // - - - ELASTIC SEARCH - - - // This elastic index contains titles mapped to ids. Lightning search @@ -426,44 +440,41 @@ const getEmoji = () => { * @param {string} query * @returns {object} List of movies and shows matching query */ -const elasticSearchMoviesAndShows = (query) => { - const url = new URL(path.join(ELASTIC_INDEX, '/_search'), ELASTIC_URL) - const headers = { - 'Content-Type': 'application/json' - } +const elasticSearchMoviesAndShows = query => { + const url = new URL(path.join(ELASTIC_INDEX, "/_search"), ELASTIC_URL); const body = { - "sort" : [ - { "popularity" : {"order" : "desc"}}, - "_score" - ], - "query": { - "bool": { - "should": [{ - "match_phrase_prefix": { - "original_name": query + sort: [{ popularity: { order: "desc" } }, "_score"], + query: { + bool: { + should: [ + { + match_phrase_prefix: { + original_name: query + } + }, + { + match_phrase_prefix: { + original_title: query + } } - }, - { - "match_phrase_prefix": { - "original_title": query - } - }] + ] } }, - "size": 6 - } + size: 22 + }; return fetch(url.href, { - method: 'POST', - headers: headers, + method: "POST", + headers: AUTHORIZATION_HEADERS(), body: JSON.stringify(body) }) .then(resp => resp.json()) - .catch(error => { console.log(`api error searching elasticsearch: ${query}`); throw error }) -} - - + .catch(error => { + console.log(`api error searching elasticsearch: ${query}`); + throw error; + }); +}; export { getMovie, @@ -477,6 +488,7 @@ export { addMagnet, request, watchLink, + movieImages, getRequestStatus, linkPlexAccount, unlinkPlexAccount, @@ -487,4 +499,4 @@ export { fetchChart, getEmoji, elasticSearchMoviesAndShows -} +}; diff --git a/src/components/404.vue b/src/components/404.vue index 14cd231..68eca47 100644 --- a/src/components/404.vue +++ b/src/components/404.vue @@ -3,26 +3,31 @@

Page Not Found

- go back to previous page + go back to previous page diff --git a/src/components/Signin.vue b/src/components/Signin.vue index 8baea18..1d056d9 100644 --- a/src/components/Signin.vue +++ b/src/components/Signin.vue @@ -2,88 +2,94 @@

Sign in

- - + + sign in - Don't have a user? Register here + Don't have a user? Register here
- -