156 lines
5.0 KiB
Dart
156 lines
5.0 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:bloc/bloc.dart';
|
|
import 'package:equatable/equatable.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:hoshan/core/services/api/dio_service.dart';
|
|
import 'package:hoshan/data/model/ai/ai_response_model.dart';
|
|
import 'package:hoshan/data/model/ai/send_message_model.dart';
|
|
import 'package:hoshan/data/repository/chatbot_repository.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
|
|
part 'media_g_response_state.dart';
|
|
|
|
class MediaGResponseCubit extends Cubit<MediaGResponseState> {
|
|
MediaGResponseCubit() : super(MediaGResponseInitial());
|
|
|
|
void request(SendMessageModel model) async {
|
|
emit(MediaGResponseLoading(file: model.file, query: model.query));
|
|
try {
|
|
AiResponseModel response = AiResponseModel();
|
|
await for (String message in ChatbotRepository.sendMessageTool(model)) {
|
|
late Map<String, dynamic> jsonMap;
|
|
try {
|
|
jsonMap = jsonDecode(message);
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('Error in Parse: $e');
|
|
}
|
|
}
|
|
|
|
final r = AiResponseModel.fromJson(jsonMap)
|
|
.copyWith(humanMessageId: model.messageId);
|
|
response = response.copyWith(
|
|
aiMessageId: r.aiMessageId,
|
|
chatId: r.chatId,
|
|
chatTitle: r.chatTitle,
|
|
content: r.content,
|
|
credit: r.credit,
|
|
detail: r.detail,
|
|
error: r.content?.startsWith('Check failed') ?? r.error,
|
|
freeCredit: r.freeCredit,
|
|
humanMessageId: r.humanMessageId,
|
|
statusCode: r.statusCode);
|
|
}
|
|
|
|
// Check if this is a Suno music creation request
|
|
const sunoMusicBotIds = [
|
|
783,
|
|
871,
|
|
957,
|
|
958,
|
|
959,
|
|
960,
|
|
961,
|
|
962,
|
|
963,
|
|
964,
|
|
965
|
|
];
|
|
if (model.botId != null && sunoMusicBotIds.contains(model.botId)) {
|
|
if (kDebugMode) {
|
|
print('🎵 Suno music creation detected for botId: ${model.botId}');
|
|
}
|
|
|
|
// Extract content (task ID) from the response
|
|
final taskId = response.content;
|
|
if (taskId != null && taskId.isNotEmpty) {
|
|
if (kDebugMode) {
|
|
print('🎵 Retrieved content (taskId): $taskId');
|
|
print('🎵 Making request to: /api/suno/tasks/$taskId');
|
|
}
|
|
|
|
try {
|
|
final dioService = DioService();
|
|
String? audioUrl;
|
|
int retryCount = 0;
|
|
const maxRetries =
|
|
60; // Maximum 60 attempts (5 minutes with 5 second delays)
|
|
const retryDelay = Duration(seconds: 5);
|
|
|
|
// Poll the Suno API until audio_url is available
|
|
while (audioUrl == null && retryCount < maxRetries) {
|
|
if (retryCount > 0) {
|
|
if (kDebugMode) {
|
|
print(
|
|
'⏳ Waiting for audio to be generated... (attempt ${retryCount + 1}/$maxRetries)');
|
|
}
|
|
await Future.delayed(retryDelay);
|
|
}
|
|
|
|
// Make GET request to Suno API to get audio_url
|
|
final sunoResponse = await dioService.sendRequest().get(
|
|
DioService.sunoTask(taskId: taskId),
|
|
);
|
|
|
|
if (kDebugMode) {
|
|
print(
|
|
'🎵 Suno API response (attempt ${retryCount + 1}): ${sunoResponse.data}');
|
|
}
|
|
|
|
// Extract audio_url from response
|
|
final responseAudioUrl =
|
|
sunoResponse.data['audio_url'] as String?;
|
|
final status = sunoResponse.data['status'] as String?;
|
|
|
|
if (kDebugMode) {
|
|
print(
|
|
'📊 Status: $status, audio_url: ${responseAudioUrl ?? "null"}');
|
|
}
|
|
|
|
if (responseAudioUrl != null && responseAudioUrl.isNotEmpty) {
|
|
audioUrl = responseAudioUrl;
|
|
if (kDebugMode) {
|
|
print('✅ Retrieved audio_url: $audioUrl');
|
|
}
|
|
} else {
|
|
retryCount++;
|
|
}
|
|
}
|
|
|
|
if (audioUrl != null) {
|
|
// Update response content with audio_url
|
|
response = response.copyWith(content: audioUrl);
|
|
} else {
|
|
if (kDebugMode) {
|
|
print('⚠️ Audio URL not available after $maxRetries attempts');
|
|
}
|
|
}
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('❌ Error fetching Suno task: $e');
|
|
}
|
|
}
|
|
} else {
|
|
if (kDebugMode) {
|
|
print('⚠️ No content (taskId) found in initial response');
|
|
}
|
|
}
|
|
}
|
|
|
|
emit(MediaGResponseSucess(
|
|
response: response,
|
|
file: model.file,
|
|
query: model.query,
|
|
error: response.error ?? false
|
|
? 'مشکلی از طرف سرور رخ داده است'
|
|
: null));
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('Dio Error is: $e');
|
|
}
|
|
emit(MediaGResponseFail());
|
|
}
|
|
}
|
|
}
|