Skip to content
Permalink
Browse files

Implement XEP-0382: Spoiler messages (v0.2.0)

This adds parsing and serialization of spoilers in the QXmppMessage class.
  • Loading branch information...
lnjX authored and jlaine committed Apr 27, 2019
1 parent 537e325 commit caeb6f2608ab0f6e769fb93fef14658bfe165378
@@ -3,6 +3,7 @@ QXmpp 1.0.1 (UNRELEASED)

New features:
- Add support for SCRAM-SHA-1 and SCRAM-SHA-256 (#183, @jlaine)
- Add XEP-0382: Spoiler messages (v0.2.0) (#195, @lnjX)

QXmpp 1.0.0 (Jan 8, 2019)
-------------------------
@@ -41,6 +41,7 @@ Complete:
- XEP-0313: Message Archive Management
- XEP-0319: Last User Interaction in Presence
- XEP-0352: Client State Indication
- XEP-0382: Spoiler messages (v0.2.0)

Ongoing:
- XEP-0009: Jabber-RPC (API is not finalized yet)
@@ -141,6 +141,8 @@ const char* ns_mix_node_participants = "urn:xmpp:mix:nodes:participants";
const char* ns_mix_node_presence = "urn:xmpp:mix:nodes:presence";
const char* ns_mix_node_config = "urn:xmpp:mix:nodes:config";
const char* ns_mix_node_info = "urn:xmpp:mix:nodes:info";
// XEP-0382: Spoiler messages
const char* ns_spoiler = "urn:xmpp:spoiler:0";
// XEP-0405: Mediated Information eXchange (MIX): Participant Server Requirements
const char* ns_mix_pam = "urn:xmpp:mix:pam:0";
const char* ns_mix_roster = "urn:xmpp:mix:roster:0";
@@ -153,6 +153,8 @@ extern const char* ns_mix_node_participants;
extern const char* ns_mix_node_presence;
extern const char* ns_mix_node_config;
extern const char* ns_mix_node_info;
// XEP-0382: Spoiler messages
extern const char* ns_spoiler;
// XEP-0405: Mediated Information eXchange (MIX): Participant Server Requirements
extern const char* ns_mix_pam;
extern const char* ns_mix_roster;
@@ -106,6 +106,10 @@ class QXmppMessagePrivate : public QSharedData
// XEP-0369: Mediated Information eXchange (MIX)
QString mixUserJid;
QString mixUserNick;

// XEP-0382: Spoiler messages
bool isSpoiler = false;
QString spoilerHint;
};

/// Constructs a QXmppMessage.
@@ -545,6 +549,52 @@ void QXmppMessage::setMixUserNick(const QString& mixUserNick)
d->mixUserNick = mixUserNick;
}

/// Returns true, if this is a spoiler message according to XEP-0382: Spoiler
/// messages. The spoiler hint however can still be empty.
///
/// A spoiler message's content should not be visible to the user by default.

bool QXmppMessage::isSpoiler() const
{
return d->isSpoiler;
}

/// Sets whether this is a spoiler message as specified in XEP-0382: Spoiler
/// messages.
///
/// The content of spoiler messages will not be displayed by default to the
/// user. However, clients not supporting spoiler messages will still display
/// the content as usual.

void QXmppMessage::setIsSpoiler(bool isSpoiler)
{
d->isSpoiler = isSpoiler;
}

/// Returns the spoiler hint as specified in XEP-0382: Spoiler messages.
///
/// The hint may be empty, even if isSpoiler is true.

QString QXmppMessage::spoilerHint() const
{
return d->spoilerHint;
}

/// Sets a spoiler hint for XEP-0382: Spoiler messages. If the spoiler hint
/// is not empty, isSpoiler will be set to true.
///
/// A spoiler hint is optional for spoiler messages.
///
/// Keep in mind that the spoiler hint is not displayed at all by clients not
/// supporting spoiler messages.

void QXmppMessage::setSpoilerHint(const QString &spoilerHint)
{
d->spoilerHint = spoilerHint;
if (!spoilerHint.isEmpty())
d->isSpoiler = true;
}

/// \cond
void QXmppMessage::parse(const QDomElement &element)
{
@@ -690,6 +740,10 @@ void QXmppMessage::parse(const QDomElement &element)
} else if (xElement.tagName() == "mix" && xElement.namespaceURI() == ns_mix) {
d->mixUserJid = xElement.firstChildElement("jid").text();
d->mixUserNick = xElement.firstChildElement("nick").text();
// XEP-0382: Spoiler messages
} else if (xElement.tagName() == "spoiler" && xElement.namespaceURI() == ns_spoiler) {
d->isSpoiler = true;
d->spoilerHint = xElement.text();
} else if (!knownElems.contains(qMakePair(xElement.tagName(), xElement.namespaceURI())) &&
!knownElems.contains(qMakePair(xElement.tagName(), QString()))) {
// other extensions
@@ -836,6 +890,14 @@ void QXmppMessage::toXml(QXmlStreamWriter *xmlWriter) const
xmlWriter->writeEndElement();
}

// XEP-0382: Spoiler messages
if (d->isSpoiler) {
xmlWriter->writeStartElement("spoiler");
xmlWriter->writeAttribute("xmlns", ns_spoiler);
xmlWriter->writeCharacters(d->spoilerHint);
xmlWriter->writeEndElement();
}

// other extensions
QXmppStanza::extensionsToXml(xmlWriter);

@@ -150,6 +150,13 @@ class QXMPP_EXPORT QXmppMessage : public QXmppStanza
QString mixUserNick() const;
void setMixUserNick(const QString&);

// XEP-0382: Spoiler messages
bool isSpoiler() const;
void setIsSpoiler(bool);

QString spoilerHint() const;
void setSpoilerHint(const QString&);

/// \cond
void parse(const QDomElement &element);
void toXml(QXmlStreamWriter *writer) const;
@@ -49,6 +49,7 @@ private slots:
void testOutOfBandUrl();
void testMessageCorrect();
void testMix();
void testSpoiler();
};

void tst_QXmppMessage::testBasic_data()
@@ -112,6 +113,7 @@ void tst_QXmppMessage::testBasic()
QCOMPARE(message.isReceiptRequested(), false);
QCOMPARE(message.receiptId(), QString());
QCOMPARE(message.xhtml(), QString());
QVERIFY(!message.isSpoiler());
serializePacket(message, xml);
}

@@ -643,5 +645,44 @@ void tst_QXmppMessage::testMix()
QCOMPARE(message.mixUserNick(), QString("erik"));
}

void tst_QXmppMessage::testSpoiler()
{
// test parsing with hint
const QByteArray xmlWithHint(
"<message to=\"foo@example.com/QXmpp\" from=\"bar@example.com/QXmpp\" type=\"normal\">"
"<body>And at the end of the story, both of them die! It is so tragic!</body>"
"<spoiler xmlns=\"urn:xmpp:spoiler:0\">Love story end</spoiler>"
"</message>");

QXmppMessage messageWithHint;
parsePacket(messageWithHint, xmlWithHint);
QVERIFY(messageWithHint.isSpoiler());
QCOMPARE(messageWithHint.spoilerHint(), QString("Love story end"));
serializePacket(messageWithHint, xmlWithHint);

// test parsing without hint
const QByteArray xmlWithoutHint(
"<message to=\"foo@example.com/QXmpp\" from=\"bar@example.com/QXmpp\" type=\"normal\">"
"<body>And at the end of the story, both of them die! It is so tragic!</body>"
"<spoiler xmlns=\"urn:xmpp:spoiler:0\"></spoiler>"
"</message>");

QXmppMessage messageWithoutHint;
parsePacket(messageWithoutHint, xmlWithoutHint);
QVERIFY(messageWithoutHint.isSpoiler());
QCOMPARE(messageWithoutHint.spoilerHint(), QString(""));
serializePacket(messageWithoutHint, xmlWithoutHint);

// test setters
QXmppMessage message;
message.setIsSpoiler(true);
QVERIFY(message.isSpoiler());

message.setIsSpoiler(false);
message.setSpoilerHint("test hint");
QCOMPARE(message.spoilerHint(), QString("test hint"));
QVERIFY(message.isSpoiler());
}

QTEST_MAIN(tst_QXmppMessage)
#include "tst_qxmppmessage.moc"

0 comments on commit caeb6f2

Please sign in to comment.
You can’t perform that action at this time.