feat: Implement XEP-0308
This commit is contained in:
parent
138edffb0a
commit
14c48bcc64
@ -74,6 +74,7 @@ class MessageEvent extends XmppEvent {
|
|||||||
this.funReplacement,
|
this.funReplacement,
|
||||||
this.funCancellation,
|
this.funCancellation,
|
||||||
this.messageRetraction,
|
this.messageRetraction,
|
||||||
|
this.messageCorrectionId,
|
||||||
});
|
});
|
||||||
final StanzaError? error;
|
final StanzaError? error;
|
||||||
final String body;
|
final String body;
|
||||||
@ -95,6 +96,7 @@ class MessageEvent extends XmppEvent {
|
|||||||
final String? funCancellation;
|
final String? funCancellation;
|
||||||
final bool encrypted;
|
final bool encrypted;
|
||||||
final MessageRetractionData? messageRetraction;
|
final MessageRetractionData? messageRetraction;
|
||||||
|
final String? messageCorrectionId;
|
||||||
final Map<String, dynamic> other;
|
final Map<String, dynamic> other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ class StanzaHandlerData with _$StanzaHandlerData {
|
|||||||
// If non-null, then it indicates the origin Id of the message that should be
|
// If non-null, then it indicates the origin Id of the message that should be
|
||||||
// retracted
|
// retracted
|
||||||
MessageRetractionData? messageRetraction,
|
MessageRetractionData? messageRetraction,
|
||||||
|
// If non-null, then the message is a correction for the specified stanza Id
|
||||||
|
String? lastMessageCorrectionSid,
|
||||||
}
|
}
|
||||||
) = _StanzaHandlerData;
|
) = _StanzaHandlerData;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,8 @@ mixin _$StanzaHandlerData {
|
|||||||
throw _privateConstructorUsedError; // If non-null, then it indicates the origin Id of the message that should be
|
throw _privateConstructorUsedError; // If non-null, then it indicates the origin Id of the message that should be
|
||||||
// retracted
|
// retracted
|
||||||
MessageRetractionData? get messageRetraction =>
|
MessageRetractionData? get messageRetraction =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError; // If non-null, then the message is a correction for the specified stanza Id
|
||||||
|
String? get lastMessageCorrectionSid => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
$StanzaHandlerDataCopyWith<StanzaHandlerData> get copyWith =>
|
$StanzaHandlerDataCopyWith<StanzaHandlerData> get copyWith =>
|
||||||
@ -92,7 +93,8 @@ abstract class $StanzaHandlerDataCopyWith<$Res> {
|
|||||||
ExplicitEncryptionType? encryptionType,
|
ExplicitEncryptionType? encryptionType,
|
||||||
DelayedDelivery? delayedDelivery,
|
DelayedDelivery? delayedDelivery,
|
||||||
Map<String, dynamic> other,
|
Map<String, dynamic> other,
|
||||||
MessageRetractionData? messageRetraction});
|
MessageRetractionData? messageRetraction,
|
||||||
|
String? lastMessageCorrectionSid});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -128,6 +130,7 @@ class _$StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
Object? delayedDelivery = freezed,
|
Object? delayedDelivery = freezed,
|
||||||
Object? other = freezed,
|
Object? other = freezed,
|
||||||
Object? messageRetraction = freezed,
|
Object? messageRetraction = freezed,
|
||||||
|
Object? lastMessageCorrectionSid = freezed,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
done: done == freezed
|
done: done == freezed
|
||||||
@ -218,6 +221,10 @@ class _$StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
? _value.messageRetraction
|
? _value.messageRetraction
|
||||||
: messageRetraction // ignore: cast_nullable_to_non_nullable
|
: messageRetraction // ignore: cast_nullable_to_non_nullable
|
||||||
as MessageRetractionData?,
|
as MessageRetractionData?,
|
||||||
|
lastMessageCorrectionSid: lastMessageCorrectionSid == freezed
|
||||||
|
? _value.lastMessageCorrectionSid
|
||||||
|
: lastMessageCorrectionSid // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,7 +258,8 @@ abstract class _$$_StanzaHandlerDataCopyWith<$Res>
|
|||||||
ExplicitEncryptionType? encryptionType,
|
ExplicitEncryptionType? encryptionType,
|
||||||
DelayedDelivery? delayedDelivery,
|
DelayedDelivery? delayedDelivery,
|
||||||
Map<String, dynamic> other,
|
Map<String, dynamic> other,
|
||||||
MessageRetractionData? messageRetraction});
|
MessageRetractionData? messageRetraction,
|
||||||
|
String? lastMessageCorrectionSid});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -289,6 +297,7 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
Object? delayedDelivery = freezed,
|
Object? delayedDelivery = freezed,
|
||||||
Object? other = freezed,
|
Object? other = freezed,
|
||||||
Object? messageRetraction = freezed,
|
Object? messageRetraction = freezed,
|
||||||
|
Object? lastMessageCorrectionSid = freezed,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$_StanzaHandlerData(
|
return _then(_$_StanzaHandlerData(
|
||||||
done == freezed
|
done == freezed
|
||||||
@ -379,6 +388,10 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res>
|
|||||||
? _value.messageRetraction
|
? _value.messageRetraction
|
||||||
: messageRetraction // ignore: cast_nullable_to_non_nullable
|
: messageRetraction // ignore: cast_nullable_to_non_nullable
|
||||||
as MessageRetractionData?,
|
as MessageRetractionData?,
|
||||||
|
lastMessageCorrectionSid: lastMessageCorrectionSid == freezed
|
||||||
|
? _value.lastMessageCorrectionSid
|
||||||
|
: lastMessageCorrectionSid // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,7 +417,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
this.encryptionType,
|
this.encryptionType,
|
||||||
this.delayedDelivery,
|
this.delayedDelivery,
|
||||||
final Map<String, dynamic> other = const <String, dynamic>{},
|
final Map<String, dynamic> other = const <String, dynamic>{},
|
||||||
this.messageRetraction})
|
this.messageRetraction,
|
||||||
|
this.lastMessageCorrectionSid})
|
||||||
: _other = other;
|
: _other = other;
|
||||||
|
|
||||||
// Indicates to the runner that processing is now done. This means that all
|
// Indicates to the runner that processing is now done. This means that all
|
||||||
@ -484,10 +498,13 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
// retracted
|
// retracted
|
||||||
@override
|
@override
|
||||||
final MessageRetractionData? messageRetraction;
|
final MessageRetractionData? messageRetraction;
|
||||||
|
// If non-null, then the message is a correction for the specified stanza Id
|
||||||
|
@override
|
||||||
|
final String? lastMessageCorrectionSid;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'StanzaHandlerData(done: $done, cancel: $cancel, cancelReason: $cancelReason, stanza: $stanza, retransmitted: $retransmitted, sims: $sims, sfs: $sfs, oob: $oob, stableId: $stableId, reply: $reply, chatState: $chatState, isCarbon: $isCarbon, deliveryReceiptRequested: $deliveryReceiptRequested, isMarkable: $isMarkable, fun: $fun, funReplacement: $funReplacement, funCancellation: $funCancellation, encrypted: $encrypted, encryptionType: $encryptionType, delayedDelivery: $delayedDelivery, other: $other, messageRetraction: $messageRetraction)';
|
return 'StanzaHandlerData(done: $done, cancel: $cancel, cancelReason: $cancelReason, stanza: $stanza, retransmitted: $retransmitted, sims: $sims, sfs: $sfs, oob: $oob, stableId: $stableId, reply: $reply, chatState: $chatState, isCarbon: $isCarbon, deliveryReceiptRequested: $deliveryReceiptRequested, isMarkable: $isMarkable, fun: $fun, funReplacement: $funReplacement, funCancellation: $funCancellation, encrypted: $encrypted, encryptionType: $encryptionType, delayedDelivery: $delayedDelivery, other: $other, messageRetraction: $messageRetraction, lastMessageCorrectionSid: $lastMessageCorrectionSid)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -525,7 +542,9 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
.equals(other.delayedDelivery, delayedDelivery) &&
|
.equals(other.delayedDelivery, delayedDelivery) &&
|
||||||
const DeepCollectionEquality().equals(other._other, this._other) &&
|
const DeepCollectionEquality().equals(other._other, this._other) &&
|
||||||
const DeepCollectionEquality()
|
const DeepCollectionEquality()
|
||||||
.equals(other.messageRetraction, messageRetraction));
|
.equals(other.messageRetraction, messageRetraction) &&
|
||||||
|
const DeepCollectionEquality().equals(
|
||||||
|
other.lastMessageCorrectionSid, lastMessageCorrectionSid));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -552,7 +571,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
|
|||||||
const DeepCollectionEquality().hash(encryptionType),
|
const DeepCollectionEquality().hash(encryptionType),
|
||||||
const DeepCollectionEquality().hash(delayedDelivery),
|
const DeepCollectionEquality().hash(delayedDelivery),
|
||||||
const DeepCollectionEquality().hash(_other),
|
const DeepCollectionEquality().hash(_other),
|
||||||
const DeepCollectionEquality().hash(messageRetraction)
|
const DeepCollectionEquality().hash(messageRetraction),
|
||||||
|
const DeepCollectionEquality().hash(lastMessageCorrectionSid)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@ -582,7 +602,8 @@ abstract class _StanzaHandlerData implements StanzaHandlerData {
|
|||||||
final ExplicitEncryptionType? encryptionType,
|
final ExplicitEncryptionType? encryptionType,
|
||||||
final DelayedDelivery? delayedDelivery,
|
final DelayedDelivery? delayedDelivery,
|
||||||
final Map<String, dynamic> other,
|
final Map<String, dynamic> other,
|
||||||
final MessageRetractionData? messageRetraction}) = _$_StanzaHandlerData;
|
final MessageRetractionData? messageRetraction,
|
||||||
|
final String? lastMessageCorrectionSid}) = _$_StanzaHandlerData;
|
||||||
|
|
||||||
@override // Indicates to the runner that processing is now done. This means that all
|
@override // Indicates to the runner that processing is now done. This means that all
|
||||||
// pre-processing is done and no other handlers should be consulted.
|
// pre-processing is done and no other handlers should be consulted.
|
||||||
@ -635,6 +656,8 @@ abstract class _StanzaHandlerData implements StanzaHandlerData {
|
|||||||
@override // If non-null, then it indicates the origin Id of the message that should be
|
@override // If non-null, then it indicates the origin Id of the message that should be
|
||||||
// retracted
|
// retracted
|
||||||
MessageRetractionData? get messageRetraction;
|
MessageRetractionData? get messageRetraction;
|
||||||
|
@override // If non-null, then the message is a correction for the specified stanza Id
|
||||||
|
String? get lastMessageCorrectionSid;
|
||||||
@override
|
@override
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
_$$_StanzaHandlerDataCopyWith<_$_StanzaHandlerData> get copyWith =>
|
_$$_StanzaHandlerDataCopyWith<_$_StanzaHandlerData> get copyWith =>
|
||||||
|
@ -25,3 +25,4 @@ const emeManager = 'org.moxxmpp.ememanager';
|
|||||||
const cryptographicHashManager = 'org.moxxmpp.cryptographichashmanager';
|
const cryptographicHashManager = 'org.moxxmpp.cryptographichashmanager';
|
||||||
const delayedDeliveryManager = 'org.moxxmpp.delayeddeliverymanager';
|
const delayedDeliveryManager = 'org.moxxmpp.delayeddeliverymanager';
|
||||||
const messageRetractionManager = 'org.moxxmpp.messageretractionmanager';
|
const messageRetractionManager = 'org.moxxmpp.messageretractionmanager';
|
||||||
|
const lastMessageCorrectionManager = 'org.moxxmpp.lastmessagecorrectionmanager';
|
||||||
|
@ -11,6 +11,7 @@ import 'package:moxxmpp/src/xeps/staging/file_upload_notification.dart';
|
|||||||
import 'package:moxxmpp/src/xeps/xep_0066.dart';
|
import 'package:moxxmpp/src/xeps/xep_0066.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0085.dart';
|
import 'package:moxxmpp/src/xeps/xep_0085.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0184.dart';
|
import 'package:moxxmpp/src/xeps/xep_0184.dart';
|
||||||
|
import 'package:moxxmpp/src/xeps/xep_0308.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0333.dart';
|
import 'package:moxxmpp/src/xeps/xep_0333.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0359.dart';
|
import 'package:moxxmpp/src/xeps/xep_0359.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0424.dart';
|
import 'package:moxxmpp/src/xeps/xep_0424.dart';
|
||||||
@ -36,6 +37,7 @@ class MessageDetails {
|
|||||||
this.funCancellation,
|
this.funCancellation,
|
||||||
this.shouldEncrypt = false,
|
this.shouldEncrypt = false,
|
||||||
this.messageRetraction,
|
this.messageRetraction,
|
||||||
|
this.lastMessageCorrectionId,
|
||||||
});
|
});
|
||||||
final String to;
|
final String to;
|
||||||
final String? body;
|
final String? body;
|
||||||
@ -53,6 +55,7 @@ class MessageDetails {
|
|||||||
final String? funCancellation;
|
final String? funCancellation;
|
||||||
final bool shouldEncrypt;
|
final bool shouldEncrypt;
|
||||||
final MessageRetractionData? messageRetraction;
|
final MessageRetractionData? messageRetraction;
|
||||||
|
final String? lastMessageCorrectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageManager extends XmppManagerBase {
|
class MessageManager extends XmppManagerBase {
|
||||||
@ -98,6 +101,7 @@ class MessageManager extends XmppManagerBase {
|
|||||||
funCancellation: state.funCancellation,
|
funCancellation: state.funCancellation,
|
||||||
encrypted: state.encrypted,
|
encrypted: state.encrypted,
|
||||||
messageRetraction: state.messageRetraction,
|
messageRetraction: state.messageRetraction,
|
||||||
|
messageCorrectionId: state.lastMessageCorrectionSid,
|
||||||
other: state.other,
|
other: state.other,
|
||||||
error: StanzaError.fromStanza(message),
|
error: StanzaError.fromStanza(message),
|
||||||
),);
|
),);
|
||||||
@ -250,6 +254,14 @@ class MessageManager extends XmppManagerBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (details.lastMessageCorrectionId != null) {
|
||||||
|
stanza.addChild(
|
||||||
|
makeLastMessageCorrectionEdit(
|
||||||
|
details.lastMessageCorrectionId!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getAttributes().sendStanza(stanza, awaitable: false);
|
getAttributes().sendStanza(stanza, awaitable: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,9 @@ const hashSha3512 = 'sha3-512';
|
|||||||
const hashBlake2b256 = 'blake2b-256';
|
const hashBlake2b256 = 'blake2b-256';
|
||||||
const hashBlake2b512 = 'blake2b-512';
|
const hashBlake2b512 = 'blake2b-512';
|
||||||
|
|
||||||
|
// XEP-0308
|
||||||
|
const lmcXmlns = 'urn:xmpp:message-correct:0';
|
||||||
|
|
||||||
// XEP-0333
|
// XEP-0333
|
||||||
const chatMarkersXmlns = 'urn:xmpp:chat-markers:0';
|
const chatMarkersXmlns = 'urn:xmpp:chat-markers:0';
|
||||||
|
|
||||||
|
52
packages/moxxmpp/lib/src/xeps/xep_0308.dart
Normal file
52
packages/moxxmpp/lib/src/xeps/xep_0308.dart
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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';
|
||||||
|
import 'package:moxxmpp/src/stringxml.dart';
|
||||||
|
|
||||||
|
XMLNode makeLastMessageCorrectionEdit(String id) {
|
||||||
|
return XMLNode.xmlns(
|
||||||
|
tag: 'replace',
|
||||||
|
xmlns: lmcXmlns,
|
||||||
|
attributes: <String, String>{
|
||||||
|
'id': id,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LastMessageCorrectionManager extends XmppManagerBase {
|
||||||
|
@override
|
||||||
|
String getName() => 'LastMessageCorrectionManager';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String getId() => lastMessageCorrectionManager;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> getDiscoFeatures() => [ lmcXmlns ];
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<StanzaHandler> getIncomingStanzaHandlers() => [
|
||||||
|
StanzaHandler(
|
||||||
|
stanzaTag: 'message',
|
||||||
|
tagName: 'reply',
|
||||||
|
tagXmlns: replyXmlns,
|
||||||
|
callback: _onMessage,
|
||||||
|
// Before the message handler
|
||||||
|
priority: -99,
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> isSupported() async => true;
|
||||||
|
|
||||||
|
Future<StanzaHandlerData> _onMessage(Stanza stanza, StanzaHandlerData state) async {
|
||||||
|
final edit = stanza.firstTag('replace', xmlns: lmcXmlns);
|
||||||
|
if (edit == null) return state;
|
||||||
|
|
||||||
|
return state.copyWith(
|
||||||
|
lastMessageCorrectionSid: edit.attributes['id']! as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user