V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
writesome6
V2EX  ›  分享创造

go 语言实现一个微信机器人

  •  
  •   writesome6 · 2021-04-17 17:05:51 +08:00 · 5705 次点击
    这是一个创建于 1315 天前的主题,其中的信息可能已经有所发展或是发生改变。

    第一步: 我们用 docker 启动一个 web 协议的服务

    可以把这个 docker 服务想像成一个无 UI 的网页版的微信,通过 grpc 暴露出一些自动化 API

    在终端执行以下命令:

    export WECHATY_LOG="verbose"
    export WECHATY_PUPPET="wechaty-puppet-wechat"
    export WECHATY_PUPPET_SERVER_PORT="30001" # 设置启动 web 协议后暴露出来的端口
    export WECHATY_TOKEN="3d415ebb-7a6f-4cba-b602-1f4ae400f891" # 自己生成一串 uuid
    
    docker run -ti \
    --name wechaty_puppet_service_token_gateway \
    --rm \
    -e WECHATY_LOG \
    -e WECHATY_PUPPET \
    -e WECHATY_PUPPET_SERVER_PORT \
    -e WECHATY_TOKEN \
    -p "$WECHATY_PUPPET_SERVER_PORT:$WECHATY_PUPPET_SERVER_PORT" \
    wechaty/wechaty:latest
    

    等待启动成功,会输出一堆日志, 当看到有输出 Online QR Code Image: https://wechaty.js.org/qrcode/xxxx 就说明启动成功了

    07:47:33 VERB PuppetWeChat start() throttleQueue.subscribe() new item: [object Object]
    07:47:33 INFO IoClient [2] https://login.weixin.qq.com/l/xxxxxxx
    Online QR Code Image: https://wechaty.js.org/qrcode/https%3A%2F%2Flogin.weixin.qq.com%2Fl%2F4Yxxxx
    07:47:33 VERB StorageFile save() to /wechaty/3d415ebb-7a6f-4cba-b602-1f4ae400f011.memory-card.json
    

    第二步: 启动 go 写的机器人

    主要使用这个开源包 https://github.com/wechaty/go-wechaty 作为 sdk

    一个简单的机器人已经提前写好了,我们 clone 下来就可以直接跑起来,这个机器人功能很简单,只要接到 ding 的消息就会回复一个 dong

    执行如下命令:

    git clone https://github.com/wechaty/go-wechaty-getting-started.git
    
    cd go-wechaty-getting-started
    
    WECHATY_PUPPET_SERVICE_ENDPOINT=127.0.0.1:30001 make bot
    

    程序跑起来之后,会返回一个微信登录二维码的链接,浏览器打开链接,然后用微信扫码,这样一个机器人就启动起来了

    $ WECHATY_PUPPET_SERVICE_ENDPOINT=127.0.0.1:30001 make bot
    go run examples/ding-dong-bot.go
    2021/04/17 16:05:52 PuppetService Start()
    2021/04/17 16:05:52 PuppetService onGrpcStreamEvent({type:EVENT_TYPE_SCAN payload:{"qrcode":"https://login.weixin.qq.com/l/xxxx","status":2}})
    Scan QR Code to login: ScanStatusWaiting
    https://wechaty.js.org/qrcode/https://login.weixin.qq.com/l/xxxx
    
    2021/04/17 16:08:45 PuppetService onGrpcStreamEvent({type:EVENT_TYPE_SCAN payload:{"qrcode":"https://login.weixin.qq.com/l/xxxx","status":4}})
    Scan QR Code to login: ScanStatusConfirmed
    
    User nickname logined
    
    

    我们用另一个微信向这个微信发送 ding 试下,可以看到机器人很快就回复了 dong

    c4BOI0.jpg

    ding-dong 机器人的核心代码

    package main
    
    import (
    	"fmt"
    	"log"
    	"os"
    	"os/signal"
    	"time"
    
    	"github.com/wechaty/go-wechaty/wechaty"
    	"github.com/wechaty/go-wechaty/wechaty-puppet/schemas"
    	"github.com/wechaty/go-wechaty/wechaty/user"
    )
    
    func main() {
    	var bot = wechaty.NewWechaty()
    
    	bot.OnScan(func(ctx *wechaty.Context, qrCode string, status schemas.ScanStatus, data string) {
    		fmt.Printf("Scan QR Code to login: %v\nhttps://wechaty.js.org/qrcode/%s\n", status, qrCode)
    	}).OnLogin(func(ctx *wechaty.Context, user *user.ContactSelf) {
    		fmt.Printf("User %s logined\n", user.Name())
    	}).OnMessage(onMessage).OnLogout(func(ctx *wechaty.Context, user *user.ContactSelf, reason string) {
    		fmt.Printf("User %s logouted: %s\n", user, reason)
    	})
    
    	var err = bot.Start()
    	if err != nil {
    		panic(err)
    	}
    
    	var quitSig = make(chan os.Signal)
    	signal.Notify(quitSig, os.Interrupt, os.Kill)
    
    	select {
    	case <-quitSig:
    		log.Fatal("exit.by.signal")
    	}
    }
    
    func onMessage(ctx *wechaty.Context, message *user.Message) {
    	log.Println(message)
    
    	if message.Self() {
    		log.Println("Message discarded because its outgoing")
    	}
    
    	if message.Age() > 2*60*time.Second {
    		log.Println("Message discarded because its TOO OLD(than 2 minutes)")
    	}
    
    	if message.Type() != schemas.MessageTypeText || message.Text() != "ding" {
    		log.Println("Message discarded because it does not match 'ding'")
    		return
    	}
    
    	// 1. reply 'dong'
    	_, err := message.Say("dong")
    	if err != nil {
    		log.Println(err)
    		return
    	}
    	log.Println("REPLY: dong")
    }
    

    一些 link

    第 1 条附言  ·  2021-04-17 17:41:00 +08:00

    觉得不错就 star 一波😉😉

    https://github.com/wechaty/go-wechaty

    第 2 条附言  ·  2021-04-17 20:43:49 +08:00
    如果你的账号不能使用微信网页端,不要担心,用这个 docker 起服务,应该是没问题的。
    24 条回复    2021-12-13 10:17:20 +08:00
    selypan
        1
    selypan  
       2021-04-17 17:22:10 +08:00   ❤️ 1
    很 nice,可以做成一个通知机器人,不需要开发服务号,还能做一些简单的运维操作
    hewelzei
        2
    hewelzei  
       2021-04-17 18:00:19 +08:00 via Android
    会被封号吗
    GoLand
        3
    GoLand  
       2021-04-17 18:01:57 +08:00 via iPhone
    这么玩微信号很容易被封,大号做机器人需谨慎。
    labulaka521
        4
    labulaka521  
       2021-04-17 18:22:16 +08:00
    别被封号了,用 tg 不香吗
    akira
        5
    akira  
       2021-04-17 18:24:19 +08:00
    star 已给
    writesome6
        6
    writesome6  
    OP
       2021-04-17 19:49:52 +08:00
    @GoLand 被封应该和自己的使用情况有关吧
    writesome6
        7
    writesome6  
    OP
       2021-04-17 19:50:58 +08:00
    @hewelzei 我的是还没被封😂
    liyaojian
        8
    liyaojian  
       2021-04-17 20:06:03 +08:00 via iPhone
    基于微信 web 弄的?我的号被禁止了 web 端登录
    jinliming2
        9
    jinliming2  
       2021-04-17 20:37:08 +08:00 via iPhone
    慎用,如果被检测到,会永久封禁网页版登录的。
    应该是不会封客户端登录,账号应该还是能正常用的。

    之前基于做过一个机器人,给它发个消息,然后它做一些查询处理之类的,然后回复结果。结果用了不到一个月就被封了,网页版拒绝登录,但是客户端正常。
    writesome6
        10
    writesome6  
    OP
       2021-04-17 20:40:18 +08:00
    可以用这个教程试下,虽然你的账号不能在浏览器里登,但是用这个 docker 应该是可以的
    writesome6
        11
    writesome6  
    OP
       2021-04-17 20:41:10 +08:00
    @liyaojian @liyaojian 可以用这个教程试下😉,虽然你的账号不能在浏览器里登,但是用这个 docker 应该是可以的
    ysicing
        12
    ysicing  
       2021-04-18 10:49:15 +08:00
    需要 WECHATY_PUPPET_SERVICE_TOKEN,然后基于这个 https://github.com/wechaty/wechaty/discussions/1986 貌似不行, `为了你的帐号安全,此微信号已不允许登录网页微信。你可以使用 Windows 微信或 Mac 微信在电脑端登录。Windows 微信下载地址:Mac 微信下载地址:`
    Muninn
        13
    Muninn  
       2021-04-18 11:26:52 +08:00
    加油

    不过这方面微信越来越严

    感觉说不定哪一天努力就都白费
    writesome6
        14
    writesome6  
    OP
       2021-04-18 12:53:43 +08:00
    @ysicing 不要用你提到的链接的教程,就用我这边文章的教程就可以哦
    qfdk
        15
    qfdk  
       2021-04-22 04:37:45 +08:00 via iPhone
    算了还是不给自己找事儿了…… 毕竟 lz 不知道封号的机制
    andych3n
        16
    andych3n  
       2021-04-22 10:16:52 +08:00
    star
    xLuoBo
        17
    xLuoBo  
       2021-04-27 12:04:56 +08:00
    用自己大号抱着玩的心态试了下, 头一天玩的挺开心的, 第二天 如图:

    https://imgtu.com/i/g9ZfbQ
    xLuoBo
        18
    xLuoBo  
       2021-04-27 12:05:39 +08:00
    用自己大号抱着玩的心态试了下, 头一天玩的挺开心的, 第二天 如图:
    writesome6
        19
    writesome6  
    OP
       2021-04-27 12:17:37 +08:00
    @xLuoBo 你做了什么不符合 wx 的事情吗,我的一个打卡机器人用了一年了,毫无问题
    xLuoBo
        20
    xLuoBo  
       2021-04-27 14:50:55 +08:00
    @writesome6 #19 A 号发你好, B 号回 你好呀, 我准备接图灵 B 就封了;

    你不信我今天上 A , 啥也不干, 明天看吧
    writesome6
        21
    writesome6  
    OP
       2021-04-27 16:16:04 +08:00
    @xLuoBo 是不是发送速度太快? 哈哈,你也是够倒霉的,我用的是 windows 协议写的打卡机器人,目前运行一年了,很多群在用,也没有被封
    hahahahahahahah
        22
    hahahahahahahah  
       2021-06-19 17:46:55 +08:00
    支持回复图片跟文件吗,我看 ding-dong 机器人代码中有回复图片的功能,但我取消注释后用不了
    writesome6
        23
    writesome6  
    OP
       2021-06-30 09:41:28 +08:00
    @hahahahahahahah 要看 web 微信是否支持,如果支持就可以
    heybuddy
        24
    heybuddy  
       2021-12-13 10:17:20 +08:00
    @writesome6 老哥,用你这个例子跑了一遍,发现 docker 的 wechaty 运行一个小时的样子会内存溢出挂掉,有什么方法可以解决这个问题吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2822 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 07:09 · PVG 15:09 · LAX 23:09 · JFK 02:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.