Skip to content

Commit

Permalink
增加当前列表模糊搜索,修复连续跳转Bug (#858)
Browse files Browse the repository at this point in the history
* mac专用版本1.0

* mac专用版本1.0

* 1.0安装

* 修复首次进评论的bug,提高主循环效率

* 修复快速按下一首多个子进程bug

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 修复线程混乱问题增加数字跳转快捷键

* 增加显示颜色自定义,按键映射,使用定时器实现自动关闭功能;修复搜索按键功能映射错误;发现快速切换时会播放多首音乐

* 0.1

* 0.1

* 0.2

* 0.2

* 0.2

* Fix comments bug.

* Fix comments bug.

* Fix comments bug.

* Fix comments bug.

* Optimize align of comments.

* Optimize align of comments.

* Optimize align of comments.

* Optimize for someone who write ':' in their comments.

* Fix comcomments.

* Fix comcomments.

* Fix comcomments.

* Update README.md

* Remove DS_Store.

* Fix keymap.

* Restore default key bindings.

* Restore osdlyrics.py

* Remove fucking glyphs.

* Fix comments bug.

* Merge.

* Remove DS_Store.

* Merge kwph and wjy.

* Change is to ==.

* Debug.

* Fix bug: fast pressing [ ] will causing multiple play instance.

* Remove build_menu_progress.

* Optimize branches.

* Add a blank in song and fmsongs.

* Add mouse support.

* Change f to config_file to stop annoying pylint.

* Fix notification on Linux.

* Move update api from macmusicbox to original one.

* Switch to timer.

* Fix display of help page.

* Add fuzzy search.

* Clean code.

* Improve performance on urxvt.

* Optimize up down key logic.

* Format const.py

* Update README.md & reset to origin default keymap.

* Remove untested platform & add dependencies for fuzzy search.

* Don't play music when press num keys.

* make num jump usable anywhere.

* Fix bug when mouse support is not enabled

* Remove num jump when using mouse.

* Abitious plan.

* Configuration: curses timeout.

* Try to optimize responsiveness.

* Remove yield latency (?).

* Partical plan.

* Update README.md

* Modifieable menu length

* Probably fix of bug darknessomi #816

* Change plan. Mark fixed.

* Fix jump logical chaos in comment.

* Fix the flash of color of lyrics when press j and k.

* Remove some targets & Use more accurate regex match to get timestap from lyrics

* Add auto adjust of page length according to terminal size.

* Update README.md to keep consist of original one.

* Use black to format code.

Co-authored-by: wangjianyuan10 <wangjianyuan10@163.com>
Co-authored-by: kenhuang <hwp0415229@sina.cn>
  • Loading branch information
3 people committed Aug 19, 2020
1 parent d09e2f0 commit 026e65c
Show file tree
Hide file tree
Showing 17 changed files with 1,266 additions and 493 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,8 @@ nemcache.sqlite

#Jetbrains
.idea

# Vim
.undodir
Session.vim
.vim
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include requirements.txt
include README.md
12 changes: 6 additions & 6 deletions NEMbox/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,10 @@ def make_cookie(self, name, value):
discard=False,
comment=None,
comment_url=None,
rest={},
rest=None,
)

def request(self, method, path, params={}, default={"code": -1}, custom_cookies={'os':'pc'}):
def request(self, method, path, params={}, default={"code": -1}, custom_cookies={}):
endpoint = "{}{}".format(BASE_URL, path)
csrf_token = ""
for cookie in self.session.cookies:
Expand Down Expand Up @@ -376,7 +376,7 @@ def login(self, username, password):
self.session.cookies.load()
if username.isdigit():
path = "/weapi/login/cellphone"
params = dict(phone=username, password=password, rememberLogin="true")
params = dict(phone=username, password=password, rememberLogin="true",)
else:
# magic token for login
# see https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/router/login.js#L15
Expand Down Expand Up @@ -433,7 +433,7 @@ def fm_like(self, songid, like=True, time=25, alg="itembased"):
# FM trash
def fm_trash(self, songid, time=25, alg="RT"):
path = "/weapi/radio/trash/add"
params = dict(songId=songid, alg=alg, time=time)
params = dict(songId=songid, alg=alg, time=time,)
return self.request("POST", path, params)["code"] == 200

# 搜索单曲(1),歌手(100),专辑(10),歌单(1000),用户(1002) *(type)*
Expand All @@ -445,7 +445,7 @@ def search(self, keywords, stype=1, offset=0, total="true", limit=50):
# 新碟上架
def new_albums(self, offset=0, limit=50):
path = "/weapi/album/new"
params = dict(area="ALL", offset=offset, total=True, limit=limit)
params = dict(area="ALL", offset=offset, total=True, limit=limit,)
return self.request("POST", path, params).get("albums", [])

# 歌单(网友精选碟) hot||new http://music.163.com/#/discover/playlist/
Expand Down Expand Up @@ -506,7 +506,7 @@ def song_comments(self, music_id, offset=0, total="false", limit=100):
# song ids --> song urls ( details )
def songs_detail(self, ids):
path = "/weapi/v3/song/detail"
params = dict(c=json.dumps([{"id": _id} for _id in ids]), ids=json.dumps(ids))
params = dict(c=json.dumps([{"id": _id} for _id in ids]), ids=json.dumps(ids),)
return self.request("POST", path, params).get("songs", [])

def songs_url(self, ids):
Expand Down
2 changes: 1 addition & 1 deletion NEMbox/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def start_download(self):
url = data[3]
onExit = data[4]
output_path = Constant.download_dir
output_file = str(artist).replace('/', ' ') + " - " + str(song_name) + ".mp3"
output_file = str(artist) + " - " + str(song_name) + ".mp3"
full_path = os.path.join(output_path, output_file)

new_url = NetEase().songs_url([song_id])[0]["url"]
Expand Down
152 changes: 152 additions & 0 deletions NEMbox/cmd_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#!/usr/bin/env python
# coding=utf-8
# __author__='walker'

"""
捕获类似curses键盘输入流,生成指令流
"""

import curses
from functools import wraps
from copy import deepcopy
from .config import Config

ERASE_SPEED = 5 # 屏幕5秒刷新一次 去除错误的显示

__all__ = ["cmd_parser", "parse_keylist", "coroutine", "erase_coroutine"]

keyMap = Config().get("keymap")


def coroutine(func):
@wraps(func)
def primer(*args, **kwargs):
gen = func(*args, **kwargs)
next(gen)
return gen

return primer


def _cmd_parser():
"""
A generator receive key value typed by user return constant keylist.
输入键盘输入流,输出指令流,以curses默认-1为信号终止.
"""
pre_key = -1
keylist = []
while 1:
key = yield
if key > 0 and pre_key == -1:
keylist.append(key)
elif key > 0 and pre_key > 0:
keylist.append(key)
elif curses.keyname(key).decode("utf-8") in keyMap.values() and pre_key > 0:
keylist.append(key)
return keylist
pre_key = key


def cmd_parser(results):
"""
A generator manager which can catch StopIteration and start a new Generator.
生成器管理对象,可以优雅地屏蔽生成器的终止信号,并重启生成器
"""
while 1:
results.clear()
results += yield from _cmd_parser()
yield results


def _erase_coroutine():
keylist = []
while 1:
key = yield
keylist.append(key)
if len(set(keylist)) > 1:
return keylist
elif len(keylist) >= ERASE_SPEED * 2:
return keylist


def erase_coroutine(erase_cmd_list):
while 1:
erase_cmd_list.clear()
erase_cmd_list += yield from _erase_coroutine()
yield erase_cmd_list


def parse_keylist(keylist):
"""
'2' '3' '4' 'j' ----> 234 j
supoort keys [ ] j k <KEY_UP> <KEY_DOWN>
"""
keylist = deepcopy(keylist)
if keylist == []:
return None
if (set(keylist) | {ord(keyMap["prevSong"]), ord(keyMap["nextSong"])}) == {
ord(keyMap["prevSong"]),
ord(keyMap["nextSong"]),
}:
delta_key = keylist.count(ord(keyMap["nextSong"])) - keylist.count(
ord(keyMap["prevSong"])
)
if delta_key < 0:
return (-delta_key, ord(keyMap["prevSong"]))
return (delta_key, ord(keyMap["nextSong"]))
tail_cmd = keylist.pop()
if tail_cmd in range(48, 58) and (set(keylist) | set(range(48, 58))) == set(
range(48, 58)
):
return int("".join([chr(i) for i in keylist] + [chr(tail_cmd)]))

if len(keylist) == 0:
return (0, tail_cmd)
if (
tail_cmd
in (
ord(keyMap["prevSong"]),
ord(keyMap["nextSong"]),
ord(keyMap["down"]),
ord(keyMap["up"]),
)
and max(keylist) <= 57
and min(keylist) >= 48
):
return (int("".join([chr(i) for i in keylist])), tail_cmd)
return None


def main(data):
"""
tset code
测试代码
"""
results = []
group = cmd_parser(results)
next(group)
for i in data:
group.send(i)
group.send(-1)
print(results)
next(group)
for i in data:
group.send(i)
group.send(-1)
print(results)
x = _cmd_parser()
print("-----------")
print(x.send(None))
print(x.send(1))
print(x.send(2))
print(x.send(3))
print(x.send(3))
print(x.send(3))
try:
print(x.send(-1))
except Exception as e:
print(e.value)


if __name__ == "__main__":
main(list(range(1, 12,)[::-1]))
91 changes: 84 additions & 7 deletions NEMbox/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
from __future__ import print_function, unicode_literals, division, absolute_import
import json
import os
from future.builtins import open

# from future.builtins import open

import sys
from .singleton import Singleton
from .const import Constant
from .utils import utf8_data_to_file
Expand All @@ -18,6 +20,13 @@ def __init__(self):
self.path = Constant.config_path
self.default_config = {
"version": 8,
"page_length": {
"value": 10,
"default": 10,
"describe": (
"Entries each page has. " "Set 0 to adjust automatically."
),
},
"cache": {
"value": False,
"default": False,
Expand Down Expand Up @@ -116,24 +125,92 @@ def __init__(self):
"default": False,
"describe": "Set true to make curses transparency.",
},
"mouse_movement": {
"value": False,
"default": False,
"describe": "Use mouse or touchpad to move.",
},
"input_timeout": {
"value": 500,
"default": 500,
"describe": "The time wait for the next key.",
},
"colors": {
"value": {
"pair1": [22, 148],
"pair2": [231, 24],
"pair3": [231, 9],
"pair4": [231, 14],
"pair5": [231, 237],
},
"default": {
"pair1": [22, 148],
"pair2": [231, 24],
"pair3": [231, 9],
"pair4": [231, 14],
"pair5": [231, 237],
},
"describe": "xterm-256color theme.",
},
"keymap": {
"value": {
"down": "j",
"up": "k",
"back": "h",
"forward": "l",
"prevPage": "u",
"nextPage": "d",
"search": "f",
"prevSong": "[",
"nextSong": "]",
"jumpIndex": "G",
"playPause": " ",
"shuffle": "?",
"volume+": "+",
"volume-": "-",
"menu": "m",
"presentHistory": "p",
"musicInfo": "i",
"playingMode": "P",
"enterAlbum": "A",
"add": "a",
"djList": "z",
"star": "s",
"collection": "c",
"remove": "r",
"moveDown": "J",
"moveUp": "K",
"like": ",",
"cache": "C",
"trashFM": ".",
"nextFM": "/",
"quit": "q",
"quitClear": "w",
"help": "y",
"top": "g",
"bottom": "G",
"countDown": "t",
},
"describe": "Keys and function.",
},
}
self.config = {}
if not os.path.isfile(self.path):
self.generate_config_file()

with open(self.path, "r") as f:
with open(self.path, "r") as config_file:
try:
self.config = json.load(f)
self.config = json.load(config_file)
except ValueError:
self.generate_config_file()

def generate_config_file(self):
with open(self.path, "w") as f:
utf8_data_to_file(f, json.dumps(self.default_config, indent=2))
with open(self.path, "w") as config_file:
utf8_data_to_file(config_file, json.dumps(self.default_config, indent=2))

def save_config_file(self):
with open(self.path, "w") as f:
utf8_data_to_file(f, json.dumps(self.config, indent=2))
with open(self.path, "w") as config_file:
utf8_data_to_file(config_file, json.dumps(self.config, indent=2))

def get(self, name):
if name not in self.config.keys():
Expand Down
31 changes: 25 additions & 6 deletions NEMbox/const.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
# encoding: UTF-8
# KenHuang: 使配置文件夹符合XDG标准
from __future__ import print_function, unicode_literals, division, absolute_import
import os


class Constant(object):
conf_dir = os.path.join(os.path.expanduser("~"), ".netease-musicbox")
download_dir = os.path.join(conf_dir, "cached")
if "XDG_CONFIG_HOME" in os.environ:
conf_dir = os.path.join(os.environ["XDG_CONFIG_HOME"], "netease-musicbox")
else:
conf_dir = os.path.join(os.path.expanduser("~"), ".netease-musicbox")
config_path = os.path.join(conf_dir, "config.json")
storage_path = os.path.join(conf_dir, "database.json")
cookie_path = os.path.join(conf_dir, "cookie")
log_path = os.path.join(conf_dir, "musicbox.log")
cache_path = os.path.join(conf_dir, "nemcache")
if "XDG_CACHE_HOME" in os.environ:
cacheDir = os.path.join(os.environ["XDG_CACHE_HOME"], "netease-musicbox")
if not os.path.exists(cacheDir):
os.mkdir(cacheDir)
download_dir = os.path.join(cacheDir, "cached")
cache_path = os.path.join(cacheDir, "nemcache")
else:
download_dir = os.path.join(conf_dir, "cached")
cache_path = os.path.join(conf_dir, "nemcache")
if "XDG_DATA_HOME" in os.environ:
dataDir = os.path.join(os.environ["XDG_DATA_HOME"], "netease-musicbox")
if not os.path.exists(dataDir):
os.mkdir(dataDir)
cookie_path = os.path.join(dataDir, "cookie")
log_path = os.path.join(dataDir, "musicbox.log")
storage_path = os.path.join(dataDir, "database.json")
else:
cookie_path = os.path.join(conf_dir, "cookie")
log_path = os.path.join(conf_dir, "musicbox.log")
storage_path = os.path.join(conf_dir, "database.json")
Loading

0 comments on commit 026e65c

Please sign in to comment.