songListActions.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. import { FETCH_NEW, FETCH_TOP_DOWNLOADS, FETCH_TOP_FINISHED, FETCH_SEARCH, FETCH_LOCAL_SONGS, ADD_BSABER_RATING, SET_SCROLLTOP, SET_LOADING, SET_LOADING_MORE, LOAD_MORE, SET_RESOURCE, DISPLAY_WARNING } from './types'
  2. import { SONG_LIST } from '../constants/views'
  3. import { BEATSAVER, LIBRARY } from '../constants/resources'
  4. import { BEATSAVER_BASE_URL, BSABER_BASE_URL } from '../constants/urls'
  5. import { hashAndWriteToMetadata } from './queueActions'
  6. import { setView } from './viewActions'
  7. import { stat } from 'original-fs'
  8. const { remote } = window.require('electron')
  9. const fs = remote.require('fs')
  10. const path = remote.require('path')
  11. var SEARCH_KEYWORD = "tv-size";
  12. var RESULT_PAGE=0;
  13. const resourceUrl = {
  14. 'BEATSAVER_NEW_SONGS': `${BEATSAVER_BASE_URL}/api/maps/latest`,
  15. 'BEATSAVER_TOP_DOWNLOADED_SONGS': `${BEATSAVER_BASE_URL}/api/maps/downloads`,
  16. 'BEATSAVER_TOP_FINISHED_SONGS': `${BEATSAVER_BASE_URL}/api/maps/plays`,
  17. 'BEATSAVER_SEARCH_SONGS':`${BEATSAVER_BASE_URL}/api/search/text`
  18. }
  19. export const fetchSearch = () => (dispatch, getState) => {
  20. setView(SONG_LIST)(dispatch, getState)
  21. dispatch({
  22. type: SET_LOADING,
  23. payload: true
  24. })
  25. dispatch({
  26. type: SET_SCROLLTOP,
  27. payload: 0
  28. })
  29. dispatch({
  30. type: SET_RESOURCE,
  31. payload: BEATSAVER.SEARCH_SONGS
  32. })
  33. RESULT_PAGE=0;
  34. SEARCH_KEYWORD = document.getElementById("SearchSongsInput").value.trim() === ""
  35. ? "tv-size" : document.getElementById("SearchSongsInput").value.trim() ;
  36. fetch(`${BEATSAVER_BASE_URL}/api/search/text/0?q=${SEARCH_KEYWORD}`)
  37. .then(res => res.json())
  38. .then(data => {
  39. console.log(data)
  40. dispatch({
  41. type: FETCH_SEARCH,
  42. payload: data
  43. })
  44. dispatch({
  45. type: SET_LOADING,
  46. payload: false
  47. })
  48. console.log(data);
  49. for(let i = 0; i < data.docs.length; i++) {
  50. fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`)
  51. .then(res => res.json())
  52. .then(bsaberData => {
  53. dispatch({
  54. type: ADD_BSABER_RATING,
  55. payload: { i, bsaberData }
  56. })
  57. })
  58. .catch((err) => {
  59. dispatch({
  60. type: ADD_BSABER_RATING,
  61. payload: { i, bsaberData: { overall_rating: 'Error' } }
  62. })
  63. })
  64. }
  65. })
  66. }
  67. export const fetchNew = () => (dispatch, getState) => {
  68. setView(SONG_LIST)(dispatch, getState)
  69. dispatch({
  70. type: SET_LOADING,
  71. payload: true
  72. })
  73. dispatch({
  74. type: SET_SCROLLTOP,
  75. payload: 0
  76. })
  77. dispatch({
  78. type: SET_RESOURCE,
  79. payload: BEATSAVER.NEW_SONGS
  80. })
  81. RESULT_PAGE=0;
  82. fetch(`${BEATSAVER_BASE_URL}/api/maps/latest`)
  83. .then(res => res.json())
  84. .then(data => {
  85. console.log(data)
  86. dispatch({
  87. type: FETCH_NEW,
  88. payload: data
  89. })
  90. dispatch({
  91. type: SET_LOADING,
  92. payload: false
  93. })
  94. console.log(data);
  95. for(let i = 0; i < data.docs.length; i++) {
  96. fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`)
  97. .then(res => res.json())
  98. .then(bsaberData => {
  99. dispatch({
  100. type: ADD_BSABER_RATING,
  101. payload: { i, bsaberData }
  102. })
  103. })
  104. .catch((err) => {
  105. dispatch({
  106. type: ADD_BSABER_RATING,
  107. payload: { i, bsaberData: { overall_rating: 'Error' } }
  108. })
  109. })
  110. }
  111. })
  112. }
  113. export const fetchTopDownloads = () => (dispatch, getState) => {
  114. setView(SONG_LIST)(dispatch, getState)
  115. dispatch({
  116. type: SET_SCROLLTOP,
  117. payload: 0
  118. })
  119. dispatch({
  120. type: SET_LOADING,
  121. payload: true
  122. })
  123. dispatch({
  124. type: SET_RESOURCE,
  125. payload: BEATSAVER.TOP_DOWNLOADED_SONGS
  126. })
  127. RESULT_PAGE=0;
  128. fetch(`${BEATSAVER_BASE_URL}/api/maps/downloads`)
  129. .then(res => res.json())
  130. .then(data => {
  131. dispatch({
  132. type: FETCH_TOP_DOWNLOADS,
  133. payload: data
  134. })
  135. dispatch({
  136. type: SET_LOADING,
  137. payload: false
  138. })
  139. for(let i = 0; i < data.docs.length; i++) {
  140. fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`)
  141. .then(res => res.json())
  142. .then(bsaberData => {
  143. dispatch({
  144. type: ADD_BSABER_RATING,
  145. payload: { i, bsaberData }
  146. })
  147. })
  148. .catch((err) => {
  149. dispatch({
  150. type: ADD_BSABER_RATING,
  151. payload: { i, bsaberData: { overall_rating: 'Error' } }
  152. })
  153. })
  154. }
  155. })
  156. }
  157. export const fetchTopFinished = () => (dispatch, getState) => {
  158. setView(SONG_LIST)(dispatch, getState)
  159. dispatch({
  160. type: SET_SCROLLTOP,
  161. payload: 0
  162. })
  163. dispatch({
  164. type: SET_LOADING,
  165. payload: true
  166. })
  167. dispatch({
  168. type: SET_RESOURCE,
  169. payload: BEATSAVER.TOP_FINISHED_SONGS
  170. })
  171. RESULT_PAGE=0;
  172. fetch(`${BEATSAVER_BASE_URL}/api/maps/plays`)
  173. .then(res => res.json())
  174. .then(data => {
  175. dispatch({
  176. type: FETCH_TOP_FINISHED,
  177. payload: data
  178. })
  179. dispatch({
  180. type: SET_LOADING,
  181. payload: false
  182. })
  183. for(let i = 0; i < data.docs.length; i++) {
  184. fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i].key}/ratings`)
  185. .then(res => res.json())
  186. .then(bsaberData => {
  187. dispatch({
  188. type: ADD_BSABER_RATING,
  189. payload: { i, bsaberData }
  190. })
  191. })
  192. .catch((err) => {
  193. dispatch({
  194. type: ADD_BSABER_RATING,
  195. payload: { i, bsaberData: { overall_rating: 'Error' } }
  196. })
  197. })
  198. }
  199. })
  200. }
  201. export const fetchLocalSongs = () => (dispatch, getState) => {
  202. setView(SONG_LIST)(dispatch, getState)
  203. dispatch({
  204. type: SET_SCROLLTOP,
  205. payload: 0
  206. })
  207. dispatch({
  208. type: SET_LOADING,
  209. payload: true
  210. })
  211. dispatch({
  212. type: SET_RESOURCE,
  213. payload: LIBRARY.SONGS
  214. })
  215. let downloadedSongs = getState().songs.downloadedSongs
  216. let songs = []
  217. for(let i = 0; i < downloadedSongs.length; i++) {
  218. fs.readFile(downloadedSongs[i].file, 'UTF-8', (err, data) => {
  219. if(err) {
  220. dispatch({
  221. type: DISPLAY_WARNING,
  222. payload: {
  223. text: `Failed to read ${ downloadedSongs[i].file }: ${ err }`
  224. }
  225. })
  226. return
  227. }
  228. let song
  229. try {
  230. song = JSON.parse(data)
  231. } catch(err) {
  232. dispatch({
  233. type: DISPLAY_WARNING,
  234. payload: {
  235. text: `Failed to parse song: ${ err }`
  236. }
  237. })
  238. return
  239. }
  240. song.coverUrl = `file://${ path.join(path.dirname(downloadedSongs[i].file), (song.coverImagePath || song._coverImageFilename)) }`
  241. song.file = downloadedSongs[i].file
  242. hashAndWriteToMetadata(downloadedSongs[i].file)(dispatch, getState)
  243. .then(hash => {
  244. song.hash = hash
  245. songs.push(song)
  246. if(i >= downloadedSongs.length - 1) {
  247. dispatch({
  248. type: FETCH_LOCAL_SONGS,
  249. payload: songs
  250. })
  251. dispatch({
  252. type: SET_LOADING,
  253. payload: false
  254. })
  255. }
  256. })
  257. })
  258. }
  259. }
  260. export const loadMore = () => (dispatch, getState) => {
  261. if(RESULT_PAGE<0) return;
  262. dispatch({
  263. type: SET_LOADING_MORE,
  264. payload: true
  265. })
  266. let state = getState()
  267. let url = state.resource === "BEATSAVER_SEARCH_SONGS"
  268. ? resourceUrl[state.resource] + '/' + (++RESULT_PAGE) + `?q=${SEARCH_KEYWORD}`
  269. : resourceUrl[state.resource] + '/' + (++RESULT_PAGE);
  270. fetch(url)
  271. .then(res => {
  272. return res.json()
  273. })
  274. .then(data => {
  275. if(data.docs.length===0){
  276. dispatch({
  277. type: SET_LOADING_MORE,
  278. payload: false
  279. })
  280. dispatch({
  281. type: DISPLAY_WARNING,
  282. payload: {
  283. text: 'No more'
  284. }
  285. })
  286. RESULT_PAGE=-1;
  287. return;
  288. }
  289. dispatch({
  290. type: LOAD_MORE,
  291. payload: data
  292. })
  293. dispatch({
  294. type: SET_LOADING_MORE,
  295. payload: false
  296. })
  297. for(let i = state.songs.songs.length; i < state.songs.songs.length + data.docs.length; i++) {
  298. fetch(`${BSABER_BASE_URL}/wp-json/bsaber-api/songs/${data.docs[i - state.songs.songs.length].key}/ratings`)
  299. .then(res => res.json())
  300. .then(bsaberData => {
  301. dispatch({
  302. type: ADD_BSABER_RATING,
  303. payload: { i, bsaberData }
  304. })
  305. })
  306. .catch((err) => {
  307. dispatch({
  308. type: ADD_BSABER_RATING,
  309. payload: { i, bsaberData: { overall_rating: 'Error' } }
  310. })
  311. })
  312. }
  313. })
  314. .catch((err) => {
  315. dispatch({
  316. type: DISPLAY_WARNING,
  317. payload: {
  318. text: 'There was error loading more songs. Check your connection to the internet and try again.'
  319. }
  320. })
  321. })
  322. }
  323. /*
  324. export const refresh = () => (dispatch, getState) => {
  325. switch(getState().resource) {
  326. case LIBRARY.SONGS:
  327. fetchLocalSongs()
  328. return
  329. default:
  330. dispatch({
  331. type: SET_LOADING,
  332. payload: true
  333. })
  334. let state = getState()
  335. fetch(resourceUrl[state.source.source][state.source.resource] + '/0')
  336. .then(res => res.json())
  337. .then(data => {
  338. dispatch({
  339. type: REFRESH,
  340. payload: data
  341. })
  342. dispatch({
  343. type: SET_LOADING,
  344. payload: false
  345. })
  346. })
  347. }
  348. }
  349. */
  350. export const setScrollTop = scrollTop => dispatch => {
  351. dispatch({
  352. type: SET_SCROLLTOP,
  353. payload: scrollTop
  354. })
  355. }