Skip to content

Commit

Permalink
feat(config): add setting and config module
Browse files Browse the repository at this point in the history
  • Loading branch information
foamzou committed Mar 2, 2024
1 parent f23a3fc commit 96466a5
Show file tree
Hide file tree
Showing 18 changed files with 327 additions and 134 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# stage: build code
FROM bsingh1904/alpine-node:latest AS NODE_IMAGE
FROM surnet/alpine-node-opencv:16.13.0-4.5.1 AS NODE_IMAGE
# FROM iamccc/alpine-node:16.20 AS NODE_IMAGE
WORKDIR /app
COPY . .

RUN export MELODY_IN_DOCKER=1 && npm run init && rm -rf frontend

# stage: copy
FROM iamccc/alpine-node:14.19
FROM iamccc/alpine-node:16.20
WORKDIR /app

COPY --from=pldin601/static-ffmpeg:22.04.061404-87ac0d7 /ffmpeg /ffprobe /usr/local/bin/
Expand Down
39 changes: 38 additions & 1 deletion backend/src/consts/source.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,40 @@
module.exports = {
Netease : 'netease',
consts: {
Netease : {
code: 'netease',
label: '网易云',
},
Bilibili : {
code: 'bilibili',
label: '哔哩哔哩',
},
Douyin : {
code: 'douyin',
label: '抖音',
},
Kugou : {
code: 'kugou',
label: '酷狗',
},
Kuwo : {
code: 'kuwo',
label: '酷我',
},
Migu : {
code: 'migu',
label: '咪咕',
},
QQ : {
code: 'qq',
label: 'QQ',
},
Youtube : {
code: 'youtube',
label: 'Youtube',
},
Qmkg : {
code: 'qmkg',
label: '全民K歌',
},
},
}
23 changes: 23 additions & 0 deletions backend/src/handler/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const ConfigService = require('../service/config_manager');

async function getGlobalConfig(req, res) {
const config = await ConfigService.getGlobalConfig();
res.send({
status: 0,
data: config
});
}

async function setGlobalConfig(req, res) {
const config = req.body;
await ConfigService.setGlobalConfig(config);
res.send({
status: 0,
data: config
});
}

module.exports = {
getGlobalConfig,
setGlobalConfig,
}
4 changes: 2 additions & 2 deletions backend/src/handler/playlists.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const logger = require('consola');
const { getUserAllPlaylist, getSongsFromPlaylist } = require('../service/music_platform/wycloud');
const Source = require('../consts/source');
const Source = require('../consts/source').consts;

async function listAllPlaylists(req, res) {
const uid = req.account.uid;
Expand All @@ -22,7 +22,7 @@ async function listSongsFromPlaylist(req, res) {
const source = req.params.source;
const playlistId = req.params.id;

if (source !== Source.Netease || !playlistId) {
if (source !== Source.Netease.code || !playlistId) {
res.send({
status: 1,
message: "source or id is invalid",
Expand Down
6 changes: 3 additions & 3 deletions backend/src/handler/sync_jobs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const logger = require('consola');
const { unblockMusicInPlaylist, unblockMusicWithSongId } = require('../service/sync_music');
const JobType = require('../consts/job_type');
const Source = require('../consts/source');
const Source = require('../consts/source').consts;
const { matchUrlFromStr } = require('../utils/regex');
const { syncSingleSongWithUrl } = require('../service/sync_music');
const findTheBestMatchFromWyCloud = require('../service/search_songs/find_the_best_match_from_wycloud');
Expand All @@ -21,7 +21,7 @@ async function createJob(req, res) {
const source = request.playlist && request.playlist.source;
const playlistId = request.playlist && request.playlist.id;

if (source !== Source.Netease || !playlistId) {
if (source !== Source.Netease.code || !playlistId) {
res.status(429).send({
status: 1,
message: "source or id is invalid",
Expand All @@ -33,7 +33,7 @@ async function createJob(req, res) {
const source = request.source;
const songId = request.songId;

if (source !== Source.Netease || !songId) {
if (source !== Source.Netease.code || !songId) {
res.status(429).send({
status: 1,
message: "source or id is invalid",
Expand Down
4 changes: 4 additions & 0 deletions backend/src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const SongMeta = require('./handler/song_meta');
const Playlists = require('./handler/playlists');
const Account = require('./handler/account');
const MediaFetcherLib = require('./handler/media_fetcher_lib');
const Config = require('./handler/config');

const asyncWrapper = (cb) => {
return (req, res, next) => cb(req, res, next).catch(next);
Expand All @@ -31,4 +32,7 @@ router.get('/api/account/qrlogin-check', asyncWrapper(Account.qrLoginCheck));
router.get('/api/media-fetcher-lib/version-check', asyncWrapper(MediaFetcherLib.checkLibVersion));
router.post('/api/media-fetcher-lib/update', asyncWrapper(MediaFetcherLib.downloadTheLatestLib));

router.get('/api/config/global', asyncWrapper(Config.getGlobalConfig));
router.post('/api/config/global', asyncWrapper(Config.setGlobalConfig));

module.exports = router;
42 changes: 42 additions & 0 deletions backend/src/service/config_manager/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const asyncFs = require('../../utils/fs');

const DataPath = `${__dirname}/../../../.profile/data`;
const ConfigPath = `${DataPath}/config`;
const GlobalConfig = `${ConfigPath}/global.json`;
const sourceConsts = require('../../consts/source').consts;

async function init() {
if (!await asyncFs.asyncFileExisted(ConfigPath)) {
await asyncFs.asyncMkdir(ConfigPath);
}
}
init();

const GlobalDefaultConfig = {
localDownloadPath: '',
// don't search youtube by default
sources: Object.values(sourceConsts).map(i => i.code).filter(s => s !== sourceConsts.Youtube.code),
sourceConsts,
};

async function setGlobalConfig(config) {
await asyncFs.asyncWriteFile(GlobalConfig, JSON.stringify(config));
}

async function getGlobalConfig() {
if (!await asyncFs.asyncFileExisted(GlobalConfig)) {
return GlobalDefaultConfig;
}
const config = JSON.parse(await asyncFs.asyncReadFile(GlobalConfig));
if (!config.sources) {
config.sources = GlobalDefaultConfig.sources;
}
config.sourceConsts = GlobalDefaultConfig.sourceConsts;
return config;
}


module.exports = {
setGlobalConfig,
getGlobalConfig,
}
2 changes: 1 addition & 1 deletion backend/src/service/job_manager/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const logger = require('consola');
const asyncFs = require('./fs');
const asyncFs = require('../../utils/fs');
const genUUID = require('../../utils/uuid');
const { lock, unlock } = require('../../utils/simple_locker');
const JobStatus = require('../../consts/job_status');
Expand Down
11 changes: 10 additions & 1 deletion backend/src/service/media_fetcher/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const md5 = require('md5');
const path = require('path');
const cmd = require('../../utils/cmd');
const fs = require('fs');
const configManager = require('../config_manager')

const { getBinPath } = require('./media_get');

Expand Down Expand Up @@ -92,10 +93,18 @@ async function searchSongFromAllPlatform({
}) {
logger.info(`searchSong with ${JSON.stringify(arguments)}`);

const globalConfig = await configManager.getGlobalConfig();

let searchParams = keyword
? ['-k', `"${keyword}"`]
: ['--searchSongName', `"${songName}"`, '--searchArtist', `"${artist}"`, '--searchAlbum', `"${album}"`];
searchParams = searchParams.concat(['--searchType="song"', '-m', '--infoFormat=json', '-l', 'silence']);
searchParams = searchParams.concat([
'--searchType="song"',
'-m',
`--sources=${globalConfig.sources.join(',')}`,
'--infoFormat=json',
'-l', 'silence'
]);

logger.info(`cmdStr: ${getBinPath()} ${searchParams.join(' ')}`);

Expand Down
61 changes: 31 additions & 30 deletions backend/src/service/media_fetcher/media_get.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const logger = require('consola');
const cmd = require('../../utils/cmd');
const https = require('https');
const cmd = require('../../utils/cmd');
var isWin = require('os').platform().indexOf('win32') > -1;
const isLinux = require('os').platform().indexOf('linux') > -1;
const isDarwin = require('os').platform().indexOf('darwin') > -1;
const httpsGet = require('../../utils/network').asyncHttpsGet;
const RemoteConfig = require('../remote_config');
const fs = require('fs');

function getBinPath(isTemp = false) {
Expand All @@ -23,26 +25,16 @@ async function getMediaGetInfo(isTempBin = false) {
return {
hasInstallFFmpeg,
versionInfo: versionInfo ? versionInfo[1].trim() : '',
fullMessage: message,
}
}

function asyncHttpsGet(url) {
return new Promise((resolve) => {
https.get(url, res => {
res.on('data', data => {
resolve(data.toString());
})
res.on('error', err => {
l(err);
resolve(null);
})
});
});
}

async function getLatestMediaGetVersion() {
const latestVerisonUrl = 'https://ghproxy.com/https://raw.githubusercontent.com/foamzou/media-get/main/LATEST_VERSION';
const latestVersion = await asyncHttpsGet(latestVerisonUrl);
const remoteConfig = await RemoteConfig.getRemoteConfig();
const latestVerisonUrl = `${remoteConfig.githubProxy}/https://raw.githubusercontent.com/foamzou/media-get/main/LATEST_VERSION`;
console.log('start to get latest version from: ' + latestVerisonUrl);
const latestVersion = await httpsGet(latestVerisonUrl);
console.log('latest version: ' + latestVersion);
if (latestVersion === null || (latestVersion || "").split('.').length !== 3) {
logger.error('获取 media-get 最新版本号失败, got: ' + latestVersion);
return false;
Expand All @@ -51,19 +43,23 @@ async function getLatestMediaGetVersion() {
}

async function downloadFile(url, filename) {
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
const fileStream = fs.createWriteStream(filename);
https.get(url, res => {
res.pipe(fs.createWriteStream(filename));
res.on('end', () => {
resolve();
}
);
}
);
res.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close(() => resolve(true)); // Successfully downloaded and saved, resolve with true
});
})
.on('error', (error) => {
console.error('Download error:', error);
fileStream.destroy();
fs.unlink(filename, () => resolve(false)); // On error, delete the file and resolve with false
});
});
}

function getMediaGetRemoteFilename(latestVersion) {
async function getMediaGetRemoteFilename(latestVersion) {
let suffix = 'win.exe';
if (isLinux) {
suffix = 'linux';
Expand All @@ -74,7 +70,8 @@ function getMediaGetRemoteFilename(latestVersion) {
if (process.arch === 'arm64') {
suffix += '-arm64';
}
return `https://ghproxy.com/https://github.com/foamzou/media-get/releases/download/v${latestVersion}/media-get-${latestVersion}-${suffix}`;
const remoteConfig = await RemoteConfig.getRemoteConfig();
return `${remoteConfig.githubProxy}/https://github.com/foamzou/media-get/releases/download/v${latestVersion}/media-get-${latestVersion}-${suffix}`;
}

const renameFile = (oldName, newName) => {
Expand All @@ -91,17 +88,21 @@ const renameFile = (oldName, newName) => {
};

async function downloadTheLatestMediaGet(version) {
const remoteFile = getMediaGetRemoteFilename(version);
const remoteFile = await getMediaGetRemoteFilename(version);
logger.info('start to download media-get: ' + remoteFile);
await downloadFile(remoteFile, getBinPath(true));
const ret = await downloadFile(remoteFile, getBinPath(true));
if (ret === false) {
logger.error('download failed');
return false;
}
fs.chmodSync(getBinPath(true), '755');
logger.info('download finished');

const temBinInfo = await getMediaGetInfo(true)
if (!temBinInfo
|| temBinInfo.versionInfo === ""
) {
logger.error('testing new bin failed. Don`t update')
logger.error('testing new bin failed. Don`t update', temBinInfo)
return false;
}

Expand Down
23 changes: 23 additions & 0 deletions backend/src/service/remote_config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const httpsGet = require('../../utils/network').asyncHttpsGet;
const logger = require('consola');


async function getRemoteConfig() {
const fallbackConfig = {
githubProxy: 'https://mirror.ghproxy.com/',
}
const remoteConfigUrl = 'https://foamzou.com/tools/melody-config.php';
const remoteConfig = await httpsGet(remoteConfigUrl);
if (remoteConfig === null) {
logger.error('get remote config failed, use fallback config');
return fallbackConfig;
}
const config = JSON.parse(remoteConfig);
return {
githubProxy: config.githubProxy,
}
}

module.exports = {
getRemoteConfig: getRemoteConfig,
}
File renamed without changes.
19 changes: 19 additions & 0 deletions backend/src/utils/network.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const https = require('https');

function asyncHttpsGet(url) {
return new Promise((resolve) => {
https.get(url, res => {
res.on('data', data => {
resolve(data.toString());
})
res.on('error', err => {
l(err);
resolve(null);
})
});
});
}

module.exports = {
asyncHttpsGet
}
2 changes: 1 addition & 1 deletion frontend/.env.development
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
NODE_ENV = 'development'
VITE_APP_MODE = 'development'
VITE_APP_API_URL = 'http://172.16.9.215:5566/api'
VITE_APP_API_URL = 'http://172.16.252.1:5566/api'
VITE_APP_API_URL = 'http://10.0.0.2:5566/api'
VITE_APP_API_URL = 'http://127.0.0.1:5566/api'
Loading

0 comments on commit 96466a5

Please sign in to comment.