472 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			472 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 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
 | |
| 
 | |
| // 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('v2/movie', SEASONED_URL)
 | |
|   url.pathname = path.join(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('v2/show', SEASONED_URL)
 | |
|   url.pathname = path.join(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('v2/person', SEASONED_URL)
 | |
|   url.pathname = path.join(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 })
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * 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('v2/movie/' + name, SEASONED_URL)
 | |
|   url.searchParams.append('page', page)
 | |
|   const headers = { authorization: storage.token }
 | |
| 
 | |
|   return fetch(url.href, { headers: 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 }
 | |
| 
 | |
|   return fetch(url.href, { headers: 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 headers = { authorization: localStorage.getItem('token') }
 | |
| 
 | |
|   return fetch(url.href, { headers })
 | |
|     .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('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)
 | |
| 
 | |
|   const headers = { authorization: localStorage.getItem('token') }
 | |
| 
 | |
|   return fetch(url.href, { headers })
 | |
|     .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, authorization_token) => {
 | |
|   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 })
 | |
|     .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('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
 | |
|     })
 | |
|     .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
 | |
|  * @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
 | |
|   }
 | |
| 
 | |
|   return fetch(url.href, {
 | |
|     method: 'POST',
 | |
|     headers: headers,
 | |
|     body: JSON.stringify(body)
 | |
|   })
 | |
|   .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, 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)
 | |
|     .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))
 | |
| }
 | |
| 
 | |
| // - - - Seasoned user endpoints - - -
 | |
| 
 | |
| const register = (username, password) => {
 | |
|   const url = new URL('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) => {
 | |
|   const url = new URL('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 => resp.json())
 | |
|     .catch(error => {
 | |
|       console.error('Unexpected error occured before receiving response. Error:', error)
 | |
|       // TODO log to sentry the issue here
 | |
|       throw error
 | |
|     })
 | |
| }
 | |
| 
 | |
| const getSettings = () => {
 | |
|   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 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 })
 | |
|     .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'
 | |
|   } : {}
 | |
| 
 | |
|   return fetch(url.href, {
 | |
|       method: 'PUT',
 | |
|       headers,
 | |
|       body: JSON.stringify(settings)
 | |
|     })
 | |
|     .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('v1/user/link_plex', SEASONED_URL)
 | |
|   const body = { username, password }
 | |
|   const headers = {
 | |
|     'Content-Type': 'application/json',
 | |
|     authorization: storage.token
 | |
|   }
 | |
| 
 | |
|   return fetch(url.href, {
 | |
|     method: 'POST',
 | |
|     headers,
 | |
|     body: JSON.stringify(body)
 | |
|   })
 | |
|   .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
 | |
|   }
 | |
| 
 | |
|   return fetch(url.href, {
 | |
|     method: 'POST',
 | |
|     headers
 | |
|   })
 | |
|   .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 authorization_token = localStorage.getItem('token')
 | |
|   const headers = authorization_token ? {
 | |
|     'Authorization': authorization_token,
 | |
|     'Content-Type': 'application/json'
 | |
|   } : {}
 | |
| 
 | |
|   return fetch(url.href, { headers })
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => { console.log('api error fetching chart'); throw error })
 | |
| }
 | |
| 
 | |
| 
 | |
| // - - - Random emoji - - -
 | |
| 
 | |
| const getEmoji = () => {
 | |
|   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 })
 | |
| }
 | |
| 
 | |
| 
 | |
| // - - - 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) => {
 | |
|   const url = new URL(path.join(ELASTIC_INDEX, '/_search'), ELASTIC_URL)
 | |
|   const headers = {
 | |
|     'Content-Type': 'application/json'
 | |
|   }
 | |
| 
 | |
|   const body = {
 | |
|     "sort" : [
 | |
|       { "popularity" : {"order" : "desc"}},
 | |
|       "_score"
 | |
|     ],
 | |
|     "query": {
 | |
|       "bool": {
 | |
|         "should": [{
 | |
|           "match_phrase_prefix": {
 | |
|             "original_name": query
 | |
|           }
 | |
|         },
 | |
|         {
 | |
|           "match_phrase_prefix": {
 | |
|             "original_title": query
 | |
|           }
 | |
|         }]
 | |
|       }
 | |
|     },
 | |
|     "size": 6
 | |
|   }
 | |
| 
 | |
|   return fetch(url.href, {
 | |
|     method: 'POST',
 | |
|     headers: headers,
 | |
|     body: JSON.stringify(body)
 | |
|   })
 | |
|     .then(resp => resp.json())
 | |
|     .catch(error => { console.log(`api error searching elasticsearch: ${query}`); throw error })
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| export {
 | |
|   getMovie,
 | |
|   getShow,
 | |
|   getPerson,
 | |
|   getTmdbMovieListByName,
 | |
|   searchTmdb,
 | |
|   getUserRequests,
 | |
|   getRequests,
 | |
|   searchTorrents,
 | |
|   addMagnet,
 | |
|   request,
 | |
|   getRequestStatus,
 | |
|   linkPlexAccount,
 | |
|   unlinkPlexAccount,
 | |
|   register,
 | |
|   login,
 | |
|   getSettings,
 | |
|   updateSettings,
 | |
|   fetchChart,
 | |
|   getEmoji,
 | |
|   elasticSearchMoviesAndShows
 | |
| }
 |