feat: 接入Mirror酱
This commit is contained in:
parent
df43422613
commit
7f40cd7c1b
554
DoroHelper.ahk
554
DoroHelper.ahk
|
@ -107,6 +107,7 @@ global g_settings := Map(
|
|||
;其他
|
||||
"AutoCheckUpdate", 0, ;自动检查更新
|
||||
"isPreRelease", 1, ;启用预发布通道
|
||||
"MirrorUpdate", 0, ;使用Mirror酱检查和更新
|
||||
"AdjustSize", 0, ;启用画面缩放
|
||||
"SelfClosing", 0, ;完成后自动关闭程序
|
||||
"OpenBlablalink", 1, ;完成后打开Blablalink
|
||||
|
@ -115,7 +116,8 @@ global g_settings := Map(
|
|||
global g_numeric_settings := Map(
|
||||
"SleepTime", 1000, ;默认等待时间
|
||||
"InterceptionBoss", 1, ;拦截战BOSS选择
|
||||
"Tolerance", 1 ;宽容度
|
||||
"Tolerance", 1, ;宽容度
|
||||
"MirrorCDK", "" ;Mirror酱的CDK
|
||||
)
|
||||
;tag 其他全局变量
|
||||
global Victory := 0
|
||||
|
@ -131,12 +133,11 @@ try {
|
|||
catch {
|
||||
WriteSettings()
|
||||
}
|
||||
if g_settings["AutoCheckUpdate"] {
|
||||
CheckForUpdateHandler(false) ;调用核心函数,标记为非手动检查
|
||||
}
|
||||
if g_settings["AutoCheckUpdate"]
|
||||
CheckForUpdate(false)
|
||||
;endregion 读取设置
|
||||
;region 创建gui
|
||||
doroGui := Gui("+Resize", "Doro小帮手" currentVersion)
|
||||
doroGui := Gui("+Resize", "DoroHelper - " currentVersion)
|
||||
doroGui.Tips := GuiCtrlTips(doroGui) ; 为 doroGui 实例化 GuiCtrlTips
|
||||
doroGui.Tips.SetBkColor(0xFFFFFF)
|
||||
doroGui.Tips.SetTxColor(0x000000)
|
||||
|
@ -166,6 +167,13 @@ Tab.UseTab("设置")
|
|||
cbAutoCheckUpdate := AddCheckboxSetting(doroGui, "AutoCheckUpdate", "自动检查更新", "Section R1.2")
|
||||
doroGui.Tips.SetTip(cbAutoCheckUpdate, "勾选后,DoroHelper 启动时会自动连接到 Github 检查是否有新版本")
|
||||
AddCheckboxSetting(doroGui, "isPreRelease", "测试版渠道", "x+5 R1.2")
|
||||
MirrorChyan := AddCheckboxSetting(doroGui, "MirrorUpdate", "改用Mirror酱", "R1.2 xs+15")
|
||||
doroGui.Tips.SetTip(MirrorChyan, "Mirror酱是一个第三方应用分发平台,让你能在普通网络环境下更新应用`r`n网址:https://mirrorchyan.com/zh/(付费使用)")
|
||||
MirrorEditControl := doroGui.Add("Edit", "x+5 yp w145 h20")
|
||||
doroGui.Tips.SetTip(MirrorEditControl, "输入你的Mirror酱CDK")
|
||||
MirrorEditControl.Value := g_numeric_settings["MirrorCDK"]
|
||||
MirrorEditControl.OnEvent("Change", (Ctrl, Info) => g_numeric_settings["MirrorCDK"] := Ctrl.Value)
|
||||
cbAdjustSize := AddCheckboxSetting(doroGui, "AdjustSize", "启用窗口调整", "xs R1.2")
|
||||
doroGui.Tips.SetTip(cbAdjustSize, "勾选后,DoroHelper运行前会尝试将窗口调整至合适的尺寸,并在运行结束后还原")
|
||||
cbOpenBlablalink := AddCheckboxSetting(doroGui, "OpenBlablalink", "任务完成后自动打开Blablalink", "R1.2")
|
||||
doroGui.Tips.SetTip(cbOpenBlablalink, "勾选后,当 DoroHelper 完成所有已选任务后,会自动在您的默认浏览器中打开 Blablalink 网站")
|
||||
|
@ -507,108 +515,480 @@ Initialization() {
|
|||
AddLog("不足1080p分辨率")
|
||||
}
|
||||
}
|
||||
; if GameRatio != 1.778 {
|
||||
; MsgBox ("请将游戏画面比例调整至16:9")
|
||||
; }
|
||||
}
|
||||
;endregion 初始化
|
||||
;region 软件更新
|
||||
;tag 检查更新
|
||||
CheckForUpdateHandler(isManualCheck) {
|
||||
global currentVersion, usr, repo, latestObj ;确保能访问全局变量
|
||||
try {
|
||||
allReleases := Github.historicReleases(usr, repo) ; 获取所有版本
|
||||
if !IsObject(allReleases) || !allReleases.Length {
|
||||
;tag 统一检查更新
|
||||
CheckForUpdate(isManualCheck) {
|
||||
; 全局变量声明 - 确保这些在函数外部有定义
|
||||
global currentVersion, usr, repo, latestObj, g_settings, g_numeric_settings
|
||||
latestObj := Map( ; 初始化 latestObj Map
|
||||
"version", "",
|
||||
"change_notes", "无更新说明。",
|
||||
"download_url", "",
|
||||
"source", "",
|
||||
"display_name", ""
|
||||
)
|
||||
local foundNewVersion := false
|
||||
local sourceName := ""
|
||||
local channelInfo := g_settings["isPreRelease"] ? "预发布" : "稳定"
|
||||
; ==================== Mirror酱 更新检查 ====================
|
||||
if g_settings["MirrorUpdate"] {
|
||||
latestObj.source := "mirror"
|
||||
latestObj.display_name := "Mirror酱"
|
||||
sourceName := "Mirror酱"
|
||||
AddLog(sourceName . " 更新检查:开始 (" . channelInfo . " 渠道)...")
|
||||
if Trim(g_numeric_settings["MirrorCDK"]) = "" {
|
||||
if (isManualCheck) {
|
||||
MsgBox("无法获取版本列表,请检查网络或仓库信息。", "检查更新错误", "IconX")
|
||||
MsgBox("Mirror酱 CDK 为空,无法检查更新。", sourceName . "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog(sourceName . " 更新检查:CDK为空。")
|
||||
return
|
||||
}
|
||||
targetRelease := "" ; 用于存储我们最终选择的版本对象
|
||||
local apiUrl := "https://mirrorchyan.com/api/resources/DoroHelper/latest?"
|
||||
apiUrl .= "cdk=" . g_numeric_settings["MirrorCDK"]
|
||||
if g_settings["isPreRelease"] {
|
||||
; 用户希望接收预发布版本,直接取最新的(通常是列表的第一个)
|
||||
targetRelease := allReleases[1]
|
||||
AddLog("检查更新:当前设置为预发布版优先,最新版本为 " . targetRelease.version)
|
||||
} else {
|
||||
; 用户希望接收稳定版本,遍历查找最新的稳定版
|
||||
AddLog("检查更新:当前设置为稳定版优先,正在查找...")
|
||||
for release in allReleases {
|
||||
; 简单的预发布版判断:如果版本名不包含beta, alpha, rc等
|
||||
if !(InStr(release.version, "beta") || InStr(release.version, "alpha") || InStr(release.version, "rc")) {
|
||||
targetRelease := release
|
||||
AddLog("找到最新稳定版:" . targetRelease.version)
|
||||
break ; 找到最新的稳定版后即停止
|
||||
}
|
||||
apiUrl .= "&channel=beta"
|
||||
}
|
||||
local HttpRequest := ""
|
||||
local ResponseStatus := 0
|
||||
local ResponseBody := "" ; 用于存储原始字节流
|
||||
try {
|
||||
HttpRequest := ComObject("WinHttp.WinHttpRequest.5.1")
|
||||
HttpRequest.Open("GET", apiUrl, false)
|
||||
HttpRequest.SetRequestHeader("User-Agent", "DoroHelper-AHK-Script/" . currentVersion)
|
||||
HttpRequest.Send()
|
||||
ResponseStatus := HttpRequest.Status
|
||||
if (ResponseStatus = 200) { ; 仅当成功时获取 ResponseBody
|
||||
ResponseBody := HttpRequest.ResponseBody
|
||||
}
|
||||
if !IsObject(targetRelease) { ; 如果遍历后没有找到合适的稳定版
|
||||
if (isManualCheck) {
|
||||
MsgBox("未找到合适的稳定版本。", "检查更新")
|
||||
} catch as e {
|
||||
if (isManualCheck) {
|
||||
MsgBox(sourceName . " API 请求失败: " . e.Message, sourceName . "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog(sourceName . " API 请求失败: " . e.Message)
|
||||
return
|
||||
}
|
||||
local ResponseTextForJson := "" ; 用于 JSON 解析的文本
|
||||
if (ResponseStatus = 200) {
|
||||
if (IsObject(ResponseBody) && (ComObjType(ResponseBody) & 0x2000)) { ; 检查是否为 SafeArray (VT_ARRAY)
|
||||
try {
|
||||
local dataPtr := 0
|
||||
local lBound := 0
|
||||
local uBound := 0
|
||||
DllCall("OleAut32\SafeArrayGetLBound", "Ptr", ComObjValue(ResponseBody), "UInt", 1, "Int64*", &lBound)
|
||||
DllCall("OleAut32\SafeArrayGetUBound", "Ptr", ComObjValue(ResponseBody), "UInt", 1, "Int64*", &uBound)
|
||||
local actualSize := uBound - lBound + 1
|
||||
if (actualSize > 0) {
|
||||
DllCall("OleAut32\SafeArrayAccessData", "Ptr", ComObjValue(ResponseBody), "Ptr*", &dataPtr)
|
||||
ResponseTextForJson := StrGet(dataPtr, actualSize, "UTF-8")
|
||||
DllCall("OleAut32\SafeArrayUnaccessData", "Ptr", ComObjValue(ResponseBody))
|
||||
AddLog(sourceName . " DEBUG: ResponseBody (SafeArray) converted to UTF-8 string using StrGet.")
|
||||
} else {
|
||||
AddLog(sourceName . " 警告: SafeArray 大小为0或无效。")
|
||||
ResponseTextForJson := "" ; 确保 ResponseTextForJson 有定义
|
||||
}
|
||||
} catch as e_sa {
|
||||
AddLog(sourceName . " 错误: 处理 ResponseBody (SafeArray) 失败: " . e_sa.Message ". 类型: " . ComObjType(ResponseBody, "Name"))
|
||||
ResponseTextForJson := HttpRequest.ResponseText ; 回退
|
||||
AddLog(sourceName . " 警告: SafeArray 处理失败,回退到 HttpRequest.ResponseText,可能存在编码问题。")
|
||||
}
|
||||
AddLog("未找到合适的稳定版本。")
|
||||
} else if (IsObject(ResponseBody)) {
|
||||
AddLog(sourceName . " 警告: ResponseBody 是对象但不是 SafeArray (类型: " . ComObjType(ResponseBody, "Name") . "),尝试 ADODB.Stream。")
|
||||
try {
|
||||
local Stream := ComObject("ADODB.Stream")
|
||||
Stream.Type := 1 ; adTypeBinary
|
||||
Stream.Open()
|
||||
Stream.Write(ResponseBody)
|
||||
Stream.Position := 0
|
||||
Stream.Type := 2 ; adTypeText
|
||||
Stream.Charset := "utf-8"
|
||||
ResponseTextForJson := Stream.ReadText()
|
||||
Stream.Close()
|
||||
AddLog(sourceName . " DEBUG: ResponseBody (non-SafeArray COM Object) converted to UTF-8 string using ADODB.Stream.")
|
||||
} catch as e_adodb {
|
||||
AddLog(sourceName . " 错误: ADODB.Stream 处理 ResponseBody (non-SafeArray COM Object) 失败: " . e_adodb.Message)
|
||||
ResponseTextForJson := HttpRequest.ResponseText ; 最终回退
|
||||
AddLog(sourceName . " 警告: ADODB.Stream 失败,回退到 HttpRequest.ResponseText,可能存在编码问题。")
|
||||
}
|
||||
} else {
|
||||
AddLog(sourceName . " 警告: ResponseBody 不是 COM 对象,或请求未成功。将直接使用 HttpRequest.ResponseText。")
|
||||
ResponseTextForJson := HttpRequest.ResponseText
|
||||
}
|
||||
AddLog(sourceName . " API Response Status 200. Decoded ResponseTextForJson (first 500 chars): " . SubStr(ResponseTextForJson, 1, 500))
|
||||
try {
|
||||
local JsonData := Json.Load(&ResponseTextForJson)
|
||||
if (!IsObject(JsonData)) {
|
||||
if (isManualCheck) MsgBox(sourceName . " API 响应格式错误。", sourceName . "检查更新错误", "IconX")
|
||||
AddLog(sourceName . " API 响应未能解析为JSON. ResponseText (first 200): " . SubStr(ResponseTextForJson, 1, 200))
|
||||
return
|
||||
}
|
||||
local jsonDataCode := JsonData.Get("code", -1)
|
||||
local potentialData := JsonData.Get("data", unset)
|
||||
if (jsonDataCode != 0) {
|
||||
local errorMsg := sourceName . " API 返回错误。 Code: " . jsonDataCode . "."
|
||||
if (JsonData.Has("msg") && Trim(JsonData.msg) != "") {
|
||||
errorMsg .= " 消息: " . JsonData.msg
|
||||
} else {
|
||||
errorMsg .= " (API未提供详细错误消息)"
|
||||
}
|
||||
if (isManualCheck) {
|
||||
MsgBox(errorMsg, sourceName . "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog(errorMsg)
|
||||
return
|
||||
}
|
||||
if (!IsSet(potentialData) || !IsObject(potentialData)) {
|
||||
local errorMsg := sourceName . " API 响应成功 (code 0),但 'data' 字段缺失或非对象类型。"
|
||||
if (JsonData.Has("msg") && Trim(JsonData.msg) != "") {
|
||||
errorMsg .= " API 消息: " . JsonData.msg
|
||||
}
|
||||
if (isManualCheck) {
|
||||
MsgBox(errorMsg, sourceName . "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog(errorMsg . " Type of 'data' retrieved: " . Type(potentialData))
|
||||
return
|
||||
}
|
||||
local mirrorData := potentialData
|
||||
latestObj.version := mirrorData.Get("version_name", "")
|
||||
latestObj.change_notes := mirrorData.Get("release_note", "无更新说明。")
|
||||
latestObj.download_url := mirrorData.Get("url", "")
|
||||
if latestObj.version = "" {
|
||||
if (isManualCheck) {
|
||||
MsgBox(sourceName . " API 响应中版本信息为空。", sourceName . "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog(sourceName . " 更新检查:API响应中版本信息为空。")
|
||||
return
|
||||
}
|
||||
AddLog(sourceName . " 更新检查:获取到版本 " . latestObj.version)
|
||||
if (CompareVersionsSemVer(latestObj.version, currentVersion) > 0) {
|
||||
foundNewVersion := true
|
||||
AddLog(sourceName . " 版本比较:发现新版本。")
|
||||
} else {
|
||||
AddLog(sourceName . " 版本比较:当前已是最新或更新。")
|
||||
}
|
||||
} catch as e {
|
||||
local errorDetails := "错误类型: " . Type(e) . ", 消息: " . e.Message
|
||||
if e.HasProp("What") errorDetails .= "`n触发对象/操作: " . e.What
|
||||
if e.HasProp("File") errorDetails .= "`n文件: " . e.File
|
||||
if e.HasProp("Line") errorDetails .= "`n行号: " . e.Line
|
||||
if (isManualCheck) MsgBox("处理 " . sourceName . " JSON 数据时发生内部错误: `n" . errorDetails, sourceName . "检查更新错误", "IconX")
|
||||
AddLog(sourceName . " 更新检查:处理JSON时发生内部错误: " . errorDetails)
|
||||
AddLog(sourceName . " 相关的 ResponseTextForJson (前1000字符): " . SubStr(ResponseTextForJson, 1, 1000))
|
||||
return
|
||||
}
|
||||
}
|
||||
latestObj := targetRelease ; 将选定的版本赋给 latestObj 供后续使用
|
||||
if (currentVersion != latestObj.version) {
|
||||
MyGui := Gui("+Resize", "更新提示")
|
||||
MyGui.Add("Text", "w300 xm ym", "DoroHelper存在更新版本 (" . (g_settings["isPreRelease"] ? "预发布" : "稳定") . "):") ; 提示版本类型
|
||||
MyGui.Add("Text", "xp yp+20 w300", "版本号: " . latestObj.version)
|
||||
MyGui.Add("Text", "xp yp+20 w300", "更新内容:")
|
||||
MyEdit := MyGui.Add("Edit", "w250 h200 ReadOnly VScroll Border", latestObj.change_notes)
|
||||
MyGui.Add("Text", "xp yp+210 w300", "`n是否下载?")
|
||||
userresponse := ""
|
||||
MyGui.Add("Button", "xm w100", "是").OnEvent("Click", DownloadHandler)
|
||||
MyGui.Add("Button", "x+10 w100", "否").OnEvent("Click", (*) => MyGui.Destroy())
|
||||
MyGui.Show("w300 h350 Center ")
|
||||
}
|
||||
else {
|
||||
;没有新版本
|
||||
if (isManualCheck) { ;只有手动检查时才提示
|
||||
MsgBox("当前Doro (" . (g_settings["isPreRelease"] ? "预发布通道" : "稳定版通道") . ")已是最新版本: " . currentVersion, "检查更新")
|
||||
} else { ; ResponseStatus != 200
|
||||
local errorResponseText := HttpRequest.ResponseText ; 尝试获取错误响应文本
|
||||
local responseTextPreview := SubStr(errorResponseText, 1, 300)
|
||||
if (isManualCheck) {
|
||||
MsgBox(sourceName . " API 请求失败!`n状态码: " . ResponseStatus . "`n响应预览:`n" . responseTextPreview, sourceName . " API 错误", "IconX")
|
||||
}
|
||||
}
|
||||
}
|
||||
catch as githubError {
|
||||
;只有手动检查时才提示连接错误,自动检查时静默失败
|
||||
if (isManualCheck) {
|
||||
MsgBox("检查更新失败,无法连接到Github或仓库信息错误`n(" githubError.Message ")", "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog("检查更新失败: " . githubError.Message)
|
||||
}
|
||||
}
|
||||
;tag 专用下载处理函数
|
||||
DownloadHandler(*) {
|
||||
try {
|
||||
downloadTempName := "DoroDownload.exe"
|
||||
finalName := "DoroHelper-" latestObj.version ".exe"
|
||||
local downloadUrlToUse := ""
|
||||
if IsObject(latestObj.downloadURLs) && latestObj.downloadURLs.Length > 0 {
|
||||
downloadUrlToUse := latestObj.downloadURLs[1]
|
||||
} else if IsObject(latestObj.downloadURL) { ; 兼容 historicReleases 返回的单个 downloadURL
|
||||
downloadUrlToUse := latestObj.downloadURL
|
||||
} else {
|
||||
MsgBox("错误:找不到有效的下载链接。", "下载错误", "IconX")
|
||||
AddLog(sourceName . " API 请求失败!状态码: " . ResponseStatus . ", 响应预览: " . responseTextPreview)
|
||||
return
|
||||
}
|
||||
; ==================== Github 更新检查 (如果 MirrorUpdate 未启用) ====================
|
||||
} else {
|
||||
latestObj.source := "github"
|
||||
latestObj.display_name := "Github"
|
||||
sourceName := "Github"
|
||||
AddLog(sourceName . " 更新检查:开始 (" . channelInfo . " 渠道)...")
|
||||
try {
|
||||
local allReleases := Github.historicReleases(usr, repo) ; 获取所有版本
|
||||
if !(allReleases is Array) || !allReleases.Length { ; AHK v2: is Array
|
||||
if (isManualCheck) {
|
||||
MsgBox("无法获取 Github 版本列表,请检查网络或仓库信息。", sourceName . "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog(sourceName . " 更新检查:无法获取版本列表。")
|
||||
return
|
||||
}
|
||||
local targetRelease := ""
|
||||
if g_settings["isPreRelease"] {
|
||||
targetRelease := allReleases[1]
|
||||
if !(IsObject(targetRelease) && (targetRelease.HasProp("version") || targetRelease.HasProp("tag_name"))) {
|
||||
local errMsg := sourceName . " 更新检查:获取到的最新预发布 Release 对象无效或缺少版本信息。"
|
||||
if (isManualCheck) MsgBox(errMsg, sourceName . "检查更新错误", "IconX")
|
||||
AddLog(errMsg)
|
||||
return
|
||||
}
|
||||
AddLog(sourceName . " 更新检查:预发布版优先,已选定 Release。")
|
||||
} else {
|
||||
AddLog(sourceName . " 更新检查:稳定版优先,正在查找...")
|
||||
for release_item in allReleases {
|
||||
if !(IsObject(release_item) && (release_item.HasProp("version") || release_item.HasProp("tag_name"))) {
|
||||
AddLog(sourceName . " DEBUG: 跳过一个无效的或缺少版本信息的 Release 对象。")
|
||||
continue
|
||||
}
|
||||
local current_release_version := release_item.HasProp("version") ? release_item.version : release_item.tag_name
|
||||
if !(InStr(current_release_version, "beta") || InStr(current_release_version, "alpha") || InStr(current_release_version, "rc")) {
|
||||
targetRelease := release_item
|
||||
AddLog(sourceName . " 更新检查:找到稳定版 " . current_release_version)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !IsObject(targetRelease) {
|
||||
AddLog(sourceName . " 更新检查:未找到稳定版,将使用最新版本进行比较。")
|
||||
targetRelease := allReleases[1]
|
||||
if !(IsObject(targetRelease) && (targetRelease.HasProp("version") || targetRelease.HasProp("tag_name"))) {
|
||||
local errMsg := sourceName . " 更新检查:回退到的最新 Release 对象也无效或缺少版本信息。"
|
||||
if (isManualCheck) MsgBox(errMsg, sourceName . "检查更新错误", "IconX")
|
||||
AddLog(errMsg)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if !IsObject(targetRelease) {
|
||||
local errMsg := sourceName . " 更新检查:最终未能确定有效的 targetRelease 对象。"
|
||||
if (isManualCheck) MsgBox(errMsg, sourceName . "检查更新错误", "IconX")
|
||||
AddLog(errMsg)
|
||||
return
|
||||
}
|
||||
; 版本号
|
||||
if (targetRelease.HasProp("version")) {
|
||||
latestObj.version := targetRelease.version
|
||||
} else if (targetRelease.HasProp("tag_name")) {
|
||||
latestObj.version := targetRelease.tag_name
|
||||
} else {
|
||||
latestObj.version := ""
|
||||
AddLog(sourceName . " 警告: Release 对象缺少 'version' 或 'tag_name' 属性。")
|
||||
}
|
||||
; 更新内容
|
||||
if (targetRelease.HasProp("change_notes")) {
|
||||
latestObj.change_notes := targetRelease.change_notes
|
||||
} else if (targetRelease.HasProp("body")) {
|
||||
latestObj.change_notes := targetRelease.body
|
||||
} else {
|
||||
latestObj.change_notes := "无更新说明。"
|
||||
}
|
||||
if Trim(latestObj.change_notes) = "" {
|
||||
latestObj.change_notes := "无更新说明。"
|
||||
}
|
||||
; 下载链接
|
||||
latestObj.download_url := "" ; 初始化
|
||||
if (targetRelease.HasProp("downloadURL") && Trim(targetRelease.downloadURL) != "") {
|
||||
latestObj.download_url := targetRelease.downloadURL
|
||||
AddLog(sourceName . " 找到下载链接 (from downloadURL): " . latestObj.download_url)
|
||||
}
|
||||
else if (targetRelease.HasProp("assets") && targetRelease.assets is Array && targetRelease.assets.Length > 0) { ; AHK v2: is Array
|
||||
AddLog(sourceName . " DEBUG: (Fallback) 'downloadURL' not found. Checking 'assets'.")
|
||||
for asset in targetRelease.assets {
|
||||
if IsObject(asset) && asset.HasProp("name") && asset.HasProp("browser_download_url") {
|
||||
AddLog(sourceName . " DEBUG: Checking asset: " . asset.name)
|
||||
if (InStr(asset.name, "DoroHelper") && InStr(asset.name, ".exe")) {
|
||||
latestObj.download_url := asset.browser_download_url
|
||||
AddLog(sourceName . " 找到 .exe asset 下载链接 (from assets): " . latestObj.download_url)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (latestObj.download_url = "")
|
||||
AddLog(sourceName . " 警告: 在 'assets' 中未精确匹配到 'DoroHelper*.exe' 或 'assets' 结构不符。")
|
||||
}
|
||||
else if (targetRelease.HasProp("downloadURLs") && targetRelease.downloadURLs is Array && targetRelease.downloadURLs.Length > 0 && Trim(targetRelease.downloadURLs[1]) != "") { ; AHK v2: is Array
|
||||
latestObj.download_url := targetRelease.downloadURLs[1]
|
||||
AddLog(sourceName . " 使用 downloadURLs[1] 作为下载链接 (Fallback): " . latestObj.download_url)
|
||||
}
|
||||
else if (targetRelease.HasProp("download_url") && Trim(targetRelease.download_url) != "") {
|
||||
latestObj.download_url := targetRelease.download_url
|
||||
AddLog(sourceName . " 使用顶层 download_url 属性作为下载链接 (Fallback): " . latestObj.download_url)
|
||||
}
|
||||
else {
|
||||
AddLog(sourceName . " 警告: Release 对象未找到任何有效的下载链接属性 (已尝试: downloadURL, assets, downloadURLs, download_url)。")
|
||||
}
|
||||
if latestObj.version = "" {
|
||||
local errMsg := sourceName . " 更新检查:未能从选定的 Release 对象获取版本号。"
|
||||
if (isManualCheck) MsgBox(errMsg, sourceName . "检查更新错误", "IconX")
|
||||
AddLog(errMsg)
|
||||
return
|
||||
}
|
||||
if latestObj.download_url = "" {
|
||||
AddLog(sourceName . " 警告: 未能为版本 " . latestObj.version . " 找到有效的下载链接。")
|
||||
}
|
||||
AddLog(sourceName . " 更新检查:获取到版本 " . latestObj.version . (latestObj.download_url ? "" : " (下载链接未找到)"))
|
||||
if (CompareVersionsSemVer(latestObj.version, currentVersion) > 0) {
|
||||
foundNewVersion := true
|
||||
AddLog(sourceName . " 版本比较:发现新版本。")
|
||||
} else {
|
||||
AddLog(sourceName . " 版本比较:当前已是最新或更新。")
|
||||
}
|
||||
} catch as githubError {
|
||||
if (isManualCheck) {
|
||||
MsgBox("Github 检查更新失败: `n" . githubError.Message . (githubError.HasProp("Extra") ? "`nExtra: " . githubError.Extra : ""), sourceName . "检查更新错误", "IconX")
|
||||
}
|
||||
AddLog(sourceName . " 检查更新失败: " . githubError.Message . (githubError.HasProp("Extra") ? ". Extra: " . githubError.Extra : ""))
|
||||
return
|
||||
}
|
||||
Github.Download(downloadUrlToUse, A_ScriptDir "\" downloadTempName)
|
||||
FileMove(A_ScriptDir "\" downloadTempName, A_ScriptDir "\" finalName, 1)
|
||||
MsgBox("新版本已下载至当前目录: " finalName, "下载完成")
|
||||
ExitApp
|
||||
}
|
||||
catch as downloadError {
|
||||
MsgBox("下载失败,请检查网络`n(" downloadError.Message ")", "下载错误", "IconX")
|
||||
if FileExist(A_ScriptDir "\" downloadTempName)
|
||||
FileDelete(A_ScriptDir "\" downloadTempName)
|
||||
; ==================== 处理检查结果 ====================
|
||||
if foundNewVersion {
|
||||
AddLog(sourceName . " 更新检查:发现新版本 " . latestObj.version . ",准备提示用户。")
|
||||
if (latestObj.download_url = "" && isManualCheck) {
|
||||
MsgBox("已检测到新版本 " . latestObj.version . ",但未能获取到下载链接。请检查 Github 库或手动下载。", "更新提示", "IconW")
|
||||
}
|
||||
local MyGui := Gui("+Resize", "更新提示 (" . latestObj.display_name . ")")
|
||||
MyGui.SetFont("s10", "Microsoft YaHei UI")
|
||||
MyGui.Add("Text", "w300 xm ym", "发现 DoroHelper 新版本 (" . channelInfo . " - " . latestObj.display_name . "):")
|
||||
MyGui.Add("Text", "xp+10 yp+25 w300", "最新版本: " . latestObj.version)
|
||||
MyGui.Add("Text", "xp yp+20 w300", "当前版本: " . currentVersion)
|
||||
MyGui.Add("Text", "xp yp+25 w300", "更新内容:")
|
||||
local notes_for_edit := latestObj.change_notes
|
||||
notes_for_edit := StrReplace(notes_for_edit, "`r`n", "`n") ; 先统一为 \n
|
||||
notes_for_edit := StrReplace(notes_for_edit, "`r", "`n") ; \r 也统一为 \n
|
||||
notes_for_edit := StrReplace(notes_for_edit, "`n", "`r`n") ; 再统一为 Edit 控件的 \r\n
|
||||
MyGui.Add("Edit", "w250 h200 ReadOnly VScroll Border", notes_for_edit)
|
||||
MyGui.Add("Button", "xm+20 w100 h30 yp+220", "立即下载").OnEvent("Click", DownloadUpdate)
|
||||
MyGui.Add("Button", "x+20 w100 h30", "稍后提醒").OnEvent("Click", (*) => MyGui.Destroy())
|
||||
MyGui.Show("w320 h400 Center")
|
||||
} else if latestObj.version != "" {
|
||||
AddLog(sourceName . " 更新检查:当前已是最新版本 " . currentVersion)
|
||||
if (isManualCheck) {
|
||||
MsgBox("当前通道为:" . channelInfo . "通道 - " . latestObj.display_name . "`n最新版本为:" . latestObj.version "`n当前版本为:" . currentVersion "`n当前已是最新版本", "检查更新", "IconI")
|
||||
}
|
||||
} else {
|
||||
AddLog((sourceName ? sourceName : "更新") . " 更新检查:未能获取到有效的版本信息或检查被中止。")
|
||||
if (isManualCheck) {
|
||||
MsgBox("未能完成更新检查。请查看日志了解详情。", "检查更新", "IconX")
|
||||
}
|
||||
}
|
||||
}
|
||||
;tag 统一更新下载
|
||||
DownloadUpdate(*) {
|
||||
global latestObj
|
||||
if !IsObject(latestObj) || !latestObj.Has("source") || latestObj.source = "" || !latestObj.Has("version") || latestObj.version = "" {
|
||||
MsgBox("下载错误:更新信息不完整,无法开始下载。", "下载错误", "IconX")
|
||||
AddLog("下载错误:latestObj 信息不完整。 Source: " . latestObj.Get("source", "N/A") . ", Version: " . latestObj.Get("version", "N/A"))
|
||||
return
|
||||
}
|
||||
downloadTempName := "DoroDownload.exe"
|
||||
finalName := "DoroHelper-" latestObj.version ".exe"
|
||||
downloadUrlToUse := latestObj.download_url
|
||||
if downloadUrlToUse = "" {
|
||||
MsgBox("错误:找不到有效的 " . latestObj.display_name . " 下载链接。", "下载错误", "IconX")
|
||||
AddLog(latestObj.display_name . " 下载错误:下载链接为空。")
|
||||
return
|
||||
}
|
||||
AddLog(latestObj.display_name . " 下载:开始下载 " . downloadUrlToUse . " 到 " . A_ScriptDir "\" finalName)
|
||||
local downloadStatusCode := 0 ; 用于存储下载结果
|
||||
try {
|
||||
if latestObj.source == "github" {
|
||||
ErrorLevel := 0
|
||||
Github.Download(downloadUrlToUse, A_ScriptDir "\" downloadTempName)
|
||||
downloadStatusCode := ErrorLevel
|
||||
if downloadStatusCode != 0 {
|
||||
throw Error("Github 下载失败 (ErrorLevel: " . downloadStatusCode . "). 检查 Github.Download 库的内部提示或网络。")
|
||||
}
|
||||
} else if latestObj.source == "mirror" {
|
||||
ErrorLevel := 0
|
||||
Download downloadUrlToUse, A_ScriptDir "\" downloadTempName
|
||||
downloadStatusCode := ErrorLevel
|
||||
if downloadStatusCode != 0 {
|
||||
throw Error("Mirror酱下载失败 (错误代码: " . downloadStatusCode . ")")
|
||||
}
|
||||
} else {
|
||||
throw Error("未知的下载源: " . latestObj.source)
|
||||
}
|
||||
FileMove A_ScriptDir "\" downloadTempName, A_ScriptDir "\" finalName, 1
|
||||
MsgBox("新版本已通过 " . latestObj.display_name . " 下载至当前目录: `n" . A_ScriptDir "\" finalName, "下载完成")
|
||||
AddLog(latestObj.display_name . " 下载:成功下载并保存为 " . finalName)
|
||||
ExitApp
|
||||
} catch as downloadError {
|
||||
MsgBox(latestObj.display_name . " 下载失败: `n" . downloadError.Message, "下载错误", "IconX")
|
||||
AddLog(latestObj.display_name . " 下载失败: " . downloadError.Message)
|
||||
if FileExist(A_ScriptDir "\" downloadTempName) {
|
||||
try {
|
||||
FileDelete(A_ScriptDir "\" downloadTempName)
|
||||
} catch {
|
||||
; 忽略删除临时文件失败
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
;tag 点击检查更新
|
||||
ClickOnCheckForUpdate(*) {
|
||||
; if InStr(currentVersion, "beta") {
|
||||
; MsgBox ("测试版本禁用更新!")
|
||||
; MsgBox ("请加群584275905")
|
||||
; Pause
|
||||
; }
|
||||
CheckForUpdateHandler(true) ;调用核心函数,标记为手动检查
|
||||
AddLog("=== 更新检查启动 (手动) ===")
|
||||
CheckForUpdate(true)
|
||||
}
|
||||
;tag 版本比较
|
||||
CompareVersionsSemVer(v1, v2) {
|
||||
_IsNumericString(str) => RegExMatch(str, "^\d+$")
|
||||
v1 := RegExReplace(v1, "^v", "")
|
||||
v2 := RegExReplace(v2, "^v", "")
|
||||
v1Parts := StrSplit(v1, "+", , 2)
|
||||
v2Parts := StrSplit(v2, "+", , 2)
|
||||
v1Base := v1Parts[1]
|
||||
v2Base := v2Parts[1]
|
||||
v1CoreParts := StrSplit(v1Base, "-", , 2)
|
||||
v2CoreParts := StrSplit(v2Base, "-", , 2)
|
||||
v1Core := v1CoreParts[1]
|
||||
v2Core := v2CoreParts[1]
|
||||
v1Pre := v1CoreParts.Length > 1 ? v1CoreParts[2] : ""
|
||||
v2Pre := v2CoreParts.Length > 1 ? v2CoreParts[2] : ""
|
||||
v1CoreNums := StrSplit(v1Core, ".")
|
||||
v2CoreNums := StrSplit(v2Core, ".")
|
||||
loop 3 {
|
||||
local seg1Str := A_Index <= v1CoreNums.Length ? Trim(v1CoreNums[A_Index]) : "0"
|
||||
local seg2Str := A_Index <= v2CoreNums.Length ? Trim(v2CoreNums[A_Index]) : "0"
|
||||
if !_IsNumericString(seg1Str) {
|
||||
seg1Str := "0"
|
||||
}
|
||||
if !_IsNumericString(seg2Str) {
|
||||
seg2Str := "0"
|
||||
}
|
||||
num1 := Integer(seg1Str)
|
||||
num2 := Integer(seg2Str)
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
}
|
||||
if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
hasV1Pre := v1Pre != ""
|
||||
hasV2Pre := v2Pre != ""
|
||||
if (hasV1Pre && !hasV2Pre) {
|
||||
return -1
|
||||
}
|
||||
if (!hasV1Pre && hasV2Pre) {
|
||||
return 1
|
||||
}
|
||||
if (!hasV1Pre && !hasV2Pre) {
|
||||
return 0
|
||||
}
|
||||
v1PreSegments := StrSplit(v1Pre, ".")
|
||||
v2PreSegments := StrSplit(v2Pre, ".")
|
||||
maxLen := Max(v1PreSegments.Length, v2PreSegments.Length)
|
||||
loop maxLen {
|
||||
if (A_Index > v1PreSegments.Length) {
|
||||
return -1
|
||||
}
|
||||
if (A_Index > v2PreSegments.Length) {
|
||||
return 1
|
||||
}
|
||||
seg1 := Trim(v1PreSegments[A_Index])
|
||||
seg2 := Trim(v2PreSegments[A_Index])
|
||||
isNum1 := _IsNumericString(seg1)
|
||||
isNum2 := _IsNumericString(seg2)
|
||||
if (isNum1 && isNum2) {
|
||||
numSeg1 := Integer(seg1)
|
||||
numSeg2 := Integer(seg2)
|
||||
if (numSeg1 > numSeg2)
|
||||
return 1
|
||||
if (numSeg1 < numSeg2)
|
||||
return -1
|
||||
} else if (!isNum1 && !isNum2) {
|
||||
; 强制进行字符串比较
|
||||
compareResult := StrCompare(seg1, seg2)
|
||||
if (compareResult > 0)
|
||||
return 1
|
||||
if (compareResult < 0)
|
||||
return -1
|
||||
} else {
|
||||
if (isNum1)
|
||||
return -1
|
||||
if (isNum2)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
;endregion 软件更新
|
||||
;region 消息辅助函数
|
||||
|
|
Loading…
Reference in New Issue