C# 结合 JS 暴改腾讯 IM SDK Demo

 

目录

关于腾讯 IM SDK Demo 

范例运行环境

设计思路

服务端生成地址

IM 服务端接收

IM 客户端程序

小结


关于腾讯 IM SDK Demo 

腾讯云即时通信 IM SDK 提供了单聊、群聊、关系链、消息漫游、群组管理、资料管理、直播弹幕等功能,并提供完备的 App 接入及管理接口。目前的下载链接请参照如下:

https://cloud.tencent.com/document/product/269/36887

我们下载的是 Windows SDK Web 版本的源码,其结构如下:

下载后感觉目录里的文件有些随意,因此围绕打包编译后的目录 dist 展开研究,运行 index.html 似乎能够出来一些效果,但实际的使用中肯定与自己的需求有出入,由于本人比较懒,仅通过跟踪终端显示呈现效果,直接暴力修改混淆代码,主要解决如下一些问题:

1、结合已有系统,通过令牌机制验证对首页登录的访问

2、成功访问登录页后生成访问用户的 UserSig ,UserSig 是用户登录即时通信 IM 的密码,其本质是对 UserID 等信息加密后得到的密文,如何生成 UserSig 请参照我的文章《C# 生成腾讯云 IM 之 TLSSigAPIv2 UserSig》

3、修改 Toast.js 的信息提示程序

4、根据判断手机微信和PC不同终端进入不同的运行环境样式

5、重写左侧分页提示消息(如我的消息、我的通讯录)

6、重写获取好友列表

7、重写左侧操作面板样式

8、重写了更新个人资料的昵称和头像功能

9、增加获取成员信息的功能

10、增加了禁言用户和解禁用户的功能

11、重写了初始化左侧好友列表、消息状态及显示的功能

12、修改了视频通话只能显示帐户名,改为可以显示昵称的功能

13、增加了视频通话云端混录的功能

14、增加了群组管理员禁言用户及获取禁言用户列表的功能

15、增加对左侧控制面板的显示配置

16、增加聊天面板的选项配置

范例运行环境

操作系统: Windows Server 2019 DataCenter

.net版本: .netFramework4.0 或以上

开发工具:VS2019  C# 

设计思路

服务端生成地址

服务端设计一个登录页面用于如客服登录或普通登录。(也可以集成在应用中直接使用Session用户帐户登录),通过建立 IM 备份帐户表,检验登录 ,表大致设计如下:

序号字段名基础类型说明
1AppUIDnvarchar应用系统可能集成的用户帐户
2Accountnvarchar腾讯IM账户
3APWDnvarchar应用系统集成的加密密码
4avatarUrlnvarchar

应用系统集成的头像地址

5nickNamenvarchar应用系统集成的昵称
6sexnvarchar应用系统集成的性别
7AppClass     nvarcharApp平台名称
8AppName      nvarchar应用分类名称
9AppSubName  nvarchar应用二类分类名称
10AppIDNnvarchar账户类型(如客服、考生、个人、企业等等)

登录通过后根据用户生成 IM 用链接,地址为 /webim/dist/index.aspx,并传递相关参数值,见下表:

序号参数类型说明
1atstring传递的即时令牌值,接收端页面检验成功后即失效,用于页面安全访问
2scenestring

场景配置参数。配置参数形式如下:{0}_{1}_{2}_{3}

{0}:表示登录帐号

{1}:表示对方帐号(比如添加好友,这里可以默认为空)

{2}:左侧控制面板配置,用6个数字连接,依次表示为显示控制列表、会话、群组、好友、黑名单、默认进入类型的对应四个图标(1234),除最后一个数字为1到4的值外,其它均为1和0,1代表显示,0代表隐藏

如110102,代表显示控制列表,显示会话,隐藏群组,显示好友、隐藏黑名单、进入第二个图标

{3}:聊天面板配置,用4个数字连接,依次表示发送图片、视频、文件、视频通话。

如1110,则表示关闭视频通话功能,其它图标都显示

综上所述,生成的拼接地址如下示例:

/webim/dist/index.aspx?at=令牌值&scene=user1_user2_110102_1110

IM 服务端接收

IM 服务端接收,只要实现令牌值的合法校验,即是否可以访问本页,成功后进行客户端用的参数赋值,并生成 UserSig,示例代码如下:

<%@ Page Language="C#"  ResponseEncoding="utf-8"  ValidateRequest="false" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Web.UI" %>
<%@ Import Namespace="System.Web.UI.WebControls" %>

<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Web.Services"%>
<%@ Import Namespace="System.Web.Script.Services"%>
<script language="C#" runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
    
        if (Page.IsPostBack == true)
        {
            return;
        }
        Security.CraneOfficeCloud cc = new Security.CraneOfficeCloud();
        ViewState["access_token"] = cc.getToken("");

        ViewState["apiurl"] = System.Configuration.ConfigurationManager.AppSettings["apiurl"];
        ViewState["userId"] = "";
        ViewState["reomteUserId"] = "";
        ViewState["cfg_showlist"] = "0";
        ViewState["cfg_clist"] = "0";
        ViewState["cfg_glist"] = "0";
        ViewState["cfg_flist"] = "0";
        ViewState["cfg_blist"] = "0";
        ViewState["cfg_dlist"] = "1";
        ViewState["cfg_spic"] = "0";
        ViewState["cfg_svideo"] = "0";
        ViewState["cfg_sfile"] = "0";
        ViewState["cfg_videocall"] = "0";
        ViewState["userSig"] ="";

        string _at = (Request.QueryString["at"] == null ? "" : Request.QueryString["at"].ToString());
        bool validresult = cc.validImToken(_at);
        if (validresult == false)
        {
            Response.Redirect("end.aspx");
            return;
        }
        string reqPara = sec.CoDecode(Request.QueryString["scene"].ToString(), "michaeln");
        string[] paras = reqPara.Split('_');
        ViewState["userId"] = paras[0];
        ViewState["reomteUserId"] = paras[1];
        string cfg = paras[2];
        ViewState["cfg_showlist"] = cfg.Substring(0, 1);
        ViewState["cfg_clist"] = cfg.Substring(1, 1);
        ViewState["cfg_glist"] = cfg.Substring(2, 1);
        ViewState["cfg_flist"] = cfg.Substring(3, 1);
        ViewState["cfg_blist"] = cfg.Substring(4, 1);
        ViewState["cfg_dlist"] = cfg.Substring(5, 1);
        string cfg2 = paras[3];
        ViewState["cfg_spic"] = cfg2.Substring(0, 1);
        ViewState["cfg_svideo"] = cfg2.Substring(1, 1);
        ViewState["cfg_sfile"] = cfg2.Substring(2, 1);
        ViewState["cfg_videocall"] = cfg2.Substring(3, 1);

        TLSSigAPIv2 sig = new TLSSigAPIv2(1400,"6b7ec2a8fd");
        string _sig = sig.GenSig(ViewState["userId"].ToString());
        ViewState["userSig"] = _sig;

    }
</script>

IM 客户端程序

客户端程序主要用于接收服务端生成的参数,并通过 JS 外围控制与改变 IM SDK 的核心JS,客户端的示例代码如下:

<html>
<head>
<meta charset="utf-8"/><meta name="renderer" content="webkit"/><meta name="force-rendering" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
<title>craneoffice TIM</title>
<style type="text/css">
  .fbbtn
  {
      cursor:pointer;
        background-color:White;
        color:Gray;
        width:100px;
         -webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
         box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
         border-style:solid;
         border-width:1px;    
  }
  .fbbtn2
  {
      cursor:pointer;
        background-color:White;
        width:100px;
        color:Gray;
         -webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
         box-shadow:0 5px 10px 0 rgba(0,0,0,.5);
         border-style:solid;
         border-width:1px;    
  }
  .fblist
  {
     width:120px;
     font-size:9pt;
     font-family:微软雅黑;
        
  }
  .rfbtn
  {
     width:35px;
     font-size:9pt;
     font-family:微软雅黑;
        
  }
  .friend-list-container
  {
      margin-top:80px;
      margin-left:10px;
  }
  .friend-item-container
  {
      cursor:pointer;
      margin-top:10px;
  }
  .friend-name
  {
      margin-top:10px;
      margin-left:0px;
      color:White;
  }
</style>
<script language="javascript" type="text/javascript">
    var app_apiurl = '<%=ViewState["apiurl"].ToString()%>';
    var app_at = '<%=ViewState["access_token"].ToString()%>';
    var app_userId = '<%=ViewState["userId"].ToString()%>';
    var app_remote_userId = '<%=ViewState["reomteUserId"].ToString()%>';
    var app_showlist = '<%=ViewState["cfg_showlist"].ToString()%>';
    var app_clist = '<%=ViewState["cfg_clist"].ToString()%>';
    var app_glist = '<%=ViewState["cfg_glist"].ToString()%>';
    var app_flist = '<%=ViewState["cfg_flist"].ToString()%>';
    var app_blist = '<%=ViewState["cfg_blist"].ToString()%>';
    var app_dlist = '<%=ViewState["cfg_dlist"].ToString()%>';
    var app_sig = '<%=ViewState["userSig"].ToString()%>';
    var app_spic = '<%=ViewState["cfg_spic"].ToString()%>';
    var app_svideo = '<%=ViewState["cfg_svideo"].ToString()%>';
    var app_sfile = '<%=ViewState["cfg_sfile"].ToString()%>';
    var app_videocall = '<%=ViewState["cfg_videocall"].ToString()%>';
    var app_roomid = '';
    var app_groupid = '';
    var app_groupMsgUserId = '';
    var app_groupMsgUserRole = '';
    var app_frameId = window.frameElement && window.frameElement.id || '';
    var app_e = null;
    var app_nickname = "";
    var app_faceurl = "";
    if (window.parent != null) {
        app_nickname=(window.parent.document.getElementById('imnickname').value);
        app_faceurl=(window.parent.document.getElementById('imfaceurl').value);
    }
</script>
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link href="css/chunk-vendors.c7922a7e.css?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>" rel="stylesheet" />
<link href="css/app.16310f51.css?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>" rel="Stylesheet" />
<link rel="stylesheet" href="css/toastify.min.css" />

</head>

<body>
<div id="app"></div>
<script src="js/toastify.js"></script>
<script src="./debug/GenerateTestUserSig.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="./debug/lib-generate-test-usersig.min.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/chunk-vendors.f90981cb.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/app.430352d1.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/jquery-3.2.1.min.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>
<script src="js/utils.js?v=<%=Server.UrlEncode(DateTime.Now.ToString()) %>"></script>

<asp:Label ID="inittip" runat="server" Width="300px" Height="70px" Text="<br>正在配置请稍候..." style="text-align:center; display:none;position:absolute;left:100px;top:100px;-webkit-box-shadow:0 5px 10px 0 rgba(0,0,0,.9);box-shadow:0 5px 10px 0 rgba(0,0,0,.9)" ForeColor="white" ></asp:Label>
<asp:Label ID="exTitle" runat="server" Text="" style="position:absolute;left:100px;top:20px;" ForeColor="#a5b5c1" ></asp:Label>

<input type="button"  ID="rfbtn" runat="server" style="display:none"   onclick="getGroupShuttedList()" value="刷新" class="rfbtn" />
<select id="shlist" class="fblist" onchange="muteRefUser(this.value)" style="display:none"></select>
<input type="button"  ID="Button1" runat="server" style="display:none"   onclick="changeArea(1)" value="刷新" class="rfbtn" />
<input type="button"  ID="Button2" runat="server" style="display:none"   onclick="changeArea(2)" value="刷新" class="rfbtn" />

</body>
</html>
<script  language="javascript" type="text/javascript">
    var app_groupmemberlist=null;

    function is_weixin(){
        var ua = navigator.userAgent.toLowerCase();  
        if(ua.match(/MicroMessenger/i)=="micromessenger") {  
            return true;  
        } else {  
            return false;  
        }  
    } 
    var vtitle='';
    if(is_weixin()==true){
         vtitle='IM 微信版';
            document.getElementById('exTitle').style.display=vtitle;
    }else{
         vtitle='IM PC版';
            document.getElementById('exTitle').style.display=vtitle;
    }
    Toast.info('正在配置启动 CO '+vtitle+',请稍候...');

    function getmemberlist(){
        var promise = tim.getGroupMemberList({ groupID: app_groupid, count: 30, offset:0 }); // 从0开始拉取30个群成员
        promise.then(function(imResponse) {
          alert(JSON.stringify(imResponse.data.memberList)); // 群成员列表
        }).catch(function(imError) {
          alert(imError);
        });
    }
async function test() {
  await sleep(10000);
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
function setTitleEx(etype){
    var title='';
    if(etype==1){
        title='我的消息';
    }else  if(etype==2){
        title='我的通讯录';
    }
    document.getElementById('exTitle').innerHTML=title;
}
    app_gfl=new Array();
    

    function gfl(){
       var promise =tim.getFriendList();
        promise.then(function(imResponse) {
             for(var i=0;i<imResponse.data.length;i++){
                app_gfl.push(imResponse.data[i]);
             }
        }).catch(function(imError) {
             Toast.error(imError);
        });
    }
    function handleFriendClickEx(e){
        e.querySelector('.friend-name').click();
    }
    function changeArea(paneltype){
        var ol=30;
        if(is_weixin()==true){
            document.getElementById('exTitle').style.display='none';
        }
        if(paneltype==1){
            if(is_weixin()==true){
                document.querySelector(".bar-right").style.display = 'none';
                document.querySelector(".current-conversation-wrapper").style.display='';
                document.querySelector(".current-conversation-wrapper").style.width = (window.frameElement.offsetWidth-ol)+'px';
                document.querySelector(".current-conversation-wrapper").style.position = 'absolute';
                document.querySelector(".current-conversation-wrapper").style.left = ol+'px';
            }
        }else if(paneltype==2){
            document.getElementById('exTitle').style.display='';
            if(is_weixin()==true){
                document.querySelector(".current-conversation-wrapper").style.display='none';
                document.querySelector(".bar-right").style.display = '';
                document.querySelector(".bar-right").style.position = 'absolute';
                document.querySelector(".bar-right").style.left = ol+'px';
                document.querySelector(".bar-right").style.width = (window.frameElement.offsetWidth-ol)+'px';
            }
        }
    }
   function updateProfile(){
        if(app_nickname==""||app_faceurl==""){
            return;
        }
          let promise = tim.updateMyProfile({
          nick: app_nickname,
          avatar: app_faceurl
        });
        promise.then(function(imResponse) {
        }).catch(function(imError) {
          alert('updateMyProfile error:'+ imError); // 更新资料失败的相关信息
        });
   }
   function getNick(userid){
             for(var i=0;i<app_gfl.length;i++){
                if(app_gfl[i].profile.userID==userid){
                    return app_gfl[i].profile.nick;
                }
             }
        return userid;
    }

    function getNick2(userid){
        let promise = tim.getUserProfile({
          userIDList: [userid] // 请注意:即使只拉取一个用户的资料,也需要用数组类型,例如:userIDList: ['user1']
        });
        promise.then(function(imResponse) {
          app_e=imResponse.data[0].nick;
            if(imResponse.data[0].nick!=undefined){
                return imResponse.data[0].nick;
            }
        }).catch(function(imError) {
          return userid; // 获取其他用户资料失败的相关信息
        });        
        
    var e=app_e;
        alert(e.$store);
        e.$store.dispatch("checkoutConversation","CC20210506102216154");
    }
    function getmemberinfo(){
        Toast.info('信息提取中,如某些选项未显示请重新点击再试...');
        if(app_groupMsgUserId==app_userId){
             app_groupMsgUserRole='';
             Toast.notify('提取用户信息完成');
             return;
        }
        var promise = tim.getGroupMemberProfile({
          groupID: app_groupid,
          userIDList: [app_userId]
        });
        promise.then(function(imResponse) {
          if(imResponse.data.memberList.length>0){
             var ml=imResponse.data.memberList[0];
             app_groupMsgUserRole=ml.role;
             Toast.notify('提取用户信息完成。');
          }
        }).catch(function(imError) {
             Toast.error(imError);
        });
    }
    function reposx(x){
        if(x+230+100>$(window).width()){
            x=$(window).width()-230-100;
        }
        return x;
    }
    function reposy(y){
        if(y+271+70>$(window).height()){
            y=$(window).height()-271-70;
        }
        return y;
    }
    function muteRefUser(userid){
        if(userid=='') return;
        if(confirm('是否解禁用户'+userid)==false){
            return;
        }
        app_groupMsgUserId=userid;
        muteUser(0);
    }
    function muteUser(seconds) {
        var promise = tim.setGroupMemberMuteTime({
          groupID: app_groupid,
          userID: app_groupMsgUserId,
          muteTime: seconds // 禁言10分钟;设为0,则表示取消禁言
        });
        promise.then(function(imResponse) {
          var tip=(seconds==0?"已取消禁言该用户":'用户'+app_groupMsgUserId+'已被禁言'+timetip(seconds));
          Toast.notify(tip);
          rfbtn.click();
        }).catch(function(imError) {
          Toast.error(imError);
        });
    }
    function timetip(off) {
        var x=parseInt(off/3600,10);
        var htip=x==0?"":x+'小时';
        off=off-x*3600;
        var z = parseInt(off / 60, 10);
        var y = off % 60;
        var mtip='';
        var stip='';
        if(z==0&&y!=0){
          stip=y+'秒';
        } else if (z != 0 && y == 0) {
          mtip = z +'分钟';
        } else if (z != 0 && y != 0) {
          mtip = z + '分';
          stip = y + '秒';
        }  
        return htip+mtip+stip;
    }

    function onl() {
        if (app_showlist == 1) {
        }
        window.setTimeout(async function () {
            document.getElementById('inittip').style.display = 'none';
            var f = false;
            var fi = 0;
            for (var i = 0; i < document.getElementsByTagName('div').length; i++) {
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'side-bar-wrapper') {
//                                        document.getElementsByTagName('div')[i].style.width = window.frameElement.offsetWidth+'px';
                }
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'bar-right') {
//                                        document.getElementsByTagName('div')[i].style.display = 'none';
                }
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'bar-left') {
                    //                    document.getElementsByTagName('div')[i].style.display = 'none';
                }
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'current-conversation-wrapper' && app_showlist == 0) {
                    if (app_frameId != "") {
                        document.getElementsByTagName('div')[i].style.width = (window.frameElement.offsetWidth - 44) + 'px';
                        document.getElementsByTagName('div')[i].style.height = '99vh';
                        document.getElementsByTagName('div')[i].style.left = '31px';
                        document.getElementsByTagName('div')[i].style.top = '0px';
                        document.getElementsByTagName('div')[i].style.position = 'absolute';
                    }
                }
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'content') {
                    //                    alert(document.getElementsByTagName('div')[i].innerHTML);
                    //                    document.getElementsByTagName('div')[i].style.width = window.frameElement.offsetWidth + 'px';
                    //                    document.getElementsByTagName('div')[i].style.height = window.frameElement.offsetHeight + 'px';
                    //                    document.getElementsByTagName('div')[i].style.position = 'absolute';
                }
                // group - list
                if (document.getElementsByTagName('div')[i].getAttribute('id') == 'group-list' && app_dlist == 2) {
                    document.getElementsByTagName('div')[i].click();
                }
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'header-bar') {
                    if (document.getElementsByTagName('div')[i].innerHTML.indexOf('创建群组') != -1) {
                        document.getElementsByTagName('div')[i].innerHTML = '';
                        shlist.style.display='none';
                        rfbtn.style.display='none';
                        document.getElementsByTagName('div')[i].appendChild(shlist);
                        document.getElementsByTagName('div')[i].appendChild(rfbtn);
                    }
                }
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'conversation-item-container' && app_dlist == 1) {
                    f = true;
                    fi = i;
                    //                    break;
                }
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'group-item' && app_dlist == 2) {
                    f = true;
                    fi = i;
                    //                    break;
                }
            }
            if (f == true) {
                document.getElementsByTagName('div')[fi].click();
                
                if(app_dlist==2){
                        await sleep(1500);
                        getmemberinfo();
                        await sleep(1500);
                        if(app_groupMsgUserRole=='Owner'||app_groupMsgUserRole=='Admin'){
                            rfbtn.click();
                            shlist.style.display='';
                            rfbtn.style.display='';
                        }
                }
            }
            updateProfile();
                document.getElementById('friend-list').click();
                await sleep(1000);
                gfl();
                
                document.getElementById('conversation-list').click();
                
        }, 3000);
    }
    
    function iconClick() {
         setTitleEx(1);
         window.setTimeout(async function () {
            var f = false;
            var fi = 0;
            for (var i = 0; i < document.getElementsByTagName('div').length; i++) {
                if (document.getElementsByTagName('div')[i].getAttribute('class') == 'conversation-item-container' ) {
                    f = true;
                    fi = i;
                    break;
                }
            }
            if (f == true&&is_weixin()==false){
                document.getElementsByTagName('div')[fi].click();
            }
            window.parent.layer.closeAll();

        }, 1000);
    }
    window.onload = function () {
        if (document.getElementsByTagName('button').length == 1) {
            document.getElementsByTagName('button')[0].click();
        }
    }
   function setonline(_user1, _user2) {
       $.ajax({
           type: "Post",
           url: app_apiurl,
           contentType: "application/x-www-form-urlencoded;charset=utf-8",
           data: {
               gettype: 'getRoomIdForMixRecord',
               at: app_at,
               user1: encodeURIComponent(_user1),
               user2: encodeURIComponent(_user2)
           },
           dataType: "json",
           success: function (res) {
               //JSON.stringify
               alert(res.roomid);
               if (res.roomid != "") {
                   app_roomid = res.roomid;
                   requestMixRecord("request", "turing", app_roomid, "ARP120102197701243273", "ARI20200401");
               }
           },
           error: function (err) {
               alert(JSON.stringify(err));
           }
       });
   }
   function requestMixRecord(_mixtype, _companyName, _roomid, _userid1, _userid2) {
       $.ajax({
           type: "Post",
           url: app_apiurl,
           contentType: "application/x-www-form-urlencoded;charset=utf-8",
           data: {
               gettype: 'MixRecord',
               at: app_at,
               mixtype: encodeURIComponent(_mixtype),
               companyName: encodeURIComponent(_companyName),
               roomid: encodeURIComponent(_roomid),
               userid1: encodeURIComponent(_userid1),
               userid2: encodeURIComponent(_userid2)
           },
           dataType: "json",
           success: function (res) {
               //返回的数据用data.d获取内容   
               if (res.code == '0') {
                   //                    Toast.notify(_mixtype + ' record ok');
               } else {
                   //                    Toast.notify(' record '+res.code);

               }
//               alert(JSON.stringify(res));
           },
           error: function (err) {
               Toast.error(err);
           }
       });
   } //mixrecord
   function delGroupMsg() {
       $.ajax({
           type: "Post",
           url: app_apiurl,
           contentType: "application/x-www-form-urlencoded;charset=utf-8",
           data: {
               gettype: 'im_deleteGroupMsg',
               at: app_at,
               groupid: encodeURIComponent(app_groupid),
               account: encodeURIComponent(app_groupMsgUserId)
           },
           dataType: "json",
           success: function (res) {
               //返回的数据用data.d获取内容   
//               alert(JSON.stringify(res));
               if(res.ErrorCode=='0'){
                  Toast.notify('删除消息成功,缓存的消息可能还会显示。');
               }else{
                  Toast.error('删除消息失败。');
               }
           },
           error: function (err) {
                  Toast.error(JSON.stringify(err));
           }
       });
   } //mixrecord
   function getGroupShuttedList() {
       $.ajax({
           type: "Post",
           url: app_apiurl,
           contentType: "application/x-www-form-urlencoded;charset=utf-8",
           data: {
               gettype: 'im_getGroupShuttedList',
               at: app_at,
               groupid: encodeURIComponent(app_groupid)
           },
           dataType: "json",
           success: function (res) {
               if(res.ErrorCode=='0'){
                  if(res.ShuttedUinList.length>0){
                      Toast.notify('获取禁言列表成功,共'+res.ShuttedUinList.length+'个用户');
                      shlist.length=0;
                      shlist.options.add(new Option('选择取消禁言用户',''));
                      for(var i=0;i<res.ShuttedUinList.length;i++){
                          var userid=res.ShuttedUinList[i].Member_Account;
                          shlist.options.add(new Option(userid,userid));
                      }
                  }else{
                      shlist.length=0;
                      shlist.options.add(new Option('没有被禁言的用户',''));
                  }
               }else{
//                  Toast.error('获取禁言列表失败。');
               }
           },
           error: function (err) {
               alert('error'+JSON.stringify(err));
               //                Toast.notify(_mixtype + ' record fail');
           }
       });
   } //mixrecord


</script>

小结

暴改的腾讯 IM SDK Demo 请下载我的资源:

https://download.csdn.net/download/michaelline/89356543

本文代码代码示例仅供您参考使用,示例中使用到了视频通话的云端混录功能,有关云端混录功能请参考我的文章《C# 实现腾讯云多路直播流的云端混合录制》,请根据实际的应用取舍,另外一些 WebAPI 如设置用户在线状态、群组管理,也可根据实际需要进行修改。

感谢您的阅读,希望本文能够对您有所帮助。

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

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

相关文章

【STM32CubeIDE】软件硬件SPI+六针OLED使用

前言 本文将介绍STM32 6针OLED的使用&#xff0c;分别使用软件和硬件两种SPI驱动方式&#xff0c;最终实现OLED显示TEST-ok字符和数字累加刷新显示 软件平台&#xff1a;STM32CubeIDEHAL库 硬件&#xff1a;STM32F103ZET6(正点原子战舰V3)六针OLED 题外话&#xff1a; 最…

开源博客项目Blog .NET Core源码学习(26:App.Hosting项目结构分析-14)

后台管理页面的系统管理下主要包括用户管理、角色管理、按钮管理和菜单管理&#xff0c;其中创建用户时要指定角色&#xff0c;创建角色时需指定菜单权限&#xff0c;按钮管理也是基于各菜单项进行设置&#xff0c;只有菜单管理相对独立&#xff0c;因此本文学习并分析App.Host…

【Python搞定车载自动化测试】——Python基于Pytest框架实现UDS诊断自动化(含Python源码)

系列文章目录 【Python搞定车载自动化测试】系列文章目录汇总 文章目录 系列文章目录&#x1f4af;&#x1f4af;&#x1f4af; 前言&#x1f4af;&#x1f4af;&#x1f4af;一、环境搭建1.软件环境2.硬件环境 二、目录结构三、源码展示1.诊断基础函数方法2.诊断业务函数方法…

基于Keras的手写数字识别(附源码)

目录 引言 为什么要创建虚拟环境&#xff0c;好处在哪里&#xff1f; 源码 我修改的部分 调用本地数据 修改第二层卷积层 引言 本文是博主为了记录一个好的开源代码而写&#xff0c;下面是代码出处&#xff01;强烈建议收藏&#xff01;【深度学习实战—1】&#xff1a…

SK6812-RGBW是一个集控制电路与发光电路于一体的智能外控LED光源

产品概述: SK6812-RGBW是一个集控制电路与发光电路于一体的智能外控LED光源。其外型与一个5050LED灯珠相同&#xff0c;每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路&#xff0c;电源稳压电路&#xff0c;内置恒流电路&#xff0…

基于51单片机的盆栽自动浇花系统

一.硬件方案 工作原理是湿度传感器将采集到的数据直接传送到ADC0832的IN端作为输入的模拟信号。选用湿度传感器和AD转换&#xff0c;电路内部包含有湿度采集、AD转换、单片机译码显示等功能。单片机需要采集数据时&#xff0c;发出指令启动A/D转换器工作&#xff0c;ADC0832根…

WordPress Country State City Dropdown CF7插件 SQL注入漏洞复现(CVE-2024-3495)

0x01 产品简介 Country State City Dropdown CF7插件是一个功能强大、易于使用的WordPress插件,它为用户在联系表单中提供国家、州/省和城市的三级下拉菜单功能,帮助用户更准确地填写地区信息。同时,插件的团队和支持也非常出色,为用户提供高质量的服务。 0x02 漏洞概述 …

零基础的粉丝有福了:逐键提示盲打更轻松

盲打就是不看键盘去打字&#xff0c;对于零基础的粉丝而言&#xff0c;盲打入门通常都是很难的&#xff0c;今天就给大家放个福利&#xff1a;从今天开始就能盲打&#xff0c;3天之后盲打就入门了。 真的有这么简单吗&#xff1f;是的&#xff0c;跟着我做就可以了。 首先&am…

结构体(位段)内存分配

结构体由多个数据类型的成员组成。那编译器分配的内存是不是所有成员的字节数总和呢&#xff1f; 首先&#xff0c;stu的内存大小并不为29个字节&#xff0c;即证明结构体内存不是所有成员的字节数和。   其次&#xff0c;stu成员中sex的内存位置不在21&#xff0c;即可推测…

Linux驱动开发笔记(二) 基于字符设备驱动的I/O操作

文章目录 前言一、设备驱动的作用与本质1. 驱动的作用2. 有无操作系统的区别 二、内存管理单元MMU三、相关函数1. ioremap( )2. iounmap( )3. class_create( )4. class_destroy( ) 四、GPIO的基本知识1. GPIO的寄存器进行读写操作流程2. 引脚复用2. 定义GPIO寄存器物理地址 五、…

视频汇聚平台LntonCVS视频监控系统前端错误日志记录及Debug模式详细讲解

LntonCVS作为一种支持GB28181标准的流媒体服务平台&#xff0c;旨在提供一个能够整合不同厂商设备、便于管理和扩展的解决方案&#xff0c;以适应日益复杂的视频监控环境。通过实现设备的统一管理和流媒体的高效传输&#xff0c;LntonCVS帮助构建更加灵活和强大的视频监控系统。…

Andoird使用Room实现持久化及使用Room进行增删查改

文章目录 Room概述Room的使用一、在gradle.build中添加依赖库kotlinJava 创建实体类创建抽象Dao层接口创建DataBase层使用创建的查看数据库 总结&#xff1a; 这篇文章会告诉你如何在Android中通过kotlin或者Java来实现数据持久化 Room概述 处理大量结构化数据的应用可极大地受…

强烈推荐 20.7k Star!企业级商城开源项目强烈推荐!基于DDD领域驱动设计模型,助您快速掌握技术奥秘,实现业务快速增长

更多资源请关注纽扣编程微信公众号 1 项目简介 商城是个从零到一的C端商城项目&#xff0c;包含商城核心业务和基础架构两大模块,推出用户、消息、商品、订单、优惠券、支付、网关、购物车等业务模块&#xff0c;通过商城系统中复杂场景&#xff0c;给出对应解决方案。使用 …

Java——简易图书管理系统

本文使用 Java 实现一个简易图书管理系统 一、思路 简易图书管理系统说白了其实就是 用户 与 图书 这两个对象之间的交互 书的属性有 书名 作者 类型 价格 借阅状态 而用户可以分为 普通用户 管理员 使用数组将书统一管理起来 用户对这个数组进行操作 普通用户可以进…

Axure RP 10汉化版修改文字

效果 安装目录 lang/default Axure 10 RP 汉化包&#xff08;概览改图层&#xff09;

Express 的 req 和 res 对象

新建 learn-express文件夹&#xff0c;执行命令行 npm init -y npm install express 新建 index.js const express require(express); const app express();app.get(/, (req, res, next) > {res.json(return get) })app.post(/, (req, res, next) > {res.json(retur…

单机一天轻松300+ 最新微信小程序拼多多+京东全自动掘金项目、

现代互联网经济的发展带来了新型的盈利方式&#xff0c;这种方法通过微信小程序的拼多多和京东进行商品自动巡视&#xff0c;以此给商家带来增加的流量&#xff0c;同时为使用者带来利润。实践这一手段无需复杂操作&#xff0c;用户仅需启动相应程序&#xff0c;商品信息便会被…

【东山派Vision K510开发板试用笔记】WiFi配网问题

目录 概述 WiFi配网的修改 悬而未决的问题 概述 最近试用了百问网提供的东山派Vision开发板&#xff0c;DongshanPI-Vision开发板是百问网针对AI应用开发设计出来的一个RSIC-V架构的AI开发板&#xff0c;主要用于学习使用嘉楠的K510芯片进行Linux项目开发和嵌入式AI应用开发…

闲话 .NET(5):.NET Core 有什么优势?

前言 .NET Core 并不是 .NET FrameWork 的升级版&#xff0c;它是一个为满足新一代的软件设计要求而从头重新开发的开发框架和平台&#xff0c;所以它没有 .NET FrameWork 的历史包袱&#xff0c;相对于 .NET FrameWork&#xff0c;它具备很多优势。 .NET Core 有哪些优势&am…

什么是DDoS流量清洗?

随着互联网的飞速发展&#xff0c;网络安全问题日益凸显&#xff0c;其中分布式拒绝服务&#xff08;DDoS&#xff09;攻击尤为引人关注。为了有效应对这一威胁&#xff0c;流量清洗服务应运而生&#xff0c;成为网络安全领域的一项重要技术。 流量清洗服务是一种专门针对DDoS…