summaryrefslogtreecommitdiffstats
blob: 6a0ab75b7e391ee88a476be1b7bf7e376a1c0581 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * 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 <Swiften/Base/API.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 SWIFTEN_API MUC {
		public:
			typedef boost::shared_ptr<MUC> ref;

			enum JoinResult { JoinSucceeded, JoinFailed };
			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();
			}

			/**
			 * Returns if the room is unlocked and other people can join the room.
			 * @return True if joinable by others; false otherwise.
			 */
			bool isUnlocked() const {
				return isUnlocked_;
			}

			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();
			std::map<std::string, MUCOccupant> getOccupants() const;
			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 = "", bool isImpromptu = false, bool isReuseChat = false);
			void setCreateAsReservedIfNew() {createAsReservedIfNew = true;}
			void setPassword(const boost::optional<std::string>& password);
			
		public:
			boost::signal<void (const std::string& /*nick*/)> onJoinComplete;
			boost::signal<void (ErrorPayload::ref)> onJoinFailed;
			boost::signal<void (ErrorPayload::ref, const JID&, MUCOccupant::Role)> onRoleChangeFailed;
			boost::signal<void (ErrorPayload::ref, const JID&, MUCOccupant::Affiliation)> onAffiliationChangeFailed;
			boost::signal<void (ErrorPayload::ref)> onConfigurationFailed;
			boost::signal<void (ErrorPayload::ref)> onAffiliationListFailed;
			boost::signal<void (Presence::ref)> onOccupantPresenceChange;
			boost::signal<void (const std::string&, const MUCOccupant& /*now*/, const MUCOccupant::Role& /*old*/)> onOccupantRoleChanged;
			boost::signal<void (const std::string&, const MUCOccupant::Affiliation& /*new*/, const MUCOccupant::Affiliation& /*old*/)> onOccupantAffiliationChanged;
			boost::signal<void (const MUCOccupant&)> onOccupantJoined;
			boost::signal<void (const MUCOccupant&, LeavingType, const std::string& /*reason*/)> onOccupantLeft;
			boost::signal<void (Form::ref)> onConfigurationFormReceived;
			boost::signal<void (MUCOccupant::Affiliation, const std::vector<JID>&)> onAffiliationListReceived;
			boost::signal<void ()> onUnlocked;
			/* boost::signal<void (const MUCInfo&)> onInfoResult; */
			/* boost::signal<void (const blah&)> onItemsResult; */
			

		private:
			bool isFromMUC(const JID& j) const {
				return ownMUCJID.equals(j, JID::WithoutResource);
			}

			const std::string& getOwnNick() const {
				return ownMUCJID.getResource();
			}

		private:
			void handleIncomingPresence(Presence::ref presence);
			void internalJoin(const std::string& nick);
			void handleCreationConfigResponse(MUCOwnerPayload::ref, ErrorPayload::ref);
			void handleOccupantRoleChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Role);
			void handleAffiliationChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Affiliation);
			void handleAffiliationListResponse(MUCAdminPayload::ref, ErrorPayload::ref, MUCOccupant::Affiliation);
			void handleConfigurationFormReceived(MUCOwnerPayload::ref, ErrorPayload::ref);
			void handleConfigurationResultReceived(MUCOwnerPayload::ref, ErrorPayload::ref);

		private:
			JID ownMUCJID;
			StanzaChannel* stanzaChannel;
			IQRouter* iqRouter_;
			DirectedPresenceSender* presenceSender;
			MUCRegistry* mucRegistry;
			std::map<std::string, MUCOccupant> occupants;
			bool joinSucceeded_;
			bool joinComplete_;
			boost::bsignals::scoped_connection scopedConnection_;
			boost::posix_time::ptime joinSince_;
			bool createAsReservedIfNew;
			bool unlocking;
			bool isUnlocked_;
			boost::optional<std::string> password;
	};
}