Files
MWClash/lib/models/profile.dart
chen08209 17cd0cf1ed Update file_picker
Add resources page

Optimize more detail
2024-06-05 13:42:33 +08:00

192 lines
5.0 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:fl_clash/clash/core.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/common/common.dart';
import 'package:json_annotation/json_annotation.dart';
part 'generated/profile.g.dart';
typedef SelectedMap = Map<String, String>;
@JsonSerializable()
class UserInfo {
int upload;
int download;
int total;
int? expire;
UserInfo({
int? upload,
int? download,
int? total,
this.expire,
}) : upload = upload ?? 0,
download = download ?? 0,
total = total ?? 0;
Map<String, dynamic> toJson() {
return _$UserInfoToJson(this);
}
factory UserInfo.fromJson(Map<String, dynamic> json) {
return _$UserInfoFromJson(json);
}
factory UserInfo.formHString(String? info) {
if (info == null) return UserInfo();
var list = info.split(";");
Map<String, int?> map = {};
for (var i in list) {
var keyValue = i.trim().split("=");
map[keyValue[0]] = int.tryParse(keyValue[1]);
}
return UserInfo(
upload: map["upload"],
download: map["download"],
total: map["total"],
expire: map["expire"],
);
}
@override
String toString() {
return 'UserInfo{upload: $upload, download: $download, total: $total, expire: $expire}';
}
}
@JsonSerializable()
class Profile {
String id;
String? label;
String? proxyName;
String? url;
DateTime? lastUpdateDate;
Duration autoUpdateDuration;
UserInfo? userInfo;
bool autoUpdate;
SelectedMap selectedMap;
Profile({
String? id,
this.label,
this.url,
this.userInfo,
this.proxyName,
this.lastUpdateDate,
SelectedMap? selectedMap,
Duration? autoUpdateDuration,
this.autoUpdate = true,
}) : id = id ?? DateTime.now().millisecondsSinceEpoch.toString(),
autoUpdateDuration = autoUpdateDuration ?? defaultUpdateDuration,
selectedMap = selectedMap ?? {};
ProfileType get type => url == null ? ProfileType.file : ProfileType.url;
Future<void> checkAndUpdate() async {
final isExists = await check();
if (!isExists) {
if (url != null) {
return await update();
}
}
}
Future<void> update() async {
if (url == null) {
throw appLocalizations.unableToUpdateCurrentProfileDesc;
}
final response = await request.getFileResponseForUrl(url!);
final disposition = response.headers.value("content-disposition");
label ??= other.getFileNameForDisposition(disposition) ?? id;
final userinfo = response.headers.value('subscription-userinfo');
userInfo = UserInfo.formHString(userinfo);
await saveFile(response.data);
lastUpdateDate = DateTime.now();
}
Future<bool> check() async {
final profilePath = await appPath.getProfilePath(id);
return await File(profilePath!).exists();
}
Future<void> saveFile(Uint8List bytes) async {
final message = await clashCore.validateConfig(utf8.decode(bytes));
if (message.isNotEmpty) {
throw message;
}
final path = await appPath.getProfilePath(id);
final file = File(path!);
final isExists = await file.exists();
if (!isExists) {
await file.create(recursive: true);
}
await file.writeAsBytes(bytes);
lastUpdateDate = DateTime.now();
}
Map<String, dynamic> toJson() {
return _$ProfileToJson(this);
}
factory Profile.fromJson(Map<String, dynamic> json) {
return _$ProfileFromJson(json);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Profile &&
runtimeType == other.runtimeType &&
id == other.id &&
label == other.label &&
proxyName == other.proxyName &&
url == other.url &&
lastUpdateDate == other.lastUpdateDate &&
autoUpdateDuration == other.autoUpdateDuration &&
userInfo == other.userInfo &&
autoUpdate == other.autoUpdate;
@override
int get hashCode =>
id.hashCode ^
label.hashCode ^
proxyName.hashCode ^
url.hashCode ^
lastUpdateDate.hashCode ^
autoUpdateDuration.hashCode ^
userInfo.hashCode ^
autoUpdate.hashCode;
@override
String toString() {
return 'Profile{id: $id, label: $label, proxyName: $proxyName, url: $url, lastUpdateDate: $lastUpdateDate, autoUpdateDuration: $autoUpdateDuration, userInfo: $userInfo, autoUpdate: $autoUpdate}';
}
Profile copyWith({
String? label,
String? url,
UserInfo? userInfo,
String? groupName,
String? proxyName,
DateTime? lastUpdateDate,
Duration? autoUpdateDuration,
bool? autoUpdate,
SelectedMap? selectedMap,
}) {
return Profile(
id: id,
label: label ?? this.label,
url: url ?? this.url,
proxyName: proxyName ?? this.proxyName,
userInfo: userInfo ?? this.userInfo,
selectedMap: selectedMap ?? this.selectedMap,
lastUpdateDate: lastUpdateDate ?? this.lastUpdateDate,
autoUpdateDuration: autoUpdateDuration ?? this.autoUpdateDuration,
autoUpdate: autoUpdate ?? this.autoUpdate,
);
}
}