# coding:utf-8 import sys import io import os import time import re import json import base64 import threading web_dir = os.getcwd() + "/web" if os.path.exists(web_dir): sys.path.append(web_dir) os.chdir(web_dir) import core.mw as mw import telebot from telebot import types from telebot.util import quick_markup # 网易音乐搜索 def isThisCmd(cmd, msg): clen = len(cmd) msg_len = len(msg) if msg_len < clen: return False check_msg = msg[0:clen] if cmd == check_msg: return True return False def getReadCmd(cmd, msg): clen = len(cmd) msg_len = len(msg) real_msg = msg[clen:] return real_msg def ip2long(ip): import struct import socket return struct.unpack("!L", socket.inet_aton(ip))[0] def long2ip(longip): import struct import socket return socket.inet_ntoa(struct.pack('!L', longip)) def mt_rand(a, b): import random return random.randint(a, b) def httpPost(url, data, timeout=10): """ 发送POST请求 @url 被请求的URL地址(必需) @data POST参数,可以是字符串或字典(必需) @timeout 超时时间默认60秒 return string """ try: import urllib.request import ssl try: ssl._create_default_https_context = ssl._create_unverified_context except: pass headers = { 'Referer': 'https://music.163.com/', 'Cookie': 'appver=8.2.30; os=iPhone OS; osver=15.0; EVNSM=1.0.0; buildver=2206; channel=distribution; machineid=iPhone13.3', 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 CloudMusic/0.1.1 NeteaseMusic/8.2.30', 'X-Real-IP': long2ip(mt_rand(1884815360, 1884890111)), 'Accept': '*/*', 'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', } data = urllib.parse.urlencode(data).encode('utf-8') req = urllib.request.Request(url, data, headers=headers) response = urllib.request.urlopen(req, timeout=timeout) result = response.read() if type(result) == bytes: result = result.decode('utf-8') return result except Exception as ex: return str(ex) def musicSearch(kw, page=1, page_size=5): m_offset = (int(page) - 1) * int(page_size) data = httpPost('http://music.163.com/api/cloudsearch/pc', { 's': kw, 'type': '1', 'total': 'true', 'limit': page_size, 'offset': m_offset, }) # data_a = json.loads(data) # print(data) # exit() return json.loads(data) def musicSongD(mid): data = httpPost('http://music.163.com/api/v3/song/detail/', { 'c': '[{"id":' + str(mid) + ',"v":0}]', }) # print(data) return json.loads(data) def musicSongDataUrl(mid): data = httpPost('http://music.163.com/api/song/enhance/player/url', { 'br': 320 * 1000, 'ids': [mid], }) return json.loads(data) def writeLog(log_str): if __name__ == "__main__": print(log_str) now = mw.getDateFromNow() log_file = mw.getServerDir() + '/tgbot/task.log' mw.writeFileLog(now + ':' + log_str, log_file, limit_size=5 * 1024) return True def tgSearchMusic_t(cmd_text): data = musicSearch(cmd_text, 1, 5) if data['code'] == 200 and len(data['result']['songs']) > 0: slist = data['result']['songs'] print(slist) else: keyboard = [ [ types.InlineKeyboardButton( text="论坛", url='https://bbs.midoks.icu'), types.InlineKeyboardButton( text="搜索", url='https://bbs.midoks.icu/search.php') ], [ types.InlineKeyboardButton( text="关闭消息", callback_data='bbs_search_close') ] ] markup = types.InlineKeyboardMarkup(keyboard) bot.send_message( message.chat.id, "未找到合适内容,请在官方论坛[bbs.midoks.icu]提问!", reply_markup=markup) return True def tgSearchMusic(bot, message, cmd_text): import math data = musicSearch(cmd_text, 1, 5) if data['code'] == 200 and len(data['result']['songs']) > 0: keyboard = [] slist = data['result']['songs'] page_total = math.ceil(data['result']['songCount'] / 5) for x in slist: author = '' if len(x['ar']) > 0: author = ' - ' + x['ar'][0]['name'] keyboard.append([types.InlineKeyboardButton( text=x['name'] + author, callback_data='m163_id:' + str(x['id']))]) keyboard.append([ types.InlineKeyboardButton( text="下一页", callback_data='m163_next_page_2'), types.InlineKeyboardButton( text="第1页,共" + str(page_total) + "页", callback_data='m163_page_total') ]) keyboard.append([types.InlineKeyboardButton( text="关闭消息", callback_data='m163_search_close')]) # print(keyboard) markup = types.InlineKeyboardMarkup(keyboard) bot.send_message(message.chat.id, "寻找【" + cmd_text.strip() + "】歌曲如下:", reply_markup=markup) else: bot.send_message(message.chat.id, "未找到合适内容") return True def getFaqKw(cmd): matchObj = re.match(r'寻找【(.*?)】歌曲如下', cmd, re.M | re.I) data = matchObj.groups() if len(data) > 0: return True, data[0] return False, '' def cleanMusicFileExpire(dir): pass def downloadAndUpMusic(bot, chat_id, mid, title): import requests murl_data = musicSongDataUrl(int(mid)) murl = murl_data['data'][0]['url'] def_dir = '/tmp/tgbot_music' if not os.path.exists(def_dir): os.mkdir(def_dir) def_abs_path = def_dir + '/' + title + '.mp3' # print('downloadAndUpMusic' + ":" + str(murl)) if murl: msg_t = bot.send_message(chat_id, "已经获取资源URL,本地下载中...") response = requests.get(murl) with open(def_abs_path, "wb") as f: f.write(response.content) bot.edit_message_text( chat_id=chat_id, message_id=msg_t.message_id, text="本地下载完,正在上传中...") audio = open(def_abs_path, 'rb') bot.send_audio(chat_id, audio) bot.edit_message_text( chat_id=chat_id, message_id=msg_t.message_id, text="上传结束...1s自动删除") time.sleep(1) bot.delete_message(chat_id=chat_id, message_id=msg_t.message_id) else: bot.send_message(chat_id, "无效资源") if os.path.exists(def_abs_path): os.remove(def_abs_path) # cleanMusicFileExpire(def_dir) return True def answer_callback_query(bot, call): import math keyword = call.data # print(keyword) if keyword == 'm163_search_close': bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id) return # 音乐下载 if keyword.startswith('m163_id:'): t = keyword.split(":") inline_keyboard = call.json['message'][ "reply_markup"]["inline_keyboard"] def_file_name = 'demo' for x in inline_keyboard: # print(x) if x[0]['callback_data'] == keyword: def_file_name = x[0]['text'] # print(call.message) downloadAndUpMusic(bot, call.message.chat.id, t[1], def_file_name) bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.message_id) return True is_m163_page = False p = 1 if keyword.startswith('m163_next_page'): is_m163_page = True p = keyword.replace('m163_next_page_', '') if keyword.startswith('m163_pre_page'): is_m163_page = True p = keyword.replace('m163_pre_page_', '') if is_m163_page: is_match, cmd_text = getFaqKw(call.message.text) if not is_match: bot.edit_message_text( chat_id=call.message.chat.id, message_id=call.message.message_id, text="出现错误!") return data = musicSearch(cmd_text, p, 5) dlist = data['result']['songs'] page_total = math.ceil(data['result']['songCount'] / 5) keyboard = [] for x in dlist: author = '' if len(x['ar']) > 0: author = ' - ' + x['ar'][0]['name'] keyboard.append([types.InlineKeyboardButton( text=x['name'] + author, callback_data='m163_id:' + str(x['id']))]) page_nav = [] if int(p) > 1: page_nav.append(types.InlineKeyboardButton( text="上一页", callback_data='m163_pre_page_' + str(int(p) - 1))) if int(p) < page_total: page_nav.append(types.InlineKeyboardButton( text="下一页", callback_data='m163_next_page_' + str(int(p) + 1))) page_nav.append(types.InlineKeyboardButton( text="第" + str(p) + "页,共" + str(page_total) + "页", callback_data='m163_page_total')) keyboard.append(page_nav) keyboard.append([types.InlineKeyboardButton( text="关闭消息", callback_data='m163_search_close')]) markup = types.InlineKeyboardMarkup(keyboard) bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=call.message.text, reply_markup=markup) def run(bot, message): text_body = message.text if isThisCmd('/music', text_body): cmd_text = getReadCmd('/music', text_body) cmd_text = cmd_text.strip().strip(":") if cmd_text == "": return bot.send_message(message.chat.id, "搜索内容不能为空, 例如:/music 刀郎") return tgSearchMusic(bot, message, cmd_text) return bot if __name__ == '__main__': # cleanMusicFileExpire("/tmp/tgbot_music") # tgSearchMusic_t("一夜泥工") # print(long2ip(mt_rand(1884815360, 1884890111))) t = musicSongDataUrl(2063487880) print(t['data']) print("111")