Skip to content

Instantly share code, notes, and snippets.

@hex-ci
Last active January 9, 2020 01:18
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save hex-ci/5ecb4b85f5064709580d560c775e906b to your computer and use it in GitHub Desktop.
Save hex-ci/5ecb4b85f5064709580d560c775e906b to your computer and use it in GitHub Desktop.
基于 itchat 的微信机器人例子,支持浏览器登录机器人,支持机器人进程管理,支持热重启
<!DOCTYPE html>
<!-- 请把这个文件放到 templates 目录下 -->
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Wechat</title>
</head>
<body>
{% if alive %}
机器人 {{ bot.storageClass.nickName }} 在线,<a href="/logout">登出</a>
{% else %}
机器人离线,<a href="/login">请登录</a>
{% endif %}
</body>
</html>
<!DOCTYPE html>
<!-- 请把这个文件放到 templates 目录下 -->
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>Wechat login</title>
</head>
<body>
<img style="width:100%;max-width:450px;" src="data:image/png;base64,{{ qr }}">
</body>
</html>
#!/bin/sh
set -e
# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/your/path
DAEMON=$DIR/wechat.py
DAEMON_NAME=wechat
# Add any command line options for your daemon here
DAEMON_OPTS=""
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=user
# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
. /lib/lsb/init-functions
do_start () {
log_daemon_msg "Starting $DAEMON_NAME daemon"
start-stop-daemon --no-close --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS >> "$DIR/output.log" 2>&1
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
restart|reload|force-reload)
do_stop
do_start
;;
status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
;;
*)
echo "Usage: ./service.sh {start|stop|restart|status}"
exit 1
;;
esac
exit 0
#!/usr/bin/env python3
# coding: utf-8
from flask import Flask, render_template, redirect
import itchat
from itchat.content import *
import base64
from threading import Thread # 多线程
from time import sleep
import os, sys, time, io, re
import threading
import logging
import datetime
dir_path = os.path.dirname(os.path.realpath(__file__))
bot = itchat.new_instance()
def auto_add_member(msg, roomName):
friend = bot.search_friends(userName=msg['FromUserName'])
bot.get_chatrooms(update=True)
chatroom = bot.search_chatrooms(roomName)[0]
r = bot.add_member_into_chatroom(chatroom['UserName'], [friend], useInvitation=True)
if r['BaseResponse']['ErrMsg'] == '请求成功':
return ''
else:
return '邀请入群出错,请重试!'
# 普通文本消息,带自动邀请入群
@bot.msg_register(TEXT)
def text_reply(msg):
if '入群' in msg['Text'].lower():
return auto_add_member(msg, '群名称')
return '机器人的回复信息'
# 群消息
@bot.msg_register(TEXT, isGroupChat=True)
def group_reply(msg):
if msg['IsAt']:
return u'@%s\u2005%s' % (msg['ActualNickName'], '圈机器人后,在群里的回复,收到:' + msg['Text'])
# 欢迎新人消息
@bot.msg_register(NOTE, isGroupChat=True)
def note_reply(msg):
try:
new_member_name = re.search(r'邀请"(.+?)"|"(.+?)"通过', msg['Text']).group(1)
except AttributeError:
return
return '\U0001F389 欢迎新人 @{}\u2005!'.format(new_member_name)
# 收到好友邀请自动添加好友
@bot.msg_register(FRIENDS)
def add_friend(msg):
bot.add_friend(msg['RecommendInfo']['UserName'], status=3, verifyContent='自动添加好友成功!')
newer = msg['Text']['autoUpdate']
bot.send_msg('{} 你好!', newer['UserName'])
def uptime(login_timestamp):
if bot.alive:
_uptime = datetime.datetime.now() - login_timestamp
_uptime = str(_uptime).split('.')[0]
return '[UPTIME] {}'.format(_uptime)
# 定时报告 uptime
def report_uptime(remote_admin, login_timestamp):
while True:
time.sleep(600)
remote_admin.send(uptime(login_timestamp))
# 机器人主线程
def wechat_main(login_info):
if not login_info:
isLoggedIn = False
while 1:
waiting_time = 0
while not isLoggedIn:
status = bot.check_login()
waiting_time += 1
if status == '200':
isLoggedIn = True
elif status == '201':
if isLoggedIn is not None:
isLoggedIn = None
elif status != '408':
break
elif waiting_time == 5:
raise
if isLoggedIn:
break
bot.web_init()
bot.show_mobile_login()
bot.get_contact(True)
bot.start_receiving()
bot.dump_login_status(dir_path + '/itchat.pkl')
bot.hotReloadDir = dir_path + '/itchat.pkl'
# 记录登录时间戳
login_timestamp = datetime.datetime.now()
# 这里需要指定管理员昵称
remote_admin = bot.search_friends(nickName='管理员')[0]
remote_admin.send('[START] OK!')
report_thread = Thread(target=report_uptime, daemon=True, args = (remote_admin, login_timestamp, ))
report_thread.start()
bot.run()
# 将二维码转化为base64 string, 简单的使用了全局变量
qr_b64 = ''
def QR_to_b64(uuid, status, qrcode):
global qr_b64
qr_b64 = base64.b64encode(qrcode)
return qr_b64
app = Flask(__name__)
thread = Thread()
@app.route('/')
def index():
return render_template('index.html', alive=bot.alive, bot=bot)
# 生成二维码 登录
@app.route('/login')
def wechat_login():
global thread
if bot.alive:
return redirect('/')
if thread.is_alive():
return render_template('login.html', qr=qr_b64.decode('utf-8'), alive=bot.alive)
bot.useHotReload = True
info = bot.load_login_status(dir_path + '/itchat.pkl')
if not info:
bot.get_QRuuid()
bot.get_QR(qrCallback=QR_to_b64)
thread = Thread(target = wechat_main, daemon=True, args = (info, ))
thread.start()
if info:
return redirect('/')
else:
return render_template('login.html', qr=qr_b64.decode('utf-8'), alive=bot.alive)
# 登出
@app.route('/logout')
def logout():
try:
bot.logout()
return redirect('/')
except Exception as e:
return "Error {0}".format(str(e))
if __name__ == '__main__':
start_info = bot.load_login_status(dir_path + '/itchat.pkl')
if start_info:
thread = Thread(target = wechat_main, daemon=True, args = (start_info, ))
thread.start()
app.run(host='0.0.0.0', port=8080)
@rotimiliu
Copy link

请问如何实现itchat多用户同时扫码登录。

@hex-ci
Copy link
Author

hex-ci commented Jan 23, 2019

@rotimiliu 这个目前我还没搞。。。

@lemonlycat
Copy link

摸摸大

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment