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

news/2024/11/7 1:29:20/

前言:本文为大家带来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 = leveldef 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, modelstencent_translate_AppId = 填入appid
tencent_secret_id = '填入id'
tencent_secret_key = '填入key'class MultiFunc:# 翻译功能@staticmethoddef 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.TargetTextexcept TencentCloudSDKException as err:print(err)# 上传图片到图床功能@staticmethoddef 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并返回结果@staticmethoddef 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# 监控日志@staticmethoddef 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 jsonclass Robot:def __init__(self):self.msg = ''def ai_talk(self):msg = self.msgdef 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_dataresponse = urllib.request.urlopen(url).read().decode('utf-8')response_msg = eval(response)['content'].replace('{br}', '\n')return response_msgif self.msg['message_type'] == 'private':return self.sdMsg(qykApi(msg), self.msg['user_id'], 'private')else:return False# ----------------------------------------------------# 接收消息函数 需要循环执行,返回值字典格式def revMsg(self):  # json or NoneListenSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)ListenSocket.bind(('localhost', 5701))ListenSocket.listen(100)HttpResponseHeader = '''HTTP/1.1 200 OKContent-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 Nonetry:Request = Client.recv(1024).decode(encoding='utf-8')rev_json = request2json(Request)Client.sendall(HttpResponseHeader.encode(encoding='utf-8'))Client.close()self.msg = rev_jsonexcept:passreturn rev_jsondef 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 Falseif rev.json()['status'] == 'ok':return Truereturn 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 timeCONTROQID = 这里填入控制机器人的QQif __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 resbot = 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_objelse: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':continueelse:continuebot.sdMsg(res, bot.msg['user_id'], 'private')

http://www.ppmy.cn/news/68040.html

相关文章

灾难恢复:支持业务连续性的策略——保证员工和客户始终可以访问关键数据和应用程序

灾难恢复:支持业务连续性的策略 保证员工和客户始终可以访问关键数据和应用程序。 为什么选择 NetApp 的业务连续性和灾难恢复解决方案? 保持弹性,自如操作 NetApp 就在您身边,在这样一个跌宕起伏的时期竭诚帮助您实现业务连续性…

1064 Complete Binary Search Tree(19行代码+详细注释)

分数 30 全屏浏览题目 作者 CHEN, Yue 单位 浙江大学 A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The left subtree of a node contains only nodes with keys less than the nodes key.The right subtree…

【pandas的dataframe过滤数据方法】

选取某一列中大于某个值的行&#xff1a; df[df[column_name] > value]选取某一列中满足多个条件的行&#xff1a; df[(df[column_name] > value1) & (df[column_name] < value2)]选取某一列中不等于某个值的行&#xff1a; df[df[column_name] ! value]选取某…

linux环境安装使用tomcat详解

01-安装Tomcat # 0.下载tomcat http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.46/bin/apache-tomcat-8.5.46.tar.gz # 1.通过工具上传到Linux系统中 # 2.解压缩到/usr目录中 [rootlocalhost ~]# tar -zxvf apache-tomcat-8.5.46.tar.gz -C /usr/ -C 用来指…

Android Studio中android: baselineAligned属性认识及用途

文章目录 使用Button控件来演示使用TextView控件来演示 android:baselineAligned 设置子元素都按照基线对齐&#xff0c;默认是true 使用Button控件来演示 在项目中经常使用layout_weight属性利用比重来设置控件的大小&#xff0c;代码如下&#xff1a; <?xml version&qu…

涉及lvm分区的命令使用

pv命令 pvdisplay #查看物理卷 pvcreate 分区路径 #创建物理卷 pvremove 分区路径 #删除物理卷 vg命令 vgdisplay #查看卷组 vgcreate 卷组名称 #创建卷组 vgextend 卷组名称 分区路径 #将分区加入某个卷组 vgremove 卷组名称 #删…

【文本三剑客】AWK

AWK 一、AWK的工作原理1.1命令格式1.2awk常见的内建变量 二、awk实验2.1按行输入文本2.2按字段输出文本2.3通过管道符、双引号调用shell命令 一、AWK的工作原理 逐行读取文本&#xff0c;默认以空格或tab键为分隔符进行分隔&#xff0c;将分隔所得的各个字段保存到内建变量中&…

python队列

简介 使用队列方法进行多线程之间的信息交互 队列 队列 First in First out可以存储不同的数据类型&#xff0c;例如整数、字符串、字典使用put放数据使用get取数据&#xff08;如果当前队列中没有数据&#xff0c;此时会堵塞&#xff09; import queueq queue.Queue() q.…