在一个月光如雪的晚上和 PMheart 在 Telegram 闲聊,突然发现群里一个人的昵称是当前时间,然后观察一会儿发现还在不停变化… 最可气的是他还弄个 “东半球🌏最准报时” 的头衔,我一开始以为是 Telegram 又出的什么 “高级功能”(毕竟微信炸💩都是 Telegram 好久之前玩剩下的),几经 Google 我发现其实就是自己写个 Bot,然后定时 rename;那我要不整个 “东半球最浪漫诗人” 岂不是太面了🤔。
一、Telegram Bot 介绍 在 Telegram 官方的文档描述中,其 Bot Api 实质上分为两种,这两种 Api 用途也各不相同:
1.1、标准 Bot 由用户自行联系 BotFather
(人如其名)交互式创建,该 Bot 是官方所认为的标准 Bot,其主要目的就是作为一个真正的 Bot;我们可以通过一个 Token 调用 Telegram Api 来控制它,玩法很多,包括不限于发送告警、作为群管机器人、交互式的帮你做各种自动化等等;同时这个 Bot 具有严格的隐私权限控制,比如拉到群里可以控制 Bot 对群消息是否可见等等(Telegram 这点做的非常 OJBK);借助于这类 Bot,也有些脑洞大开的大哥在浪的边缘疯狂试探,比如下面的扫雷机器人:
还有算命的:
Github 真正干活的:
我的证书告警:
当然肯定有高铁动车组的(🔞我是正经人):
1.2、客户端 Bot 准确的官方介绍是 TDLib – build your own Telegram
,从这个介绍可以看出,这一个 “Bot” Api 本质上并不是让你写 Bot,而是作为开发一个第三方 Telegram 客户端用的;所以这个 Api 的权限很大,可以完整的模拟一个用户;目前我发现被滥用最多的就是用这个 Api 作为恶意拉人、发广告等,简直是币圈割韭菜御用。
TDLib 本质上是一个 C++ 的 lib,官方提供了引导页面来帮助你用主流语言跨语言调用来使用它:
二、标准 Bot 使用 标准 Bot 使用相对简单,按照官方文档跟 BotFather
聊天创建一个即可:
当创建完成后在 Bot 设置界面你可以获取一个 Token
,使用这个 Token 连接 Bot Api 地址就可以开始控制你的 Bot;Golang 开发可以考虑使用 https://github.com/tucnak/telebot 这个库,用法相当简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package mainimport ( "log" "time" tb "gopkg.in/tucnak/telebot.v2" )func main () { b, err := tb.NewBot(tb.Settings{ URL: "http://195.129.111.17:8012" , Token: "TOKEN_HERE" , Poller: &tb.LongPoller{Timeout: 10 * time.Second}, }) if err != nil { log.Fatal(err) return } b.Handle("/hello" , func (m *tb.Message) { b.Send(m.Sender, "Hello World!" ) }) b.Start() }
基于这个库,我为了方便使用写了一个命令行小工具,方便我发送告警信息等: tgsend
三、客户端 Api 使用 标准 Bot Api 很丰富,日常干活啥的也完全能满足,但是!人如果不会装X那和咸鱼有什么区别? 我的 “东半球最浪漫诗人” 得提上日程。
3.1、TDLib 构建 关于 Api 易用性,开发生态环境,这一点说实话,Telegram 能把所有国内 IM 按在地上摩擦,就像这样:
Telegram 官方提供了完整的 “点一点” 构建 TDLib 引导页面: https://tdlib.github.io/td/build.html
勾选好自己的语言、操作系统、系统版本、甚至是编译的内存大小等设置后,无脑复制下面的命令执行就行:
3.2、Telegram API HASH TDLib 构建完成后,需要自行申请一个 API_HASH,API_HASH 类似一个让 Telegram 识别你的客户端的 “合法标识”;API_HASH 申请需要登陆 https://my.telegram.org/ ,然后选择 API development tools :
然后填写相关信息,最后 Telegram 就会为你生成好 API_HASH:
3.3、TDLib 使用 TDLib 构建好了,API HASH 也有了,那么根据自己选择的语言找一个靠谱的 SDK 使用即可;比如 Golang 开发,我选择了 https://github.com/Arman92/go-tdlib ,这个库使用相当简单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package mainimport ( "fmt" "github.com/Arman92/go-tdlib" )func main () { tdlib.SetLogVerbosityLevel(1 ) tdlib.SetFilePath("./errors.txt" ) client := tdlib.NewClient(tdlib.Config{ APIID: "187786" , APIHash: "e782045df67ba48e441ccb105da8fc85" , SystemLanguageCode: "en" , DeviceModel: "Server" , SystemVersion: "1.0.0" , ApplicationVersion: "1.0.0" , UseMessageDatabase: true , UseFileDatabase: true , UseChatInfoDatabase: true , UseTestDataCenter: false , DatabaseDirectory: "./tdlib-db" , FileDirectory: "./tdlib-files" , IgnoreFileNames: false , }) for { currentState, _ := client.Authorize() if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateWaitPhoneNumberType { fmt.Print("Enter phone: " ) var number string fmt.Scanln(&number) _, err := client.SendPhoneNumber(number) if err != nil { fmt.Printf("Error sending phone number: %v" , err) } } else if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateWaitCodeType { fmt.Print("Enter code: " ) var code string fmt.Scanln(&code) _, err := client.SendAuthCode(code) if err != nil { fmt.Printf("Error sending auth code : %v" , err) } } else if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateWaitPasswordType { fmt.Print("Enter Password: " ) var password string fmt.Scanln(&password) _, err := client.SendAuthPassword(password) if err != nil { fmt.Printf("Error sending auth password: %v" , err) } } else if currentState.GetAuthorizationStateEnum() == tdlib.AuthorizationStateReadyType { fmt.Println("Authorization Ready! Let's rock" ) break } } for update := range client.RawUpdates { fmt.Println(update.Data) fmt.Print("\n\n" ) } }
由于 Telegram 是允许多客户端登陆的(跟我一起喊:微信垃圾、张小龙垃圾 ),所以使用 TDLib 我们可以完全控制我们的账户行为;那么 “东半球最浪漫诗人” 实现就相对简单:
核心代码就这几行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cn := cron.New() _, err = cn.AddFunc(c.String("cron" ), func () { rand.Seed(time.Now().Unix()) name := data[rand.Intn(len (data)-1 )] logger.Infof("update name to [%s]..." , name) _, err := client.SetName(name, "" ) if err != nil { logger.Error(err) } })
效果嘛,就这样: