From 84d05f67c06eb59515258856767f8ddd1458653f Mon Sep 17 00:00:00 2001 From: Weiliang Li Date: Tue, 5 Jun 2018 15:27:27 +0900 Subject: [PATCH 1/3] Minor bug fix --- NEMbox/menu.py | 2 +- NEMbox/player.py | 28 ++++++++++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/NEMbox/menu.py b/NEMbox/menu.py index 11cd9692..9537dacc 100644 --- a/NEMbox/menu.py +++ b/NEMbox/menu.py @@ -158,7 +158,7 @@ def login(self): x = self.ui.build_login_error() if x != ord('1'): return False - return self.build_login() + return self.login() def search(self, category): self.ui.screen.timeout(-1) diff --git a/NEMbox/player.py b/NEMbox/player.py index 423ea164..1a695267 100644 --- a/NEMbox/player.py +++ b/NEMbox/player.py @@ -133,6 +133,20 @@ def is_empty(self): def is_index_valid(self): return 0 <= self.index < len(self.list) + def notify_playing(self): + if not self.current_song: + return + + if not self.config_notifier: + return + + song = self.current_song + notify('正在播放: {}\n{}-{}'.format(song['song_name'], song['artist'], song['album_name'])) + + def notify_copyright_issue(self): + log.warning('Song {} is unavailable due to copyright issue.'.format(self.playing_id)) + notify('版权限制,无法播放此歌曲') + def change_mode(self, step=1): self.info['playing_mode'] = (self.info['playing_mode'] + step) % 5 @@ -223,8 +237,7 @@ def run_mpg123(self, on_exit, url): elif strout[:2] == '@E': # error, stop song and move to next self.playing_flag = True - notify('版权限制,无法播放此歌曲') - log.warning('Song {} is unavailable due to copyright issue.'.format(self.playing_id)) + self.notify_copyright_issue() break elif strout == '@P 0': # end, moving to next @@ -300,14 +313,13 @@ def replay(self): self.end_callback() return + if not self.current_song: + return + self.playing_flag = True - item = self.current_song self.build_playinfo() - - if self.config_notifier: - notify('正在播放: {}\n{}-{}'.format(item['song_name'], item['artist'], item['album_name'])) - - self.start_playing(lambda: 0, item) + self.notify_playing() + self.start_playing(lambda: 0, self.current_song) def shuffle_order(self): self.order.clear() From bcd95d1e07fe0c5e2eac67b29e5b99dbc60f29c5 Mon Sep 17 00:00:00 2001 From: Weiliang Li Date: Thu, 7 Jun 2018 12:30:10 +0900 Subject: [PATCH 2/3] [Fix] config file --- NEMbox/__init__.py | 55 +++--------------- NEMbox/__main__.py | 47 ++++++++++++++++ NEMbox/api.py | 19 ++++--- NEMbox/cache.py | 9 +-- NEMbox/config.py | 118 +++------------------------------------ NEMbox/logger.py | 4 +- NEMbox/menu.py | 10 +--- NEMbox/player.py | 4 +- NEMbox/storage.py | 3 +- NEMbox/tests/test_api.py | 3 +- NEMbox/utils.py | 37 ++++++++++-- setup.py | 2 +- 12 files changed, 120 insertions(+), 191 deletions(-) create mode 100644 NEMbox/__main__.py diff --git a/NEMbox/__init__.py b/NEMbox/__init__.py index 1c7b7663..5f3aab0d 100644 --- a/NEMbox/__init__.py +++ b/NEMbox/__init__.py @@ -1,47 +1,8 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -''' -网易云音乐 Entry -''' -from __future__ import ( - print_function, unicode_literals, division, absolute_import -) -import curses -import traceback -import argparse -import sys - -from future.builtins import str - -from .menu import Menu -from .__version__ import __version__ as version - - -def start(): - parser = argparse.ArgumentParser() - parser.add_argument("-v", - "--version", - help="show this version and exit", - action="store_true") - args = parser.parse_args() - if args.version: - latest = Menu().check_version() - curses.endwin() - print('NetEase-MusicBox installed version:' + version) - if latest != version: - print('NetEase-MusicBox latest version:' + str(latest)) - sys.exit() - - nembox_menu = Menu() - try: - nembox_menu.start_fork(version) - except (OSError, TypeError, ValueError, KeyError, IndexError): - # clean up terminal while failed - curses.echo() - curses.nocbreak() - curses.endwin() - traceback.print_exc() - - -if __name__ == '__main__': - start() +from .utils import create_dir, create_file +from .const import Constant + +create_dir(Constant.conf_dir) +create_dir(Constant.download_dir) +create_file(Constant.storage_path) +create_file(Constant.log_path, default='') +create_file(Constant.cookie_path, default='#LWP-Cookies-2.0\n') diff --git a/NEMbox/__main__.py b/NEMbox/__main__.py new file mode 100644 index 00000000..1c7b7663 --- /dev/null +++ b/NEMbox/__main__.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +''' +网易云音乐 Entry +''' +from __future__ import ( + print_function, unicode_literals, division, absolute_import +) +import curses +import traceback +import argparse +import sys + +from future.builtins import str + +from .menu import Menu +from .__version__ import __version__ as version + + +def start(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", + "--version", + help="show this version and exit", + action="store_true") + args = parser.parse_args() + if args.version: + latest = Menu().check_version() + curses.endwin() + print('NetEase-MusicBox installed version:' + version) + if latest != version: + print('NetEase-MusicBox latest version:' + str(latest)) + sys.exit() + + nembox_menu = Menu() + try: + nembox_menu.start_fork(version) + except (OSError, TypeError, ValueError, KeyError, IndexError): + # clean up terminal while failed + curses.echo() + curses.nocbreak() + curses.endwin() + traceback.print_exc() + + +if __name__ == '__main__': + start() diff --git a/NEMbox/api.py b/NEMbox/api.py index bdbe325b..5ca3f4dd 100644 --- a/NEMbox/api.py +++ b/NEMbox/api.py @@ -84,12 +84,13 @@ def song_url(cls, song): if url is None: return Parse._song_url_by_id(song['id']) br = song['br'] - quality_map = { - 320000: 'HD 320k', - 192000: 'MD 192k', - 128000: 'LD 128k', - } - return url, quality_map[br] + if br >= 320000: + quality = 'HD' + elif br >= 192000: + quality = 'MD' + else: + quality = 'LD' + return url, '{} {}k'.format(quality, br // 1000) else: # songs_detail resp return Parse._song_url_by_id(song['id']) @@ -278,7 +279,7 @@ def login(self, username, password): # 每日签到 def daily_task(self, is_mobile=True): - path = '/point/dailyTask' + path = '/weapi/point/dailyTask' params = dict(type=0 if is_mobile else 1) return self.request('POST', path, params) @@ -508,6 +509,10 @@ def dig_info(self, data, dig_type): if not data: return [] if dig_type == 'songs' or dig_type == 'fmsongs': + urls = self.songs_url([s['id'] for s in data]) + for s, u in zip(data, urls): + s['url'] = u['url'] + s['br'] = u['br'] return Parse.songs(data) elif dig_type == 'artists': return Parse.artists(data) diff --git a/NEMbox/cache.py b/NEMbox/cache.py index 98110025..c20060a6 100644 --- a/NEMbox/cache.py +++ b/NEMbox/cache.py @@ -24,10 +24,12 @@ class Cache(Singleton): + def __init__(self): if hasattr(self, '_init'): return self._init = True + self.const = Constant() self.config = Config() self.download_lock = threading.Lock() @@ -52,12 +54,6 @@ def _kill(p): _kill(self.aria2c) _kill(self.wget) - def _mkdir(self, name): - try: - os.mkdir(name) - except OSError: - pass - def start_download(self): check = self.download_lock.acquire(False) if not check: @@ -97,7 +93,6 @@ def start_download(self): except OSError as e: log.warning('{}.\tAria2c is unavailable, fall back to wget'.format(e)) - self._mkdir(output_path) para = ['wget', '-O', full_path, new_url] self.wget = subprocess.Popen(para, stdin=subprocess.PIPE, diff --git a/NEMbox/config.py b/NEMbox/config.py index 7dc6a94e..34205acc 100644 --- a/NEMbox/config.py +++ b/NEMbox/config.py @@ -6,13 +6,10 @@ import os from future.builtins import open -from . import logger from .singleton import Singleton from .const import Constant from .utils import utf8_data_to_file -log = logger.getLogger(__name__) - class Config(Singleton): @@ -20,7 +17,8 @@ def __init__(self): if hasattr(self, '_init'): return self._init = True - self.config_file_path = Constant.config_path + + self.path = Constant.config_path self.default_config = { 'version': 8, 'cache': { @@ -117,120 +115,22 @@ def __init__(self): } } self.config = {} - if not os.path.isfile(self.config_file_path): + if not os.path.isfile(self.path): self.generate_config_file() - with open(self.config_file_path, 'r') as f: + with open(self.path, 'r') as f: try: self.config = json.load(f) except ValueError: - log.debug('Load config json data failed.') - return - - if not self.check_version(): - self.save_config_file() + self.generate_config_file() def generate_config_file(self): - f = open(self.config_file_path, 'w') - utf8_data_to_file(f, json.dumps(self.default_config, indent=2)) - f.close() + with open(self.path, 'w') as f: + utf8_data_to_file(f, json.dumps(self.default_config, indent=2)) def save_config_file(self): - f = open(self.config_file_path, 'w') - utf8_data_to_file(f, json.dumps(self.config, indent=2)) - f.close() - - def check_version(self): - if self.config['version'] == self.default_config['version']: - return True - else: - # Should do some update. Like - # if self.database['version'] == 2 : self.database.['version'] = 3 - # update database form version 1 to version 2 - if self.config['version'] == 1: - self.config['version'] = 2 - self.config['global_play_pause'] = { - 'value': 'p', - 'default': 'p', - 'describe': 'Global keybind for play/pause.' - 'Uses gtk notation for keybinds.' - } - self.config['global_next'] = { - 'value': 'j', - 'default': 'j', - 'describe': 'Global keybind for next song.' - 'Uses gtk notation for keybinds.' - } - self.config['global_previous'] = { - 'value': 'k', - 'default': 'k', - 'describe': 'Global keybind for previous song.' - 'Uses gtk notation for keybinds.' - } - elif self.config['version'] == 2: - self.config['version'] = 3 - self.config['notifier'] = { - 'value': True, - 'default': True, - 'describe': 'Notifier when switching songs.' - } - elif self.config['version'] == 3: - self.config['version'] = 4 - self.config['translation'] = { - 'value': True, - 'default': True, - 'describe': 'Foreign language lyrics translation.' - } - elif self.config['version'] == 4: - self.config['version'] = 5 - self.config['osdlyrics'] = { - 'value': False, - 'default': False, - 'describe': 'Desktop lyrics for musicbox.' - } - self.config['osdlyrics_color'] = { - 'value': [225, 248, 113], - 'default': [225, 248, 113], - 'describe': 'Desktop lyrics RGB Color.' - } - self.config['osdlyrics_font'] = { - 'value': ['Decorative', 16], - 'default': ['Decorative', 16], - 'describe': 'Desktop lyrics font-family and font-size.' - } - self.config['osdlyrics_background'] = { - 'value': 'rgba(100, 100, 100, 120)', - 'default': 'rgba(100, 100, 100, 120)', - 'describe': 'Desktop lyrics background color.' - } - self.config['osdlyrics_transparent'] = { - 'value': False, - 'default': False, - 'describe': 'Desktop lyrics transparent bg.' - } - elif self.config['version'] == 5: - self.config['version'] = 6 - self.config['osdlyrics_on_top'] = { - 'value': True, - 'default': True, - 'describe': 'Desktop lyrics OnTopHint.' - } - elif self.config['version'] == 6: - self.config['version'] = 7 - self.config['curses_transparency'] = { - 'value': False, - 'default': False, - 'describe': 'Set true to make curses transparency.' - } - elif self.config['version'] == 7: - self.config['version'] = 8 - self.config['osdlyrics_size'] = { - 'value': [600, 60], - 'default': [600, 60], - 'describe': 'Desktop lyrics area size.' - } - self.check_version() - return False + with open(self.path, 'w') as f: + utf8_data_to_file(f, json.dumps(self.config, indent=2)) def get(self, name): if name not in self.config.keys(): diff --git a/NEMbox/logger.py b/NEMbox/logger.py index 370bb804..8165f757 100644 --- a/NEMbox/logger.py +++ b/NEMbox/logger.py @@ -5,7 +5,6 @@ from __future__ import ( print_function, unicode_literals, division, absolute_import ) -import os import logging from future.builtins import open @@ -13,8 +12,7 @@ from . import const FILE_NAME = const.Constant.log_path -if os.path.isdir(const.Constant.conf_dir) is False: - os.mkdir(const.Constant.conf_dir) + with open(FILE_NAME, 'a+') as f: f.write('#' * 80) diff --git a/NEMbox/menu.py b/NEMbox/menu.py index 9537dacc..bcb716fd 100644 --- a/NEMbox/menu.py +++ b/NEMbox/menu.py @@ -25,7 +25,6 @@ from .player import Player from .ui import Ui from .osdlyrics import show_lyrics_new_process -from .const import Constant from .config import Config from .utils import notify from .storage import Storage @@ -37,10 +36,6 @@ log = logger.getLogger(__name__) -home = os.path.expanduser('~') -if os.path.isdir(Constant.conf_dir) is False: - os.mkdir(Constant.conf_dir) - def carousel(left, right, x): # carousel x in [left, right] @@ -208,12 +203,11 @@ def check_version(self): # 检查更新 && 签到 try: mobile = self.api.daily_task(is_mobile=True) - time.sleep(0.5) pc = self.api.daily_task(is_mobile=False) - if mobile['code'] not in (-1, -2, 301): + if mobile['code'] == 200: notify('移动端签到成功', 1) - if pc['code'] not in (-1, -2, 301): + if pc['code'] == 200: notify('PC端签到成功', 1) data = self.api.get_version() diff --git a/NEMbox/player.py b/NEMbox/player.py index 1a695267..883143d4 100644 --- a/NEMbox/player.py +++ b/NEMbox/player.py @@ -232,8 +232,7 @@ def run_mpg123(self, on_exit, url): # playing, update progress out = strout.split(' ') self.process_location = int(float(out[3])) - if not self.process_length: - self.process_length = int(float(out[3]) + float(out[4])) + self.process_length = int(float(out[3]) + float(out[4])) elif strout[:2] == '@E': # error, stop song and move to next self.playing_flag = True @@ -242,6 +241,7 @@ def run_mpg123(self, on_exit, url): elif strout == '@P 0': # end, moving to next self.playing_flag = True + break elif strout == '': endless_loop_cnt += 1 # 有播放后没有退出,mpg123一直在发送空消息的情况,此处直接终止处理 diff --git a/NEMbox/storage.py b/NEMbox/storage.py index 083991d5..ee6bf516 100644 --- a/NEMbox/storage.py +++ b/NEMbox/storage.py @@ -59,6 +59,7 @@ def __init__(self): if hasattr(self, '_init'): return self._init = True + self.database = { 'user': { 'username': '', @@ -107,7 +108,7 @@ def load(self): else: self.database[k] = v except (OSError, KeyError, ValueError) as e: - self.__init__() + pass self.save() def save(self): diff --git a/NEMbox/tests/test_api.py b/NEMbox/tests/test_api.py index b45af9fe..632f247f 100644 --- a/NEMbox/tests/test_api.py +++ b/NEMbox/tests/test_api.py @@ -33,4 +33,5 @@ def test_api(self): # limit=5, # offset=0 # ))) - print(api.recommend_resource()[0]) + # print(api.recommend_resource()[0]) + print(api.songs_url([561307346])) diff --git a/NEMbox/utils.py b/NEMbox/utils.py index 67532633..b9369031 100644 --- a/NEMbox/utils.py +++ b/NEMbox/utils.py @@ -8,19 +8,42 @@ import platform import subprocess +import os from collections import OrderedDict from future.builtins import str -from . import logger - -log = logger.getLogger(__name__) __all__ = [ - 'utf8_data_to_file', 'notify', 'uniq' + 'utf8_data_to_file', 'notify', 'uniq', 'create_dir', 'create_file' ] +def mkdir(path): + try: + os.mkdir(path) + return True + except OSError: + return False + + +def create_dir(path): + if not os.path.exists(path): + return mkdir(path) + + if os.path.isdir(path): + return True + + os.remove(path) + return mkdir(path) + + +def create_file(path, default='\n'): + if not os.path.exists(path): + with open(path, 'w') as f: + f.write(default) + + def uniq(arr): return list(OrderedDict.fromkeys(arr).keys()) @@ -50,17 +73,21 @@ def notify_command_linux(msg, t=None): def notify(msg, msg_type=0, t=None): + msg = msg.replace('"', '\\"') "Show system notification with duration t (ms)" if platform.system() == 'Darwin': command = notify_command_osx(msg, msg_type, t) else: command = notify_command_linux(msg, t) + try: subprocess.call(command) + return True except OSError as e: - log.warning('Sending notification error.') + return False if __name__ == "__main__": + notify("I'm test \"\"quote", msg_type=1, t=1000) notify("I'm test 1", msg_type=1, t=1000) notify("I'm test 2", msg_type=0, t=1000) diff --git a/setup.py b/setup.py index 06af9ade..b4572937 100644 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ ], entry_points={ 'console_scripts': [ - 'musicbox = NEMbox:start' + 'musicbox = NEMbox.__main__:start' ], }, keywords=['music', 'netease', 'cli', 'player'], From 559d4dcaea734452a870e99d1b6e33cee41ec39b Mon Sep 17 00:00:00 2001 From: Weiliang Li Date: Thu, 7 Jun 2018 12:40:44 +0900 Subject: [PATCH 3/3] update README --- NEMbox/__version__.py | 2 +- README.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEMbox/__version__.py b/NEMbox/__version__.py index 628a7307..53e3ef11 100644 --- a/NEMbox/__version__.py +++ b/NEMbox/__version__.py @@ -9,7 +9,7 @@ ''' __title__ = 'NetEase-MusicBox' -__version__ = '0.2.5.0' +__version__ = '0.2.5.1' __description__ = 'A sexy command line interface musicbox' __url__ = 'https://github.com/darknessomi/musicbox' __author__ = 'omi' diff --git a/README.md b/README.md index 969977fe..8c01c1a8 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,8 @@ Enjoy it ! ### 更新日志 +2018-06-07 版本 0.2.5.1 修复配置文件错误 + 2018-06-05 版本 0.2.5.0 全部迁移到新版api,大量错误修复 2018-05-21 版本 0.2.4.3 更新依赖,错误修复