Compare commits

..

4 Commits

Author SHA1 Message Date
edc86a10b3 feat: Implement parsing and sending of retractions 2022-11-20 23:43:58 +01:00
39e9c55fae chore(release): publish packages
- moxxmpp@0.1.3+1
 - moxxmpp_socket_tcp@0.1.2+5
2022-11-19 22:50:39 +01:00
1b2c567787 fix: Expose the error classes 2022-11-19 22:50:28 +01:00
d3955479f7 chore(release): publish packages
- moxxmpp@0.1.3
 - moxxmpp_socket_tcp@0.1.2+4
2022-11-19 22:32:56 +01:00
13 changed files with 173 additions and 15 deletions

View File

@ -16,10 +16,10 @@ dependencies:
version: 0.1.4+1 version: 0.1.4+1
moxxmpp: moxxmpp:
hosted: https://git.polynom.me/api/packages/Moxxy/pub hosted: https://git.polynom.me/api/packages/Moxxy/pub
version: 0.1.2+3 version: 0.1.3+1
moxxmpp_socket_tcp: moxxmpp_socket_tcp:
hosted: https://git.polynom.me/api/packages/Moxxy/pub hosted: https://git.polynom.me/api/packages/Moxxy/pub
version: 0.1.2+3 version: 0.1.2+5
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -1,3 +1,13 @@
## 0.1.3+1
- **FIX**: Expose the error classes.
## 0.1.3
- **REFACTOR**: Replace MayFail by Result.
- **FIX**: Remove the old Results API.
- **FEAT**: Rework how the negotiator system works.
## 0.1.2+3 ## 0.1.2+3
- **FIX**: SASL SCRAM-SHA-{256,512} should now work. - **FIX**: SASL SCRAM-SHA-{256,512} should now work.

View File

@ -1,6 +1,7 @@
library moxxmpp; library moxxmpp;
export 'package:moxxmpp/src/connection.dart'; export 'package:moxxmpp/src/connection.dart';
export 'package:moxxmpp/src/errors.dart';
export 'package:moxxmpp/src/events.dart'; export 'package:moxxmpp/src/events.dart';
export 'package:moxxmpp/src/iq.dart'; export 'package:moxxmpp/src/iq.dart';
export 'package:moxxmpp/src/jid.dart'; export 'package:moxxmpp/src/jid.dart';
@ -16,6 +17,7 @@ export 'package:moxxmpp/src/negotiators/manager.dart';
export 'package:moxxmpp/src/negotiators/namespaces.dart'; export 'package:moxxmpp/src/negotiators/namespaces.dart';
export 'package:moxxmpp/src/negotiators/negotiator.dart'; export 'package:moxxmpp/src/negotiators/negotiator.dart';
export 'package:moxxmpp/src/negotiators/resource_binding.dart'; export 'package:moxxmpp/src/negotiators/resource_binding.dart';
export 'package:moxxmpp/src/negotiators/sasl/errors.dart';
export 'package:moxxmpp/src/negotiators/sasl/negotiator.dart'; export 'package:moxxmpp/src/negotiators/sasl/negotiator.dart';
export 'package:moxxmpp/src/negotiators/sasl/plain.dart'; export 'package:moxxmpp/src/negotiators/sasl/plain.dart';
export 'package:moxxmpp/src/negotiators/sasl/scram.dart'; export 'package:moxxmpp/src/negotiators/sasl/scram.dart';
@ -71,6 +73,7 @@ export 'package:moxxmpp/src/xeps/xep_0384/types.dart';
export 'package:moxxmpp/src/xeps/xep_0384/xep_0384.dart'; export 'package:moxxmpp/src/xeps/xep_0384/xep_0384.dart';
export 'package:moxxmpp/src/xeps/xep_0385.dart'; export 'package:moxxmpp/src/xeps/xep_0385.dart';
export 'package:moxxmpp/src/xeps/xep_0414.dart'; export 'package:moxxmpp/src/xeps/xep_0414.dart';
export 'package:moxxmpp/src/xeps/xep_0424.dart';
export 'package:moxxmpp/src/xeps/xep_0446.dart'; export 'package:moxxmpp/src/xeps/xep_0446.dart';
export 'package:moxxmpp/src/xeps/xep_0447.dart'; export 'package:moxxmpp/src/xeps/xep_0447.dart';
export 'package:moxxmpp/src/xeps/xep_0448.dart'; export 'package:moxxmpp/src/xeps/xep_0448.dart';

View File

@ -8,6 +8,7 @@ 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_0359.dart'; import 'package:moxxmpp/src/xeps/xep_0359.dart';
import 'package:moxxmpp/src/xeps/xep_0385.dart'; import 'package:moxxmpp/src/xeps/xep_0385.dart';
import 'package:moxxmpp/src/xeps/xep_0424.dart';
import 'package:moxxmpp/src/xeps/xep_0446.dart'; import 'package:moxxmpp/src/xeps/xep_0446.dart';
import 'package:moxxmpp/src/xeps/xep_0447.dart'; import 'package:moxxmpp/src/xeps/xep_0447.dart';
import 'package:moxxmpp/src/xeps/xep_0461.dart'; import 'package:moxxmpp/src/xeps/xep_0461.dart';
@ -71,6 +72,7 @@ class MessageEvent extends XmppEvent {
this.fun, this.fun,
this.funReplacement, this.funReplacement,
this.funCancellation, this.funCancellation,
this.messageRetraction,
}); });
final String body; final String body;
final JID fromJid; final JID fromJid;
@ -90,6 +92,7 @@ class MessageEvent extends XmppEvent {
final String? funReplacement; final String? funReplacement;
final String? funCancellation; final String? funCancellation;
final bool encrypted; final bool encrypted;
final MessageRetractionData? messageRetraction;
final Map<String, dynamic> other; final Map<String, dynamic> other;
} }

View File

@ -6,6 +6,7 @@ import 'package:moxxmpp/src/xeps/xep_0203.dart';
import 'package:moxxmpp/src/xeps/xep_0359.dart'; import 'package:moxxmpp/src/xeps/xep_0359.dart';
import 'package:moxxmpp/src/xeps/xep_0380.dart'; import 'package:moxxmpp/src/xeps/xep_0380.dart';
import 'package:moxxmpp/src/xeps/xep_0385.dart'; import 'package:moxxmpp/src/xeps/xep_0385.dart';
import 'package:moxxmpp/src/xeps/xep_0424.dart';
import 'package:moxxmpp/src/xeps/xep_0446.dart'; import 'package:moxxmpp/src/xeps/xep_0446.dart';
import 'package:moxxmpp/src/xeps/xep_0447.dart'; import 'package:moxxmpp/src/xeps/xep_0447.dart';
import 'package:moxxmpp/src/xeps/xep_0461.dart'; import 'package:moxxmpp/src/xeps/xep_0461.dart';
@ -55,6 +56,9 @@ class StanzaHandlerData with _$StanzaHandlerData {
// This is for stanza handlers that are not part of the XMPP library but still need // This is for stanza handlers that are not part of the XMPP library but still need
// pass data around. // pass data around.
@Default(<String, dynamic>{}) Map<String, dynamic> other, @Default(<String, dynamic>{}) Map<String, dynamic> other,
// If non-null, then it indicates the origin Id of the message that should be
// retracted
MessageRetractionData? messageRetraction,
} }
) = _StanzaHandlerData; ) = _StanzaHandlerData;
} }

View File

@ -54,7 +54,11 @@ mixin _$StanzaHandlerData {
DelayedDelivery? get delayedDelivery => DelayedDelivery? get delayedDelivery =>
throw _privateConstructorUsedError; // This is for stanza handlers that are not part of the XMPP library but still need throw _privateConstructorUsedError; // This is for stanza handlers that are not part of the XMPP library but still need
// pass data around. // pass data around.
Map<String, dynamic> get other => throw _privateConstructorUsedError; Map<String, dynamic> get other =>
throw _privateConstructorUsedError; // If non-null, then it indicates the origin Id of the message that should be
// retracted
MessageRetractionData? get messageRetraction =>
throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
$StanzaHandlerDataCopyWith<StanzaHandlerData> get copyWith => $StanzaHandlerDataCopyWith<StanzaHandlerData> get copyWith =>
@ -87,7 +91,8 @@ abstract class $StanzaHandlerDataCopyWith<$Res> {
bool encrypted, bool encrypted,
ExplicitEncryptionType? encryptionType, ExplicitEncryptionType? encryptionType,
DelayedDelivery? delayedDelivery, DelayedDelivery? delayedDelivery,
Map<String, dynamic> other}); Map<String, dynamic> other,
MessageRetractionData? messageRetraction});
} }
/// @nodoc /// @nodoc
@ -122,6 +127,7 @@ class _$StanzaHandlerDataCopyWithImpl<$Res>
Object? encryptionType = freezed, Object? encryptionType = freezed,
Object? delayedDelivery = freezed, Object? delayedDelivery = freezed,
Object? other = freezed, Object? other = freezed,
Object? messageRetraction = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
done: done == freezed done: done == freezed
@ -208,6 +214,10 @@ class _$StanzaHandlerDataCopyWithImpl<$Res>
? _value.other ? _value.other
: other // ignore: cast_nullable_to_non_nullable : other // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>, as Map<String, dynamic>,
messageRetraction: messageRetraction == freezed
? _value.messageRetraction
: messageRetraction // ignore: cast_nullable_to_non_nullable
as MessageRetractionData?,
)); ));
} }
} }
@ -240,7 +250,8 @@ abstract class _$$_StanzaHandlerDataCopyWith<$Res>
bool encrypted, bool encrypted,
ExplicitEncryptionType? encryptionType, ExplicitEncryptionType? encryptionType,
DelayedDelivery? delayedDelivery, DelayedDelivery? delayedDelivery,
Map<String, dynamic> other}); Map<String, dynamic> other,
MessageRetractionData? messageRetraction});
} }
/// @nodoc /// @nodoc
@ -277,6 +288,7 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res>
Object? encryptionType = freezed, Object? encryptionType = freezed,
Object? delayedDelivery = freezed, Object? delayedDelivery = freezed,
Object? other = freezed, Object? other = freezed,
Object? messageRetraction = freezed,
}) { }) {
return _then(_$_StanzaHandlerData( return _then(_$_StanzaHandlerData(
done == freezed done == freezed
@ -363,6 +375,10 @@ class __$$_StanzaHandlerDataCopyWithImpl<$Res>
? _value._other ? _value._other
: other // ignore: cast_nullable_to_non_nullable : other // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>, as Map<String, dynamic>,
messageRetraction: messageRetraction == freezed
? _value.messageRetraction
: messageRetraction // ignore: cast_nullable_to_non_nullable
as MessageRetractionData?,
)); ));
} }
} }
@ -387,7 +403,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
this.encrypted = false, this.encrypted = false,
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})
: _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
@ -463,9 +480,14 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
return EqualUnmodifiableMapView(_other); return EqualUnmodifiableMapView(_other);
} }
// If non-null, then it indicates the origin Id of the message that should be
// retracted
@override
final MessageRetractionData? messageRetraction;
@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)'; 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)';
} }
@override @override
@ -501,7 +523,9 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
.equals(other.encryptionType, encryptionType) && .equals(other.encryptionType, encryptionType) &&
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other.delayedDelivery, delayedDelivery) && .equals(other.delayedDelivery, delayedDelivery) &&
const DeepCollectionEquality().equals(other._other, this._other)); const DeepCollectionEquality().equals(other._other, this._other) &&
const DeepCollectionEquality()
.equals(other.messageRetraction, messageRetraction));
} }
@override @override
@ -527,7 +551,8 @@ class _$_StanzaHandlerData implements _StanzaHandlerData {
const DeepCollectionEquality().hash(encrypted), const DeepCollectionEquality().hash(encrypted),
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)
]); ]);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@ -556,7 +581,8 @@ abstract class _StanzaHandlerData implements StanzaHandlerData {
final bool encrypted, final bool encrypted,
final ExplicitEncryptionType? encryptionType, final ExplicitEncryptionType? encryptionType,
final DelayedDelivery? delayedDelivery, final DelayedDelivery? delayedDelivery,
final Map<String, dynamic> other}) = _$_StanzaHandlerData; final Map<String, dynamic> other,
final MessageRetractionData? messageRetraction}) = _$_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.
@ -606,6 +632,9 @@ abstract class _StanzaHandlerData implements StanzaHandlerData {
@override // This is for stanza handlers that are not part of the XMPP library but still need @override // This is for stanza handlers that are not part of the XMPP library but still need
// pass data around. // pass data around.
Map<String, dynamic> get other; Map<String, dynamic> get other;
@override // If non-null, then it indicates the origin Id of the message that should be
// retracted
MessageRetractionData? get messageRetraction;
@override @override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$_StanzaHandlerDataCopyWith<_$_StanzaHandlerData> get copyWith => _$$_StanzaHandlerDataCopyWith<_$_StanzaHandlerData> get copyWith =>

View File

@ -24,3 +24,4 @@ const omemoManager = 'org.moxxmpp.omemomanager';
const emeManager = 'org.moxxmpp.ememanager'; 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';

View File

@ -13,12 +13,12 @@ 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_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_0446.dart'; import 'package:moxxmpp/src/xeps/xep_0446.dart';
import 'package:moxxmpp/src/xeps/xep_0447.dart'; import 'package:moxxmpp/src/xeps/xep_0447.dart';
import 'package:moxxmpp/src/xeps/xep_0448.dart'; import 'package:moxxmpp/src/xeps/xep_0448.dart';
class MessageDetails { class MessageDetails {
const MessageDetails({ const MessageDetails({
required this.to, required this.to,
this.body, this.body,
@ -35,6 +35,7 @@ class MessageDetails {
this.funReplacement, this.funReplacement,
this.funCancellation, this.funCancellation,
this.shouldEncrypt = false, this.shouldEncrypt = false,
this.messageRetraction,
}); });
final String to; final String to;
final String? body; final String? body;
@ -51,6 +52,7 @@ class MessageDetails {
final String? funReplacement; final String? funReplacement;
final String? funCancellation; final String? funCancellation;
final bool shouldEncrypt; final bool shouldEncrypt;
final MessageRetractionData? messageRetraction;
} }
class MessageManager extends XmppManagerBase { class MessageManager extends XmppManagerBase {
@ -95,6 +97,7 @@ class MessageManager extends XmppManagerBase {
funReplacement: state.funReplacement, funReplacement: state.funReplacement,
funCancellation: state.funCancellation, funCancellation: state.funCancellation,
encrypted: state.encrypted, encrypted: state.encrypted,
messageRetraction: state.messageRetraction,
other: state.other, other: state.other,
),); ),);
@ -159,6 +162,8 @@ class MessageManager extends XmppManagerBase {
} else if (firstSource is StatelessFileSharingEncryptedSource) { } else if (firstSource is StatelessFileSharingEncryptedSource) {
body = firstSource.source.url; body = firstSource.source.url;
} }
} else if (details.messageRetraction?.fallback != null) {
body = details.messageRetraction!.fallback;
} }
stanza.addChild( stanza.addChild(
@ -217,6 +222,33 @@ class MessageManager extends XmppManagerBase {
); );
} }
if (details.messageRetraction != null) {
stanza.addChild(
XMLNode.xmlns(
tag: 'apply-to',
xmlns: fasteningXmlns,
attributes: <String, String>{
'id': details.messageRetraction!.id,
},
children: [
XMLNode.xmlns(
tag: 'retract',
xmlns: messageRetractionXmlns,
),
],
),
);
if (details.messageRetraction!.fallback != null) {
stanza.addChild(
XMLNode.xmlns(
tag: 'fallback',
xmlns: fallbackIndicationXmlns,
),
);
}
}
getAttributes().sendStanza(stanza, awaitable: false); getAttributes().sendStanza(stanza, awaitable: false);
} }
} }

View File

@ -114,6 +114,15 @@ const simsXmlns = 'urn:xmpp:sims:1';
// XEP-0420 // XEP-0420
const sceXmlns = 'urn:xmpp:sce:1'; const sceXmlns = 'urn:xmpp:sce:1';
// XEP-0422
const fasteningXmlns = 'urn:xmpp:fasten:0';
// XEP-0424
const messageRetractionXmlns = 'urn:xmpp:message-retract:0';
// XEp-0428
const fallbackIndicationXmlns = 'urn:xmpp:fallback:0';
// XEP-0446 // XEP-0446
const fileMetadataXmlns = 'urn:xmpp:file:metadata:0'; const fileMetadataXmlns = 'urn:xmpp:file:metadata:0';

View File

@ -0,0 +1,59 @@
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';
class MessageRetractionData {
MessageRetractionData(this.id, this.fallback);
final String? fallback;
final String id;
}
class MessageRetractionManager extends XmppManagerBase {
@override
String getName() => 'MessageRetractionManager';
@override
String getId() => messageRetractionManager;
@override
List<String> getDiscoFeatures() => [ messageRetractionXmlns ];
@override
List<StanzaHandler> getIncomingStanzaHandlers() => [
StanzaHandler(
stanzaTag: 'message',
callback: _onMessage,
// Before the MessageManager
priority: -99,
)
];
@override
Future<bool> isSupported() async => true;
Future<StanzaHandlerData> _onMessage(Stanza message, StanzaHandlerData state) async {
final applyTo = message.firstTag('apply-to', xmlns: fasteningXmlns);
if (applyTo == null) {
return state;
}
final retract = applyTo.firstTag('retract', xmlns: messageRetractionXmlns);
if (retract == null) {
return state;
}
final isFallbackBody = message.firstTag('fallback', xmlns: fallbackIndicationXmlns) != null;
return state.copyWith(
messageRetraction: MessageRetractionData(
applyTo.attributes['id']! as String,
isFallbackBody ?
message.firstTag('body')?.innerText() :
null,
),
);
}
}

View File

@ -1,6 +1,6 @@
name: moxxmpp name: moxxmpp
description: A pure-Dart XMPP library description: A pure-Dart XMPP library
version: 0.1.2+3 version: 0.1.3+1
homepage: https://codeberg.org/moxxy/moxxmpp homepage: https://codeberg.org/moxxy/moxxmpp
publish_to: https://git.polynom.me/api/packages/Moxxy/pub publish_to: https://git.polynom.me/api/packages/Moxxy/pub
@ -31,6 +31,6 @@ dev_dependencies:
build_runner: ^2.1.11 build_runner: ^2.1.11
moxxmpp_socket_tcp: moxxmpp_socket_tcp:
hosted: https://git.polynom.me/api/packages/Moxxy/pub hosted: https://git.polynom.me/api/packages/Moxxy/pub
version: ^0.1.2+3 version: ^0.1.2+5
test: ^1.16.0 test: ^1.16.0
very_good_analysis: ^3.0.1 very_good_analysis: ^3.0.1

View File

@ -1,3 +1,11 @@
## 0.1.2+5
- Update a dependency to the latest release.
## 0.1.2+4
- Update a dependency to the latest release.
## 0.1.2+3 ## 0.1.2+3
- Update a dependency to the latest release. - Update a dependency to the latest release.

View File

@ -1,6 +1,6 @@
name: moxxmpp_socket_tcp name: moxxmpp_socket_tcp
description: A socket for moxxmpp using TCP that implements the RFC6120 connection algorithm and XEP-0368 description: A socket for moxxmpp using TCP that implements the RFC6120 connection algorithm and XEP-0368
version: 0.1.2+3 version: 0.1.2+5
homepage: https://codeberg.org/moxxy/moxxmpp homepage: https://codeberg.org/moxxy/moxxmpp
publish_to: https://git.polynom.me/api/packages/Moxxy/pub publish_to: https://git.polynom.me/api/packages/Moxxy/pub
@ -12,7 +12,7 @@ dependencies:
meta: ^1.6.0 meta: ^1.6.0
moxxmpp: moxxmpp:
hosted: https://git.polynom.me/api/packages/Moxxy/pub hosted: https://git.polynom.me/api/packages/Moxxy/pub
version: ^0.1.2+3 version: ^0.1.3+1
dev_dependencies: dev_dependencies:
lints: ^2.0.0 lints: ^2.0.0