FormMain.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. using RevokeMsgPatcher.Model;
  2. using RevokeMsgPatcher.Modifier;
  3. using RevokeMsgPatcher.Utils;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Net;
  8. using System.Threading.Tasks;
  9. using System.Web.Script.Serialization;
  10. using System.Windows.Forms;
  11. namespace RevokeMsgPatcher
  12. {
  13. public partial class FormMain : Form
  14. {
  15. // 当前使用的修改者
  16. private AppModifier modifier = null;
  17. private WechatModifier wechatModifier = null;
  18. private QQModifier qqModifier = null;
  19. private TIMModifier timModifier = null;
  20. private QQLiteModifier qqLiteModifier = null;
  21. private string thisVersion;
  22. private bool needUpdate = false;
  23. private GAHelper ga = new GAHelper(); // Google Analytics 记录
  24. public void InitModifier()
  25. {
  26. // 从配置文件中读取配置
  27. JavaScriptSerializer serializer = new JavaScriptSerializer();
  28. Bag bag = serializer.Deserialize<Bag>(Properties.Resources.PatchJson);
  29. // 初始化每个应用对应的修改者
  30. wechatModifier = new WechatModifier(bag.Apps["Wechat"]);
  31. qqModifier = new QQModifier(bag.Apps["QQ"]);
  32. timModifier = new TIMModifier(bag.Apps["TIM"]);
  33. qqLiteModifier = new QQLiteModifier(bag.Apps["QQLite"]);
  34. rbtWechat.Tag = wechatModifier;
  35. rbtQQ.Tag = qqModifier;
  36. rbtTIM.Tag = timModifier;
  37. rbtQQLite.Tag = qqLiteModifier;
  38. // 默认微信
  39. rbtWechat.Enabled = true;
  40. modifier = wechatModifier;
  41. }
  42. public FormMain()
  43. {
  44. InitializeComponent();
  45. // 标题加上版本号
  46. string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
  47. if (currentVersion.Length > 3)
  48. {
  49. thisVersion = currentVersion.Substring(0, 3);
  50. currentVersion = " v" + thisVersion;
  51. }
  52. this.Text += currentVersion;
  53. InitModifier();
  54. InitControls();
  55. ga.RequestPageView($"/main/{thisVersion}", $"进入{thisVersion}版本主界面");
  56. }
  57. private void InitControls()
  58. {
  59. // 自动获取应用安装路径
  60. txtPath.Text = modifier.FindInstallPath();
  61. btnRestore.Enabled = false;
  62. // 显示是否能够备份还原
  63. if (!string.IsNullOrEmpty(txtPath.Text))
  64. {
  65. modifier.InitEditors(txtPath.Text);
  66. lblVersion.Text = modifier.GetVersion();
  67. btnRestore.Enabled = modifier.BackupExists();
  68. }
  69. }
  70. private void btnPatch_Click(object sender, EventArgs e)
  71. {
  72. if (!modifier.IsAllFilesExist(txtPath.Text))
  73. {
  74. MessageBox.Show("请选择正确的安装路径!");
  75. return;
  76. }
  77. // 记录点了什么应用的防撤回
  78. string enName = GetCheckedRadioButtonNameEn(); // 应用英文名
  79. string version = modifier.GetVersion(); // 应用版本
  80. ga.RequestPageView($"{enName}/{version}/patch", "点击防撤回");
  81. EnableAllButton(false);
  82. // a.重新初始化编辑器
  83. modifier.InitEditors(txtPath.Text);
  84. // b.计算SHA1,验证文件完整性,寻找对应的补丁信息
  85. try
  86. {
  87. modifier.ValidateAndFindModifyInfo();
  88. }
  89. catch (BusinessException ex)
  90. {
  91. ga.RequestPageView($"{enName}/{version}/patch/sha1/ex/{ex.ErrorCode}", ex.Message);
  92. MessageBox.Show(ex.Message);
  93. return;
  94. }
  95. catch (IOException ex)
  96. {
  97. ga.RequestPageView($"{enName}/{version}/patch/sha1/ex/{ex.HResult.ToString("x4")}", ex.Message);
  98. MessageBox.Show(ex.Message + " 请以管理员权限启动本程序,并确认当前应用(微信/QQ/TIM)处于关闭状态。");
  99. return;
  100. }
  101. catch (Exception ex)
  102. {
  103. ga.RequestPageView($"{enName}/{version}/patch/sha1/ex/{ex.HResult.ToString("x4")}", ex.Message);
  104. MessageBox.Show(ex.Message);
  105. return;
  106. }
  107. finally
  108. {
  109. EnableAllButton(true);
  110. btnRestore.Enabled = modifier.BackupExists();
  111. }
  112. // c.打补丁
  113. try
  114. {
  115. modifier.Patch();
  116. ga.RequestPageView($"{enName}/{version}/patch/succ", "防撤回成功");
  117. MessageBox.Show("补丁安装成功!");
  118. }
  119. catch (Exception ex)
  120. {
  121. Console.WriteLine(ex.Message);
  122. ga.RequestPageView($"{enName}/{version}/patch/ex/{ex.HResult.ToString("x4")}", ex.Message);
  123. MessageBox.Show(ex.Message + " 请以管理员权限启动本程序,并确认当前应用(微信/QQ/TIM)处于关闭状态。");
  124. }
  125. finally
  126. {
  127. EnableAllButton(true);
  128. btnRestore.Enabled = modifier.BackupExists();
  129. }
  130. }
  131. private void txtPath_TextChanged(object sender, EventArgs e)
  132. {
  133. if (modifier.IsAllFilesExist(txtPath.Text))
  134. {
  135. modifier.InitEditors(txtPath.Text);
  136. btnRestore.Enabled = modifier.BackupExists();
  137. }
  138. else
  139. {
  140. btnPatch.Enabled = false;
  141. btnRestore.Enabled = false;
  142. }
  143. }
  144. private void btnChoosePath_Click(object sender, EventArgs e)
  145. {
  146. FolderBrowserDialog dialog = new FolderBrowserDialog();
  147. dialog.Description = "请选择安装路径";
  148. if (dialog.ShowDialog() == DialogResult.OK)
  149. {
  150. if (string.IsNullOrEmpty(dialog.SelectedPath) || !modifier.IsAllFilesExist(dialog.SelectedPath))
  151. {
  152. MessageBox.Show("无法找到此应用的关键文件,请选择正确的安装路径!");
  153. }
  154. else
  155. {
  156. txtPath.Text = dialog.SelectedPath;
  157. btnRestore.Enabled = false;
  158. // 显示是否能够备份还原
  159. if (!string.IsNullOrEmpty(txtPath.Text))
  160. {
  161. modifier.InitEditors(txtPath.Text);
  162. lblVersion.Text = modifier.GetVersion();
  163. btnRestore.Enabled = modifier.BackupExists();
  164. }
  165. }
  166. }
  167. }
  168. private void btnRestore_Click(object sender, EventArgs e)
  169. {
  170. EnableAllButton(false);
  171. try
  172. {
  173. modifier.Restore();
  174. MessageBox.Show("还原成功!");
  175. }
  176. catch (Exception ex)
  177. {
  178. Console.WriteLine(ex.Message);
  179. MessageBox.Show(ex.Message);
  180. }
  181. EnableAllButton(true);
  182. btnRestore.Enabled = modifier.BackupExists();
  183. }
  184. private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
  185. {
  186. System.Diagnostics.Process.Start("https://github.com/huiyadanli/RevokeMsgPatcher");
  187. }
  188. private async void FormMain_Load(object sender, EventArgs e)
  189. {
  190. // 异步获取最新的补丁信息
  191. string json = await GetPathJsonAsync();
  192. if (string.IsNullOrEmpty(json))
  193. {
  194. lblUpdatePachJson.Text = "[ 获取最新补丁信息失败 ]";
  195. }
  196. else
  197. {
  198. try
  199. {
  200. JavaScriptSerializer serializer = new JavaScriptSerializer();
  201. Bag bag = serializer.Deserialize<Bag>(json);
  202. wechatModifier.Config = bag.Apps["Wechat"];
  203. qqModifier.Config = bag.Apps["QQ"];
  204. timModifier.Config = bag.Apps["TIM"];
  205. qqLiteModifier.Config = bag.Apps["QQLite"];
  206. if (Convert.ToDecimal(bag.LatestVersion) > Convert.ToDecimal(thisVersion))
  207. {
  208. needUpdate = true;
  209. lblUpdatePachJson.Text = $"[ 存在最新版本 {bag.LatestVersion} ]";
  210. }
  211. else
  212. {
  213. needUpdate = false;
  214. lblUpdatePachJson.Text = "[ 获取成功,点击查看更多信息 ]";
  215. }
  216. }
  217. catch (Exception ex)
  218. {
  219. Console.WriteLine(ex.Message);
  220. lblUpdatePachJson.Text = "[ 更换新配置时异常 ]";
  221. }
  222. }
  223. }
  224. private async Task<string> GetPathJsonAsync()
  225. {
  226. string downStr = null;
  227. try
  228. {
  229. downStr = await HttpUtil.Client.GetStringAsync("https://huiyadanli.coding.me/i/revokemsg/05.json");
  230. }
  231. catch (Exception ex1)
  232. {
  233. Console.WriteLine(ex1.Message);
  234. try
  235. {
  236. downStr = await HttpUtil.Client.GetStringAsync("https://www.huiyadan.com/i/revokemsg/05.json");
  237. }
  238. catch (Exception ex2)
  239. {
  240. Console.WriteLine(ex2.Message);
  241. }
  242. }
  243. return downStr;
  244. }
  245. private void lblUpdatePachJson_Click(object sender, EventArgs e)
  246. {
  247. string tips = "";
  248. if (needUpdate)
  249. {
  250. tips += "【当前存在最新版本,点击确定进入软件主页下载最新版本。】" + Environment.NewLine + Environment.NewLine;
  251. }
  252. tips += "支持以下版本" + Environment.NewLine;
  253. tips += " ➯ 微信:" + wechatModifier.Config.GetSupportVersionStr() + Environment.NewLine;
  254. tips += " ➯ QQ:" + qqModifier.Config.GetSupportVersionStr() + Environment.NewLine;
  255. tips += " ➯ QQ轻聊版:" + qqLiteModifier.Config.GetSupportVersionStr() + Environment.NewLine;
  256. tips += " ➯ TIM:" + timModifier.Config.GetSupportVersionStr() + Environment.NewLine;
  257. DialogResult dr = MessageBox.Show(tips, "当前支持防撤回的版本", MessageBoxButtons.OKCancel);
  258. if (dr == DialogResult.OK && needUpdate)
  259. {
  260. System.Diagnostics.Process.Start("https://github.com/huiyadanli/RevokeMsgPatcher/releases");
  261. }
  262. }
  263. private void radioButtons_CheckedChanged(object sender, EventArgs e)
  264. {
  265. EnableAllButton(false);
  266. RadioButton radioButton = sender as RadioButton;
  267. // 切换使用不同的防撤回对象
  268. if (rbtWechat.Checked)
  269. {
  270. modifier = (WechatModifier)rbtWechat.Tag;
  271. }
  272. else if (rbtQQ.Checked)
  273. {
  274. modifier = (QQModifier)rbtQQ.Tag;
  275. }
  276. else if (rbtTIM.Checked)
  277. {
  278. modifier = (TIMModifier)rbtTIM.Tag;
  279. }
  280. else if (rbtQQLite.Checked)
  281. {
  282. modifier = (QQLiteModifier)rbtQQLite.Tag;
  283. }
  284. txtPath.Text = modifier.FindInstallPath();
  285. ga.RequestPageView($"{GetCheckedRadioButtonNameEn()}/{lblVersion.Text}/switch", "切换标签页");
  286. EnableAllButton(true);
  287. lblVersion.Text = "";
  288. btnRestore.Enabled = false;
  289. // 显示是否能够备份还原
  290. if (!string.IsNullOrEmpty(txtPath.Text))
  291. {
  292. modifier.InitEditors(txtPath.Text);
  293. lblVersion.Text = modifier.GetVersion();
  294. btnRestore.Enabled = modifier.BackupExists();
  295. }
  296. }
  297. private string GetCheckedRadioButtonNameEn()
  298. {
  299. if (rbtWechat.Checked)
  300. {
  301. return "wechat";
  302. }
  303. else if (rbtQQ.Checked)
  304. {
  305. return "qq";
  306. }
  307. else if (rbtTIM.Checked)
  308. {
  309. return "tim";
  310. }
  311. else if (rbtQQLite.Checked)
  312. {
  313. return "qqlite";
  314. }
  315. return "none";
  316. }
  317. private void EnableAllButton(bool state)
  318. {
  319. foreach (Control c in this.Controls)
  320. {
  321. if (c is Button)
  322. {
  323. c.Enabled = state;
  324. }
  325. }
  326. }
  327. }
  328. }