mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Fri Aug 2 20:31:39 CEST 2024
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -721,3 +721,4 @@ Update On Mon Jul 29 20:33:10 CEST 2024
|
||||
Update On Tue Jul 30 20:33:50 CEST 2024
|
||||
Update On Wed Jul 31 20:30:50 CEST 2024
|
||||
Update On Thu Aug 1 20:31:07 CEST 2024
|
||||
Update On Fri Aug 2 20:31:28 CEST 2024
|
||||
|
3
bbdown/.github/workflows/build_latest.yml
vendored
3
bbdown/.github/workflows/build_latest.yml
vendored
@@ -4,6 +4,7 @@ on: [push,workflow_dispatch]
|
||||
|
||||
env:
|
||||
DOTNET_SDK_VERSION: '8.0.*'
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -105,4 +106,4 @@ jobs:
|
||||
uses: actions/upload-artifact@v3.1.3
|
||||
with:
|
||||
name: BBDown_osx-arm64
|
||||
path: artifact-arm64/BBDown
|
||||
path: artifact-arm64/BBDown
|
||||
|
@@ -40,5 +40,10 @@ namespace BBDown.Core.Entity
|
||||
/// 视频分P信息
|
||||
/// </summary>
|
||||
public required List<Page> PagesInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为互动视频
|
||||
/// </summary>
|
||||
public bool IsSteinGate { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using BBDown.Core.Entity;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using static BBDown.Core.Entity.Entity;
|
||||
using static BBDown.Core.Util.HTTPUtil;
|
||||
|
||||
@@ -22,9 +23,15 @@ namespace BBDown.Core.Fetcher
|
||||
string ownerName = owner.GetProperty("name").ToString();
|
||||
long pubTime = data.GetProperty("pubdate").GetInt64();
|
||||
bool bangumi = false;
|
||||
var bvid = data.GetProperty("bvid").ToString();
|
||||
var cid = data.GetProperty("cid").GetInt64();
|
||||
|
||||
var pages = data.GetProperty("pages").EnumerateArray().ToList();
|
||||
// 互动视频 1:是 0:否
|
||||
var isSteinGate = data.GetProperty("rights").GetProperty("is_stein_gate").GetInt16();
|
||||
|
||||
// 分p信息
|
||||
List<Page> pagesInfo = new();
|
||||
var pages = data.GetProperty("pages").EnumerateArray().ToList();
|
||||
foreach (var page in pages)
|
||||
{
|
||||
Page p = new(page.GetProperty("page").GetInt32(),
|
||||
@@ -39,10 +46,57 @@ namespace BBDown.Core.Fetcher
|
||||
"",
|
||||
ownerName,
|
||||
ownerMid
|
||||
);
|
||||
);
|
||||
pagesInfo.Add(p);
|
||||
}
|
||||
|
||||
if (isSteinGate == 1) // 互动视频获取分P信息
|
||||
{
|
||||
var playerSoApi = $"https://api.bilibili.com/x/player.so?bvid={bvid}&id=cid:{cid}";
|
||||
var playerSoText = await GetWebSourceAsync(playerSoApi);
|
||||
var playerSoXml = new XmlDocument();
|
||||
playerSoXml.LoadXml($"<root>{playerSoText}</root>");
|
||||
|
||||
var interactionNode = playerSoXml.SelectSingleNode("//interaction");
|
||||
|
||||
if (interactionNode is { InnerText.Length: > 0 })
|
||||
{
|
||||
var graphVersion = JsonDocument.Parse(interactionNode.InnerText).RootElement
|
||||
.GetProperty("graph_version").GetInt64();
|
||||
var edgeInfoApi = $"https://api.bilibili.com/x/stein/edgeinfo_v2?graph_version={graphVersion}&bvid={bvid}";
|
||||
var edgeInfoJson = await GetWebSourceAsync(edgeInfoApi);
|
||||
var edgeInfoData = JsonDocument.Parse(edgeInfoJson).RootElement.GetProperty("data");
|
||||
var questions = edgeInfoData.GetProperty("edges").GetProperty("questions").EnumerateArray()
|
||||
.ToList();
|
||||
var index = 2; // 互动视频分P索引从2开始
|
||||
foreach (var question in questions)
|
||||
{
|
||||
var choices = question.GetProperty("choices").EnumerateArray().ToList();
|
||||
foreach (var page in choices)
|
||||
{
|
||||
Page p = new(index++,
|
||||
id,
|
||||
page.GetProperty("cid").ToString(),
|
||||
"", //epid
|
||||
page.GetProperty("option").ToString().Trim(),
|
||||
0,
|
||||
"",
|
||||
pubTime, //分p视频没有发布时间
|
||||
"",
|
||||
"",
|
||||
ownerName,
|
||||
ownerMid
|
||||
);
|
||||
pagesInfo.Add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("互动视频获取分P信息失败");
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (data.GetProperty("redirect_url").ToString().Contains("bangumi"))
|
||||
@@ -65,7 +119,8 @@ namespace BBDown.Core.Fetcher
|
||||
Pic = pic,
|
||||
PubTime = pubTime,
|
||||
PagesInfo = pagesInfo,
|
||||
IsBangumi = bangumi
|
||||
IsBangumi = bangumi,
|
||||
IsSteinGate = isSteinGate == 1
|
||||
};
|
||||
|
||||
return info;
|
||||
|
@@ -264,6 +264,12 @@ namespace BBDown
|
||||
{
|
||||
Log($"UP主页: https://space.bilibili.com/{mid}");
|
||||
}
|
||||
|
||||
if (vInfo.IsSteinGate && myOption.UseTvApi)
|
||||
{
|
||||
Log("视频为互动视频,暂时不支持tv下载,修改为默认下载");
|
||||
myOption.UseTvApi = false;
|
||||
}
|
||||
string apiType = myOption.UseTvApi ? "TV" : (myOption.UseAppApi ? "APP" : (myOption.UseIntlApi ? "INTL" : "WEB"));
|
||||
|
||||
//打印分P信息
|
||||
|
@@ -12,7 +12,7 @@ module.exports = {
|
||||
],
|
||||
ignorePatterns: ["index.html", "node_modules/", "dist/", "backend/**/target"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
plugins: ["@typescript-eslint", "react-compiler", "react-hooks"],
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||
@@ -20,6 +20,9 @@ module.exports = {
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"react-compiler/react-compiler": "error",
|
||||
"react-hooks/rules-of-hooks": "error",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
|
11
clash-nyanpasu/backend/Cargo.lock
generated
11
clash-nyanpasu/backend/Cargo.lock
generated
@@ -1211,6 +1211,7 @@ dependencies = [
|
||||
"display-info",
|
||||
"dunce",
|
||||
"dyn-clone",
|
||||
"enumflags2",
|
||||
"fast_image_resize",
|
||||
"fs_extra",
|
||||
"futures",
|
||||
@@ -4901,12 +4902,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29d73ba8daf8fac13b0501d1abeddcfe21ba7401ada61a819144b6c2a4f32209"
|
||||
checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6216,9 +6217,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.121"
|
||||
version = "1.0.122"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609"
|
||||
checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
|
||||
dependencies = [
|
||||
"indexmap 2.3.0",
|
||||
"itoa 1.0.11",
|
||||
|
@@ -30,7 +30,7 @@ pub fn set_identifier(identifier: &str) -> Result<()> {
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **macOS**: On macOS schemes must be defined in an Info.plist file, therefore this function only calls [`listen()`] without registering the scheme. This function can only be called once on macOS.
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(scheme: &str, handler: F) -> Result<()> {
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(scheme: &[&str], handler: F) -> Result<()> {
|
||||
platform_impl::register(scheme, handler)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ pub fn listen<F: FnMut(String) + Send + 'static>(handler: F) -> Result<()> {
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **macOS**: This function has no effect on macOS.
|
||||
pub fn unregister(scheme: &str) -> Result<()> {
|
||||
pub fn unregister(scheme: &[&str]) -> Result<()> {
|
||||
platform_impl::unregister(scheme)
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@ use dirs::data_dir;
|
||||
|
||||
use crate::ID;
|
||||
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(scheme: &str, handler: F) -> Result<()> {
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(schemes: &[&str], handler: F) -> Result<()> {
|
||||
listen(handler)?;
|
||||
|
||||
let mut target = data_dir()
|
||||
@@ -18,68 +18,76 @@ pub fn register<F: FnMut(String) + Send + 'static>(scheme: &str, handler: F) ->
|
||||
|
||||
create_dir_all(&target)?;
|
||||
|
||||
let exe = tauri_utils::platform::current_exe()?;
|
||||
for (i, scheme) in schemes.iter().enumerate() {
|
||||
let exe = tauri_utils::platform::current_exe()?;
|
||||
|
||||
let file_name = format!(
|
||||
"{}-handler.desktop",
|
||||
exe.file_name()
|
||||
.ok_or_else(|| Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"Couldn't get file name of curent executable.",
|
||||
))?
|
||||
.to_string_lossy()
|
||||
);
|
||||
let file_name = format!(
|
||||
"{}-handler-{}.desktop",
|
||||
exe.file_name()
|
||||
.ok_or_else(|| Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"Couldn't get file name of curent executable.",
|
||||
))?
|
||||
.to_string_lossy(),
|
||||
i
|
||||
);
|
||||
|
||||
target.push(&file_name);
|
||||
target.push(&file_name);
|
||||
|
||||
let mime_types = format!("x-scheme-handler/{};", scheme);
|
||||
let mime_types = format!("x-scheme-handler/{};", scheme);
|
||||
|
||||
let mut file = File::create(&target)?;
|
||||
file.write_all(
|
||||
format!(
|
||||
include_str!("template.desktop"),
|
||||
name = ID
|
||||
.get()
|
||||
.expect("Called register() before prepare()")
|
||||
.split('.')
|
||||
.last()
|
||||
.unwrap(),
|
||||
exec = std::env::var("APPIMAGE").unwrap_or_else(|_| exe.display().to_string()),
|
||||
mime_types = mime_types
|
||||
)
|
||||
.as_bytes(),
|
||||
)?;
|
||||
let mut file = File::create(&target)?;
|
||||
file.write_all(
|
||||
format!(
|
||||
include_str!("template.desktop"),
|
||||
name = ID
|
||||
.get()
|
||||
.expect("Called register() before prepare()")
|
||||
.split('.')
|
||||
.last()
|
||||
.unwrap(),
|
||||
exec = std::env::var("APPIMAGE").unwrap_or_else(|_| exe.display().to_string()),
|
||||
mime_types = mime_types
|
||||
)
|
||||
.as_bytes(),
|
||||
)?;
|
||||
|
||||
target.pop();
|
||||
Command::new("update-desktop-database")
|
||||
.arg(&target)
|
||||
.status()?;
|
||||
|
||||
Command::new("update-desktop-database")
|
||||
.arg(target)
|
||||
.status()?;
|
||||
Command::new("xdg-mime")
|
||||
.args(["default", &file_name, scheme])
|
||||
.status()?;
|
||||
|
||||
Command::new("xdg-mime")
|
||||
.args(["default", &file_name, scheme])
|
||||
.status()?;
|
||||
target.pop();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister(_scheme: &str) -> Result<()> {
|
||||
pub fn unregister(schemes: &[&str]) -> Result<()> {
|
||||
let mut target =
|
||||
data_dir().ok_or_else(|| Error::new(ErrorKind::NotFound, "data directory not found."))?;
|
||||
|
||||
target.push("applications");
|
||||
target.push(format!(
|
||||
"{}-handler.desktop",
|
||||
tauri_utils::platform::current_exe()?
|
||||
.file_name()
|
||||
.ok_or_else(|| Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"Couldn't get file name of curent executable.",
|
||||
))?
|
||||
.to_string_lossy()
|
||||
));
|
||||
|
||||
remove_file(&target)?;
|
||||
for (i, _) in schemes.iter().enumerate() {
|
||||
target.push(format!(
|
||||
"{}-handler-{}.desktop",
|
||||
tauri_utils::platform::current_exe()?
|
||||
.file_name()
|
||||
.ok_or_else(|| Error::new(
|
||||
ErrorKind::NotFound,
|
||||
"Couldn't get file name of curent executable.",
|
||||
))?
|
||||
.to_string_lossy(),
|
||||
i
|
||||
));
|
||||
|
||||
remove_file(&target)?;
|
||||
target.pop();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -21,13 +21,13 @@ type THandler = OnceCell<Mutex<Box<dyn FnMut(String) + Send + 'static>>>;
|
||||
// If the Mutex turns out to be a problem, or FnMut turns out to be useless, we can remove the Mutex and turn FnMut into Fn
|
||||
static HANDLER: THandler = OnceCell::new();
|
||||
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(_scheme: &str, handler: F) -> Result<()> {
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(_scheme: &[&str], handler: F) -> Result<()> {
|
||||
listen(handler)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister(_scheme: &str) -> Result<()> {
|
||||
pub fn unregister(_scheme: &[&str]) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@@ -12,42 +12,46 @@ use winreg::{enums::HKEY_CURRENT_USER, RegKey};
|
||||
|
||||
use crate::ID;
|
||||
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(scheme: &str, handler: F) -> Result<()> {
|
||||
pub fn register<F: FnMut(String) + Send + 'static>(schemes: &[&str], handler: F) -> Result<()> {
|
||||
listen(handler)?;
|
||||
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let base = Path::new("Software").join("Classes").join(scheme);
|
||||
for scheme in schemes {
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let base = Path::new("Software").join("Classes").join(scheme);
|
||||
|
||||
let exe = tauri_utils::platform::current_exe()?
|
||||
.display()
|
||||
.to_string()
|
||||
.replace("\\\\?\\", "");
|
||||
let exe = tauri_utils::platform::current_exe()?
|
||||
.display()
|
||||
.to_string()
|
||||
.replace("\\\\?\\", "");
|
||||
|
||||
let (key, _) = hkcu.create_subkey(&base)?;
|
||||
key.set_value(
|
||||
"",
|
||||
&format!(
|
||||
"URL:{}",
|
||||
ID.get().expect("register() called before prepare()")
|
||||
),
|
||||
)?;
|
||||
key.set_value("URL Protocol", &"")?;
|
||||
let (key, _) = hkcu.create_subkey(&base)?;
|
||||
key.set_value(
|
||||
"",
|
||||
&format!(
|
||||
"URL:{}",
|
||||
ID.get().expect("register() called before prepare()")
|
||||
),
|
||||
)?;
|
||||
key.set_value("URL Protocol", &"")?;
|
||||
|
||||
let (icon, _) = hkcu.create_subkey(base.join("DefaultIcon"))?;
|
||||
icon.set_value("", &format!("\"{}\",0", &exe))?;
|
||||
let (icon, _) = hkcu.create_subkey(base.join("DefaultIcon"))?;
|
||||
icon.set_value("", &format!("\"{}\",0", &exe))?;
|
||||
|
||||
let (cmd, _) = hkcu.create_subkey(base.join("shell").join("open").join("command"))?;
|
||||
let (cmd, _) = hkcu.create_subkey(base.join("shell").join("open").join("command"))?;
|
||||
|
||||
cmd.set_value("", &format!("\"{}\" \"%1\"", &exe))?;
|
||||
cmd.set_value("", &format!("\"{}\" \"%1\"", &exe))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unregister(scheme: &str) -> Result<()> {
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let base = Path::new("Software").join("Classes").join(scheme);
|
||||
pub fn unregister(schemes: &[&str]) -> Result<()> {
|
||||
for scheme in schemes {
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let base = Path::new("Software").join("Classes").join(scheme);
|
||||
|
||||
hkcu.delete_subkey_all(base)?;
|
||||
hkcu.delete_subkey_all(base)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -125,6 +125,7 @@ mlua = { version = "0.9", features = [
|
||||
"parking_lot",
|
||||
"vendored",
|
||||
] }
|
||||
enumflags2 = "0.7"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
cocoa = "0.25.0"
|
||||
|
@@ -2,18 +2,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<!-- Obviously needs to be replaced with your app's bundle identifier -->
|
||||
<string>Clash Nyanpasu</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<!-- Obviously needs to be replaced with your app's bundle identifier -->
|
||||
<string>Clash Nyanpasu</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>clash-nyanpasu</string>
|
||||
</array>
|
||||
</dict>
|
||||
<string>clash-nyanpasu</string>
|
||||
<!-- Compatible with Clash common register handler -->
|
||||
<string>clash</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@@ -1,8 +1,8 @@
|
||||
use crate::utils::{dirs, help};
|
||||
use anyhow::Result;
|
||||
// use log::LevelFilter;
|
||||
use enumflags2::bitflags;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod clash_strategy;
|
||||
pub mod logging;
|
||||
|
||||
@@ -10,10 +10,12 @@ pub use self::clash_strategy::{ClashStrategy, ExternalControllerPortStrategy};
|
||||
pub use logging::LoggingLevel;
|
||||
|
||||
// TODO: when support sing-box, remove this struct
|
||||
#[bitflags]
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub enum ClashCore {
|
||||
#[serde(rename = "clash", alias = "clash-premium")]
|
||||
ClashPremium,
|
||||
ClashPremium = 0b0001,
|
||||
#[serde(rename = "clash-rs")]
|
||||
ClashRs,
|
||||
#[serde(rename = "mihomo", alias = "clash-meta")]
|
||||
|
@@ -4,6 +4,7 @@ use anyhow::{bail, Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_yaml::Mapping;
|
||||
use std::{fs, io::Write};
|
||||
use tracing_attributes::instrument;
|
||||
|
||||
/// Define the `profiles.yaml` schema
|
||||
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
|
||||
@@ -182,7 +183,9 @@ impl IProfiles {
|
||||
}
|
||||
|
||||
/// update the item value
|
||||
#[instrument]
|
||||
pub fn patch_item(&mut self, uid: String, item: ProfileItem) -> Result<()> {
|
||||
tracing::debug!("patch item: {uid} with {item:?}");
|
||||
let mut items = self.items.take().unwrap_or_default();
|
||||
|
||||
for each in items.iter_mut() {
|
||||
@@ -196,7 +199,8 @@ impl IProfiles {
|
||||
patch!(each, item, extra);
|
||||
patch!(each, item, updated);
|
||||
patch!(each, item, option);
|
||||
|
||||
patch!(each, item, chains);
|
||||
tracing::debug!("patch item: {each:?}");
|
||||
self.items = Some(items);
|
||||
return self.save_file();
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
use crate::config::Config;
|
||||
use anyhow::{bail, Result};
|
||||
use indexmap::IndexMap;
|
||||
use reqwest::header::HeaderMap;
|
||||
use reqwest::{header::HeaderMap, StatusCode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_yaml::Mapping;
|
||||
use std::{
|
||||
@@ -22,12 +22,12 @@ pub async fn put_configs(path: &str) -> Result<()> {
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.put(&url).headers(headers).json(&data);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
match response.status().as_u16() {
|
||||
204 => Ok(()),
|
||||
status => {
|
||||
bail!("failed to put configs with status \"{status}\"")
|
||||
match response.status() {
|
||||
StatusCode::NO_CONTENT | StatusCode::ACCEPTED => Ok(()),
|
||||
_ => {
|
||||
bail!("failed to put configs")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ pub async fn patch_configs(config: &Mapping) -> Result<()> {
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.patch(&url).headers(headers.clone()).json(config);
|
||||
builder.send().await?;
|
||||
builder.send().await?.error_for_status()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ pub async fn get_proxies() -> Result<ProxiesRes> {
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.get(&url).headers(headers);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
Ok(response.json::<ProxiesRes>().await?)
|
||||
}
|
||||
@@ -143,7 +143,7 @@ pub async fn get_proxy(name: String) -> Result<ProxyItem> {
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.get(&url).headers(headers);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
Ok(response.json::<ProxyItem>().await?)
|
||||
}
|
||||
@@ -162,10 +162,10 @@ pub async fn update_proxy(group: &str, name: &str) -> Result<()> {
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.put(&url).headers(headers).json(&data);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
match response.status().as_u16() {
|
||||
204 => Ok(()),
|
||||
match response.status() {
|
||||
StatusCode::ACCEPTED | StatusCode::NO_CONTENT => Ok(()),
|
||||
status => {
|
||||
bail!("failed to put proxy with status \"{status}\"")
|
||||
}
|
||||
@@ -227,7 +227,7 @@ pub async fn get_providers_proxies() -> Result<ProvidersProxiesRes> {
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.get(&url).headers(headers);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
Ok(response.json::<ProvidersProxiesRes>().await?)
|
||||
}
|
||||
@@ -243,7 +243,7 @@ pub async fn get_providers_proxies_group(group: String) -> Result<ProxyProviderI
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.get(&url).headers(headers);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
Ok(response.json::<ProxyProviderItem>().await?)
|
||||
}
|
||||
@@ -258,10 +258,10 @@ pub async fn update_providers_proxies_group(name: &str) -> Result<()> {
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.put(&url).headers(headers);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
match response.status().as_u16() {
|
||||
204 => Ok(()),
|
||||
match response.status() {
|
||||
StatusCode::NO_CONTENT | StatusCode::ACCEPTED => Ok(()),
|
||||
status => {
|
||||
bail!("failed to put providers proxies name with status \"{status}\"")
|
||||
}
|
||||
@@ -279,7 +279,7 @@ pub async fn get_providers_proxies_healthcheck(name: String) -> Result<Mapping>
|
||||
|
||||
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
|
||||
let builder = client.get(&url).headers(headers);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
Ok(response.json::<Mapping>().await?)
|
||||
}
|
||||
@@ -305,7 +305,7 @@ pub async fn get_proxy_delay(name: String, test_url: Option<String>) -> Result<D
|
||||
.get(&url)
|
||||
.headers(headers)
|
||||
.query(&[("timeout", "10000"), ("url", &test_url)]);
|
||||
let response = builder.send().await?;
|
||||
let response = builder.send().await?.error_for_status()?;
|
||||
|
||||
Ok(response.json::<DelayRes>().await?)
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ use std::{
|
||||
};
|
||||
use tauri::api::process::Command;
|
||||
use tokio::time::sleep;
|
||||
use tracing_attributes::instrument;
|
||||
|
||||
pub enum RunType {
|
||||
/// Run as child process directly
|
||||
@@ -392,7 +393,7 @@ impl CoreManager {
|
||||
let config_path = Config::generate_file(ConfigType::Check)?;
|
||||
let config_path = dirs::path_to_str(&config_path)?;
|
||||
|
||||
let clash_core = { Config::verge().latest().clash_core.clone() };
|
||||
let clash_core = { Config::verge().latest().clash_core };
|
||||
let clash_core = clash_core.unwrap_or(ClashCore::ClashPremium).to_string();
|
||||
|
||||
let app_dir = dirs::app_data_dir()?;
|
||||
@@ -561,6 +562,7 @@ impl CoreManager {
|
||||
}
|
||||
|
||||
/// 切换核心
|
||||
#[instrument(skip(self))]
|
||||
pub async fn change_core(&self, clash_core: Option<ClashCore>) -> Result<()> {
|
||||
let clash_core = clash_core.ok_or(anyhow::anyhow!("clash core is null"))?;
|
||||
|
||||
@@ -578,12 +580,14 @@ impl CoreManager {
|
||||
|
||||
match self.run_core().await {
|
||||
Ok(_) => {
|
||||
tracing::info!("change core success");
|
||||
Config::verge().apply();
|
||||
Config::runtime().apply();
|
||||
log_err!(Config::verge().latest().save_file());
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("failed to change core: {err}");
|
||||
Config::verge().discard();
|
||||
Config::runtime().discard();
|
||||
self.run_core().await?;
|
||||
|
@@ -3,14 +3,32 @@ use crate::log_err;
|
||||
use anyhow::{bail, Result};
|
||||
use once_cell::sync::OnceCell;
|
||||
use parking_lot::Mutex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use tauri::{AppHandle, Manager, Window};
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Handle {
|
||||
pub app_handle: Arc<Mutex<Option<AppHandle>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StateChanged {
|
||||
NyanpasuConfig,
|
||||
ClashConfig,
|
||||
Profiles,
|
||||
Proxies,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Message {
|
||||
SetConfig(Result<(), String>),
|
||||
}
|
||||
|
||||
const STATE_CHANGED_URI: &str = "nyanpasu://mutation";
|
||||
const NOTIFY_MESSAGE_URI: &str = "nyanpasu://notice-message";
|
||||
|
||||
impl Handle {
|
||||
pub fn global() -> &'static Handle {
|
||||
static HANDLE: OnceCell<Handle> = OnceCell::new();
|
||||
@@ -33,32 +51,32 @@ impl Handle {
|
||||
|
||||
pub fn refresh_clash() {
|
||||
if let Some(window) = Self::global().get_window() {
|
||||
log_err!(window.emit("verge://refresh-clash-config", "yes"));
|
||||
log_err!(window.emit(STATE_CHANGED_URI, StateChanged::ClashConfig));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh_verge() {
|
||||
if let Some(window) = Self::global().get_window() {
|
||||
log_err!(window.emit("verge://refresh-verge-config", "yes"));
|
||||
log_err!(window.emit(STATE_CHANGED_URI, StateChanged::NyanpasuConfig));
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn refresh_profiles() {
|
||||
if let Some(window) = Self::global().get_window() {
|
||||
log_err!(window.emit("verge://refresh-profiles-config", "yes"));
|
||||
log_err!(window.emit(STATE_CHANGED_URI, StateChanged::Profiles));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mutate_proxies() {
|
||||
if let Some(window) = Self::global().get_window() {
|
||||
log_err!(window.emit("verge://mutate-proxies", "yes"));
|
||||
log_err!(window.emit(STATE_CHANGED_URI, StateChanged::Proxies));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notice_message<S: Into<String>, M: Into<String>>(status: S, msg: M) {
|
||||
pub fn notice_message(message: &Message) {
|
||||
if let Some(window) = Self::global().get_window() {
|
||||
log_err!(window.emit("verge://notice-message", (status.into(), msg.into())));
|
||||
log_err!(window.emit(NOTIFY_MESSAGE_URI, message));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -208,7 +208,6 @@ impl Updater {
|
||||
let current_core = crate::config::Config::verge()
|
||||
.latest()
|
||||
.clash_core
|
||||
.clone()
|
||||
.unwrap_or_default();
|
||||
if current_core == self.core_type {
|
||||
CoreManager::global().stop_core().await?;
|
||||
|
@@ -227,7 +227,7 @@ impl UpdaterManager {
|
||||
let updater = Arc::new(
|
||||
instance::UpdaterBuilder::new()
|
||||
.set_client(self.client.clone())
|
||||
.set_core_type(core_type.clone())
|
||||
.set_core_type(*core_type)
|
||||
.set_mirror(mirror)
|
||||
.set_artifact(artifact)
|
||||
.set_tag(tag)
|
||||
|
@@ -0,0 +1,15 @@
|
||||
-- compatible with ipv6 decrepation
|
||||
if config["ipv6"] ~= nil then
|
||||
config["ipv6"] = nil
|
||||
if config["dns"] ~= nil and config["dns"]["enabled"] == true then
|
||||
config["dns"]["ipv6"] = true
|
||||
end
|
||||
end
|
||||
|
||||
-- compatible with allow lan decrepation
|
||||
if config["allow_lan"] == true then
|
||||
config["allow_lan"] = nil
|
||||
config["bind_address"] = "0.0.0.0"
|
||||
end
|
||||
|
||||
return config;
|
@@ -1,4 +1,4 @@
|
||||
function main(params) {
|
||||
export default function main(params) {
|
||||
if (params.mode === "script") {
|
||||
params.mode = "rule";
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
function main(params) {
|
||||
export default function main(params) {
|
||||
if (Array.isArray(params.proxies)) {
|
||||
params.proxies.forEach((p, i) => {
|
||||
if (p.type === "hysteria" && typeof p.alpn === "string") {
|
||||
|
@@ -2,6 +2,7 @@ use crate::{
|
||||
config::{nyanpasu::ClashCore, profile::item_type::ProfileItemType, ProfileItem},
|
||||
utils::{dirs, help},
|
||||
};
|
||||
use enumflags2::BitFlags;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_yaml::Mapping;
|
||||
use std::fs;
|
||||
@@ -102,17 +103,9 @@ pub enum ScriptType {
|
||||
Lua,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ChainSupport {
|
||||
Clash,
|
||||
Mihomo,
|
||||
ClashRs,
|
||||
All,
|
||||
}
|
||||
|
||||
impl ChainItem {
|
||||
/// 内建支持一些脚本
|
||||
pub fn builtin() -> Vec<(ChainSupport, ChainItem)> {
|
||||
pub fn builtin() -> Vec<(BitFlags<ClashCore>, ChainItem)> {
|
||||
// meta 的一些处理
|
||||
let meta_guard = ChainItem::to_script(
|
||||
"verge_meta_guard",
|
||||
@@ -125,9 +118,16 @@ impl ChainItem {
|
||||
ChainTypeWrapper::new_js(include_str!("./builtin/meta_hy_alpn.js").to_string()),
|
||||
);
|
||||
|
||||
// 移除或转换 Clash Rs 不支持的字段
|
||||
let clash_rs_comp = ChainItem::to_script(
|
||||
"clash_rs_comp",
|
||||
ChainTypeWrapper::new_lua(include_str!("./builtin/clash_rs_comp.lua").to_string()),
|
||||
);
|
||||
|
||||
vec![
|
||||
(ChainSupport::Mihomo, hy_alpn),
|
||||
(ChainSupport::Mihomo, meta_guard),
|
||||
(ClashCore::Mihomo | ClashCore::MihomoAlpha, hy_alpn),
|
||||
(ClashCore::Mihomo | ClashCore::MihomoAlpha, meta_guard),
|
||||
(ClashCore::ClashRs.into(), clash_rs_comp),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -138,21 +138,3 @@ impl ChainItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ChainSupport {
|
||||
pub fn is_support(&self, core: Option<&ClashCore>) -> bool {
|
||||
match core {
|
||||
Some(core) => matches!(
|
||||
(self, core),
|
||||
(ChainSupport::All, _)
|
||||
| (ChainSupport::Clash, ClashCore::ClashPremium)
|
||||
| (ChainSupport::ClashRs, ClashCore::ClashRs)
|
||||
| (
|
||||
ChainSupport::Mihomo,
|
||||
ClashCore::Mihomo | ClashCore::MihomoAlpha
|
||||
)
|
||||
),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ mod utils;
|
||||
|
||||
pub use self::chain::ScriptType;
|
||||
use self::{chain::*, field::*, merge::*, script::*, tun::*};
|
||||
use crate::config::Config;
|
||||
use crate::config::{nyanpasu::ClashCore, Config};
|
||||
use indexmap::IndexMap;
|
||||
use serde_yaml::Mapping;
|
||||
use std::collections::HashSet;
|
||||
@@ -23,7 +23,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, IndexMap<String, Logs>) {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.clash_core.clone(),
|
||||
verge.clash_core,
|
||||
verge.enable_tun_mode.unwrap_or(false),
|
||||
verge.enable_builtin_enhanced.unwrap_or(true),
|
||||
verge.enable_clash_fields.unwrap_or(true),
|
||||
@@ -119,13 +119,13 @@ pub async fn enhance() -> (Mapping, Vec<String>, IndexMap<String, Logs>) {
|
||||
if enable_builtin {
|
||||
for item in ChainItem::builtin()
|
||||
.into_iter()
|
||||
.filter(|(s, _)| s.is_support(clash_core.as_ref()))
|
||||
.filter(|(s, _)| s.contains(*clash_core.as_ref().unwrap_or(&ClashCore::default())))
|
||||
.map(|(_, c)| c)
|
||||
{
|
||||
log::debug!(target: "app", "run builtin script {}", item.uid);
|
||||
|
||||
if let ChainTypeWrapper::Script(script) = item.data {
|
||||
let (res, logs) = script_runner
|
||||
let (res, _) = script_runner
|
||||
.process_script(script, config.to_owned())
|
||||
.await;
|
||||
match res {
|
||||
|
@@ -113,6 +113,7 @@ mod tests {
|
||||
- 123
|
||||
- 12312
|
||||
- asdxxx
|
||||
shoud_remove: 123
|
||||
"#;
|
||||
|
||||
let mapping = serde_yaml::from_str::<Mapping>(mapping).unwrap();
|
||||
@@ -121,6 +122,7 @@ mod tests {
|
||||
console.warn("Hello, world!");
|
||||
console.error("Hello, world!");
|
||||
config["proxies"] = {1, 2, 3};
|
||||
config["shoud_remove"] = nil;
|
||||
return config;
|
||||
"#;
|
||||
let expected = r#"
|
||||
|
@@ -74,6 +74,7 @@ impl RunnerManager {
|
||||
config: Mapping,
|
||||
) -> ProcessOutput {
|
||||
let runner = wrap_result!(self.get_or_init_runner(&script.0));
|
||||
tracing::debug!("script: {:?}", script);
|
||||
runner.process_honey(config, script.1.as_str()).await
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ use crate::{
|
||||
utils::{self, help::get_clash_external_port, resolve},
|
||||
};
|
||||
use anyhow::{bail, Result};
|
||||
use handle::Message;
|
||||
use nyanpasu_ipc::api::status::CoreState;
|
||||
use serde_yaml::{Mapping, Value};
|
||||
use wry::application::clipboard::Clipboard;
|
||||
@@ -53,10 +54,10 @@ pub fn restart_clash_core() {
|
||||
match CoreManager::global().run_core().await {
|
||||
Ok(_) => {
|
||||
handle::Handle::refresh_clash();
|
||||
handle::Handle::notice_message("set_config::ok", "ok");
|
||||
handle::Handle::notice_message(&Message::SetConfig(Ok(())));
|
||||
}
|
||||
Err(err) => {
|
||||
handle::Handle::notice_message("set_config::error", format!("{err}"));
|
||||
handle::Handle::notice_message(&Message::SetConfig(Err(format!("{err}"))));
|
||||
log::error!(target:"app", "{err}");
|
||||
}
|
||||
}
|
||||
@@ -394,11 +395,11 @@ async fn update_core_config() -> Result<()> {
|
||||
match CoreManager::global().update_config().await {
|
||||
Ok(_) => {
|
||||
handle::Handle::refresh_clash();
|
||||
handle::Handle::notice_message("set_config::ok", "ok");
|
||||
handle::Handle::notice_message(&Message::SetConfig(Ok(())));
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
handle::Handle::notice_message("set_config::error", format!("{err}"));
|
||||
handle::Handle::notice_message(&Message::SetConfig(Err(format!("{err}"))));
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
@@ -103,6 +103,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult {
|
||||
/// 修改某个profile item的
|
||||
#[tauri::command]
|
||||
pub fn patch_profile(index: String, profile: ProfileItem) -> CmdResult {
|
||||
tracing::debug!("patch profile: {index} with {profile:?}");
|
||||
wrap_err!(Config::profiles().data().patch_item(index, profile))?;
|
||||
ProfilesJobGuard::global().lock().refresh();
|
||||
Ok(())
|
||||
|
@@ -128,8 +128,9 @@ fn main() -> std::io::Result<()> {
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
log_err!(tauri_plugin_deep_link::register(
|
||||
"clash-nyanpasu",
|
||||
&["clash-nyanpasu", "clash"],
|
||||
move |request| {
|
||||
log::info!(target: "app", "scheme request received: {:?}", &request);
|
||||
resolve::create_window(&handle.clone()); // create window if not exists
|
||||
|
97
clash-nyanpasu/cliff.toml
Normal file
97
clash-nyanpasu/cliff.toml
Normal file
@@ -0,0 +1,97 @@
|
||||
# git-cliff ~ configuration file
|
||||
# https://git-cliff.org/docs/configuration
|
||||
|
||||
[changelog]
|
||||
# changelog header
|
||||
header = """
|
||||
# Changelog\n
|
||||
All notable changes to this project will be documented in this file.\n
|
||||
"""
|
||||
# template for the changelog body
|
||||
# https://keats.github.io/tera/docs/#introduction
|
||||
body = """
|
||||
{% if version %}\
|
||||
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
|
||||
{% else %}\
|
||||
## [unreleased]
|
||||
{% endif %}\
|
||||
{% for group, commits in commits | group_by(attribute="group") %}
|
||||
### {{ group | upper_first }}
|
||||
{% for commit in commits %}
|
||||
- {{ commit.message | upper_first | trim_end }}\
|
||||
{% if commit.github.username %} by @{{ commit.github.username }} {% else %} by {{ commit.author.name }} {%- endif -%}
|
||||
{% if commit.github.pr_number %} in \
|
||||
[#{{ commit.github.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.github.pr_number }}) \
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}\n
|
||||
|
||||
{%- if github -%}
|
||||
|
||||
-----------------
|
||||
|
||||
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
|
||||
{% raw %}\n{% endraw -%}
|
||||
## New Contributors
|
||||
{%- endif %}\
|
||||
{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
|
||||
* @{{ contributor.username }} made their first contribution
|
||||
{%- if contributor.pr_number %} in \
|
||||
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
|
||||
{%- endif %}
|
||||
{%- endfor -%}
|
||||
|
||||
{% if version %}
|
||||
{% if previous.version %}
|
||||
**Full Changelog**: {{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }}
|
||||
{% endif %}
|
||||
{% else -%}
|
||||
{% raw %}\n{% endraw %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{%- macro remote_url() -%}
|
||||
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
|
||||
{%- endmacro -%}
|
||||
"""
|
||||
# template for the changelog footer
|
||||
footer = """"""
|
||||
# remove the leading and trailing whitespace from the templates
|
||||
trim = true
|
||||
|
||||
[git]
|
||||
# parse the commits based on https://www.conventionalcommits.org
|
||||
conventional_commits = true
|
||||
# filter out the commits that are not conventional
|
||||
filter_unconventional = false
|
||||
# process each line of a commit as an individual commit
|
||||
split_commits = false
|
||||
# regex for parsing and grouping commits
|
||||
commit_parsers = [
|
||||
{ message = "^feat", group = "✨ Features" },
|
||||
{ message = "^fix", group = "🐛 Bug Fixes" },
|
||||
{ message = "^doc", group = "📚 Documentation" },
|
||||
{ message = "^perf", group = "⚡ Performance Improvements" },
|
||||
{ message = "^refactor", group = "🔨 Refactor" },
|
||||
{ message = "^style", group = "💅 Styling" },
|
||||
{ message = "^test", group = "✅ Testing" },
|
||||
{ message = "^chore\\(release\\): prepare for", skip = true },
|
||||
{ message = "^chore: bump version", skip = true },
|
||||
{ message = "^chore", group = "🧹 Miscellaneous Tasks" },
|
||||
{ body = ".*security", group = "🛡️ Security" },
|
||||
{ body = ".*", group = "Other (unconventional)", skip = true },
|
||||
]
|
||||
# protect breaking changes from being skipped due to matching a skipping commit_parser
|
||||
protect_breaking_commits = false
|
||||
# filter out the commits that are not matched by commit parsers
|
||||
filter_commits = false
|
||||
# regex for matching git tags
|
||||
tag_pattern = "v[0-9].*"
|
||||
# regex for skipping tags
|
||||
skip_tags = "v0.1.0-beta.1"
|
||||
# regex for ignoring tags
|
||||
ignore_tags = ""
|
||||
# sort the tags topologically
|
||||
topo_order = false
|
||||
# sort the commits inside sections by oldest/newest order
|
||||
sort_commits = "newest"
|
@@ -46,16 +46,16 @@ export const useClash = () => {
|
||||
await tauri.setProfiles({ index, profile });
|
||||
|
||||
await getProfiles.mutate();
|
||||
|
||||
await getRuntimeLogs.mutate();
|
||||
};
|
||||
|
||||
const setProfilesConfig = async (profiles: Profile.Config) => {
|
||||
try {
|
||||
await tauri.setProfilesConfig(profiles);
|
||||
await tauri.setProfilesConfig(profiles);
|
||||
|
||||
await getProfiles.mutate();
|
||||
} finally {
|
||||
return getProfiles.data;
|
||||
}
|
||||
await getProfiles.mutate();
|
||||
|
||||
await getRuntimeLogs.mutate();
|
||||
};
|
||||
|
||||
const createProfile = async (item: Partial<Profile.Item>, data?: string) => {
|
||||
|
@@ -11,6 +11,7 @@ import { useClash } from "./useClash";
|
||||
* Data from tauri backend.
|
||||
*/
|
||||
export const useNyanpasu = (options?: {
|
||||
onSuccess?: (data?: VergeConfig) => void;
|
||||
onUpdate?: (data?: VergeConfig) => void;
|
||||
onError?: (error: any) => void;
|
||||
}) => {
|
||||
@@ -19,6 +20,9 @@ export const useNyanpasu = (options?: {
|
||||
const { data, error, mutate } = useSWR<VergeConfig>(
|
||||
"nyanpasuConfig",
|
||||
service.getNyanpasuConfig,
|
||||
{
|
||||
onSuccess: options?.onSuccess,
|
||||
},
|
||||
);
|
||||
|
||||
const setNyanpasuConfig = async (payload: Partial<VergeConfig>) => {
|
||||
|
@@ -24,7 +24,7 @@
|
||||
"@tauri-apps/api": "1.6.0",
|
||||
"ahooks": "3.8.0",
|
||||
"allotment": "1.20.2",
|
||||
"axios": "1.7.2",
|
||||
"axios": "1.7.3",
|
||||
"country-code-emoji": "2.3.0",
|
||||
"dayjs": "1.11.12",
|
||||
"framer-motion": "12.0.0-alpha.0",
|
||||
@@ -40,7 +40,7 @@
|
||||
"react-hook-form-mui": "7.0.1",
|
||||
"react-i18next": "15.0.0",
|
||||
"react-markdown": "9.0.1",
|
||||
"react-router-dom": "6.25.1",
|
||||
"react-router-dom": "6.26.0",
|
||||
"react-split-grid": "1.0.4",
|
||||
"swr": "2.2.5",
|
||||
"virtua": "0.33.4"
|
||||
@@ -50,8 +50,6 @@
|
||||
"@emotion/react": "11.13.0",
|
||||
"@types/react": "18.3.3",
|
||||
"@types/react-dom": "18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.18.0",
|
||||
"@typescript-eslint/parser": "7.18.0",
|
||||
"@vitejs/plugin-react": "4.3.1",
|
||||
"@vitejs/plugin-react-swc": "3.7.0",
|
||||
"clsx": "2.1.1",
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import { useInterval } from "ahooks";
|
||||
import { countryCodeEmoji } from "country-code-emoji";
|
||||
import { useRef, useState } from "react";
|
||||
import { useColorForDelay } from "@/hooks/theme";
|
||||
import { Visibility, VisibilityOff } from "@mui/icons-material";
|
||||
import { CircularProgress, IconButton, Paper, Tooltip } from "@mui/material";
|
||||
import Grid from "@mui/material/Unstable_Grid2";
|
||||
import { timing, useIPSB } from "@nyanpasu/interface";
|
||||
import { cn } from "@nyanpasu/ui";
|
||||
import { getColorForDelay } from "../proxies/utils";
|
||||
|
||||
const IP_REFRESH_SECONDS = 180;
|
||||
|
||||
@@ -60,20 +60,9 @@ export const HealthPanel = () => {
|
||||
<Paper className="relative !rounded-3xl">
|
||||
<div className="flex justify-between gap-8 p-4">
|
||||
<div className="flex flex-col justify-between">
|
||||
{Object.entries(health).map(([name, value]) => {
|
||||
return (
|
||||
<div key={name} className="flex justify-between gap-1">
|
||||
<div className="min-w-20 font-bold">{name}:</div>
|
||||
|
||||
<div
|
||||
className="min-w-16 text-end"
|
||||
style={{ color: getColorForDelay(value) }}
|
||||
>
|
||||
{value ? `${value.toFixed(0)} ms` : "Timeout"}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{Object.entries(health).map(([name, value]) => (
|
||||
<LatencyTag key={name} name={name} value={value} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="relative flex flex-1 select-text justify-center gap-4">
|
||||
@@ -150,4 +139,17 @@ export const HealthPanel = () => {
|
||||
);
|
||||
};
|
||||
|
||||
function LatencyTag({ name, value }: { name: string; value: number }) {
|
||||
const color = useColorForDelay(value);
|
||||
return (
|
||||
<div className="flex justify-between gap-1">
|
||||
<div className="min-w-20 font-bold">{name}:</div>
|
||||
|
||||
<div className="min-w-16 text-end" style={{ color }}>
|
||||
{value ? `${value.toFixed(0)} ms` : "Timeout"}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default HealthPanel;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { debounce } from "lodash-es";
|
||||
import { useEffect, useState } from "react";
|
||||
import { NotificationType, useNotification } from "@/hooks/use-notification";
|
||||
import { classNames } from "@/utils";
|
||||
import { notification, NotificationType } from "@/utils/notification";
|
||||
import {
|
||||
CloseRounded,
|
||||
CropSquareRounded,
|
||||
@@ -38,7 +38,7 @@ export const LayoutControl = ({ className }: { className?: string }) => {
|
||||
const isMaximized = await appWindow.isMaximized();
|
||||
setIsMaximized(() => isMaximized);
|
||||
} catch (error) {
|
||||
useNotification({
|
||||
notification({
|
||||
type: NotificationType.Error,
|
||||
title: "Error",
|
||||
body: typeof error === "string" ? error : (error as Error).message,
|
||||
|
@@ -0,0 +1,85 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useGlobalMutation } from "@/utils/mutation";
|
||||
import { notification, NotificationType } from "@/utils/notification";
|
||||
import { listen, UnlistenFn } from "@tauri-apps/api/event";
|
||||
|
||||
export default function MutationProvider() {
|
||||
const { t } = useTranslation();
|
||||
const unlistenFn = useRef<UnlistenFn>(null);
|
||||
const mutate = useGlobalMutation();
|
||||
useEffect(() => {
|
||||
listen<"nyanpasu_config" | "clash_config" | "proxies" | "profiles">(
|
||||
"nyanpasu://mutation",
|
||||
({ payload }) => {
|
||||
switch (payload) {
|
||||
case "nyanpasu_config":
|
||||
mutate((key) => {
|
||||
if (typeof key === "string") {
|
||||
return (
|
||||
key.includes("nyanpasuConfig") ||
|
||||
key.includes("getProxies") ||
|
||||
key.includes("getProfiles")
|
||||
);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case "clash_config":
|
||||
mutate((key) => {
|
||||
if (typeof key === "string") {
|
||||
return (
|
||||
key.includes("getClashRules") ||
|
||||
key.includes("getClashInfo") ||
|
||||
key.includes("getClashVersion") ||
|
||||
key.includes("getProxies") ||
|
||||
key.includes("getProfiles") ||
|
||||
key.includes("getRulesProviders") ||
|
||||
key.includes("getProxiesProviders") ||
|
||||
key.includes("getAllProxiesProviders")
|
||||
);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case "proxies":
|
||||
mutate(
|
||||
(key) => typeof key === "string" && key.includes("getProxies"),
|
||||
);
|
||||
break;
|
||||
case "profiles":
|
||||
mutate((key) => {
|
||||
if (typeof key === "string") {
|
||||
return (
|
||||
key.includes("getClashRules") ||
|
||||
key.includes("getClashInfo") ||
|
||||
key.includes("getClashVersion") ||
|
||||
key.includes("getProxies") ||
|
||||
key.includes("getProfiles") ||
|
||||
key.includes("getRulesProviders") ||
|
||||
key.includes("getProxiesProviders") ||
|
||||
key.includes("getAllProxiesProviders")
|
||||
);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
)
|
||||
.then((unlisten) => {
|
||||
unlistenFn.current = unlisten;
|
||||
})
|
||||
.catch((e) => {
|
||||
notification({
|
||||
title: t("Error"),
|
||||
body: e.message,
|
||||
type: NotificationType.Error,
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
unlistenFn.current?.();
|
||||
};
|
||||
}, []);
|
||||
return null;
|
||||
}
|
@@ -1,36 +1,43 @@
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { NotificationType, useNotification } from "@/hooks/use-notification";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { notification, NotificationType } from "@/utils/notification";
|
||||
import { listen, UnlistenFn } from "@tauri-apps/api/event";
|
||||
|
||||
export const NoticeProvider = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const unlistenFn = useRef<UnlistenFn>(null);
|
||||
useEffect(() => {
|
||||
listen("verge://notice-message", ({ payload }) => {
|
||||
const [status, msg] = payload as [string, string];
|
||||
switch (status) {
|
||||
case "set_config::ok":
|
||||
useNotification({
|
||||
title: t("Success"),
|
||||
body: "Refresh Clash Config",
|
||||
type: NotificationType.Success,
|
||||
});
|
||||
break;
|
||||
|
||||
case "set_config::error":
|
||||
useNotification({
|
||||
title: t("Error"),
|
||||
body: msg,
|
||||
type: NotificationType.Error,
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
listen<{
|
||||
set_config: { ok: string } | { err: string };
|
||||
}>("nyanpasu://notice-message", ({ payload }) => {
|
||||
if ("ok" in payload?.set_config) {
|
||||
notification({
|
||||
title: t("Success"),
|
||||
body: "Refresh Clash Config",
|
||||
type: NotificationType.Success,
|
||||
});
|
||||
} else if ("err" in payload?.set_config) {
|
||||
notification({
|
||||
title: t("Error"),
|
||||
body: payload.set_config.err,
|
||||
type: NotificationType.Error,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
})
|
||||
.then((unlisten) => {
|
||||
unlistenFn.current = unlisten;
|
||||
})
|
||||
.catch((e) => {
|
||||
notification({
|
||||
title: t("Error"),
|
||||
body: e.message,
|
||||
type: NotificationType.Error,
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
unlistenFn.current?.();
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
@@ -20,6 +20,7 @@ export const SchemeProvider = () => {
|
||||
}
|
||||
|
||||
switch (url.pathname) {
|
||||
case "/install-config":
|
||||
case "/subscribe-remote-profile":
|
||||
navigate("/profiles", {
|
||||
state: {
|
||||
|
@@ -21,7 +21,7 @@ export const ChainItem = memo(function ChainItem({
|
||||
|
||||
const { palette } = useTheme();
|
||||
|
||||
const { deleteProfile } = useClash();
|
||||
const { deleteProfile, viewProfile } = useClash();
|
||||
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
@@ -34,6 +34,7 @@ export const ChainItem = memo(function ChainItem({
|
||||
const menuMapping = {
|
||||
Apply: () => handleClick(),
|
||||
"Edit Info": () => onChainEdit(),
|
||||
"Open File": () => viewProfile(item.uid),
|
||||
Delete: () => deleteProfile(item.uid),
|
||||
};
|
||||
|
||||
|
@@ -1,5 +1,9 @@
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { formatError } from "@/utils";
|
||||
import { message } from "@/utils/notification";
|
||||
import { Add } from "@mui/icons-material";
|
||||
import { alpha, ListItemButton, useTheme } from "@mui/material";
|
||||
import { Profile, useClash } from "@nyanpasu/interface";
|
||||
@@ -12,37 +16,48 @@ export interface SideChainProps {
|
||||
}
|
||||
|
||||
export const SideChain = ({ onChainEdit }: SideChainProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { palette } = useTheme();
|
||||
|
||||
const isGlobalChainCurrent = useAtomValue(atomGlobalChainCurrent);
|
||||
|
||||
const currnetProfile = useAtomValue(atomChainsSelected);
|
||||
const currentProfileUid = useAtomValue(atomChainsSelected);
|
||||
|
||||
const {
|
||||
getProfiles,
|
||||
setProfilesConfig,
|
||||
setProfiles,
|
||||
getRuntimeLogs: { mutate: mutateRuntimeLogs },
|
||||
} = useClash();
|
||||
const { getProfiles, setProfilesConfig, setProfiles } = useClash();
|
||||
|
||||
const { scripts } = filterProfiles(getProfiles.data?.items);
|
||||
|
||||
const currentProfile = useMemo(() => {
|
||||
return getProfiles.data?.items?.find(
|
||||
(item) => item.uid === currentProfileUid,
|
||||
);
|
||||
}, [getProfiles.data?.items, currentProfileUid]);
|
||||
|
||||
const handleChainClick = useLockFn(async (uid: string) => {
|
||||
const chains = isGlobalChainCurrent
|
||||
? (getProfiles.data?.chain ?? [])
|
||||
: (currnetProfile?.chains ?? []);
|
||||
: (currentProfile?.chains ?? []);
|
||||
|
||||
const updatedChains = chains.includes(uid)
|
||||
? chains.filter((chain) => chain !== uid)
|
||||
: [...chains, uid];
|
||||
|
||||
if (isGlobalChainCurrent) {
|
||||
await setProfilesConfig({ chain: updatedChains });
|
||||
} else {
|
||||
await setProfiles(uid, { chains: updatedChains });
|
||||
try {
|
||||
if (isGlobalChainCurrent) {
|
||||
await setProfilesConfig({ chain: updatedChains });
|
||||
} else {
|
||||
if (!currentProfile?.uid) {
|
||||
return;
|
||||
}
|
||||
await setProfiles(currentProfile!.uid, { chains: updatedChains });
|
||||
}
|
||||
} catch (e) {
|
||||
message(`Apply error: ${formatError(e)}`, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
}
|
||||
|
||||
mutateRuntimeLogs();
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -50,7 +65,7 @@ export const SideChain = ({ onChainEdit }: SideChainProps) => {
|
||||
{scripts?.map((item, index) => {
|
||||
const selected = isGlobalChainCurrent
|
||||
? getProfiles.data?.chain?.includes(item.uid)
|
||||
: currnetProfile?.chains?.includes(item.uid);
|
||||
: currentProfile?.chains?.includes(item.uid);
|
||||
|
||||
return (
|
||||
<ChainItem
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { isEmpty } from "lodash-es";
|
||||
import { memo } from "react";
|
||||
import { memo, useEffect } from "react";
|
||||
import { VList } from "virtua";
|
||||
import { classNames } from "@/utils";
|
||||
import { RamenDining, Terminal } from "@mui/icons-material";
|
||||
@@ -21,8 +21,9 @@ const LogListItem = memo(function LogListItem({
|
||||
{showDivider && <Divider />}
|
||||
|
||||
<div className="w-full break-all font-mono">
|
||||
<span className="text-red-500">[{name}]: </span>
|
||||
<span>{item}</span>
|
||||
<span className="rounded-sm bg-blue-600 px-0.5">{name}</span>
|
||||
<span className="text-red-500"> [{item?.[0]}]: </span>
|
||||
<span>{item?.[1]}</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@@ -3,4 +3,4 @@ import type { Profile } from "@nyanpasu/interface";
|
||||
|
||||
export const atomGlobalChainCurrent = atom<boolean>(false);
|
||||
|
||||
export const atomChainsSelected = atom<Profile.Item>();
|
||||
export const atomChainsSelected = atom<Profile.Item["uid"]>();
|
||||
|
@@ -3,7 +3,7 @@ import dayjs from "dayjs";
|
||||
import { motion } from "framer-motion";
|
||||
import { memo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
import {
|
||||
FiberManualRecord,
|
||||
@@ -108,7 +108,7 @@ export const ProfileItem = memo(function ProfileItem({
|
||||
await deleteConnections();
|
||||
} catch (err) {
|
||||
const is_fetch_error = err instanceof Error && err.name === "FetchError";
|
||||
useMessage(
|
||||
message(
|
||||
is_fetch_error
|
||||
? t("FetchError", {
|
||||
content: t("Subscription"),
|
||||
@@ -153,7 +153,7 @@ export const ProfileItem = memo(function ProfileItem({
|
||||
try {
|
||||
await deleteProfile(item.uid);
|
||||
} catch (err) {
|
||||
useMessage(`Delete failed: \n ${JSON.stringify(err)}`, {
|
||||
message(`Delete failed: \n ${JSON.stringify(err)}`, {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { useAsyncEffect, useUpdateEffect } from "ahooks";
|
||||
import { useUpdateEffect } from "ahooks";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { forwardRef, useImperativeHandle, useRef } from "react";
|
||||
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
||||
import { monaco } from "@/services/monaco";
|
||||
import { themeMode } from "@/store";
|
||||
|
||||
@@ -27,10 +27,9 @@ export const ProfileMonacoView = forwardRef(function ProfileMonacoView(
|
||||
|
||||
const instanceRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);
|
||||
|
||||
useAsyncEffect(async () => {
|
||||
if (open) {
|
||||
useEffect(() => {
|
||||
const run = async () => {
|
||||
const { monaco } = await import("@/services/monaco");
|
||||
|
||||
monacoeditorRef.current = monaco;
|
||||
|
||||
if (!monacoRef.current) {
|
||||
@@ -44,9 +43,13 @@ export const ProfileMonacoView = forwardRef(function ProfileMonacoView(
|
||||
minimap: { enabled: false },
|
||||
automaticLayout: true,
|
||||
});
|
||||
} else {
|
||||
instanceRef.current?.dispose();
|
||||
};
|
||||
if (open) {
|
||||
run().catch(console.error);
|
||||
}
|
||||
return () => {
|
||||
instanceRef.current?.dispose();
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
|
@@ -1,15 +1,16 @@
|
||||
import { Allotment } from "allotment";
|
||||
import "allotment/dist/style.css";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Close } from "@mui/icons-material";
|
||||
import { IconButton } from "@mui/material";
|
||||
import { Profile } from "@nyanpasu/interface";
|
||||
import { Profile, useClash } from "@nyanpasu/interface";
|
||||
import { SideChain } from "./modules/side-chain";
|
||||
import { SideLog } from "./modules/side-log";
|
||||
import { atomChainsSelected, atomGlobalChainCurrent } from "./modules/store";
|
||||
import { ScriptDialog } from "./script-dialog";
|
||||
import { filterProfiles } from "./utils";
|
||||
|
||||
export interface ProfileSideProps {
|
||||
onClose: () => void;
|
||||
@@ -24,7 +25,15 @@ export const ProfileSide = ({ onClose }: ProfileSideProps) => {
|
||||
|
||||
const isGlobalChainCurrent = useAtomValue(atomGlobalChainCurrent);
|
||||
|
||||
const currentProfile = useAtomValue(atomChainsSelected);
|
||||
const currentProfileUid = useAtomValue(atomChainsSelected);
|
||||
|
||||
const { getProfiles } = useClash();
|
||||
|
||||
const currentProfile = useMemo(() => {
|
||||
return getProfiles.data?.items?.find(
|
||||
(item) => item.uid === currentProfileUid,
|
||||
);
|
||||
}, [getProfiles.data?.items, currentProfileUid]);
|
||||
|
||||
const handleEditChain = async (_item?: Profile.Item) => {
|
||||
setItem(_item);
|
||||
|
@@ -2,11 +2,10 @@ import { useLockFn } from "ahooks";
|
||||
import dayjs from "dayjs";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import parseTraffic from "@/utils/parse-traffic";
|
||||
import { message } from "@/utils/notification";
|
||||
import { Refresh } from "@mui/icons-material";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import { Chip, LinearProgress, Paper, Tooltip } from "@mui/material";
|
||||
import { Chip, Paper } from "@mui/material";
|
||||
import { ProviderItem, useClashCore } from "@nyanpasu/interface";
|
||||
import ProxiesProviderTraffic from "./proxies-provider-traffic";
|
||||
|
||||
@@ -27,7 +26,7 @@ export const ProxiesProvider = ({ provider }: ProxiesProviderProps) => {
|
||||
|
||||
await updateProxiesProviders(provider.name);
|
||||
} catch (e) {
|
||||
useMessage(`Update ${provider.name} failed.\n${String(e)}`, {
|
||||
message(`Update ${provider.name} failed.\n${String(e)}`, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@ import { useLockFn } from "ahooks";
|
||||
import dayjs from "dayjs";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import { Refresh } from "@mui/icons-material";
|
||||
import LoadingButton from "@mui/lab/LoadingButton/LoadingButton";
|
||||
import { Chip, Paper } from "@mui/material";
|
||||
@@ -25,7 +25,7 @@ export default function RulesProvider({ provider }: RulesProviderProps) {
|
||||
|
||||
await updateRulesProviders(provider.name);
|
||||
} catch (e) {
|
||||
useMessage(`Update ${provider.name} failed.\n${String(e)}`, {
|
||||
message(`Update ${provider.name} failed.\n${String(e)}`, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import { Refresh } from "@mui/icons-material";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import { useClashCore } from "@nyanpasu/interface";
|
||||
@@ -15,7 +15,7 @@ export const UpdateProviders = () => {
|
||||
|
||||
const handleProviderUpdate = useLockFn(async () => {
|
||||
if (!getRulesProviders.data) {
|
||||
useMessage(`No Providers.`, {
|
||||
message(`No Providers.`, {
|
||||
type: "info",
|
||||
title: t("Info"),
|
||||
});
|
||||
@@ -34,7 +34,7 @@ export const UpdateProviders = () => {
|
||||
providers.map((provider) => updateRulesProviders(provider)),
|
||||
);
|
||||
} catch (e) {
|
||||
useMessage(`Update all failed.\n${String(e)}`, {
|
||||
message(`Update all failed.\n${String(e)}`, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import { Refresh } from "@mui/icons-material";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import { useClashCore } from "@nyanpasu/interface";
|
||||
@@ -15,7 +15,7 @@ export const UpdateProxiesProviders = () => {
|
||||
|
||||
const handleProviderUpdate = useLockFn(async () => {
|
||||
if (!getProxiesProviders.data) {
|
||||
useMessage(`No Providers.`, {
|
||||
message(`No Providers.`, {
|
||||
type: "info",
|
||||
title: t("Info"),
|
||||
});
|
||||
@@ -34,7 +34,7 @@ export const UpdateProxiesProviders = () => {
|
||||
providers.map((provider) => updateProxiesProviders(provider)),
|
||||
);
|
||||
} catch (e) {
|
||||
useMessage(`Update all failed.\n${String(e)}`, {
|
||||
message(`Update all failed.\n${String(e)}`, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import clsx from "clsx";
|
||||
import { memo, useState } from "react";
|
||||
import { useColorForDelay } from "@/hooks/theme";
|
||||
import { classNames } from "@/utils";
|
||||
import { Bolt } from "@mui/icons-material";
|
||||
import { CircularProgress } from "@mui/material";
|
||||
import FeatureChip from "./feature-chip";
|
||||
import { getColorForDelay } from "./utils";
|
||||
|
||||
export const DelayChip = memo(function DelayChip({
|
||||
className,
|
||||
@@ -32,7 +32,7 @@ export const DelayChip = memo(function DelayChip({
|
||||
className={clsx(className, loading && "!visible")}
|
||||
sx={{
|
||||
ml: "auto",
|
||||
color: getColorForDelay(delay),
|
||||
color: useColorForDelay(delay),
|
||||
}}
|
||||
label={
|
||||
<>
|
||||
|
@@ -1,6 +1,3 @@
|
||||
import { useAtomValue } from "jotai";
|
||||
import { proxyGroupSortAtom } from "@/store";
|
||||
import { useTheme } from "@mui/material";
|
||||
import type { Clash } from "@nyanpasu/interface";
|
||||
|
||||
export type History = Clash.Proxy["history"];
|
||||
@@ -13,30 +10,6 @@ export const filterDelay = (history?: History): number => {
|
||||
}
|
||||
};
|
||||
|
||||
export const getColorForDelay = (delay: number): string => {
|
||||
const { palette } = useTheme();
|
||||
|
||||
const delayColorMapping: { [key: string]: string } = {
|
||||
"-1": palette.text.primary,
|
||||
"0": palette.text.secondary,
|
||||
"1": palette.text.secondary,
|
||||
"100": palette.success.main,
|
||||
"500": palette.warning.main,
|
||||
"10000": palette.error.main,
|
||||
};
|
||||
|
||||
let color: string = palette.text.secondary;
|
||||
|
||||
for (const key in delayColorMapping) {
|
||||
if (delay <= parseInt(key)) {
|
||||
color = delayColorMapping[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
};
|
||||
|
||||
export enum SortType {
|
||||
Default = "default",
|
||||
Dealy = "delay",
|
||||
|
@@ -22,7 +22,7 @@ export const clash = {
|
||||
* @author keiko233 <i@elaina.moe>
|
||||
* @copyright LibNyanpasu org. 2024
|
||||
*/
|
||||
createBooleanProps: (
|
||||
useBooleanProps: (
|
||||
propName: {
|
||||
[K in keyof Clash.Config]: Clash.Config[K] extends boolean ? K : never;
|
||||
}[keyof Clash.Config],
|
||||
@@ -52,7 +52,7 @@ export const clash = {
|
||||
* @author keiko233 <i@elaina.moe>
|
||||
* @copyright LibNyanpasu org. 2024
|
||||
*/
|
||||
createMenuProps: (
|
||||
useMenuProps: (
|
||||
propName: keyof Clash.Config,
|
||||
{ options, fallbackSelect }: CreateMenuPropsOptions,
|
||||
): Omit<MenuItemProps, "label"> => {
|
||||
@@ -81,7 +81,7 @@ export const nyanpasu = {
|
||||
* @author keiko233 <i@elaina.moe>
|
||||
* @copyright LibNyanpasu org. 2024
|
||||
*/
|
||||
createBooleanProps: (propName: keyof VergeConfig): SwitchProps => {
|
||||
useBooleanProps: (propName: keyof VergeConfig): SwitchProps => {
|
||||
const { nyanpasuConfig, setNyanpasuConfig } = useNyanpasu();
|
||||
|
||||
if (typeof nyanpasuConfig?.[propName] !== "boolean") {
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import { useLockFn, useMemoizedFn } from "ahooks";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { NotificationType, useNotification } from "@/hooks/use-notification";
|
||||
import { notification, NotificationType } from "@/utils/notification";
|
||||
import { Typography } from "@mui/material";
|
||||
import { useNyanpasu } from "@nyanpasu/interface";
|
||||
import { BaseDialog, BaseDialogProps } from "@nyanpasu/ui";
|
||||
import HotkeyInput from "./hotkey-input";
|
||||
|
||||
export interface HotkeyDialogProps extends Omit<BaseDialogProps, "title"> {}
|
||||
export type HotkeyDialogProps = Omit<BaseDialogProps, "title">;
|
||||
|
||||
const HOTKEY_FUNC = [
|
||||
"open_or_close_dashboard",
|
||||
@@ -86,7 +86,7 @@ export default function HotkeyDialog({
|
||||
try {
|
||||
await setNyanpasuConfig({ hotkeys });
|
||||
} catch (err: any) {
|
||||
useNotification({
|
||||
notification({
|
||||
title: t("Error"),
|
||||
body: err.message || err.toString(),
|
||||
type: NotificationType.Error,
|
||||
|
@@ -1,23 +1,25 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import getSystem from "@/utils/get-system";
|
||||
import { message } from "@/utils/notification";
|
||||
import { Button, List, ListItem, ListItemText } from "@mui/material";
|
||||
import { pullupUWPTool } from "@nyanpasu/interface";
|
||||
import { BaseCard, MenuItem, SwitchItem } from "@nyanpasu/ui";
|
||||
import { clash } from "./modules";
|
||||
|
||||
const { createBooleanProps, createMenuProps } = clash;
|
||||
const { useBooleanProps: createBooleanProps, useMenuProps: createMenuProps } =
|
||||
clash;
|
||||
|
||||
const isWIN = getSystem() === "windows";
|
||||
|
||||
export const SettingClashBase = () => {
|
||||
const { t } = useTranslation();
|
||||
// const [coreType] = useCoreType();
|
||||
|
||||
const clickUWP = async () => {
|
||||
try {
|
||||
await pullupUWPTool();
|
||||
} catch (e) {
|
||||
useMessage(`Failed to Open UWP Tools.\n${JSON.stringify(e)}`, {
|
||||
message(`Failed to Open UWP Tools.\n${JSON.stringify(e)}`, {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@ import { useLockFn, useReactive } from "ahooks";
|
||||
import { motion } from "framer-motion";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import { Box, List, ListItem } from "@mui/material";
|
||||
import { ClashCore, useClash, useNyanpasu } from "@nyanpasu/interface";
|
||||
@@ -39,22 +39,25 @@ export const SettingClashCore = () => {
|
||||
: data?.meta
|
||||
? `${data.version} Meta`
|
||||
: data?.version || "-";
|
||||
}, [getVersion.data, nyanpasuConfig]);
|
||||
}, [getVersion.data]);
|
||||
|
||||
const changeClashCore = useLockFn(async (core: ClashCore) => {
|
||||
try {
|
||||
loading.mask = true;
|
||||
|
||||
await deleteConnections();
|
||||
try {
|
||||
await deleteConnections();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
await setClashCore(core);
|
||||
|
||||
useMessage(`Successfully switch to ${core}`, {
|
||||
message(`Successfully switch to ${core}`, {
|
||||
type: "info",
|
||||
title: t("Success"),
|
||||
});
|
||||
} catch (e) {
|
||||
useMessage(
|
||||
message(
|
||||
`Switching failed, you could see the details in the log. \nError: ${
|
||||
e instanceof Error ? e.message : String(e)
|
||||
}`,
|
||||
@@ -74,12 +77,12 @@ export const SettingClashCore = () => {
|
||||
|
||||
await restartSidecar();
|
||||
|
||||
useMessage(t("Successfully restart core"), {
|
||||
message(t("Successfully restart core"), {
|
||||
type: "info",
|
||||
title: t("Success"),
|
||||
});
|
||||
} catch (e) {
|
||||
useMessage("Restart failed, please check log.", {
|
||||
message("Restart failed, please check log.", {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
@@ -94,7 +97,7 @@ export const SettingClashCore = () => {
|
||||
|
||||
await getLatestCore.mutate();
|
||||
} catch (e) {
|
||||
useMessage("Fetch failed, please check your internet connection.", {
|
||||
message("Fetch failed, please check your internet connection.", {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
@@ -110,12 +113,12 @@ export const SettingClashCore = () => {
|
||||
|
||||
await updateCore(core);
|
||||
|
||||
useMessage(`Successfully update core ${core}`, {
|
||||
message(`Successfully update core ${core}`, {
|
||||
type: "info",
|
||||
title: t("Success"),
|
||||
});
|
||||
} catch (e) {
|
||||
useMessage(`Update failed.`, {
|
||||
message(`Update failed.`, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
@@ -137,7 +140,7 @@ export const SettingClashCore = () => {
|
||||
};
|
||||
});
|
||||
}, [getClashCore.data, getLatestCore.data]);
|
||||
|
||||
console.log(nyanpasuConfig?.clash_core);
|
||||
return (
|
||||
<BaseCard
|
||||
label={t("Clash Core")}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { ChangeEvent, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import Done from "@mui/icons-material/Done";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import {
|
||||
@@ -79,7 +79,7 @@ export const SettingClashExternal = () => {
|
||||
}),
|
||||
]);
|
||||
} catch (e) {
|
||||
useMessage(JSON.stringify(e), {
|
||||
message(JSON.stringify(e), {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import { List } from "@mui/material";
|
||||
import { useClash, useNyanpasu } from "@nyanpasu/interface";
|
||||
import { BaseCard, NumberItem, SwitchItem } from "@nyanpasu/ui";
|
||||
@@ -43,12 +43,12 @@ export const SettingClashPort = () => {
|
||||
enable_random_port: !nyanpasuConfig?.enable_random_port,
|
||||
});
|
||||
} catch (e) {
|
||||
useMessage(JSON.stringify(e), {
|
||||
message(JSON.stringify(e), {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
useMessage(t("After restart to take effect"), {
|
||||
message(t("After restart to take effect"), {
|
||||
title: t("Success"),
|
||||
type: "info",
|
||||
});
|
||||
|
@@ -30,7 +30,7 @@ export const SettingClashWeb = () => {
|
||||
port,
|
||||
secret: getClashInfo.data?.secret,
|
||||
};
|
||||
}, [getClashInfo.data, getClashInfo.data?.server]);
|
||||
}, [getClashInfo.data]);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
@@ -47,7 +47,7 @@ export const SettingClashWeb = () => {
|
||||
};
|
||||
|
||||
const updateItem = () => {
|
||||
const list = nyanpasuConfig?.web_ui_list || [];
|
||||
const list = [...(nyanpasuConfig?.web_ui_list || [])];
|
||||
|
||||
if (!list) return;
|
||||
|
||||
|
@@ -4,7 +4,7 @@ import { useNyanpasu } from "@nyanpasu/interface";
|
||||
import { BaseCard, MenuItem, SwitchItem, TextItem } from "@nyanpasu/ui";
|
||||
import { nyanpasu } from "./modules/create-props";
|
||||
|
||||
const { createBooleanProps } = nyanpasu;
|
||||
const { useBooleanProps: createBooleanProps } = nyanpasu;
|
||||
|
||||
export const SettingNyanpasuMisc = () => {
|
||||
const { t } = useTranslation();
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { sleep } from "@/utils";
|
||||
import { message } from "@/utils/notification";
|
||||
import Grid from "@mui/material/Unstable_Grid2";
|
||||
import {
|
||||
collectLogs,
|
||||
@@ -33,7 +33,7 @@ export const SettingNyanpasuPath = () => {
|
||||
}
|
||||
|
||||
if (Array.isArray(selected)) {
|
||||
useMessage(t("Multiple directories are not supported"), {
|
||||
message(t("Multiple directories are not supported"), {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
@@ -43,7 +43,7 @@ export const SettingNyanpasuPath = () => {
|
||||
|
||||
await setCustomAppDir(selected);
|
||||
|
||||
useMessage(t("App directory changed successfully"), {
|
||||
message(t("App directory changed successfully"), {
|
||||
title: t("Success"),
|
||||
type: "error",
|
||||
});
|
||||
@@ -52,7 +52,7 @@ export const SettingNyanpasuPath = () => {
|
||||
|
||||
await restartApplication();
|
||||
} catch (e) {
|
||||
useMessage(`Migration failed! ${JSON.stringify(e)}`, {
|
||||
message(`Migration failed! ${JSON.stringify(e)}`, {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import { version } from "~/package.json";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import LogoSvg from "@/assets/image/logo.svg?react";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import {
|
||||
alpha,
|
||||
@@ -53,24 +53,21 @@ export const SettingNyanpasuVersion = () => {
|
||||
const info = await checkUpdate();
|
||||
|
||||
if (!info?.shouldUpdate) {
|
||||
useMessage(t("No update available."), {
|
||||
message(t("No update available."), {
|
||||
title: t("Info"),
|
||||
type: "info",
|
||||
});
|
||||
} else {
|
||||
useMessage(`New Version: ${info.manifest?.version}`, {
|
||||
message(`New Version: ${info.manifest?.version}`, {
|
||||
title: t("New Version"),
|
||||
type: "info",
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
useMessage(
|
||||
"Update check failed. Please verify your network connection.",
|
||||
{
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
},
|
||||
);
|
||||
message("Update check failed. Please verify your network connection.", {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { useLockFn, useReactive } from "ahooks";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import { Done } from "@mui/icons-material";
|
||||
import {
|
||||
Box,
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
List,
|
||||
ListItem,
|
||||
TextField,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import Grid from "@mui/material/Unstable_Grid2";
|
||||
@@ -43,7 +42,7 @@ export const SettingSystemProxy = () => {
|
||||
[key]: !nyanpasuConfig?.[key],
|
||||
});
|
||||
} catch (e) {
|
||||
useMessage(`Activation failed!`, {
|
||||
message(`Activation failed!`, {
|
||||
title: t("Error"),
|
||||
type: "error",
|
||||
});
|
||||
|
@@ -1,14 +1,14 @@
|
||||
import { useMemoizedFn } from "ahooks";
|
||||
import { ChangeEvent, useTransition } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMessage } from "@/hooks/use-notification";
|
||||
import { message } from "@/utils/notification";
|
||||
import { LoadingButton } from "@mui/lab";
|
||||
import { List, ListItem, ListItemText, Typography } from "@mui/material";
|
||||
import { restartSidecar, useNyanpasu } from "@nyanpasu/interface";
|
||||
import { BaseCard, SwitchItem } from "@nyanpasu/ui";
|
||||
import { nyanpasu } from "./modules/create-props";
|
||||
|
||||
const { createBooleanProps } = nyanpasu;
|
||||
const { useBooleanProps: createBooleanProps } = nyanpasu;
|
||||
|
||||
export const SettingSystemService = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -65,7 +65,7 @@ export const SettingSystemService = () => {
|
||||
? "Install failed"
|
||||
: "Uninstall failed";
|
||||
|
||||
useMessage(errorMessage, {
|
||||
message(errorMessage, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
@@ -94,7 +94,7 @@ export const SettingSystemService = () => {
|
||||
const errorMessage =
|
||||
getServiceStatus.data === "running" ? "Stop failed" : "Start failed";
|
||||
|
||||
useMessage(errorMessage, {
|
||||
message(errorMessage, {
|
||||
type: "error",
|
||||
title: t("Error"),
|
||||
});
|
||||
|
25
clash-nyanpasu/frontend/nyanpasu/src/hooks/theme.ts
Normal file
25
clash-nyanpasu/frontend/nyanpasu/src/hooks/theme.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useTheme } from "@mui/material";
|
||||
|
||||
export const useColorForDelay = (delay: number): string => {
|
||||
const { palette } = useTheme();
|
||||
|
||||
const delayColorMapping: { [key: string]: string } = {
|
||||
"-1": palette.text.primary,
|
||||
"0": palette.text.secondary,
|
||||
"1": palette.text.secondary,
|
||||
"100": palette.success.main,
|
||||
"500": palette.warning.main,
|
||||
"10000": palette.error.main,
|
||||
};
|
||||
|
||||
let color: string = palette.text.secondary;
|
||||
|
||||
for (const key in delayColorMapping) {
|
||||
if (delay <= parseInt(key)) {
|
||||
color = delayColorMapping[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
};
|
17
clash-nyanpasu/frontend/nyanpasu/src/hooks/use-store.ts
Normal file
17
clash-nyanpasu/frontend/nyanpasu/src/hooks/use-store.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useAtom } from "jotai";
|
||||
import { coreTypeAtom } from "@/store/clash";
|
||||
import { useNyanpasu } from "@nyanpasu/interface";
|
||||
|
||||
export function useCoreType() {
|
||||
const [coreType, setCoreType] = useAtom(coreTypeAtom);
|
||||
const { setNyanpasuConfig } = useNyanpasu({
|
||||
onSuccess(data) {
|
||||
setCoreType(data?.clash_core || "mihomo");
|
||||
},
|
||||
});
|
||||
const setter = (value: typeof coreType) => {
|
||||
setCoreType(value);
|
||||
setNyanpasuConfig({ clash_core: value });
|
||||
};
|
||||
return [coreType, setter] as const;
|
||||
}
|
@@ -1,13 +1,7 @@
|
||||
import dayjs from "dayjs";
|
||||
import "dayjs/locale/ru";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { AnimatePresence } from "framer-motion";
|
||||
import { useMemo } from "react";
|
||||
import { FallbackProps } from "react-error-boundary";
|
||||
import { SWRConfig } from "swr";
|
||||
import AppContainer from "@/components/app/app-container";
|
||||
import LocalesProvider from "@/components/app/locales-provider";
|
||||
import MutationProvider from "@/components/layout/mutation-provider";
|
||||
import NoticeProvider from "@/components/layout/notice-provider";
|
||||
import PageTransition from "@/components/layout/page-transition";
|
||||
import SchemeProvider from "@/components/layout/scheme-provider";
|
||||
@@ -20,6 +14,12 @@ import { classNames } from "@/utils";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { Experimental_CssVarsProvider as CssVarsProvider } from "@mui/material/styles";
|
||||
import { useBreakpoint } from "@nyanpasu/ui";
|
||||
import "dayjs/locale/ru";
|
||||
import "dayjs/locale/zh-cn";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { useMemo } from "react";
|
||||
import { FallbackProps } from "react-error-boundary";
|
||||
import { SWRConfig } from "swr";
|
||||
import styles from "./_app.module.scss";
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
@@ -37,6 +37,7 @@ export default function App() {
|
||||
<ThemeModeProvider />
|
||||
<LogProvider />
|
||||
<LocalesProvider />
|
||||
<MutationProvider />
|
||||
<NoticeProvider />
|
||||
<SchemeProvider />
|
||||
|
||||
|
@@ -34,10 +34,10 @@ export const ProfilePage = () => {
|
||||
const onClickChains = (profile: Profile.Item) => {
|
||||
setGlobalChain(false);
|
||||
|
||||
if (chainsSelected?.uid == profile.uid) {
|
||||
if (chainsSelected == profile.uid) {
|
||||
setChainsSelected(undefined);
|
||||
} else {
|
||||
setChainsSelected(profile);
|
||||
setChainsSelected(profile.uid);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -85,7 +85,7 @@ export const ProfilePage = () => {
|
||||
item={item}
|
||||
onClickChains={onClickChains}
|
||||
selected={getProfiles.data?.current == item.uid}
|
||||
chainsSelected={chainsSelected?.uid == item.uid}
|
||||
chainsSelected={chainsSelected == item.uid}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
5
clash-nyanpasu/frontend/nyanpasu/src/store/clash.ts
Normal file
5
clash-nyanpasu/frontend/nyanpasu/src/store/clash.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { atom } from "jotai";
|
||||
import type { VergeConfig } from "@nyanpasu/interface/service/types";
|
||||
|
||||
export const coreTypeAtom =
|
||||
atom<NonNullable<VergeConfig["clash_core"]>>("mihomo");
|
16
clash-nyanpasu/frontend/nyanpasu/src/utils/mutation.ts
Normal file
16
clash-nyanpasu/frontend/nyanpasu/src/utils/mutation.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useCallback } from "react";
|
||||
import { cache, mutate } from "swr/_internal";
|
||||
|
||||
export const useGlobalMutation = () => {
|
||||
return useCallback((swrKey, ...args) => {
|
||||
const matcher = typeof swrKey === "function" ? swrKey : undefined;
|
||||
|
||||
if (matcher) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const keys = Array.from(cache.keys()).filter(matcher as any);
|
||||
keys.forEach((key) => mutate(key, ...args));
|
||||
} else {
|
||||
mutate(swrKey, ...args);
|
||||
}
|
||||
}, []) as typeof mutate;
|
||||
};
|
@@ -1,6 +1,9 @@
|
||||
import { Notice } from "@/components/base";
|
||||
import { isPortable } from "@nyanpasu/interface";
|
||||
import { message, MessageDialogOptions } from "@tauri-apps/api/dialog";
|
||||
import {
|
||||
MessageDialogOptions,
|
||||
message as tauriMessage,
|
||||
} from "@tauri-apps/api/dialog";
|
||||
import {
|
||||
isPermissionGranted,
|
||||
Options,
|
||||
@@ -35,7 +38,7 @@ export enum NotificationType {
|
||||
Error = "error",
|
||||
}
|
||||
|
||||
export const useNotification = async ({
|
||||
export const notification = async ({
|
||||
title,
|
||||
body,
|
||||
type = NotificationType.Info,
|
||||
@@ -60,16 +63,16 @@ export const useNotification = async ({
|
||||
sendNotification(options);
|
||||
};
|
||||
|
||||
export const useMessage = async (
|
||||
export const message = async (
|
||||
value: string,
|
||||
options?: string | MessageDialogOptions | undefined,
|
||||
) => {
|
||||
if (typeof options === "object") {
|
||||
await message(value, {
|
||||
await tauriMessage(value, {
|
||||
...options,
|
||||
title: `Clash Nyanpasu - ${options.title}`,
|
||||
});
|
||||
} else {
|
||||
await message(value, options);
|
||||
await tauriMessage(value, options);
|
||||
}
|
||||
};
|
@@ -1,8 +1,9 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const plugin = require("tailwindcss/plugin");
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
module.exports = {
|
||||
content: ["./src/**/*.{tsx,ts}", "../ui/**/*.{tsx,ts}"],
|
||||
theme: {
|
||||
extend: {
|
10
clash-nyanpasu/knip.config.ts
Normal file
10
clash-nyanpasu/knip.config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { KnipConfig } from "knip";
|
||||
|
||||
export default {
|
||||
entry: [
|
||||
"frontend/nyanpasu/src/main.tsx",
|
||||
"frontend/nyanpasu/src/pages/**/*.tsx",
|
||||
"scripts/*.{js,ts}",
|
||||
],
|
||||
project: ["frontend/**/*.{ts,js,jsx,tsx}", "scripts/**/*.{js,ts}"],
|
||||
} satisfies KnipConfig;
|
@@ -3,7 +3,7 @@
|
||||
"latest": {
|
||||
"mihomo": "v1.18.7",
|
||||
"mihomo_alpha": "alpha-e7e1400",
|
||||
"clash_rs": "v0.1.20",
|
||||
"clash_rs": "v0.2.0",
|
||||
"clash_premium": "2023-09-05-gdcc8d87"
|
||||
},
|
||||
"arch_template": {
|
||||
@@ -36,5 +36,5 @@
|
||||
"darwin-x64": "clash-darwin-amd64-n{}.gz"
|
||||
}
|
||||
},
|
||||
"updated_at": "2024-07-31T22:20:11.102Z"
|
||||
"updated_at": "2024-08-02T13:35:50.641Z"
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@
|
||||
"lint:ts": "tsc --noEmit",
|
||||
"lint:clippy": "cargo clippy --manifest-path ./backend/Cargo.toml --all-targets --all-features",
|
||||
"lint:rustfmt": "cargo fmt --manifest-path ./backend/Cargo.toml --all -- --check",
|
||||
"knip": "knip",
|
||||
"test": "run-p test:*",
|
||||
"test:backend": "cargo test --manifest-path ./backend/Cargo.toml --all-features",
|
||||
"fmt": "run-p fmt:*",
|
||||
@@ -55,7 +56,9 @@
|
||||
"@tauri-apps/cli": "1.6.0",
|
||||
"@types/fs-extra": "11.0.4",
|
||||
"@types/lodash-es": "4.17.12",
|
||||
"@types/node": "20.14.13",
|
||||
"@types/node": "20.14.14",
|
||||
"@typescript-eslint/eslint-plugin": "8.0.0",
|
||||
"@typescript-eslint/parser": "8.0.0",
|
||||
"autoprefixer": "10.4.19",
|
||||
"conventional-changelog-conventionalcommits": "8.0.0",
|
||||
"cross-env": "7.0.3",
|
||||
@@ -70,6 +73,9 @@
|
||||
"eslint-plugin-prettier": "5.2.1",
|
||||
"eslint-plugin-promise": "6.6.0",
|
||||
"eslint-plugin-react": "7.35.0",
|
||||
"eslint-plugin-react-compiler": "0.0.0-experimental-9ed098e-20240725",
|
||||
"eslint-plugin-react-hooks": "4.6.2",
|
||||
"knip": "5.27.0",
|
||||
"lint-staged": "15.2.7",
|
||||
"npm-run-all2": "6.2.2",
|
||||
"postcss": "8.4.40",
|
||||
|
695
clash-nyanpasu/pnpm-lock.yaml
generated
695
clash-nyanpasu/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
51
lede/package/lean/leigod-acc/files/leigod-helper.sh
Normal file
51
lede/package/lean/leigod-acc/files/leigod-helper.sh
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
# https://github.com/isecret/leigod-helper/blob/main/leigod-helper.sh
|
||||
|
||||
USERNAME="${USERNAME:-phone}"
|
||||
PASSWORD="${PASSWORD:-password}"
|
||||
|
||||
if ! command -v "jq" > /dev/null; then
|
||||
echo "缺失 jq 依赖";
|
||||
exit;
|
||||
fi
|
||||
|
||||
if command -v md5sum > /dev/null; then
|
||||
password_hash=$(echo -n "$PASSWORD" | md5sum | awk '{print $1}')
|
||||
elif command -v md5 > /dev/null; then
|
||||
password_hash=$(echo -n "$PASSWORD" | md5)
|
||||
else
|
||||
echo "缺失 md5 或 md5sum 依赖,请手动安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
login=$(curl -Lks -X POST https://webapi.leigod.com/api/auth/login \
|
||||
-H 'content-type: application/json' \
|
||||
-d "{
|
||||
\"account_token\": null,
|
||||
\"country_code\": 86,
|
||||
\"lang\": \"zh_CN\",
|
||||
\"password\": \"$password_hash\",
|
||||
\"region_code\": 1,
|
||||
\"src_channel\": \"guanwang\",
|
||||
\"user_type\": \"0\",
|
||||
\"username\": \"$USERNAME\"
|
||||
}")
|
||||
|
||||
login_code=$(echo $login | jq -r ".code" 2>&1)
|
||||
login_msg=$(echo $login | jq -r ".msg" 2>&1)
|
||||
|
||||
if [ "$login_code" -eq 0 ]; then
|
||||
account_token=$(echo $login | jq -r ".data.login_info.account_token" 2>&1)
|
||||
pause=$(curl -Lks -X POST https://webapi.leigod.com/api/user/pause \
|
||||
-H 'content-type: application/json' \
|
||||
-d "{
|
||||
\"account_token\": \"$account_token\",
|
||||
\"lang\": \"zh_CN\"
|
||||
}")
|
||||
pause_code=$(echo $pause | jq -r ".code" 2>&1)
|
||||
pause_msg=$(echo $pause | jq -r ".msg" 2>&1)
|
||||
|
||||
echo "暂停结果: $pause_msg"
|
||||
else
|
||||
echo "登录失败...原因: $login_msg"
|
||||
fi
|
@@ -10,7 +10,7 @@ LUCI_TITLE:=Luci for Leigod Game Accelerater
|
||||
LUCI_PKGARCH:=all
|
||||
LUCI_DEPENDS:=+libpcap +iptables +kmod-ipt-nat +iptables-mod-tproxy +kmod-ipt-tproxy +kmod-tun +kmod-netem +tc-full +kmod-ipt-ipset +ipset +curl +miniupnpd +conntrack +conntrackd +leigod-acc
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
@@ -5,6 +5,7 @@ function index()
|
||||
entry({ "admin", "services", "acc" }, alias("admin", "services", "acc", "service"), translate("Leigod Acc"), 50)
|
||||
entry({ "admin", "services", "acc", "service" }, cbi("leigod/service"), translate("Leigod Service"), 30).i18n = "acc"
|
||||
entry({ "admin", "services", "acc", "device" }, cbi("leigod/device"), translate("Leigod Device"), 50).i18n = "acc"
|
||||
entry({ "admin", "services", "acc", "app" }, cbi("leigod/app"), translate("Leigod App"), 60).i18n = "acc"
|
||||
entry({ "admin", "services", "acc", "notice" }, cbi("leigod/notice"), translate("Leigod Notice"), 80).i18n = "acc"
|
||||
entry({ "admin", "services", "acc", "status" }, call("get_acc_status")).leaf = true
|
||||
entry({ "admin", "services", "acc", "start_acc_service" }, call("start_acc_service"))
|
||||
@@ -61,7 +62,7 @@ function start_acc_service()
|
||||
luci.http.write_json(resp)
|
||||
end
|
||||
|
||||
-- start_acc_service
|
||||
-- stop_acc_service
|
||||
function stop_acc_service()
|
||||
-- util module
|
||||
local util = require "luci.util"
|
||||
@@ -71,4 +72,30 @@ function stop_acc_service()
|
||||
resp.result = "OK"
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(resp)
|
||||
end
|
||||
|
||||
-- schedule_pause
|
||||
function schedule_pause()
|
||||
local util = require "luci.util"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local schedule_enabled = uci:get("accelerator", "system", "schedule_enabled") or "0"
|
||||
local pause_time = uci:get("accelerator", "system", "pause_time") or "01:00"
|
||||
local username = uci:get("accelerator", "system", "username") or ""
|
||||
local password = uci:get("accelerator", "system", "password") or ""
|
||||
|
||||
-- Remove existing cron jobs related to leigod_helper.sh
|
||||
util.exec("sed -i '/usr/sbin/leigod/leigod_helper.sh/d' /etc/crontabs/root")
|
||||
|
||||
if schedule_enabled == "1" then
|
||||
-- Set the new cron job
|
||||
local hour, minute = pause_time:match("(%d+):(%d+)")
|
||||
local cron_time = string.format("%d %d * * * USERNAME=%s PASSWORD=%s /usr/sbin/leigod/leigod_helper.sh", tonumber(minute), tonumber(hour), username, password)
|
||||
util.exec(string.format('echo "%s" >> /etc/crontabs/root', cron_time))
|
||||
util.exec("/etc/init.d/cron restart")
|
||||
end
|
||||
|
||||
local resp = {}
|
||||
resp.result = "OK"
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(resp)
|
||||
end
|
@@ -0,0 +1,7 @@
|
||||
require("luci.util")
|
||||
|
||||
mp = Map("accelerator")
|
||||
|
||||
mp:section(SimpleSection).template = "leigod/app"
|
||||
|
||||
return mp
|
@@ -1,10 +1,46 @@
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
|
||||
-- config
|
||||
m = Map("accelerator")
|
||||
m.title = translate("Leigod Accelerator Config")
|
||||
m.description = translate("Control Accelerator Config")
|
||||
m = Map("accelerator")
|
||||
m.title = translate("Leigod Accelerator Config")
|
||||
m.description = translate("Control Accelerator Config")
|
||||
|
||||
s = m:section(TypedSection, "system")
|
||||
s.addremove = false
|
||||
s.anonymous = true
|
||||
|
||||
enable = s:option(Flag,"enabled" ,translate("Enable"))
|
||||
enable.rmempty = false
|
||||
enable.default = 0
|
||||
|
||||
tun = s:option(Flag,"tun" ,translate("Tunnel Mode"))
|
||||
tun.rmempty = false
|
||||
tun.default = 0
|
||||
tun.description = translate("Turning Leigod into Tunnel mode can make some proxy plugins available")
|
||||
|
||||
schedule_enabled = s:option(Flag, "schedule_enabled", translate("Scheduled Pause"))
|
||||
schedule_enabled.rmempty = false
|
||||
schedule_enabled.default = 0
|
||||
schedule_enabled.description = translate("夜猫子选项")
|
||||
|
||||
pause_time = s:option(ListValue, "pause_time", translate("Pause Time"))
|
||||
pause_time:depends("schedule_enabled", 1)
|
||||
for i = 0, 23 do
|
||||
pause_time:value(string.format("%02d:00", i), string.format("%02d:00", i))
|
||||
end
|
||||
pause_time.rmempty = false
|
||||
pause_time.description = translate("选择好时间雷神加速器会定时暂停,请避开你的游戏时间以免影响游戏体验")
|
||||
|
||||
|
||||
username = s:option(Value, "username", translate("Phone Number"))
|
||||
username:depends("schedule_enabled", 1)
|
||||
username.rmempty = false
|
||||
|
||||
password = s:option(Value, "password", translate("Leigod Password"))
|
||||
password:depends("schedule_enabled", 1)
|
||||
password.password = true
|
||||
password.rmempty = false
|
||||
|
||||
m:section(SimpleSection).template = "leigod/service"
|
||||
|
||||
return m
|
||||
return m
|
@@ -0,0 +1,6 @@
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<p id="leigod_qcode">
|
||||
<img src="/leigodapp.png" height="300" /><img src="/leigodbind.png" height="300" />
|
||||
</p>
|
||||
</fieldset>
|
@@ -1,4 +1,4 @@
|
||||
<!-- acc service state -->
|
||||
<!-- acc service state
|
||||
<fieldset class="cbi-section">
|
||||
<table class="cbi-section-table" id="acc_service_state_table">
|
||||
<tr class="cbi-section-table-title">
|
||||
@@ -12,7 +12,7 @@
|
||||
<td id="acc_service_state_button"><%:Acc_Service_Operate%></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
</fieldset> -->
|
||||
|
||||
<!-- acc catalog state -->
|
||||
<fieldset class="cbi-section">
|
||||
|
@@ -8,14 +8,17 @@ msgstr "服务控制"
|
||||
msgid "Leigod Device"
|
||||
msgstr "设备管理"
|
||||
|
||||
msgid "Leigod App"
|
||||
msgstr "雷神移动端APP"
|
||||
|
||||
msgid "Leigod Notice"
|
||||
msgstr "加速公告"
|
||||
|
||||
msgid "Leigod Accelerator Config"
|
||||
msgstr "加速器配置"
|
||||
msgstr "雷神加速器 - 专线加速游戏,按分钟计费可暂停,玩多久算多久,时长永久有效"
|
||||
|
||||
msgid "Control Accelerator Config"
|
||||
msgstr "控制加速配置选项"
|
||||
msgstr "加速时长6端通用 (Windows端 | Mac端 | NN | 手机端 | 主机端 | 路由器)"
|
||||
|
||||
msgid "Acc_Service_Name"
|
||||
msgstr "服务名称"
|
||||
@@ -80,8 +83,8 @@ msgstr "手机设备"
|
||||
msgid "None_Catalog"
|
||||
msgstr "未分类设备"
|
||||
|
||||
msgid "None"
|
||||
msgstr "无数据"
|
||||
msgid "Tunnel Mode"
|
||||
msgstr "TUN 模式"
|
||||
|
||||
msgid "PC_Catalog"
|
||||
msgstr "PC 设备"
|
||||
|
@@ -3,6 +3,12 @@ config system 'base'
|
||||
option url 'https://opapi.nn.com/speed/router/plug/check'
|
||||
option heart 'https://opapi.nn.com/speed/router/heartbeat'
|
||||
option base_url 'https://opapi.nn.com/speed'
|
||||
option enabled '0'
|
||||
option tun '0'
|
||||
option schedule_enabled '0'
|
||||
option pause_time '01:00'
|
||||
option username ''
|
||||
option password ''
|
||||
|
||||
config bind 'bind'
|
||||
|
||||
|
@@ -126,7 +126,6 @@ get_xiaomi_name() {
|
||||
echo "router is not xiaomi, use general openwrt"
|
||||
sbin_dir="/usr/sbin/leigod"
|
||||
init_dir="/etc/init.d"
|
||||
show_openwrt_suggestion
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -144,19 +143,24 @@ start_service_daemon() {
|
||||
procd_close_instance
|
||||
# start check update
|
||||
# update_plugin &
|
||||
# start led light
|
||||
# /etc/init.d/internetled start
|
||||
}
|
||||
|
||||
|
||||
# proc start service
|
||||
start_service() {
|
||||
# prepare env
|
||||
# prepare_env
|
||||
# run service as daemon
|
||||
|
||||
config_load "accelerator"
|
||||
|
||||
local enabled
|
||||
config_get_bool enabled base enabled 0
|
||||
|
||||
local tun
|
||||
config_get_bool tun base tun 0
|
||||
|
||||
[ "${enabled}" -gt 0 ] || return
|
||||
[ "${tun}" -eq 1 ] && args="--mode tun"
|
||||
|
||||
get_device_arch
|
||||
get_xiaomi_name
|
||||
start_service_daemon
|
||||
}
|
||||
|
||||
|
||||
|
@@ -18,7 +18,12 @@ uci set accelerator.base.heart='https://opapi.nn.com/speed/router/heartbeat'
|
||||
uci set accelerator.base.base_url='https://opapi.nn.com/speed'
|
||||
uci commit accelerator
|
||||
|
||||
echo "Fistboot Disable "
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@accelerator[-1]
|
||||
add ucitrack accelerator
|
||||
set ucitrack.@accelerator[-1].init=acc
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
/etc/init.d/acc stop
|
||||
/etc/init.d/acc disable
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
||||
|
BIN
lede/package/lean/luci-app-leigod-acc/root/www/leigodapp.png
Normal file
BIN
lede/package/lean/luci-app-leigod-acc/root/www/leigodapp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
BIN
lede/package/lean/luci-app-leigod-acc/root/www/leigodbind.png
Normal file
BIN
lede/package/lean/luci-app-leigod-acc/root/www/leigodbind.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
@@ -13,6 +13,8 @@
|
||||
|
||||
<br>中文 | [English](README_en.md)
|
||||
|
||||
* 仓库里luci-theme-argon 与 luci-app-homeproxy 适配23.05 不适配18.06,切记!
|
||||
|
||||
* 把openwrt-packages与small仓库重新归类,ssr、passwall、vssr以及依赖合并small
|
||||
|
||||
* 喜欢追新的可以去下载small-package,该仓库每天自动同步更新
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
20240708150024
|
||||
20240802150027
|
||||
|
@@ -1,21 +1,23 @@
|
||||
2001:250::/30
|
||||
2001:254::/31
|
||||
2001:256:100::/48
|
||||
2001:550:1601::/48
|
||||
2001:67c:aec::/48
|
||||
2001:67c:c28::/48
|
||||
2001:67c:ebc::/48
|
||||
2001:7fa:5::/48
|
||||
2001:c68::/32
|
||||
2001:cc0::/32
|
||||
2001:da8::/32
|
||||
2001:daa:1::/48
|
||||
2001:daa:2::/47
|
||||
2001:daa:4::/48
|
||||
2001:daa:4::/47
|
||||
2001:daa:6::/48
|
||||
2001:dc7::/32
|
||||
2001:dd8:1::/48
|
||||
2001:dd8:5::/48
|
||||
2001:dd9::/48
|
||||
2001:df0:2e00::/48
|
||||
2001:df0:a640::/48
|
||||
2001:df0:ac40::/48
|
||||
2001:df1:2b40::/48
|
||||
2001:df1:5fc0::/48
|
||||
@@ -39,7 +41,7 @@
|
||||
2400:6460::/40
|
||||
2400:6600::/32
|
||||
2400:6e60:1301::/48
|
||||
2400:73e0:201::/48
|
||||
2400:73e0::/32
|
||||
2400:75aa::/32
|
||||
2400:7bc0:20::/43
|
||||
2400:7fc0::/40
|
||||
@@ -82,7 +84,7 @@
|
||||
2400:9380:9060::/48
|
||||
2400:9380:9071::/48
|
||||
2400:9380:9080::/47
|
||||
2400:9380:90a0::/47
|
||||
2400:9380:90a1::/48
|
||||
2400:9380:90b0::/45
|
||||
2400:9380:9100::/47
|
||||
2400:9380:9121::/48
|
||||
@@ -97,9 +99,8 @@
|
||||
2400:9380:9272::/48
|
||||
2400:9380:9280::/47
|
||||
2400:9380:9282::/48
|
||||
2400:9380:92a0::/47
|
||||
2400:9380:92a1::/48
|
||||
2400:9380:92b0::/45
|
||||
2400:9520:434::/48
|
||||
2400:95e0::/48
|
||||
2400:9600:8800::/48
|
||||
2400:9620::/32
|
||||
@@ -110,6 +111,7 @@
|
||||
2400:b600::/32
|
||||
2400:b700::/48
|
||||
2400:be00::/48
|
||||
2400:cb80:e2e::/47
|
||||
2400:cb80:e30::/44
|
||||
2400:cb80:e40::/44
|
||||
2400:da00::/32
|
||||
@@ -126,6 +128,8 @@
|
||||
2400:fe00::/32
|
||||
2401:20::/40
|
||||
2401:800::/32
|
||||
2401:b60:300::/48
|
||||
2401:ba0::/32
|
||||
2401:e60:10::/44
|
||||
2401:1160::/32
|
||||
2401:11a0:10::/44
|
||||
@@ -135,7 +139,6 @@
|
||||
2401:11a0:d152::/48
|
||||
2401:1200::/48
|
||||
2401:1320::/32
|
||||
2401:1740:2000::/48
|
||||
2401:1d40::/32
|
||||
2401:2780::/32
|
||||
2401:2e00::/32
|
||||
@@ -190,6 +193,7 @@
|
||||
2401:b400:20::/47
|
||||
2401:b680::/32
|
||||
2401:be00::/32
|
||||
2401:ca00::/32
|
||||
2401:cb80::/32
|
||||
2401:cc00::/32
|
||||
2401:ce00::/32
|
||||
@@ -204,8 +208,8 @@
|
||||
2402:840:f000::/38
|
||||
2402:1440::/32
|
||||
2402:2000::/32
|
||||
2402:2b40:8000::/36
|
||||
2402:3180:8000::/33
|
||||
2402:33c0::/32
|
||||
2402:3c00::/32
|
||||
2402:3f80:1400::/40
|
||||
2402:4440::/32
|
||||
@@ -259,10 +263,18 @@
|
||||
2403:1ec0:1400::/48
|
||||
2403:1ec0:1610::/48
|
||||
2403:2040::/48
|
||||
2403:27c0:c03::/48
|
||||
2403:27c0:1000::/48
|
||||
2403:2280::/48
|
||||
2403:2b40::/32
|
||||
2403:3140::/32
|
||||
2403:3480::/46
|
||||
2403:3480:4::/48
|
||||
2403:3480:12::/47
|
||||
2403:3480:14::/46
|
||||
2403:3480:18::/47
|
||||
2403:3480:1b::/48
|
||||
2403:3480:1c::/46
|
||||
2403:3480:20::/48
|
||||
2403:3480:30::/47
|
||||
2403:4240::/32
|
||||
2403:4280::/47
|
||||
2403:4b40::/32
|
||||
@@ -270,9 +282,8 @@
|
||||
2403:4c80:128::/48
|
||||
2403:5c80::/48
|
||||
2403:6380:14::/47
|
||||
2403:6380:20::/44
|
||||
2403:6380:40::/48
|
||||
2403:6380:42::/47
|
||||
2403:6380:40::/47
|
||||
2403:6380:42::/48
|
||||
2403:6a00::/32
|
||||
2403:7580::/32
|
||||
2403:8080:101::/48
|
||||
@@ -283,6 +294,7 @@
|
||||
2403:a140:100::/40
|
||||
2403:a200::/32
|
||||
2403:ac00::/32
|
||||
2403:ad80:102a::/48
|
||||
2403:ad80:8008::/48
|
||||
2403:b400::/32
|
||||
2403:c980::/32
|
||||
@@ -299,6 +311,7 @@
|
||||
2404:bc0:4400::/43
|
||||
2404:bc0:4f00::/43
|
||||
2404:1c80::/32
|
||||
2404:2280:103::/48
|
||||
2404:2280:106::/47
|
||||
2404:2280:10b::/48
|
||||
2404:2280:10d::/48
|
||||
@@ -306,11 +319,12 @@
|
||||
2404:2280:112::/47
|
||||
2404:2280:115::/48
|
||||
2404:2280:11a::/47
|
||||
2404:2280:11c::/47
|
||||
2404:2280:11e::/48
|
||||
2404:2280:11c::/46
|
||||
2404:2280:123::/48
|
||||
2404:2280:125::/48
|
||||
2404:2280:126::/47
|
||||
2404:2280:12e::/48
|
||||
2404:2280:130::/48
|
||||
2404:2280:134::/48
|
||||
2404:2280:136::/47
|
||||
2404:2280:13b::/48
|
||||
@@ -325,7 +339,7 @@
|
||||
2404:2280:19c::/47
|
||||
2404:2280:19e::/48
|
||||
2404:2280:1a4::/47
|
||||
2404:2280:1a8::/48
|
||||
2404:2280:1a8::/47
|
||||
2404:2280:1b0::/48
|
||||
2404:2280:1b2::/48
|
||||
2404:2280:1b4::/46
|
||||
@@ -431,49 +445,6 @@
|
||||
2405:f580::/32
|
||||
2405:f940::/32
|
||||
2406:280::/32
|
||||
2406:840:1::/48
|
||||
2406:840:2::/48
|
||||
2406:840:7::/48
|
||||
2406:840:10::/45
|
||||
2406:840:20::/48
|
||||
2406:840:44::/47
|
||||
2406:840:78::/47
|
||||
2406:840:80::/47
|
||||
2406:840:90::/48
|
||||
2406:840:100::/48
|
||||
2406:840:110::/48
|
||||
2406:840:180::/48
|
||||
2406:840:1c0::/48
|
||||
2406:840:2e0::/48
|
||||
2406:840:301::/48
|
||||
2406:840:302::/48
|
||||
2406:840:3c1::/48
|
||||
2406:840:410::/48
|
||||
2406:840:420::/48
|
||||
2406:840:480::/48
|
||||
2406:840:540::/48
|
||||
2406:840:680::/48
|
||||
2406:840:801::/48
|
||||
2406:840:802::/47
|
||||
2406:840:840::/47
|
||||
2406:840:860::/48
|
||||
2406:840:880::/48
|
||||
2406:840:9b1::/48
|
||||
2406:840:a08::/48
|
||||
2406:840:a90::/48
|
||||
2406:840:c00::/47
|
||||
2406:840:c60::/48
|
||||
2406:840:1800::/48
|
||||
2406:840:2800::/48
|
||||
2406:840:3800::/48
|
||||
2406:840:4100::/47
|
||||
2406:840:43c0::/47
|
||||
2406:840:4800::/47
|
||||
2406:840:4880::/47
|
||||
2406:840:5100::/47
|
||||
2406:840:5800::/47
|
||||
2406:840:5860::/47
|
||||
2406:840:5880::/47
|
||||
2406:840:8100::/40
|
||||
2406:840:9000::/44
|
||||
2406:840:9100::/47
|
||||
@@ -487,33 +458,30 @@
|
||||
2406:840:981c::/46
|
||||
2406:840:9960::/47
|
||||
2406:840:9962::/48
|
||||
2406:840:9969::/48
|
||||
2406:840:996f::/48
|
||||
2406:840:9980::/48
|
||||
2406:840:9984::/48
|
||||
2406:840:9ef0::/44
|
||||
2406:840:c0a8::/48
|
||||
2406:840:e010::/47
|
||||
2406:840:e014::/46
|
||||
2406:840:e018::/45
|
||||
2406:840:e030::/47
|
||||
2406:840:e031::/48
|
||||
2406:840:e033::/48
|
||||
2406:840:e03f::/48
|
||||
2406:840:e080::/44
|
||||
2406:840:e0cf::/48
|
||||
2406:840:e0e0::/44
|
||||
2406:840:e0e0::/47
|
||||
2406:840:e0e2::/48
|
||||
2406:840:e0e4::/47
|
||||
2406:840:e10f::/48
|
||||
2406:840:e14f::/48
|
||||
2406:840:e180::/44
|
||||
2406:840:e20f::/48
|
||||
2406:840:e230::/47
|
||||
2406:840:e232::/48
|
||||
2406:840:e234::/48
|
||||
2406:840:e234::/47
|
||||
2406:840:e270::/44
|
||||
2406:840:e300::/47
|
||||
2406:840:e302::/48
|
||||
2406:840:e301::/48
|
||||
2406:840:e302::/47
|
||||
2406:840:e304::/48
|
||||
2406:840:e340::/44
|
||||
2406:840:e351::/48
|
||||
2406:840:e354::/48
|
||||
2406:840:e36f::/48
|
||||
2406:840:e500::/47
|
||||
2406:840:e57b::/48
|
||||
@@ -530,6 +498,7 @@
|
||||
2406:840:e84f::/48
|
||||
2406:840:e880::/44
|
||||
2406:840:eab0::/46
|
||||
2406:840:eab4::/48
|
||||
2406:840:eab6::/48
|
||||
2406:840:eb00::/46
|
||||
2406:840:eb04::/47
|
||||
@@ -538,7 +507,7 @@
|
||||
2406:840:eb0b::/48
|
||||
2406:840:eb0f::/48
|
||||
2406:840:eb80::/42
|
||||
2406:840:ed02::/48
|
||||
2406:840:ed02::/47
|
||||
2406:840:eed0::/44
|
||||
2406:840:eee0::/44
|
||||
2406:840:f0a1::/48
|
||||
@@ -548,27 +517,24 @@
|
||||
2406:840:f203::/48
|
||||
2406:840:f230::/44
|
||||
2406:840:f380::/44
|
||||
2406:840:f401::/48
|
||||
2406:840:f40f::/48
|
||||
2406:840:f440::/47
|
||||
2406:840:f44f::/48
|
||||
2406:840:f48f::/48
|
||||
2406:840:f660::/44
|
||||
2406:840:f990::/44
|
||||
2406:840:fa01::/48
|
||||
2406:840:fa02::/47
|
||||
2406:840:fa04::/48
|
||||
2406:840:fa40::/48
|
||||
2406:840:fc80::/45
|
||||
2406:840:fc88::/46
|
||||
2406:840:fc8c::/47
|
||||
2406:840:fc8e::/48
|
||||
2406:840:fcc0::/44
|
||||
2406:840:fcd0::/48
|
||||
2406:840:fd00::/47
|
||||
2406:840:fd03::/48
|
||||
2406:840:fd1f::/48
|
||||
2406:840:fd90::/44
|
||||
2406:840:fda0::/43
|
||||
2406:840:fd40::/42
|
||||
2406:840:fd80::/42
|
||||
2406:840:fdc0::/44
|
||||
2406:840:fdd1::/48
|
||||
2406:840:fde0::/48
|
||||
@@ -577,6 +543,8 @@
|
||||
2406:840:fe60::/48
|
||||
2406:840:fe72::/47
|
||||
2406:840:fe90::/46
|
||||
2406:840:fe97::/48
|
||||
2406:840:fe98::/46
|
||||
2406:840:fec0::/47
|
||||
2406:840:fec3::/48
|
||||
2406:840:fec4::/46
|
||||
@@ -594,8 +562,8 @@
|
||||
2406:840:fef8::/47
|
||||
2406:840:fefb::/48
|
||||
2406:840:fefc::/46
|
||||
2406:1080::/48
|
||||
2406:1e40:f012::/47
|
||||
2406:2000:a0::/48
|
||||
2406:2700::/32
|
||||
2406:3340::/32
|
||||
2406:3640:1::/48
|
||||
@@ -801,37 +769,38 @@
|
||||
2408:8406:b580::/42
|
||||
2408:8409::/40
|
||||
2408:8409:120::/43
|
||||
2408:8409:140::/42
|
||||
2408:8409:1a0::/43
|
||||
2408:8409:c00::/40
|
||||
2408:8409:d00::/42
|
||||
2408:8409:d00::/41
|
||||
2408:8409:1800::/40
|
||||
2408:8409:1900::/42
|
||||
2408:8409:1900::/41
|
||||
2408:8409:2400::/40
|
||||
2408:8409:2500::/42
|
||||
2408:8409:2500::/41
|
||||
2408:8409:3000::/40
|
||||
2408:8409:3100::/42
|
||||
2408:8409:3100::/41
|
||||
2408:8409:3c00::/40
|
||||
2408:8409:3d00::/42
|
||||
2408:8409:3d00::/41
|
||||
2408:8409:4800::/40
|
||||
2408:8409:4900::/42
|
||||
2408:8409:4900::/41
|
||||
2408:8409:5400::/40
|
||||
2408:8409:5500::/42
|
||||
2408:8409:5500::/41
|
||||
2408:8409:6000::/40
|
||||
2408:8409:6100::/42
|
||||
2408:8409:6100::/41
|
||||
2408:8409:6c00::/40
|
||||
2408:8409:6d00::/42
|
||||
2408:8409:6d00::/41
|
||||
2408:8409:7800::/40
|
||||
2408:8409:7900::/42
|
||||
2408:8409:7900::/41
|
||||
2408:8409:8400::/40
|
||||
2408:8409:8500::/42
|
||||
2408:8409:8500::/41
|
||||
2408:8409:9000::/40
|
||||
2408:8409:9100::/42
|
||||
2408:8409:9100::/41
|
||||
2408:8409:9c00::/40
|
||||
2408:8409:9d00::/42
|
||||
2408:8409:9d00::/41
|
||||
2408:8409:a800::/40
|
||||
2408:8409:a900::/42
|
||||
2408:8409:a900::/41
|
||||
2408:8409:b400::/40
|
||||
2408:8409:b500::/42
|
||||
2408:8409:b500::/41
|
||||
2408:840c::/40
|
||||
2408:840c:200::/40
|
||||
2408:840c:400::/40
|
||||
@@ -1072,7 +1041,6 @@
|
||||
2408:880c::/30
|
||||
2408:8810::/30
|
||||
2408:8814::/31
|
||||
2408:8816::/32
|
||||
2408:8818::/31
|
||||
2408:882c::/32
|
||||
2408:883a::/32
|
||||
@@ -1147,6 +1115,7 @@
|
||||
240a:4021:83a::/48
|
||||
240a:4021:883a::/48
|
||||
240a:4084:2000::/35
|
||||
240a:4088:a000::/35
|
||||
240a:408c:2000::/35
|
||||
240a:4090:50::/48
|
||||
240a:4090:120::/48
|
||||
@@ -1162,6 +1131,7 @@
|
||||
240a:4090:5200::/40
|
||||
240a:4090:7000::/39
|
||||
240a:4090:7200::/40
|
||||
240a:4090:a000::/35
|
||||
240a:4094:2000::/35
|
||||
240a:409c:2000::/35
|
||||
240a:40a4:2000::/35
|
||||
@@ -1177,6 +1147,7 @@
|
||||
240a:4172::/31
|
||||
240a:41b0::/34
|
||||
240a:41f2::/31
|
||||
240a:420a::/31
|
||||
240a:4242::/31
|
||||
240a:4280::/26
|
||||
240a:42c0::/27
|
||||
@@ -1195,23 +1166,6 @@
|
||||
240c:4000::/22
|
||||
240c:c000::/20
|
||||
240d:4000::/21
|
||||
240d:c000:1000::/36
|
||||
240d:c000:2000::/35
|
||||
240d:c000:6000::/36
|
||||
240d:c000:7000::/44
|
||||
240d:c000:f000::/44
|
||||
240d:c000:f020::/43
|
||||
240d:c010::/47
|
||||
240d:c010:14::/48
|
||||
240d:c010:16::/48
|
||||
240d:c010:20::/44
|
||||
240d:c010:30::/47
|
||||
240d:c010:58::/48
|
||||
240d:c010:5b::/48
|
||||
240d:c010:5c::/48
|
||||
240d:c010:68::/48
|
||||
240d:c010:6c::/48
|
||||
240d:c040::/44
|
||||
240e::/20
|
||||
2601:1d08:4000::/44
|
||||
2602:2a3::/48
|
||||
@@ -1222,7 +1176,7 @@
|
||||
2602:f9df:505::/48
|
||||
2602:f9df:515::/48
|
||||
2602:f9df:516::/48
|
||||
2602:f9f6:400::/47
|
||||
2602:f9f6:400::/48
|
||||
2602:fa4f:600::/40
|
||||
2602:fab0:11::/48
|
||||
2602:fbda:600::/48
|
||||
@@ -1274,7 +1228,6 @@
|
||||
2804:1e48::/32
|
||||
2a03:5840:f3::/48
|
||||
2a03:5840:11b::/48
|
||||
2a03:5840:290::/48
|
||||
2a04:3e00:1002::/48
|
||||
2a04:f580:8010::/47
|
||||
2a04:f580:8090::/48
|
||||
@@ -1308,9 +1261,11 @@
|
||||
2a05:1087::/32
|
||||
2a05:4140:66::/48
|
||||
2a05:dfc1:1600::/48
|
||||
2a05:dfc1:1604::/48
|
||||
2a05:dfc1:1607::/48
|
||||
2a05:dfc1:1608::/48
|
||||
2a05:dfc1:1610::/46
|
||||
2a05:dfc1:1620::/48
|
||||
2a05:dfc1:1631::/48
|
||||
2a05:dfc1:16fd::/48
|
||||
2a05:dfc1:16fe::/48
|
||||
2a05:dfc1:7106::/47
|
||||
2a05:dfc1:7108::/47
|
||||
2a05:dfc1:7110::/48
|
||||
@@ -1325,15 +1280,21 @@
|
||||
2a05:dfc1:8c22::/48
|
||||
2a05:dfc1:8c24::/48
|
||||
2a05:dfc1:8c42::/48
|
||||
2a05:dfc1:8c90::/45
|
||||
2a05:dfc1:8c90::/46
|
||||
2a05:dfc1:8c94::/47
|
||||
2a05:dfc1:8d02::/48
|
||||
2a06:3600::/29
|
||||
2a06:9f81:4610::/44
|
||||
2a06:1281:8100::/40
|
||||
2a06:1281:8200::/39
|
||||
2a06:1281:8400::/40
|
||||
2a06:1281:8f00::/40
|
||||
2a06:3600::/30
|
||||
2a06:9f81:4600::/43
|
||||
2a06:9f81:4620::/44
|
||||
2a06:9f81:4640::/43
|
||||
2a06:9f81:5100::/47
|
||||
2a06:9f81:5102::/48
|
||||
2a06:9f81:4660::/44
|
||||
2a06:9f81:5100::/40
|
||||
2a06:9f81:5400::/40
|
||||
2a06:9f81:5902::/48
|
||||
2a06:a005:260::/43
|
||||
2a06:a005:280::/43
|
||||
2a06:a005:2a0::/44
|
||||
@@ -1349,20 +1310,18 @@
|
||||
2a06:a005:13c0::/43
|
||||
2a06:a005:13e0::/47
|
||||
2a06:a005:13e2::/48
|
||||
2a06:a005:13ea::/47
|
||||
2a06:a005:13ed::/48
|
||||
2a06:a005:13ef::/48
|
||||
2a06:a005:13eb::/48
|
||||
2a06:a005:1520::/44
|
||||
2a06:a005:1800::/48
|
||||
2a06:a005:1b60::/47
|
||||
2a06:a005:1c40::/44
|
||||
2a06:a005:1ee1::/48
|
||||
2a06:a005:1ee9::/48
|
||||
2a06:a005:1ee8::/47
|
||||
2a06:a005:1eee::/48
|
||||
2a06:a005:2040::/44
|
||||
2a06:a005:2100::/44
|
||||
2a06:a005:28f3::/48
|
||||
2a06:a005:28f4::/48
|
||||
2a06:a005:2910::/44
|
||||
2a06:a005:2922::/48
|
||||
2a06:a005:2926::/48
|
||||
2a06:a005:2940::/43
|
||||
@@ -1370,24 +1329,22 @@
|
||||
2a06:a005:29d1::/48
|
||||
2a06:de00:de04::/48
|
||||
2a06:de00:de0e::/48
|
||||
2a06:de01:80f::/48
|
||||
2a06:de01:821::/48
|
||||
2a06:de01:854::/48
|
||||
2a06:de01:85f::/48
|
||||
2a06:de01:8a4::/48
|
||||
2a06:de01:8b8::/48
|
||||
2a06:de01:8c4::/48
|
||||
2a06:de01:8cb::/48
|
||||
2a06:de01:917::/48
|
||||
2a06:de01:92f::/48
|
||||
2a06:de01:944::/47
|
||||
2a06:de01:98c::/48
|
||||
2a06:de01:9a8::/48
|
||||
2a06:de01:acd::/48
|
||||
2a06:de01:af9::/48
|
||||
2a06:de01:b1a::/48
|
||||
2a06:de01:b32::/48
|
||||
2a06:e881:2509::/48
|
||||
2a06:de01:840::/48
|
||||
2a06:de01:85d::/48
|
||||
2a06:de01:867::/48
|
||||
2a06:de01:883::/48
|
||||
2a06:de01:891::/48
|
||||
2a06:de01:8f9::/48
|
||||
2a06:de01:93e::/47
|
||||
2a06:de01:942::/48
|
||||
2a06:de01:970::/48
|
||||
2a06:de01:99d::/48
|
||||
2a06:de01:9ba::/48
|
||||
2a06:de01:ada::/48
|
||||
2a06:de01:af6::/48
|
||||
2a06:de01:b04::/48
|
||||
2a06:de01:b07::/48
|
||||
2a06:e881:5501::/48
|
||||
2a06:e881:5502::/48
|
||||
2a06:e881:5506::/48
|
||||
@@ -1400,6 +1357,8 @@
|
||||
2a09:b280:ff84::/47
|
||||
2a0a:2840:20::/43
|
||||
2a0a:2845:aab8::/46
|
||||
2a0a:2940::/29
|
||||
2a0a:6040:300::/40
|
||||
2a0a:6040:c00::/40
|
||||
2a0a:6040:e01::/48
|
||||
2a0a:6040:e02::/48
|
||||
@@ -1415,27 +1374,24 @@
|
||||
2a0a:6040:2255::/48
|
||||
2a0a:6040:2277::/48
|
||||
2a0a:6040:2d00::/44
|
||||
2a0a:6040:3410::/48
|
||||
2a0a:6040:3420::/48
|
||||
2a0a:6040:3430::/48
|
||||
2a0a:6040:34ff::/48
|
||||
2a0a:6040:5555::/48
|
||||
2a0a:6040:6607::/48
|
||||
2a0a:6040:6c40::/44
|
||||
2a0a:6040:7e00::/48
|
||||
2a0a:6040:a450::/47
|
||||
2a0a:6040:a740::/48
|
||||
2a0a:6040:a900::/47
|
||||
2a0a:6040:a901::/48
|
||||
2a0a:6040:b770::/44
|
||||
2a0a:6040:c601::/48
|
||||
2a0a:6040:c700::/42
|
||||
2a0a:6040:c740::/47
|
||||
2a0a:6040:c742::/48
|
||||
2a0a:6040:c750::/47
|
||||
2a0a:6040:c760::/47
|
||||
2a0a:6040:c770::/44
|
||||
2a0a:6040:c7a0::/48
|
||||
2a0a:6040:ce11::/48
|
||||
2a0a:6040:d310::/48
|
||||
2a0a:6040:d400::/47
|
||||
2a0a:6040:d600::/44
|
||||
2a0a:6040:d610::/48
|
||||
@@ -1471,7 +1427,6 @@
|
||||
2a0b:4340:404::/47
|
||||
2a0b:4340:406::/48
|
||||
2a0b:4340:434::/48
|
||||
2a0b:4340:560::/44
|
||||
2a0b:4340:1304::/48
|
||||
2a0b:4340:1340::/48
|
||||
2a0c:9a40:8cf0::/48
|
||||
@@ -1479,7 +1434,6 @@
|
||||
2a0c:b641:210::/47
|
||||
2a0c:b641:510::/48
|
||||
2a0c:b641:570::/47
|
||||
2a0c:b641:730::/44
|
||||
2a0c:b641:a60::/44
|
||||
2a0c:b641:b21::/48
|
||||
2a0c:b642:4101::/48
|
||||
@@ -1490,8 +1444,7 @@
|
||||
2a0d:2406:512::/48
|
||||
2a0d:2580:ff00::/45
|
||||
2a0d:2580:ff08::/46
|
||||
2a0d:2581:fffc::/48
|
||||
2a0d:2581:fffe::/47
|
||||
2a0d:2581:ffff::/48
|
||||
2a0d:2687::/32
|
||||
2a0d:2904::/44
|
||||
2a0d:c7c7::/32
|
||||
@@ -1520,6 +1473,7 @@
|
||||
2a0e:aa06:500::/44
|
||||
2a0e:aa06:520::/48
|
||||
2a0e:aa06:525::/48
|
||||
2a0e:aa06:541::/48
|
||||
2a0e:aa07:e00e::/48
|
||||
2a0e:aa07:e01b::/48
|
||||
2a0e:aa07:e024::/47
|
||||
@@ -1540,7 +1494,6 @@
|
||||
2a0e:aa07:e148::/48
|
||||
2a0e:aa07:e16a::/48
|
||||
2a0e:aa07:e1a0::/46
|
||||
2a0e:aa07:e1b0::/44
|
||||
2a0e:aa07:e1e1::/48
|
||||
2a0e:aa07:e200::/44
|
||||
2a0e:aa07:f000::/48
|
||||
@@ -1551,7 +1504,6 @@
|
||||
2a0e:aa07:f0d0::/47
|
||||
2a0e:aa07:f0d2::/48
|
||||
2a0e:aa07:f0d4::/47
|
||||
2a0e:aa07:f0d6::/48
|
||||
2a0e:aa07:f0d8::/45
|
||||
2a0e:aa07:f0e0::/44
|
||||
2a0e:b107:30::/48
|
||||
@@ -1559,7 +1511,6 @@
|
||||
2a0e:b107:a0::/44
|
||||
2a0e:b107:12b::/48
|
||||
2a0e:b107:272::/48
|
||||
2a0e:b107:710::/48
|
||||
2a0e:b107:740::/44
|
||||
2a0e:b107:790::/45
|
||||
2a0e:b107:798::/46
|
||||
@@ -1569,27 +1520,29 @@
|
||||
2a0e:b107:14a0::/44
|
||||
2a0e:b107:16b0::/44
|
||||
2a0e:b107:16c0::/44
|
||||
2a0e:b107:178c::/48
|
||||
2a0e:b107:1a40::/46
|
||||
2a0e:b107:1b60::/48
|
||||
2a0e:b107:1b6e::/47
|
||||
2a0e:b107:1b6e::/48
|
||||
2a0e:b107:1d25::/48
|
||||
2a0e:b107:1e85::/48
|
||||
2a0e:b107:2440::/44
|
||||
2a0f:1440::/29
|
||||
2a0f:2100::/29
|
||||
2a0f:5707:fe01::/48
|
||||
2a0f:5707:fff5::/48
|
||||
2a0f:7802:e000::/40
|
||||
2a0f:7802:e104::/47
|
||||
2a0f:7802:e110::/47
|
||||
2a0f:7802:e120::/44
|
||||
2a0f:7802:e138::/45
|
||||
2a0f:7802:e140::/46
|
||||
2a0f:7803:dd00::/41
|
||||
2a0f:7803:dd80::/42
|
||||
2a0f:7803:ddc0::/42
|
||||
2a0f:7803:f8b0::/44
|
||||
2a0f:7803:f970::/44
|
||||
2a0f:7803:fa21::/48
|
||||
2a0f:7803:fa22::/47
|
||||
2a0f:7803:fc00::/43
|
||||
2a0f:7803:fa24::/47
|
||||
2a0f:7803:fc00::/44
|
||||
2a0f:7803:fc80::/44
|
||||
2a0f:7803:fcaa::/48
|
||||
2a0f:7803:fe21::/48
|
||||
@@ -1599,18 +1552,20 @@
|
||||
2a0f:7803:fe82::/48
|
||||
2a0f:7803:fe84::/48
|
||||
2a0f:7803:ff10::/48
|
||||
2a0f:7803:ffd0::/47
|
||||
2a0f:85c1:100::/48
|
||||
2a0f:85c1:3b5::/48
|
||||
2a0f:85c1:816::/48
|
||||
2a0f:9400:6110::/48
|
||||
2a0f:9400:7700::/48
|
||||
2a0f:9b00::/29
|
||||
2a0f:c400::/29
|
||||
2a0f:dec0::/29
|
||||
2a0f:e401:133::/48
|
||||
2a10:2f00:13a::/48
|
||||
2a0f:e540::/29
|
||||
2a10:2f00:147::/48
|
||||
2a10:2f00:15a::/48
|
||||
2a10:2f00:18e::/48
|
||||
2a10:2f01:100::/48
|
||||
2a10:3340::/29
|
||||
2a10:3440::/29
|
||||
2a10:cc40:180::/47
|
||||
2a10:cc40:188::/48
|
||||
@@ -1619,7 +1574,7 @@
|
||||
2a10:ccc0:cc1::/48
|
||||
2a10:ccc0:cc2::/48
|
||||
2a10:ccc0:ccc::/48
|
||||
2a10:ccc0:c0c3::/48
|
||||
2a10:ccc0:c0c2::/47
|
||||
2a10:ccc0:ccc6::/48
|
||||
2a10:ccc0:cccc::/46
|
||||
2a11:f2c0:ffc4::/48
|
||||
@@ -1631,6 +1586,8 @@
|
||||
2a12:3fc2:e72e::/48
|
||||
2a12:3fc7::/48
|
||||
2a12:3fc7:8000::/48
|
||||
2a12:d5c0::/29
|
||||
2a12:d6c0::/29
|
||||
2a12:dd47:5c00::/40
|
||||
2a12:f8c0:1000::/40
|
||||
2a12:f8c3::/36
|
||||
@@ -1640,6 +1597,7 @@
|
||||
2a13:1800:300::/44
|
||||
2a13:1801:180::/43
|
||||
2a13:1802::/43
|
||||
2a13:4900::/29
|
||||
2a13:a5c3:f000::/40
|
||||
2a13:a5c4:1000::/38
|
||||
2a13:a5c4:1400::/39
|
||||
@@ -1655,37 +1613,23 @@
|
||||
2a13:a5c7:1804::/47
|
||||
2a13:a5c7:1888::/48
|
||||
2a13:a5c7:2102::/47
|
||||
2a13:a5c7:2104::/48
|
||||
2a13:a5c7:2106::/48
|
||||
2a13:a5c7:2109::/48
|
||||
2a13:a5c7:2200::/40
|
||||
2a13:aac4:f000::/44
|
||||
2a13:b487:11da::/48
|
||||
2a13:b487:1200::/44
|
||||
2a13:b487:1200::/43
|
||||
2a13:b487:1b86::/47
|
||||
2a13:b487:1bb2::/48
|
||||
2a13:b487:1bba::/47
|
||||
2a13:b487:1f02::/47
|
||||
2a13:b487:1f04::/46
|
||||
2a13:df80:3b00::/44
|
||||
2a13:df80:3b11::/48
|
||||
2a13:df85:a201::/48
|
||||
2a13:df85:a202::/47
|
||||
2a13:df85:a204::/48
|
||||
2a13:df85:a2ff::/48
|
||||
2a13:df85:be10::/48
|
||||
2a13:df85:be80::/48
|
||||
2a13:df85:be88::/48
|
||||
2a13:df85:beaa::/48
|
||||
2a13:df85:bed0::/48
|
||||
2a13:df85:bedc::/48
|
||||
2a13:df85:befe::/48
|
||||
2a14:7c0:4a01::/48
|
||||
2a14:7c0:4d00::/40
|
||||
2a14:4c41::/32
|
||||
2a14:7581:b40::/48
|
||||
2a14:7581:f5e::/47
|
||||
2a14:7581:ffb::/48
|
||||
2a14:7581:ffc::/48
|
||||
2a14:7583::/32
|
||||
2a14:7586::/31
|
||||
2a14:7586::/32
|
||||
2c0f:f7a8:8011::/48
|
||||
2c0f:f7a8:8050::/48
|
||||
2c0f:f7a8:805f::/48
|
||||
|
@@ -1 +1 @@
|
||||
20240708150024
|
||||
20240802150027
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
202407102210
|
||||
202408012210
|
||||
|
@@ -292,6 +292,7 @@ anonymouse.org
|
||||
anpopo.com
|
||||
answering-islam.org
|
||||
anthonycalzadilla.com
|
||||
anthropic.com
|
||||
anti1984.com
|
||||
antichristendom.com
|
||||
antiwave.net
|
||||
@@ -427,6 +428,7 @@ axios.com
|
||||
axureformac.com
|
||||
azerbaycan.tv
|
||||
azerimix.com
|
||||
azirevpn.com
|
||||
azubu.tv
|
||||
azurewebsites.net
|
||||
b-ok.cc
|
||||
@@ -711,6 +713,7 @@ bloomfortune.com
|
||||
blubrry.com
|
||||
blueangellive.com
|
||||
bmfinn.com
|
||||
bnbstatic.com
|
||||
bnews.co
|
||||
bnext.com.tw
|
||||
bnn.co
|
||||
@@ -1075,6 +1078,7 @@ ck101.com
|
||||
cl.d0z.net
|
||||
clarionproject.org
|
||||
classicalguitarblog.net
|
||||
claude.ai
|
||||
clb.org.hk
|
||||
cldr.unicode.org
|
||||
cleansite.biz
|
||||
@@ -1095,6 +1099,7 @@ club1069.com
|
||||
clubhouseapi.com
|
||||
clyp.it
|
||||
cmcn.org
|
||||
cmegroup.com
|
||||
cmi.org.tw
|
||||
cmp.hku.hk
|
||||
cms.gov
|
||||
@@ -2793,6 +2798,7 @@ im88.tw
|
||||
imageab.com
|
||||
imagefap.com
|
||||
imageflea.com
|
||||
imageglass.org
|
||||
images-gaytube.com
|
||||
images.comico.tw
|
||||
imageshack.us
|
||||
@@ -4028,6 +4034,7 @@ percy.in
|
||||
perfect-privacy.com
|
||||
perfectgirls.net
|
||||
periscope.tv
|
||||
perplexity.ai
|
||||
persecutionblog.com
|
||||
persiankitty.com
|
||||
phapluan.org
|
||||
|
@@ -1 +1 @@
|
||||
202407102210
|
||||
202408012210
|
||||
|
201
openwrt-packages/luci-theme-argon/LICENSE
Normal file
201
openwrt-packages/luci-theme-argon/LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@@ -8,20 +8,11 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=Argon Theme
|
||||
LUCI_DEPENDS:=+curl +jsonfilter
|
||||
PKG_VERSION:=1.8.3
|
||||
PKG_RELEASE:=20230710
|
||||
PKG_VERSION:=2.3.1
|
||||
PKG_RELEASE:=20230420
|
||||
|
||||
CONFIG_LUCI_CSSTIDY:=
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
define Package/luci-theme-argon/postinst
|
||||
#!/bin/sh
|
||||
sed -i ":a;$!N;s/tmpl.render.*sysauth_template.*return/local scope = { duser = default_user, fuser = user }\nlocal ok, res = luci.util.copcall\(luci.template.render_string, [[<% include\(\"themes\/\" .. theme .. \"\/sysauth\"\) %>]], scope\)\nif ok then\nreturn res\nend\nreturn luci.template.render\(\"sysauth\", scope\)/;ba" /usr/lib/lua/luci/dispatcher.lua
|
||||
sed -i ":a;$!N;s/t.render.*sysauth_template.*return/local scope = { duser = h, fuser = a }\nlocal ok, res = luci.util.copcall\(luci.template.render_string, [[<% include\(\"themes\/\" .. theme .. \"\/sysauth\"\) %>]], scope\)\nif ok then\nreturn res\nend\nreturn luci.template.render\(\"sysauth\", scope\)/;ba" /usr/lib/lua/luci/dispatcher.lua
|
||||
[ -f /usr/lib/lua/luci/view/themes/argon/out_header_login.htm ] && mv -f /usr/lib/lua/luci/view/themes/argon/out_header_login.htm /usr/lib/lua/luci/view/header_login.htm
|
||||
rm -Rf /var/luci-modulecache
|
||||
rm -Rf /var/luci-indexcache
|
||||
exit 0
|
||||
endef
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user