From 6ebd81c2fa26fb7410228b73b24357c12a728637 Mon Sep 17 00:00:00 2001 From: Anthony Tsang Date: Mon, 20 Jan 2020 12:49:37 +0900 Subject: [PATCH 1/2] Fix incorrectly concatenated urls and add wrapper function to improve proper url creation --- src/actions/detailsActions.js | 7 ++++--- src/actions/modActions.js | 32 +++++++++++++++---------------- src/actions/playlistsActions.js | 9 +++++---- src/actions/queueActions.js | 11 ++++++----- src/actions/searchActions.js | 7 ++++--- src/actions/songListActions.js | 17 ++++++++-------- src/components/ModsView.js | 7 ++++--- src/components/PlaylistDetails.js | 7 ++++--- src/components/SettingsView.js | 4 +++- src/components/WelcomePage.js | 5 ++++- src/utilities.js | 15 +++++++++++++++ 11 files changed, 74 insertions(+), 47 deletions(-) diff --git a/src/actions/detailsActions.js b/src/actions/detailsActions.js index 2e481b3..db9b4b8 100644 --- a/src/actions/detailsActions.js +++ b/src/actions/detailsActions.js @@ -1,6 +1,7 @@ import { LOAD_DETAILS, CLEAR_DETAILS, SET_DETAILS_LOADING, DISPLAY_WARNING } from './types' import { SONG_DETAILS } from '../constants/views' import { BEATSAVER_BASE_URL, BSABER_BASE_URL } from '../constants/urls' +import { makeUrl } from '../utilities' import AdmZip from 'adm-zip' import { hashAndWriteToMetadata } from './queueActions' @@ -61,7 +62,7 @@ export const loadDetailsFromKey = key => (dispatch, getState) => { }) setView(SONG_DETAILS)(dispatch, getState) if((/^[a-f0-9]+$/).test(key)) { - fetch(`${BEATSAVER_BASE_URL}/api/maps/detail/${key}`) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/maps/detail/${key}`)) .then(res => { if(res.status === 404){ dispatch({ @@ -75,7 +76,7 @@ export const loadDetailsFromKey = key => (dispatch, getState) => { }) .then(res => res.json()) .then(details => { - fetch(`${BEATSAVER_BASE_URL}${details.downloadURL}`) + fetch(makeUrl(BEATSAVER_BASE_URL, details.downloadURL)) .then(res => res.arrayBuffer()) .then(data => { let zip = new AdmZip(new Buffer(data)) @@ -106,7 +107,7 @@ export const loadDetailsFromKey = key => (dispatch, getState) => { } }) }) - fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${key}/ratings`) + fetch(makeUrl(BSABER_BASE_URL, `/wp-json/bsaber-api/songs/${key}/ratings`)) .then(res => res.json()) .then(bsaberData => { dispatch({ diff --git a/src/actions/modActions.js b/src/actions/modActions.js index 160dee7..43ba3fd 100644 --- a/src/actions/modActions.js +++ b/src/actions/modActions.js @@ -1,7 +1,7 @@ import { SET_MOD_LIST, SET_RESOURCE, SET_LOADING, LOAD_MOD_DETAILS, INSTALL_MOD, SET_SCANNING_FOR_MODS, SET_INSTALLED_MODS, DISPLAY_WARNING, UNINSTALL_MOD, CLEAR_MODS, ADD_TO_QUEUE, UPDATE_PROGRESS, ADD_DEPENDENT, SET_MOD_ACTIVE, ADD_PENDING_MOD, SET_PATCHING, SET_MOD_UPDATE_AVAILABLE, CLEAR_MOD_UPDATES, SET_IGNORE_MOD_UPDATE } from './types' import { MODS_VIEW, MOD_DETAILS } from '../constants/views' import { BEATMODS_BASE_URL } from '../constants/urls' - +import { makeUrl } from '../utilities' import { BEATMODS, LIBRARY } from '../constants/resources' import modIcon from '../assets/dark/mod.png' @@ -28,7 +28,7 @@ export const fetchApprovedMods = () => (dispatch, getState) => { type: SET_LOADING, payload: true }) - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?status=approved&gameVersion=${getState().settings.gameVersion}`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?status=approved&gameVersion=${getState().settings.gameVersion}`)) .then(res => res.json()) .then(beatModsResponse => { dispatch({ @@ -55,7 +55,7 @@ export const fetchRecommendedMods = () => (dispatch, getState) => { let recommendedMods = ['CameraPlus', 'YUR Fit Calorie Tracker', 'SyncSaber', 'Custom Sabers', 'Custom Platforms', 'Custom Avatars', 'BeatSaberTweaks', 'PracticePlugin', 'Counters+'] let mods = [] for(let i = 0; i < recommendedMods.length; i++) { - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?name=${encodeURIComponent(recommendedMods[i])}&gameVersion=${getState().settings.gameVersion}`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?name=${encodeURIComponent(recommendedMods[i])}&gameVersion=${getState().settings.gameVersion}`)) .then(res => res.json()) .then(beatModsResponse => { if(beatModsResponse.length === 0) { recommendedMods.splice(i, 1); return } @@ -100,7 +100,7 @@ export const fetchModCategory = category => (dispatch, getState) => { type: SET_LOADING, payload: true }) - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?category=${ category }&status=approved&gameVersion=${getState().settings.gameVersion}`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?category=${ category }&status=approved&gameVersion=${getState().settings.gameVersion}`)) .then(res => res.json()) .then(beatModsResponse => { dispatch({ @@ -124,7 +124,7 @@ export const fetchLocalMods = () => (dispatch, getState) => { type: SET_LOADING, payload: true }) - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?status=approved&status=inactive`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?status=approved&status=inactive`)) .then(res => res.json()) .then(beatModsResponse => { let installedMods = getState().mods.installedMods @@ -162,7 +162,7 @@ export const fetchActivatedMods = () => (dispatch, getState) => { type: SET_LOADING, payload: true }) - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?status=approved&status=inactive`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?status=approved&status=inactive`)) .then(res => res.json()) .then(beatModsResponse => { let activatedMods = getState().mods.installedMods.filter(mod => mod.active === true) @@ -196,7 +196,7 @@ export const loadModDetails = modId => (dispatch, getState) => { type: SET_LOADING, payload: true }) - fetch(`${BEATMODS_BASE_URL}/api/v1/mod`) + fetch(makeUrl(BEATMODS_BASE_URL, '/api/v1/mod')) .then(res => res.json()) .then(beatModsResponse => { dispatch({ @@ -234,7 +234,7 @@ export const installMod = (modName, version, dependencyOf = '') => (dispatch, ge } return } - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?status=approved&status=inactivename=${ encodeURIComponent(modName) }&gameVersion=${ getState().settings.gameVersion }`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?status=approved&status=inactivename=${ encodeURIComponent(modName) }&gameVersion=${ getState().settings.gameVersion }`)) .then(res => res.json()) .then(beatModsResponse => { let latestVersion = '0.0.0' @@ -285,13 +285,13 @@ export const installMod = (modName, version, dependencyOf = '') => (dispatch, ge } else { zip.extractAllTo(path.join(getState().settings.installationDirectory, 'IPA', 'Pending')) } - + let entries = zip.getEntries() let files = [] for(let i = 0; i < entries.length; i++) { files.push(entries[i].entryName) } - + if(modName === 'BSIPA') { execFile(path.join(getState().settings.installationDirectory, 'IPA.exe'), ['-n'], { cwd: getState().settings.installationDirectory }) dispatch({ @@ -332,13 +332,13 @@ export const installMod = (modName, version, dependencyOf = '') => (dispatch, ge let zip = new AdmZip(data) zip.extractAllTo(getState().settings.installationDirectory) - + let entries = zip.getEntries() let files = [] for(let i = 0; i < entries.length; i++) { files.push(entries[i].entryName) } - + dispatch({ type: INSTALL_MOD, payload: { @@ -518,7 +518,7 @@ export const checkInstalledMods = () => (dispatch, getState) => { let md5sum = crypto.createHash('md5') md5sum.update(data) let hash = md5sum.digest('hex') - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?hash=${hash}`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?hash=${hash}`)) .then(res => res.json()) .then(beatModsResponse => { if(beatModsResponse.length > 0) { @@ -573,7 +573,7 @@ export const checkInstalledMods = () => (dispatch, getState) => { let md5sum = crypto.createHash('md5') md5sum.update(data) let hash = md5sum.digest('hex') - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?hash=${hash}`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?hash=${hash}`)) .then(res => res.json()) .then(beatModsResponse => { if(beatModsResponse.length > 0) { @@ -672,7 +672,7 @@ export const checkModsForUpdates = () => (dispatch, getState) => { }) let installedMods = getState().mods.installedMods for(let m = 0; m < installedMods.length; m++) { - fetch(`${BEATMODS_BASE_URL}/api/v1/mod?status=approved&name=${ installedMods[m].name }&gameVersion=${ getState().settings.gameVersion }`) + fetch(makeUrl(BEATMODS_BASE_URL, `/api/v1/mod?status=approved&name=${ installedMods[m].name }&gameVersion=${ getState().settings.gameVersion }`)) .then(res => res.json()) .then(beatModsResponse => { if(beatModsResponse.length === 0) return @@ -732,7 +732,7 @@ export const gamePatchedWith = () => (dispatch, getState) => { installationType = 'IPA' dispatch({ type: 'DISPLAY_WARNING', - payload: { + payload: { text: `Your game is patched with IPA. It is reccommeded that you upgrade to BSIPA to maintain compatability with future mods. To upgrade, reinstall Beat Saber and download any mod from BeatDrop.`, color: 'gold' diff --git a/src/actions/playlistsActions.js b/src/actions/playlistsActions.js index 368bf24..0fda1ea 100644 --- a/src/actions/playlistsActions.js +++ b/src/actions/playlistsActions.js @@ -1,6 +1,7 @@ import { FETCH_LOCAL_PLAYLISTS, LOAD_NEW_PLAYLIST_IMAGE, SET_NEW_PLAYLIST_OPEN, SET_PLAYLIST_PICKER_OPEN, CLEAR_PLAYLIST_DIALOG, LOAD_PLAYLIST_DETAILS, LOAD_PLAYLIST_SONGS, CLEAR_PLAYLIST_DETAILS, SET_PLAYLIST_EDITING, SET_LOADING, DISPLAY_WARNING } from './types' import { PLAYLIST_LIST, PLAYLIST_DETAILS } from '../constants/views' import { BEATSAVER_BASE_URL } from '../constants/urls' +import { makeUrl } from '../utilities' import { defaultPlaylistIcon } from '../b64Assets' import { hashAndWriteToMetadata } from './queueActions' import { setView } from './viewActions' @@ -21,7 +22,7 @@ export const fetchLocalPlaylists = (doSetView) => (dispatch, getState) => { } let playlists = [] fs.access(path.join(state.settings.installationDirectory, 'Playlists'), (err) => { - if(err) { + if(err) { fs.mkdirSync(path.join(state.settings.installationDirectory, 'Playlists')) } fs.readdir(path.join(state.settings.installationDirectory, 'Playlists'), (err, files) => { @@ -197,7 +198,7 @@ export const loadPlaylistDetails = playlistFile => (dispatch, getState) => { }) }) } else { - fetch(`${BEATSAVER_BASE_URL}/api/maps/by-hash/${playlist.songs[i].hash}`) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/maps/by-hash/${playlist.songs[i].hash}`)) .then(res => res.json()) .then(song => { song.coverURL = `https://beatsaver.com/${song.coverURL}` @@ -214,7 +215,7 @@ export const loadPlaylistDetails = playlistFile => (dispatch, getState) => { }) } } else { - fetch(`${BEATSAVER_BASE_URL}/api/maps/detail/${playlist.songs[i].key}`) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/maps/detail/${playlist.songs[i].key}`)) .then(res => res.json()) .then(details => { details.coverURL = `${BEATSAVER_BASE_URL}/${details.coverURL}` @@ -331,7 +332,7 @@ export const addSongToPlaylist = (song, playlistFile) => (dispatch, getState) => }) }) } - + fs.writeFile(playlistFile, JSON.stringify(playlist), 'UTF8', (err) => { if(err) { dispatch({ diff --git a/src/actions/queueActions.js b/src/actions/queueActions.js index 9e03d45..d83aad4 100644 --- a/src/actions/queueActions.js +++ b/src/actions/queueActions.js @@ -1,6 +1,7 @@ import { ADD_TO_QUEUE, CLEAR_QUEUE, UPDATE_PROGRESS, SET_DOWNLOADED_SONGS, SET_DOWNLOADING_COUNT, SET_WAIT_LIST, DISPLAY_WARNING, SET_SCANNING_FOR_SONGS, SET_DISCOVERED_FILES, SET_PROCESSED_FILES } from './types' import { SONG_LIST } from '../constants/views' import { BEATSAVER_BASE_URL } from '../constants/urls' +import { makeUrl } from '../utilities' import { isModInstalled, installEssentialMods } from './modActions' import { setView } from './viewActions' @@ -20,7 +21,7 @@ export const downloadSong = (identity) => (dispatch, getState) => { if(!isModInstalled('SongLoader')(dispatch, getState)) installEssentialMods()(dispatch, getState) let hash = identity if(identity) { - fetch(`${BEATSAVER_BASE_URL}/api/maps/by-hash/${hash}`) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/maps/by-hash/${hash}`)) .then(res => res.json()) .then(song => { hash = song.hash @@ -40,14 +41,14 @@ export const downloadSong = (identity) => (dispatch, getState) => { setTimeout(() => { document.getElementById('queue-button').classList.remove('notify') }, 1000) - fetch(`${BEATSAVER_BASE_URL}/api/maps/by-hash/${hash}`) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/maps/by-hash/${hash}`)) .then(res => res.json()) .then(song => { let utc = Date.now() if(song) { dispatch({ type: ADD_TO_QUEUE, - payload: { + payload: { utc, hash: song.hash, image: `${BEATSAVER_BASE_URL}${ song.coverURL }`, @@ -238,13 +239,13 @@ export const downloadSong = (identity) => (dispatch, getState) => { setTimeout(() => { document.getElementById('queue-button').classList.remove('notify') }, 1000) - fetch(`${BEATSAVER_BASE_URL}/api/maps/by-hash/${hash}`) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/maps/by-hash/${hash}`)) .then(res => res.json()) .then(song => { let utc = Date.now() dispatch({ type: ADD_TO_QUEUE, - payload: { + payload: { utc, hash: song.hash, image: `${BEATSAVER_BASE_URL}${ song.coverURL }`, diff --git a/src/actions/searchActions.js b/src/actions/searchActions.js index e375587..c9d1808 100644 --- a/src/actions/searchActions.js +++ b/src/actions/searchActions.js @@ -1,5 +1,6 @@ import { SET_SEARCH_SOURCES, SUBMIT_SEARCH, SET_LOADING } from './types' import { BEATSAVER_BASE_URL } from '../constants/urls' +import { makeUrl } from '../utilities' const { remote } = window.require('electron') const fs = remote.require('fs') @@ -49,7 +50,7 @@ export const submitSearch = keywords => (dispatch, getState) => { localResultsReady = true // BeatSaver Search - fetch(`${BEATSAVER_BASE_URL}/api/search/text/all?q=` + encodeURIComponent(keywords.replace('/', '\\'))) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/search/text/all?q=${encodeURIComponent(keywords.replace('/', '\\'))}`)) .then(res => res.json()) .then(data => { beatSaverSongs = data.docs @@ -66,10 +67,10 @@ export const submitSearch = keywords => (dispatch, getState) => { } beatSaverResultsReady = true }) - + // BeatSaver ID Search if(isId) { - fetch(`${BEATSAVER_BASE_URL}/api/maps/detail/` + keywords) + fetch(makeUrl(BEATSAVER_BASE_URL, `/api/maps/detail/${keywords}`)) .then(res => { if(res.status !== 200) { beatSaverIdResultsReady = true; return } return res.json() }) .then(data => { if(!data) { beatSaverIdResultsReady = true; return } diff --git a/src/actions/songListActions.js b/src/actions/songListActions.js index cb39a52..00e777d 100644 --- a/src/actions/songListActions.js +++ b/src/actions/songListActions.js @@ -2,6 +2,7 @@ import { FETCH_NEW, FETCH_TOP_DOWNLOADS, FETCH_TOP_FINISHED, FETCH_LOCAL_SONGS, import { SONG_LIST } from '../constants/views' import { BEATSAVER, LIBRARY } from '../constants/resources' import { BEATSAVER_BASE_URL, BSABER_BASE_URL } from '../constants/urls' +import { makeUrl } from '../utilities' import { hashAndWriteToMetadata } from './queueActions' import { setView } from './viewActions' @@ -29,7 +30,7 @@ export const fetchNew = () => (dispatch, getState) => { type: SET_RESOURCE, payload: BEATSAVER.NEW_SONGS }) - fetch(`${BEATSAVER_BASE_URL}api/maps/latest`) + fetch(makeUrl(BEATSAVER_BASE_URL, '/api/maps/latest')) .then(res => res.json()) .then(data => { console.log(data) @@ -43,7 +44,7 @@ export const fetchNew = () => (dispatch, getState) => { }) console.log(data); for(let i = 0; i < data.docs.length; i++) { - fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`) + fetch(makeUrl(BSABER_BASE_URL, `/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`)) .then(res => res.json()) .then(bsaberData => { dispatch({ @@ -75,7 +76,7 @@ export const fetchTopDownloads = () => (dispatch, getState) => { type: SET_RESOURCE, payload: BEATSAVER.TOP_DOWNLOADED_SONGS }) - fetch(`${BEATSAVER_BASE_URL}/api/maps/downloads`) + fetch(makeUrl(BEATSAVER_BASE_URL, '/api/maps/downloads')) .then(res => res.json()) .then(data => { dispatch({ @@ -87,7 +88,7 @@ export const fetchTopDownloads = () => (dispatch, getState) => { payload: false }) for(let i = 0; i < data.songs.length; i++) { - fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`) + fetch(makeUrl(BSABER_BASE_URL, `/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`)) .then(res => res.json()) .then(bsaberData => { dispatch({ @@ -119,7 +120,7 @@ export const fetchTopFinished = () => (dispatch, getState) => { type: SET_RESOURCE, payload: BEATSAVER.TOP_FINISHED_SONGS }) - fetch(`${BEATSAVER_BASE_URL}/api/maps/plays`) + fetch(makeUrl(BEATSAVER_BASE_URL, '/api/maps/plays')) .then(res => res.json()) .then(data => { dispatch({ @@ -131,7 +132,7 @@ export const fetchTopFinished = () => (dispatch, getState) => { payload: false }) for(let i = 0; i < data.docs.length; i++) { - fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`) + fetch(makeUrl(BSABER_BASE_URL, `/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`)) .then(res => res.json()) .then(bsaberData => { dispatch({ @@ -216,7 +217,7 @@ export const loadMore = () => (dispatch, getState) => { payload: true }) let state = getState() - fetch(resourceUrl[state.resource] + '/' + state.songs.songs.length) + fetch(makeUrl(resourceUrl[state.resource], state.songs.songs.length)) .then(res => { return res.json() }) @@ -231,7 +232,7 @@ export const loadMore = () => (dispatch, getState) => { }) console.log(data) for(let i = state.songs.songs.length; i < state.songs.songs.length + data.docs.length; i++) { - fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i - state.songs.songs.length].key}/ratings`) + fetch(makeUrl(BSABER_BASE_URL, `/wp-json/bsaber-api/songs/${data.docs[i - state.songs.songs.length].key}/ratings`)) .then(res => res.json()) .then(bsaberData => { dispatch({ diff --git a/src/components/ModsView.js b/src/components/ModsView.js index 9ab7ed1..2f3e24c 100644 --- a/src/components/ModsView.js +++ b/src/components/ModsView.js @@ -2,13 +2,14 @@ import React, { Component, Fragment } from 'react' import '../css/ModsView.scss' import { connect } from 'react-redux' +import { BEATMODS_BASE_URL } from '../constants/urls' import { BEATMODS, LIBRARY } from '../constants/resources'; +import { makeRenderKey, makeUrl } from '../utilities' import { loadModDetails, installMod, uninstallMod, fetchModCategory, deactivateMod, activateMod } from '../actions/modActions' import { displayWarning } from '../actions/warningActions' import { ContextMenuTrigger, MenuItem, ContextMenu } from 'react-contextmenu'; -import { makeRenderKey } from '../utilities' import LibraryIndicator from './LibraryIndicator'; import DeactivatedIndicator from './DeactivatedIndicator'; import SortBar from './SortBar'; @@ -19,7 +20,7 @@ class ModsView extends Component { Catergories(props) { return (