feat(xep): Allow ignoring the discussion history

Also allow specifying the amount of stanzas of discussion history we
want.
This commit is contained in:
PapaTutuWawa 2023-09-22 19:23:35 +02:00
parent d4416c8a47
commit d7c13abde6
3 changed files with 105 additions and 13 deletions

View File

@ -58,7 +58,11 @@ void main(List<String> args) async {
Logger.root.info('Connected.');
// Join room
await connection.getManagerById<MUCManager>(mucManager)!.joinRoom(muc, nick);
await connection.getManagerById<MUCManager>(mucManager)!.joinRoom(
muc,
nick,
maxHistoryStanzas: 0,
);
final repl = Repl(prompt: '> ');
await for (final line in repl.runAsync()) {

View File

@ -34,10 +34,25 @@ class RoomInformation {
}
class RoomState {
RoomState({
required this.roomJid,
this.nick,
});
RoomState({required this.roomJid, this.nick, required this.joined});
/// The JID of the room.
final JID roomJid;
/// The nick we're joined with.
String? nick;
/// Flag whether we're joined and can process messages
bool joined;
RoomState copyWith({
bool? joined,
String? nick,
}) {
return RoomState(
roomJid: roomJid,
joined: joined ?? this.joined,
nick: nick ?? this.nick,
);
}
}

View File

@ -1,6 +1,8 @@
import 'package:moxlib/moxlib.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/managers/data.dart';
import 'package:moxxmpp/src/managers/handlers.dart';
import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/stanza.dart';
@ -9,6 +11,7 @@ import 'package:moxxmpp/src/xeps/xep_0030/types.dart';
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
import 'package:moxxmpp/src/xeps/xep_0045/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0045/types.dart';
import 'package:synchronized/extension.dart';
import 'package:synchronized/synchronized.dart';
class MUCManager extends XmppManagerBase {
@ -23,6 +26,16 @@ class MUCManager extends XmppManagerBase {
/// Cache lock
final Lock _cacheLock = Lock();
@override
List<StanzaHandler> getIncomingStanzaHandlers() => [
StanzaHandler(
stanzaTag: 'message',
callback: _onMessage,
// Before the message handler
priority: -99,
)
];
/// Queries the information of a Multi-User Chat room.
///
/// Retrieves the information about the specified MUC room by performing a
@ -55,11 +68,23 @@ class MUCManager extends XmppManagerBase {
/// if applicable.
Future<Result<bool, MUCError>> joinRoom(
JID roomJid,
String nick,
) async {
String nick, {
int? maxHistoryStanzas,
}) async {
if (nick.isEmpty) {
return Result(NoNicknameSpecified());
}
await _cacheLock.synchronized(
() {
_mucRoomCache[roomJid] = RoomState(
roomJid: roomJid,
nick: nick,
joined: false,
);
},
);
await getAttributes().sendStanza(
StanzaDetails(
Stanza.presence(
@ -68,16 +93,20 @@ class MUCManager extends XmppManagerBase {
XMLNode.xmlns(
tag: 'x',
xmlns: mucXmlns,
)
children: [
if (maxHistoryStanzas != null)
XMLNode(
tag: 'history',
attributes: {
'maxstanzas': maxHistoryStanzas.toString(),
},
),
],
),
],
),
),
);
await _cacheLock.synchronized(
() {
_mucRoomCache[roomJid] = RoomState(roomJid: roomJid, nick: nick);
},
);
return const Result(true);
}
@ -108,4 +137,48 @@ class MUCManager extends XmppManagerBase {
);
return const Result(true);
}
Future<StanzaHandlerData> _onMessage(
Stanza message,
StanzaHandlerData state,
) async {
final roomJid = JID.fromString(message.from!).toBare();
return _mucRoomCache.synchronized(() {
final roomState = _mucRoomCache[roomJid];
if (roomState == null) {
return state;
}
if (message.type == 'groupchat' && message.firstTag('subject') != null) {
// The room subject marks the end of the join flow.
if (!roomState.joined) {
// Mark the room as joined.
_mucRoomCache[roomJid] = roomState.copyWith(joined: true);
logger.finest('$roomJid is now joined');
}
// TODO(Unknown): Signal the subject?
return StanzaHandlerData(
true,
false,
message,
state.extensions,
);
} else {
if (!roomState.joined) {
// Ignore the discussion history.
// TODO: Implement a copyWith method
return StanzaHandlerData(
true,
false,
message,
state.extensions,
);
}
}
return state;
});
}
}