【零基础QQ机器人开发三】程序上云篇

前言:本文为大家带来QQ机器人程序上云的教程,环境搭建请参考下面链接
【0基础QQ机器人开发】基于go-cqhttp的QQ机器人开发教程,仅供自学
【零基础QQ机器人开发二】服务器篇

文章目录

    • 程序
      • Logger类
      • StatuStore类
      • MultiFunc类
      • QQBot类
      • main.py

前言:基础的程序以及windows下的环境配置我们已经在基于go-cqhttp的QQ机器人开发教程中说过了,本次我们使用云服务器中的Linux环境以及python程序来配置
这篇文章是22年写的,可能会有些过时,仅供参考

程序

本程序参考@小锋学长生活大爆炸的程序进行开发。
因为我们的程序是运行在服务器并接通互联网的,所以理论上我们可以把该程序作为一个通入互联网的入口,通过QQ实现所有通过互联网可以实现的功能,比如发送邮件,访问网站等。在这里我们先实现一点简单的功能,以后有了新的创意再更新。

程序结构图如下:
在这里插入图片描述

Logger类

用于输出内容到日志中

class Logger:
    def __init__(self, level='debug'):
        self.level = level

    def DebugLog(self, *args):
        if self.level == 'debug':
            print(*args)

    def TraceLog(self, *args):
        if self.level == 'trace':
            print(*args)

    def setDebugLevel(self, level):
        self.level = level.lower()

StatuStore类

用于存储当前指令的状态,便于处理下一步命令

class StatusStore:
    def __init__(self, from_qq: int = None, is_cmd: bool = False, funcName: str = None, need_second: bool = False, msg: str = None) -> None:
        self.from_qq = from_qq  # 发送者的QQ号
        self.is_cmd = is_cmd  # 是否是指令(选择功能)
        self.funcName = funcName  # 选择的功能的名称
        self.need_second = need_second  # 是否需要经过两步:先发cmd指令,再发详细内容
        self.msg = msg  # 本次发送的消息内容

    def detail(self):
        return self.__dict__

MultiFunc类

保存了相应功能的代码
里面用中文写的参数需要改成自己的

import re
import time
import requests
import json
from github import Github
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.tmt.v20180321 import tmt_client, models

tencent_translate_AppId = 填入appid
tencent_secret_id = '填入id'
tencent_secret_key = '填入key'


class MultiFunc:
    # 翻译功能
    @staticmethod
    def translate(original: str, convert: str = 'en'):
        try:
            cred = credential.Credential(tencent_secret_id, tencent_secret_key)
            client = tmt_client.TmtClient(cred, "ap-guangzhou")
            req = models.TextTranslateRequest()
            params = {
                "SourceText": original,
                "Source": "auto",
                "Target": convert,
                "ProjectId": tencent_translate_AppId
            }
            req.from_json_string(json.dumps(params))
            resp = client.TextTranslate(req)
            return resp.TargetText
        except TencentCloudSDKException as err:
            print(err)

    # 上传图片到图床功能
    @staticmethod
    def uploadImage(imgMsg):
        cmt = '来自QQ'
        timestamp = time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime())
        p = re.compile(r'=(https.+?)]')
        imgUrl = p.findall(imgMsg)
        response = requests.get(url=imgUrl[0])
        token = '这里填入github仓库的token'
        g = Github(token)
        # user = g.get_user()
        # repo = user.create_repo("q_img")
        # 如果是已经存在的仓库,可以使用get_repo来获得repo对象
        repo = g.get_repo('175603a/q_img')
        # 读取文件并上传
        data = response.content
        # 不需要进行Base64编码,编码过程在create_file内部已经完成了
        try:
            repo.create_file(f'{timestamp}.jfif', f'{cmt}', data)
            res = 'https://github.com/175603a/q_img/blob/main/' + f'{timestamp}.jfif?raw=true'
        except:
            repo.create_file(f'{timestamp}.jfif', f'{cmt}', data)
            res = 'https://github.com/175603a/q_img/blob/main/' + f'{timestamp}.jfif?raw=true'
        return res

    # 图片OCR并返回结果
    @staticmethod
    def imageOCR(imgMsg):
        p = re.compile(r'=(.+?.image)')
        imgId = p.findall(imgMsg)
        url = 'http://127.0.0.1:5700/ocr_image'
        data = {
            'image': imgId
        }
        r = requests.post(url=url, data=data)
        content = ''
        for text in json.loads(r.content)['data']['texts']:
            content += text['text'] + '\n'
        return content

    # 监控日志
    @staticmethod
    def monitor_crawler():
        with open('/root/QQBot/go-cqhttp/nohup.out', 'a', encoding='utf-8') as fp:
            res = fp.read()
            fp.write('')
        return res

QQBot类

封装了机器人这个类,里面有收发消息的功能

import urllib.parse
import requests
import urllib.parse
import urllib.request
import socket
import json


class Robot:
    def __init__(self):
        self.msg = ''

    def ai_talk(self):
        msg = self.msg
        def qykApi(msg):
            base_url = 'http://api.qingyunke.com/api.php?key=free&appid=0&'
            data = {
                'msg': msg['raw_message']
            }
            new_data = urllib.parse.urlencode(data)
            url = base_url + new_data
            response = urllib.request.urlopen(url).read().decode('utf-8')
            response_msg = eval(response)['content'].replace('{br}', '\n')
            return response_msg

        if self.msg['message_type'] == 'private':
            return self.sdMsg(qykApi(msg), self.msg['user_id'], 'private')
        else:
            return False

    # ----------------------------------------------------
    # 接收消息函数 需要循环执行,返回值字典格式
    def revMsg(self):  # json or None
        ListenSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        ListenSocket.bind(('localhost', 5701))
        ListenSocket.listen(100)

        HttpResponseHeader = '''HTTP/1.1 200 OK
        Content-Type: text/html
        '''
        Client, Address = ListenSocket.accept()

        def request2json(msg):
            for i in range(len(msg)):
                if msg[i] == "{" and msg[-2] == "}":
                    return json.loads(msg[i:])
            return None

        try:
            Request = Client.recv(1024).decode(encoding='utf-8')
            rev_json = request2json(Request)
            Client.sendall(HttpResponseHeader.encode(encoding='utf-8'))
            Client.close()
            self.msg = rev_json
        except:
            pass
        return rev_json

    def sdMsg(self, msg, qq_id, msg_type):
        if msg_type == "private":
            data = {
                'user_id': qq_id,
                'message': msg,
                'auto_escape': False
            }
            cq_url = "http://127.0.0.1:5700/send_private_msg"
            rev = requests.post(cq_url, data=data)
        elif msg_type == "group":
            data = {
                'group_id': qq_id,
                'message': msg,
                'auto_escape': False
            }
            cq_url = "http://127.0.0.1:5700/send_group_msg"
            rev = requests.post(cq_url, data=data)
        else:
            return False
        if rev.json()['status'] == 'ok':
            return True
        return False

main.py

from MultiFunc import MultiFunc
from QQBot import Robot
from Logger import Logger
from StatuStore import StatusStore
import threading
import random
import re
import requests
import ddddocr
import time

CONTROQID = 这里填入控制机器人的QQ

if __name__ == '__main__':
    logger = Logger()
    status_store = {}

    logger.DebugLog('====================开始运行========================')
    function_map = {
        '翻译': {'function': MultiFunc.translate, 'need_second': True, 'desc': '请输入您要翻译的内容~'},
        '上传图片': {'function': MultiFunc.uploadImage, 'need_second': True, 'desc': '请发送图片过来吧~'},
        'ocr': {'function': MultiFunc.imageOCR, 'need_second': True, 'desc': '请发送图片过来吧~'},
        '监控日志': {'function': MultiFunc.monitor_crawler, 'need_second': False}
    }


    def choiceFunction(store_obj: StatusStore):
        res = ''
        if function_map.get(store_obj.funcName):
            res = function_map.get(store_obj.funcName)['function'](store_obj.msg)
        return res



    bot = Robot()  # 实例化

    while True:
        bot.revMsg()
        if bot.msg['user_id'] == CONTROQID and bot.msg['message_type'] == 'private':
            if bot.msg['message'].strip().lower().startswith('cmd'):
                try:
                    funcName = bot.msg['message'].strip().split('\n')[0].split()[1]
                    store_obj = StatusStore(from_qq=CONTROQID, is_cmd=True, funcName=funcName)
                    func_info = function_map.get(funcName)
                    if not func_info:
                        res = '指令[{}]暂不支持'.format(funcName)
                    elif func_info.get('need_second'):
                        res = '收到你的指令:{}\n{}'.format(funcName, func_info.get(
                            'desc') or '已进入对应状态, 请继续发送详细内容')
                        # 添加或更新记录
                        status_store[CONTROQID] = store_obj
                    else:
                        res = '请求结果为:\n' + str(choiceFunction(store_obj))
                        status_store.pop(CONTROQID, '')
                except:
                    res = 'cmd与命令之间请加空格'
            else:
                res = '请先发送指令哦...'
                store_obj = status_store.get(CONTROQID)
                if store_obj and store_obj.is_cmd:
                    store_obj.msg = bot.msg['message']
                    res = '请求结果为:\n' + str(choiceFunction(store_obj))
                    status_store.pop(CONTROQID, '')
        elif bot.msg['message_type'] == 'private':
            res = bot.ai_talk()
        elif bot.msg['message_type'] == 'group':
            continue
        else:
            continue

        bot.sdMsg(res, bot.msg['user_id'], 'private')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/19870.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高级Web题库

高级Web题库 For ZPT 声明 一切开发旨在学习,请勿用于非法用途 by rick rick 关注 永雏塔菲喵 永雏塔菲喵 选择题 第1题 知识点:CSS 题目:设置text-decoration属性的删除线的值为( )。 选项: A underlin…

Pytest自动化测试框架一些常见的插件

Pytest拥有丰富的插件架构,超过800个以上的外部插件和活跃的社区,在PyPI项目中以“ pytest- *”为标识。 本篇将列举github标星超过两百的一些插件进行实战演示。 插件库地址:http://plugincompat.herokuapp.com/ 1、pytest-html&#xff…

冗余-安全设计的基石

冗余构成原理就是在系统中采用2套中央处理器(CPU)单元,其中1套为工作主机,1套为热备,一旦工作主机发生故障,热备的CPU将自动投入工作,此时热备的CPU变为工作主机,原工作主机故障处理…

a标签属性href的多种写法

众所周知,a标签的最重要功能是实现超链接和锚点。而且,大多数人认为a标签最重要的作用是实现超链接,其实不单单是实现超链接的方法,今天新起点博客就来整理下a标签中href的几种用法。 1、a href“[removed]js_method();” 这是常用…

Android aidl及binder基础知识巩固

作者:义华 1、什么是binder binder是android framework提供的,用于跨进程方法调用的机制,具有安全高效等特点。 我们知道,在 Android 系统中,每个应用程序都运行在一个独立的进程中,各个进程之间需要进行…

chatGPT提问,BGP内容

ChatGPT提问:提问框架 背景角色任务要求 动态路由:内部网关协议:如RIP ISIS OSPF 在同一个公司内部运行的路由协议 外部网关协议:如 BGP 在不同公司之间运行的路由协议 AS:自治系统 每个自治系统都有唯一的…

玩机搞机-----安卓全机型 ADB FAST 各种指令解析说明与操作【二】基础联机

安卓全机型 玩机 搞机 ADB FAST 各种指令解析说明与操作_adb线刷命令_安卓机器的博客-CSDN博客 今天对上个帖子不足的地方进行补正。方便友友进行基础的联机操作,很多时候我们用adb指令的时候会有各种奇奇怪怪的问题。例如同一个机型,同一个指令。有时候…

OpenCL编程指南-4.4矢量操作符

矢量操作符 如下描述了可用于矢量数据类型或矢量和标量数据类型组合的各类操作符。 算术操作符 算术操作符(加()、减(–)、乘(*)和除(/)),可以作用于内置整数、浮点标量和矢量数…

AWS 中的另外一种远程工具 AWS Session Manager

作者:SRE运维博客 博客地址:https://www.cnsre.cn/ 文章地址:https://www.cnsre.cn/posts/230129126154/ 相关话题:https://www.cnsre.cn/tags/aws/ 背景需求 因为项目的安全性。为了避免项目的服务器暴露在公网中。很多时候我们…

Python时间模块:time和datetime的区别与用法

前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 目录标题 前言一. Python中表示时间的两种方式:二. time三. datetime1. datetime.datetime2.datetime.timedelta 尾语 💝 一. Python中表示时间的两种方式: 时间戳:相对于197…

OpenCL编程指南-3.2OpenCL上下文

OpenCL上下文 上下文是所有OpenCL应用的核心。上下文为关联的设备、内存对象(例如,缓冲区和图像)以及命令队列(在上下文和各设备之间提供一个接口)提供了一个容器。正是上下文驱动着应用程序与特定设备以及特定设备之…

Echarts 热力图的详细配置过程

文章目录 一&#xff0c;配置过程二&#xff0c;具体实例 一&#xff0c;配置过程 引入Echarts库和热力图插件 <script src"https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> <script src"https://cdn.jsdelivr.net/npm/…

实时聊天如何做,让客户眼前一亮(二)

让我们继续讨论一下如何利用SaleSmartly&#xff08;ss客服&#xff09;在网站中的实时聊天视图如何提供出色的实时聊天体验。 四、在实时聊天会话期间 让我们来看看我们可以确保尽可能的提高客户体验的各种方法&#xff0c;使用SaleSmartly&#xff08;ss客服&#xff09;时聊…

算法设计 || 第5题:钓鱼问题-北京大学网站在线算法题(贪心算法)

目录 &#xff08;一&#xff09;题目网址视频网址 &#xff08;二&#xff09;手写草稿思考 Part1: 慕课PPT Part2: 笨蛋的学习 &#xff08;一&#xff09;题目网址视频网址 北京大学网站在线算法题&#xff1a;1042 -- Gone Fishing (poj.org) 视频讲解&#xff08;北…

MYSQL基本操作

数据库的列类型 int&#xff1a;整型 用于定义整数类型的数据 float&#xff1a;单精度浮点4字节32位 准确表示到小数点后六位 double&#xff1a;双精度浮点8字节64位 char&#xff1a;固定长度的字符类 用于定义字符类型数据&#xff0c;固定10字节&#xff0c;如果你设定5字…

(转载)从0开始学matlab(第1天)—变量和数组

MATLAB 程序的基本数据单元是数组。一个数组是以行和列组织起来的数据集合&#xff0c;并且拥有一个数组名。数组中的单个数据是可以被访问的&#xff0c;访问的方法是数组名后带一个括号&#xff0c;括号内是这个数据所对应行标和列标。标量在 MATLAB 中也被当作数组来处理——…

实在智能与浙江工商大学官宣战略合作,共建人工智能联合实验室和实习基地

5月10日&#xff0c;实在智能与浙江工商大学正式官宣战略合作&#xff0c;并进行“人工智能联合实验室” “大学生实习实践基地”揭牌仪式。躬身入局共筑人工智能人才生态&#xff0c;这是实在智能和浙江工商大学的共同愿景&#xff0c;也是校企双方深度产学研融合、加速科技型…

【蓝桥杯国赛真题26】Scratch队列练习 少儿编程scratch图形化编程 蓝桥杯省赛真题讲解

目录 scratch队列练习 一、题目要求 编程实现 二、案例分析 1、角色分析

【Linux】进程信号(中)

在上一个文章中&#xff0c;关于信号的产生&#xff0c;还有没补充完的&#xff0c;所以在这篇文章补充一下 文章目录 1.信号的产生硬件异常产生信号a/0问题验证为8号信号 野指针问题验证为11号信号 核心转储设置核心转储大小Core与Term的区别核心转储的作用 2.信号保存1. 概念…

np读取txt、csv文件的数据

目录 1、基础参数 2、参数详解 3、应用参数示例 机器学习中使用np.loadtxt()可以高效的导入数据&#xff0c;np.loadtxt()适合.txt文件和.csv文件。但是它默认读取float类型的值。 1、基础参数 numpy.loadtxt(fname, dtype, comments#, delimiterNone, convertersNone, s…