rocketchatchannelservice.cpp 29.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/********************************************************************************************
 *                                                                                          *
 * Copyright (C) 2017 Armin Felder, Dennis Beier                                            *
 * This file is part of RocketChatMobileEngine <https://git.fairkom.net/chat/fairchat>.     *
 *                                                                                          *
 * RocketChatMobileEngine is free software: you can redistribute it and/or modify           *
 * it under the terms of the GNU General Public License as published by                     *
 * the Free Software Foundation, either version 3 of the License, or                        *
 * (at your option) any later version.                                                      *
 *                                                                                          *
 * RocketChatMobileEngine is distributed in the hope that it will be useful,                *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                           *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                            *
 * GNU General Public License for more details.                                             *
 *                                                                                          *
 * You should have received a copy of the GNU General Public License                        *
 * along with RocketChatMobileEngine. If not, see <http://www.gnu.org/licenses/>.           *
 *                                                                                          *
 ********************************************************************************************/



armin's avatar
armin committed
23
24
#include "rocketchatchannelservice.h"

armin's avatar
armin committed
25
26
#include <CustomModels/models.h>

armin's avatar
armin committed
27
28


armin's avatar
armin committed
29
RocketChatChannelService::RocketChatChannelService( QObject *parent, RocketChatServerData *pServer, MessageService *pMessageService, FileService *pFileService ): QObject( parent ), mFileService( pFileService )
armin's avatar
armin committed
30
31
32
33
{
    this->mServer = pServer;
    this->mMessageService = pMessageService;
    mStorage = PersistanceLayer::instance();
34
35
    qRegisterMetaType<channelVector>( "channelVector" );
    qRegisterMetaType<userVector>( "userVector" );
armin's avatar
armin committed
36
37
38

}

Armin Felder's avatar
Armin Felder committed
39
QSharedPointer<RocketChatChannel> RocketChatChannelService::createChannelObject( const QString &pRoomId, const QString &pName, const QString &pType, bool insertIntoRepo )
armin's avatar
armin committed
40
{
armin's avatar
armin committed
41
42
    if ( mServer ) {
        auto ptr = QSharedPointer<RocketChatChannel>::create( mServer, mMessageService, pRoomId, pName, pType );
armin's avatar
armin committed
43

armin's avatar
armin committed
44
45
46
47
48
        if ( Q_LIKELY( mChannels ) ) {
            mChannels->add( ptr );
        } else {
            qCritical() << "Channelsrepo not available to ChannelService";
        }
49

armin's avatar
armin committed
50
        fillChannelWithMessages( ptr );
armin's avatar
armin committed
51

armin's avatar
armin committed
52
53
        return ptr;
    } else {
Armin Felder's avatar
Armin Felder committed
54
55
        return nullptr;
    }
armin's avatar
armin committed
56
57
}

Armin Felder's avatar
Armin Felder committed
58
QSharedPointer<RocketChatChannel> RocketChatChannelService::createChannelObject( const QString &pRoomId, const QString &pName, const QString &pType, const QString &pUsername, bool insertIntoRepo )
armin's avatar
armin committed
59
{
armin's avatar
armin committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    if ( mServer ) {
        auto ptr = QSharedPointer<RocketChatChannel>::create( mServer, mMessageService, pRoomId, pName, pType );

        if ( pType == "d" ) {
            ptr->setUsername( pUsername );

            //TODO: place RocketChatUserObject inside Message instead...
            auto then = [ ptr ]( QSharedPointer<TempFile> tempfile, bool showInline ) {
                ptr->setAvatarImg( tempfile );
            };
            auto avatarUrl = "/avatar/" + pUsername + ".jpg";
            auto avatarRequest = QSharedPointer<FileRequest>::create( avatarUrl, "temp", then, true );
            mFileService->getFileRessource( avatarRequest );
        }
armin's avatar
armin committed
74

armin's avatar
armin committed
75
76
77
78
79
80
        //TODO: this should not be done here!
        if ( insertIntoRepo && Q_LIKELY( mChannels ) ) {
            mChannels->add( ptr );
        } else if ( !mChannels ) {
            qCritical() << "Channelsrepo not available to ChannelService";
        }
armin's avatar
armin committed
81

armin's avatar
armin committed
82
        fillChannelWithMessages( ptr );
armin's avatar
armin committed
83

armin's avatar
armin committed
84
        return ptr;
armin's avatar
armin committed
85
    } else {
Armin Felder's avatar
Armin Felder committed
86
87
        return nullptr;
    }
armin's avatar
armin committed
88
89
}

armin's avatar
armin committed
90

armin's avatar
armin committed
91
QList<QSharedPointer<RocketChatChannel> > RocketChatChannelService::processChannelData( const QJsonArray &pChannelArray, bool pJoined, bool pUpdateOnly )
armin's avatar
armin committed
92
{
armin's avatar
armin committed
93
    QList<QSharedPointer<RocketChatChannel> > vec;
armin's avatar
armin committed
94

armin's avatar
armin committed
95
96
97
98
    if ( mServer ) {
        std::tuple<QString, QString> openChannelTupel =  mStorage->getCurrentChannel();
        QString openChannel = std::get<0>( openChannelTupel );
        mStorage->transaction();
armin's avatar
armin committed
99

armin's avatar
armin committed
100
101
        for ( const auto &currentChannel : pChannelArray ) {
            QJsonObject currentChannelObject = currentChannel.toObject();
armin's avatar
armin committed
102

armin's avatar
armin committed
103
104
105
            if ( Q_LIKELY( ( currentChannelObject.contains( "rid" ) &&
                             currentChannelObject.contains( "name" ) ) || ( currentChannelObject.contains( "_id" ) &&
                                     currentChannelObject.contains( "t" ) ) ) ) {
armin's avatar
armin committed
106

armin's avatar
armin committed
107
108
109
110
111
                QString id = currentChannelObject["rid"].toString();
                QString name = currentChannelObject["name"].toString();
                QString type = currentChannelObject["t"].toString();
                QString username = "";
                QString chatPartnerId ;
armin's avatar
armin committed
112

armin's avatar
armin committed
113
                qint64 updatedAt = -1;
armin's avatar
armin committed
114

armin's avatar
armin committed
115
116
117
                //don't ask ...
                if ( currentChannelObject.contains( QStringLiteral( "_updatedAt" ) ) ) {
                    auto updatedObj = currentChannelObject[QStringLiteral( "_updatedAt" )].toObject();
armin's avatar
armin committed
118
119
                    updatedAt = static_cast<qint64>( updatedObj[QStringLiteral( "$date" )].toDouble() );
                }
armin's avatar
armin committed
120

armin's avatar
armin committed
121
122
123
                if ( id == "" ) {
                    id = currentChannelObject["_id"].toString();
                }
armin's avatar
armin committed
124

armin's avatar
armin committed
125
126
127
                if ( type == "d" ) {
                    username = name;
                    name = currentChannelObject["fname"].toString();
128

armin's avatar
armin committed
129
130
131
132
                    QString ownUser = mServer->getUserId();
                    chatPartnerId = id;
                    chatPartnerId.replace( ownUser, "" );
                }
armin's avatar
ias    
armin committed
133

armin's avatar
armin committed
134
135
136
137
                //TODO: refactor me please!
                if ( pUpdateOnly && !mChannels->contains( id ) ) {
                    continue;
                }
armin's avatar
ias    
armin committed
138

armin's avatar
armin committed
139
140
141
142
143
                if ( currentChannelObject.contains( "open" ) && !currentChannelObject["open"].toBool() ) {
                    mChannels->remove( id );
                    mStorage->deleteChannel( id );
                    continue;
                }
armin's avatar
ias    
armin committed
144

armin's avatar
armin committed
145
                QSharedPointer<RocketChatChannel> channel = nullptr;
armin's avatar
armin committed
146

armin's avatar
armin committed
147
148
149
150
151
                if ( mChannels->contains( id ) ) {
                    channel = mChannels->get( id );
                } else {
                    channel = createChannelObject( id, name, type, username );
                }
armin's avatar
armin committed
152

armin's avatar
armin committed
153
                if ( !channel.isNull() ) {
armin's avatar
armin committed
154
155


armin's avatar
armin committed
156
157
158
                    if ( type == "d" ) {
                        channel->setChatPartnerId( chatPartnerId );
                    }
armin's avatar
ias    
armin committed
159

armin's avatar
armin committed
160
161
162
                    if ( !name.isEmpty() ) {
                        channel->setName( name );
                    }
armin's avatar
armin committed
163

armin's avatar
armin committed
164
165
166
                    if ( currentChannelObject.contains( "ro" ) ) {
                        channel->setReadOnly( currentChannelObject["ro"].toBool() );
                    }
armin's avatar
armin committed
167

armin's avatar
armin committed
168
169
170
                    if ( currentChannelObject.contains( "archived" ) ) {
                        channel->setArchived( currentChannelObject["archived"].toBool() );
                    }
armin's avatar
armin committed
171

armin's avatar
armin committed
172
173
                    if ( currentChannelObject.contains( "blocker" ) ) {
                        channel->setBlocked( currentChannelObject["blocker"].toBool() );
armin's avatar
armin committed
174

armin's avatar
armin committed
175
176
177
                        if ( currentChannelObject["blocker"].toBool() ) {
                            mMessageService->addChannelToBlockList( channel->getRoomId() );
                        }
armin's avatar
armin committed
178
                    }
armin's avatar
armin committed
179

armin's avatar
armin committed
180
181
                    if ( currentChannelObject.contains( "u" ) ) {
                        auto userObj = currentChannelObject["u"].toObject();
182

armin's avatar
armin committed
183
184
185
186
                        if ( userObj.contains( "username" ) && userObj.contains( "_id" ) ) {
                            channel->setOwnerName( userObj["username"].toString() );
                            channel->setOwnerId( userObj["_id"].toString() );
                        }
187
188
                    }

armin's avatar
armin committed
189
190
191
192
193
194
195
196
197
                    if ( currentChannelObject.contains( "muted" ) ) {
                        auto muted = currentChannelObject["muted"].toArray().toVariantList();
                        auto mutedUsers = QVariant( muted ).toStringList();
                        channel->setMuted( mutedUsers );

                        if ( currentChannelObject.contains( "username" ) && mutedUsers.contains( currentChannelObject["username"].toString() ) ) {
                            channel->setSelfMuted( true );
                        }
                    }
armin's avatar
armin committed
198

armin's avatar
armin committed
199
200
201
202
                    if ( id == openChannel ) {
                        channel->setUnreadMessages( 0 );
                    } else if ( currentChannelObject.contains( "unread" ) ) {
                        channel->setUnreadMessages( static_cast<unsigned int>( currentChannelObject["unread"].toInt() ) );
armin's avatar
armin committed
203
                    }
204

armin's avatar
armin committed
205
206
                    channel->setJoined( pJoined );
                    loadUsersOfChannel( channel );
207

armin's avatar
armin committed
208
                    subscribeChannel( channel );
armin's avatar
armin committed
209

armin's avatar
armin committed
210
                    channel->setUpdatedAt( updatedAt );
211

armin's avatar
armin committed
212
213
214
                    vec.append( channel );
                    persistChannel( channel );
                }
armin's avatar
armin committed
215

armin's avatar
armin committed
216
217
218
            }
        }

armin's avatar
armin committed
219
220
        mStorage->askForcommit();
    }
armin's avatar
armin committed
221

armin's avatar
armin committed
222
    return vec;
armin's avatar
armin committed
223
224
}

armin's avatar
armin committed
225

armin's avatar
as    
armin committed
226
void RocketChatChannelService::loadJoinedChannelsFromServer( )
armin's avatar
armin committed
227
{
armin's avatar
ias    
armin committed
228
    DdpCallback subscriptionSuccess = [ = ]( QJsonObject pResponse, MeteorDDP * pDdpApi ) {
armin's avatar
armin committed
229
        Q_UNUSED( pDdpApi );
230
231

        if ( Q_LIKELY( pResponse.contains( "result" ) ) ) {
armin's avatar
armin committed
232
            QJsonArray channels = pResponse["result"].toArray();
233
234
235
236
            auto channelsParsed = processChannelData( channels, true, false );
            emit channelsLoaded( channelsParsed, true );
        }
    };
armin's avatar
ias    
armin committed
237
    DdpCallback roomsSuccess = [ = ]( QJsonObject pResponse, MeteorDDP * pDdpApi ) {
238
239
240
241
242
        Q_UNUSED( pDdpApi );

        if ( Q_LIKELY( pResponse.contains( "result" ) ) ) {
            QJsonArray channels = pResponse["result"].toArray();
            auto channelsParsed = processChannelData( channels, true, true );
armin's avatar
armin committed
243
244
245

            auto channelsLocal = mChannels->getElements();

armin's avatar
as    
armin committed
246
            for ( auto it = channelsLocal.begin(); it != channelsLocal.end(); it++ ) {
armin's avatar
armin committed
247
248
                bool deleteFlag = true;

armin's avatar
armin committed
249
                for ( const auto &channelServer : channelsParsed ) {
armin's avatar
as    
armin committed
250
                    if ( channelServer->getRoomId() == it.key() ) {
armin's avatar
armin committed
251
252
253
254
255
                        deleteFlag = false;
                    }
                }

                if ( deleteFlag ) {
armin's avatar
as    
armin committed
256
                    deleteChannel( it.key() );
armin's avatar
armin committed
257
258
259
                }
            }

armin's avatar
armin committed
260
261
262
            emit channelsLoaded( channelsParsed, true );
        }
    };
armin's avatar
c++ 17    
armin committed
263

264
265
    auto subscriptionsSuccess = [ = ]( QJsonObject pResponse, MeteorDDP * pDdpApi ) {
        subscriptionSuccess( pResponse, pDdpApi );
armin's avatar
c++ 17    
armin committed
266
267
        QJsonArray empty;
        auto rooms = QSharedPointer<DDPMethodRequest>::create( "rooms/get", empty, roomsSuccess );
268
269
        mServer->sendDdprequest( rooms );
    } ;
armin's avatar
c++ 17    
armin committed
270
271
    QJsonArray empty;
    auto subscriptions = QSharedPointer<DDPMethodRequest>::create( QStringLiteral( "subscriptions/get" ), empty, subscriptionsSuccess );
armin's avatar
armin committed
272
273
274
275
276
277
278
279
280
    mServer->sendDdprequest( subscriptions );
}



void RocketChatChannelService::loadJoinedChannelsFromDb()
{
    QList<QVariantHash> roomsList = mStorage->getChannels();

281
    if ( Q_LIKELY( !roomsList.isEmpty() ) ) {
armin's avatar
armin committed
282
283
284
285
        QList<QSharedPointer<RocketChatChannel>> channels;
        QList<QSharedPointer<RocketChatChannel>> channelsP;
        QList<QSharedPointer<RocketChatChannel>> channelsD;
        QList<QSharedPointer<RocketChatChannel>> channelsC;
Armin Felder's avatar
Armin Felder committed
286

armin's avatar
armin committed
287

288
289
        auto users = Models::getUsersModel();

armin's avatar
armin committed
290
        for ( const auto &roomHash : roomsList ) {
Armin Felder's avatar
Armin Felder committed
291
            auto channelPointer =  createChannelObject( roomHash["id"].toString(), roomHash["name"].toString(), roomHash["type"].toString(), roomHash["username"].toString(), false );
292
293

            if ( !channelPointer.isNull() ) {
armin's avatar
armin committed
294
295
296
297
                channelPointer->setMuted( roomHash["list"].toStringList() );
                channelPointer->setArchived( roomHash["archived"].toBool() );
                channelPointer->setReadOnly( roomHash["readOnly"].toBool() );
                channelPointer->setJoined( roomHash["joined"].toBool() );
298
                channelPointer->setChatPartnerId( roomHash["chatPartnerId"].toString() );
armin's avatar
armin committed
299
                channelPointer->setUpdatedAt( roomHash["updatedAt"].toLongLong() );
300
301
302
303
304
305
306

                if ( channelPointer->getType() == "d" ) {
                    auto user = users->getUserById( channelPointer->getChatPartnerId() );

                    if ( !user.isNull() ) {
                        channelPointer->setChatPartner( user );
                    } else {
307
                        auto newUser = QSharedPointer<RocketChatUser>::create( channelPointer->getChatPartnerId() );
armin's avatar
isad    
armin committed
308
                        newUser->setUserName( roomHash["username"].toString() );
309
                        channelPointer->setChatPartner( newUser );
armin's avatar
as    
armin committed
310
311
                        auto result = QMetaObject::invokeMethod( users, "addUser", Q_ARG( User, newUser ) );
                        Q_ASSERT( result );
312
313
                    }
                }
armin's avatar
armin committed
314
315
316
317
318

                if ( roomHash.contains( "blocked" ) ) {
                    channelPointer->setBlocked( roomHash["blocked"].toBool() );
                }

armin's avatar
armin committed
319
                channels.append( channelPointer );
armin's avatar
armin committed
320
321
322
323
324
325
326

                if ( channelPointer->getType() == "p" ) {
                    channelsP.append( channelPointer );
                } else if ( channelPointer->getType() == "c" ) {
                    channelsC.append( channelPointer );
                } else if ( channelPointer->getType() == "d" ) {
                    channelsD.append( channelPointer );
Armin Felder's avatar
Armin Felder committed
327
                }
armin's avatar
armin committed
328
            }
armin's avatar
armin committed
329
        }
armin's avatar
armin committed
330
331
332
333

        mChannels->add( "p", channelsP );
        mChannels->add( "c", channelsC );
        mChannels->add( "d", channelsD );
armin's avatar
armin committed
334
335
336
337
        emit  channelsLoaded( channels, true );
    }
}

armin's avatar
cleanup    
armin committed
338
void RocketChatChannelService::persistChannel( const QSharedPointer<RocketChatChannel> &pChannel )
armin's avatar
armin committed
339
{
340
341
342
343
344
345
346
347
348
349
    auto id = pChannel->getRoomId();
    auto name  = pChannel->getName();
    auto type = pChannel->getType();
    auto muted = pChannel->getMuted().join( "," );
    auto username = pChannel->getUsername();
    auto joined = pChannel->getJoined();
    auto archived = pChannel->getArchived();
    auto readonly = pChannel->getReadOnly();
    auto blocked = pChannel->getBlocked();
    auto chatPartnerId = pChannel->getChatPartnerId();
armin's avatar
armin committed
350
351
    qint64 updatedAt = pChannel->getUpdatedAt();
    mStorage->addChannel( id, name, type, updatedAt, joined, readonly, muted, archived, blocked, username, chatPartnerId );
armin's avatar
armin committed
352
}
armin's avatar
as    
armin committed
353
354
355
356
357
358
359
360
361
362
363

void RocketChatChannelService::persist()
{
    mStorage->transaction();

    for ( const auto &channel : mChannels->getElements() ) {
        persistChannel( channel );
    }

    mStorage->askForcommit();
}
armin's avatar
armin committed
364
365
366
367
368
369
/**
 * Fills the channel with users, which are loaded from the server
 *
 * @brief RocketChatChannelService::loadUsersOfChannel
 * @param channel
 */
armin's avatar
cleanup    
armin committed
370
void RocketChatChannelService::loadUsersOfChannel( const QSharedPointer<RocketChatChannel> &pChannel )
armin's avatar
armin committed
371
{
372
    if ( !pChannel.isNull() ) {
armin's avatar
armin committed
373
374
        QString channelId = pChannel->getRoomId();
        QJsonArray params = {channelId, true};
375
        auto request = QSharedPointer<DDPMethodRequest>::create( "getUsersOfRoom", params );
armin's avatar
ias    
armin committed
376
        DdpCallback success = [ = ]( QJsonObject data, MeteorDDP * ddp ) {
armin's avatar
armin committed
377
378
            Q_UNUSED( ddp );

379
            if ( Q_LIKELY( data.contains( "result" ) ) ) {
armin's avatar
armin committed
380
381
                QJsonObject result = data["result"].toObject();

382
                if ( Q_LIKELY( result.contains( "records" ) && result["records"].isArray() ) ) {
armin's avatar
armin committed
383
384
                    QJsonArray records = result["records"].toArray();
                    QVector<QSharedPointer<RocketChatUser>> userList;
armin's avatar
armin committed
385
                    auto userModel = Models::getUsersModel();
armin's avatar
armin committed
386
387

                    //crate new user objects and add them to the channel
armin's avatar
armin committed
388
                    for ( const auto current : records ) {
armin's avatar
armin committed
389
390
                        if ( current.type() == QJsonValue::Object ) {
                            QJsonObject userObject = current.toObject();
391
392
                            QString username;
                            QString userId;
armin's avatar
armin committed
393
                            QString status;
394
395
396
397
398
399
400
401
402
403
404
                            QString name;

                            if ( userObject.contains( "id" ) ) {
                                userId = userObject["id"].toString();
                            } else if ( userObject.contains( "_id" ) ) {
                                userId = userObject["_id"].toString();
                            }

                            if ( userObject.contains( "username" ) ) {
                                username = userObject["username"].toString();
                            }
armin's avatar
armin committed
405
406
407
408
409

                            if ( userObject.contains( "status" ) ) {
                                status = userObject["status"].toString();
                            }

410
411
                            if ( userObject.contains( "name" ) ) {
                                name = userObject["name"].toString();
armin's avatar
armin committed
412
413
                            }

414
                            auto user = QSharedPointer<RocketChatUser>( nullptr );
armin's avatar
armin committed
415

416

armin's avatar
armin committed
417
418
419
420
421
422
423
424
425
                            auto oldUser = userModel->getUserById( userId );

                            if ( !oldUser.isNull() ) {
                                oldUser->setName( name );
                                oldUser->setUserId( username );
                                oldUser->setStatus( status );
                                user = oldUser;

                            } else {
426
                                auto newUser = QSharedPointer<RocketChatUser>::create( userId );
armin's avatar
armin committed
427
428
429
430
431
432
433
434
435
436
                                newUser->setName( name );
                                newUser->setUserName( username );
                                newUser->setStatus( status );
                                user = newUser;
                            }

                            if ( userId == pChannel->getChatPartnerId() ) {
                                pChannel->setChatPartner( user );
                            }

armin's avatar
armin committed
437
                            userList.append( user );
armin's avatar
armin committed
438

439
                        } else if ( current.type() == QJsonValue::String ) {
armin's avatar
armin committed
440
                            //TODO: still relevant?
armin's avatar
armin committed
441
                            QString name = current.toString();
442
                            auto user = QSharedPointer<RocketChatUser>::create( name );
armin's avatar
armin committed
443
444
                            userList.append( user );
                        }
armin's avatar
armin committed
445
446
447
                    }

                    emit usersLoaded( channelId, userList );
armin's avatar
armin committed
448
449
                }
            }
armin's avatar
armin committed
450
451
452
453
        };
        request->setSuccess( success );
        mServer->sendDdprequest( request );
    }
armin's avatar
armin committed
454
455
}

armin's avatar
cleanup    
armin committed
456
void RocketChatChannelService::subscribeChannel( const QSharedPointer<RocketChatChannel> &pChannel )
armin's avatar
armin committed
457
{
458
    if ( !pChannel.isNull() ) {
armin's avatar
armin committed
459
        QString roomId = pChannel->getRoomId();
armin's avatar
ias    
armin committed
460
        subscribeChannel( roomId );
armin's avatar
armin committed
461
    }
armin's avatar
armin committed
462
463
}

armin's avatar
ias    
armin committed
464
void RocketChatChannelService::subscribeChannel( const QString &pChannel )
armin's avatar
armin committed
465
{
466
    auto subscription = QSharedPointer<RocketChatSubscribeChannelRequest>::create( pChannel );
467
468
    QJsonArray params = {pChannel + "/deleteMessage"};
    auto deletesub = QSharedPointer<DDPSubscriptionRequest>::create( "stream-notify-room", params );
armin's avatar
armin committed
469
    mServer->sendDdprequest( subscription );
Dennis Beier's avatar
Dennis Beier committed
470
    mServer->sendDdprequest( deletesub );
armin's avatar
armin committed
471
472
}

armin's avatar
armin committed
473

armin's avatar
armin committed
474

armin's avatar
cleanup    
armin committed
475
void RocketChatChannelService::fillChannelWithMessages( const QSharedPointer<RocketChatChannel> &pChannel )
armin's avatar
armin committed
476
{
477
    if ( !pChannel.isNull() ) {
armin's avatar
armin committed
478
        QString roomId = pChannel->getRoomId();
479
        auto messages = mStorage->getMessagesByRid( roomId );
armin's avatar
armin committed
480
        MessageList list;
481
482
483
484
485
486

        for ( const auto &currentMessage : messages ) {
            auto newMessage = mMessageService->parseMessage( currentMessage, false );

            if ( Q_LIKELY( !newMessage.isNull() ) ) {
                list.append( newMessage );
armin's avatar
armin committed
487
            }
armin's avatar
armin committed
488
        }
489
490

        pChannel->addMessages( list );
armin's avatar
armin committed
491
492
493
    }
}

494
495
496
497
498
499
500
501
502
503
MeteorDDP *RocketChatChannelService::getDdp() const
{
    return mDdp;
}

void RocketChatChannelService::setDdp( MeteorDDP *ddp )
{
    mDdp = ddp;
}

armin's avatar
armin committed
504
505
506
507
508
ChannelRepository *RocketChatChannelService::getChannels() const
{
    return mChannels;
}

509
void RocketChatChannelService::setChannels( ChannelRepository *pChannels )
armin's avatar
armin committed
510
{
armin's avatar
armin committed
511
512
513
    if ( pChannels ) {
        mChannels = pChannels;
    }
armin's avatar
armin committed
514
}
armin's avatar
armin committed
515
516
517
518
519

void RocketChatChannelService::leaveChannel( const QString &pId )
{
    //TODO: handle response, as soon as RC is fixed to do so
    if ( mChannels->contains( pId ) ) {
520
        auto request = QSharedPointer<RocketChatLeaveRoomRequest>::create( pId );
521
522
        auto ddp = getDdp();
        ddp->sendRequest( request );
523
        auto request2 = QSharedPointer<RocketChatHideRoomRequest>::create( pId );
armin's avatar
ias    
armin committed
524
        getDdp()->sendRequest( request2 );
armin's avatar
armin committed
525
526
527
528
529
530
531
532
        deleteChannel( pId );
    }
}

void RocketChatChannelService::deleteChannel( const QString &pId )
{
    if ( mChannels->contains( pId ) ) {
        mChannels->get( pId )->setDeleted( true );
armin's avatar
ias    
armin committed
533
        mChannels->remove( pId );
armin's avatar
armin committed
534
535
        mStorage->transaction();
        mStorage->deleteChannel( pId );
armin's avatar
ad    
armin committed
536
        mStorage->askForcommit();
armin's avatar
armin committed
537
538
539
    }
}

armin's avatar
armin committed
540
541
void RocketChatChannelService::hideRoom( const QString &pId )
{
542
    auto request = QSharedPointer<RocketChatHideRoomRequest>::create( pId );
armin's avatar
armin committed
543
544
545
546
    mDdp->sendRequest( request );
    deleteChannel( pId );
}

547
548
549
void RocketChatChannelService::reportContent( const QString &pMessageId, const QString &pAuthorId )
{
    QJsonArray params = {QStringLiteral( "abuse" )};
550
    auto request = QSharedPointer<DDPMethodRequest>::create( QStringLiteral( "createDirectMessage" ), params );
armin's avatar
ias    
armin committed
551
    DdpCallback success = [ = ]( QJsonObject pResponse, MeteorDDP * pDdp ) {
552
553
554
555
556
        if ( Q_LIKELY( pResponse.contains( QStringLiteral( "result" ) ) ) ) {
            QJsonObject result = pResponse[QStringLiteral( "result" )].toObject();

            if ( Q_LIKELY( result.contains( QStringLiteral( "rid" ) ) ) ) {
                QString rid = result[QStringLiteral( "rid" )].toString();
557
558
559
                auto subRoom = QSharedPointer<DDPSubscriptionRequest>::create( QStringLiteral( "room" ), QJsonArray( {"d" + QStringLiteral( "abuse" )} ) );
                auto subMessages = QSharedPointer<RocketChatSubscribeChannelRequest>::create( rid );
                auto channel = createChannelObject( rid, QStringLiteral( "abuse" ), "d" );
560
561
562
563
564
565

                if ( !channel.isNull() ) {

                    emit channelsLoaded( {channel}, true );
                    pDdp->sendRequest( subRoom );
                    pDdp->sendRequest( subMessages );
armin's avatar
ias    
armin committed
566
                    emit directChannelReady( rid, "d" );
567
                    QString message = QStringLiteral( "Report message with id:" ) + pMessageId + QStringLiteral( " from user with id:" ) + pAuthorId;
568
                    auto reportMessage = QSharedPointer<RocketChatMessage>::create( std::move( rid ), std::move( message ) );
569
570
571
572
573
574
575
576
577
578
579
580
                    mMessageService->sendMessage( reportMessage );
                }
            }
        }

        pDdp->unsetResponseBinding( request->getFrame() );

    };
    request->setSuccess( success );
    mServer->sendDdprequest( request );
}

armin's avatar
ias    
armin committed
581
582

void RocketChatChannelService::searchRoom( const QString &pTerm, const QString &pType )
armin's avatar
armin committed
583
584
{
    auto roomsModel = Models::getRoomSearchModel();
armin's avatar
ias    
armin committed
585
586
587
    RestRequestCallback success = [ = ]( QNetworkReply * reply, QJsonObject data, RestApi * ) {
        Q_UNUSED( reply )
        qDebug() << data;
armin's avatar
armin committed
588
        channelVector channelList;
armin's avatar
ias    
armin committed
589
        QHash<QString, bool> ids;
armin's avatar
armin committed
590
        QHash<QString, bool> names;
armin's avatar
ias    
armin committed
591

armin's avatar
armin committed
592
593
594
595
596
597
598
599
600
601
602
        if ( pType != "d" ) {
            if ( data.contains( "rooms" ) ) {
                QJsonArray rooms = data["rooms"].toArray();

                for ( auto room : rooms ) {
                    QJsonObject roomObj = room.toObject();

                    if ( roomObj.contains( "_id" ) && roomObj.contains( "name" ) && roomObj.contains( "t" ) ) {
                        QString name = roomObj["name"].toString();
                        QString id = roomObj["_id"].toString();
                        QString type = roomObj["t"].toString();
603
                        auto ptr = QSharedPointer<RocketChatChannel>::create( mServer, mMessageService, id, name, type );
armin's avatar
armin committed
604
605
606
607
                        channelList.append( ptr );
                        ids[id] = true;
                        names[name] = true;
                    }
armin's avatar
armin committed
608
609
610
                }
            }
        }
armin's avatar
ias    
armin committed
611

armin's avatar
armin committed
612
613
614
615
616
617
618
619
620
621
622
623
        if ( pType == "d" || pType.isEmpty() ) {
            if ( data.contains( "users" ) ) {
                QJsonArray rooms = data["users"].toArray();

                for ( auto room : rooms ) {
                    QJsonObject roomObj = room.toObject();

                    if ( roomObj.contains( "_id" ) && roomObj.contains( "name" ) && roomObj.contains( "username" ) ) {
                        QString name = roomObj["name"].toString();
                        QString id = roomObj["_id"].toString();
                        QString type = "d";
                        QString username = roomObj["username"].toString();
624
625
                        auto ptr = QSharedPointer<RocketChatChannel>::create( mServer, mMessageService, id, name, type );

armin's avatar
armin committed
626
627
628
629
630
                        ptr->setUsername( username );
                        channelList.append( ptr );
                        ids[id] = true;
                        names[name] = true;
                    }
armin's avatar
armin committed
631
632
633
                }
            }
        }
armin's avatar
ias    
armin committed
634

armin's avatar
armin committed
635
        channelList << searchRoomLocal( pTerm, ids, pType, names );
armin's avatar
ias    
armin committed
636

armin's avatar
as    
armin committed
637
        if ( !channelList.isEmpty() ) {
armin's avatar
armin committed
638
            std::sort( channelList.begin(), channelList.end(), []( const QSharedPointer<RocketChatChannel> &v1, const QSharedPointer<RocketChatChannel> &v2 )->bool{
armin's avatar
ias    
armin committed
639
640
                return v1->getName().toLower() < v2->getName().toLower();
            } );
armin's avatar
as    
armin committed
641
642
            auto result = QMetaObject::invokeMethod( roomsModel, "addChannels", Q_ARG( channelVector, channelList ) );
            Q_ASSERT( result );
armin's avatar
armin committed
643
644
645
        }
    };

646
    auto request = QSharedPointer<RestSpotlightRequest>::create( pTerm, "" );
armin's avatar
ias    
armin committed
647
648
649
650
651
    request->setSuccess( success );

    mServer->sendApiRequest( request );
}

armin's avatar
armin committed
652
channelVector RocketChatChannelService::searchRoomLocal( const QString &pTerm, const QHash<QString, bool>  &pFilter, const QString &pType, const QHash<QString, bool> &pNames )
armin's avatar
ias    
armin committed
653
654
{
    channelVector list;
655
    QString term = pTerm.toLower();
armin's avatar
ias    
armin committed
656

armin's avatar
armin committed
657
    for ( const auto &channel : mChannels->getElements() ) {
armin's avatar
ias    
armin committed
658
659
        QString id = channel->getRoomId();
        QString type = channel->getType();
660
661
        QString name = channel->getName().toLower();
        QString username = channel->getUsername().toLower();
armin's avatar
ias    
armin committed
662

663
        if ( !pFilter.contains( id ) && !pNames.contains( name ) && !pNames.contains( username ) && ( pType.isEmpty() || pType == type ) ) {
armin's avatar
ias    
armin committed
664

665
            if ( name.indexOf( term, Qt::CaseInsensitive ) != -1 || username.indexOf( term, Qt::CaseInsensitive ) != -1 ) {
armin's avatar
ias    
armin committed
666
667
668
669
                list.append( channel );
            }
        }
    }
armin's avatar
armin committed
670

armin's avatar
ias    
armin committed
671
    return list;
armin's avatar
armin committed
672
673
}

armin's avatar
ias    
armin committed
674
//TODO: fix
armin's avatar
cleanup    
armin committed
675
void RocketChatChannelService::openPrivateChannelWith( const QString &pUsername )
armin's avatar
armin committed
676
677
{
    QJsonArray params = {pUsername};
armin's avatar
c++ 17    
armin committed
678
    auto request = QSharedPointer<DDPMethodRequest>::create( QStringLiteral( "createDirectMessage" ), params );
armin's avatar
ias    
armin committed
679
    DdpCallback success = [ = ]( QJsonObject pResponse, MeteorDDP * pDdp ) {
680
681
        if ( Q_LIKELY( pResponse.contains( QStringLiteral( "result" ) ) ) ) {
            QJsonObject result = pResponse[QStringLiteral( "result" )].toObject();
armin's avatar
armin committed
682

683
684
            if ( Q_LIKELY( result.contains( QStringLiteral( "rid" ) ) ) ) {
                QString rid = result[QStringLiteral( "rid" )].toString();
armin's avatar
ias    
armin committed
685
686

                QSharedPointer<RocketChatChannel> channel;
687
688
                auto subRoom = QSharedPointer<DDPSubscriptionRequest>::create( QStringLiteral( "room" ), QJsonArray( {"d" + pUsername} ) );
                auto subMessages = QSharedPointer<RocketChatSubscribeChannelRequest>::create( rid );
armin's avatar
ias    
armin committed
689
690
691

                //TODO: fix
                if ( !mChannels->contains( rid ) ) {
armin's avatar
armin committed
692
                    DdpCallback success = [ = ]( QJsonObject pResponse, MeteorDDP * pDdp ) {
693
694
                        Q_UNUSED( pDdp )

armin's avatar
armin committed
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
                        if ( pResponse.contains( "result" ) ) {
                            QString name = pResponse["fname"].toString();
                            QString username = pResponse["name"].toString();
                            QString id = pResponse["_id"].toString();
                            QSharedPointer<RocketChatChannel> channel = createChannelObject( id, name, "d", username );

                            mServer->loadRecentHistory( rid );

                            if ( !channel.isNull() ) {
                                emit channelsLoaded( {channel}, true );
                                mServer->sendDdprequest( subRoom );
                                mServer->sendDdprequest( subMessages );
                                emit directChannelReady( channel->getName(), "d" );
                            }
                        }
                    };
711
                    auto detailsRequest = QSharedPointer<RocketChatGetRoomByNameAndType>::create( pUsername, "d" );
armin's avatar
armin committed
712
713
                    detailsRequest->setSuccess( success );
                    mServer->sendDdprequest( detailsRequest );
armin's avatar
ias    
armin committed
714
715
716
                } else {
                    channel = mChannels->get( rid );

armin's avatar
armin committed
717
                    mServer->loadRecentHistory( rid );
718

armin's avatar
armin committed
719
720
721
722
723
724
                    if ( !channel.isNull() ) {
                        emit channelsLoaded( {channel}, true );
                        mServer->sendDdprequest( subRoom );
                        mServer->sendDdprequest( subMessages );
                        emit directChannelReady( channel->getName(), "d" );
                    }
armin's avatar
armin committed
725
                }
armin's avatar
armin committed
726
727
728
729
730
731
732
733
734
            }
        }

        pDdp->unsetResponseBinding( request->getFrame() );

    };
    request->setSuccess( success );
    mServer->sendDdprequest( request );
}