1 /*
2  * %kadu copyright begin%
3  * Copyright 2014 Rafał Przemysław Malinowski (rafal.przemyslaw.malinowski@gmail.com)
4  * %kadu copyright end%
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "jabber-room-chat-service.h"
21 
22 #include "services/jabber-presence-service.h"
23 #include "jabber-room-chat.h"
24 #include "jabber-protocol.h"
25 #include "jid.h"
26 
27 #include "buddies/buddy-manager.h"
28 #include "chat/chat-details-room.h"
29 #include "chat/chat-manager.h"
30 #include "chat/chat.h"
31 #include "contacts/contact-manager.h"
32 #include "message/message-storage.h"
33 
34 #include <qxmpp/QXmppClient.h>
35 #include <qxmpp/QXmppMessage.h>
36 #include <qxmpp/QXmppMucManager.h>
37 
JabberRoomChatService(QXmppClient * client,QXmppMucManager * muc,Account account,QObject * parent)38 JabberRoomChatService::JabberRoomChatService(QXmppClient *client, QXmppMucManager *muc, Account account, QObject *parent) :
39 		AccountService{account, parent},
40 		m_client{client},
41 		m_muc{muc}
42 {
43 	connect(m_client, SIGNAL(connected()), this, SLOT(connected()));
44 }
45 
~JabberRoomChatService()46 JabberRoomChatService::~JabberRoomChatService()
47 {
48 }
49 
setBuddyManager(BuddyManager * buddyManager)50 void JabberRoomChatService::setBuddyManager(BuddyManager *buddyManager)
51 {
52 	m_buddyManager = buddyManager;
53 }
54 
setChatManager(ChatManager * chatManager)55 void JabberRoomChatService::setChatManager(ChatManager *chatManager)
56 {
57 	m_chatManager = chatManager;
58 	connect(m_chatManager, SIGNAL(chatOpened(Chat)), this, SLOT(chatOpened(Chat)));
59 	connect(m_chatManager, SIGNAL(chatClosed(Chat)), this, SLOT(chatClosed(Chat)));
60 }
61 
setContactManager(ContactManager * contactManager)62 void JabberRoomChatService::setContactManager(ContactManager *contactManager)
63 {
64 	m_contactManager = contactManager;
65 }
66 
setMessageStorage(MessageStorage * messageStorage)67 void JabberRoomChatService::setMessageStorage(MessageStorage *messageStorage)
68 {
69 	m_messageStorage = messageStorage;
70 }
71 
setPresenceService(JabberPresenceService * presenceService)72 void JabberRoomChatService::setPresenceService(JabberPresenceService *presenceService)
73 {
74 	m_presenceService = presenceService;
75 }
76 
init()77 void JabberRoomChatService::init()
78 {
79 	for (auto &&chat : m_chatManager->chats(account()))
80 		if (chat.isOpen() && myRoomChatDetails(chat))
81 			getOrCreateRoomChat(chat);
82 }
83 
myRoomChatDetails(const Chat & chat) const84 ChatDetailsRoom * JabberRoomChatService::myRoomChatDetails(const Chat &chat) const
85 {
86 	if (chat.chatAccount() != account())
87 		return nullptr;
88 
89 	return qobject_cast<ChatDetailsRoom *>(chat.details());
90 }
91 
connected()92 void JabberRoomChatService::connected()
93 {
94 	for (auto &&roomChat : m_chats)
95 		roomChat->join();
96 }
97 
getRoomChat(const QString & id) const98 JabberRoomChat * JabberRoomChatService::getRoomChat(const QString &id) const
99 {
100 	for (auto &&roomChat : m_chats)
101 	{
102 		auto details = myRoomChatDetails(roomChat->chat());
103 		if (details && details->room() == id)
104 			return roomChat;
105 	}
106 
107 	return nullptr;
108 }
109 
getRoomChat(const Chat & chat) const110 JabberRoomChat * JabberRoomChatService::getRoomChat(const Chat &chat) const
111 {
112 	if (chat.chatAccount() != account())
113 		return nullptr;
114 
115 	if (m_chats.contains(chat))
116 		return m_chats[chat];
117 	else
118 		return nullptr;
119 }
120 
getOrCreateRoomChat(const Chat & chat)121 JabberRoomChat * JabberRoomChatService::getOrCreateRoomChat(const Chat &chat)
122 {
123 	if (chat.chatAccount() != account())
124 		return nullptr;
125 
126 	if (m_chats.contains(chat))
127 		return m_chats[chat];
128 
129 	auto details = qobject_cast<ChatDetailsRoom *>(chat.details());
130 	if (!details)
131 		return nullptr;
132 
133 	auto room = m_muc->addRoom(details->room());
134 	auto roomChat = new JabberRoomChat{room, chat, this};
135 	roomChat->setBuddyManager(m_buddyManager);
136 	roomChat->setContactManager(m_contactManager);
137 	roomChat->setPresenceService(m_presenceService);
138 
139 	m_chats[chat] = roomChat;
140 	return roomChat;
141 }
142 
chatOpened(const Chat & chat)143 void JabberRoomChatService::chatOpened(const Chat &chat)
144 {
145 	auto roomChat = getOrCreateRoomChat(chat);
146 	if (!roomChat)
147 		return;
148 
149 	if (m_client->isConnected())
150 		roomChat->join();
151 }
152 
chatClosed(const Chat & chat)153 void JabberRoomChatService::chatClosed(const Chat &chat)
154 {
155 	auto roomChat = getRoomChat(chat);
156 	if (!roomChat)
157 		return;
158 
159 	if (!roomChat->stayInRoomAfterClosingWindow())
160 		leaveChat(chat);
161 }
162 
leaveChat(const Chat & chat)163 void JabberRoomChatService::leaveChat(const Chat &chat)
164 {
165 	auto roomChat = getRoomChat(chat);
166 	if (!roomChat)
167 		return;
168 
169 	roomChat->leave();
170 	m_chats[chat]->deleteLater();
171 	m_chats.remove(chat);
172 }
173 
isRoomChat(const Chat & chat) const174 bool JabberRoomChatService::isRoomChat(const Chat &chat) const
175 {
176 	return myRoomChatDetails(chat) != nullptr;
177 }
178 
handleReceivedMessage(const QXmppMessage & xmppMessage) const179 Message JabberRoomChatService::handleReceivedMessage(const QXmppMessage &xmppMessage) const
180 {
181 	auto jid = Jid::parse(xmppMessage.from());
182 	auto roomChat = getRoomChat(jid.bare());
183 	if (!roomChat)
184 		return Message::null;
185 
186 	if (jid.resource() == roomChat->nick()) // message from myself
187 		return Message::null;
188 
189 	auto contact = m_contactManager->byId(account(), jid.full(), ActionCreateAndAdd);
190 	auto buddy = m_buddyManager->byContact(contact, ActionCreateAndAdd);
191 	buddy.setDisplay(jid.resource());
192 	buddy.setTemporary(true);
193 
194 	auto result = m_messageStorage->create();
195 	result.setMessageChat(roomChat->chat());
196 	result.setMessageSender(contact);
197 
198 	return result;
199 }
200 
201 #include "moc_jabber-room-chat-service.cpp"
202