選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

176 行
5.3KB

  1. import 'dart:io';
  2. import 'dart:typed_data';
  3. import 'package:dio/dio.dart';
  4. import 'package:path/path.dart' as path;
  5. import '../models/content_post.dart';
  6. /// Service API pour l'amélioration IA et la génération de texte
  7. class ApiService {
  8. ApiService() {
  9. _dio = Dio(
  10. BaseOptions(
  11. baseUrl: baseUrl,
  12. connectTimeout: const Duration(seconds: 30),
  13. receiveTimeout: const Duration(seconds: 30),
  14. sendTimeout: const Duration(seconds: 30),
  15. ),
  16. );
  17. // Ajouter un interceptor pour les logs (development)
  18. _dio.interceptors.add(
  19. LogInterceptor(
  20. requestBody: true,
  21. responseBody: true,
  22. error: true,
  23. ),
  24. );
  25. }
  26. late final Dio _dio;
  27. static const String baseUrl = 'https://api.your-ai-provider.com';
  28. static const String aiEnhancementEndpoint = '/api/v1/enhance-image';
  29. static const String textGenerationEndpoint = '/api/v1/generate-text';
  30. /// Améliorer un média via l'API IA
  31. Future<EnhancementResult> enhanceMedia(
  32. File mediaFile, {
  33. required MediaType mediaType,
  34. }) async {
  35. try {
  36. final fileName = path.basename(mediaFile.path);
  37. final bytes = await mediaFile.readAsBytes();
  38. final formData = FormData.fromMap({
  39. 'media': MultipartFile.fromBytes(bytes, filename: fileName),
  40. 'type': mediaType.name,
  41. 'versions': '3',
  42. });
  43. final response = await _dio.post<Map<String, dynamic>>(
  44. aiEnhancementEndpoint,
  45. data: formData,
  46. );
  47. if (response.statusCode == 200) {
  48. final data = response.data!;
  49. final versions = <File>[];
  50. // Parser les URLs retournées et télécharger
  51. if (data['urls'] is List) {
  52. for (final url in data['urls'] as List) {
  53. final file = await _downloadFile(url.toString());
  54. versions.add(file);
  55. }
  56. }
  57. return (
  58. versions: versions,
  59. processedAt: DateTime.now(),
  60. error: null,
  61. );
  62. } else {
  63. throw Exception('API error: ${response.statusCode}');
  64. }
  65. } on DioException catch (e) {
  66. return (
  67. versions: const <File>[],
  68. processedAt: DateTime.now(),
  69. error: e.message ?? 'Unknown error',
  70. );
  71. } catch (e) {
  72. return (
  73. versions: const <File>[],
  74. processedAt: DateTime.now(),
  75. error: e.toString(),
  76. );
  77. }
  78. }
  79. /// Générer du texte basé sur le profil et les préférences
  80. Future<TextGenerationResult> generateTextProposals({
  81. required String profession,
  82. required String tone,
  83. required String style,
  84. required bool includeEmojis,
  85. required bool includeCommercialInfo,
  86. String? mediaDescription,
  87. }) async {
  88. try {
  89. final response = await _dio.post<Map<String, dynamic>>(
  90. textGenerationEndpoint,
  91. data: {
  92. 'profession': profession,
  93. 'tone': tone,
  94. 'style': style,
  95. 'include_emojis': includeEmojis,
  96. 'include_commercial_info': includeCommercialInfo,
  97. 'media_description': mediaDescription,
  98. 'num_proposals': 3,
  99. },
  100. );
  101. if (response.statusCode == 200) {
  102. final data = response.data!;
  103. final proposals = List<String>.from(data['proposals'] as List? ?? []);
  104. return (
  105. proposals: proposals,
  106. generatedAt: DateTime.now(),
  107. error: null,
  108. );
  109. } else {
  110. throw Exception('API error: ${response.statusCode}');
  111. }
  112. } on DioException catch (e) {
  113. // Retourner des proposals mock pour le développement
  114. return (
  115. proposals: _getMockProposals(includeEmojis),
  116. generatedAt: DateTime.now(),
  117. error: e.message,
  118. );
  119. } catch (e) {
  120. return (
  121. proposals: _getMockProposals(includeEmojis),
  122. generatedAt: DateTime.now(),
  123. error: e.toString(),
  124. );
  125. }
  126. }
  127. /// Télécharger un fichier depuis une URL
  128. Future<File> _downloadFile(String urlString) async {
  129. try {
  130. final response = await _dio.get<Uint8List>(
  131. urlString,
  132. options: Options(responseType: ResponseType.bytes),
  133. );
  134. final dir = Directory.systemTemp;
  135. final file = File('${dir.path}/enhanced_${DateTime.now().millisecondsSinceEpoch}.jpg');
  136. await file.writeAsBytes(response.data!);
  137. return file;
  138. } catch (e) {
  139. throw Exception('Failed to download file: $e');
  140. }
  141. }
  142. /// Propositions mock pour le développement
  143. List<String> _getMockProposals(bool withEmojis) {
  144. if (withEmojis) {
  145. return [
  146. '🌟 Découvrez notre nouvelle collection ! ✨ Qualité premium et innovation réunies. 💼 Rejoignez-nous pour transformer vos projets !',
  147. '💡 Excellence et professionnalisme au rendez-vous ! 🎯 Solutions innovantes pour tous. Faites confiance à notre expertise ! 🚀',
  148. '🔥 Olé Olé ! 🎉 Créativité et style sans limites. Vos rêves deviennent réalité avec nous ! ✨🌈',
  149. ];
  150. } else {
  151. return [
  152. 'Découvrez notre nouvelle collection. Qualité premium et innovation réunies. Rejoignez-nous pour transformer vos projets.',
  153. 'Excellence et professionnalisme au rendez-vous. Solutions innovantes pour tous. Faites confiance à notre expertise.',
  154. 'Créativité et style sans limites. Vos rêves deviennent réalité avec nous.',
  155. ];
  156. }
  157. }
  158. }