Skip to content

Commit

Permalink
针对主播电台的修复,添加搜索主播电台的功能 (#928)
Browse files Browse the repository at this point in the history
* add search for djchannels

* fix empty song name in djprogram

1. 增大电台歌曲数至100
2. 修复#894导致的主播电台歌名大部分为空的情况

* change song info when playing djprogram

电台节目没必要显示空的艺术家和专辑名

* fix KeyError in Parse.songs

* fix space key event in djchannels

* fix songs_url sometimes return empty list (when sids list len>=400)

* add function to get all djprograms

* format with black

* fix songs_url return empty list in "refresh_urls"

* simplify code

以350个为一组,使用了一段时间djprogram未见报错,故精简

* replace djchannels to djRadios
  • Loading branch information
moomiji committed Jun 28, 2022
1 parent 1618998 commit 592e13d
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 37 deletions.
45 changes: 33 additions & 12 deletions NEMbox/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,18 +536,26 @@ def song_tlyric(self, music_id):
return lyric.split("\n")

# 今日最热(0), 本周最热(10),历史最热(20),最新节目(30)
def djchannels(self, offset=0, limit=50):
def djRadios(self, offset=0, limit=50):
path = "/weapi/djradio/hot/v1"
params = dict(limit=limit, offset=offset)
channels = self.request("POST", path, params).get("djRadios", [])
return channels
return self.request("POST", path, params).get("djRadios", [])

def djprograms(self, radio_id, asc=False, offset=0, limit=50):
path = "/weapi/dj/program/byradio"
params = dict(asc=asc, radioId=radio_id, offset=offset, limit=limit)
programs = self.request("POST", path, params).get("programs", [])
return [p["mainSong"] for p in programs]

def alldjprograms(self, radio_id, asc=False, offset=0, limit=500):
programs = []
ps = self.djprograms(radio_id, asc=asc, offset=offset, limit=limit)
while ps:
programs.extend(ps)
offset += limit
ps = self.djprograms(radio_id, asc=asc, offset=offset, limit=limit)
return programs

# 获取版本
def get_version(self):
action = "https://pypi.org/pypi/NetEase-MusicBox/json"
Expand All @@ -560,34 +568,44 @@ def get_version(self):
def dig_info(self, data, dig_type):
if not data:
return []
if dig_type == "songs" or dig_type == "fmsongs":
if dig_type == "songs" or dig_type == "fmsongs" or dig_type == "djprograms":
sids = [x["id"] for x in data]
urls = self.songs_url(sids)
i = 0
# 可能因网络波动,返回空值,在Parse.songs中引发KeyError
# 导致日志记录大量can't get song url的可能原因
urls = []
for i in range(0, len(sids), 350):
urls.extend(self.songs_url(sids[i : i + 350]))
# songs_detail api会返回空的电台歌名,故使用原数据
sds = []
while i < len(sids):
sds.extend(self.songs_detail(sids[i : i + 500]))
i += 500
timestamp = time.time()
if dig_type == "djprograms":
sds.extend(data)
# 支持超过1000首歌曲的歌单
else:
for i in range(0, len(sids), 500):
sds.extend(self.songs_detail(sids[i : i + 500]))
# api 返回的 urls 的 id 顺序和 data 的 id 顺序不一致
# 为了获取到对应 id 的 url,对返回的 urls 做一个 id2index 的缓存
# 同时保证 data 的 id 顺序不变
url_id_index = {}
for index, url in enumerate(urls):
url_id_index[url["id"]] = index

timestamp = time.time()
for s in sds:
url_index = url_id_index.get(s["id"])
if url_index is None:
log.error("can't get song url, id: %s", s["id"])
continue
return []
s["url"] = urls[url_index]["url"]
s["br"] = urls[url_index]["br"]
s["expires"] = urls[url_index]["expi"]
s["get_time"] = timestamp
return Parse.songs(sds)

elif dig_type == "refresh_urls":
urls_info = self.songs_url(data)
urls_info = []
for i in range(0, len(data), 350):
urls_info.extend(self.songs_url(data[i : i + 350]))
timestamp = time.time()

songs = []
Expand All @@ -614,5 +632,8 @@ def dig_info(self, data, dig_type):

elif dig_type == "playlist_class_detail":
return PLAYLIST_CLASSES[data]

elif dig_type == "djRadios":
return data
else:
raise ValueError("Invalid dig type")
34 changes: 19 additions & 15 deletions NEMbox/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ def search(self, category):
"albums": SearchArg("搜索专辑:", 10, lambda datalist: datalist),
"artists": SearchArg("搜索艺术家:", 100, lambda datalist: datalist),
"playlists": SearchArg("搜索网易精选集:", 1000, lambda datalist: datalist),
"djRadios": SearchArg("搜索主播电台:", 1009, lambda datalist: datalist),
}

prompt, api_type, post_process = category_map[category]
Expand Down Expand Up @@ -350,8 +351,8 @@ def space_key_event_in_search_result(self):
self.player.end_callback = None
self.player.play_or_pause(origin_index, self.at_playing_list)
self.at_playing_list = False
elif datatype == "djchannels":
self.player.new_player_list("djchannels", title, datalist, -1)
elif datatype == "djprograms":
self.player.new_player_list("djprograms", title, datalist, -1)
self.player.end_callback = None
self.player.play_or_pause(origin_index, self.at_playing_list)
self.at_playing_list = False
Expand All @@ -378,11 +379,11 @@ def space_key_event(self):
# If change to a new playing list. Add playing list and play.
datatype_callback = {
"songs": None,
"djchannels": None,
"djprograms": None,
"fmsongs": self.fm_callback,
}

if datatype in ["songs", "djchannels", "fmsongs"]:
if datatype in ["songs", "djprograms", "fmsongs"]:
self.player.new_player_list(datatype, self.title, self.datalist, -1)
self.player.end_callback = datatype_callback[datatype]
self.player.play_or_pause(idx, self.at_playing_list)
Expand Down Expand Up @@ -485,7 +486,7 @@ def num_jump_key_event(self):
self.build_menu_processbar()

def digit_key_song_event(self):
""" 直接跳到指定id 歌曲 """
"""直接跳到指定id 歌曲"""
step = self.step
self.key_list.pop()
song_index = parse_keylist(self.key_list)
Expand Down Expand Up @@ -829,7 +830,9 @@ def start(self):

# 添加到打碟歌单
elif C.keyname(key).decode("utf-8") == KEY_MAP["add"]:
if datatype == "songs" and len(datalist) != 0:
if (self.datatype == "songs" or self.datatype == "djprograms") and len(
self.datalist
) != 0:
self.djstack.append(datalist[idx])
elif datatype == "artists":
pass
Expand All @@ -847,7 +850,7 @@ def start(self):

# 添加到本地收藏
elif C.keyname(key).decode("utf-8") == KEY_MAP["star"]:
if (self.datatype == "songs" or self.datatype == "djchannels") and len(
if (self.datatype == "songs" or self.datatype == "djprograms") and len(
self.datalist
) != 0:
self.collection.append(self.datalist[self.index])
Expand All @@ -867,7 +870,7 @@ def start(self):
# 从当前列表移除
elif C.keyname(key).decode("utf-8") == KEY_MAP["remove"]:
if (
self.datatype in ("songs", "djchannels", "fmsongs")
self.datatype in ("songs", "djprograms", "fmsongs")
and len(self.datalist) != 0
):
self.datalist.pop(self.index)
Expand Down Expand Up @@ -1015,12 +1018,12 @@ def dispatch_enter(self, idx):
self.datatype = "albums"
self.datalist = netease.dig_info(albums, "albums")

elif datatype == "djchannels":
elif datatype == "djRadios":
radio_id = datalist[idx]["id"]
programs = netease.djprograms(radio_id)
programs = netease.alldjprograms(radio_id)
self.title += " > " + datalist[idx]["name"]
self.datatype = "songs"
self.datalist = netease.dig_info(programs, "songs")
self.datatype = "djprograms"
self.datalist = netease.dig_info(programs, "djprograms")

# 该专辑包含的歌曲
elif datatype == "albums":
Expand Down Expand Up @@ -1116,6 +1119,7 @@ def dispatch_enter(self, idx):
1: SearchCategory("songs", "歌曲搜索列表"),
2: SearchCategory("artists", "艺术家搜索列表"),
3: SearchCategory("albums", "专辑搜索列表"),
4: SearchCategory("djRadios", "主播电台搜索列表"),
}
self.datatype, self.title = idx_map[idx]
self.datalist = self.search(self.datatype)
Expand Down Expand Up @@ -1221,9 +1225,9 @@ def choice_channel(self, idx):
self.datalist = self.api.dig_info(myplaylist, self.datatype)
self.title += " > " + self.username + " 的歌单"
elif idx == 5:
self.datatype = "djchannels"
self.datatype = "djRadios"
self.title += " > 主播电台"
self.datalist = self.api.djchannels()
self.datalist = self.api.djRadios()
elif idx == 6:
self.datatype = "songs"
self.title += " > 每日推荐歌曲"
Expand All @@ -1243,7 +1247,7 @@ def choice_channel(self, idx):
elif idx == 9:
self.datatype = "search"
self.title += " > 搜索"
self.datalist = ["歌曲", "艺术家", "专辑", "网易精选集"]
self.datalist = ["歌曲", "艺术家", "专辑", "主播电台", "网易精选集"]
elif idx == 10:
self.datatype = "help"
self.title += " > 帮助"
Expand Down
2 changes: 1 addition & 1 deletion NEMbox/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ def append_songs(self, datalist):
self.add_songs(datalist)

# switch_flag为true表示:
# 在播放列表中 || 当前所在列表类型不在"songs"、"djchannels"、"fmsongs"中
# 在播放列表中 || 当前所在列表类型不在"songs"、"djprograms"、"fmsongs"中
def play_or_pause(self, idx, switch_flag):
if self.is_empty:
return
Expand Down
20 changes: 12 additions & 8 deletions NEMbox/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,16 @@ def build_playinfo(
1, self.indented_startcol, "♫ ♪ ♫ ♪ " + quality, curses.color_pair(3)
)

song_info = "{}{}{} < {} >".format(
song_name,
self.space,
artist,
album_name,
)
if artist or album_name:
song_info = "{}{}{} < {} >".format(
song_name,
self.space,
artist,
album_name,
)
else:
song_info = song_name

if truelen(song_info) <= self.endcol - self.indented_startcol - 19:
self.addstr(
1,
Expand Down Expand Up @@ -394,7 +398,7 @@ def build_menu(self, datatype, title, datalist, offset, index, step, start):
str(i) + ". " + datalist[i]["entry_name"],
)

elif datatype == "songs" or datatype == "fmsongs":
elif datatype == "songs" or datatype == "djprograms" or datatype == "fmsongs":
iter_range = min(len(datalist), offset + step)
for i in range(offset, iter_range):
if isinstance(datalist[i], str):
Expand Down Expand Up @@ -625,7 +629,7 @@ def build_menu(self, datatype, title, datalist, offset, index, step, start):
i - offset + 9, self.startcol, str(i) + ". " + datalist[i]
)

elif datatype == "djchannels":
elif datatype == "djRadios":
for i in range(offset, min(len(datalist), offset + step)):
if i == index:
self.addstr(
Expand Down
2 changes: 1 addition & 1 deletion NEMbox/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def notify_command_linux(msg, duration_time=None):


def notify(msg, msg_type=0, duration_time=None):
""" Show system notification with duration t (ms) """
"""Show system notification with duration t (ms)"""
msg = msg.replace('"', '\\"')
if platform.system() == "Darwin":
command = notify_command_osx(msg, msg_type, duration_time)
Expand Down

0 comments on commit 592e13d

Please sign in to comment.