前言
之前写过一篇文章Emby公益服-上万部电影电视剧免费看,如今账号快到期了,需要考核后才能延长账号有效期。正准备去考核时发现不是三天一次考核机会了,而是每日签到获取积分后才能考核,一次考核需要40积分,每日签到获取的积分不固定,好像1-5分都有!考核失败还是需要72小时后才能再次考试!
这就有点蛋疼了,他们bot签到是需要回答问题验证的,之前好像没有。本想实现自动签到,就用telegram-cli试了一下,发现根本不支持内联键盘消息!!!毕竟好几年前的代码了,作者也没有在维护。那么现在只能找找其他的telegram client api集成包玩玩了!
皇天不负有心人,找到了一个python包python-telegram,赶紧上手试试看支不支持内联键盘消息!
开搞
python-telegram命名空间和python-telegram-bot有冲突,如果装了两者没法用。
有两种解决办法,要么卸载掉python-telegram-bot,要么使用virtualenv环境隔离。
python-telegram没办法在windows下使用,还不支持!
先来将环境隔离,创建一个工作目录,然后在目录下安装隔离venv
是隔离环境名称:
mkdir python-telegram-client
cd python-telegram-client
virtualenv venv
# 进入隔离环境
source venv/bin/activate
# 安装python-telegram
pip install python-telegram
# 建个文件写代码
nano server.py
退出隔离环境使用:
# 退出隔离环境
deactivate
在Github看了下作者的例子和文档,随便找了个试一试。tg.get_chats()
返回的都是chat_id
,找不到哪个chat_id对应的群组/bot
。想了个办法,查看每个chat_id
最后一条消息,然后自己一个个找:
from telegram.client import Telegram
import re,time
...
tg = Telegram(...)
tg.login()
result = tg.get_chats()
result.wait()
if result.error:
print(f'get chats error: {result.error_info}')
else:
print(f'chats: {result.update}')
# 查看所有会话的最后一条消息,用来查找对应的chat_id
chat_ids = result.update['chat_ids']
for chat_id in chat_ids:
chat_history = tg.get_chat_history(chat_id=chat_id,limit=1)
chat_history.wait()
print(f'chat id:{chat_id},message:{chat_history.update["messages"][0]["content"]}\n')
...
找到了对应的chat_id
就可以和签到bot交互了。在发送签到命令之前,还需要监听新消息:
tg.add_update_handler('updateNewMessage', send_verification_code)
def send_verification_code(update):
# 所有的新消息都会被监听,增加判断只监听自己感兴趣的
if 123456789 == update['message']['chat_id']:
# print(update)
# 提取问题并且计算
question = update['message']['content']['text']['text']
print(question)
a = re.findall(r"\s\s(.+?)\+", question, re.M)
b = re.findall(r"\+(.+?)=", question, re.M)
if a and b:
print(a, b)
c = int(a[-1].strip()) + int(b[-1].strip())
answers = update['message']['reply_markup']['rows'][0]
print(f'{a} + {b} = {c}')
# 用答案和内联键盘值做匹配,一旦匹配执行按钮点击效果
for answer in answers:
print(f'答案:{answer["text"]}')
if int(answer['text']) == c:
payload = {
'@type': 'callbackQueryPayloadData',
'data': answer['type']['data'], ##每一个内联键盘都带有data数据
}
# 发送答案(点击内联键盘)
result = tg.call_method(method_name='getCallbackQueryAnswer',
params={'chat_id': update['message']['chat_id'],
'message_id': update['message']['id'], 'payload': payload})
result.wait()
if result.error:
print(f'getCallbackQueryAnswer error: {result.error_info}')
else:
print(f'getCallbackQueryAnswer: {result.update}')
break
以下是签到验证内联键盘消息部分报文:
...
'content': {'@type': 'messageText',
'text': {'@type': 'formattedText', 'text': '签到需要确认问题并选择您认为正确的答案:\n\n25 + 1 = ?\n\n请在 30 秒内作答',
'entities': [{'@type': 'textEntity', 'offset': 22, 'length': 10,
'type': {'@type': 'textEntityTypeBold'}},
{'@type': 'textEntity', 'offset': 37, 'length': 2,
'type': {'@type': 'textEntityTypeBold'}}]}},
'reply_markup': {'@type': 'replyMarkupInlineKeyboard',
'rows': [
[
{'@type': 'inlineKeyboardButton', 'text': '26',
'type': {'@type': 'inlineKeyboardButtonTypeCallback',
'data': 'Y2hlY2tpbi1RbWFYT3Z5SzlKb0VMZmtmUURMN3ZYcVZMeFIxNk1CRQ=='}},
{'@type': 'inlineKeyboardButton', 'text': '22',
'type': {'@type': 'inlineKeyboardButtonTypeCallback',
'data': 'Y2hlY2tpbi1PVkdOSjliZTJncXgxdDdmQTFQdnc5b2RtTXoxNlJ4WA=='}},
{'@type': 'inlineKeyboardButton', 'text': '85',
'type': {'@type': 'inlineKeyboardButtonTypeCallback',
'data': 'Y2hlY2tpbi1EV1gwTDYxTzRvWmxqRjFmYTlkMThBcFZ4OW1ZbmR5Sg=='}},
{'@type': 'inlineKeyboardButton', 'text': '66',
'type': {'@type': 'inlineKeyboardButtonTypeCallback',
'data': 'Y2hlY2tpbi1WR05KOWJlMmdxeEUxaTdmQTFQdnc5b2RtTXoxNlJ4WA=='}},
{'@type': 'inlineKeyboardButton', 'text': '68',
'type': {'@type': 'inlineKeyboardButtonTypeCallback',
'data': 'Y2hlY2tpbi1sNUJrbVBOd1hxQnhWZnpmMmJBUVZMclFKN0RSOXlqeA=='}}]]}}}
最后发送签到命令:
result = tg.send_message(
chat_id=123456789, ##chat_id自己找一找,虽然都一样!
text="/checkin",
)
result.wait()
tg.idle()
这就完成了一个账号的签到,如果是多个账号使用tg.idle()
就不行了,tg.idle()
会堵塞当前进程,需要终止信号终止。要跑多个账号只能等待一段时候后自动停止,然后再执行下一个账号。需要修改下代码,让他可以跑多个账号:
accounts = ['+123456789', '+456789123', '+789456123' ...]
for account in accounts:
tg = Telegram(... phone=account, ...)
tg.add_update_handler('updateNewMessage', send_verification_code)
tg.login()
...
print(f'当前账号:{account}')
print(f'等待15秒,接收签到验证信息并且验证签到')
time.sleep(15)
tg.stop()
python-telegram是支持多账户的,会保存用户凭证,所以登陆一次即可,新账户登陆还是需要输入验证码的。
现在我们将他打包成可执行程序:
pip install pyinstaller
打包
pyinstaller -F server.py
打包完成在dist
文件夹下。 如果直接跑起来会报错:..../libtdjson.so
的话可以下载作者编译好的libtdjson.so,也可以自己编译td build。libtdjson.so的位置可以在代码中指定:
tg = Telegram(...,library_path='/path/to/libtdjson.so')
这时候退出隔离环境deactivate
,跑一下../dist/server
,没有其他问题的话加入crontab, 设定每天执行一次即可自动签到!
结语
我个人感觉python-telegram在可编程上比telegram-cli要好用,之前LXK0301京东签到脚本-自动提交互助码一文中使用telegram-cli虽然也可以达到效果,但是不如直接敲代码来得舒服。telegram-cli更多的还是作为一个linux的telegram客户端。
python-telegram用来做签到只是个引子,更多的还是各种自动化非常简单了,毕竟官方提供了所有API。本来以为要自己集成实现API,还好有大佬做好了!
求大佬出个视频
大佬能不能出个详细的教程啊
centos7试验成功,十分感谢!
不过有centos7的小伙伴除了作者文章提到的centos7的libtdjson.so可以直接用以外,动态链接库libstdc++.so.6及libc.so.6都太旧了,需要自己make & make install(gcc的默认版本甚至低到没办法编译要先更新),然后替换了动态库链接也有可能发生其他程序没办法正常运行的问题,要生产环境做的话还是建议上docker吧(hhhh放自己博客的服务器我就随便换着玩了
能用!很稳!几乎没怎么改动!这种共产精神值得膜拜!
thanks!!!
就是我的ubuntu18.04的 libtdjson.so不支持前向兼容,ubuntu20编译的就只支持20以后的。我在18上编译了一下:
https://drive.google.com/file/d/1amS6i7bnzFoNx8UEg3r76osojKWpbLao/view?usp=sharing
可以直接用telethon,比python-telegram要简洁,教程也多得多
感谢,有时间玩玩!
你好,能出个详细点的教程吗?我想在openwrt的docker中安装py,再用py签到
...这个要复制进文件里吗
三个点是我省略的代码!懂代码稍微拼接下,不懂可能有难度!
能给个完整的代码文件嘛,账号信息我自己可以填上去,没这方面的经验,一脸懵
您好,请问有完整的代码文件吗,还是说上面的出现的代码写到一起就可以了