Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature room bot can be removed after disconnection #4

Merged
merged 20 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2554,7 +2554,7 @@
"youDonTHaveConversation": "You don't have any conversation yet.",
"connectChatNetworks": "Connect your chat networks",
"addSocialMessagingAccounts": "Add your social messaging accounts",
"addSocialMessagingAccountsText": "Connect all your conversation!",
"addSocialMessagingAccountsText": "Connect all your conversations!",
"connected": "Connected",
"notConnected": "Not connected",
"connectYourSocialAccount": "Login to your account",
Expand All @@ -2567,6 +2567,7 @@
"err_desc": "An error has occurred:",
"err_toConnect": "A problem occurred when connecting to",
"err_timeOut": "A network problem has been detected",
"err_tryAgain": "Please try again",
"bridgeBot_menuItemTitle" : "Connected social networks",
"bridgeBot_deleteConvTitle": "Delete Conversation",
"bridgeBot_deleteConvDescription": "Do you want to delete the conversation with the bot?",
Expand Down
61 changes: 44 additions & 17 deletions lib/pages/add_bridge/add_bridge_body.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:fluffychat/pages/add_bridge/service/bot_bridge_connection.dart';
import 'package:fluffychat/pages/add_bridge/service/hostname.dart';
import 'package:fluffychat/pages/add_bridge/show_bottom_sheet.dart';
import 'package:fluffychat/pages/add_bridge/show_delete_conversation_dialog.dart';
import 'package:fluffychat/utils/platform_infos.dart';
Expand All @@ -27,40 +28,66 @@ class AddBridgeBody extends StatefulWidget {

class _AddBridgeBodyState extends State<AddBridgeBody> {
late BotBridgeConnection botConnection;

late String hostname;
bool timeoutErrorOccurred = false;

@override
void initState() {
final client = Matrix.of(context).client;
botConnection = BotBridgeConnection(client: client);
String fullUrl = client.homeserver!.host;
hostname = extractHostName(fullUrl);
botConnection = BotBridgeConnection(client: client, hostname: hostname);
super.initState();
_initStateAsync();
}

// Online status update when page is opened
@override
void dispose() {
botConnection.stopProcess();
super.dispose();
}

// Online status update when page is opened
Future<void> _initStateAsync() async {
try {
final instagramConnected = await botConnection.pingWithTimeout(
context, botConnection.instagramPing());
setState(() {
socialNetwork
.firstWhere((element) => element.name == "Instagram")
.connected = instagramConnected;
socialNetwork
.firstWhere((element) => element.name == "Instagram")
.loading = false;
});
context,
botConnection.instagramPing(),
);
if (!mounted) return; // Check if the widget is still mounted

if (instagramConnected != 'error') {
setState(() {
socialNetwork
.firstWhere((element) => element.name == "Instagram")
.connected = instagramConnected == 'Connected' ? true : false;
socialNetwork
.firstWhere((element) => element.name == "Instagram")
.loading = false;
});
} else {
ignyx marked this conversation as resolved.
Show resolved Hide resolved
if (mounted) {
showCatchErrorDialog(
context,
"${L10n.of(context)!.err_toConnect} ${L10n.of(context)!.instagram}",
);
}
}
} on TimeoutException {
// To indicate that the time-out error has occurred
timeoutErrorOccurred = true;
if (mounted) {
timeoutErrorOccurred = true;
}
} catch (error) {
print("Error pinging Instagram: $error");
await Future.delayed(
const Duration(seconds: 1)); // Precaution to let the page load
if (!timeoutErrorOccurred) {
showCatchErrorDialog(context,
"${L10n.of(context)!.err_toConnect} ${L10n.of(context)!.instagram}");
const Duration(seconds: 1),
); // Precaution to let the page load
if (mounted && !timeoutErrorOccurred) {
showCatchErrorDialog(
context,
"${L10n.of(context)!.err_toConnect} ${L10n.of(context)!.instagram}",
);
}
}
}
Expand Down
18 changes: 15 additions & 3 deletions lib/pages/add_bridge/connection_bridge_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,15 @@ Future<bool> connectToInstagram(BuildContext context, SocialNetwork network,
await showFutureLoadingDialog(
context: context,
future: () async {
if (network.name == "Instagram") {
result = await botConnection.createBridgeInstagram(
username!, password!);
switch (network.name) {
case "Instagram":
result =
await botConnection.createBridgeInstagram(
username!,
password!,
);
break;
// Other network
}
},
);
Expand All @@ -116,6 +122,12 @@ Future<bool> connectToInstagram(BuildContext context, SocialNetwork network,
} else if (result == "rateLimitError") {
// Display a showDialog with an error message related to the rate limit
showRateLimitDialog(context);
} else if (result == "error") {
// Display a showDialog with an unknown error message
showCatchErrorDialog(
context,
L10n.of(context)!.err_tryAgain,
);
}
ignyx marked this conversation as resolved.
Show resolved Hide resolved
} catch (e) {
Navigator.of(context).pop();
Expand Down
3 changes: 3 additions & 0 deletions lib/pages/add_bridge/error_message_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ void showCatchErrorDialog(BuildContext context, Object e) {
return AlertDialog(
title: Text(
L10n.of(context)!.err_,
style: const TextStyle(
color: Colors.red,
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
Expand Down
6 changes: 3 additions & 3 deletions lib/pages/add_bridge/model/social_network.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ final List<SocialNetwork> socialNetwork = [
SocialNetwork(
logo: Logo(Logos.facebook_messenger),
name: "Facebook Messenger",
chatBot: "",
chatBot: "@facebookbot:",
),
SocialNetwork(
logo: Logo(Logos.instagram),
name: "Instagram",
chatBot: "@instagrambot:loveto.party",
chatBot: "@instagrambot:",
),
SocialNetwork(
logo: Logo(Logos.whatsapp),
name: "Whatsapp",
chatBot: "@whatsappbot:loveto.party",
chatBot: "@whatsappbot:",
),
];

Expand Down
82 changes: 65 additions & 17 deletions lib/pages/add_bridge/service/bot_bridge_connection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:matrix/matrix.dart';
import 'package:uuid/uuid.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';

import '../error_message_dialog.dart';
Expand All @@ -11,14 +10,22 @@ import '../error_message_dialog.dart';
// For the moment, rooms are DirectChat
class BotBridgeConnection {
Client client;
String hostname;
bool continueProcess = true;

BotBridgeConnection({
required this.client,
required this.hostname,
});

// To stop loops (when leaving the page)
void stopProcess() {
continueProcess = false;
}

// Ping to find out if we're connected to Instagram
Future<bool> instagramPing() async {
const String botUserId = '@instagrambot:loveto.party';
Future<String> instagramPing() async {
final String botUserId = '@instagrambot:$hostname';

// Message to spot when we're online
final RegExp onlineMatch = RegExp(r"MQTT connection is active");
Expand All @@ -35,13 +42,17 @@ class BotBridgeConnection {

final Room? roomBot = client.getRoomById(directChat);

bool result = false; // Variable to track the result of the connection
String result = ''; // Variable to track the result of the connection

// variable for loop limit
const int maxIterations = 5;
int currentIteration = 0;

// Get the latest messages from the room (limited to the specified number)
while (true) {
while (continueProcess && currentIteration < maxIterations) {
// Send the "ping" message to the bot
await roomBot?.sendTextEvent("ping");
await Future.delayed(const Duration(seconds: 2)); // Wait 2 sec
await Future.delayed(const Duration(seconds: 2)); // Wait sec

// To take latest message
final GetRoomEventsResponse response = await client.getRoomEvents(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to own function, like getLastEvent

Expand All @@ -62,23 +73,35 @@ class BotBridgeConnection {
successfullyMatch.hasMatch(latestMessage)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move logic to own function, maybe isInstagramMessageConnected

print("You're logged");

result = true;
result = 'Connected';

break; // Exit the loop if bridge is connected
} else if (notLoggedMatch.hasMatch(latestMessage) ||
disconnectMatch.hasMatch(latestMessage)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move logic to own function

print('Not connected');

result = 'Not Connected';
break; // Exit the loop if bridge is disconnected
}
}
currentIteration++;
}

if (currentIteration == maxIterations) {
print("Maximum iterations reached, setting result to 'error'");

result = 'error';
} else if (!continueProcess) {
print(('ping stoping'));
result = 'stop';
}

return result;
}

// Function for create and login bridge with bot
Future<String> createBridgeInstagram(String username, String password) async {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comments apply here

const String botUserId = '@instagrambot:loveto.party';
final String botUserId = '@instagrambot:$hostname';

// Success phrases to spot
final RegExp successMatch = RegExp(r"Successfully logged in");
Expand All @@ -98,8 +121,12 @@ class BotBridgeConnection {

String result = ""; // Variable to track the result of the connection

// variable for loop limit
const int maxIterations = 5;
int currentIteration = 0;

// Get the latest messages from the room (limited to the specified number)
while (true) {
while (currentIteration < maxIterations) {
// Send the "login" message to the bot
await roomBot?.sendTextEvent("login $username $password");
await Future.delayed(const Duration(seconds: 5)); // Wait 5 sec
Expand Down Expand Up @@ -143,13 +170,21 @@ class BotBridgeConnection {
break;
}
}
currentIteration++;
}

if (currentIteration == maxIterations) {
print("Maximum iterations reached, setting result to 'error'");

result = 'error';
}

return result;
}

// To disconnect from Instagram
Future<bool> disconnectToInstagram() async {
const String botUserId = '@instagrambot:loveto.party';
Future<String> disconnectToInstagram() async {
final String botUserId = '@instagrambot:$hostname';

final RegExp successMatch = RegExp(r"Successfully logged out");
final RegExp aldreadyLogoutMatch =
Expand All @@ -161,9 +196,14 @@ class BotBridgeConnection {

final Room? roomBot = client.getRoomById(directChat);

bool result = true; // Variable to track the result of the connection
String result =
"Connected"; // Variable to track the result of the connection

// variable for loop limit
const int maxIterations = 5;
int currentIteration = 0;

while (true) {
while (currentIteration < maxIterations) {
// Send the "logout" message to the bot
await roomBot?.sendTextEvent("logout");
await Future.delayed(const Duration(seconds: 5)); // Wait 5 sec
Expand All @@ -185,17 +225,25 @@ class BotBridgeConnection {
if (!successMatch.hasMatch(latestMessage) &&
!aldreadyLogoutMatch.hasMatch(latestMessage)) {
print("You're always connected");
result = true;
result = 'Connected';
break;
} else if (successMatch.hasMatch(latestMessage) ||
aldreadyLogoutMatch.hasMatch(latestMessage)) {
print("You're disconnected");

result = false;
result = 'Not Connected';
break; // Exit the loop if bridge is connected
}
}
currentIteration++;
}

if (currentIteration == maxIterations) {
print("Maximum iterations reached, setting result to 'error'");

result = 'error';
}

return result;
}

Expand All @@ -216,8 +264,8 @@ class BotBridgeConnection {
}

// Function to manage missed deadlines
Future<bool> pingWithTimeout(
BuildContext context, Future<bool> pingFunction) async {
Future<String> pingWithTimeout(
BuildContext context, Future<String> pingFunction) async {
try {
// Future.timeout to define a maximum waiting time
return await pingFunction.timeout(const Duration(seconds: 15));
Expand Down
19 changes: 19 additions & 0 deletions lib/pages/add_bridge/service/hostname.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
String extractHostName(String fullUrl) {
const String prefixToRemove = "https://";
const String prefixToRemoveTwo = "matrix.";

// Check if the string begins with "https://".
if (fullUrl.startsWith(prefixToRemove)) {
// replaceFirst to remove the prefix
return fullUrl.replaceFirst(prefixToRemove, '');
}

// Check if the string begins with "matrix.".
if (fullUrl.startsWith(prefixToRemoveTwo)) {
// replaceFirst to remove the prefix
return fullUrl.replaceFirst(prefixToRemoveTwo, '');
}

// If the prefix is not found, the string remains unchanged.
return fullUrl;
}
Loading