douban.fm
Version:
a tiny and smart cli player of douban.fm in Node.js
276 lines (225 loc) • 6.91 kB
JavaScript
var fs = require('fsplus');
var path = require('path');
var async = require('async');
var inquirer = require("inquirer");
var consoler = require('consoler');
var ffmetadata = require("ffmetadata");
require('colorful').toxic();
var Fm = require('./fm');
var sdk = require('./sdk');
var utils = require('./utils');
var menu = require('./menu');
exports.id3 = id3;
exports.help = help;
exports.quit = quit;
exports.ready = ready;
exports.config = config;
exports.account = account;
exports.download = download;
exports.http_proxy = http_proxy;
/**
* [Show configs UI]
* @param {Object} fm [a douban.fm instance]
* @param {Array} argv [command line arguments]
*/
function config(fm, argv) {
inquirer.prompt(menu.main, function(result) {
if (!exports[result.type])
return exports.help();
exports[result.type](fm, argv);
});
}
/**
* [Auth and save user's account infomation and token]
* @param {Object} fm [a douban.fm instance]
*/
function account(fm) {
inquirer.prompt(menu.account, function(result) {
sdk.fm.auth({
form: result
}, function(err, account) {
if (err)
return consoler.error(err);
var configs = {};
configs.account = account;
try {
fs.updateJSON(fm.rc.profile, configs);
} catch (err) {
if (!utils.noSuchFile(err.message))
return consoler.error(err);
fs.writeJSON(fm.rc.profile, configs);
}
return ready(account);
});
});
function ready(account) {
consoler.success(
'欢迎,' +
account.user_name +
'。您的豆瓣账户已经成功修改为:' +
account.email
);
fm.init(exports.ready);
}
}
/**
* [Update download directory path]
* @param {Object} fm [a douban.fm instance]
* @param {Array} argv [command line arguments]
*/
function download(fm, argv) {
var workingPath = process.cwd();
var profile = {};
inquirer.prompt(menu.download.main(workingPath), function(result) {
if (!result.useWorkingPath)
return inputNewPath();
profile.home = workingPath;
return updatePath(profile);
});
function inputNewPath() {
inquirer.prompt(menu.download.setting, function(dir) {
if (!fs.existsSync(dir.download)) {
console.log(dir.download + ' 这个目录好像并不存在,请输入一个有效的路径');
return inputNewPath();
}
profile.home = dir.download;
return updatePath(profile);
});
}
function updatePath(profile) {
try {
fs.updateJSON(fm.rc.profile, profile);
} catch (err) {
if (!utils.noSuchFile(err.message))
return consoler.error(err);
fs.writeJSON(fm.rc.profile, profile);
}
consoler.success('下载目录已成功修改为 ' + profile.home);
var f = new Fm;
return f.init(exports.ready);
}
}
/**
* [Update ID3 tags for local songs]
* @param {Object} fm [a douban.fm instance]
* @param {Array} argv [command line arguments]
*/
function id3(fm, argv) {
consoler.loading('正在从 ' + fm.home + ' 读取音乐列表');
sdk.local(fm.home, fm.rc.history, function(err, list) {
if (err)
return consoler.error(err);
var songs = list.filter(function(song) {
var keys = Object.keys(song);
if (keys.length === 1 && keys[0] === 'url') return false;
return true;
});
if (songs.length === 0)
return consoler.error('没有歌曲符合条件');
consoler.success('找到 ' + songs.length + ' 首有效歌曲,正在添加 id3 信息');
async.eachLimit(songs, 20, addid3, function(err) {
if (err)
return consoler.error(err);
return consoler.success('添加歌曲 id3 信息完成');
});
});
/**
* [Add ID3 to single song]
* @param {Object} song
* @param {Function} callback
*/
function addid3(song, callback) {
if (!song.url)
return callback(null);
var id3 = {};
id3.artist = song.artist;
id3.title = song.title;
id3.album = song.albumtitle;
id3.date = song.public_time;
id3.year = song.public_time;
id3.publisher = song.company;
ffmetadata.write(song.url, id3, function(err) {
if (!err)
consoler.success('√ ' + id3.title);
if (err)
consoler.error('X ' + id3.title);
callback(null);
});
}
}
/**
* [http_proxy]
* @param {[type]} fm [description]
* @param {[type]} argv [description]
* @return {[type]} [description]
*/
function http_proxy(fm, argv) {
var profile = {};
var defaultProxy = process.env.HTTP_PROXY || process.env.http_proxy || null;
inquirer.prompt(menu.http_proxy.main(defaultProxy), function(result) {
if (!result.useDefaultProxy)
return inputNewProxy();
if (defaultProxy === null || validate(defaultProxy)) {
profile.http_proxy = defaultProxy;
return updateProxy(profile);
}
console.log(defaultProxy + '格式不符合规范,请输入有效的HTTP_PROXY');
return inputNewProxy();
});
function validate(value) {
var proxyReg = /http:\/\/((?:\d{1,3}\.){3}\d{1,3}):(\d+)/;
return proxyReg.test(value);
}
function inputNewProxy() {
inquirer.prompt(menu.http_proxy.setting, function(result) {
if (!validate(result.http_proxy)) {
console.log(result.http_proxy + '格式不符合规范,请输入有效的HTTP PROXY');
return inputNewProxy();
}
profile.http_proxy = result.http_proxy;
return updateProxy(profile);
});
}
function updateProxy(profile) {
try {
fs.updateJSON(fm.rc.profile, profile);
} catch (err) {
if (!utils.noSuchFile(err.message)) return consoler.error(err);
fs.writeJSON(fm.rc.profile, profile);
}
consoler.success('HTTP PROXY已经成功修改为 ' + profile.http_proxy);
var f = new Fm;
return f.init(exports.ready);
}
}
/**
* [Show help messages]
* @return {String} [a help manual]
*/
function help() {
console.log([
'',
'安装/更新豆瓣电台命令行版:'.yellow,
'$ [sudo] npm install douban.fm -g',
'',
'豆瓣电台设置:'.green,
'$ douban.fm config',
'',
'菜单快捷键:'.yellow,
'[ Return ] 播放另一个频道,或者重新播放当前频道 (PLAY)',
'[ Backspace ] 停止播放当前歌曲或频道 (DELETE)',
'[ N ] 本频道列表的下一首歌曲 (NEXT)',
'[ L ] 添加到红心列表或者删除红心 (LOVE)',
'[ S ] 分享当前歌曲到新浪微博 (SHARE)',
'[ R ] 开启或关闭歌词,默认关闭歌词显示 (LRC)',
'[ G ] 跳转到当前播放歌曲的专辑页面 (GOTO)',
'[ Q ] 退出豆瓣电台 (QUIT)',
""
].join('\n '));
}
function quit() {
return process.exit();
}
function ready() {
return consoler.loading('正在加载...');
}