PC端从零搭建微信自动回复机器人(一)基础框架搭建及源码

news2024/11/18 16:49:02

由于工作需要,最近一年一直在研究和使用C#,加上最近工作上有做微信机器人的需要,在已经对接、调试稳定之后,将项目的源码分享给大家,传递开源精神。

一、环境依赖

1、开发工具:Vistual Studio 2022
2、NetFramework版本:6.0及以上
3、微信版本:WeChatSetup_3.7.0.30.exe (找不到可以私信我)

二、支持功能

目前该组件自身支持很多功能,如下所示:

  • 获取通讯录
  • 获取所有群成员基础信息(含wxid,群昵称,微信昵称)
  • 发送文本、图片、文件、xml文章、名片、群艾特消息
  • 根据wxid查询好友信息
  • 根据群ID获取所有群成员WXID / 同时获取一个微信群内所有成员的群昵称
  • 检测好友状态(是否好友、被删除、被拉黑)
  • 接收各类消息,可写回调函数进行处理
  • 群管理
  • 微信多开
  • 自动合并短的文本、艾特信息(可设定单条信息最大长度)
  • 自动分割过长的单条信息

在这些功能的基础上我们可以结合自身的使用场景进行定制化开发和调用。目前我主要根据群聊中@和私聊这两个场景进行一些封装,我将代码进行了删减,仅保留基础部分。

三、项目结构及如何运行

1、项目结构

项目整体有三个部分构成。如下图所示:
在这里插入图片描述
ConsoleApp1用于自定义逻辑和启动类都写在中。–自行创建
RS.Snail.JJJ.Wechat是底层依赖组件。–可参考我上传的附件
Segments是自带中文分词器的一个组件,用于对用户问题与问题列表进行分词匹配。–下篇文章详解

2、自定义逻辑实现

启动类实现代码 Program.cs 代码如下

// See https://aka.ms/new-console-template for more information
using ConsoleApp1;
using Newtonsoft.Json.Linq;
using RS.Snail.JJJ.Wechat;
using static ConsoleApp1.MessageHandler;

Console.WriteLine("Hello, World!");
var wechat = new RS.Snail.JJJ.Wechat.Service();
String mSelf_WXID = "wxid_m2khoia398xh22";//登录
bool v = wechat.Init(
                    // new List<string> { "wxid_1234_" },
                    new List<string> { mSelf_WXID },
                    new Func<dynamic, Task>((msg) => {

                        Console.Write(msg);
   

                                          ;
                        //CDATA[,wxid_8qfg0x0do56t22
                        MessageParam mMessageParam = new MessageParam(mSelf_WXID,wechat, (JObject)msg);         
                       
                        if (mMessageParam.isAtSelf())//判断是否是群聊@微信机器人
                        {
                            List<String> atPersons = mMessageParam.getAtList();
                            String mTemp = ((JObject)msg).GetValue("message").ToString();
                            foreach (String mItem in atPersons) {
                                String mOld = "@" + wechat.ChatroomGetMemberNick(mSelf_WXID, ((JObject)msg).GetValue("sender").ToString(), mItem);
                                mTemp = mTemp.Replace("@微信客服", "").Trim();//注意,这里需要与自身微信昵称保持一致
                            }
                            ThreadParam mThreadParam = new ThreadParam() {
                                ObjParam = wechat,Msg=msg, MTemp=mTemp, Self_WXID=mSelf_WXID
                            };
                          
                            new Thread(new ParameterizedThreadStart((Obj) =>
                            {
                                new MessageHandler().sendAnswer((ThreadParam)Obj);

                            })).Start(mThreadParam);

                        }
                        else {
                            String mTemp = ((JObject)msg).GetValue("message").ToString();
                         
                                List<String> atPersons = mMessageParam.getAtList();
                                ThreadParam mThreadParam = new ThreadParam()
                                {
                                    ObjParam = wechat,
                                    Msg = msg,
                                    MTemp = mTemp,
                                    Self_WXID = mSelf_WXID
                                };
                                new Thread(new ParameterizedThreadStart((Obj) =>
                                {
                                    new MessageHandler().transferAnser((ThreadParam)Obj);

                                })).Start(mThreadParam);
                        }
               
                        return new Task(new Action(() => {
                                                   }));
                    
                    })


                    //msg =>  Console.Write(msg)
                    ) ;
//图片保存钩子
//wechat.MsgStartImageHook(mSelf_WXID, "D:\\image");


wechat.StartReceive();
Console.ReadKey();
Console.ReadKey();
Console.ReadKey();
Console.ReadKey();
Console.ReadKey();
Console.ReadKey();
Console.ReadKey();
Console.ReadKey();
Console.ReadKey();

自定义问答逻辑类MessageParam.cs 代码如下:


using JiebaNet.Segmenter.PosSeg;
using Newtonsoft.Json.Linq;
using RS.Snail.JJJ.Wechat;
using System.Diagnostics;
using System.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Segments;

namespace ConsoleApp1
{

    public class MessageParam
    {
        private RS.Snail.JJJ.Wechat.Service wechat;
        private JObject msg;
        private String self_WXID;
        public Service Wechat { get => wechat; set => wechat = value; }
        public JObject Msg { get => msg; set => msg = value; }
        public string Self_WXID { get => self_WXID; set => self_WXID = value; }

        public MessageParam(String self_WXID, RS.Snail.JJJ.Wechat.Service wechat, JObject msg) {
          this.self_WXID = self_WXID;
          this.wechat= wechat;
          this.msg = msg;
        }

        public bool isAtSelf() {
            String mextrainfo = ((JObject)msg).GetValue("message").ToString();
            if (mextrainfo.Contains("@微信客服"))//注意,这里需要与自身微信昵称保持一致
            {
                return true;
            }
            else {
                return false;
            }
        }

        public List<String> getAtList() {
            String mextrainfo = ((JObject)msg).GetValue("extrainfo").ToString();
            List<String> mStrs = new List<String>();
            try
            {
                mStrs = mextrainfo.Split(new String[] { "<atuserlist><![CDATA[", "]]></atuserlist>" }, StringSplitOptions.None)[1].Split(",").ToList();
            }
            catch (Exception ex) {
                mStrs = new List<String>();
            }

            try
            {
                if (mStrs.Count == 0) {
                    mStrs = mextrainfo.Split(new String[] { "<atuserlist>", "</atuserlist>" }, StringSplitOptions.None)[1].Split(",").ToList();
                }
               
            }
            catch (Exception ex)
            {
                mStrs = new List<String>();
            }

           
            return mStrs;
        }

    }
    public  class MessageHandler
    {
        public void sendAnswer(ThreadParam mThreadParam)
        {

            Object Obj = mThreadParam.ObjParam;
            String mSelf_WXID = mThreadParam.Self_WXID;
            Object msg = mThreadParam.Msg;
            String mTemp = mThreadParam.MTemp.Replace("@智能客服", "").Trim();//注意,这里需要与自身微信昵称保持一致
            String roomName = getChatRoomName(mSelf_WXID, Obj, msg);
            String roomId = ((JObject)msg).GetValue("sender").ToString();
            Service wechat = (Service)Obj;
            String sendStr = "";
            String similarity = "1";
         if (mTemp.Equals("智能客服")|| mTemp.Trim().Equals(""))
            {
                sendStr = "@" + wechat.ChatroomGetMemberNick(mSelf_WXID, ((JObject)msg).GetValue("sender").ToString(),
                                                                 ((JObject)msg).GetValue("wxid").ToString()) + "您好,我是微信客服。有什么问题可以直接向我提问哦~ 提问方式请参考下方模板\r\n【常见问题搜索】请输入报错码/错误关键字,例如:96000322/系统异常,请您稍后再试\r\n";
                ((Service)Obj).MsgSendAt(
                                                                 mSelf_WXID,
                                                                 ((JObject)msg).GetValue("sender").ToString(),
                                                                 new List<string> { ((JObject)msg).GetValue("wxid").ToString() },
                                                                 sendStr, false);
            }else
            {

            //调用分词匹配进行初筛
            List<JObject> resList = Segments.Segments.selectQuestion(mTemp,CommonUtils.parseErrorList());
            similarity = resList.Count.ToString();
            //调用搜索接口
            //List<JObject> resList = CommonUtils.QueryMsg(mTemp);
            if (resList.Count == 0)//未查询到答案信息
            {
                sendStr = "@" + wechat.ChatroomGetMemberNick(mSelf_WXID, ((JObject)msg).GetValue("sender").ToString(),
                                                  ((JObject)msg).GetValue("wxid").ToString()) + " 您发送了:" + mTemp + ",未找到相应答案,请用报错码/报错信息直接进行提问。或者@群内技术推广老师进行咨询";
                ((Service)Obj).MsgSendAt(
                                                  mSelf_WXID,
                                                  ((JObject)msg).GetValue("sender").ToString(),
                                                  new List<string> { ((JObject)msg).GetValue("wxid").ToString() },
                                                  sendStr, false);
             
            }
            else
            {
               
                StringBuilder sb = new StringBuilder();
                sb.AppendLine( " 您发送了:" + mTemp + ",为您匹配到了:" + resList.Count + "条解答,详情如下:");
                List<JObject> imgList = new List<JObject>();
                for (int i = 0; i < resList.Count; i++)
                {
                    String errorDetail = resList[i]["errorDetail"].ToString();
                    String isImg = resList[i]["isImg"].ToString();
                    String errorType = CommonUtils.getErrorType(resList[i]["errorType"].ToString());

                    //如果isImg为1,则下载并发送图片
                    if (isImg.Equals("1"))
                    {
                        imgList.Add(resList[i]);
                    }
                    else
                    {
                        String solution = resList[i]["errorSolution"].ToString();
                        String errorCode = resList[i]["errorCode"].ToString();
                        sb.AppendLine("错误码:"+errorCode);
                        sb.AppendLine("错误类型:"+ errorType);
                        sb.AppendLine("错误描述:"+ errorDetail);
                        sb.AppendLine("解决方案:"+ solution);
                        sb.AppendLine("=====================");
                    }
                }
                sendStr = "@" + wechat.ChatroomGetMemberNick(mSelf_WXID, ((JObject)msg).GetValue("sender").ToString(),
                        ((JObject)msg).GetValue("wxid").ToString()) + sb.ToString();
                 ((Service)Obj).MsgSendAt(
                        mSelf_WXID,
                        ((JObject)msg).GetValue("sender").ToString(),
                        new List<string> { ((JObject)msg).GetValue("wxid").ToString() },
                       sendStr, false);

            }
            }

        }


        //   查询群名称
        public String getChatRoomName(String mSelf_WXID,Object Obj,Object msg)
        {
            //获取数据库句柄
            JArray obj = ((Service)Obj).DatabaseGetHandles(mSelf_WXID);
            //查询群名称
            String sql = "select NickName from Contact where UserName = '" + ((JObject)msg).GetValue("sender").ToString() + "'";
            JObject first = obj.First() as JObject;
            obj = ((Service)Obj).DatabaseQuery(mSelf_WXID, (uint)first["handle"], sql);
            return obj[1][0].ToString();
        }

        public void transferAnser(ThreadParam mThreadParam)
        {
           //自定义逻辑            
        }
     }

    public class ThreadParam {
        Object mObj; 
        String self_WXID;
        Object msg;
        String mTemp;

        public object ObjParam { get => mObj; set => mObj = value; }
        public string Self_WXID { get => self_WXID; set => self_WXID = value; }
        public object Msg { get => msg; set => msg = value; }
        public string MTemp { get => mTemp; set => mTemp = value; }
    }

}

CommonUtils.cs由于都是一些发送http请求的方法,就不放源码了,大家自行实现。

3、项目启动演示

首先需要配置启动项,我们需要将ConsoleApp1配置为启动项。
在这里插入图片描述
启动项目后会自动打开一个控制台,同时唤醒微信客户端。在这里插入图片描述
需要扫码登录后,在控制台中输入大写的Y,即可完成登录。
这里由于我的微信自动升级了版本,就不演示了。
当你在群聊中@微信机器人时,就会按照代码中的实现逻辑自动回复你了。这其中的语料库可以自己通过查库,本地读取,或者直接接入目前主流的各类大语言模型(chatGPT,文心一言,通义千问,科大星火等等),发挥自己的想象力,尽情的尝试吧。
在这里插入图片描述

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

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

相关文章

【FFmpeg视频解码】解码数据结构及函数总结

转载自原文地址&#xff1a;https://www.cnblogs.com/wangguchangqing/p/5744941.html 本文的总结分为以下两个部分&#xff1a; 数据读取&#xff0c;主要关注在解码过程中所用到的FFmpeg中的结构体。解码过程中所调用的函数 在学习的过程主要参考的是dranger tutorial&…

从零开始搭建博客网站-----源代码试部署

拿到了该项目的源码&#xff0c;先尝试是否可以成功部署&#xff0c;详细的部署视频地址 后端项目部署 先把maven配置好&#xff0c;都改成自己下载的maven地址 文件编码改成utf-8&#xff0c;防止配置文件乱码 如果maven是刚下的&#xff0c;要改一下下载包的地址&#xff0…

使用信息面板沟通研发工作

凌鲨里面的内容面板里面有专门针对研发团队的白板功能&#xff0c;它可以把文档&#xff0c;图片&#xff0c;软件设计&#xff0c;需求&#xff0c;任务/缺陷等相关研发要素串接起来。 使用 你还可以调整背景颜色。 引用项目内数据 点击面板中的连接会在右侧打开对应内容

电子学会C/C++编程等级考试2021年12月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:统计指定范围里的数 给定一个数的序列S,以及一个区间[L, R], 求序列中介于该区间的数的个数,即序列中大于等于L且小于等于R的数的个数。 时间限制:1000 内存限制:65536输入 第一行1个整数n、,分别表示序列的长。(0 < n…

浅谈建筑节能监管平台在高校能源管理中的实践与应用

安科瑞 华楠 摘要&#xff1a;以节约型校园建设示范工程———宁夏大学节能监管平台项目建设为例&#xff0c;对系统的总体构架、关键技术、管理软件功能进行了详细的介绍。同时针对项目建设、运行和管理过程中出现的一些问题&#xff0c;提出有针对性的解决措施&#xff0c;为…

模拟退火算法应用——求解一元函数的最小值

仅作自己学习使用 一、问题 需求&#xff1a; 计算函数 的极小值&#xff0c;其中个体x的维数n10&#xff0c;即x(x1,x2,…,x10)&#xff0c;其中每一个分量xi均需在[-20,20]内。因此可以知道&#xff0c;这个函数只有一个极小值点x (0,0,…,0)&#xff0c;且其极小值是0&…

信息检索指标直接优化的通用近似框架

1、直接优化信息检索指标的背景 1.1、存在问题 直接优化信息检索的指标是信息检索的一大方向。主要包含两类方法&#xff0c;一类是将IR指标作为上界进行优化&#xff1b;另一类是使用平滑函数近似表示IR指标进行优化。 直接优化IR指标方式很自然&#xff0c;但没有提供理论…

【ArcGIS Pro微课1000例】0037:ArcGIS Pro中模型构建器的使用---以shp批量转kml/kmz为例

文章目录 一、ArcGIS Pro模型构建器介绍二、shp批量转kml/kmz1. 打开模型构建器2. 添加工作空间4. 添加【创建要素图层】工具5. 添加【图层转kml】工具6. 输出文件命名7. 运行模型一、ArcGIS Pro模型构建器介绍 模型构建器是一种可视化编程语言,用于构建地理处理工作流。 地理…

Inport 模块

文章目录 Interpolate datainport 模块存在于模型最顶层Port Dimension 和 Variable-size signal Interpolate data Interpolate data&#xff1a;当将 Workspace 的数据导人模型时, 对没有对应数据点的采样时刻进行线性插值的开关选项。 inport 模块存在于模型最顶层 inpo…

区块链技术将如何影响未来的数字营销?

你是否听腻了区块链和数字营销等流行语&#xff0c;却不明白它们对未来意味着什么&#xff1f;那么&#xff0c;准备好系好安全带吧&#xff0c;因为区块链技术将彻底改变我们对数字营销的看法。从建立消费者信任到提高透明度和效率&#xff0c;其可能性是无限的。 让我们来探…

3.10-容器的操作

这一节讲解一下对于container我们可以进行哪些操作&#xff1f; 可以使用以下命令来停止正在运行的Docker容器&#xff1a; docker container stop <CONTAINER ID> 关于运行中的容器&#xff0c;我们可以进行的操作&#xff1a; 第一个是docker exec命令&#xff0c;这个…

软件开发中的抓大放小vs极致细节思维

最近在开发过程中&#xff0c;遇到了好多次 “这个需求点这次要不要做&#xff1f;” 的问题&#xff0c; 主要有两方阵营&#xff0c;比如以研发主导的 “这次先不做、等必要的时候再做” &#xff0c;另外一方是以PM主导的 “这个不做需求不完整&#xff0c;可能影响用户体验…

单片机AT89C51直流电机控制电路PWM设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;直流电机 获取论文报告源码源程序原理图 此文将介绍一种直流电机&#xff0c;详细阐述了用单片机输出口所给占空比的不同实现电机的调速的设计方法&#xff1b;着重讨论L298用于电机驱动时特有的优势。直流电机调速具有…

影刀RPA_boss直聘翻页(避坑)

boss直聘翻页这里有个坑 问题&#xff1a; 无限循环中&#xff0c;点击下一页按钮&#xff0c;直到不可点击为止。 发现&#xff0c;在点到第5页的时候&#xff0c;再次点击下一页&#xff0c;直接就点击了页码10&#xff0c;导致流程直接就结束了。 在第5页进行校验&#xff0…

基于51单片机的百叶窗控制系统设计

**单片机设计介绍&#xff0c; 基于51单片机的百叶窗控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的百叶窗控制系统设计可以分为硬件设计和软件设计两个方面。下面是一个简要的设计介绍&#xff1a; …

阿里云服务器安装mysql数据库之后无法远程连接

目录 一、mysql安装完成后直接远程远程连接阿里云服务器上的MySQL会报下述错误&#xff1a; 1、修改root用户的host 为% 登录MySQL 后 执行 2、修改完成后执行 3、退出mysql 重启mysql服务 exit; 4、修改完成后需要设置阿里云的安全规则。 二、dbaver测试链…

C语言每日一题(37)两数相加

力扣网 2 两数相加 题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&a…

【Spring篇】Spring注解式开发

本文根据哔哩哔哩课程内容结合自己自学所得&#xff0c;用于自己复习&#xff0c;如有错误欢迎指正&#xff1b; 我在想用一句话激励我自己努力学习&#xff0c;却想不出来什么惊为天人、精妙绝伦的句子&#xff0c;脑子里全是上课老师想说却没想起的四个字 “ 唯手熟尔 ”&am…

python pip安装第三方包时报错 error: Microsoft Visual C++ 14.0 or greater is required.

文章目录 1.问题2.原因3.解决办法 1.问题 pip install 的时候报错一大堆&#xff0c;其中有这么一段话 &#x1f447; error: Microsoft Visual C 14.0 or greater is required. Get it with "Microsoft C Build Tools": https://visualstudio.microsoft.com/visua…

java基于springboot公益帮学网站 新闻发布系统的设计与实现vue

以Java为开发平台&#xff0c;综合利用Java Web开发技术、数据库技术等&#xff0c;开发出公益帮学网站。用户使用版块&#xff1a;可以选择注册并登录&#xff0c;可以浏览信息、可以网上互动、发布文章、内容推荐等。后台管理员管理版块&#xff1a;以管理员身份登录网站后台…