diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..04ab4bf --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,34 @@ +version: "2" # required to adjust maintainability checks +checks: + argument-count: + config: + threshold: 4 + complex-logic: + config: + threshold: 4 + file-lines: + config: + threshold: 1000 + method-complexity: + config: + threshold: 6 + method-count: + config: + threshold: 20 + method-lines: + config: + threshold: 500 + nested-control-flow: + config: + threshold: 4 + return-statements: + config: + threshold: 4 + +engines: + duplication: + enabled: false + config: + languages: + javascript: + mass_threshold: 65 diff --git a/README.md b/README.md index d4faa4e..af8299d 100644 --- a/README.md +++ b/README.md @@ -48,27 +48,27 @@ Download the last version on the [website](https://github.com/trazyn/ieaseMusic/releases/latest) or below. #### Mac(10.9+) -[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.0/ieaseMusic-1.3.0-mac.dmg) the `.dmg` file, Or use `homebrew`: +[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.1/ieaseMusic-1.3.1-mac.dmg) the `.dmg` file, Or use `homebrew`: ``` brew cask install ieasemusic ``` #### Linux -[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.0/ieaseMusic-1.3.0-linux-amd64.deb) the `.deb` file for 'Debian / Ubuntu': +[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.1/ieaseMusic-1.3.1-linux-amd64.deb) the `.deb` file for 'Debian / Ubuntu': ``` -$ sudo dpkg -i ieaseMusic-1.3.0-linux-amd64.deb +$ sudo dpkg -i ieaseMusic-1.3.1-linux-amd64.deb ``` -[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.0/ieaseMusic-1.3.0-linux-x86_64.rpm) the `.rpm` file for 'Centos/RHEL': +[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.1/ieaseMusic-1.3.1-linux-x86_64.rpm) the `.rpm` file for 'Centos/RHEL': ``` -$ sudo yum localinstall ieaseMusic-1.3.0-linux-x86_64.rpm +$ sudo yum localinstall ieaseMusic-1.3.1-linux-x86_64.rpm ``` -[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.0/iease-music-1.3.0-x86_64.AppImage) the `.Appimage` file for other distribution: +[Download](https://github.com/trazyn/ieaseMusic/releases/download/v1.3.1/iease-music-1.3.1-x86_64.AppImage) the `.Appimage` file for other distribution: ``` -$ chmod u+x iease-music-1.3.0-x86_64.AppImage -$ ./iease-music-1.3.0-x86_64.AppImage +$ chmod u+x iease-music-1.3.1-x86_64.AppImage +$ ./iease-music-1.3.1-x86_64.AppImage ``` Archlinux `pacman` install: diff --git a/main.js b/main.js index e998d37..eca9c06 100644 --- a/main.js +++ b/main.js @@ -23,6 +23,10 @@ let tray; let mainWindow; let isOsx = _PLATFORM === 'darwin'; let isLinux = _PLATFORM === 'linux'; + +let showMenuBarOnLinux = false; +let revertTrayIcon = false; + // Shared data to other applocation via a unix socket file let shared = { modes: [], @@ -400,7 +404,7 @@ let dockMenu = [ ]; function updateMenu(playing) { - if (!isOsx) { + if (!isOsx && !showMenuBarOnLinux) { return; } @@ -420,6 +424,13 @@ function updateTray(playing) { : `${__dirname}/src/assets/notplaying.png` ; + if (revertTrayIcon) { + icon = playing + ? `${__dirname}/src/assets/playing-dark-panel.png` + : `${__dirname}/src/assets/notplaying-dark-panel.png` + ; + } + if (!tray) { // Init tray icon tray = new Tray(icon); @@ -479,7 +490,9 @@ const createMainWindow = () => { path.join(__dirname, 'src/assets/dock.png') ); // Disable default menu bar - mainWindow.setMenu(null); + if (!showMenuBarOnLinux) { + mainWindow.setMenu(null); + } } mainWindowState.manage(mainWindow); @@ -586,6 +599,9 @@ const createMainWindow = () => { () => debug('Apply proxy: %s', args.proxy) ); + revertTrayIcon = args.revertTrayIcon; + debug(revertTrayIcon); + if (!args.showTray) { if (tray) { tray.destroy(); @@ -638,6 +654,8 @@ const createMainWindow = () => { updater.installAutoUpdater(() => goodbye()); downloader.createDownloader(); mainWindow.webContents.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8'); + + global.mainWindow = mainWindow; debug('Create main process success 🍻'); }; @@ -666,6 +684,14 @@ app.on('before-quit', e => { process.exit(0); }); app.on('ready', () => { + storage.get('preferences', (err, data) => { + debug(data); + if (!err && data) { + showMenuBarOnLinux = data.showMenuBarOnLinux; + revertTrayIcon = data.revertTrayIcon; + } + }); + createMainWindow(); storage.get('preferences', (err, data) => { diff --git a/package.json b/package.json index bc6fd47..8d4d327 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iease-music", - "version": "1.3.0", + "version": "1.3.1", "description": "θΏ™εΊ”θ―₯ζ˜―ζœ€ε₯½ηš„η½‘ζ˜“δΊ‘ιŸ³δΉζ’­ζ”Ύε™¨δΊ†οΌŒζ²‘ζœ‰δΉ‹δΈ€οΌŒε¦‚ζžœζœ‰θ―·ζ‰“ι†’ 🀘", "main": "main.js", "scripts": { @@ -99,7 +99,7 @@ "copy-webpack-plugin": "^4.0.1", "cross-env": "^5.2.0", "css-loader": "^1.0.0", - "electron": "^2.0.6", + "electron": "^2.0.9", "electron-builder": "^20.19.2", "eslint": "^5.2.0", "eslint-config-standard": "^11.0.0", @@ -114,7 +114,7 @@ "express": "^4.15.4", "html-loader": "^0.5.1", "html-webpack-plugin": "^3.2.0", - "style-loader": "^0.21.0", + "style-loader": "^0.23.0", "svg-inline-loader": "^0.8.0", "uglifyjs-webpack-plugin": "^1.1.8", "url-loader": "^1.0.1", @@ -129,11 +129,12 @@ "big-integer": "^1.6.25", "classname": "0.0.0", "cookie-parser": "^1.4.3", - "debug": "^3.1.0", + "crypto": "^1.0.1", + "debug": "^4.0.1", "delegate": "^3.1.3", "electron-json-storage": "^4.1.1", "electron-updater": "^3.0.3", - "electron-window-state": "^4.1.1", + "electron-window-state": "^5.0.1", "han": "0.0.7", "ionicons201": "^1.0.0", "libphonenumber-js": "^0.4.44", diff --git a/server/provider/Kuwo.js b/server/provider/Kuwo.js index c83f848..58e9f4f 100644 --- a/server/provider/Kuwo.js +++ b/server/provider/Kuwo.js @@ -52,7 +52,7 @@ export default async(request, keyword, artists) => { }, }); - if (!response) { + if (!response || response === 'IPDeny') { error(chalk.black.bgRed('🚧 Nothing.')); return Promise.reject(Error(404)); } diff --git a/server/provider/MiGu.js b/server/provider/MiGu.js index 2ade43e..88b26a7 100644 --- a/server/provider/MiGu.js +++ b/server/provider/MiGu.js @@ -19,7 +19,12 @@ export default async(request, keyword, artists) => { } }); - if (response.success !== true || response.musics.length === 0) { + if ( + false + || response.success !== true + || !response.musics + || response.musics.length === 0 + ) { error(chalk.black.bgRed('🚧 Nothing.')); return Promise.reject(Error(404)); } diff --git a/server/provider/index.js b/server/provider/index.js index 7087a31..64a8071 100644 --- a/server/provider/index.js +++ b/server/provider/index.js @@ -1,5 +1,5 @@ -import storage from 'electron-json-storage'; +import fs from 'fs'; import Netease from './Netease'; import QQ from './QQ'; import MiGu from './MiGu'; @@ -7,13 +7,10 @@ import Kugou from './Kugou'; import Baidu from './Baidu'; import Xiami from './Xiami'; import Kuwo from './Kuwo'; +import storage from '../../common/storage'; async function getPreferences() { - return new Promise(resolve => { - storage.get('preferences', (err, data) => { - resolve(err ? {} : data); - }); - }); + return await storage.get('preferences') || {}; } async function exe(plugins, ...args) { @@ -53,6 +50,23 @@ async function getFlac(keyword, artists) { return exe([QQ], keyword, artists, true); } +async function loadFromLocal(id) { + var downloaded = (await storage.get('downloaded')) || {}; + var task = downloaded[id]; + + if (task) { + if (fs.existsSync(task.path) === false) { + delete downloaded[id]; + await storage.set('downloaded', downloaded); + return; + } + + return { + src: encodeURI(`file://${task.path}`) + }; + } +} + async function getTrack(keyword, artists, id /** This id is only work for netease music */) { var preferences = await getPreferences(); var enginers = preferences.enginers; @@ -97,6 +111,7 @@ async function getTrack(keyword, artists, id /** This id is only work for neteas } export { + loadFromLocal, getFlac, getTrack, }; diff --git a/server/router/artist.js b/server/router/artist.js index a306588..752b3b0 100644 --- a/server/router/artist.js +++ b/server/router/artist.js @@ -1,12 +1,33 @@ import express from 'express'; import axios from 'axios'; +import crypto from 'crypto'; import _debug from 'debug'; const debug = _debug('dev:api'); const error = _debug('dev:error'); const router = express(); +// https://github.com/skyline75489/nmdown/blob/ee0f66448b6e64f8b9bdb2f7451a8d4ff63e14c4/cloudmusic/hasher.py +function id2url(id) { + var key = '3go8&$8*3*3h0k(2)2'; + var keyCodes = Array.from(key).map((e, i) => key.charCodeAt(i)); + var fidCodes = Array.from(id).map((e, i) => id.charCodeAt(i)); + + var hashCodes = []; + + for (let i = 0; i < fidCodes.length; i++) { + let code = (fidCodes[i] ^ keyCodes[i % key.length]) & 0XFF; + hashCodes.push(code); + } + + var string = hashCodes.map((e, i) => String.fromCharCode(hashCodes[i])).join(''); + var md5 = crypto.createHash('md5').update(string).digest(); + var result = Buffer.from(md5).toString('base64').replace(/\//g, '_').replace(/\+/g, '-'); + + return `https://p4.music.126.net/${result}/${id}.jpg?param=y177y177`; +} + async function getArtist(id) { var profile = {}; var songs = []; @@ -43,7 +64,7 @@ async function getArtist(id) { album: { id: al.id.toString(), name: al.name, - cover: `${al.picUrl}?param=y100y100`, + cover: id2url(al.pic_str), link: `/player/1/${al.id}` }, artists: ar.map(e => ({ @@ -84,7 +105,8 @@ async function getAlbums(id) { id: e.id.toString(), name: e.name, cover: e.picUrl, - link: `/player/1/${e.id}` + link: `/player/1/${e.id}`, + publishTime: e.publishTime, })); } } catch (ex) { diff --git a/server/router/player.js b/server/router/player.js index 7cdacdf..6403900 100644 --- a/server/router/player.js +++ b/server/router/player.js @@ -189,7 +189,7 @@ router.get('/song/:id/:name/:artists/:flac?', cache('3 minutes', onlyStatus200), try { // Get the highquality track - song = await selector.getFlac(name, artists, true); + song = await selector.loadFromLocal(id) || await selector.getFlac(name, artists, true); } catch (ex) { error(ex); } @@ -204,6 +204,7 @@ router.get('/song/:id/:name/:artists/:flac?', cache('3 minutes', onlyStatus200), } } } catch (ex) { + error(ex); debug(chalk.red.underline.bold(`πŸ’” Not found: "${name} - ${artists}"`)); } diff --git a/src/app.js b/src/app.js index f0425b1..499ee50 100644 --- a/src/app.js +++ b/src/app.js @@ -118,6 +118,15 @@ class App extends Component { playing.toggle(true); }); + // Get the playlist + ipcRenderer.on('request-playlist', () => { + let downloader = remote.getGlobal('downloader'); + + if (downloader) { + downloader.webContents.send('response-playlist', JSON.stringify(controller.playlist)); + } + }); + // Right click menu window.addEventListener('contextmenu', e => { let logined = me.hasLogin(); @@ -173,7 +182,7 @@ class App extends Component { { label: 'Download 🍭', click: () => { - ipcRenderer.send('download', { song: JSON.stringify(controller.song) }); + ipcRenderer.send('download', { songs: JSON.stringify(controller.song) }); } }, { diff --git a/src/assets/notplaying-dark-panel.png b/src/assets/notplaying-dark-panel.png new file mode 100644 index 0000000..1ecd9f1 Binary files /dev/null and b/src/assets/notplaying-dark-panel.png differ diff --git a/src/assets/playing-dark-panel.png b/src/assets/playing-dark-panel.png new file mode 100644 index 0000000..d1dbad9 Binary files /dev/null and b/src/assets/playing-dark-panel.png differ diff --git a/src/js/components/Controller/classes.js b/src/js/components/Controller/classes.js index a0f7c39..16e6f77 100644 --- a/src/js/components/Controller/classes.js +++ b/src/js/components/Controller/classes.js @@ -49,6 +49,8 @@ export default theme => { '& $playing:after': { bottom: 16, + opacity: 1, + visibility: 'visible', } }, @@ -75,6 +77,8 @@ export default theme => { right: 0, bottom: 2, display: 'inline-block', + opacity: 0, + visibility: 'hidden', padding: '10px 6px', fontFamily: 'Roboto', fontSize: 12, diff --git a/src/js/components/Preferences/index.js b/src/js/components/Preferences/index.js index a7465e6..66fe4a6 100644 --- a/src/js/components/Preferences/index.js +++ b/src/js/components/Preferences/index.js @@ -56,6 +56,10 @@ class Preferences extends Component { var { showTray, setShowTray, + showMenuBarOnLinux, + setShowMenuBarOnLinux, + revertTrayIcon, + setRevertTrayIcon, alwaysOnTop, setAlwaysOnTop, autoPlay, @@ -111,6 +115,29 @@ class Preferences extends Component { onChange={e => setShowTray(e.target.checked)} /> + + + +