From dff08f1f844e36a28b14f2b463a92af35b64b593 Mon Sep 17 00:00:00 2001 From: XerolySkinner Date: Mon, 29 Dec 2025 11:48:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=B3=E4=BA=8E=E4=BC=81=E4=B8=9A=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ramitta/Ramitta.cs | 25 ++++ Ramitta/WeComRobot.cs | 259 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 284 insertions(+) create mode 100644 Ramitta/WeComRobot.cs diff --git a/Ramitta/Ramitta.cs b/Ramitta/Ramitta.cs index 370b963..1764674 100644 --- a/Ramitta/Ramitta.cs +++ b/Ramitta/Ramitta.cs @@ -118,6 +118,31 @@ namespace Ramitta.lib #endregion #region 文件解析 + public static string? GetExeVersion(string exePath) + { + try + { + if (!File.Exists(exePath)) + { + return null; // 文件不存在时返回null + } + + var versionInfo = FileVersionInfo.GetVersionInfo(exePath); + string? version = versionInfo.FileVersion; + + // 如果FileVersion为空,尝试使用ProductVersion + if (string.IsNullOrEmpty(version)) + { + version = versionInfo.ProductVersion; + } + + return string.IsNullOrEmpty(version) ? null : version; + } + catch + { + return null; // 出现任何异常都返回null + } + } public static bool IsPathExist(string databasePath) { if (string.IsNullOrWhiteSpace(databasePath)) diff --git a/Ramitta/WeComRobot.cs b/Ramitta/WeComRobot.cs new file mode 100644 index 0000000..ea900ca --- /dev/null +++ b/Ramitta/WeComRobot.cs @@ -0,0 +1,259 @@ +锘縰sing HelixToolkit.Maths; +using NPOI.HPSF; +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +namespace Ramitta +{ + public class WeComRobot + { + private readonly string _webhookUrl; + private readonly HttpClient _httpClient; + + public WeComRobot(string webhookUrl) + { + _webhookUrl = webhookUrl; + _httpClient = new HttpClient(); + } + + /// + /// 鍙戦佹枃鏈秷鎭 + /// + public async Task SendTextMessageAsync(string content, string[] mentionedList = null, string[] mentionedMobileList = null) + { + var message = new + { + msgtype = "text", + text = new + { + content = content, + mentioned_list = mentionedList, + mentioned_mobile_list = mentionedMobileList + } + }; + + return await SendMessageAsync(message); + } + + /// + /// 鍙戦丮arkdown娑堟伅 + /// + public async Task SendMarkdownMessageAsync(string content) + { + var message = new + { + msgtype = "markdown", + markdown = new + { + content = content + } + }; + + return await SendMessageAsync(message); + } + + /// + /// 鍙戦佸浘鐗囨秷鎭 + /// + public async Task SendImageMessageAsync(string base64, string md5) + { + var message = new + { + msgtype = "image", + image = new + { + base64 = base64, + md5 = md5 + } + }; + + return await SendMessageAsync(message); + } + + /// + /// 鍙戦佸浘鏂囨秷鎭 + /// + public async Task SendNewsMessageAsync(Article[] articles) + { + var message = new + { + msgtype = "news", + news = new + { + articles = articles + } + }; + + return await SendMessageAsync(message); + } + + /// + /// 鍙戦佹枃浠舵秷鎭 + /// + public async Task SendFileMessageAsync(string mediaId) + { + var message = new + { + msgtype = "file", + file = new + { + media_id = mediaId + } + }; + + return await SendMessageAsync(message); + } + + private async Task SendMessageAsync(object message) + { + try + { + var json = JsonSerializer.Serialize(message); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + var response = await _httpClient.PostAsync(_webhookUrl, content); + var responseContent = await response.Content.ReadAsStringAsync(); + + if (response.IsSuccessStatusCode) + { + var result = JsonSerializer.Deserialize(responseContent); + return result?.errcode == 0; + } + + Console.WriteLine($"鍙戦佸け璐: {responseContent}"); + return false; + } + catch (Exception ex) + { + Console.WriteLine($"鍙戦佹秷鎭紓甯: {ex.Message}"); + return false; + } + } + /// + /// 涓婁紶鏂囦欢鍒颁紒涓氬井淇″苟鑾峰彇media_id (淇鐗) + /// + public async Task UploadFileAsync(string filePath,string? fileName=null) + { + try + { + // 1. 浠巜ebhook鍦板潃涓彁鍙杒ey + var uri = new Uri(_webhookUrl); + var key = System.Web.HttpUtility.ParseQueryString(uri.Query)["key"]; + string uploadUrl = $"https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key={key}&type=file"; + + // 2. 鍑嗗鏂囦欢鍜岃竟鐣 + if(fileName==null) fileName = Path.GetFileName(filePath); + var fileBytes = await File.ReadAllBytesAsync(filePath); + string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x"); // 闅忔満杈圭晫瀛楃涓 + string startBoundary = "--" + boundary; + string endBoundary = "--" + boundary + "--"; + + // 3. 鍒涘缓骞堕厤缃瓾ttpWebRequest + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uploadUrl); + request.Method = "POST"; + request.ContentType = "multipart/form-data; boundary=" + boundary; + request.Timeout = 30000; // 鍙牴鎹渶瑕佽皟鏁磋秴鏃 + + // 4. 鎵嬪姩鏋勫缓骞跺啓鍏ヨ姹備綋锛堝叧閿楠わ級 + using (Stream requestStream = await request.GetRequestStreamAsync()) + { + using (var writer = new StreamWriter(requestStream, Encoding.UTF8, 1024, true)) + { + // 4.1 鍐欏叆寮濮嬭竟鐣 (蹇呴』鏈夊洖杞︽崲琛) + await writer.WriteAsync(startBoundary + "\r\n"); + await writer.FlushAsync(); + + // 4.2 鍐欏叆鏂囦欢澶翠俊鎭 (娉ㄦ剰鏍煎紡涓殑鍙屽紩鍙) + string header = $"Content-Disposition: form-data; name=\"media\"; filename=\"{fileName}\"\r\n"; + header += "Content-Type: application/octet-stream\r\n"; + header += "\r\n"; // 鏂囦欢澶寸粨鏉熷悗闇瑕佷竴涓澶栫殑绌鸿锛堝嵆涓や釜杩炵画鐨刓r\n锛 + await writer.WriteAsync(header); + await writer.FlushAsync(); + + // 4.3 鐩存帴鍐欏叆鏂囦欢瀛楄妭 + await requestStream.WriteAsync(fileBytes, 0, fileBytes.Length); + await writer.WriteAsync("\r\n"); // 鏂囦欢鍐呭鍚庨渶瑕佷竴涓洖杞︽崲琛 + await writer.FlushAsync(); + + // 4.4 鍐欏叆缁撴潫杈圭晫 + await writer.WriteAsync(endBoundary + "\r\n"); + await writer.FlushAsync(); + } + } + + // 5. 鑾峰彇骞惰В鏋愬搷搴 + using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) + using (StreamReader reader = new StreamReader(response.GetResponseStream())) + { + string responseContent = await reader.ReadToEndAsync(); + Console.WriteLine($"涓婁紶鍝嶅簲: {responseContent}"); + + using (var doc = JsonDocument.Parse(responseContent)) + { + if (doc.RootElement.TryGetProperty("media_id", out var mediaIdElement)) + { + return mediaIdElement.GetString(); + } + else + { + // 瑙f瀽閿欒淇℃伅 + var errcode = doc.RootElement.GetProperty("errcode").GetInt32(); + var errmsg = doc.RootElement.GetProperty("errmsg").GetString(); + Console.WriteLine($"鏂囦欢涓婁紶澶辫触: errcode={errcode}, errmsg={errmsg}"); + return null; + } + } + } + } + catch (WebException ex) + { + // 灏濊瘯璇诲彇閿欒鍝嶅簲浣 + if (ex.Response is HttpWebResponse errorResponse) + { + using (var reader = new StreamReader(errorResponse.GetResponseStream())) + { + string errorContent = await reader.ReadToEndAsync(); + Console.WriteLine($"HTTP璇锋眰澶辫触 ({errorResponse.StatusCode}): {errorContent}"); + } + } + else + { + Console.WriteLine($"缃戠粶璇锋眰寮傚父: {ex.Message}"); + } + return null; + } + catch (Exception ex) + { + Console.WriteLine($"鏂囦欢涓婁紶杩囩▼寮傚父: {ex.Message}"); + return null; + } + } + + + } + + /// + /// 鍥炬枃娑堟伅鏂囩珷 + /// + public class Article + { + public string title { get; set; } + public string description { get; set; } + public string url { get; set; } + public string picurl { get; set; } + } + + /// + /// 浼佷笟寰俊鍝嶅簲 + /// + public class WeComResponse + { + public int errcode { get; set; } + public string errmsg { get; set; } + } + +} \ No newline at end of file