Skip to content

Commit

Permalink
✨添加歌单压缩上传
Browse files Browse the repository at this point in the history
🐛#8
  • Loading branch information
kitUIN committed Dec 10, 2022
1 parent 17c35e3 commit 1ca3269
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 82 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ ncm_admin_level=1 # 设置命令权限(1:仅限superusers和群主,2:在1的基
ncm_ctcode="86" # 手机号区域码,默认86
ncm_phone= # 手机登录
ncm_password= # 密码
ncm_playlist_zip=False # 上传歌单时是否压缩
```

## 功能列表
Expand Down
32 changes: 18 additions & 14 deletions nonebot-plugin-ncm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
from typing import Tuple, Any, Union

import nonebot
Expand Down Expand Up @@ -129,20 +130,21 @@ async def receive_song(bot: Bot,


@music_regex.handle()
async def music_receive(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent], regroup: Tuple[Any, ...] = RegexGroup()):
async def music_receive(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent],
regroup: Tuple[Any, ...] = RegexGroup()):
nid = regroup[1]
logger.info(f"已识别NID:{nid}的歌曲")
nncm.get_session(bot, event)
nncm.get_song(nid)


@playlist_regex.handle()
async def music_list_receive(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent], regroup: Tuple[Any, ...] = RegexGroup()):
async def music_list_receive(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent],
regroup: Tuple[Any, ...] = RegexGroup()):
lid = regroup[0]
logger.info(f"已识别LID:{lid}的歌单")
nncm.get_session(bot, event)
msg = await nncm.playlist(lid=lid)
await bot.send(event=event, message=Message(MessageSegment.text(msg)))
nncm.get_playlist(lid=lid)


@music_reply.handle()
Expand All @@ -158,24 +160,26 @@ async def music_reply_receive(bot: Bot, event: Union[GroupMessageEvent, PrivateM
data = await nncm.music_check(info["nid"])
if data:
if isinstance(event, GroupMessageEvent):
await nncm.upload_group_file(data)
await nncm.upload_group_data_file(data)
elif isinstance(event, PrivateMessageEvent):
await nncm.upload_private_file(data)
await nncm.upload_private_data_file(data)
else:
logger.error("数据库中未有该音乐地址数据")

elif info["type"] == "playlist" and await playlist_is_open(event):
await nncm.download(ids=info["ids"])
for i in info["ids"]:
data = await nncm.music_check(i)
if data:
await nncm.upload_group_file(data)
else:
logger.error("数据库中未有该音乐地址数据")
await bot.send(event=event, message=info["lmsg"]+"\n下载中")
await nncm.download(ids=info["ids"], lid=info["lid"], is_zip=ncm_config.ncm_playlist_zip)
filename = f"{info['lid']}.zip"
data = Path.cwd().joinpath("music").joinpath(filename)
if isinstance(event, GroupMessageEvent):
await nncm.upload_group_file(file=str(data), name=filename)
elif isinstance(event, PrivateMessageEvent):
await nncm.upload_private_file(file=str(data), name=filename)


@ncm_set.handle()
async def set_receive(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent], args: Message = CommandArg()): # 功能设置接收
async def set_receive(bot: Bot, event: Union[GroupMessageEvent, PrivateMessageEvent],
args: Message = CommandArg()): # 功能设置接收
logger.debug(f"权限为{event.sender.role}的用户<{event.sender.nickname}>尝试使用命令{cmd}ncm {args}")
if args:
args = str(args).split()
Expand Down
3 changes: 3 additions & 0 deletions nonebot-plugin-ncm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class Config(BaseModel, extra=Extra.ignore):
ncm_password: str = ""
'''密码'''

ncm_playlist_zip: bool = False
'''上传歌单时是否压缩'''


global_config = nonebot.get_driver().config
ncm_config = Config(**global_config.dict()) # 载入配置
120 changes: 52 additions & 68 deletions nonebot-plugin-ncm/data_source.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import zipfile
from pathlib import Path
from datetime import datetime
from typing import Union
Expand All @@ -12,6 +13,7 @@

import httpx
import nonebot
from nonebot.utils import run_sync

from pyncm import apis, Session, GetCurrentSession, DumpSessionAsString, LoadSessionFromString, SetCurrentSession
from pyncm.apis.cloudsearch import SONG, USER, PLAYLIST
Expand All @@ -34,8 +36,7 @@
if not dbPath.is_dir():
dbPath.mkdir()
logger.success("ncm数据库目录创建成功")
music = TinyDB("./db/musics.json")
playlist = TinyDB("./db/playlist.json")
music = TinyDB("./db/ncm_musics.json")
setting = TinyDB("./db/ncm_setting.json")
ncm_user_cache = TinyDB("./db/ncm_cache.json")
ncm_check_cache = TinyDB("./db/ncm_check_cache.json")
Expand Down Expand Up @@ -161,13 +162,8 @@ async def search_user(self, keyword: str, limit: int = 1): # 搜索用户
async def search_playlist(self, keyword: str, limit: int = 1): # 搜索歌单
self.api.cloudsearch.GetSearchResult(keyword=keyword, stype=PLAYLIST, limit=limit)

async def parse_song(self, nid: Union[int, str]):
msg = f"歌曲ID:{nid}\r\n如需下载请回复该条消息\r\n关闭解析请使用指令\r\n{cmd}ncm f"
await self.bot.send(event=self.event, message=Message(MessageSegment.text(msg)))

def check_message(self):
"""检查缓存中是否存在解析
:return:
"""
info = ncm_check_cache.search(Q.message_id == self.event.dict()["reply"]["message_id"])
Expand All @@ -187,32 +183,40 @@ def get_song(self, nid: Union[int, str], message_id=None):
ncm_check_cache.insert({"message_id": mid,
"type": "song",
"nid": nid,
"lid": 0,
"ids": [],
"lmsg": "",
"time": int(time.time())})

def get_playlist(self, ids: list, message_id=None):
"""解析歌曲id,并且加入缓存
:param message_id:
:param ids:
:return:
"""
if message_id:
mid = message_id
else:
mid = self.event.message_id
ncm_check_cache.insert({"message_id": mid,
"type": "playlist",
"nid": 0,
"ids": ids,
"time": int(time.time())})

async def upload_group_file(self, data):
def get_playlist(self, lid: Union[int, str]):
data = self.api.playlist.GetPlaylistInfo(lid)
# logger.info(data)
if data["code"] == 200:
raw = data["playlist"]
tags = ",".join(raw['tags'])
songs = [i['id'] for i in raw['trackIds']]
ncm_check_cache.insert({"message_id": self.event.message_id,
"type": "playlist",
"nid": 0,
"lid": lid,
"ids": songs,
"lmsg": f"歌单:{raw['name']}\r\n创建者:{raw['creator']['nickname']}\r\n歌曲总数:{raw['trackCount']}\r\n"
f"标签:{tags}\r\n播放次数:{raw['playCount']}\r\n收藏:{raw['subscribedCount']}\r\n"
f"评论:{raw['commentCount']}\r\n分享:{raw['shareCount']}\r\nListID:{lid}",
"time": int(time.time())})

async def upload_group_data_file(self, data):
await self.upload_group_file(file=data["file"], name=data["filename"])

async def upload_private_data_file(self, data):
await self.upload_private_file(file=data["file"], name=data["filename"])

async def upload_group_file(self, file, name):
try:
await self.bot.call_api('upload_group_file', group_id=self.event.group_id,
file=data["file"], name=data["filename"])
await self.bot.upload_group_file(group_id=self.event.group_id,
file=file, name=name)
except (ActionFailed, NetworkError) as e:
logger.error(e.info)
logger.error(e)
if isinstance(e, ActionFailed) and e.info["wording"] == "server" \
" requires unsupported ftn upload":
await self.bot.send(event=self.event, message=Message(MessageSegment.text(
Expand All @@ -222,47 +226,28 @@ async def upload_group_file(self, data):
await self.bot.send(event=self.event, message=Message(MessageSegment.text(
"[ERROR] 文件上传失败\r\n[原因] 上传超时(一般来说还在传,建议等待五分钟)")))

async def upload_private_file(self, data):
async def upload_private_file(self, file, name):
try:
await self.bot.call_api('upload_private_file', user_id=self.event.get_user_id(),
file=data["file"], name=data["filename"])
await self.bot.upload_private_file(user_id=self.event.user_id,
file=file, name=name)
except (ActionFailed, NetworkError) as e:
logger.error(e.info)
logger.error(e)
if isinstance(e, NetworkError):
await self.bot.send(event=self.event, message=Message(MessageSegment.text(
"[ERROR] 文件上传失败\r\n[原因] 上传超时(一般来说还在传,建议等待五分钟)")))

async def playlist(self, lid: Union[int, str]): # 下载歌单
data = self.api.playlist.GetPlaylistInfo(lid)
# logger.info(data)
if data["code"] == 200:
raw = data["playlist"]
tags = ",".join(raw['tags'])
msg = f"歌单:{raw['name']}\r\n创建者:{raw['creator']['nickname']}\r\n歌曲总数:{raw['trackCount']}\r\n" \
f"标签:{tags}\r\n播放次数:{raw['playCount']}\r\n收藏:{raw['subscribedCount']}\r\n" \
f"评论:{raw['commentCount']}\r\n分享:{raw['shareCount']}\r\nLIST:{lid}" \
f"\r\n如需下载请回复该条消息\r\n关闭解析请使用指令\r\n{cmd}ncm f"
songs = [i['id'] for i in raw['trackIds']]
info = playlist.search(Q["playlist_id"] == lid)
if info:
info[0]["time"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
playlist.update(info[0], Q["playlist_id"] == lid)
else:
config = {
"playlist_id": lid,
"counts": raw['trackCount'], # 歌曲总数
"ids": songs, # id列表
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 获取时间
}
playlist.insert(config)
return msg

async def download(self, ids: list, check=False): # 下载音乐
@run_sync
def get_zip(self, lid, filenames: list):
zip_file_new = f'{lid}.zip'
with zipfile.ZipFile(str(Path.cwd().joinpath("music").joinpath(zip_file_new)), 'w', zipfile.ZIP_DEFLATED) as z:
for f in filenames:
z.write(str(f), f.name)
return zip_file_new

async def download(self, ids: list, check=False, lid=0, is_zip=False): # 下载音乐
data: list = self.api.track.GetTrackAudio(song_ids=ids, bitrate=3200 * 1000)["data"]
# logger.info(data)
name: list = self.detail(ids)
# logger.info(name)
num = 1
filenames = []
for i in range(len(ids)):
if data[i]["code"] == 404:
logger.error("未从网易云读取到下载地址")
Expand All @@ -279,6 +264,7 @@ async def download(self, ids: list, check=False): # 下载音乐
"from": "song" if len(ids) == 1 else "list", # 判断来自单曲还是歌单
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 获取时间
}
filenames.append(file)
info = music.search(Q["id"] == nid)
if info: # 数据库储存
music.update(config, Q["id"] == nid)
Expand All @@ -289,12 +275,10 @@ async def download(self, ids: list, check=False): # 下载音乐
async with async_open(file, 'wb') as out_file:
async for chunk in r.aiter_bytes():
await out_file.write(chunk)
if not check and len(ids) > 1:
if num // 10 == 0 or num == len(ids):
await self.bot.send(event=self.event,
message=Message(MessageSegment.text(f"下载进度:{num}/{len(ids)}")))
num += 1
return config
if is_zip:
await self.get_zip(lid=lid, filenames=filenames)
return config


nncm = Ncm()
info = ncm_user_cache.search(Q.uid == "user")
Expand Down

0 comments on commit 1ca3269

Please sign in to comment.