feat(app): finalize ad gated flows and weather
- add AppLogger and replace scattered print logging\n- implement ad-gated recommendation flow with reminder handling and calendar link\n- complete Bluetooth share pipeline with ad gate and merge\n- integrate KMA weather API with caching and dart-define decoding\n- add NaverUrlProcessor refactor and restore restaurant repository tests
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:lunchpick/core/utils/app_logger.dart';
|
||||
|
||||
import '../../../core/network/network_client.dart';
|
||||
import '../../../core/errors/network_exceptions.dart';
|
||||
@@ -46,7 +46,11 @@ class NaverGraphQLApi {
|
||||
|
||||
return response.data!;
|
||||
} on DioException catch (e) {
|
||||
debugPrint('fetchGraphQL error: $e');
|
||||
AppLogger.error(
|
||||
'fetchGraphQL error: $e',
|
||||
error: e,
|
||||
stackTrace: e.stackTrace,
|
||||
);
|
||||
throw ServerException(
|
||||
message: 'GraphQL 요청 중 오류가 발생했습니다',
|
||||
statusCode: e.response?.statusCode ?? 500,
|
||||
@@ -104,13 +108,17 @@ class NaverGraphQLApi {
|
||||
);
|
||||
|
||||
if (response['errors'] != null) {
|
||||
debugPrint('GraphQL errors: ${response['errors']}');
|
||||
AppLogger.error('GraphQL errors: ${response['errors']}');
|
||||
throw ParseException(message: 'GraphQL 오류: ${response['errors']}');
|
||||
}
|
||||
|
||||
return response['data']?['place'] ?? {};
|
||||
} catch (e) {
|
||||
debugPrint('fetchKoreanTextsFromPcmap error: $e');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'fetchKoreanTextsFromPcmap error: $e',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
@@ -150,8 +158,12 @@ class NaverGraphQLApi {
|
||||
}
|
||||
|
||||
return response['data']?['place'] ?? {};
|
||||
} catch (e) {
|
||||
debugPrint('fetchPlaceBasicInfo error: $e');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'fetchPlaceBasicInfo error: $e',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:lunchpick/core/utils/app_logger.dart';
|
||||
|
||||
import '../../../core/constants/api_keys.dart';
|
||||
import '../../../core/network/network_client.dart';
|
||||
@@ -143,9 +143,13 @@ class NaverLocalSearchApi {
|
||||
.map((item) => NaverLocalSearchResult.fromJson(item))
|
||||
.toList();
|
||||
} on DioException catch (e) {
|
||||
debugPrint('NaverLocalSearchApi Error: ${e.message}');
|
||||
debugPrint('Error type: ${e.type}');
|
||||
debugPrint('Error response: ${e.response?.data}');
|
||||
AppLogger.error(
|
||||
'NaverLocalSearchApi error: ${e.message}',
|
||||
error: e,
|
||||
stackTrace: e.stackTrace,
|
||||
);
|
||||
AppLogger.debug('Error type: ${e.type}');
|
||||
AppLogger.debug('Error response: ${e.response?.data}');
|
||||
|
||||
if (e.error is NetworkException) {
|
||||
throw e.error!;
|
||||
@@ -189,8 +193,12 @@ class NaverLocalSearchApi {
|
||||
|
||||
// 정확한 매칭이 없으면 첫 번째 결과 반환
|
||||
return results.first;
|
||||
} catch (e) {
|
||||
debugPrint('searchRestaurantDetails error: $e');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'searchRestaurantDetails error: $e',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:lunchpick/core/utils/app_logger.dart';
|
||||
|
||||
import '../../../core/network/network_client.dart';
|
||||
import '../../../core/network/network_config.dart';
|
||||
@@ -22,7 +23,7 @@ class NaverProxyClient {
|
||||
|
||||
try {
|
||||
final proxyUrl = NetworkConfig.getCorsProxyUrl(url);
|
||||
debugPrint('Using proxy URL: $proxyUrl');
|
||||
AppLogger.debug('Using proxy URL: $proxyUrl');
|
||||
|
||||
final response = await _networkClient.get<String>(
|
||||
proxyUrl,
|
||||
@@ -42,9 +43,13 @@ class NaverProxyClient {
|
||||
|
||||
return response.data!;
|
||||
} on DioException catch (e) {
|
||||
debugPrint('Proxy fetch error: ${e.message}');
|
||||
debugPrint('Status code: ${e.response?.statusCode}');
|
||||
debugPrint('Response: ${e.response?.data}');
|
||||
AppLogger.error(
|
||||
'Proxy fetch error: ${e.message}',
|
||||
error: e,
|
||||
stackTrace: e.stackTrace,
|
||||
);
|
||||
AppLogger.debug('Status code: ${e.response?.statusCode}');
|
||||
AppLogger.debug('Response: ${e.response?.data}');
|
||||
|
||||
if (e.response?.statusCode == 403) {
|
||||
throw ServerException(
|
||||
@@ -78,8 +83,12 @@ class NaverProxyClient {
|
||||
);
|
||||
|
||||
return response.statusCode == 200;
|
||||
} catch (e) {
|
||||
debugPrint('Proxy status check failed: $e');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'Proxy status check failed: $e',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:lunchpick/core/utils/app_logger.dart';
|
||||
|
||||
import '../../../core/network/network_client.dart';
|
||||
import '../../../core/network/network_config.dart';
|
||||
@@ -39,7 +40,11 @@ class NaverUrlResolver {
|
||||
// 리다이렉트가 없으면 원본 URL 반환
|
||||
return shortUrl;
|
||||
} on DioException catch (e) {
|
||||
debugPrint('resolveShortUrl error: $e');
|
||||
AppLogger.error(
|
||||
'resolveShortUrl error: $e',
|
||||
error: e,
|
||||
stackTrace: e.stackTrace,
|
||||
);
|
||||
|
||||
// 리다이렉트 응답인 경우 Location 헤더 확인
|
||||
if (e.response?.statusCode == 301 || e.response?.statusCode == 302) {
|
||||
@@ -98,8 +103,12 @@ class NaverUrlResolver {
|
||||
}
|
||||
|
||||
return shortUrl;
|
||||
} catch (e) {
|
||||
debugPrint('_resolveShortUrlViaProxy error: $e');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'_resolveShortUrlViaProxy error: $e',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
return shortUrl;
|
||||
}
|
||||
}
|
||||
@@ -139,8 +148,12 @@ class NaverUrlResolver {
|
||||
}
|
||||
|
||||
return currentUrl;
|
||||
} catch (e) {
|
||||
debugPrint('getFinalRedirectUrl error: $e');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'getFinalRedirectUrl error: $e',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:lunchpick/core/utils/app_logger.dart';
|
||||
|
||||
import '../../core/network/network_client.dart';
|
||||
import '../../core/errors/network_exceptions.dart';
|
||||
@@ -88,7 +89,11 @@ class NaverApiClient {
|
||||
|
||||
return response.data!;
|
||||
} on DioException catch (e) {
|
||||
debugPrint('fetchMapPageHtml error: $e');
|
||||
AppLogger.error(
|
||||
'fetchMapPageHtml error: $e',
|
||||
error: e,
|
||||
stackTrace: e.stackTrace,
|
||||
);
|
||||
|
||||
if (e.error is NetworkException) {
|
||||
throw e.error!;
|
||||
@@ -123,9 +128,9 @@ class NaverApiClient {
|
||||
final pcmapUrl = 'https://pcmap.place.naver.com/restaurant/$placeId/home';
|
||||
|
||||
try {
|
||||
debugPrint('========== 네이버 pcmap 한글 추출 시작 ==========');
|
||||
debugPrint('요청 URL: $pcmapUrl');
|
||||
debugPrint('Place ID: $placeId');
|
||||
AppLogger.debug('========== 네이버 pcmap 한글 추출 시작 ==========');
|
||||
AppLogger.debug('요청 URL: $pcmapUrl');
|
||||
AppLogger.debug('Place ID: $placeId');
|
||||
|
||||
String html;
|
||||
if (kIsWeb) {
|
||||
@@ -148,7 +153,7 @@ class NaverApiClient {
|
||||
);
|
||||
|
||||
if (response.statusCode != 200 || response.data == null) {
|
||||
debugPrint(
|
||||
AppLogger.error(
|
||||
'NaverApiClient: pcmap 페이지 로드 실패 - status: ${response.statusCode}',
|
||||
);
|
||||
return {
|
||||
@@ -172,11 +177,11 @@ class NaverApiClient {
|
||||
html,
|
||||
);
|
||||
|
||||
debugPrint('========== 추출 결과 ==========');
|
||||
debugPrint('총 한글 텍스트 수: ${koreanTexts.length}');
|
||||
debugPrint('JSON-LD 상호명: $jsonLdName');
|
||||
debugPrint('Apollo State 상호명: $apolloName');
|
||||
debugPrint('=====================================');
|
||||
AppLogger.debug('========== 추출 결과 ==========');
|
||||
AppLogger.debug('총 한글 텍스트 수: ${koreanTexts.length}');
|
||||
AppLogger.debug('JSON-LD 상호명: $jsonLdName');
|
||||
AppLogger.debug('Apollo State 상호명: $apolloName');
|
||||
AppLogger.debug('=====================================');
|
||||
|
||||
return {
|
||||
'success': true,
|
||||
@@ -187,8 +192,12 @@ class NaverApiClient {
|
||||
'apolloStateName': apolloName,
|
||||
'extractedAt': DateTime.now().toIso8601String(),
|
||||
};
|
||||
} catch (e) {
|
||||
debugPrint('NaverApiClient: pcmap 페이지 파싱 실패 - $e');
|
||||
} catch (e, stackTrace) {
|
||||
AppLogger.error(
|
||||
'NaverApiClient: pcmap 페이지 파싱 실패 - $e',
|
||||
error: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
return {
|
||||
'success': false,
|
||||
'error': e.toString(),
|
||||
|
||||
Reference in New Issue
Block a user