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

news2024/11/19 5:38:13

前言:本文为大家带来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')

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AP3266 DC-DC大功率同步降压恒流芯片 过EMC三级 摩托电动汽车灯IC

1,产品描述 AP3266 是高效率、外围简单、内置功率管的同步降压恒流芯片,适用于4-40V输入的降压LED恒流驱动芯片。输出功率可达 40W,电流3.6A。AP3266 可通过调节 OVP 端口的分压电阻,设定输出空载电压 保护,避免高压 空…

DenseNet与ResNet

ResNet(深度残差网络) 深度残差网络 DenseNet 采用密集连接机制,即互相连接所有的层,每个层都会与前面所有层在channel维度上连接在一起,实现特征重用,作为下一层的输入。 这样不但缓解了梯度消失的现象…

2023数维杯数学建模ABC题思路分析

占个位置吧,开始在本帖实时更新数维杯数学建模赛题思路代码,文章末尾获取! 持续为更新参考思路 赛题思路 已完成全部可以领取,详情看文末!!! 数维杯A题思路 A题是这次比赛比较难的题目&…

AI落地:如何用AI做出可用的PPT?

ChatGPT问世以来,很多工具都有了AI版。原来让我们头疼的PPT,这不现在也能一键生成了。 看了网友分享的各种一键生成PPT技术,真是牛。 很快没错,但是。。。缺点你是一句不提啊。 PPT做成这样,这要是直接用&#xff0c…

【MATLAB图像处理实用案例详解(8)】—— 图像数字水印算法

目录 一、背景意义二、基本原理三、算法介绍3.1 数字水印嵌入3.2 数字水印提取 四、程序实现 一、背景意义 数字水印技术作为信息隐藏技术的一个重要分支,是将信息(水印)隐藏于数字图像、视频、音频及文本文档等数字媒体中,从而实现隐秘传输、存储、标注…

基于等照度线和窗口匹配的图像修补算法

作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 一、关于图像修补 图像修补的目的是基于已有的图像信息或数据库内信息,对缺失区域进行合理地修复。在诸多领域如电影、…

35个开源的工业软件-工业4.0

不同的工业流程,需要不同的工业软件。面向研发设计环节的开源软件,今天就来介绍一下面向生产控制环节的开源软件,主要为可编程逻辑控制器(PLC)、分布式控制系统(DCS)、生产执行系统(MES&#xf…

以“阵地战”打法,多样性算力攻坚数字经济基础设施

作者 | 曾响铃 文 | 响铃说 人人都知道数字化转型进入深水区后,对算力的渴求在不断增长。 包括政务、能源、金融、制造业等领域的数字化转型铆足了劲头,不断向那些数字基础设施索要源源不断的算力。 但是,更应该注意到的是,在…

Debian 12 “Bookworm” 的新特性和发布日期

导读Debian 12 即将发布。了解一下更多关于其新特性和发布日期的相关信息。 debian 12 Debian 即将发布系统代号为 “书虫” 的新版本。与 Debian 11 “Bullseye” 相比,有许多改进和新功能。 Debian 12 “Bookworm” 包含了超过 11200 个新软件包,软件…

泰克RSA306B频谱分析仪测试信道功率方法

泰克RSA306B实时频谱分析仪是一种用于无线信号分析的仪器。它可以实时监控无线信号的频谱,帮助用户分析信号特征,掌握信号的功率、频率、调制等关键信息。在无线通信中,信道功率是一个非常重要的指标,它反映了信号在传输过程中的强…

基于matlab使用广义互相关和三角测量来确定宽带信号源的位置

一、前言 此示例说明如何使用广义互相关 (GCC) 和三角测量来确定宽带信号源的位置。为简单起见,此示例仅限于由一个源和两个接收传感器阵列组成的二维方案。您可以将此方法扩展到两个以上的传感器或传感器阵列以及三维。 二、介绍 源定位不同…

速锐得工业物联网技术无线自动化解决方案在物流业的应用

物流业一直走在工业物联网的最前沿,因为许多工业物联网的机会和技术与物流业完美匹配。因此,物流业多年依赖一直使用许多工业物联网相关的传感器和技术。 例如,多年来,物流业一直在包装、托盘和集装箱中使用条形码,从9…

Redis(18. 面试题简析)学习笔记

上一篇 :17. Redis 分布式锁 - 周阳 下一篇 :18. 面试题简析 文章目录 1. 为什么要用缓存?2. redis 和 memcached 有什么区别?3. redis 的线程模型4. 为啥 redis 单线程模型也能效率这么高?5. redis 都有哪些数据类型…

CodeArts持续发力输出,华为云重塑软件开发

配图来自Canva可画 互联网时代,软件技术对企业成功的助益越来越明显。不管是为了顺遂大众趋势,还是迫于生存压力,可以确定的是,目前各类软件的开发已经被纳入众多企业的发展规划当中。 只是,长期以来国内软件行业一直…

机器学习回归任务指标评价及Sklearn神经网络模型评价实践

机器学习回归模型评价是指对回归模型的性能进行评估,以便选择最佳的回归模型。其中,MAE、MSE、RMSE 用于衡量模型预测值与真实值之间的误差大小,R 用于衡量模型对数据的拟合程度。在实际应用中,我们可以使用这些指标来评估回归模型…

git 撤销中间某次提交,保留其他提交的方法

今天上班脑抽了,吧test直接合到了uat,因为项目近期就我一个人开发,自己拉个三个分支再改不同的东西,最后都是发到test分支发测试,发生产的时候一个个和嫌麻烦,直接吧test分支怼到了uat,结果生产就出问题了&…

Revit插件 | 精装模块15个新功能正式上线,快来体验

大家好,这里是建模助手。 建模助手建模、算量、出图,一站搞定的——精装模块,正式上线了! 简单来说,精装模块就是辅助用户快速搭建精装修模型,便于后续的模型渲染、出量、出图工作。 目前暂时上线15个功能&#xff0…

ShardingSphere数据分片、读写分离、数据屏蔽教程

本文不讨论框架实现原理以及源码分析,只做功能使用案例说明 数据分片: 表分片可以帮助评论应用程序更有效地管理其不断增长的评论表,提高性能和可扩展性,同时还使备份和维护任务更易于管理 Apache ShardingSphere 有两种形式&am…

公众号推文添加附件秀米添加附件?三步轻松实现

很多人都不知道,其实公众号文章正文是支持添加附件的,只是需要借助一个叫做“文章附件”的网站来实现。公众号自身是不支持直接上传文件的,但是我们可以通过另外的方式来实现。 其实原理很简单,公众号文章中是可以添加小程序链接…

AOP(小卡拉米!!!)温故!

前面我们说了AOP底层是使用代理模式进行实现,spring写的接口是通过代理反射,实现方法,然后定义切入点: springAOP接口定义的方法有:被加强的方法前执行,被加强的方法后执行,出错了执行&#xf…