new: add postfix to name if it is not unique

This commit is contained in:
Hiddify
2024-01-30 19:14:05 +01:00
parent 1b372b5180
commit e13b4b269a
4 changed files with 40 additions and 22 deletions

View File

@@ -9,6 +9,7 @@ part 'profile_data_source.g.dart';
abstract interface class ProfileDataSource { abstract interface class ProfileDataSource {
Future<ProfileEntry?> getById(String id); Future<ProfileEntry?> getById(String id);
Future<ProfileEntry?> getByUrl(String url); Future<ProfileEntry?> getByUrl(String url);
Future<ProfileEntry?> getByName(String name);
Stream<ProfileEntry?> watchActiveProfile(); Stream<ProfileEntry?> watchActiveProfile();
Stream<int> watchProfilesCount(); Stream<int> watchProfilesCount();
Stream<List<ProfileEntry>> watchAll({ Stream<List<ProfileEntry>> watchAll({
@@ -44,6 +45,13 @@ class ProfileDao extends DatabaseAccessor<AppDatabase>
..limit(1)) ..limit(1))
.getSingleOrNull(); .getSingleOrNull();
} }
@override
Future<ProfileEntry?> getByName(String name) async {
return (select(profileEntries)
..where((tbl) => tbl.name.equals(name))
..limit(1))
.getSingleOrNull();
}
@override @override
Stream<ProfileEntry?> watchActiveProfile() { Stream<ProfileEntry?> watchActiveProfile() {

View File

@@ -22,6 +22,7 @@ import 'package:uuid/uuid.dart';
abstract interface class ProfileRepository { abstract interface class ProfileRepository {
TaskEither<ProfileFailure, Unit> init(); TaskEither<ProfileFailure, Unit> init();
TaskEither<ProfileFailure, ProfileEntity?> getById(String id); TaskEither<ProfileFailure, ProfileEntity?> getById(String id);
Future<ProfileEntity?> getByName(String name);
Stream<Either<ProfileFailure, ProfileEntity?>> watchActiveProfile(); Stream<Either<ProfileFailure, ProfileEntity?>> watchActiveProfile();
Stream<Either<ProfileFailure, bool>> watchHasAnyProfile(); Stream<Either<ProfileFailure, bool>> watchHasAnyProfile();
@@ -97,6 +98,11 @@ class ProfileRepositoryImpl
); );
} }
@override
Future<ProfileEntity?> getByName(String name) async {
return (await profileDataSource.getByName(name))?.toEntity();
}
@override @override
Stream<Either<ProfileFailure, ProfileEntity?>> watchActiveProfile() { Stream<Either<ProfileFailure, ProfileEntity?>> watchActiveProfile() {
return profileDataSource return profileDataSource
@@ -361,7 +367,7 @@ class ProfileRepositoryImpl
); );
} }
static final _subInfoHeaders = [ static final _subInfoHeaders = [
'profile-title', 'profile-title',
'content-disposition', 'content-disposition',
'subscription-userinfo', 'subscription-userinfo',
@@ -422,9 +428,9 @@ class ProfileRepositoryImpl
for (final entry in contentHeaders.entries) { for (final entry in contentHeaders.entries) {
if (!headers.keys.contains(entry.key) && entry.value.isNotEmpty) { if (!headers.keys.contains(entry.key) && entry.value.isNotEmpty) {
headers[entry.key] = entry.value; headers[entry.key] = entry.value;
} }
} }
return headers; return headers;
} }

View File

@@ -68,9 +68,14 @@ class AddProfile extends _$AddProfile with AppLogger {
); );
} else if (LinkParser.protocol(rawInput) case (final parsed)?) { } else if (LinkParser.protocol(rawInput) case (final parsed)?) {
loggy.debug("adding profile, content"); loggy.debug("adding profile, content");
var name = parsed.name;
while (await _profilesRepo.getByName(name) != null) {
name+= '${randomInt(0, 9).run()}';
}
task = _profilesRepo.addByContent( task = _profilesRepo.addByContent(
parsed.content, parsed.content,
name: parsed.name, name: name,
markAsActive: markAsActive, markAsActive: markAsActive,
); );
} else { } else {

View File

@@ -1,6 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:dartx/dartx.dart'; import 'package:dartx/dartx.dart';
import 'package:fpdart/fpdart.dart';
import 'package:hiddify/features/profile/data/profile_parser.dart'; import 'package:hiddify/features/profile/data/profile_parser.dart';
import 'package:hiddify/features/profile/data/profile_repository.dart'; import 'package:hiddify/features/profile/data/profile_repository.dart';
import 'package:hiddify/singbox/model/singbox_proxy_type.dart'; import 'package:hiddify/singbox/model/singbox_proxy_type.dart';
@@ -49,30 +50,28 @@ abstract class LinkParser {
if (uri == null) continue; if (uri == null) continue;
final fragment = final fragment =
uri.hasFragment ? Uri.decodeComponent(uri.fragment) : null; uri.hasFragment ? Uri.decodeComponent(uri.fragment) : null;
if (name != null) { name ??= switch (uri.scheme) {
name = switch (uri.scheme) { 'ss' => fragment ?? ProxyType.shadowsocks.label,
'ss' => fragment ?? ProxyType.shadowsocks.label, 'ssconf' => fragment ?? ProxyType.shadowsocks.label,
'ssconf' => fragment ?? ProxyType.shadowsocks.label, 'vmess' => ProxyType.vmess.label,
'vmess' => ProxyType.vmess.label, 'vless' => fragment ?? ProxyType.vless.label,
'vless' => fragment ?? ProxyType.vless.label, 'trojan' => fragment ?? ProxyType.trojan.label,
'trojan' => fragment ?? ProxyType.trojan.label, 'tuic' => fragment ?? ProxyType.tuic.label,
'tuic' => fragment ?? ProxyType.tuic.label, 'hy2' || 'hysteria2' => fragment ?? ProxyType.hysteria2.label,
'hy2' || 'hysteria2' => fragment ?? ProxyType.hysteria2.label, 'hy' || 'hysteria' => fragment ?? ProxyType.hysteria.label,
'hy' || 'hysteria' => fragment ?? ProxyType.hysteria.label, 'ssh' => fragment ?? ProxyType.ssh.label,
'ssh' => fragment ?? ProxyType.ssh.label, 'wg' => fragment ?? ProxyType.wireguard.label,
'wg' => fragment ?? ProxyType.wireguard.label, 'warp' => fragment ?? ProxyType.warp.label,
'warp' => fragment ?? ProxyType.warp.label, _ => null,
_ => null, };
};
}
} }
final headers = ProfileRepositoryImpl.parseHeadersFromContent(content); final headers = ProfileRepositoryImpl.parseHeadersFromContent(content);
final subinfo = ProfileParser.parse("", headers); final subinfo = ProfileParser.parse("", headers);
if (subinfo.name.isNotNullOrEmpty) { if (subinfo.name.isNotNullOrEmpty && subinfo.name != "Remote Profile") {
name = subinfo.name; name = subinfo.name;
} }
return (content: normalContent, name: name ?? ProxyType.unknown.label); return (content: normalContent, name: name ?? ProxyType.unknown.label);
} }