@ -0,0 +1,175 @@ | |||||
import 'dart:convert'; | |||||
import 'dart:io'; | |||||
import 'package:http/http.dart' as http; | |||||
import 'package:sqflite/sqflite.dart'; | |||||
import 'package:uuid/uuid.dart'; | |||||
import '/database/models/messages.dart'; | |||||
import '/database/models/image_message.dart'; | |||||
import '/database/models/text_messages.dart'; | |||||
import '/database/models/conversation_users.dart'; | |||||
import '/database/models/conversations.dart'; | |||||
import '/database/models/my_profile.dart'; | |||||
import '/utils/storage/database.dart'; | |||||
import '/utils/storage/session_cookie.dart'; | |||||
import '/utils/storage/write_file.dart'; | |||||
class MessagesService { | |||||
static Future<void> sendMessage(Conversation conversation, { | |||||
String? data, | |||||
List<File> files = const [] | |||||
}) async { | |||||
MyProfile profile = await MyProfile.getProfile(); | |||||
var uuid = const Uuid(); | |||||
ConversationUser currentUser = await getConversationUser(conversation, profile.id); | |||||
List<Message> messages = []; | |||||
List<Map<String, dynamic>> messagesToSend = []; | |||||
final db = await getDatabaseConnection(); | |||||
if (data != null) { | |||||
TextMessage message = TextMessage( | |||||
id: uuid.v4(), | |||||
symmetricKey: '', | |||||
userSymmetricKey: '', | |||||
senderId: currentUser.userId, | |||||
senderUsername: profile.username, | |||||
associationKey: currentUser.associationKey, | |||||
createdAt: DateTime.now().toIso8601String(), | |||||
failedToSend: false, | |||||
text: data, | |||||
); | |||||
messages.add(message); | |||||
messagesToSend.add(await message.payloadJson( | |||||
conversation, | |||||
)); | |||||
await db.insert( | |||||
'messages', | |||||
message.toMap(), | |||||
conflictAlgorithm: ConflictAlgorithm.replace, | |||||
); | |||||
} | |||||
for (File file in files) { | |||||
String messageId = uuid.v4(); | |||||
File writtenFile = await writeImage( | |||||
messageId, | |||||
file.readAsBytesSync(), | |||||
); | |||||
ImageMessage message = ImageMessage( | |||||
id: messageId, | |||||
symmetricKey: '', | |||||
userSymmetricKey: '', | |||||
senderId: currentUser.userId, | |||||
senderUsername: profile.username, | |||||
associationKey: currentUser.associationKey, | |||||
createdAt: DateTime.now().toIso8601String(), | |||||
failedToSend: false, | |||||
file: writtenFile, | |||||
); | |||||
messages.add(message); | |||||
messagesToSend.add(await message.payloadJson( | |||||
conversation, | |||||
)); | |||||
await db.insert( | |||||
'messages', | |||||
message.toMap(), | |||||
conflictAlgorithm: ConflictAlgorithm.replace, | |||||
); | |||||
} | |||||
String sessionCookie = await getSessionCookie(); | |||||
return http.post( | |||||
await MyProfile.getServerUrl('api/v1/auth/message'), | |||||
headers: <String, String>{ | |||||
'Content-Type': 'application/json; charset=UTF-8', | |||||
'cookie': sessionCookie, | |||||
}, | |||||
body: jsonEncode(messagesToSend), | |||||
) | |||||
.then((resp) { | |||||
if (resp.statusCode != 204) { | |||||
throw Exception('Unable to send message'); | |||||
} | |||||
}) | |||||
.catchError((exception) { | |||||
for (Message message in messages) { | |||||
message.failedToSend = true; | |||||
db.update( | |||||
'messages', | |||||
message.toMap(), | |||||
where: 'id = ?', | |||||
whereArgs: [message.id], | |||||
); | |||||
} | |||||
throw exception; | |||||
}); | |||||
} | |||||
static Future<void> updateMessageThread(Conversation conversation, {MyProfile? profile}) async { | |||||
profile ??= await MyProfile.getProfile(); | |||||
ConversationUser currentUser = await getConversationUser(conversation, profile.id); | |||||
var resp = await http.get( | |||||
await MyProfile.getServerUrl('api/v1/auth/messages/${currentUser.associationKey}'), | |||||
headers: { | |||||
'cookie': await getSessionCookie(), | |||||
} | |||||
); | |||||
if (resp.statusCode != 200) { | |||||
throw Exception(resp.body); | |||||
} | |||||
List<dynamic> messageThreadJson = jsonDecode(resp.body); | |||||
final db = await getDatabaseConnection(); | |||||
for (var i = 0; i < messageThreadJson.length; i++) { | |||||
var messageJson = messageThreadJson[i] as Map<String, dynamic>; | |||||
var message = messageJson['message_data']['attachment_id'] != null ? | |||||
await ImageMessage.fromJson( | |||||
messageJson, | |||||
profile.privateKey!, | |||||
) : | |||||
TextMessage.fromJson( | |||||
messageJson, | |||||
profile.privateKey!, | |||||
); | |||||
ConversationUser messageUser = await getConversationUser(conversation, message.senderId); | |||||
message.senderUsername = messageUser.username; | |||||
await db.insert( | |||||
'messages', | |||||
message.toMap(), | |||||
conflictAlgorithm: ConflictAlgorithm.replace, | |||||
); | |||||
} | |||||
} | |||||
static Future<void> updateMessageThreads({List<Conversation>? conversations}) async { | |||||
MyProfile profile = await MyProfile.getProfile(); | |||||
conversations ??= await getConversations(); | |||||
for (var i = 0; i < conversations.length; i++) { | |||||
await updateMessageThread(conversations[i], profile: profile); | |||||
} | |||||
} | |||||
} |
@ -1,176 +0,0 @@ | |||||
import 'dart:convert'; | |||||
import 'dart:io'; | |||||
import 'package:Envelope/utils/storage/write_file.dart'; | |||||
import 'package:http/http.dart' as http; | |||||
import 'package:sqflite/sqflite.dart'; | |||||
import 'package:uuid/uuid.dart'; | |||||
import '/database/models/messages.dart'; | |||||
import '/database/models/image_message.dart'; | |||||
import '/database/models/text_messages.dart'; | |||||
import '/database/models/conversation_users.dart'; | |||||
import '/database/models/conversations.dart'; | |||||
import '/database/models/my_profile.dart'; | |||||
import '/utils/storage/database.dart'; | |||||
import '/utils/storage/session_cookie.dart'; | |||||
Future<void> sendMessage(Conversation conversation, { | |||||
String? data, | |||||
List<File> files = const [] | |||||
}) async { | |||||
MyProfile profile = await MyProfile.getProfile(); | |||||
var uuid = const Uuid(); | |||||
ConversationUser currentUser = await getConversationUser(conversation, profile.id); | |||||
List<Message> messages = []; | |||||
List<Map<String, dynamic>> messagesToSend = []; | |||||
final db = await getDatabaseConnection(); | |||||
if (data != null) { | |||||
TextMessage message = TextMessage( | |||||
id: uuid.v4(), | |||||
symmetricKey: '', | |||||
userSymmetricKey: '', | |||||
senderId: currentUser.userId, | |||||
senderUsername: profile.username, | |||||
associationKey: currentUser.associationKey, | |||||
createdAt: DateTime.now().toIso8601String(), | |||||
failedToSend: false, | |||||
text: data, | |||||
); | |||||
messages.add(message); | |||||
messagesToSend.add(await message.payloadJson( | |||||
conversation, | |||||
)); | |||||
await db.insert( | |||||
'messages', | |||||
message.toMap(), | |||||
conflictAlgorithm: ConflictAlgorithm.replace, | |||||
); | |||||
} | |||||
for (File file in files) { | |||||
String messageId = uuid.v4(); | |||||
File writtenFile = await writeImage( | |||||
messageId, | |||||
file.readAsBytesSync(), | |||||
); | |||||
ImageMessage message = ImageMessage( | |||||
id: messageId, | |||||
symmetricKey: '', | |||||
userSymmetricKey: '', | |||||
senderId: currentUser.userId, | |||||
senderUsername: profile.username, | |||||
associationKey: currentUser.associationKey, | |||||
createdAt: DateTime.now().toIso8601String(), | |||||
failedToSend: false, | |||||
file: writtenFile, | |||||
); | |||||
messages.add(message); | |||||
messagesToSend.add(await message.payloadJson( | |||||
conversation, | |||||
)); | |||||
await db.insert( | |||||
'messages', | |||||
message.toMap(), | |||||
conflictAlgorithm: ConflictAlgorithm.replace, | |||||
); | |||||
} | |||||
String sessionCookie = await getSessionCookie(); | |||||
return http.post( | |||||
await MyProfile.getServerUrl('api/v1/auth/message'), | |||||
headers: <String, String>{ | |||||
'Content-Type': 'application/json; charset=UTF-8', | |||||
'cookie': sessionCookie, | |||||
}, | |||||
body: jsonEncode(messagesToSend), | |||||
) | |||||
.then((resp) { | |||||
if (resp.statusCode != 204) { | |||||
throw Exception('Unable to send message'); | |||||
} | |||||
}) | |||||
.catchError((exception) { | |||||
for (Message message in messages) { | |||||
message.failedToSend = true; | |||||
db.update( | |||||
'messages', | |||||
message.toMap(), | |||||
where: 'id = ?', | |||||
whereArgs: [message.id], | |||||
); | |||||
} | |||||
throw exception; | |||||
}); | |||||
} | |||||
Future<void> updateMessageThread(Conversation conversation, {MyProfile? profile}) async { | |||||
profile ??= await MyProfile.getProfile(); | |||||
ConversationUser currentUser = await getConversationUser(conversation, profile.id); | |||||
var resp = await http.get( | |||||
await MyProfile.getServerUrl('api/v1/auth/messages/${currentUser.associationKey}'), | |||||
headers: { | |||||
'cookie': await getSessionCookie(), | |||||
} | |||||
); | |||||
if (resp.statusCode != 200) { | |||||
throw Exception(resp.body); | |||||
} | |||||
List<dynamic> messageThreadJson = jsonDecode(resp.body); | |||||
final db = await getDatabaseConnection(); | |||||
for (var i = 0; i < messageThreadJson.length; i++) { | |||||
var messageJson = messageThreadJson[i] as Map<String, dynamic>; | |||||
var message = messageJson['message_data']['attachment_id'] != null ? | |||||
await ImageMessage.fromJson( | |||||
messageJson, | |||||
profile.privateKey!, | |||||
) : | |||||
TextMessage.fromJson( | |||||
messageJson, | |||||
profile.privateKey!, | |||||
); | |||||
ConversationUser messageUser = await getConversationUser(conversation, message.senderId); | |||||
message.senderUsername = messageUser.username; | |||||
await db.insert( | |||||
'messages', | |||||
message.toMap(), | |||||
conflictAlgorithm: ConflictAlgorithm.replace, | |||||
); | |||||
} | |||||
} | |||||
Future<void> updateMessageThreads({List<Conversation>? conversations}) async { | |||||
// try { | |||||
MyProfile profile = await MyProfile.getProfile(); | |||||
conversations ??= await getConversations(); | |||||
for (var i = 0; i < conversations.length; i++) { | |||||
await updateMessageThread(conversations[i], profile: profile); | |||||
} | |||||
// } catch(SocketException) { | |||||
// return; | |||||
// } | |||||
} |