Encrypted messaging app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.6 KiB

  1. import 'dart:convert';
  2. import 'dart:io';
  3. import 'package:Envelope/models/text_messages.dart';
  4. import 'package:http/http.dart' as http;
  5. import 'package:sqflite/sqflite.dart';
  6. import 'package:uuid/uuid.dart';
  7. import '/models/conversation_users.dart';
  8. import '/models/conversations.dart';
  9. import '/models/messages.dart';
  10. import '/models/my_profile.dart';
  11. import '/utils/storage/database.dart';
  12. import '/utils/storage/session_cookie.dart';
  13. Future<void> sendMessage(Conversation conversation, { String? data, List<File>? files }) async {
  14. MyProfile profile = await MyProfile.getProfile();
  15. var uuid = const Uuid();
  16. final String messageId = uuid.v4();
  17. ConversationUser currentUser = await getConversationUser(conversation, profile.id);
  18. List<Map<String, dynamic>> messagesToAdd = [];
  19. if (data != null) {
  20. messagesToAdd.add({ 'text': data });
  21. }
  22. if (files != null && files.isNotEmpty) {
  23. for (File file in files) {
  24. messagesToAdd.add({ 'file': file });
  25. }
  26. }
  27. var message = TextMessage(
  28. id: messageId,
  29. symmetricKey: '',
  30. userSymmetricKey: '',
  31. senderId: currentUser.userId,
  32. senderUsername: profile.username,
  33. text: data!,
  34. associationKey: currentUser.associationKey,
  35. createdAt: DateTime.now().toIso8601String(),
  36. failedToSend: false,
  37. );
  38. final db = await getDatabaseConnection();
  39. await db.insert(
  40. 'messages',
  41. message.toMap(),
  42. conflictAlgorithm: ConflictAlgorithm.replace,
  43. );
  44. String sessionCookie = await getSessionCookie();
  45. message.payloadJson(conversation, messageId)
  46. .then((messageJson) async {
  47. return http.post(
  48. await MyProfile.getServerUrl('api/v1/auth/message'),
  49. headers: <String, String>{
  50. 'Content-Type': 'application/json; charset=UTF-8',
  51. 'cookie': sessionCookie,
  52. },
  53. body: messageJson,
  54. );
  55. })
  56. .then((resp) {
  57. if (resp.statusCode != 200) {
  58. throw Exception('Unable to send message');
  59. }
  60. })
  61. .catchError((exception) {
  62. message.failedToSend = true;
  63. db.update(
  64. 'messages',
  65. message.toMap(),
  66. where: 'id = ?',
  67. whereArgs: [message.id],
  68. );
  69. throw exception;
  70. });
  71. }
  72. Future<void> updateMessageThread(Conversation conversation, {MyProfile? profile}) async {
  73. profile ??= await MyProfile.getProfile();
  74. ConversationUser currentUser = await getConversationUser(conversation, profile.id);
  75. var resp = await http.get(
  76. await MyProfile.getServerUrl('api/v1/auth/messages/${currentUser.associationKey}'),
  77. headers: {
  78. 'cookie': await getSessionCookie(),
  79. }
  80. );
  81. if (resp.statusCode != 200) {
  82. throw Exception(resp.body);
  83. }
  84. List<dynamic> messageThreadJson = jsonDecode(resp.body);
  85. final db = await getDatabaseConnection();
  86. for (var i = 0; i < messageThreadJson.length; i++) {
  87. var message = TextMessage.fromJson(
  88. messageThreadJson[i] as Map<String, dynamic>,
  89. profile.privateKey!,
  90. );
  91. ConversationUser messageUser = await getConversationUser(conversation, message.senderId);
  92. message.senderUsername = messageUser.username;
  93. await db.insert(
  94. 'messages',
  95. message.toMap(),
  96. conflictAlgorithm: ConflictAlgorithm.replace,
  97. );
  98. }
  99. }
  100. Future<void> updateMessageThreads({List<Conversation>? conversations}) async {
  101. // try {
  102. MyProfile profile = await MyProfile.getProfile();
  103. conversations ??= await getConversations();
  104. for (var i = 0; i < conversations.length; i++) {
  105. await updateMessageThread(conversations[i], profile: profile);
  106. }
  107. // } catch(SocketException) {
  108. // return;
  109. // }
  110. }