写这玩意的初衷是我所在的某个群搭建了私有的 Mattermost 聊天环境来防御天朝网络环境日益严重的自我审查

程序一共有两个部分, QQ 部分依旧使用的是我们的老朋友Coolq HTTP API 通过 http api 进行发送,通过 Websocket 接受消息推送
Mattermost 部分同样是监听 Websocket 服务器并进行转发
当初写这个脚本时踩了很多关于 Python 多进程和协程的奇怪的坑,下面的代码为啥能正常跑我完全不知道(划掉)

下面是效果

mattermost
qq
以及代码

import re
import os
import json
import html
import time
import urllib
import random
import logging
import requests
import websocket
import threading
import subprocess
import mattermost
import mattermost.ws as mws

qbot_api_event_url = 'ws://河蟹:6700/event/'
qbot_api_post_url = 'http://河蟹:5700/'

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s [%(levelname)s] : %(message)s') 

mattermost_addr = '河蟹'

mattermost_api = mattermost.MMApi('https://' + mattermost_addr + '/api')
status = mattermost_api.token_login('河蟹')
logging.info('login successfully')

REPORT_CHANNEL_ID = '河蟹'
MASTER_GROUP_ID = '河蟹'
BOT_NAME = '@pigeon'
MasterID = ''

websocket.enableTrace(True)

status = mattermost_api.create_post(REPORT_CHANNEL_ID, '复读机正在初始化...')

def qbot_send_msg(user_id, message):
    logging.info("[QQBot] post private message to " + user_id)
    post = qbot_api_post_url + "send_msg"
    api_payload = {
        'user_id': user_id,
        'message': message
    }
    res = requests.post(post, data=api_payload).text
    logging.debug('[QQBot] ' + res)

def qbot_send_gmsg(group_id, message):
    logging.info("[QQBot] post group message to " + group_id)
    post = qbot_api_post_url + "send_group_msg"
    api_payload = {
        'group_id': group_id,
        'message': message
    }
    res = requests.post(post, data = api_payload).text
    logging.debug('[QQBot] ' + res)

qbot_send_gmsg(MASTER_GROUP_ID, '复读机正在初始化...')

def process_cqcode(message_str):
    if not('[CQ' in message_str) :
        return message_str
    start_index = message_str.find('[CQ')
    end_index = message_str[start_index:].find(']') + start_index + 1
    if ('face' in message_str[start_index : end_index]) or ('emoji' in message_str[start_index : end_index]):
        return process_cqcode(message_str[:start_index] + message_str[end_index + 1:])
    if ('image' in message_str[start_index : end_index]):
        if not('url' in message_str[start_index : end_index]):
            return process_cqcode(message_str[:start_index] + '[图片]' + message_str[end_index + 1:])
        image_url = message_str[message_str.find('url=') + 4 : end_index - 1]
        image_str = '![tr](' + image_url + ')'
        return process_cqcode(message_str[:start_index] + image_str + message_str[end_index + 1:])
    if ('at' in message_str[start_index : end_index]):
        at_people = '\n@ ' + message_str[message_str.find('qq=') + 3 : end_index - 1] + '\n'
        return process_cqcode(at_people + message_str[:start_index] + message_str[end_index + 1:])

class mbot_event_posted:

    def __init__(self, source_json):
        self.channel_id = source_json['broadcast']['channel_id']
        self.sender_name = source_json['data']['sender_name']
        strtmp = source_json['data']['post']
        json2 = json.loads(strtmp)
        self.msg = json2['message']

def mattermost_websocket_listen_handler(mmws, event_data):
    if event_data['event'] == 'posted':
        event = mbot_event_posted(event_data)
        if (event.channel_id == REPORT_CHANNEL_ID) and (len(event.msg) != 0) and (event.sender_name != BOT_NAME):
            logging.info('[MMBot] receive a new message from ' + event.sender_name)
            send_msg = ''
            if (event.msg[0] == '!') or (event.msg[0] == '!') or (event.msg[0] == '.') or (event.msg[0] == '%') or (event.msg[0] == '$') :
                send_msg = event.msg
            else :
                send_msg = 'From: ' + event.sender_name + '\n' + event.msg
            qbot_send_gmsg(MASTER_GROUP_ID, send_msg)

def mattermost_websocket_listen():
    logging.info('[MMBot] Now login to mattermost websocket server...')
    mmws = mws.MMws(mattermost_websocket_listen_handler, mattermost_api, 'wss://' + mattermost_addr + '/api/v4/websocket')
    
def shrink(string, length=300):
    string = str(string)
    length_s = len(string)
    if length_s < length:
        return string
    else:
        return '{} <{} more characters> {}'.format(
            string[:50], length_s - length + 100, string[-50:])

class qbot_event:

    def __init__(self, source_json):
        event_json = json.loads(source_json)
        self.post_type = event_json['post_type']
        if event_json['post_type'] == 'message':
            message = event_json
            self.msg_type = message['message_type']
            self.sender = message['sender']['user_id']
            self.nickname = message['sender']['nickname']
            self.nickname_title = message['sender']['title']
            if self.msg_type == 'group':
                self.group_id = message['group_id']
            else:
                self.group_id = 0
            self.msg = message['message']
            if self.sender == MasterID:
                self.is_master = 1
        elif event_json['post_type'] == 'request':
            self.req_type = event_json['request_type']
            self.flag = event_json['flag']

    def process_request(self):
        if self.req_type == 'friend':
            post = qbot_api_post_url + "set_friend_add_request"
        elif self.req_type == 'group':
            post = qbot_api_post_url + "set_group_add_request"

        logging.info("[QQBot] receive a new request!")
        api_payload = {
            'flag': self.flag,
            'approve': True,
            'remark': 'qbot添加好友'
        }
        res = requests.post(post, data=api_payload).text
        logging.debug('[QQBot] ' + res)

    def process_message(self):
        logging.info('[QQBot] receive a new message from ' + 'sender:' + str(self.sender) + ' message:' + self.msg + ' group id:' + str(self.group_id))
        if (str(self.group_id) == MASTER_GROUP_ID):
            message = 'From:' + '[' + self.nickname_title + ']' + self.nickname + '\n' + process_cqcode(str(self.msg))
            status = mattermost_api.create_post(REPORT_CHANNEL_ID, message)
            logging.info('[MMBot] send message to ' + REPORT_CHANNEL_ID)
            logging.debug(str(status))

def qbot_listen_process(event):
    event = qbot_event(event)
    if event.post_type == 'request':
        event.process_request()
    elif event.post_type == 'message':
        event.process_message()


def qbot_listen_on_message(event_ws, event):
    th = threading.Thread(
        target=qbot_listen_process,
        name="NewEvent",
        args=(
            event,
        ))
    th.start()

def qbot_listen_on_error(event_ws, error):
    print(error)

def qbot_listen_on_close(event_ws):
    print("API Websocket closed.")


def qq_websocket_listen():
    websocket.enableTrace(True)
    event_ws = websocket.WebSocketApp(
        qbot_api_event_url,
        on_message=qbot_listen_on_message,
        on_error=qbot_listen_on_error,
        on_close=qbot_listen_on_close
    )
    event_ws.run_forever()

mattermost_websocket_listen()
qq_websocket_listen()