Now avatars are properly autogenerated, reduced vCard spam

This commit is contained in:
Blue 2024-01-31 20:22:49 -03:00
parent 93c5be412e
commit 0be2648849
Signed by: blue
GPG Key ID: 9B203B252A63EE38
9 changed files with 76 additions and 92 deletions

View File

@ -367,19 +367,23 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence) {
vh->handlePresenceOfMyAccountChange(p_presence); vh->handlePresenceOfMyAccountChange(p_presence);
} else { } else {
RosterItem* item = rh->getRosterItem(jid); RosterItem* item = rh->getRosterItem(jid);
if (item != nullptr) if (item != nullptr) {
item->handlePresence(p_presence); if (item->isMuc()) //MUC presence is handled by inner muc events
return;
else
item->handlePresence(p_presence);
}
} }
switch (p_presence.type()) { switch (p_presence.type()) {
case QXmppPresence::Error: case QXmppPresence::Error:
qDebug() << "An error reported by presence from" << id << p_presence.error().text(); qDebug() << "An error reported by presence from" << id << p_presence.error().text();
break; break;
case QXmppPresence::Available:{ case QXmppPresence::Available: {
QDateTime lastInteraction = p_presence.lastUserInteraction(); QDateTime lastInteraction = p_presence.lastUserInteraction();
if (!lastInteraction.isValid()) { if (!lastInteraction.isValid())
lastInteraction = QDateTime::currentDateTimeUtc(); lastInteraction = QDateTime::currentDateTimeUtc();
}
emit addPresence(jid, resource, { emit addPresence(jid, resource, {
{"lastActivity", lastInteraction}, {"lastActivity", lastInteraction},
{"availability", p_presence.availableStatusType()}, //TODO check and handle invisible {"availability", p_presence.availableStatusType()}, //TODO check and handle invisible
@ -392,8 +396,7 @@ void Core::Account::onPresenceReceived(const QXmppPresence& p_presence) {
) )
} }
}); });
} } break;
break;
case QXmppPresence::Unavailable: case QXmppPresence::Unavailable:
emit removePresence(jid, resource); emit removePresence(jid, resource);
break; break;

View File

@ -132,9 +132,8 @@ void Core::Conference::onRoomParticipantAdded(const QString& p_name) {
if (resource.size() > 0) { if (resource.size() > 0) {
QDateTime lastInteraction = pres.lastUserInteraction(); QDateTime lastInteraction = pres.lastUserInteraction();
if (!lastInteraction.isValid()) { if (!lastInteraction.isValid())
lastInteraction = QDateTime::currentDateTimeUtc(); lastInteraction = QDateTime::currentDateTimeUtc();
}
QMap<QString, QVariant> cData = { QMap<QString, QVariant> cData = {
{"lastActivity", lastInteraction}, {"lastActivity", lastInteraction},
@ -153,29 +152,37 @@ void Core::Conference::onRoomParticipantAdded(const QString& p_name) {
careAboutAvatar(hasAvatar, itr->second, cData, resource, p_name); careAboutAvatar(hasAvatar, itr->second, cData, resource, p_name);
emit addParticipant(resource, cData); emit addParticipant(resource, cData);
if (!hasAvatar) // because this way vCard is already requested, no need to handle possible avatar update
return;
} }
handlePossibleAvatarUpdate(pres, resource, hasAvatar, itr->second);
}
void Core::Conference::handlePossibleAvatarUpdate (
const QXmppPresence& pres,
const QString& resource,
bool hasAvatar,
const Archive::AvatarInfo& info
) {
switch (pres.vCardUpdateType()) { switch (pres.vCardUpdateType()) {
case QXmppPresence::VCardUpdateNone: //this presence has nothing to do with photo case QXmppPresence::VCardUpdateNone: //this presence has nothing to do with photo
break; break;
case QXmppPresence::VCardUpdateNotReady: //let's say the photo didn't change here case QXmppPresence::VCardUpdateNotReady: //let's say the photo didn't change here
break; break;
case QXmppPresence::VCardUpdateNoPhoto: { //there is no photo, need to drop if any case QXmppPresence::VCardUpdateNoPhoto: //there is no photo, need to drop if any
if (!hasAvatar || !itr->second.autogenerated) { if (!hasAvatar || !info.autogenerated)
setAutoGeneratedAvatar(resource); setAutoGeneratedAvatar(resource);
}
}
break;
case QXmppPresence::VCardUpdateValidPhoto:{ //there is a photo, need to load
if (hasAvatar) {
if (itr->second.autogenerated || itr->second.hash != pres.photoHash())
emit requestVCard(p_name);
break;
case QXmppPresence::VCardUpdateValidPhoto: //there is a photo, need to load
if (hasAvatar) {
if (info.autogenerated || info.hash != pres.photoHash())
emit requestVCard(pres.from());
} else { } else {
emit requestVCard(p_name); emit requestVCard(pres.from());
} }
break; break;
}
} }
} }
@ -235,32 +242,10 @@ void Core::Conference::handlePresence(const QXmppPresence& pres) {
QString resource(""); QString resource("");
if (comps.size() > 1) if (comps.size() > 1)
resource = comps.back(); resource = comps.back();
switch (pres.vCardUpdateType()) { Archive::AvatarInfo info;
case QXmppPresence::VCardUpdateNone: //this presence has nothing to do with photo bool hasAvatar = readAvatarInfo(info, resource);
break; handlePossibleAvatarUpdate(pres, resource, hasAvatar, info);
case QXmppPresence::VCardUpdateNotReady: //let's say the photo didn't change here
break;
case QXmppPresence::VCardUpdateNoPhoto: { //there is no photo, need to drop if any
Archive::AvatarInfo info;
bool hasAvatar = readAvatarInfo(info, resource);
if (!hasAvatar || !info.autogenerated) {
setAutoGeneratedAvatar(resource);
}
}
break;
case QXmppPresence::VCardUpdateValidPhoto:{ //there is a photo, need to load
Archive::AvatarInfo info;
bool hasAvatar = readAvatarInfo(info, resource);
if (hasAvatar) {
if (info.autogenerated || info.hash != pres.photoHash())
emit requestVCard(id);
} else {
emit requestVCard(id);
}
break;
}
}
} }
bool Core::Conference::setAutoGeneratedAvatar(const QString& resource) { bool Core::Conference::setAutoGeneratedAvatar(const QString& resource) {
@ -272,6 +257,7 @@ bool Core::Conference::setAutoGeneratedAvatar(const QString& resource) {
exParticipants.insert(std::make_pair(resource, newInfo)); exParticipants.insert(std::make_pair(resource, newInfo));
else else
itr->second = newInfo; itr->second = newInfo;
emit changeParticipant(resource, { emit changeParticipant(resource, {
{"avatarState", static_cast<uint>(Shared::Avatar::autocreated)}, {"avatarState", static_cast<uint>(Shared::Avatar::autocreated)},
{"avatarPath", avatarPath(resource) + "." + newInfo.type} {"avatarPath", avatarPath(resource) + "." + newInfo.type}
@ -313,18 +299,18 @@ bool Core::Conference::setAvatar(const QByteArray& data, Archive::AvatarInfo& in
void Core::Conference::handleResponseVCard(const QXmppVCardIq& card, const QString &resource, Shared::VCard& out) { void Core::Conference::handleResponseVCard(const QXmppVCardIq& card, const QString &resource, Shared::VCard& out) {
RosterItem::handleResponseVCard(card, resource, out); RosterItem::handleResponseVCard(card, resource, out);
if (resource.size() > 0) { if (resource.size() > 0)
emit changeParticipant(resource, { emit changeParticipant(resource, {
{"avatarState", static_cast<uint>(out.getAvatarType())}, {"avatarState", static_cast<uint>(out.getAvatarType())},
{"avatarPath", out.getAvatarPath()} {"avatarPath", out.getAvatarPath()}
}); });
}
} }
QMap<QString, QVariant> Core::Conference::getAllAvatars() const { QMap<QString, QVariant> Core::Conference::getAllAvatars() const {
QMap<QString, QVariant> result; QMap<QString, QVariant> result;
for (const std::pair<const QString, Archive::AvatarInfo>& pair : exParticipants) for (const std::pair<const QString, Archive::AvatarInfo>& pair : exParticipants)
result.insert(pair.first, avatarPath(pair.first) + "." + pair.second.type); result.insert(pair.first, avatarPath(pair.first) + "." + pair.second.type);
return result; return result;
} }

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef CORE_CONFERENCE_H #pragma once
#define CORE_CONFERENCE_H
#include <QDir> #include <QDir>
@ -29,14 +28,8 @@
#include <shared/global.h> #include <shared/global.h>
#include <shared/clientid.h> #include <shared/clientid.h>
namespace Core namespace Core {
{ class Conference : public RosterItem {
/**
* @todo write docs
*/
class Conference : public RosterItem
{
Q_OBJECT Q_OBJECT
public: public:
Conference(const QString& p_jid, const QString& p_account, bool p_autoJoin, const QString& p_name, const QString& p_nick, QXmppMucRoom* p_room); Conference(const QString& p_jid, const QString& p_account, bool p_autoJoin, const QString& p_name, const QString& p_nick, QXmppMucRoom* p_room);
@ -69,6 +62,14 @@ signals:
protected: protected:
bool setAvatar(const QByteArray &data, Archive::AvatarInfo& info, const QString &resource = "") override; bool setAvatar(const QByteArray &data, Archive::AvatarInfo& info, const QString &resource = "") override;
private:
void handlePossibleAvatarUpdate(
const QXmppPresence& pres,
const QString& resource,
bool hasAvatar,
const Archive::AvatarInfo& info
);
private: private:
QString nick; QString nick;
QXmppMucRoom* room; QXmppMucRoom* room;
@ -91,5 +92,3 @@ private slots:
}; };
} }
#endif // CORE_CONFERENCE_H

View File

@ -73,18 +73,17 @@ void Core::Contact::handlePresence(const QXmppPresence& pres) {
case QXmppPresence::VCardUpdateNoPhoto: { //there is no photo, need to drop if any case QXmppPresence::VCardUpdateNoPhoto: { //there is no photo, need to drop if any
Archive::AvatarInfo info; Archive::AvatarInfo info;
bool hasAvatar = readAvatarInfo(info); bool hasAvatar = readAvatarInfo(info);
if (!hasAvatar || !info.autogenerated) { if (!hasAvatar || !info.autogenerated)
setAutoGeneratedAvatar(); setAutoGeneratedAvatar();
}
} }
break; break;
case QXmppPresence::VCardUpdateValidPhoto:{ //there is a photo, need to load case QXmppPresence::VCardUpdateValidPhoto:{ //there is a photo, need to load
Archive::AvatarInfo info; Archive::AvatarInfo info;
bool hasAvatar = readAvatarInfo(info); bool hasAvatar = readAvatarInfo(info);
if (hasAvatar) { if (hasAvatar) {
if (info.autogenerated || info.hash != pres.photoHash()) { if (info.autogenerated || info.hash != pres.photoHash())
emit requestVCard(jid); emit requestVCard(jid);
}
} else { } else {
emit requestVCard(jid); emit requestVCard(jid);
} }

View File

@ -98,13 +98,13 @@ void Core::RosterHandler::addedAccount(const QString& jid) {
contact->setName(re.name()); contact->setName(re.name());
if (newContact) { if (newContact) {
handleNewContact(contact);
QMap<QString, QVariant> cData = contact->getInfo(); QMap<QString, QVariant> cData = contact->getInfo();
#if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 5, 0) #if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 5, 0)
cData.insert("trust", QVariant::fromValue(acc->th->getSummary(jid))); cData.insert("trust", QVariant::fromValue(acc->th->getSummary(jid)));
#endif #endif
int grCount = 0; int grCount = 0;
for (QSet<QString>::const_iterator itr = gr.begin(), end = gr.end(); itr != end; ++itr) { for (const QString& groupName : gr) {
const QString& groupName = *itr;
addToGroup(jid, groupName); addToGroup(jid, groupName);
emit acc->addContact(jid, groupName, cData); emit acc->addContact(jid, groupName, cData);
grCount++; grCount++;
@ -117,7 +117,6 @@ void Core::RosterHandler::addedAccount(const QString& jid) {
acc->dm->requestInfo(jid); acc->dm->requestInfo(jid);
//acc->dm->requestItems(jid); //acc->dm->requestItems(jid);
} }
handleNewContact(contact);
} }
} }
@ -495,22 +494,23 @@ void Core::RosterHandler::removeContactFromGroupRequest(const QString& jid, cons
if (itr == contacts.end()) { if (itr == contacts.end()) {
qDebug() << "An attempt to remove non existing contact" << lcJid << "of account" qDebug() << "An attempt to remove non existing contact" << lcJid << "of account"
<< acc->name << "from the group" << groupName << ", skipping"; << acc->name << "from the group" << groupName << ", skipping";
return;
}
QXmppRosterIq::Item item = acc->rm->getRosterEntry(lcJid);
QSet<QString> groups = item.groups();
QSet<QString>::const_iterator gItr = groups.find(groupName);
if (gItr != groups.end()) {
groups.erase(gItr);
item.setGroups(groups);
QXmppRosterIq iq;
iq.setType(QXmppIq::Set);
iq.addItem(item);
acc->client.sendPacket(iq);
} else { } else {
QXmppRosterIq::Item item = acc->rm->getRosterEntry(lcJid); qDebug() << "An attempt to remove contact" << lcJid << "of account"
QSet<QString> groups = item.groups(); << acc->name << "from the group" << groupName << "but it's not in that group, skipping";
QSet<QString>::const_iterator gItr = groups.find(groupName);
if (gItr != groups.end()) {
groups.erase(gItr);
item.setGroups(groups);
QXmppRosterIq iq;
iq.setType(QXmppIq::Set);
iq.addItem(item);
acc->client.sendPacket(iq);
} else {
qDebug() << "An attempt to remove contact" << lcJid << "of account"
<< acc->name << "from the group" << groupName << "but it's not in that group, skipping";
}
} }
} }

View File

@ -16,8 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef CORE_ROSTERITEM_H #pragma once
#define CORE_ROSTERITEM_H
#include <QObject> #include <QObject>
#include <QString> #include <QString>
@ -130,5 +129,3 @@ private:
}; };
} }
#endif // CORE_ROSTERITEM_H

2
external/lmdbal vendored

@ -1 +1 @@
Subproject commit c83369f34761e7a053d62312bd07fe5b3db3a519 Subproject commit 79240aa5354e9fa9d09d3b12ea1077a81bb90809

2
external/qxmpp vendored

@ -1 +1 @@
Subproject commit 8dda3c9921c34b9e33883b0d140e8de12edc0736 Subproject commit 0cd7379bd78aa01af7e84f2fad6269ef0c0ba49c

View File

@ -650,10 +650,10 @@ void Models::Roster::onChildRemoved() {
void Models::Roster::addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data) { void Models::Roster::addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data) {
ElId contactId(account, jid); ElId contactId(account, jid);
std::map<ElId, Contact*>::iterator itr = contacts.find(contactId); std::map<ElId, Contact*>::iterator itr = contacts.find(contactId);
if (itr != contacts.end()) { if (itr != contacts.end())
itr->second->addPresence(name, data); itr->second->addPresence(name, data);
} else
qDebug() << "Received a presence" << jid + "/" + name << "don't know what to do with it";
} }
void Models::Roster::removePresence(const QString& account, const QString& jid, const QString& name) { void Models::Roster::removePresence(const QString& account, const QString& jid, const QString& name) {