diff --git a/BetterGenshinImpact/Core/Script/Dependence/Http.cs b/BetterGenshinImpact/Core/Script/Dependence/Http.cs
new file mode 100644
index 00000000..5a5e43cf
--- /dev/null
+++ b/BetterGenshinImpact/Core/Script/Dependence/Http.cs
@@ -0,0 +1,84 @@
+using BetterGenshinImpact.Core.Script.Utils;
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using OpenCvSharp;
+using System.Linq;
+using System.Text.Json;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Text;
+using BetterGenshinImpact.GameTask;
+
+namespace BetterGenshinImpact.Core.Script.Dependence;
+
+public class Http
+{
+ private bool CheckHttpPermission()
+ {
+ try
+ {
+ var currentProject = TaskContext.Instance().CurrentScriptProject;
+ return currentProject?.AllowJsHTTP ?? false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// 执行HTTP请求
+ ///
+ /// HTTP方法
+ /// 请求URL
+ /// 请求体
+ public async Task Request(string method, string url, string? body, string? headersJson)
+ {
+ if (!CheckHttpPermission())
+ {
+ throw new UnauthorizedAccessException("当前JS脚本不允许使用HTTP请求,请在调度器通用设置中启用“JS HTTP权限”");
+ }
+ var dictHeaders = new Dictionary();
+ if (!string.IsNullOrWhiteSpace(headersJson))
+ {
+ try
+ {
+ var headers = JsonSerializer.Deserialize>(headersJson);
+ if (headers != null)
+ {
+ dictHeaders = headers;
+ }
+ }
+ catch (JsonException)
+ {
+ throw new ArgumentException("Headers JSON格式错误");
+ }
+ }
+
+ // header全部小写
+ dictHeaders = dictHeaders.ToDictionary(kvp => kvp.Key.ToLowerInvariant(), kvp => kvp.Value);
+
+ // 提前取出来Content-Type,防止被覆盖
+ string contentType = "application/json";
+ if (dictHeaders.TryGetValue("content-type", out var ct))
+ {
+ contentType = ct;
+ dictHeaders.Remove("content-type");
+ }
+
+ // 使用HttpClient发送请求
+ using var httpClient = new HttpClient();
+ httpClient.DefaultRequestHeaders.Clear();
+ foreach (var header in dictHeaders)
+ {
+ httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
+ }
+
+ var content = body == null ? null : new StringContent(body, Encoding.UTF8, contentType);
+ var response = await httpClient.SendAsync(new HttpRequestMessage(new HttpMethod(method), url) { Content = content });
+
+ return await response.Content.ReadAsStringAsync();
+ }
+}
diff --git a/BetterGenshinImpact/Core/Script/EngineExtend.cs b/BetterGenshinImpact/Core/Script/EngineExtend.cs
index a977415d..6c115545 100644
--- a/BetterGenshinImpact/Core/Script/EngineExtend.cs
+++ b/BetterGenshinImpact/Core/Script/EngineExtend.cs
@@ -32,6 +32,7 @@ public class EngineExtend
engine.AddHostObject("genshin", new Dependence.Genshin());
engine.AddHostObject("log", new Log());
engine.AddHostObject("file", new LimitedFile(workDir)); // 限制文件访问
+ engine.AddHostObject("http", new Http()); // 限制文件访问
engine.AddHostObject("notification", new Notification());
// 任务调度器
diff --git a/BetterGenshinImpact/Core/Script/Group/ScriptGroupProject.cs b/BetterGenshinImpact/Core/Script/Group/ScriptGroupProject.cs
index be1bf101..28817a67 100644
--- a/BetterGenshinImpact/Core/Script/Group/ScriptGroupProject.cs
+++ b/BetterGenshinImpact/Core/Script/Group/ScriptGroupProject.cs
@@ -106,6 +106,10 @@ public partial class ScriptGroupProject : ObservableObject
[ObservableProperty]
private bool? _allowJsNotification = true;
+ [ObservableProperty]
+ private bool? _allowJsHTTP = false;
+
+
public ScriptGroupProject()
{
}
diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs
index 29285ced..b513e6aa 100644
--- a/BetterGenshinImpact/Service/ScriptService.cs
+++ b/BetterGenshinImpact/Service/ScriptService.cs
@@ -486,6 +486,7 @@ public partial class ScriptService : IScriptService
target.JsScriptSettingsObject = source.JsScriptSettingsObject;
target.GroupInfo = source.GroupInfo;
target.AllowJsNotification = source.AllowJsNotification;
+ target.AllowJsHTTP = source.AllowJsHTTP;
target.SkipFlag = source.SkipFlag;
}
diff --git a/BetterGenshinImpact/View/Windows/Editable/ScriptGroupProjectEditor.xaml b/BetterGenshinImpact/View/Windows/Editable/ScriptGroupProjectEditor.xaml
index 7fb60ad1..31dcd0a3 100644
--- a/BetterGenshinImpact/View/Windows/Editable/ScriptGroupProjectEditor.xaml
+++ b/BetterGenshinImpact/View/Windows/Editable/ScriptGroupProjectEditor.xaml
@@ -49,6 +49,14 @@
SelectedValue="{Binding AllowJsNotification, Mode=TwoWay}"
Visibility="{Binding IsJsScript, Converter={StaticResource BoolToVisConverter}}">
+
+
+
diff --git a/BetterGenshinImpact/ViewModel/Windows/Editable/ScriptGroupProjectEditorViewModel.cs b/BetterGenshinImpact/ViewModel/Windows/Editable/ScriptGroupProjectEditorViewModel.cs
index 6938617c..376a5d80 100644
--- a/BetterGenshinImpact/ViewModel/Windows/Editable/ScriptGroupProjectEditorViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/Windows/Editable/ScriptGroupProjectEditorViewModel.cs
@@ -35,6 +35,16 @@ public class ScriptGroupProjectEditorViewModel : ObservableObject
}
}
+ public bool? AllowJsHTTP
+ {
+ get => _project.AllowJsHTTP;
+ set
+ {
+ _project.AllowJsHTTP = value;
+ OnPropertyChanged();
+ }
+ }
+
public string Status
{
get => _project.Status;
@@ -58,6 +68,10 @@ public class ScriptGroupProjectEditorViewModel : ObservableObject
{
OnPropertyChanged(nameof(AllowJsNotification));
}
+ if (e.PropertyName == nameof(ScriptGroupProject.AllowJsHTTP))
+ {
+ OnPropertyChanged(nameof(AllowJsHTTP));
+ }
};
}
}