diff --git a/packages/moxxmpp/lib/src/managers/attributes.dart b/packages/moxxmpp/lib/src/managers/attributes.dart index 72360c1..7630940 100644 --- a/packages/moxxmpp/lib/src/managers/attributes.dart +++ b/packages/moxxmpp/lib/src/managers/attributes.dart @@ -1,5 +1,4 @@ import 'dart:async'; - import 'package:moxxmpp/src/connection.dart'; import 'package:moxxmpp/src/events.dart'; import 'package:moxxmpp/src/jid.dart'; @@ -11,7 +10,6 @@ import 'package:moxxmpp/src/stanza.dart'; import 'package:moxxmpp/src/stringxml.dart'; class XmppManagerAttributes { - XmppManagerAttributes({ required this.sendStanza, required this.sendNonza, diff --git a/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart b/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart index ed594e1..dcabd5e 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0030/xep_0030.dart @@ -289,7 +289,7 @@ class DiscoManager extends XmppManagerBase { } /// Sends a disco info query to the (full) jid [entity], optionally with node=[node]. - Future> discoInfoQuery(String entity, { String? node}) async { + Future> discoInfoQuery(String entity, { String? node, bool shouldEncrypt = true }) async { final cacheKey = DiscoCacheKey(entity, node); DiscoInfo? info; Completer>? completer; @@ -316,6 +316,7 @@ class DiscoManager extends XmppManagerBase { final stanza = await getAttributes().sendStanza( buildDiscoInfoQueryStanza(entity, node), + encrypted: !shouldEncrypt, ); final query = stanza.firstTag('query'); if (query == null) { @@ -359,9 +360,12 @@ class DiscoManager extends XmppManagerBase { } /// Sends a disco items query to the (full) jid [entity], optionally with node=[node]. - Future>> discoItemsQuery(String entity, { String? node }) async { + Future>> discoItemsQuery(String entity, { String? node, bool shouldEncrypt = true }) async { final stanza = await getAttributes() - .sendStanza(buildDiscoItemsQueryStanza(entity, node: node)) as Stanza; + .sendStanza( + buildDiscoItemsQueryStanza(entity, node: node), + encrypted: !shouldEncrypt, + ) as Stanza; final query = stanza.firstTag('query'); if (query == null) return Result(InvalidResponseDiscoError()); diff --git a/packages/moxxmpp/lib/src/xeps/xep_0054.dart b/packages/moxxmpp/lib/src/xeps/xep_0054.dart index 4723fed..464c2dc 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0054.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0054.dart @@ -7,15 +7,20 @@ 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'; +import 'package:moxxmpp/src/types/result.dart'; + +abstract class VCardError {} + +class UnknownVCardError extends VCardError {} + +class InvalidVCardError extends VCardError {} class VCardPhoto { - const VCardPhoto({ this.binval }); final String? binval; } class VCard { - const VCard({ this.nickname, this.url, this.photo }); final String? nickname; final String? url; @@ -23,7 +28,6 @@ class VCard { } class VCardManager extends XmppManagerBase { - VCardManager() : _lastHash = {}, super(); final Map _lastHash; @@ -59,12 +63,18 @@ class VCardManager extends XmppManagerBase { final lastHash = _lastHash[from]; if (lastHash != hash) { _lastHash[from] = hash; - final vcard = await requestVCard(from); + final vcardResult = await requestVCard(from); - if (vcard != null) { - final binval = vcard.photo?.binval; + if (vcardResult.isType()) { + final binval = vcardResult.get().photo?.binval; if (binval != null) { - getAttributes().sendEvent(AvatarUpdatedEvent(jid: from, base64: binval, hash: hash)); + getAttributes().sendEvent( + AvatarUpdatedEvent( + jid: from, + base64: binval, + hash: hash, + ), + ); } else { logger.warning('No avatar data found'); } @@ -95,7 +105,7 @@ class VCardManager extends XmppManagerBase { ); } - Future requestVCard(String jid) async { + Future> requestVCard(String jid) async { final result = await getAttributes().sendStanza( Stanza.iq( to: jid, @@ -107,12 +117,13 @@ class VCardManager extends XmppManagerBase { ) ], ), + encrypted: true, ); - if (result.attributes['type'] != 'result') return null; + if (result.attributes['type'] != 'result') return Result(UnknownVCardError()); final vcard = result.firstTag('vCard', xmlns: vCardTempXmlns); - if (vcard == null) return null; + if (vcard == null) return Result(UnknownVCardError()); - return _parseVCard(vcard); + return Result(_parseVCard(vcard)); } } diff --git a/packages/moxxmpp/lib/src/xeps/xep_0084.dart b/packages/moxxmpp/lib/src/xeps/xep_0084.dart index 959ae6f..657c099 100644 --- a/packages/moxxmpp/lib/src/xeps/xep_0084.dart +++ b/packages/moxxmpp/lib/src/xeps/xep_0084.dart @@ -3,21 +3,24 @@ import 'package:moxxmpp/src/managers/base.dart'; import 'package:moxxmpp/src/managers/namespaces.dart'; import 'package:moxxmpp/src/namespaces.dart'; import 'package:moxxmpp/src/stringxml.dart'; +import 'package:moxxmpp/src/types/result.dart'; import 'package:moxxmpp/src/xeps/xep_0030/errors.dart'; 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_0060/errors.dart'; import 'package:moxxmpp/src/xeps/xep_0060/xep_0060.dart'; -class UserAvatar { +abstract class AvatarError {} +class UnknownAvatarError extends AvatarError {} + +class UserAvatar { const UserAvatar({ required this.base64, required this.hash }); final String base64; final String hash; } class UserAvatarMetadata { - const UserAvatarMetadata( this.id, this.length, @@ -62,30 +65,30 @@ class UserAvatarManager extends XmppManagerBase { // TODO(PapaTutuWawa): Check for PEP support @override Future isSupported() async => true; - + /// Requests the avatar from [jid]. Returns the avatar data if the request was /// successful. Null otherwise - // TODO(Unknown): Migrate to Resultsv2 - Future getUserAvatar(String jid) async { + Future> getUserAvatar(String jid) async { final pubsub = _getPubSubManager(); final resultsRaw = await pubsub.getItems(jid, userAvatarDataXmlns); - if (resultsRaw.isType()) return null; + if (resultsRaw.isType()) return Result(UnknownAvatarError()); final results = resultsRaw.get>(); - if (results.isEmpty) return null; + if (results.isEmpty) return Result(UnknownAvatarError()); final item = results[0]; - return UserAvatar( - base64: item.payload.innerText(), - hash: item.id, + return Result( + UserAvatar( + base64: item.payload.innerText(), + hash: item.id, + ), ); } /// Publish the avatar data, [base64], on the pubsub node using [hash] as /// the item id. [hash] must be the SHA-1 hash of the image data, while /// [base64] must be the base64-encoded version of the image data. - // TODO(Unknown): Migrate to Resultsv2 - Future publishUserAvatar(String base64, String hash, bool public) async { + Future> publishUserAvatar(String base64, String hash, bool public) async { final pubsub = _getPubSubManager(); final result = await pubsub.publish( getAttributes().getFullJID().toBare().toString(), @@ -101,14 +104,15 @@ class UserAvatarManager extends XmppManagerBase { ), ); - return !result.isType(); + if (result.isType()) return Result(UnknownAvatarError()); + + return const Result(true); } /// Publish avatar metadata [metadata] to the User Avatar's metadata node. If [public] /// is true, then the node will be set to an 'open' access model. If [public] is false, /// then the node will be set to an 'roster' access model. - // TODO(Unknown): Migrate to Resultsv2 - Future publishUserAvatarMetadata(UserAvatarMetadata metadata, bool public) async { + Future> publishUserAvatarMetadata(UserAvatarMetadata metadata, bool public) async { final pubsub = _getPubSubManager(); final result = await pubsub.publish( getAttributes().getFullJID().toBare().toString(), @@ -135,39 +139,37 @@ class UserAvatarManager extends XmppManagerBase { ), ); - return result.isType(); + if (result.isType()) return Result(UnknownAvatarError()); + return const Result(true); } /// Subscribe the data and metadata node of [jid]. - // TODO(Unknown): Migrate to Resultsv2 - Future subscribe(String jid) async { + Future> subscribe(String jid) async { await _getPubSubManager().subscribe(jid, userAvatarDataXmlns); await _getPubSubManager().subscribe(jid, userAvatarMetadataXmlns); - return true; + return const Result(true); } /// Unsubscribe the data and metadata node of [jid]. - // TODO(Unknown): Migrate to Resultsv2 - Future unsubscribe(String jid) async { + Future> unsubscribe(String jid) async { await _getPubSubManager().unsubscribe(jid, userAvatarDataXmlns); await _getPubSubManager().subscribe(jid, userAvatarMetadataXmlns); - return true; + return const Result(true); } /// Returns the PubSub Id of an avatar after doing a disco#items query. /// Note that this assumes that there is only one (1) item published on /// the node. - // TODO(Unknown): Migrate to Resultsv2 - Future getAvatarId(String jid) async { + Future> getAvatarId(String jid) async { final disco = getAttributes().getManagerById(discoManager)! as DiscoManager; - final response = await disco.discoItemsQuery(jid, node: userAvatarDataXmlns); - if (response.isType()) return null; + final response = await disco.discoItemsQuery(jid, node: userAvatarDataXmlns, shouldEncrypt: false); + if (response.isType()) return Result(UnknownAvatarError()); final items = response.get>(); - if (items.isEmpty) return null; + if (items.isEmpty) return Result(UnknownAvatarError()); - return items.first.name; + return Result(items.first.name); } }