Skip to content

Commit

Permalink
🍰 complete
Browse files Browse the repository at this point in the history
  • Loading branch information
kba977 committed Feb 22, 2020
0 parents commit c67cb30
Show file tree
Hide file tree
Showing 11 changed files with 348 additions and 0 deletions.
126 changes: 126 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@

# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

### Python Patch ###
.venv/

# End of https://www.gitignore.io/api/python
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: python app.py
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Telegram 音乐盒子
在Telegram上搜索并下载某易云音乐


### 效果展示

![效果展示](./images/music_box_0.png)

在发出我想听XXX(歌曲名)后,bot返回的对话框状态由 搜索中 -> 下载中 -> 发送中 -> 歌曲 自动转换

搜索中
![效果展示](./images/music_box_1.png)

下载中
![效果展示](./images/music_box_2.png)


发送中
![效果展示](./images/music_box_3.png)

发送成功
![效果展示](./images/music_box_4.png)


### 部署到Heroku

1. 第一步,根据[此项目](https://github.com/Binaryify/NeteaseCloudMusicApi)建立音乐API 并部署到heroku。
2. 在 app.py 中修改对应地方的变量,如 机器人Token,上一步中音乐API的地址等。
3. 修改之后即可将本项目一同部署到heroku,即可。

7 changes: 7 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "MusicBox",
"description": "Telegram Music Box",
"image": "heroku/python",
"repository": "{部署代码的仓库地址}",
"keywords": ["python"]
}
172 changes: 172 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# -*- coding: utf-8 -*-

import os
import io
import re
from functools import wraps
import logging
from collections import namedtuple
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)

import requests
import telegram
from telegram import ChatAction
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from telegram.error import (TelegramError, Unauthorized, BadRequest,
TimedOut, ChatMigrated, NetworkError)

# 机器人的 TOKEN 填写在这里
TOKEN = "{YOUR_BOT_TOKEN}"
PORT = int(os.environ.get('PORT', '80'))

def error_callback(bot, context, error):
try:
raise error
except Unauthorized:
# remove update.message.chat_id from conversation list
bot.sendMessage(chat_id=context.message.chat.id,
text = '网络不稳定, 请稍后再试(1)')
except BadRequest:
# handle malformed requests - read more below!
bot.sendMessage(chat_id=context.message.chat.id,
text = '网络不稳定, 请稍后再试(2)')
except TimedOut:
# handle slow connection problems
bot.sendMessage(chat_id=context.message.chat.id,
text = '网络不稳定, 请稍后再试(3)')
except NetworkError:
# handle other connection problems
bot.sendMessage(chat_id=context.message.chat.id,
text = '网络不稳定, 请稍后再试(4)')
except ChatMigrated as e:
# the chat_id of a group has changed, use e.new_chat_id instead
bot.sendMessage(chat_id=context.message.chat.id,
text = '网络不稳定, 请稍后再试(5)')
except TelegramError:
# handle all other telegram related errors
bot.sendMessage(chat_id=context.message.chat.id,
text = '网络不稳定, 请稍后再试(6)')


def getMusicNameFromUser(context):
message = context.message.text
if not message.startswith('我想听'):
return None
name = message.replace('我想听','').strip()
return name


def getMusicInfoFromInternet(bot, context, musicName, msg):

# 这里添加网易云音乐 API 的地址
baseUrl = '{网易云音乐API的地址}'

music = namedtuple('music_info', ['name', 'id', 'author', 'thumb', 'url', 'lyric'])
resp = requests.get(baseUrl + f'/search?keywords={musicName}').json()
music_info = None
try:
music_info = resp['result']['songs'][0]
except KeyError as e:
bot.edit_message_text(chat_id=context.message.chat_id,
message_id=msg.message_id,
text='「'+ musicName +'」- 找不到该歌曲')
return None

music_id = music_info['id']
music_name = music_info['name']
music_author = music_info['artists'][0]['name']
music_url = f'https://music.163.com/song/media/outer/url?id={music_id}.mp3'
thumb_url = None
music_lyric = None

try:
resp = requests.get(baseUrl + f'/song/detail?ids={music_id}').json()
music_info = resp['songs'][0]
thumb_url = music_info['al']['picUrl']
except KeyError as e:
logging.info('cannot find music detail info !')


try:
resp = requests.get(baseUrl + f'/lyric?id={music_id}').json()
music_lyric = handle_lyric(resp['lrc']['lyric'])
except KeyError as e:
logging.info('cannot find music lyric !')

return music(music_name, music_id, music_author, thumb_url, music_url, music_lyric)


def handle_lyric(old_lyric):
lyric = re.sub(r'\[.*\]','', old_lyric).split('\n')
return '\n'.join(l.strip() for l in lyric)


def downloadMusicWithProgress(bot, context, music, msg):
logging.info(f'music: {music}')
if music.url == '':
return msg, None
resp = requests.get(music.url, stream=True)
total_length = resp.headers.get('Content-Length')
dl = 0
total_length = int(total_length)
output = io.BytesIO()
for data in resp.iter_content(chunk_size=1024*1024):
output.write(data)
dl += len(data)
done = int(25 * dl / total_length)
msg = bot.edit_message_text(chat_id=context.message.chat_id,
message_id=msg.message_id,
text="「"+ music.name +"」- " + music.author + ", 下载中....\n\r`[%s%s]`" % ('█' * done, '.' * (25-done)),
parse_mode='Markdown')
return msg, output


def echo(bot, context):
name = getMusicNameFromUser(context)
if not name: return

msg = context.message.reply_text("「"+ name +"」 搜索中...",
reply_to_message_id=context.message.message_id)

music = getMusicInfoFromInternet(bot, context, name, msg)
if not music: return

msg, output = downloadMusicWithProgress(bot, context, music, msg)

if output is not None:
msg = bot.edit_message_text(chat_id=context.message.chat_id,
message_id=msg.message_id,
text='mp3发送中....')

bot.sendAudio(chat_id=context.message.chat.id,
audio=io.BytesIO(output.getvalue()),
timeout=3000,
title=music.name,
performer=music.author,
thumb=music.thumb,
caption=music.lyric)
else:
bot.sendMessage(chat_id=context.message.chat.id,
text = '_该歌曲由于版权或者其他原因无法下载_\n\n' + music.author + ' - ' + music.name + '\n' + music.lyric,
parse_mode='Markdown')

bot.delete_message(chat_id=context.message.chat_id,
message_id=msg.message_id)


def main():
updater = Updater(TOKEN)

updater.start_webhook(listen="0.0.0.0",port=PORT,url_path=TOKEN)
updater.bot.set_webhook("{部署代码的URL}" + TOKEN)

dp = updater.dispatcher
dp.add_handler(MessageHandler(Filters.text, echo))
dp.add_error_handler(error_callback)

updater.idle()


if __name__ == '__main__':
main()
Binary file added images/music_box_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/music_box_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/music_box_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/music_box_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/music_box_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
asn1crypto==0.24.0
certifi==2018.11.29
cffi==1.12.2
chardet==3.0.4
cryptography==2.6.1
future==0.17.1
idna==2.8
pycparser==2.19
python-telegram-bot==11.1.0
requests==2.21.0
six==1.12.0
urllib3==1.24.1

0 comments on commit c67cb30

Please sign in to comment.