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.

124 lines
3.6 KiB

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