summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp30
-rw-r--r--Swiften/MUC/MUC.cpp22
-rw-r--r--Swiften/MUC/MUC.h2
3 files changed, 49 insertions, 5 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index dd109a3..cf0d39d 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -417,93 +417,119 @@ std::string MUCController::roleToGroupName(MUCOccupant::Role role) {
return result;
}
void MUCController::setOnline(bool online) {
ChatControllerBase::setOnline(online);
if (!online) {
muc_->part();
parting_ = true;
processUserPart();
} else {
if (shouldJoinOnReconnect_) {
chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Trying to enter room %1%")) % toJID_.toString()));
if (loginCheckTimer_) {
loginCheckTimer_->start();
}
nick_ = desiredNick_;
rejoin();
}
}
}
void MUCController::processUserPart() {
roster_->removeAll();
/* handleUserLeft won't throw a part back up unless this is called
when it doesn't yet know we've left - which only happens on
disconnect, so call with disconnect here so if the signal does
bubble back up, it'll be with the right type.*/
muc_->handleUserLeft(MUC::Disconnect);
setEnabled(false);
}
bool MUCController::shouldUpdateJoinParts() {
return lastWasPresence_;
}
-void MUCController::handleOccupantLeft(const MUCOccupant& occupant, MUC::LeavingType, const std::string& reason) {
+void MUCController::handleOccupantLeft(const MUCOccupant& occupant, MUC::LeavingType type, const std::string& reason) {
NickJoinPart event(occupant.getNick(), Part);
appendToJoinParts(joinParts_, event);
currentOccupants_.erase(occupant.getNick());
completer_->removeWord(occupant.getNick());
- std::string partMessage = (occupant.getNick() != nick_) ? str(format(QT_TRANSLATE_NOOP("", "%1% has left the room")) % occupant.getNick()) : QT_TRANSLATE_NOOP("", "You have left the room");
+ std::string partMessage;
+ bool clearAfter = false;
+ if (occupant.getNick() != nick_) {
+ std::string partType;
+ switch (type) {
+ case MUC::LeaveKick: clearPresenceQueue(); clearAfter = true; partType = " (kicked)"; break;
+ case MUC::LeaveBan: clearPresenceQueue(); clearAfter = true; partType = " (banned)"; break;
+ case MUC::LeaveNotMember: clearPresenceQueue(); clearAfter = true; partType = " (no longer a member)"; break;
+ case MUC::LeaveDestroy:
+ case MUC::Disconnect:
+ case MUC::LeavePart: break;
+ }
+ partMessage = str(format(QT_TRANSLATE_NOOP("", "%1% has left the room%2%")) % occupant.getNick() % partType);
+ }
+ else {
+ switch (type) {
+ case MUC::LeaveKick: clearPresenceQueue(); clearAfter = true; partMessage = QT_TRANSLATE_NOOP("", "You have been kicked out of the room"); break;
+ case MUC::LeaveBan: clearPresenceQueue(); clearAfter = true; partMessage = QT_TRANSLATE_NOOP("", "You have been banned from the room"); break;
+ case MUC::LeaveNotMember: clearPresenceQueue(); clearAfter = true; partMessage = QT_TRANSLATE_NOOP("", "You are no longer a member of the room and have been removed"); break;
+ case MUC::LeaveDestroy: clearPresenceQueue(); clearAfter = true; partMessage = QT_TRANSLATE_NOOP("", "The room has been destroyed"); break;
+ case MUC::Disconnect:
+ case MUC::LeavePart: partMessage = QT_TRANSLATE_NOOP("", "You have left the room");
+ }
+ }
if (!reason.empty()) {
partMessage += " (" + reason + ")";
}
partMessage += ".";
if (occupant.getNick() != nick_) {
if (shouldUpdateJoinParts()) {
updateJoinParts();
} else {
addPresenceMessage(partMessage);
}
roster_->removeContact(JID(toJID_.getNode(), toJID_.getDomain(), occupant.getNick()));
} else {
addPresenceMessage(partMessage);
parting_ = true;
processUserPart();
}
+ if (clearAfter) {
+ clearPresenceQueue();
+ }
}
void MUCController::handleOccupantPresenceChange(boost::shared_ptr<Presence> presence) {
receivedActivity();
roster_->applyOnItems(SetPresence(presence, JID::WithResource));
}
bool MUCController::isIncomingMessageFromMe(boost::shared_ptr<Message> message) {
JID from = message->getFrom();
return nick_ == from.getResource();
}
std::string MUCController::senderDisplayNameFromMessage(const JID& from) {
return from.getResource();
}
void MUCController::preSendMessageRequest(boost::shared_ptr<Message> message) {
message->setType(Swift::Message::Groupchat);
}
boost::optional<boost::posix_time::ptime> MUCController::getMessageTimestamp(boost::shared_ptr<Message> message) const {
return message->getTimestampFrom(toJID_);
}
void MUCController::updateJoinParts() {
chatWindow_->replaceLastMessage(generateJoinPartString(joinParts_));
}
void MUCController::appendToJoinParts(std::vector<NickJoinPart>& joinParts, const NickJoinPart& newEvent) {
std::vector<NickJoinPart>::iterator it = joinParts.begin();
bool matched = false;
for (; it != joinParts.end(); ++it) {
if ((*it).nick == newEvent.nick) {
matched = true;
JoinPart type = (*it).type;
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index 78546c8..9f6c7fb 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -113,79 +113,97 @@ void MUC::handleIncomingPresence(Presence::ref presence) {
}
}
// On the first incoming presence, check if our join has succeeded
// (i.e. we start getting non-error presence from the MUC) or not
if (!joinSucceeded_) {
if (presence->getType() == Presence::Error) {
std::string reason;
onJoinFailed(presence->getPayload<ErrorPayload>());
return;
}
else {
joinSucceeded_ = true;
presenceSender->addDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::AndSendPresence);
}
}
std::string nick = presence->getFrom().getResource();
if (nick.empty()) {
return;
}
MUCOccupant::Role role(MUCOccupant::NoRole);
MUCOccupant::Affiliation affiliation(MUCOccupant::NoAffiliation);
boost::optional<JID> realJID;
if (mucPayload && mucPayload->getItems().size() > 0) {
role = mucPayload->getItems()[0].role ? mucPayload->getItems()[0].role.get() : MUCOccupant::NoRole;
affiliation = mucPayload->getItems()[0].affiliation ? mucPayload->getItems()[0].affiliation.get() : MUCOccupant::NoAffiliation;
realJID = mucPayload->getItems()[0].realJID;
}
//100 is non-anonymous
//TODO: 100 may also be specified in a <message/>
//170 is room logging to http
//TODO: Nick changes
if (presence->getType() == Presence::Unavailable) {
+ LeavingType type = LeavePart;
+ if (mucPayload) {
+ if (boost::dynamic_pointer_cast<MUCDestroyPayload>(mucPayload->getPayload())) {
+ type = LeaveDestroy;
+ }
+ else foreach (MUCUserPayload::StatusCode status, mucPayload->getStatusCodes()) {
+ if (status.code == 307) {
+ type = LeaveKick;
+ }
+ else if (status.code == 301) {
+ type = LeaveBan;
+ }
+ else if (status.code == 321) {
+ type = LeaveNotMember;
+ }
+ }
+ }
+
if (presence->getFrom() == ownMUCJID) {
- handleUserLeft(Part);
+ handleUserLeft(type);
return;
}
else {
std::map<std::string,MUCOccupant>::iterator i = occupants.find(nick);
if (i != occupants.end()) {
//TODO: part type
- onOccupantLeft(i->second, Part, "");
+ onOccupantLeft(i->second, type, "");
occupants.erase(i);
}
}
}
else if (presence->getType() == Presence::Available) {
std::map<std::string, MUCOccupant>::iterator it = occupants.find(nick);
MUCOccupant occupant(nick, role, affiliation);
bool isJoin = true;
if (realJID) {
occupant.setRealJID(realJID.get());
}
if (it != occupants.end()) {
isJoin = false;
MUCOccupant oldOccupant = it->second;
if (oldOccupant.getRole() != role) {
onOccupantRoleChanged(nick, occupant, oldOccupant.getRole());
}
if (oldOccupant.getAffiliation() != affiliation) {
onOccupantAffiliationChanged(nick, affiliation, oldOccupant.getAffiliation());
}
occupants.erase(it);
}
std::pair<std::map<std::string, MUCOccupant>::iterator, bool> result = occupants.insert(std::make_pair(nick, occupant));
if (isJoin) {
onOccupantJoined(result.first->second);
}
onOccupantPresenceChange(presence);
}
if (mucPayload && !joinComplete_) {
foreach (MUCUserPayload::StatusCode status, mucPayload->getStatusCodes()) {
if (status.code == 110) {
/* Simply knowing this is your presence is enough, 210 doesn't seem to be necessary. */
joinComplete_ = true;
if (ownMUCJID != presence->getFrom()) {
presenceSender->removeDirectedPresenceReceiver(ownMUCJID, DirectedPresenceSender::DontSendPresence);
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index 39acb22..60ed697 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -1,70 +1,70 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <Swiften/JID/JID.h>
#include <string>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/Presence.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swiften/Elements/MUCOwnerPayload.h>
#include <Swiften/Elements/MUCAdminPayload.h>
#include <Swiften/Elements/Form.h>
#include <boost/shared_ptr.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <boost/signals/connection.hpp>
#include <map>
namespace Swift {
class StanzaChannel;
class IQRouter;
class DirectedPresenceSender;
class MUC {
public:
typedef boost::shared_ptr<MUC> ref;
enum JoinResult { JoinSucceeded, JoinFailed };
- enum LeavingType { Part, Disconnect };
+ enum LeavingType { LeavePart, LeaveKick, LeaveBan, LeaveDestroy, LeaveNotMember, Disconnect };
public:
MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry);
/**
* Returns the (bare) JID of the MUC.
*/
JID getJID() const {
return ownMUCJID.toBare();
}
void joinAs(const std::string &nick);
void joinWithContextSince(const std::string &nick, const boost::posix_time::ptime& since);
/*void queryRoomInfo(); */
/*void queryRoomItems(); */
std::string getCurrentNick();
void part();
void handleIncomingMessage(Message::ref message);
/** Expose public so it can be called when e.g. user goes offline */
void handleUserLeft(LeavingType);
/** Get occupant information*/
const MUCOccupant& getOccupant(const std::string& nick);
bool hasOccupant(const std::string& nick);
void kickOccupant(const JID& jid);
void changeOccupantRole(const JID& jid, MUCOccupant::Role role);
void requestAffiliationList(MUCOccupant::Affiliation);
void changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation);
void changeSubject(const std::string& subject);
void requestConfigurationForm();
void configureRoom(Form::ref);
void cancelConfigureRoom();
void destroyRoom();
/** Send an invite for the person to join the MUC */
void invitePerson(const JID& person, const std::string& reason = "");
void setCreateAsReservedIfNew() {createAsReservedIfNew = true;}