mirror of
https://github.com/huiyadanli/RevokeMsgPatcher.git
synced 2025-08-23 20:16:07 +08:00
feat(architecture): Implement decoupled modifier architecture
This commit introduces a major architectural refactoring to improve the maintainability, extensibility, and testability of the application. Key changes include: - **IAppModifier Interface:** Defines a clear contract for all application-specific modifiers. - **BaseAppModifier Abstract Class:** Provides common implementations for shared modifier logic, reducing code duplication. - **Refactored Concrete Modifiers:** Existing modifier classes now inherit from BaseAppModifier, focusing on their unique application-specific logic. - **ModifierFactory:** Centralizes the creation of modifier instances, decoupling the UI from concrete implementations. - **Updated FormMain.cs:** The main UI now interacts with modifiers through the IAppModifier interface and uses the ModifierFactory, significantly reducing coupling and simplifying UI logic. This refactoring adheres to principles of abstraction, encapsulation, and polymorphism, making the codebase more robust and easier to extend with support for new applications in the future.
This commit is contained in:
parent
480bc7ad81
commit
2fe0f0ee8e
|
@ -16,14 +16,7 @@ namespace RevokeMsgPatcher
|
|||
public partial class FormMain : Form
|
||||
{
|
||||
// 当前使用的修改者
|
||||
private AppModifier modifier = null;
|
||||
|
||||
private WechatModifier wechatModifier = null;
|
||||
private WeixinModifier weixinModifier = null;
|
||||
private QQModifier qqModifier = null;
|
||||
private TIMModifier timModifier = null;
|
||||
private QQLiteModifier qqLiteModifier = null;
|
||||
private QQNTModifier qqntModifier = null;
|
||||
private IAppModifier modifier = null;
|
||||
|
||||
private string thisVersion;
|
||||
private bool needUpdate = false;
|
||||
|
@ -41,24 +34,9 @@ namespace RevokeMsgPatcher
|
|||
JavaScriptSerializer serializer = new JavaScriptSerializer();
|
||||
bag = serializer.Deserialize<Bag>(Properties.Resources.PatchJson);
|
||||
|
||||
// 初始化每个应用对应的修改者
|
||||
wechatModifier = new WechatModifier(bag.Apps["Wechat"]);
|
||||
weixinModifier = new WeixinModifier(bag.Apps["Weixin"]);
|
||||
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;
|
||||
rbtWeixin.Tag = weixinModifier;
|
||||
rbtQQ.Tag = qqModifier;
|
||||
rbtTIM.Tag = timModifier;
|
||||
rbtQQLite.Tag = qqLiteModifier;
|
||||
rbtQQNT.Tag = qqntModifier;
|
||||
|
||||
// 默认微信
|
||||
rbtWechat.Enabled = true;
|
||||
modifier = wechatModifier;
|
||||
modifier = ModifierFactory.CreateModifier("WeChat", bag.Apps["WeChat"]);
|
||||
}
|
||||
|
||||
public FormMain()
|
||||
|
@ -349,11 +327,7 @@ namespace RevokeMsgPatcher
|
|||
lblUpdatePachJson.Text = "[ 获取成功,点击查看更多信息 ]";
|
||||
lblUpdatePachJson.ForeColor = Color.RoyalBlue;
|
||||
|
||||
wechatModifier.Config = newBag.Apps["Wechat"];
|
||||
weixinModifier.Config = newBag.Apps["Weixin"];
|
||||
qqModifier.Config = newBag.Apps["QQ"];
|
||||
timModifier.Config = newBag.Apps["TIM"];
|
||||
qqLiteModifier.Config = newBag.Apps["QQLite"];
|
||||
modifier.Config = newBag.Apps[modifier.Config.Name];
|
||||
|
||||
getPatchJsonStatus = "SUCCESS";
|
||||
bag = newBag;
|
||||
|
@ -412,31 +386,8 @@ namespace RevokeMsgPatcher
|
|||
EnableAllButton(false);
|
||||
|
||||
// 切换使用不同的防撤回对象
|
||||
if (rbtWechat.Checked)
|
||||
{
|
||||
modifier = (WechatModifier)rbtWechat.Tag;
|
||||
}
|
||||
else if (rbtWeixin.Checked)
|
||||
{
|
||||
modifier = (WeixinModifier)rbtWeixin.Tag;
|
||||
}
|
||||
else if (rbtQQ.Checked)
|
||||
{
|
||||
modifier = (QQModifier)rbtQQ.Tag;
|
||||
}
|
||||
else if (rbtTIM.Checked)
|
||||
{
|
||||
modifier = (TIMModifier)rbtTIM.Tag;
|
||||
}
|
||||
else if (rbtQQLite.Checked)
|
||||
{
|
||||
modifier = (QQLiteModifier)rbtQQLite.Tag;
|
||||
}
|
||||
else if (rbtQQNT.Checked)
|
||||
{
|
||||
modifier = (QQNTModifier)rbtQQNT.Tag;
|
||||
// ShowOrFocusFormLiteLoaderQQNT();
|
||||
}
|
||||
string appName = GetCheckedRadioButtonNameEn();
|
||||
modifier = ModifierFactory.CreateModifier(appName, bag.Apps[appName]);
|
||||
|
||||
EnableAllButton(true);
|
||||
// 触发了 txtPath_TextChanged 方法 已经调用了 InitEditorsAndUI(txtPath.Text);
|
||||
|
@ -466,27 +417,13 @@ namespace RevokeMsgPatcher
|
|||
|
||||
private string GetCheckedRadioButtonNameEn()
|
||||
{
|
||||
if (rbtWechat.Checked)
|
||||
foreach (Control control in this.panelAppSelect.Controls)
|
||||
{
|
||||
return "wechat";
|
||||
}
|
||||
else if (rbtQQ.Checked)
|
||||
if (control is RadioButton radioButton && radioButton.Checked)
|
||||
{
|
||||
return "qq";
|
||||
return radioButton.Text;
|
||||
}
|
||||
else if (rbtTIM.Checked)
|
||||
{
|
||||
return "tim";
|
||||
}
|
||||
else if (rbtQQLite.Checked)
|
||||
{
|
||||
return "qqlite";
|
||||
}
|
||||
else if (rbtQQNT.Checked)
|
||||
{
|
||||
return "qqnt";
|
||||
}
|
||||
|
||||
return "none";
|
||||
}
|
||||
|
||||
|
|
141
RevokeMsgPatcher/Modifier/BaseAppModifier.cs
Normal file
141
RevokeMsgPatcher/Modifier/BaseAppModifier.cs
Normal file
|
@ -0,0 +1,141 @@
|
|||
using RevokeMsgPatcher.Model;
|
||||
using RevokeMsgPatcher.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
public abstract class BaseAppModifier : AppModifier, IAppModifier
|
||||
{
|
||||
public abstract string VersionFileName { get; }
|
||||
public App Config { get; set; }
|
||||
|
||||
protected BaseAppModifier(App config)
|
||||
{
|
||||
this.Config = config;
|
||||
}
|
||||
|
||||
public override string GetVersion()
|
||||
{
|
||||
if (editors != null && editors.Count > 0)
|
||||
{
|
||||
foreach (FileHexEditor editor in editors)
|
||||
{
|
||||
if (editor.FileName == VersionFileName)
|
||||
{
|
||||
return editor.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public override void AfterPatchSuccess() { }
|
||||
|
||||
public override void AfterPatchFail() { }
|
||||
|
||||
public bool BackupExists()
|
||||
{
|
||||
if (editors == null || editors.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach (FileHexEditor editor in editors)
|
||||
{
|
||||
if (!System.IO.File.Exists(editor.FileBakPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsAllFilesExist(string installPath)
|
||||
{
|
||||
if (Config.TargetFiles == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
foreach (TargetInfo target in Config.TargetFiles)
|
||||
{
|
||||
if (!System.IO.File.Exists(target.GetAbsolutePath(installPath)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool InitEditors(string installPath)
|
||||
{
|
||||
// 判断是否是安装路径
|
||||
if (!IsAllFilesExist(installPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 初始化十六进制文件编辑器
|
||||
// 并寻找与之配对的版本修改信息
|
||||
editors = new List<FileHexEditor>();
|
||||
foreach (TargetInfo target in Config.TargetFiles)
|
||||
{
|
||||
editors.Add(new FileHexEditor(installPath, target));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetVersionLabelAndCategoryCategories(Label lblVersion, Panel panelCategories)
|
||||
{
|
||||
lblVersion.Text = GetVersion();
|
||||
UIController.AddCategoriesToPanel(panelCategories, Config.Categories);
|
||||
}
|
||||
|
||||
public void ValidateAndFindModifyInfo(List<string> categories)
|
||||
{
|
||||
foreach (FileHexEditor editor in editors)
|
||||
{
|
||||
// 寻找精确版本修改信息
|
||||
ModifyInfo modifyInfo = ModifyFinder.FindModifyInfo(editor.FileSHA1, Config.ModifyInfos);
|
||||
if (modifyInfo != null)
|
||||
{
|
||||
editor.FileModifyInfo = modifyInfo;
|
||||
editor.TargetChanges = modifyInfo.Changes;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 寻找通用特征码修改信息
|
||||
CommonModifyInfo commonModifyInfo = ModifyFinder.FindCommonModifyInfo(editor.FileVersion, Config.CommonModifyInfos);
|
||||
if (commonModifyInfo != null)
|
||||
{
|
||||
editor.FileCommonModifyInfo = commonModifyInfo;
|
||||
editor.TargetChanges = ModifyFinder.FindChangesByCategories(editor.FilePath, commonModifyInfo.ReplacePatterns, categories);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessException("not_support_version", $"当前版本 {editor.FileVersion} 不支持,请等待更新!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Patch()
|
||||
{
|
||||
foreach (FileHexEditor editor in editors)
|
||||
{
|
||||
editor.Backup();
|
||||
editor.Patch();
|
||||
}
|
||||
AfterPatchSuccess();
|
||||
}
|
||||
|
||||
public bool Restore()
|
||||
{
|
||||
foreach (FileHexEditor editor in editors)
|
||||
{
|
||||
editor.Restore();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
24
RevokeMsgPatcher/Modifier/IAppModifier.cs
Normal file
24
RevokeMsgPatcher/Modifier/IAppModifier.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using RevokeMsgPatcher.Model;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
public interface IAppModifier
|
||||
{
|
||||
App Config { get; set; }
|
||||
List<FileHexEditor> editors { get; set; }
|
||||
|
||||
string FindInstallPath();
|
||||
string GetVersion();
|
||||
bool InitEditors(string installPath);
|
||||
void ValidateAndFindModifyInfo(List<string> categories);
|
||||
void Patch();
|
||||
bool Restore();
|
||||
bool BackupExists();
|
||||
bool IsAllFilesExist(string installPath);
|
||||
void SetVersionLabelAndCategoryCategories(Label lblVersion, Panel panelCategories);
|
||||
void AfterPatchSuccess();
|
||||
void AfterPatchFail();
|
||||
}
|
||||
}
|
28
RevokeMsgPatcher/Modifier/ModifierFactory.cs
Normal file
28
RevokeMsgPatcher/Modifier/ModifierFactory.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
using RevokeMsgPatcher.Model;
|
||||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
public static class ModifierFactory
|
||||
{
|
||||
public static IAppModifier CreateModifier(string appName, App config)
|
||||
{
|
||||
switch (appName)
|
||||
{
|
||||
case "WeChat":
|
||||
return new WechatModifier(config);
|
||||
case "Weixin":
|
||||
return new WeixinModifier(config);
|
||||
case "QQ":
|
||||
return new QQModifier(config);
|
||||
case "TIM":
|
||||
return new TIMModifier(config);
|
||||
case "QQLite":
|
||||
return new QQLiteModifier(config);
|
||||
case "QQNT":
|
||||
return new QQNTModifier(config);
|
||||
default:
|
||||
throw new System.ArgumentException($"Unknown application name: {appName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,20 +5,11 @@ using System.Collections.Generic;
|
|||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
class QQLiteModifier : AppModifier
|
||||
class QQLiteModifier : BaseAppModifier
|
||||
{
|
||||
public QQLiteModifier(App config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
public override string VersionFileName => "IM.dll";
|
||||
|
||||
public override void AfterPatchSuccess()
|
||||
{
|
||||
}
|
||||
|
||||
public override void AfterPatchFail()
|
||||
{
|
||||
}
|
||||
public QQLiteModifier(App config) : base(config) { }
|
||||
|
||||
/// <summary>
|
||||
/// 自动寻找获取微信安装路径
|
||||
|
@ -51,24 +42,5 @@ namespace RevokeMsgPatcher.Modifier
|
|||
}
|
||||
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 == "IM.dll")
|
||||
{
|
||||
return editor.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,11 @@ using System.Collections.Generic;
|
|||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
class QQModifier : AppModifier
|
||||
class QQModifier : BaseAppModifier
|
||||
{
|
||||
public QQModifier(App config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
public override string VersionFileName => "IM.dll";
|
||||
|
||||
public override void AfterPatchSuccess()
|
||||
{
|
||||
}
|
||||
|
||||
public override void AfterPatchFail()
|
||||
{
|
||||
}
|
||||
public QQModifier(App config) : base(config) { }
|
||||
|
||||
/// <summary>
|
||||
/// 自动寻找获取微信安装路径
|
||||
|
@ -51,24 +42,5 @@ namespace RevokeMsgPatcher.Modifier
|
|||
}
|
||||
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 == "IM.dll")
|
||||
{
|
||||
return editor.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,11 @@ using System.Windows.Forms;
|
|||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
class QQNTModifier : AppModifier
|
||||
class QQNTModifier : BaseAppModifier
|
||||
{
|
||||
public QQNTModifier(App config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
public override string VersionFileName => "wrapper.node";
|
||||
|
||||
public QQNTModifier(App config) : base(config) { }
|
||||
|
||||
/// <summary>
|
||||
/// 自动寻找获取微信安装路径
|
||||
|
@ -59,38 +58,9 @@ namespace RevokeMsgPatcher.Modifier
|
|||
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 == "wrapper.node")
|
||||
{
|
||||
return editor.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public override void AfterPatchSuccess()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void AfterPatchFail()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public new bool Restore()
|
||||
{
|
||||
AfterPatchFail();
|
||||
base.AfterPatchFail();
|
||||
return base.Restore();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,21 +3,11 @@ using RevokeMsgPatcher.Utils;
|
|||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
class TIMModifier : AppModifier
|
||||
class TIMModifier : BaseAppModifier
|
||||
{
|
||||
public override string VersionFileName => "IM.dll";
|
||||
|
||||
public TIMModifier(App config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public override void AfterPatchSuccess()
|
||||
{
|
||||
}
|
||||
|
||||
public override void AfterPatchFail()
|
||||
{
|
||||
}
|
||||
public TIMModifier(App config) : base(config) { }
|
||||
|
||||
/// <summary>
|
||||
/// 自动寻找获取微信安装路径
|
||||
|
@ -42,24 +32,5 @@ namespace RevokeMsgPatcher.Modifier
|
|||
}
|
||||
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 == "IM.dll")
|
||||
{
|
||||
return editor.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,21 +6,11 @@ using System.IO;
|
|||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
class WechatModifier : AppModifier
|
||||
class WechatModifier : BaseAppModifier
|
||||
{
|
||||
public override string VersionFileName => "WeChatWin.dll";
|
||||
|
||||
public WechatModifier(App config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public override void AfterPatchSuccess()
|
||||
{
|
||||
}
|
||||
|
||||
public override void AfterPatchFail()
|
||||
{
|
||||
}
|
||||
public WechatModifier(App config) : base(config) { }
|
||||
|
||||
/// <summary>
|
||||
/// 自动寻找获取微信安装路径
|
||||
|
@ -82,40 +72,5 @@ namespace RevokeMsgPatcher.Modifier
|
|||
}
|
||||
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 == "WeChatWin.dll")
|
||||
{
|
||||
return editor.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//public override bool ValidateAndInitialize(string installPath)
|
||||
//{
|
||||
// // 判断是否是安装路径
|
||||
// if (!IsAllBinaryFilesExist(installPath))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // 初始化十六进制文件编辑器
|
||||
// // 并寻找与之配对的版本修改信息
|
||||
// InitEditors(installPath);
|
||||
|
||||
// return true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,21 +6,11 @@ using System.IO;
|
|||
|
||||
namespace RevokeMsgPatcher.Modifier
|
||||
{
|
||||
class WeixinModifier : AppModifier
|
||||
class WeixinModifier : BaseAppModifier
|
||||
{
|
||||
public override string VersionFileName => "Weixin.dll";
|
||||
|
||||
public WeixinModifier(App config)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public override void AfterPatchSuccess()
|
||||
{
|
||||
}
|
||||
|
||||
public override void AfterPatchFail()
|
||||
{
|
||||
}
|
||||
public WeixinModifier(App config) : base(config) { }
|
||||
|
||||
/// <summary>
|
||||
/// 自动寻找获取微信安装路径
|
||||
|
@ -83,40 +73,5 @@ namespace RevokeMsgPatcher.Modifier
|
|||
}
|
||||
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 == "Weixin.dll")
|
||||
{
|
||||
return editor.FileVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//public override bool ValidateAndInitialize(string installPath)
|
||||
//{
|
||||
// // 判断是否是安装路径
|
||||
// if (!IsAllBinaryFilesExist(installPath))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // 初始化十六进制文件编辑器
|
||||
// // 并寻找与之配对的版本修改信息
|
||||
// InitEditors(installPath);
|
||||
|
||||
// return true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user