Telegram 自动签到--Telethon

需求

Telegram 上包含很多机器人,机器人提供签到功能供用户获取资源,如机场机器人可以通过签到获取不定额度的流量。然而每天手动签到费时费力,而且经常容易忘记,因而想通过脚本结合定时任务自动签到。

准备工作

  1. Telegram 账号
  2. Linux 服务器

技术选型

Telegram 官方提供了开放的API,使得我们可以通过HTTP或Mtproto的方式自定义客户端与Telegram Server进行交互。但是为了更轻松编写可以与Telegram交互的Python程序,通常使用第三方封装库,例如pyrogram 以及 telethon。两者均为基于Mtproto协议实现的库,提供异步API,但telethon提供更多的高级接口方便我们快速开发,且GitHub上telethon也更加活跃与受关注。

实现

激活Telegram API

  1. 登录 Telegram 官方网站 https://my.telegram.org
  2. 选择 API development tools并填充相关信息
  3. 完成后保存api_idapi_hash凭证

安装依赖库

需要提前安装好python3.6以上版本,并安装pip

pip install telethon
pip install requests

编写代码

首先我们需要导入依赖库并创建一个client实例,其中,API_IDAPI_HASH为我们之前从https://my.telegram.org获取的凭证,CLIENT_NAME为客户端名称,用于标记该客户端,名字可自定义。

import asyncio
import base64
import json
import os
import re
import requests
from telethon import TelegramClient, events

async def main():
    async with TelegramClient(CLIENT_NAME, API_ID, API_HASH) as client:

签到脚本需要我们主动发送消息给对应机器人,其中CHANNEL_ID为机器人ID,例如'@channel_name',MSG为签到对应指令,例如'签到'。

async def main():
    MSG = '签到'
    CHANNEL_ID = '@channel_name'
    async with TelegramClient("CLIENT_NAME", API_ID, API_HASH) as client:
        await client.send_message(CHANNEL_ID, MSG)

部分机器人经过上述步骤即可完成签到,但是有些机器人需要进行验证,如图片验证码、内联按钮等。
我们可以通过OCR对图片进行识别从而通过验证。这里使用来truecaptcha实现图片验证码ocr。truecaptcha 提供100/天的免费额度。首先发送签到指令,然后等待机器人回复,如果机器人回复了验证码,我们可以通过truecaptcha的API识别图片验证码,并调用client.send_message(CHANNEL_ID, MSG)发送验证码,同时继续监听验证码是否通过验证,如果失败,则重新发送签到指令,直到验证通过。

async def main():
    MSG = '签到'
    CHANNEL_ID = '@channel_name'
    async with TelegramClient("CLIENT_NAME", API_ID, API_HASH) as client:
        await client.send_message(CHANNEL_ID, MSG)
        @client.on(events.NewMessage(chats=CHANNEL_ID))
        async def handler(event):
            # 根据button count 区分消息类型
            if "签到成功" in event.message.text or "上次签到" in event.message.text:
                # 结束异步任务
                await client.disconnect()
            elif event.message.buttons:
                if event.message.button_count == 6:  # 主菜单
                    await event.message.buttons[2][0].click()
                elif event.message.button_count == 7:  # 更多功能
                    await event.message.buttons[0][1].click()
            # 图像验证码处理
            elif "请输入验证码" in event.message.text:  # 获取图像验证码
                await client.download_media(event.message.photo, "captcha.jpg")
                # 使用 TRUECAPTCHA 模块解析验证码
                solved_result = captcha_solver("captcha.jpg")
                if not "result" in solved_result:
                    await client.send_message(CHANNEL_ID, "21342")
                    return
                captcha_code = handle_captcha_solved_result(solved_result)
                await client.send_message(event.message.chat_id, captcha_code)
                # 删除临时文件
                os.remove("captcha.jpg")
            # 是否成功签到
            elif "验证码错误" in event.message.text:
                await client.send_message(event.message.chat_id, RETURE_MENU)

内联按钮我们则通过区分不同类型的消息类型来获取内联按钮数据,并触发按钮点击事件完成验证,这里以 简单加法计算结果为例。

async def main():
    async with TelegramClient("CLIENT_NAME", API_ID, API_HASH) as client:
        await client.send_message(CHANNEL_ID, '/checkin')

        @client.on(events.NewMessage(chats=CHANNEL_ID))
        async def handler(event):
            # 获取带按钮的消息
            if "已经签到过了" in event.message.text:
                await client.disconnect()
            elif event.message.buttons:
                # 获取算式
                # '签到需要确认问题并选择您认为正确的答案:\n\n25 + 1 = ?\n\n请在 30 秒内作答'
                formula = event.message.raw_text.split('\n\n')[1]
                # 计算结果 25 + 1 = ?
                result = int(formula.split(' ')[0]) + int(formula.split(' ')[2])
                # 匹配按钮文本并点击
                for button in event.message.buttons[0]:
                    if int(button.text) == result:
                        await button.click()
                        break
                # 结束异步任务
                await client.disconnect()

最后通过asyncio.run()方法启动异步任务,并等待任务结束。

asyncio.run(main())

定时运行

python 定时运行可以通过 scheduler 模块实现,但是简单脚本可以直接使用 linux的 crontab实现,减少了编码和调试难度。

# 每天凌晨1点执行
0 1 * * * python3 /path/to/script.py
已有 2 条评论
  1. shino shino

    请问如何能运行里面的handler()呢,我运行代码发现这里没有运行

    1. handler()的代码是基于回调事件执行的, @client.on(events.NewMessage(chats=CHANNEL_ID))这个是监听到指定CHANNEL_ID的对话收到消息后被调用

添加新评论