1
0
forked from blue/squawk

removed own VCard request at the start if the presence doesn't show that the avatar changed, little refactoring

This commit is contained in:
Blue 2022-08-27 14:39:24 +03:00
parent 7b2b7ee5d5
commit b6ba022bff
Signed by untrusted user: blue
GPG Key ID: 9B203B252A63EE38
10 changed files with 215 additions and 129 deletions

View File

@ -9,6 +9,7 @@
- deactivated accounts now don't appear in combobox of "Add contact" and "Join conference" dialogues - deactivated accounts now don't appear in combobox of "Add contact" and "Join conference" dialogues
- all of the expandable roster items now get saved between launches - all of the expandable roster items now get saved between launches
- settings file on the disk is not rewritten every roster element expansion or collapse - settings file on the disk is not rewritten every roster element expansion or collapse
- removed unnecessary own vcard request at sturtup (used to do it to discover my own avatar)
### New features ### New features
- Now you can enable tray icon from settings! - Now you can enable tray icon from settings!

View File

@ -18,6 +18,7 @@
#include "account.h" #include "account.h"
#include <QXmppMessage.h> #include <QXmppMessage.h>
#include <QDateTime> #include <QDateTime>
using namespace Core; using namespace Core;
@ -44,12 +45,13 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
network(p_net), network(p_net),
passwordType(Shared::AccountPassword::plain), passwordType(Shared::AccountPassword::plain),
lastError(Error::none), lastError(Error::none),
pepSupport(false), pepSupport(Shared::Support::unknown),
active(p_active), active(p_active),
notReadyPassword(false), notReadyPassword(false),
mh(new MessageHandler(this)), mh(new MessageHandler(this)),
rh(new RosterHandler(this)), rh(new RosterHandler(this)),
vh(new VCardHandler(this)) vh(new VCardHandler(this)),
dh(new DiscoveryHandler(this))
{ {
config.setUser(p_login); config.setUser(p_login);
config.setDomain(p_server); config.setDomain(p_server);
@ -79,9 +81,6 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
QObject::connect(um, &QXmppUploadRequestManager::slotReceived, mh, &MessageHandler::onUploadSlotReceived); QObject::connect(um, &QXmppUploadRequestManager::slotReceived, mh, &MessageHandler::onUploadSlotReceived);
QObject::connect(um, &QXmppUploadRequestManager::requestFailed, mh, &MessageHandler::onUploadSlotRequestFailed); QObject::connect(um, &QXmppUploadRequestManager::requestFailed, mh, &MessageHandler::onUploadSlotRequestFailed);
QObject::connect(dm, &QXmppDiscoveryManager::itemsReceived, this, &Account::onDiscoveryItemsReceived);
QObject::connect(dm, &QXmppDiscoveryManager::infoReceived, this, &Account::onDiscoveryInfoReceived);
QObject::connect(network, &NetworkAccess::uploadFileComplete, mh, &MessageHandler::onUploadFileComplete); QObject::connect(network, &NetworkAccess::uploadFileComplete, mh, &MessageHandler::onUploadFileComplete);
QObject::connect(network, &NetworkAccess::downloadFileComplete, mh, &MessageHandler::onDownloadFileComplete); QObject::connect(network, &NetworkAccess::downloadFileComplete, mh, &MessageHandler::onDownloadFileComplete);
QObject::connect(network, &NetworkAccess::loadFileError, mh, &MessageHandler::onLoadFileError); QObject::connect(network, &NetworkAccess::loadFileError, mh, &MessageHandler::onLoadFileError);
@ -93,8 +92,6 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
QObject::connect(reconnectTimer, &QTimer::timeout, this, &Account::onReconnectTimer); QObject::connect(reconnectTimer, &QTimer::timeout, this, &Account::onReconnectTimer);
if (name == "Test") { if (name == "Test") {
qDebug() << "Presence capabilities: " << presence.capabilityNode();
QXmppLogger* logger = new QXmppLogger(this); QXmppLogger* logger = new QXmppLogger(this);
logger->setLoggingType(QXmppLogger::SignalLogging); logger->setLoggingType(QXmppLogger::SignalLogging);
client.setLogger(logger); client.setLogger(logger);
@ -263,9 +260,8 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence)
if (jid == getBareJid()) { if (jid == getBareJid()) {
if (resource == getResource()) { if (resource == getResource()) {
emit availabilityChanged(static_cast<Shared::Availability>(p_presence.availableStatusType())); emit availabilityChanged(static_cast<Shared::Availability>(p_presence.availableStatusType()));
} else {
vh->handleOtherPresenceOfMyAccountChange(p_presence);
} }
vh->handlePresenceOfMyAccountChange(p_presence);
} else { } else {
RosterItem* item = rh->getRosterItem(jid); RosterItem* item = rh->getRosterItem(jid);
if (item != 0) { if (item != 0) {
@ -574,104 +570,6 @@ void Core::Account::setRoomJoined(const QString& jid, bool joined)
conf->setJoined(joined); conf->setJoined(joined);
} }
void Core::Account::onDiscoveryItemsReceived(const QXmppDiscoveryIq& items)
{
if (items.from() == getServer()) {
std::set<QString> needToRequest;
qDebug() << "Server items list received for account " << name << ":";
for (QXmppDiscoveryIq::Item item : items.items()) {
QString jid = item.jid();
if (jid != getServer()) {
qDebug() << " Node" << jid;
needToRequest.insert(jid);
} else {
qDebug() << " " << item.node().toStdString().c_str();
}
}
for (const QString& jid : needToRequest) {
dm->requestInfo(jid);
}
}
}
void Core::Account::onDiscoveryInfoReceived(const QXmppDiscoveryIq& info)
{
QString from = info.from();
if (from == getServer()) {
bool enableCC = false;
qDebug() << "Server info received for account" << name;
QStringList features = info.features();
qDebug() << "List of supported features of the server " << getServer() << ":";
for (const QString& feature : features) {
qDebug() << " " << feature.toStdString().c_str();
if (feature == "urn:xmpp:carbons:2") {
enableCC = true;
}
}
if (enableCC) {
qDebug() << "Enabling carbon copies for account" << name;
cm->setCarbonsEnabled(true);
}
qDebug() << "Requesting account" << name << "capabilities";
dm->requestInfo(getBareJid());
} else if (from == getBareJid()) {
qDebug() << "Received capabilities for account" << name << ":";
QList<QXmppDiscoveryIq::Identity> identities = info.identities();
bool pepSupported = false;
for (const QXmppDiscoveryIq::Identity& identity : identities) {
QString type = identity.type();
QString category = identity.category();
qDebug() << " " << category << type;
if (type == "pep" && category == "pubsub") {
pepSupported = true;
}
}
rh->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported);
} else {
qDebug() << "Received info for account" << name << "about" << from;
QString node = info.queryNode();
if (!node.isEmpty()) {
QStringList feats = info.features();
std::set<Shared::Identity> identities;
std::set<QString> features(feats.begin(), feats.end());
QList<QXmppDiscoveryIq::Identity> idents = info.identities();
for (const QXmppDiscoveryIq::Identity& ident : idents) {
Shared::Identity identity;
identity.category = ident.category();
identity.language = ident.language();
identity.name = ident.name();
identity.type = ident.type();
identities.insert(identity);
qDebug() << " " << identity.name << identity.category << identity.type;
}
for (const QString& feat : features) {
qDebug() << " " << feat;
}
emit infoDiscovered(from, node, identities, features);
} else {
Contact* cont = rh->getContact(from);
if (cont != nullptr) {
qDebug() << "Received info for account" << name << "about" << from;
QList<QXmppDiscoveryIq::Identity> identities = info.identities();
bool pepSupported = false;
for (const QXmppDiscoveryIq::Identity& identity : identities) {
QString type = identity.type();
QString category = identity.category();
qDebug() << " " << category << type;
if (type == "pep" && category == "pubsub") {
pepSupported = true;
}
}
cont->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported);
}
}
}
}
void Core::Account::discoverInfo(const QString& address, const QString& node) { void Core::Account::discoverInfo(const QString& address, const QString& node) {
if (state == Shared::ConnectionState::connected) { if (state == Shared::ConnectionState::connected) {
dm->requestInfo(address, node); dm->requestInfo(address, node);
@ -682,8 +580,17 @@ void Core::Account::discoverInfo(const QString& address, const QString& node) {
} }
} }
void Core::Account::setPepSupport(Shared::Support support)
{
if (support != pepSupport) {
pepSupport = support;
emit pepSupportChanged(pepSupport);
}
}
void Core::Account::handleDisconnection() void Core::Account::handleDisconnection()
{ {
setPepSupport(Shared::Support::unknown);
cm->setCarbonsEnabled(false); cm->setCarbonsEnabled(false);
rh->handleOffline(); rh->handleOffline();
vh->handleOffline(); vh->handleOffline();

View File

@ -52,6 +52,7 @@
#include "handlers/messagehandler.h" #include "handlers/messagehandler.h"
#include "handlers/rosterhandler.h" #include "handlers/rosterhandler.h"
#include "handlers/vcardhandler.h" #include "handlers/vcardhandler.h"
#include "handlers/discoveryhandler.h"
namespace Core namespace Core
{ {
@ -62,6 +63,7 @@ class Account : public QObject
friend class MessageHandler; friend class MessageHandler;
friend class RosterHandler; friend class RosterHandler;
friend class VCardHandler; friend class VCardHandler;
friend class DiscoveryHandler;
public: public:
enum class Error { enum class Error {
authentication, authentication,
@ -156,6 +158,7 @@ signals:
void uploadFileError(const QString& jid, const QString& messageId, const QString& error); void uploadFileError(const QString& jid, const QString& messageId, const QString& error);
void needPassword(); void needPassword();
void infoDiscovered(const QString& address, const QString& node, const std::set<Shared::Identity>& identities, const std::set<QString>& features); void infoDiscovered(const QString& address, const QString& node, const std::set<Shared::Identity>& identities, const std::set<QString>& features);
void pepSupportChanged(Shared::Support support);
private: private:
QString name; QString name;
@ -179,13 +182,14 @@ private:
NetworkAccess* network; NetworkAccess* network;
Shared::AccountPassword passwordType; Shared::AccountPassword passwordType;
Error lastError; Error lastError;
bool pepSupport; Shared::Support pepSupport;
bool active; bool active;
bool notReadyPassword; bool notReadyPassword;
MessageHandler* mh; MessageHandler* mh;
RosterHandler* rh; RosterHandler* rh;
VCardHandler* vh; VCardHandler* vh;
DiscoveryHandler* dh;
private slots: private slots:
void onClientStateChange(QXmppClient::State state); void onClientStateChange(QXmppClient::State state);
@ -199,13 +203,12 @@ private slots:
void onMamLog(QXmppLogger::MessageType type, const QString &msg); void onMamLog(QXmppLogger::MessageType type, const QString &msg);
void onDiscoveryItemsReceived (const QXmppDiscoveryIq& items);
void onDiscoveryInfoReceived (const QXmppDiscoveryIq& info);
void onContactHistoryResponse(const std::list<Shared::Message>& list, bool last); void onContactHistoryResponse(const std::list<Shared::Message>& list, bool last);
private: private:
void handleDisconnection(); void handleDisconnection();
void onReconnectTimer(); void onReconnectTimer();
void setPepSupport(Shared::Support support);
}; };
} }

View File

@ -5,4 +5,6 @@ target_sources(squawk PRIVATE
rosterhandler.h rosterhandler.h
vcardhandler.cpp vcardhandler.cpp
vcardhandler.h vcardhandler.h
discoveryhandler.cpp
discoveryhandler.h
) )

View File

@ -0,0 +1,135 @@
// Squawk messenger.
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "discoveryhandler.h"
#include "core/account.h"
#include <QDebug>
Core::DiscoveryHandler::DiscoveryHandler(Core::Account* account):
QObject(),
acc(account)
{
QObject::connect(acc->dm, &QXmppDiscoveryManager::itemsReceived, this, &DiscoveryHandler::onItemsReceived);
QObject::connect(acc->dm, &QXmppDiscoveryManager::infoReceived, this, &DiscoveryHandler::onInfoReceived);
acc->dm->setClientType("pc");
acc->dm->setClientCategory("client");
acc->dm->setClientName(qApp->applicationDisplayName() + " " + qApp->applicationVersion());
acc->dm->setClientCapabilitiesNode("https://git.macaw.me/blue/squawk");
}
void Core::DiscoveryHandler::onItemsReceived(const QXmppDiscoveryIq& items)
{
QString server = acc->getServer();
if (items.from() == server) {
std::set<QString> needToRequest;
qDebug() << "Server items list received for account " << acc->getName() << ":";
for (QXmppDiscoveryIq::Item item : items.items()) {
QString jid = item.jid();
if (jid != server) {
qDebug() << " Node" << jid;
needToRequest.insert(jid);
} else {
qDebug() << " " << item.node().toStdString().c_str();
}
}
for (const QString& jid : needToRequest) {
acc->dm->requestInfo(jid);
}
}
}
void Core::DiscoveryHandler::onInfoReceived(const QXmppDiscoveryIq& info)
{
QString from = info.from();
QString server = acc->getServer();
QString accName = acc->getName();
QString bareJid = acc->getBareJid();
if (from == server) {
bool enableCC = false;
qDebug() << "Server info received for account" << accName;
QStringList features = info.features();
qDebug() << "List of supported features of the server " << server << ":";
for (const QString& feature : features) {
qDebug() << " " << feature.toStdString().c_str();
if (feature == "urn:xmpp:carbons:2") {
enableCC = true;
}
}
if (enableCC) {
qDebug() << "Enabling carbon copies for account" << accName;
acc->cm->setCarbonsEnabled(true);
}
qDebug() << "Requesting account" << accName << "capabilities";
acc->dm->requestInfo(bareJid);
} else if (from == bareJid) {
qDebug() << "Received capabilities for account" << accName << ":";
QList<QXmppDiscoveryIq::Identity> identities = info.identities();
bool pepSupported = false;
for (const QXmppDiscoveryIq::Identity& identity : identities) {
QString type = identity.type();
QString category = identity.category();
qDebug() << " " << category << type;
if (type == "pep" && category == "pubsub") {
pepSupported = true;
}
}
acc->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported);
} else {
qDebug() << "Received info for account" << accName << "about" << from;
QString node = info.queryNode();
if (!node.isEmpty()) {
QStringList feats = info.features();
std::set<Shared::Identity> identities;
std::set<QString> features(feats.begin(), feats.end());
QList<QXmppDiscoveryIq::Identity> idents = info.identities();
for (const QXmppDiscoveryIq::Identity& ident : idents) {
Shared::Identity identity;
identity.category = ident.category();
identity.language = ident.language();
identity.name = ident.name();
identity.type = ident.type();
identities.insert(identity);
qDebug() << " " << identity.name << identity.category << identity.type;
}
for (const QString& feat : features) {
qDebug() << " " << feat;
}
emit acc->infoDiscovered(from, node, identities, features);
} else {
Contact* cont = acc->rh->getContact(from);
if (cont != nullptr) {
qDebug() << "Received info for account" << accName << "about" << from;
QList<QXmppDiscoveryIq::Identity> identities = info.identities();
bool pepSupported = false;
for (const QXmppDiscoveryIq::Identity& identity : identities) {
QString type = identity.type();
QString category = identity.category();
qDebug() << " " << category << type;
if (type == "pep" && category == "pubsub") {
pepSupported = true;
}
}
cont->setPepSupport(pepSupported ? Shared::Support::supported : Shared::Support::unsupported);
}
}
}
}

View File

@ -0,0 +1,45 @@
// Squawk messenger.
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef CORE_DISCOVERYHANDLER_H
#define CORE_DISCOVERYHANDLER_H
#include <QObject>
#include <QXmppDiscoveryManager.h>
#include <QXmppDiscoveryIq.h>
namespace Core {
class Account;
class DiscoveryHandler : public QObject
{
Q_OBJECT
public:
DiscoveryHandler(Account* account);
~DiscoveryHandler();
private slots:
void onItemsReceived (const QXmppDiscoveryIq& items);
void onInfoReceived (const QXmppDiscoveryIq& info);
private:
Account* acc;
};
}
#endif // CORE_DISCOVERYHANDLER_H

View File

@ -26,8 +26,7 @@ Core::RosterHandler::RosterHandler(Core::Account* account):
conferences(), conferences(),
groups(), groups(),
queuedContacts(), queuedContacts(),
outOfRosterContacts(), outOfRosterContacts()
pepSupport(Shared::Support::unknown)
{ {
connect(acc->rm, &QXmppRosterManager::rosterReceived, this, &RosterHandler::onRosterReceived); connect(acc->rm, &QXmppRosterManager::rosterReceived, this, &RosterHandler::onRosterReceived);
connect(acc->rm, &QXmppRosterManager::itemAdded, this, &RosterHandler::onRosterItemAdded); connect(acc->rm, &QXmppRosterManager::itemAdded, this, &RosterHandler::onRosterItemAdded);
@ -37,6 +36,8 @@ Core::RosterHandler::RosterHandler(Core::Account* account):
connect(acc->mm, &QXmppMucManager::roomAdded, this, &RosterHandler::onMucRoomAdded); connect(acc->mm, &QXmppMucManager::roomAdded, this, &RosterHandler::onMucRoomAdded);
connect(acc->bm, &QXmppBookmarkManager::bookmarksReceived, this, &RosterHandler::bookmarksReceived); connect(acc->bm, &QXmppBookmarkManager::bookmarksReceived, this, &RosterHandler::bookmarksReceived);
connect(acc, &Account::pepSupportChanged, this, &RosterHandler::onPepSupportedChanged);
} }
Core::RosterHandler::~RosterHandler() Core::RosterHandler::~RosterHandler()
@ -52,8 +53,6 @@ Core::RosterHandler::~RosterHandler()
void Core::RosterHandler::onRosterReceived() void Core::RosterHandler::onRosterReceived()
{ {
acc->requestVCard(acc->getBareJid()); //TODO need to make sure server actually supports vCards
QStringList bj = acc->rm->getRosterBareJids(); QStringList bj = acc->rm->getRosterBareJids();
for (int i = 0; i < bj.size(); ++i) { for (int i = 0; i < bj.size(); ++i) {
const QString& jid = bj[i]; const QString& jid = bj[i];
@ -111,7 +110,7 @@ void Core::RosterHandler::addedAccount(const QString& jid)
if (grCount == 0) { if (grCount == 0) {
emit acc->addContact(jid, "", cData); emit acc->addContact(jid, "", cData);
} }
if (pepSupport == Shared::Support::supported) { if (acc->pepSupport == Shared::Support::supported) {
acc->dm->requestInfo(jid); acc->dm->requestInfo(jid);
//acc->dm->requestItems(jid); //acc->dm->requestItems(jid);
} }
@ -592,21 +591,16 @@ void Core::RosterHandler::handleOffline()
pair.second->clearArchiveRequests(); pair.second->clearArchiveRequests();
pair.second->downgradeDatabaseState(); pair.second->downgradeDatabaseState();
} }
setPepSupport(Shared::Support::unknown);
} }
void Core::RosterHandler::setPepSupport(Shared::Support support) void Core::RosterHandler::onPepSupportedChanged(Shared::Support support)
{ {
if (pepSupport != support) { if (support == Shared::Support::supported) {
pepSupport = support;
if (pepSupport == Shared::Support::supported) {
for (const std::pair<const QString, Contact*>& pair : contacts) { for (const std::pair<const QString, Contact*>& pair : contacts) {
if (pair.second->getPepSupport() == Shared::Support::unknown) { if (pair.second->getPepSupport() == Shared::Support::unknown) {
acc->dm->requestInfo(pair.first); acc->dm->requestInfo(pair.first);
} }
} }
} }
}
} }

View File

@ -65,7 +65,6 @@ public:
void storeConferences(); void storeConferences();
void clearConferences(); void clearConferences();
void setPepSupport(Shared::Support support);
private slots: private slots:
void onRosterReceived(); void onRosterReceived();
@ -89,6 +88,7 @@ private slots:
void onContactNameChanged(const QString& name); void onContactNameChanged(const QString& name);
void onContactSubscriptionStateChanged(Shared::SubscriptionState state); void onContactSubscriptionStateChanged(Shared::SubscriptionState state);
void onContactAvatarChanged(Shared::Avatar, const QString& path); void onContactAvatarChanged(Shared::Avatar, const QString& path);
void onPepSupportedChanged(Shared::Support support);
private: private:
void addNewRoom(const QString& jid, const QString& nick, const QString& roomName, bool autoJoin); void addNewRoom(const QString& jid, const QString& nick, const QString& roomName, bool autoJoin);
@ -109,7 +109,6 @@ private:
std::map<QString, std::set<QString>> groups; std::map<QString, std::set<QString>> groups;
std::map<QString, QString> queuedContacts; std::map<QString, QString> queuedContacts;
std::set<QString> outOfRosterContacts; std::set<QString> outOfRosterContacts;
Shared::Support pepSupport;
}; };
} }

View File

@ -228,7 +228,7 @@ void Core::VCardHandler::requestVCard(const QString& jid)
} }
} }
void Core::VCardHandler::handleOtherPresenceOfMyAccountChange(const QXmppPresence& p_presence) void Core::VCardHandler::handlePresenceOfMyAccountChange(const QXmppPresence& p_presence)
{ {
if (!ownVCardRequestInProgress) { if (!ownVCardRequestInProgress) {
switch (p_presence.vCardUpdateType()) { switch (p_presence.vCardUpdateType()) {

View File

@ -44,7 +44,7 @@ public:
void handleOffline(); void handleOffline();
void requestVCard(const QString& jid); void requestVCard(const QString& jid);
void handleOtherPresenceOfMyAccountChange(const QXmppPresence& p_presence); void handlePresenceOfMyAccountChange(const QXmppPresence& p_presence);
void uploadVCard(const Shared::VCard& card); void uploadVCard(const Shared::VCard& card);
QString getAvatarPath() const; QString getAvatarPath() const;