From d4789216fc8894a5ce3ed359851422acecfe6bdb Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Wed, 19 Oct 2011 16:02:47 +0100
Subject: For abnormal MUC parts, give the reason.

Makes abnormals immune to presence folding.

Resolves: #1004

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
@@ -449,12 +449,35 @@ 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 + ")";
 	}
@@ -472,6 +495,9 @@ void MUCController::handleOccupantLeft(const MUCOccupant& occupant, MUC::Leaving
 		parting_ = true;
 		processUserPart();
 	}
+	if (clearAfter) {
+		clearPresenceQueue();
+	}
 }
 
 void MUCController::handleOccupantPresenceChange(boost::shared_ptr<Presence> presence) {
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
@@ -145,15 +145,33 @@ void MUC::handleIncomingPresence(Presence::ref presence) {
 	//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);
 			}
 		}
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
@@ -32,7 +32,7 @@ namespace Swift {
 			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);
-- 
cgit v0.10.2-6-g49f6