mirror of
				https://github.com/huiyadanli/RevokeMsgPatcher.git
				synced 2025-11-04 13:56:08 +08:00 
			
		
		
		
	Merge pull request #730 from huiyadanli/feat-qqnt
安装 LiteLoaderQQNT 实现 QQNT 的防撤回
This commit is contained in:
		
						commit
						193dec8810
					
				
							
								
								
									
										1
									
								
								RevokeMsgPatcher.Assistant/Data/1.8/patch.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								RevokeMsgPatcher.Assistant/Data/1.8/patch.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -16,8 +16,8 @@ namespace RevokeMsgPatcher
 | 
			
		|||
            return new Bag
 | 
			
		||||
            {
 | 
			
		||||
                Apps = AppConfig(),
 | 
			
		||||
                LatestVersion = "1.7",
 | 
			
		||||
                PatchVersion = 20240614,
 | 
			
		||||
                LatestVersion = "1.8",
 | 
			
		||||
                PatchVersion = 20240615,
 | 
			
		||||
                Notice = "",
 | 
			
		||||
                NoticeUrl = "",
 | 
			
		||||
            };
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,8 @@ namespace RevokeMsgPatcher
 | 
			
		|||
                { "Wechat" , Wechat() },
 | 
			
		||||
                { "QQ" , QQ() },
 | 
			
		||||
                { "TIM" , TIM() },
 | 
			
		||||
                { "QQLite" , QQLite() }
 | 
			
		||||
                { "QQLite" , QQLite() },
 | 
			
		||||
                { "QQNT" , QQNT() }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1344,5 +1345,49 @@ namespace RevokeMsgPatcher
 | 
			
		|||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public App QQNT()
 | 
			
		||||
        {
 | 
			
		||||
            return new App
 | 
			
		||||
            {
 | 
			
		||||
                Name = "QQNT",
 | 
			
		||||
                FileTargetInfos = new Dictionary<string, TargetInfo>
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        "QQ.exe",
 | 
			
		||||
                        new TargetInfo
 | 
			
		||||
                        {
 | 
			
		||||
                            Name = "QQ.exe",
 | 
			
		||||
                            RelativePath = "QQ.exe"
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                FileCommonModifyInfos = new Dictionary<string, List<CommonModifyInfo>>
 | 
			
		||||
                {
 | 
			
		||||
                    {
 | 
			
		||||
                        "QQ.exe",
 | 
			
		||||
                        new List<CommonModifyInfo>
 | 
			
		||||
                        {
 | 
			
		||||
                            new CommonModifyInfo
 | 
			
		||||
                            {
 | 
			
		||||
                                Name="QQ.exe",
 | 
			
		||||
                                StartVersion="9.9.10.00000",
 | 
			
		||||
                                EndVersion="",
 | 
			
		||||
                                ReplacePatterns = new List<ReplacePattern>
 | 
			
		||||
                                {
 | 
			
		||||
                                    new ReplacePattern
 | 
			
		||||
                                    {
 | 
			
		||||
                                        Search = ByteUtil.HexStringToByteArray("48 89 CE 48 8B 11 4C 8B 41 08 49 29 D0 48 8B 49 18 E8 3F 3F 3F 3F"),
 | 
			
		||||
                                        Replace = ByteUtil.HexStringToByteArray("48 89 CE 48 8B 11 4C 8B 41 08 49 29 D0 48 8B 49 18 B8 01 00 00 00"),
 | 
			
		||||
                                        Category = "LiteLoaderQQNT+插件列表+防撤回"
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,6 +95,7 @@
 | 
			
		|||
    <None Include="Data\1.5\patch.json" />
 | 
			
		||||
    <None Include="Data\1.6\patch.json" />
 | 
			
		||||
    <None Include="Data\1.7\patch.json" />
 | 
			
		||||
    <None Include="Data\1.8\patch.json" />
 | 
			
		||||
    <None Include="Properties\Settings.settings">
 | 
			
		||||
      <Generator>SettingsSingleFileGenerator</Generator>
 | 
			
		||||
      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								RevokeMsgPatcher/FormMain.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										20
									
								
								RevokeMsgPatcher/FormMain.Designer.cs
									
									
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -63,6 +63,7 @@
 | 
			
		|||
            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
 | 
			
		||||
            this.panelNotice = new System.Windows.Forms.Panel();
 | 
			
		||||
            this.labelNotice = new System.Windows.Forms.Label();
 | 
			
		||||
            this.rbtQQNT = new System.Windows.Forms.RadioButton();
 | 
			
		||||
            this.menuStrip1.SuspendLayout();
 | 
			
		||||
            this.panelNotice.SuspendLayout();
 | 
			
		||||
            this.SuspendLayout();
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +186,7 @@
 | 
			
		|||
            // rbtQQ
 | 
			
		||||
            // 
 | 
			
		||||
            this.rbtQQ.AutoSize = true;
 | 
			
		||||
            this.rbtQQ.Location = new System.Drawing.Point(142, 36);
 | 
			
		||||
            this.rbtQQ.Location = new System.Drawing.Point(190, 36);
 | 
			
		||||
            this.rbtQQ.Name = "rbtQQ";
 | 
			
		||||
            this.rbtQQ.Size = new System.Drawing.Size(35, 16);
 | 
			
		||||
            this.rbtQQ.TabIndex = 13;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +197,7 @@
 | 
			
		|||
            // rbtTIM
 | 
			
		||||
            // 
 | 
			
		||||
            this.rbtTIM.AutoSize = true;
 | 
			
		||||
            this.rbtTIM.Location = new System.Drawing.Point(188, 36);
 | 
			
		||||
            this.rbtTIM.Location = new System.Drawing.Point(236, 36);
 | 
			
		||||
            this.rbtTIM.Name = "rbtTIM";
 | 
			
		||||
            this.rbtTIM.Size = new System.Drawing.Size(41, 16);
 | 
			
		||||
            this.rbtTIM.TabIndex = 14;
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +217,7 @@
 | 
			
		|||
            // rbtQQLite
 | 
			
		||||
            // 
 | 
			
		||||
            this.rbtQQLite.AutoSize = true;
 | 
			
		||||
            this.rbtQQLite.Location = new System.Drawing.Point(237, 36);
 | 
			
		||||
            this.rbtQQLite.Location = new System.Drawing.Point(285, 36);
 | 
			
		||||
            this.rbtQQLite.Name = "rbtQQLite";
 | 
			
		||||
            this.rbtQQLite.Size = new System.Drawing.Size(71, 16);
 | 
			
		||||
            this.rbtQQLite.TabIndex = 18;
 | 
			
		||||
| 
						 | 
				
			
			@ -372,11 +373,23 @@
 | 
			
		|||
            this.labelNotice.TabIndex = 0;
 | 
			
		||||
            this.labelNotice.Text = "测试测试测试测试";
 | 
			
		||||
            // 
 | 
			
		||||
            // rbtQQNT
 | 
			
		||||
            // 
 | 
			
		||||
            this.rbtQQNT.AutoSize = true;
 | 
			
		||||
            this.rbtQQNT.Location = new System.Drawing.Point(135, 36);
 | 
			
		||||
            this.rbtQQNT.Name = "rbtQQNT";
 | 
			
		||||
            this.rbtQQNT.Size = new System.Drawing.Size(47, 16);
 | 
			
		||||
            this.rbtQQNT.TabIndex = 24;
 | 
			
		||||
            this.rbtQQNT.Text = "QQNT";
 | 
			
		||||
            this.rbtQQNT.UseVisualStyleBackColor = true;
 | 
			
		||||
            this.rbtQQNT.CheckedChanged += new System.EventHandler(this.radioButtons_CheckedChanged);
 | 
			
		||||
            // 
 | 
			
		||||
            // FormMain
 | 
			
		||||
            // 
 | 
			
		||||
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
 | 
			
		||||
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
 | 
			
		||||
            this.ClientSize = new System.Drawing.Size(490, 169);
 | 
			
		||||
            this.Controls.Add(this.rbtQQNT);
 | 
			
		||||
            this.Controls.Add(this.panelNotice);
 | 
			
		||||
            this.Controls.Add(this.panelCategories);
 | 
			
		||||
            this.Controls.Add(this.lblCategory);
 | 
			
		||||
| 
						 | 
				
			
			@ -445,6 +458,7 @@
 | 
			
		|||
        private System.Windows.Forms.ToolTip toolTip1;
 | 
			
		||||
        private System.Windows.Forms.Panel panelNotice;
 | 
			
		||||
        private System.Windows.Forms.Label labelNotice;
 | 
			
		||||
        private System.Windows.Forms.RadioButton rbtQQNT;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ namespace RevokeMsgPatcher
 | 
			
		|||
        private QQModifier qqModifier = null;
 | 
			
		||||
        private TIMModifier timModifier = null;
 | 
			
		||||
        private QQLiteModifier qqLiteModifier = null;
 | 
			
		||||
        private QQNTModifier qqntModifier = null;
 | 
			
		||||
 | 
			
		||||
        private string thisVersion;
 | 
			
		||||
        private bool needUpdate = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,11 +43,13 @@ namespace RevokeMsgPatcher
 | 
			
		|||
            qqModifier = new QQModifier(bag.Apps["QQ"]);
 | 
			
		||||
            timModifier = new TIMModifier(bag.Apps["TIM"]);
 | 
			
		||||
            qqLiteModifier = new QQLiteModifier(bag.Apps["QQLite"]);
 | 
			
		||||
            qqntModifier = new QQNTModifier(bag.Apps["QQNT"]);
 | 
			
		||||
 | 
			
		||||
            rbtWechat.Tag = wechatModifier;
 | 
			
		||||
            rbtQQ.Tag = qqModifier;
 | 
			
		||||
            rbtTIM.Tag = timModifier;
 | 
			
		||||
            rbtQQLite.Tag = qqLiteModifier;
 | 
			
		||||
            rbtQQNT.Tag = qqntModifier;
 | 
			
		||||
 | 
			
		||||
            // 默认微信
 | 
			
		||||
            rbtWechat.Enabled = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -168,7 +171,7 @@ namespace RevokeMsgPatcher
 | 
			
		|||
                {
 | 
			
		||||
                    DialogResult result = MessageBox.Show(@"防撤回(老) 和 防撤回带提示(新) 两个功能二选一即可!
 | 
			
		||||
 | 
			
		||||
1. 防撤回(老) 没有提示;
 | 
			
		||||
1. 防撤回(老) 没有提示,新版本会出现撤回自己消息不断转圈的情况(实际撤回成功);
 | 
			
		||||
 | 
			
		||||
2. 防撤回带提示(新) 有撤回提示 但是存在以下问题:
 | 
			
		||||
    a. 如果正在和对方聊天时,对方撤回了消息,那撤回提示依然不会显示,只有在左侧预览窗有显示撤回,需要切换到和别人的聊天窗再切回来才能看到撤回提示,如果是把聊天拉出单独窗口,一直不会有撤回提示。
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +221,7 @@ namespace RevokeMsgPatcher
 | 
			
		|||
            {
 | 
			
		||||
                modifier.Patch();
 | 
			
		||||
                ga.RequestPageView($"{enName}/{version}/patch/succ", "补丁安装成功");
 | 
			
		||||
                MessageBox.Show("补丁安装成功!");
 | 
			
		||||
                MessageBox.Show("补丁安装成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
 | 
			
		||||
            }
 | 
			
		||||
            catch (BusinessException ex)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -277,7 +280,16 @@ namespace RevokeMsgPatcher
 | 
			
		|||
            EnableAllButton(false);
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                bool succ = modifier.Restore();
 | 
			
		||||
                bool succ;
 | 
			
		||||
                if (rbtQQNT.Checked)
 | 
			
		||||
                {
 | 
			
		||||
                    succ = qqntModifier.Restore();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    succ = modifier.Restore();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (succ)
 | 
			
		||||
                {
 | 
			
		||||
                    MessageBox.Show("还原成功!");
 | 
			
		||||
| 
						 | 
				
			
			@ -368,6 +380,7 @@ namespace RevokeMsgPatcher
 | 
			
		|||
 | 
			
		||||
            tips += "支持以下版本" + Environment.NewLine;
 | 
			
		||||
            tips += " ➯ 微信:" + wechatModifier.Config.GetSupportVersionStr() + Environment.NewLine;
 | 
			
		||||
            tips += " ➯ QQNT:" + qqntModifier.Config.GetSupportVersionStr() + Environment.NewLine;
 | 
			
		||||
            tips += " ➯ QQ:" + qqModifier.Config.GetSupportVersionStr() + Environment.NewLine;
 | 
			
		||||
            tips += " ➯ QQ轻聊版:" + qqLiteModifier.Config.GetSupportVersionStr() + Environment.NewLine;
 | 
			
		||||
            tips += " ➯ TIM:" + timModifier.Config.GetSupportVersionStr() + Environment.NewLine;
 | 
			
		||||
| 
						 | 
				
			
			@ -406,6 +419,10 @@ namespace RevokeMsgPatcher
 | 
			
		|||
            {
 | 
			
		||||
                modifier = (QQLiteModifier)rbtQQLite.Tag;
 | 
			
		||||
            }
 | 
			
		||||
            else if (rbtQQNT.Checked)
 | 
			
		||||
            {
 | 
			
		||||
                modifier = (QQNTModifier)rbtQQNT.Tag;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            EnableAllButton(true);
 | 
			
		||||
            // 触发了 txtPath_TextChanged 方法 已经调用了 InitEditorsAndUI(txtPath.Text);
 | 
			
		||||
| 
						 | 
				
			
			@ -433,6 +450,10 @@ namespace RevokeMsgPatcher
 | 
			
		|||
            {
 | 
			
		||||
                return "qqlite";
 | 
			
		||||
            }
 | 
			
		||||
            else if (rbtQQNT.Checked)
 | 
			
		||||
            {
 | 
			
		||||
                return "qqnt";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return "none";
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,11 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
    {
 | 
			
		||||
        protected App config;
 | 
			
		||||
 | 
			
		||||
        public App Config { set { config = value; } get { return config; } }
 | 
			
		||||
        public App Config
 | 
			
		||||
        {
 | 
			
		||||
            set { config = value; }
 | 
			
		||||
            get { return config; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected List<FileHexEditor> editors;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,18 +60,22 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            foreach (FileHexEditor editor in editors) // 多种文件
 | 
			
		||||
            {
 | 
			
		||||
                // 精确版本匹配
 | 
			
		||||
                bool haven = false;
 | 
			
		||||
                foreach (ModifyInfo modifyInfo in config.FileModifyInfos[editor.FileName]) // 多个版本信息
 | 
			
		||||
                if (config.FileModifyInfos != null && config.FileModifyInfos.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    if (editor.FileVersion == modifyInfo.Version)
 | 
			
		||||
                    bool haven = false;
 | 
			
		||||
                    foreach (ModifyInfo modifyInfo in config.FileModifyInfos[editor.FileName]) // 多个版本信息
 | 
			
		||||
                    {
 | 
			
		||||
                        haven = true;
 | 
			
		||||
                        break;
 | 
			
		||||
                        if (editor.FileVersion == modifyInfo.Version)
 | 
			
		||||
                        {
 | 
			
		||||
                            haven = true;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (haven)
 | 
			
		||||
                    {
 | 
			
		||||
                        i++;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (haven)
 | 
			
		||||
                {
 | 
			
		||||
                    i++;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,16 +110,19 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                                    categories.Add(c);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            // 获取已经安装过的功能类型
 | 
			
		||||
                            SortedSet<string> replaced = ModifyFinder.FindReplacedFunction(editor.FilePath, commonModifyInfo.ReplacePatterns);
 | 
			
		||||
                            foreach (string c in replaced)
 | 
			
		||||
                            {
 | 
			
		||||
                                installed.Add(c);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            inRange = true;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (inRange)
 | 
			
		||||
                    {
 | 
			
		||||
                        j++;
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +134,12 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            if (j == editors.Count)
 | 
			
		||||
            {
 | 
			
		||||
                label.Text = version + "(支持特征防撤回)";
 | 
			
		||||
                // QQNT 特殊处理
 | 
			
		||||
                if (config.Name == "QQNT")
 | 
			
		||||
                {
 | 
			
		||||
                    label.Text = version + "(支持LiteLoader)";
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                label.ForeColor = Color.LimeGreen;
 | 
			
		||||
                UIController.AddCategoryCheckBoxToPanel(panel, categories.ToArray(), installed.ToArray());
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +149,6 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                label.ForeColor = Color.Red;
 | 
			
		||||
                UIController.AddMsgToPanel(panel, "无功能选项");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +162,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int success = 0, count = 0;
 | 
			
		||||
            foreach (TargetInfo info in config.FileTargetInfos.Values)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +176,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (success == count && success >= 1)
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -189,6 +207,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            {
 | 
			
		||||
                Console.WriteLine("判断版本范围时出错:" + e.Message);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -207,6 +226,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                    return commonModifyInfo;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -225,6 +245,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (i == editors.Count)
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -241,6 +262,8 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
        /// <param name="installPath">APP安装路径</param>
 | 
			
		||||
        public bool InitEditors(string installPath)
 | 
			
		||||
        {
 | 
			
		||||
            InstallPath = null;
 | 
			
		||||
 | 
			
		||||
            // 初始化文件修改器
 | 
			
		||||
            editors = new List<FileHexEditor>();
 | 
			
		||||
            foreach (TargetInfo info in config.FileTargetInfos.Values)
 | 
			
		||||
| 
						 | 
				
			
			@ -253,11 +276,15 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                    editors.Add(editor);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (editors.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show("当前版本没有对应的文件修改信息,请确认补丁信息是否正常!");
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            InstallPath = installPath;
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -272,26 +299,30 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            {
 | 
			
		||||
                // 通过SHA1和文件版本判断是否可以打补丁 根据不同结果返回不同的提示
 | 
			
		||||
                ModifyInfo matchingSHA1Before = null, matchingSHA1After = null, matchingVersion = null;
 | 
			
		||||
                foreach (ModifyInfo modifyInfo in config.FileModifyInfos[editor.FileName]) // 多个版本信息
 | 
			
		||||
                if (config.FileModifyInfos != null && config.FileModifyInfos.Count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    if (modifyInfo.Name == editor.FileName) // 保险用的无用判断
 | 
			
		||||
                    foreach (ModifyInfo modifyInfo in config.FileModifyInfos[editor.FileName]) // 多个版本信息
 | 
			
		||||
                    {
 | 
			
		||||
                        if (editor.FileSHA1 == modifyInfo.SHA1After)
 | 
			
		||||
                        if (modifyInfo.Name == editor.FileName) // 保险用的无用判断
 | 
			
		||||
                        {
 | 
			
		||||
                            matchingSHA1After = modifyInfo;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (editor.FileSHA1 == modifyInfo.SHA1Before)
 | 
			
		||||
                        {
 | 
			
		||||
                            matchingSHA1Before = modifyInfo;
 | 
			
		||||
                        }
 | 
			
		||||
                            if (editor.FileSHA1 == modifyInfo.SHA1After)
 | 
			
		||||
                            {
 | 
			
		||||
                                matchingSHA1After = modifyInfo;
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (editor.FileSHA1 == modifyInfo.SHA1Before)
 | 
			
		||||
                            {
 | 
			
		||||
                                matchingSHA1Before = modifyInfo;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                        if (editor.FileVersion == modifyInfo.Version)
 | 
			
		||||
                        {
 | 
			
		||||
                            matchingVersion = modifyInfo;
 | 
			
		||||
                            if (editor.FileVersion == modifyInfo.Version)
 | 
			
		||||
                            {
 | 
			
		||||
                                matchingVersion = modifyInfo;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                // 补丁前SHA1匹配上,肯定是正确的dll
 | 
			
		||||
                if (matchingSHA1Before != null)
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -299,6 +330,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                    editor.TargetChanges = matchingSHA1Before.Changes;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 补丁后SHA1匹配上,肯定已经打过补丁
 | 
			
		||||
                if (matchingSHA1After != null)
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -324,6 +356,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                        {
 | 
			
		||||
                            replacePatterns = editor.FileCommonModifyInfo.ReplacePatterns.Where(info => categories.Contains(info.Category)).ToList();
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        // 如果能顺利得到 TargetChanges 不报错则可以使用特征替换方式
 | 
			
		||||
                        editor.TargetChanges = ModifyFinder.FindChanges(editor.FilePath, replacePatterns);
 | 
			
		||||
                        continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -335,6 +368,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                        {
 | 
			
		||||
                            throw new BusinessException("not_support", $"不支持的文件:名称 {editor.FileName} 版本 {editor.FileVersion}!");
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        // SHA1不匹配,但是版本匹配,可能dll已经被其他补丁程序修改过
 | 
			
		||||
                        if (matchingVersion != null)
 | 
			
		||||
                        {
 | 
			
		||||
| 
						 | 
				
			
			@ -357,6 +391,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            {
 | 
			
		||||
                throw new Exception("补丁安装失败,原因:无对应的文件修改器");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (FileHexEditor editor in editors)
 | 
			
		||||
            {
 | 
			
		||||
                if (editor == null)
 | 
			
		||||
| 
						 | 
				
			
			@ -364,11 +399,13 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                    throw new Exception("补丁安装失败,原因:文件修改器初始化失败!");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 再备份所有文件
 | 
			
		||||
            foreach (FileHexEditor editor in editors)
 | 
			
		||||
            {
 | 
			
		||||
                editor.Backup();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 打补丁!
 | 
			
		||||
            List<FileHexEditor> done = new List<FileHexEditor>(); // 已经打上补丁的
 | 
			
		||||
            try
 | 
			
		||||
| 
						 | 
				
			
			@ -386,6 +423,8 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                        done.Add(editor);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                AfterPatchSuccess();
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -394,8 +433,11 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                {
 | 
			
		||||
                    editor.Restore();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                AfterPatchFail();
 | 
			
		||||
                throw ex;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -408,6 +450,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -440,6 +483,7 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                        editor.Restore();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
| 
						 | 
				
			
			@ -447,5 +491,9 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
                throw new Exception("备份文件不存在,还原失败!");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public abstract void  AfterPatchSuccess();
 | 
			
		||||
 | 
			
		||||
        public abstract void AfterPatchFail();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +12,14 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            this.config = config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchSuccess()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchFail()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自动寻找获取微信安装路径
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,14 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            this.config = config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchSuccess()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchFail()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自动寻找获取微信安装路径
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										154
									
								
								RevokeMsgPatcher/Modifier/QQNTModifier.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								RevokeMsgPatcher/Modifier/QQNTModifier.cs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,154 @@
 | 
			
		|||
using RevokeMsgPatcher.Model;
 | 
			
		||||
using RevokeMsgPatcher.Utils;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Windows.Forms;
 | 
			
		||||
 | 
			
		||||
namespace RevokeMsgPatcher.Modifier
 | 
			
		||||
{
 | 
			
		||||
    class QQNTModifier : AppModifier
 | 
			
		||||
    {
 | 
			
		||||
        public QQNTModifier(App config)
 | 
			
		||||
        {
 | 
			
		||||
            this.config = config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自动寻找获取微信安装路径
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public override string FindInstallPath()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                string installPath = PathUtil.FindInstallPathFromRegistryWOW6432Node("QQ");
 | 
			
		||||
                if (!string.IsNullOrEmpty(installPath))
 | 
			
		||||
                {
 | 
			
		||||
                    installPath = Path.GetDirectoryName(installPath);
 | 
			
		||||
                    if (IsAllFilesExist(installPath))
 | 
			
		||||
                    {
 | 
			
		||||
                        return installPath;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                installPath = PathUtil.FindInstallPathFromRegistry("QQNT");
 | 
			
		||||
                if (!IsAllFilesExist(installPath))
 | 
			
		||||
                {
 | 
			
		||||
                    List<string> defaultPathList = PathUtil.GetDefaultInstallPaths(@"Tencent\QQNT");
 | 
			
		||||
                    foreach (string defaultPath in defaultPathList)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (IsAllFilesExist(defaultPath))
 | 
			
		||||
                        {
 | 
			
		||||
                            return defaultPath;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return installPath;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine(e.Message);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取整个APP的当前版本
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public override string GetVersion()
 | 
			
		||||
        {
 | 
			
		||||
            if (editors != null && editors.Count > 0)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (FileHexEditor editor in editors)
 | 
			
		||||
                {
 | 
			
		||||
                    if (editor.FileName == "QQ.exe")
 | 
			
		||||
                    {
 | 
			
		||||
                        return editor.FileVersion;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string GetIndexJsPath()
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(InstallPath))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("未获取到QQNT安装路径或者QQNT安装路径不合法");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            string indexPath = Path.Combine(InstallPath, @"resources\app\app_launcher\index.js");
 | 
			
		||||
            if (!File.Exists(indexPath))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("未找到index.js文件");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return indexPath;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string GetLiteLoaderPath()
 | 
			
		||||
        {
 | 
			
		||||
            return Path.Combine(Application.StartupPath, @"LiteLoaderQQNT");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchSuccess()
 | 
			
		||||
        {
 | 
			
		||||
            string indexPath = GetIndexJsPath();
 | 
			
		||||
            string content = File.ReadAllText(indexPath);
 | 
			
		||||
            // 正则 require\(String.raw`.*`\);
 | 
			
		||||
            string pattern = @"require\(String.raw`.*`\);";
 | 
			
		||||
            string liteLoaderPath = GetLiteLoaderPath();
 | 
			
		||||
            if (!File.Exists(liteLoaderPath))
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show("LiteLoaderQQNT文件夹不存在,仅安装QQNT去验证补丁", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            string replacement = $"require(String.raw`{liteLoaderPath}`);";
 | 
			
		||||
            if (Regex.IsMatch(content, pattern))
 | 
			
		||||
            {
 | 
			
		||||
                content = Regex.Replace(content, pattern, replacement);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                content = replacement + "\n" + content;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            File.WriteAllText(indexPath, content);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchFail()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                string indexPath = GetIndexJsPath();
 | 
			
		||||
                string content = File.ReadAllText(indexPath);
 | 
			
		||||
                string pattern = @"require\(String.raw`.*`\);\n";
 | 
			
		||||
                if (Regex.IsMatch(content, pattern))
 | 
			
		||||
                {
 | 
			
		||||
                    content = Regex.Replace(content, pattern, "");
 | 
			
		||||
                    File.WriteAllText(indexPath, content);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.WriteLine(e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public new bool Restore()
 | 
			
		||||
        {
 | 
			
		||||
            AfterPatchFail();
 | 
			
		||||
            return base.Restore();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,6 +10,15 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
        {
 | 
			
		||||
            this.config = config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchSuccess()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchFail()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自动寻找获取微信安装路径
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,14 @@ namespace RevokeMsgPatcher.Modifier
 | 
			
		|||
            this.config = config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchSuccess()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void AfterPatchFail()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自动寻找获取微信安装路径
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
 | 
			
		|||
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
 | 
			
		||||
// 方法是按如下所示使用“*”: :
 | 
			
		||||
//[assembly: AssemblyVersion("1.0.*")]
 | 
			
		||||
[assembly: AssemblyVersion("1.7")]
 | 
			
		||||
[assembly: AssemblyFileVersion("1.7")]
 | 
			
		||||
[assembly: AssemblyVersion("1.8")]
 | 
			
		||||
[assembly: AssemblyFileVersion("1.8")]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -81,6 +81,7 @@
 | 
			
		|||
    <Compile Include="Modifier\AppModifier.cs" />
 | 
			
		||||
    <Compile Include="Modifier\FileHexEditor.cs" />
 | 
			
		||||
    <Compile Include="Modifier\QQLiteModifier.cs" />
 | 
			
		||||
    <Compile Include="Modifier\QQNTModifier.cs" />
 | 
			
		||||
    <Compile Include="Modifier\QQModifier.cs" />
 | 
			
		||||
    <Compile Include="Modifier\TIMModifier.cs" />
 | 
			
		||||
    <Compile Include="Modifier\WechatModifier.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,6 +57,30 @@ namespace RevokeMsgPatcher.Utils
 | 
			
		|||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public static string FindInstallPathFromRegistryWOW6432Node(string uninstallKeyName)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                RegistryKey key = Registry.LocalMachine.OpenSubKey($@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{uninstallKeyName}");
 | 
			
		||||
                if (key == null)
 | 
			
		||||
                {
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
                object installLocation = key.GetValue("UninstallString");
 | 
			
		||||
                key.Close();
 | 
			
		||||
                if (installLocation != null && !string.IsNullOrEmpty(installLocation.ToString()))
 | 
			
		||||
                {
 | 
			
		||||
                    return installLocation.ToString();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Console.WriteLine(e.Message);
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取所有可能的默认安装路径
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user