new: add link parser and allow custom configs to be imported

This commit is contained in:
Hiddify
2024-01-27 03:11:52 +01:00
parent 0e64e26688
commit 569088aa1a
2 changed files with 50 additions and 26 deletions

View File

@@ -361,7 +361,7 @@ class ProfileRepositoryImpl
);
}
final _subInfoHeaders = [
static final _subInfoHeaders = [
'profile-title',
'content-disposition',
'subscription-userinfo',
@@ -418,8 +418,20 @@ class ProfileRepositoryImpl
"only [$headersFound] headers found, checking file content for possible information",
);
var content = await File(path).readAsString();
content = safeDecodeBase64(content);
final lines = content.split("\n");
final contentHeaders = parseHeadersFromContent(content);
for (final entry in contentHeaders.entries) {
if (!headers.keys.contains(entry.key) && entry.value.isNotEmpty) {
headers[entry.key] = entry.value;
}
}
return headers;
}
static Map<String, List<String>> parseHeadersFromContent(String content) {
final headers = <String, List<String>>{};
final content_ = safeDecodeBase64(content);
final lines = content_.split("\n");
final linesToProcess = lines.length < 10 ? lines.length : 10;
for (int i = 0; i < linesToProcess; i++) {
final line = lines[i];

View File

@@ -1,5 +1,8 @@
import 'dart:convert';
import 'package:dartx/dartx.dart';
import 'package:hiddify/features/profile/data/profile_parser.dart';
import 'package:hiddify/features/profile/data/profile_repository.dart';
import 'package:hiddify/singbox/model/singbox_proxy_type.dart';
import 'package:hiddify/utils/validators.dart';
@@ -19,13 +22,11 @@ abstract class LinkParser {
);
// return 'hiddify://import/$modifiedUri';
return '$modifiedUri';
}
// protocols schemas
static const protocols = {'clash', 'clashmeta', 'sing-box', 'hiddify'};
static ProfileLink? parse(String link) {
return simple(link) ?? deep(link);
}
@@ -40,13 +41,16 @@ abstract class LinkParser {
}
static ({String content, String name})? protocol(String content) {
final lines = safeDecodeBase64(content).split('\n');
final normalContent = safeDecodeBase64(content);
final lines = normalContent.split('\n');
String? name;
for (final line in lines) {
final uri = Uri.tryParse(line);
if (uri == null) continue;
final fragment =
uri.hasFragment ? Uri.decodeComponent(uri.fragment) : null;
final name = switch (uri.scheme) {
if (name != null) {
name = switch (uri.scheme) {
'ss' => fragment ?? ProxyType.shadowsocks.label,
'ssconf' => fragment ?? ProxyType.shadowsocks.label,
'vmess' => ProxyType.vmess.label,
@@ -58,13 +62,18 @@ abstract class LinkParser {
'ssh' => fragment ?? ProxyType.ssh.label,
'wg' => fragment ?? ProxyType.wireguard.label,
'warp' => fragment ?? ProxyType.warp.label,
_ => ProxyType.unknown.label,
_ => null,
};
if (name != null) {
return (content: content, name: name);
}
}
return null;
final headers = ProfileRepositoryImpl.parseHeadersFromContent(content);
final subinfo = ProfileParser.parse("", headers);
if (subinfo.name.isNotNullOrEmpty) {
name = subinfo.name;
}
return (content: normalContent, name: name ?? ProxyType.unknown.label);
}
static ProfileLink? deep(String link) {
@@ -82,7 +91,10 @@ abstract class LinkParser {
return (url: queryParams['url']!, name: queryParams['name'] ?? '');
case 'hiddify':
if (uri.authority == "import") {
return (url: uri.path.substring(1)+(uri.hasQuery?"?${uri.query}":""), name: uri.fragment);
return (
url: uri.path.substring(1) + (uri.hasQuery ? "?${uri.query}" : ""),
name: uri.fragment
);
}
//for backward compatibility
if ((uri.authority != 'install-config' &&