138 lines
4.9 KiB
Dart
138 lines
4.9 KiB
Dart
import '../data/service_data_repository.dart';
|
|
import '../data/legacy_service_data.dart';
|
|
import 'url_matcher_service.dart';
|
|
|
|
/// 해지 URL 관련 기능을 제공하는 서비스 클래스
|
|
class CancellationUrlService {
|
|
final ServiceDataRepository _dataRepository;
|
|
final UrlMatcherService _urlMatcher;
|
|
|
|
CancellationUrlService(this._dataRepository, this._urlMatcher);
|
|
|
|
/// 서비스명 또는 URL로 해지 안내 페이지 URL 찾기
|
|
Future<String?> findCancellationUrl({
|
|
String? serviceName,
|
|
String? websiteUrl,
|
|
String locale = 'kr',
|
|
}) async {
|
|
// JSON 데이터가 있으면 JSON에서 찾기
|
|
final servicesData = _dataRepository.getServicesData();
|
|
if (servicesData != null) {
|
|
final categories = servicesData['categories'] as Map<String, dynamic>;
|
|
|
|
// 1. 서비스명으로 찾기
|
|
if (serviceName != null && serviceName.isNotEmpty) {
|
|
final lowerName = serviceName.toLowerCase().trim();
|
|
|
|
for (final categoryData in categories.values) {
|
|
final services = (categoryData as Map<String, dynamic>)['services']
|
|
as Map<String, dynamic>;
|
|
|
|
for (final serviceData in services.values) {
|
|
final names = List<String>.from(
|
|
(serviceData as Map<String, dynamic>)['names'] ?? []);
|
|
|
|
for (final name in names) {
|
|
if (lowerName.contains(name.toLowerCase()) ||
|
|
name.toLowerCase().contains(lowerName)) {
|
|
final cancellationUrls =
|
|
serviceData['cancellationUrls'] as Map<String, dynamic>?;
|
|
if (cancellationUrls != null) {
|
|
// 요청한 언어의 URL이 있으면 반환, 없으면 다른 언어 URL 반환
|
|
return cancellationUrls[locale] ??
|
|
cancellationUrls[locale == 'kr' ? 'en' : 'kr'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. URL로 찾기
|
|
if (websiteUrl != null && websiteUrl.isNotEmpty) {
|
|
final domain = _urlMatcher.extractDomain(websiteUrl);
|
|
if (domain != null) {
|
|
for (final categoryData in categories.values) {
|
|
final services = (categoryData as Map<String, dynamic>)['services']
|
|
as Map<String, dynamic>;
|
|
|
|
for (final serviceData in services.values) {
|
|
final domains = List<String>.from(
|
|
(serviceData as Map<String, dynamic>)['domains'] ?? []);
|
|
|
|
for (final serviceDomain in domains) {
|
|
if (domain.contains(serviceDomain) ||
|
|
serviceDomain.contains(domain)) {
|
|
final cancellationUrls =
|
|
serviceData['cancellationUrls'] as Map<String, dynamic>?;
|
|
if (cancellationUrls != null) {
|
|
return cancellationUrls[locale] ??
|
|
cancellationUrls[locale == 'kr' ? 'en' : 'kr'];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// JSON에서 못 찾았으면 레거시 방식으로 찾기
|
|
return _findCancellationUrlLegacy(serviceName ?? websiteUrl ?? '');
|
|
}
|
|
|
|
/// 서비스명 또는 웹사이트 URL을 기반으로 해지 안내 페이지 URL 찾기 (레거시)
|
|
String? _findCancellationUrlLegacy(String serviceNameOrUrl) {
|
|
if (serviceNameOrUrl.isEmpty) {
|
|
return null;
|
|
}
|
|
|
|
// 소문자로 변환하여 처리
|
|
final String lowerText = serviceNameOrUrl.toLowerCase().trim();
|
|
|
|
// 직접 서비스명으로 찾기
|
|
if (LegacyServiceData.cancellationUrls.containsKey(lowerText)) {
|
|
return LegacyServiceData.cancellationUrls[lowerText];
|
|
}
|
|
|
|
// 서비스명에 부분 포함으로 찾기
|
|
for (var entry in LegacyServiceData.cancellationUrls.entries) {
|
|
final String key = entry.key.toLowerCase();
|
|
if (lowerText.contains(key) || key.contains(lowerText)) {
|
|
return entry.value;
|
|
}
|
|
}
|
|
|
|
// URL을 통해 서비스명 추출 후 찾기
|
|
if (lowerText.startsWith('http')) {
|
|
// URL 도메인 추출 (https://www.netflix.com 에서 netflix 추출)
|
|
final domainRegex = RegExp(r'https?://(?:www\.)?([a-zA-Z0-9-]+)');
|
|
final match = domainRegex.firstMatch(lowerText);
|
|
|
|
if (match != null && match.groupCount >= 1) {
|
|
final domain = match.group(1)?.toLowerCase() ?? '';
|
|
|
|
// 도메인으로 서비스명 찾기
|
|
for (var entry in LegacyServiceData.cancellationUrls.entries) {
|
|
if (entry.key.toLowerCase().contains(domain)) {
|
|
return entry.value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 해지 안내 페이지를 찾지 못함
|
|
return null;
|
|
}
|
|
|
|
/// 서비스에 공식 해지 안내 페이지가 있는지 확인
|
|
Future<bool> hasCancellationPage(String serviceNameOrUrl) async {
|
|
// 새로운 JSON 기반 방식으로 확인
|
|
final cancellationUrl = await findCancellationUrl(
|
|
serviceName: serviceNameOrUrl,
|
|
websiteUrl: serviceNameOrUrl,
|
|
);
|
|
return cancellationUrl != null;
|
|
}
|
|
}
|