File indexing completed on 2024-05-05 05:40:26

0001 /***************************************************************************
0002  *  Copyright (C) 2020 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "data/chatroom.h"
0021 
0022 #include <QtConcurrent>
0023 #include <set>
0024 
0025 #include "model/playermodel.h"
0026 #include "worker/utilshelper.h"
0027 #include <diceparser_qobject/diceroller.h>
0028 
0029 namespace InstantMessaging
0030 {
0031 namespace
0032 {
0033 InstantMessaging::MessageInterface::MessageType textToType(const QString& text)
0034 {
0035     auto type= InstantMessaging::MessageInterface::Text;
0036     if(text.startsWith("!"))
0037         type= InstantMessaging::MessageInterface::Dice;
0038     else if(text.startsWith("/"))
0039         type= InstantMessaging::MessageInterface::Command;
0040 
0041     return type;
0042 }
0043 } // namespace
0044 ChatRoom::ChatRoom(PlayerModel* model, ChatRoomType type, const QStringList& recipiants, const QString& id,
0045                    QObject* parent)
0046     : QObject(parent)
0047     , m_recipiants(new FilteredPlayerModel(recipiants))
0048     , m_messageModel(new MessageModel(model))
0049     , m_type(type)
0050     , m_uuid(id)
0051 {
0052     connect(m_messageModel.get(), &MessageModel::localIdChanged, this, &ChatRoom::localIdChanged);
0053     connect(m_messageModel.get(), &MessageModel::unreadMessageChanged, this, [this]() { setUnreadMessage(true); });
0054 }
0055 
0056 ChatRoom::~ChatRoom()= default;
0057 
0058 MessageModel* ChatRoom::messageModel() const
0059 {
0060     return m_messageModel.get();
0061 }
0062 
0063 bool ChatRoom::unreadMessage() const
0064 {
0065     return m_unreadMessage;
0066 }
0067 
0068 QString ChatRoom::uuid() const
0069 {
0070     return m_uuid;
0071 }
0072 
0073 QString ChatRoom::localId() const
0074 {
0075     return m_messageModel->localId();
0076 }
0077 
0078 FilteredPlayerModel* ChatRoom::recipiants() const
0079 {
0080     return m_recipiants.get();
0081 }
0082 
0083 QString ChatRoom::title() const
0084 {
0085     return m_title;
0086 }
0087 
0088 ChatRoom::ChatRoomType ChatRoom::type() const
0089 {
0090     return m_type;
0091 }
0092 
0093 int ChatRoom::recipiantCount() const
0094 {
0095     return m_recipiants->rowCount();
0096 }
0097 
0098 void ChatRoom::setUuid(const QString& id)
0099 {
0100     if(id == m_uuid)
0101         return;
0102     m_uuid= id;
0103     emit uuidChanged(m_uuid);
0104 }
0105 
0106 void ChatRoom::setTitle(const QString& title)
0107 {
0108     if(m_title == title)
0109         return;
0110     m_title= title;
0111     emit titleChanged(m_title);
0112 }
0113 
0114 void ChatRoom::setUnreadMessage(bool b)
0115 {
0116     if(b == m_unreadMessage)
0117         return;
0118     m_unreadMessage= b;
0119     emit unreadMessageChanged(m_unreadMessage);
0120 }
0121 
0122 void ChatRoom::addMessage(const QString& text, const QUrl& url, const QString& personId, const QString& personName)
0123 {
0124     auto type= textToType(text);
0125     using IM= InstantMessaging::MessageInterface;
0126     bool valid= false;
0127     if(type == IM::Dice)
0128     { // dice
0129         auto command= text;
0130         valid= rollDice(command.remove(0, 1), personId);
0131     }
0132     else if(type == IM::Command)
0133     {
0134         auto command= text;
0135         valid= runCommand(command.remove(0, 1), personId, personName);
0136     }
0137 
0138     if(type == IM::Text || !valid)
0139     {
0140         m_messageModel->addMessage(text, url, QDateTime::currentDateTime(), localId(),
0141                                    personId.isEmpty() ? localId() : personId, type);
0142     }
0143 }
0144 
0145 bool ChatRoom::rollDice(const QString& command, const QString& personId)
0146 {
0147     using IM= InstantMessaging::MessageInterface;
0148     auto id= personId.isEmpty() ? localId() : personId;
0149 
0150     helper::utils::setContinuation<std::pair<bool, QString>>(
0151         QtConcurrent::run(
0152             [this, command, id]() -> std::pair<bool, QString>
0153             {
0154                 if(!m_diceParser)
0155                     return {false, tr("No Diceparser Object")};
0156 
0157                 auto diceParser= m_diceParser->parser();
0158 
0159                 if(!diceParser->parseLine(command))
0160                 {
0161                     auto error= diceParser->humanReadableError();
0162                     return {false, error};
0163                 }
0164 
0165                 diceParser->start();
0166                 auto error= diceParser->humanReadableError();
0167                 if(!error.isEmpty())
0168                     return {false, error};
0169 
0170                 auto result= diceParser->resultAsJSon(
0171                     [](const QString& value, const QString& color, bool highlight)
0172                     {
0173                         QString resultTmp= value;
0174                         bool hasColor= !color.isEmpty();
0175                         QString style;
0176                         if(hasColor)
0177                         {
0178                             style+= QStringLiteral("color:%1;").arg(color);
0179                         }
0180                         if(highlight)
0181                         {
0182                             if(style.isEmpty())
0183                                 style+= QStringLiteral("color:%1;")
0184                                             .arg("red"); // default color must get the value from the setting object
0185                             style+= QStringLiteral("font-weight:bold;");
0186                         }
0187                         if(!style.isEmpty())
0188                             resultTmp= QString("<span style=\"%2\">%1</span>").arg(value).arg(style);
0189                         return resultTmp;
0190                     });
0191                 return {true, result};
0192             }),
0193         this,
0194         [this, id](const std::pair<bool, QString>& result)
0195         {
0196             m_messageModel->addMessage(result.second, {}, QDateTime::currentDateTime(), localId(), id,
0197                                        result.first ? IM::Dice : IM::Error);
0198         });
0199 
0200     return true;
0201 }
0202 
0203 bool ChatRoom::runCommand(const QString& command, const QString& personId, const QString& personName)
0204 {
0205     QStringList meCommand({"emote ", "me ", "em ", "e "});
0206     auto text= command;
0207     for(auto const& e : qAsConst(meCommand))
0208     {
0209         if(text.startsWith(e))
0210         {
0211             text.remove(0, e.size());
0212             text= QString("<i>%2 %1<\\i>").arg(text).arg(personName);
0213             m_messageModel->addMessage(text, {}, QDateTime::currentDateTime(), localId(),
0214                                        personId.isEmpty() ? localId() : personId,
0215                                        InstantMessaging::MessageInterface::Command);
0216             return true;
0217         }
0218     }
0219 
0220     return false;
0221 }
0222 
0223 void ChatRoom::addMessageInterface(MessageInterface* message)
0224 {
0225     m_messageModel->addMessageInterface(message);
0226 }
0227 
0228 void ChatRoom::setLocalId(const QString& id)
0229 {
0230     m_messageModel->setLocalId(id);
0231 }
0232 bool ChatRoom::hasRecipiant(const QString& id)
0233 {
0234     return m_recipiants->hasRecipiant(id);
0235 }
0236 
0237 void ChatRoom::setDiceParser(DiceRoller* diceParser)
0238 {
0239     m_diceParser= diceParser;
0240 }
0241 } // namespace InstantMessaging