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.

121 lines
3.4 KiB

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