Files
sm-emby-share/lib/core/domain/usecases/server_usecases.dart
T
2026-07-14 11:11:36 +08:00

180 lines
4.8 KiB
Dart

import 'package:uuid/uuid.dart';
import '../../contracts/contracts.dart';
import '../errors.dart';
import '../ports/emby_gateway.dart';
import '../ports/server_repository.dart';
import '../ports/session_repository.dart';
const _uuid = Uuid();
class ListServersUseCase {
final ServerRepository serverRepository;
ListServersUseCase({required this.serverRepository});
Future<List<EmbyServer>> execute() => serverRepository.list();
}
class ReorderServersUseCase {
final ServerRepository serverRepository;
ReorderServersUseCase({required this.serverRepository});
Future<void> execute(List<EmbyServer> orderedServers) {
return serverRepository.replaceAll(orderedServers);
}
}
class ProbeServerUseCase {
final EmbyGateway embyGateway;
ProbeServerUseCase({required this.embyGateway});
Future<ProbePublicInfoRes> execute(EmbyServerProbeReq input) async {
final baseUrl = input.baseUrl.trim();
if (baseUrl.isEmpty) {
throw DomainError(ErrorCode.invalidParams, '服务器地址不能为空');
}
return embyGateway.probePublicInfo(baseUrl);
}
}
class SaveServerUseCase {
final ServerRepository serverRepository;
final DateTime Function() now;
final String Function() idGenerator;
SaveServerUseCase({
required this.serverRepository,
DateTime Function()? now,
String Function()? idGenerator,
}) : now = (now ?? DateTime.now),
idGenerator = (idGenerator ?? _defaultIdGenerator);
static String _defaultIdGenerator() => _uuid.v4();
Future<EmbyServer> execute(EmbyServerSaveReq input) async {
final name = input.name.trim();
if (name.isEmpty) {
throw DomainError(ErrorCode.invalidParams, '服务器名称不能为空');
}
final baseUrl = _normalizeBaseUrl(input.baseUrl);
final nowIso = now().toUtc().toIso8601String();
final duplicated = await serverRepository.findByBaseUrl(baseUrl);
if (duplicated != null && duplicated.id != input.id) {
throw DomainError(
ErrorCode.storeConflict,
'服务器地址已存在',
details: {'baseUrl': baseUrl},
);
}
final iconUrl = input.iconUrl.trim();
if (input.id != null) {
final current = await serverRepository.findById(input.id!);
if (current == null) {
throw DomainError(
ErrorCode.storeNotFound,
'服务器不存在',
details: {'id': input.id},
);
}
return serverRepository.update(
current.copyWith(
name: name,
baseUrl: baseUrl,
updatedAt: nowIso,
iconUrl: iconUrl,
),
);
}
return serverRepository.create(
EmbyServer(
id: idGenerator(),
name: name,
baseUrl: baseUrl,
createdAt: nowIso,
updatedAt: nowIso,
iconUrl: iconUrl,
),
);
}
String _normalizeBaseUrl(String raw) {
final trimmed = raw.trim();
if (trimmed.isEmpty) {
throw DomainError(ErrorCode.invalidParams, '服务器地址不能为空');
}
Uri parsed;
try {
parsed = Uri.parse(trimmed);
} catch (_) {
throw DomainError(
ErrorCode.invalidParams,
'服务器地址格式不正确',
details: {'baseUrl': raw},
);
}
if (parsed.scheme != 'http' && parsed.scheme != 'https') {
throw DomainError(
ErrorCode.invalidParams,
'仅支持 HTTP/HTTPS 协议',
details: {'baseUrl': raw},
);
}
final origin =
'${parsed.scheme}://${parsed.host}'
'${parsed.hasPort ? ':${parsed.port}' : ''}';
final cleanPath = parsed.path.replaceAll(RegExp(r'/+$'), '');
final normalizedPath = cleanPath.isEmpty ? '/' : cleanPath;
if (RegExp(r'/emby$', caseSensitive: false).hasMatch(normalizedPath)) {
return '$origin$normalizedPath';
}
if (normalizedPath == '/') {
return '$origin/emby';
}
return '$origin$normalizedPath/emby';
}
}
class TogglePauseServerUseCase {
final ServerRepository serverRepository;
TogglePauseServerUseCase({required this.serverRepository});
Future<EmbyServer> execute(String id) async {
final current = await serverRepository.findById(id);
if (current == null) {
throw DomainError(ErrorCode.storeNotFound, '服务器不存在', details: {'id': id});
}
return serverRepository.update(current.copyWith(paused: !current.paused));
}
}
class DeleteServerUseCase {
final ServerRepository serverRepository;
final SessionRepository sessionRepository;
DeleteServerUseCase({
required this.serverRepository,
required this.sessionRepository,
});
Future<void> execute(String id) async {
final exists = await serverRepository.findById(id);
if (exists == null) {
throw DomainError(ErrorCode.storeNotFound, '服务器不存在', details: {'id': id});
}
await serverRepository.deleteById(id);
await sessionRepository.clear(id);
}
}