starting work on websocket chat reader
This commit is contained in:
@@ -12,6 +12,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
|
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
|
||||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
|
||||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Network)
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Network)
|
||||||
|
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS WebSockets)
|
||||||
|
|
||||||
set(PROJECT_SOURCES
|
set(PROJECT_SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
@@ -37,6 +38,11 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
|||||||
settings.hpp settings.cpp
|
settings.hpp settings.cpp
|
||||||
invalididexception.hpp invalididexception.cpp
|
invalididexception.hpp invalididexception.cpp
|
||||||
tierplaceholder.hpp tierplaceholder.cpp
|
tierplaceholder.hpp tierplaceholder.cpp
|
||||||
|
chatreader.hpp chatreader.cpp
|
||||||
|
chatmessage.hpp chatmessage.cpp
|
||||||
|
messagetype.hpp messagetype.cpp
|
||||||
|
ircmessagetype.hpp ircmessagetype.cpp
|
||||||
|
ircexception.hpp ircexception.cpp
|
||||||
|
|
||||||
)
|
)
|
||||||
# Define target properties for Android with Qt 6 as:
|
# Define target properties for Android with Qt 6 as:
|
||||||
@@ -59,6 +65,7 @@ endif()
|
|||||||
|
|
||||||
target_link_libraries(qt-app PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
target_link_libraries(qt-app PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
|
||||||
target_link_libraries(qt-app PRIVATE Qt${QT_VERISON_MAJOR}::Network)
|
target_link_libraries(qt-app PRIVATE Qt${QT_VERISON_MAJOR}::Network)
|
||||||
|
target_link_libraries(qt-app PRIVATE Qt${QT_VERISON_MAJOR}::WebSockets)
|
||||||
|
|
||||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||||
# If you are developing for iOS or macOS you should consider setting an
|
# If you are developing for iOS or macOS you should consider setting an
|
||||||
|
|||||||
253
chatmessage.cpp
Normal file
253
chatmessage.cpp
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
#include "chatmessage.hpp"
|
||||||
|
|
||||||
|
#include "ircexception.hpp"
|
||||||
|
|
||||||
|
#include <QException>
|
||||||
|
|
||||||
|
std::unordered_map<QString, QString> ChatMessage::parseTags(QString tagStr)
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FindingKey,
|
||||||
|
FindingValue,
|
||||||
|
ValueEscaped,
|
||||||
|
} state;
|
||||||
|
QString s = tagStr;
|
||||||
|
if (s.startsWith('@'))
|
||||||
|
s = s.mid(1);
|
||||||
|
std::unordered_map<QString, QString> tags;
|
||||||
|
QString key = "";
|
||||||
|
QString value = "";
|
||||||
|
state = FindingKey;
|
||||||
|
for(const auto c : std::as_const(s))
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case FindingKey:
|
||||||
|
if (c == '=')
|
||||||
|
state = FindingValue;
|
||||||
|
else if (c == ';')
|
||||||
|
{
|
||||||
|
state = FindingKey;
|
||||||
|
tags[key] = "";
|
||||||
|
key = "";
|
||||||
|
}
|
||||||
|
else if (c == ' ')
|
||||||
|
{
|
||||||
|
tags[key] = "";
|
||||||
|
goto EndParse;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
key += c;
|
||||||
|
break;
|
||||||
|
case FindingValue:
|
||||||
|
if (c == '\\')
|
||||||
|
{
|
||||||
|
state = ValueEscaped;
|
||||||
|
}
|
||||||
|
else if (c == ';')
|
||||||
|
{
|
||||||
|
tags[key] = value;
|
||||||
|
key = value = "";
|
||||||
|
state = FindingKey;
|
||||||
|
}
|
||||||
|
else if (c == ' ')
|
||||||
|
{
|
||||||
|
tags[key] = value;
|
||||||
|
goto EndParse;
|
||||||
|
}
|
||||||
|
else if (c == '\r' || c == '\n' || c == '\0')
|
||||||
|
throw IrcParseException("Invalid character in tag string", s);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value += c;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ValueEscaped:
|
||||||
|
if (c == ':')
|
||||||
|
{
|
||||||
|
value += ';';
|
||||||
|
state = FindingValue;
|
||||||
|
}
|
||||||
|
else if (c == 's')
|
||||||
|
{
|
||||||
|
value += ' ';
|
||||||
|
state = FindingValue;
|
||||||
|
}
|
||||||
|
else if (c == '\\')
|
||||||
|
{
|
||||||
|
value += '\\';
|
||||||
|
state = FindingValue;
|
||||||
|
}
|
||||||
|
else if (c == 'r')
|
||||||
|
{
|
||||||
|
value += '\r';
|
||||||
|
state = FindingValue;
|
||||||
|
}
|
||||||
|
else if (c == 'n')
|
||||||
|
{
|
||||||
|
value += '\n';
|
||||||
|
state = FindingValue;
|
||||||
|
}
|
||||||
|
else if (c == ';')
|
||||||
|
{
|
||||||
|
tags[key] = value;
|
||||||
|
key = value = "";
|
||||||
|
state = FindingKey;
|
||||||
|
}
|
||||||
|
//spaces should already be stripped, but handle this as end of tags just in case
|
||||||
|
else if (c == ' ')
|
||||||
|
{
|
||||||
|
tags[key] = value;
|
||||||
|
key = value = "";
|
||||||
|
goto EndParse;
|
||||||
|
}
|
||||||
|
else if (c == '\r' || c == '\n' || c == '\0')
|
||||||
|
throw IrcParseException("Invalid character in tag string", s);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value += c;
|
||||||
|
state = FindingValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new QException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//this is reached after processing the last character without hitting a space
|
||||||
|
tags[key] = value;
|
||||||
|
EndParse:
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatMessage* ChatMessage::Parse(QString message)
|
||||||
|
{
|
||||||
|
QString rawMessage = message;
|
||||||
|
std::unordered_map<QString, QString> tags;
|
||||||
|
QString sender = "";
|
||||||
|
QList<QString> parameters;
|
||||||
|
QString prefix = "";
|
||||||
|
|
||||||
|
QString s = message;
|
||||||
|
if (s.startsWith('@'))
|
||||||
|
{
|
||||||
|
s = s.mid(1);
|
||||||
|
//first ' ' acts as the delimeter
|
||||||
|
auto split = s.split(' ');
|
||||||
|
auto tagString = split.takeFirst();
|
||||||
|
s = split.join(' ');
|
||||||
|
tags = parseTags(tagString);
|
||||||
|
}
|
||||||
|
//message has source
|
||||||
|
if (s.startsWith(':'))
|
||||||
|
{
|
||||||
|
s = s.mid(1);
|
||||||
|
auto split = s.split(' ');
|
||||||
|
prefix = split.takeFirst();
|
||||||
|
s = split.join(' ');
|
||||||
|
while (s[0] == ' ')
|
||||||
|
s = s.mid(1);
|
||||||
|
}
|
||||||
|
auto spl_command = s.split(' ');
|
||||||
|
IrcMessageType type = IrcMessageType::parse(spl_command.takeFirst());
|
||||||
|
//message has parameters
|
||||||
|
if (!spl_command.isEmpty())
|
||||||
|
{
|
||||||
|
s = spl_command.join(' ');
|
||||||
|
//message has single parameter marked as the final parameter
|
||||||
|
//this needs to be handled specially because the leading ' '
|
||||||
|
//is stripped
|
||||||
|
if (s.startsWith(':'))
|
||||||
|
{
|
||||||
|
parameters.append(s.mid(1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto spl_final = s.split(" :");
|
||||||
|
auto spl_initial = spl_final.takeFirst().split(' ', Qt::SkipEmptyParts);
|
||||||
|
for (auto& part : spl_initial)
|
||||||
|
{
|
||||||
|
part = part.trimmed();
|
||||||
|
}
|
||||||
|
parameters.append(spl_initial);
|
||||||
|
if (!spl_final.isEmpty())
|
||||||
|
parameters.append(spl_final.join(" :"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ChatMessage(rawMessage, tags, sender, parameters, prefix, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ChatMessage::ChatMessage(QString rawMessage, std::unordered_map<QString, QString> tags,
|
||||||
|
QString sender, QList<QString> parameters, QString prefix,
|
||||||
|
IrcMessageType type)
|
||||||
|
: _rawMessage(rawMessage), _tags(tags), _sender(sender), _parameters(parameters),
|
||||||
|
_prefix(prefix), _type(type)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatMessage::rawMessage() const
|
||||||
|
{
|
||||||
|
return _rawMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_map<QString, QString>* ChatMessage::tags() const
|
||||||
|
{
|
||||||
|
return &_tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatMessage::sender() const
|
||||||
|
{
|
||||||
|
return _sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<QString>* ChatMessage::parameters() const
|
||||||
|
{
|
||||||
|
return &_parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatMessage::prefix() const
|
||||||
|
{
|
||||||
|
return _prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrcMessageType ChatMessage::type() const
|
||||||
|
{
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PrivmsgView::PrivmsgView(const ChatMessage* msg)
|
||||||
|
: parent(msg)
|
||||||
|
{
|
||||||
|
if (parent->type() != Expected)
|
||||||
|
throw IrcIncorrectTypeException(Expected, parent->type());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PrivmsgView::message() const
|
||||||
|
{
|
||||||
|
return parent->parameters()->last();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PrivmsgView::user() const
|
||||||
|
{
|
||||||
|
static constexpr const char* KEY = "display-name";
|
||||||
|
if (parent->tags()->contains(KEY))
|
||||||
|
return parent->tags()->at(KEY);
|
||||||
|
throw IrcTagNotFoundException(KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
PingView::PingView(const ChatMessage* msg)
|
||||||
|
: parent(msg)
|
||||||
|
{
|
||||||
|
if (parent->type() != Expected)
|
||||||
|
throw IrcIncorrectTypeException(Expected, parent->type());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PingView::toPong() const
|
||||||
|
{
|
||||||
|
return parent->rawMessage().replace("PING", "PONG");
|
||||||
|
}
|
||||||
67
chatmessage.hpp
Normal file
67
chatmessage.hpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#ifndef CHATMESSAGE_HPP
|
||||||
|
#define CHATMESSAGE_HPP
|
||||||
|
|
||||||
|
// #include "messagetype.hpp"
|
||||||
|
#include "ircmessagetype.hpp"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class ChatMessage
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
public:
|
||||||
|
static ChatMessage* Parse(QString message);
|
||||||
|
QString rawMessage() const;
|
||||||
|
const std::unordered_map<QString, QString>* tags() const;
|
||||||
|
QString sender() const;
|
||||||
|
const QList<QString>* parameters() const;
|
||||||
|
QString prefix() const;
|
||||||
|
IrcMessageType type() const;
|
||||||
|
// explicit ChatMessage(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit ChatMessage(QString message);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChatMessage(QString rawMessage, std::unordered_map<QString, QString> tags,
|
||||||
|
QString sender, QList<QString> parameters, QString prefix,
|
||||||
|
IrcMessageType type);
|
||||||
|
const QString _rawMessage;
|
||||||
|
const std::unordered_map<QString, QString> _tags;
|
||||||
|
const QString _sender;
|
||||||
|
const QList<QString> _parameters;
|
||||||
|
const QString _prefix;
|
||||||
|
const IrcMessageType _type;
|
||||||
|
static std::unordered_map<QString, QString> parseTags(QString tagStr);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class PrivmsgView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PrivmsgView(const ChatMessage* msg);
|
||||||
|
QString message() const;
|
||||||
|
QString user() const;
|
||||||
|
static constexpr IrcMessageType Expected = IrcMessageType::PRIVMSG;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ChatMessage* const parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PingView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PingView(const ChatMessage* msg);
|
||||||
|
QString toPong() const;
|
||||||
|
static constexpr IrcMessageType Expected = IrcMessageType::PING;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const ChatMessage* const parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHATMESSAGE_HPP
|
||||||
53
chatreader.cpp
Normal file
53
chatreader.cpp
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include "chatreader.hpp"
|
||||||
|
|
||||||
|
ChatReader::ChatReader()
|
||||||
|
: QObject(nullptr), socket()
|
||||||
|
{
|
||||||
|
QObject::connect(&socket, SIGNAL(socketConnect),
|
||||||
|
this, SLOT(socketConnect));
|
||||||
|
QObject::connect(&socket, SIGNAL(socketDisconnect),
|
||||||
|
this, SLOT(socketDisconnect));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatReader::getConnected() const
|
||||||
|
{
|
||||||
|
return _connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatReader::socketConnect()
|
||||||
|
{
|
||||||
|
_connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatReader::socketDisconnect()
|
||||||
|
{
|
||||||
|
_connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatReader::open()
|
||||||
|
{
|
||||||
|
socket.open(URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 ChatReader::send(QString message)
|
||||||
|
{
|
||||||
|
return socket.sendTextMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatReader::messageReceived(QString message)
|
||||||
|
{
|
||||||
|
auto chat = ChatMessage::Parse(message);
|
||||||
|
if (chat->type() == PingView::Expected)
|
||||||
|
{
|
||||||
|
const PingView ping(chat);
|
||||||
|
send(ping.toPong());
|
||||||
|
}
|
||||||
|
emit chatMessageReceived(chat);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatReader::~ChatReader()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUrl ChatReader::URL = QUrl("wss://irc-ws.chat.twitch.tv:443");
|
||||||
30
chatreader.hpp
Normal file
30
chatreader.hpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef CHATREADER_HPP
|
||||||
|
#define CHATREADER_HPP
|
||||||
|
|
||||||
|
#include "chatmessage.hpp"
|
||||||
|
|
||||||
|
#include <QWebSocket>
|
||||||
|
|
||||||
|
class ChatReader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static const QUrl URL;
|
||||||
|
|
||||||
|
ChatReader();
|
||||||
|
~ChatReader();
|
||||||
|
bool getConnected() const;
|
||||||
|
void open();
|
||||||
|
qint64 send(QString message);
|
||||||
|
signals:
|
||||||
|
void chatMessageReceived(const ChatMessage* message);
|
||||||
|
protected slots:
|
||||||
|
void socketConnect();
|
||||||
|
void socketDisconnect();
|
||||||
|
void messageReceived(QString message);
|
||||||
|
private:
|
||||||
|
QWebSocket socket;
|
||||||
|
bool _connected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CHATREADER_HPP
|
||||||
@@ -6,7 +6,7 @@ InvalidIdException::InvalidIdException()
|
|||||||
}
|
}
|
||||||
|
|
||||||
InvalidRowIdException::InvalidRowIdException(TierRow::IdType id)
|
InvalidRowIdException::InvalidRowIdException(TierRow::IdType id)
|
||||||
: _id(id), _what(std::format("id: {}", _id))
|
: _id(id), _what(QString("id: {}").arg(QString::number(id)).toLocal8Bit())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -18,11 +18,11 @@ TierRow::IdType InvalidRowIdException::id() const
|
|||||||
|
|
||||||
const char* InvalidRowIdException::what() const noexcept
|
const char* InvalidRowIdException::what() const noexcept
|
||||||
{
|
{
|
||||||
return _what.c_str();
|
return _what.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
InvalidCardIdException::InvalidCardIdException(TierCard::IdType id)
|
InvalidCardIdException::InvalidCardIdException(TierCard::IdType id)
|
||||||
: _id(id), _what(std::format("id: {}", _id))
|
: _id(id), _what(QString("id: {}").arg(QString::number(id)).toLocal8Bit())
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -34,5 +34,5 @@ TierCard::IdType InvalidCardIdException::id() const
|
|||||||
|
|
||||||
const char* InvalidCardIdException::what() const noexcept
|
const char* InvalidCardIdException::what() const noexcept
|
||||||
{
|
{
|
||||||
return _what.c_str();
|
return _what.data();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const TierRow::IdType _id;
|
const TierRow::IdType _id;
|
||||||
const std::string _what;
|
const QByteArray _what;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InvalidCardIdException : public InvalidIdException
|
class InvalidCardIdException : public InvalidIdException
|
||||||
@@ -33,7 +33,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const TierCard::IdType _id;
|
const TierCard::IdType _id;
|
||||||
const std::string _what;
|
const QByteArray _what;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INVALIDIDEXCEPTION_HPP
|
#endif // INVALIDIDEXCEPTION_HPP
|
||||||
|
|||||||
40
ircexception.cpp
Normal file
40
ircexception.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include "ircexception.hpp"
|
||||||
|
|
||||||
|
IrcException::IrcException(QString _what)
|
||||||
|
: _what(_what.toLocal8Bit())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* IrcException::what() const noexcept
|
||||||
|
{
|
||||||
|
return _what.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
IrcTagNotFoundException::IrcTagNotFoundException(QString tag)
|
||||||
|
: IrcException(QString("missing tag: %1").arg(tag)), tag(tag)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IrcParseException::IrcParseException(QString message, QString description)
|
||||||
|
: IrcException(_makeWhat(message, description)),
|
||||||
|
message(message), description(description)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IrcParseException::_makeWhat(QString message, QString description)
|
||||||
|
{
|
||||||
|
QString s = "";
|
||||||
|
if (!message.isEmpty())
|
||||||
|
s = QString("Description: %1\n").arg(description);
|
||||||
|
return s + QString("Message: %1").arg(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
IrcIncorrectTypeException::IrcIncorrectTypeException(IrcMessageType expected, IrcMessageType actual)
|
||||||
|
: IrcException(QString("Expected: %1 Actual: %2").arg(expected.toString(), actual.toString())),
|
||||||
|
expected(expected), actual(actual)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
43
ircexception.hpp
Normal file
43
ircexception.hpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef IRCEXCEPTIONS_HPP
|
||||||
|
#define IRCEXCEPTIONS_HPP
|
||||||
|
|
||||||
|
#include "ircmessagetype.hpp"
|
||||||
|
|
||||||
|
#include <QException>
|
||||||
|
|
||||||
|
class IrcException : public QException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* what() const noexcept override;
|
||||||
|
protected:
|
||||||
|
IrcException(QString _what);
|
||||||
|
const QByteArray _what;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IrcParseException : public IrcException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IrcParseException(QString message, QString description);
|
||||||
|
const QString message;
|
||||||
|
const QString description;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QString _makeWhat(QString message, QString description="");
|
||||||
|
};
|
||||||
|
|
||||||
|
class IrcTagNotFoundException : public IrcException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IrcTagNotFoundException(QString tag);
|
||||||
|
const QString tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IrcIncorrectTypeException : public IrcException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IrcIncorrectTypeException(IrcMessageType expected, IrcMessageType actual);
|
||||||
|
const IrcMessageType expected;
|
||||||
|
const IrcMessageType actual;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IRCEXCEPTIONS_HPP
|
||||||
45
ircmessagetype.cpp
Normal file
45
ircmessagetype.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#include "ircmessagetype.hpp"
|
||||||
|
|
||||||
|
#include <QMetaObject>
|
||||||
|
#include <QMetaEnum>
|
||||||
|
|
||||||
|
IrcMessageType::MessageType IrcMessageType::getType() const
|
||||||
|
{
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IrcMessageType IrcMessageType::parse(QString str)
|
||||||
|
{
|
||||||
|
// QVariant var = QVariant::fromValue(str);
|
||||||
|
// if (var.convert(QMetaType::fromType<IrcMessageType>()))
|
||||||
|
// return var.value<IrcMessageType>();
|
||||||
|
// return IrcMessageType::MessageType::UNKNOWN;
|
||||||
|
auto&& meta = QMetaEnum::fromType<IrcMessageType::MessageType>();
|
||||||
|
bool ok = false;
|
||||||
|
auto value = static_cast<IrcMessageType>(meta.keyToValue(str.toLocal8Bit().data(), &ok));
|
||||||
|
if (ok)
|
||||||
|
return value;
|
||||||
|
auto num = str.toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
return num;
|
||||||
|
return Unknown();
|
||||||
|
}
|
||||||
|
|
||||||
|
IrcMessageType::IrcMessageType(const IrcMessageType& other)
|
||||||
|
: _type(other._type)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IrcMessageType::IrcMessageType(int type)
|
||||||
|
: _type(static_cast<MessageType>(type))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString IrcMessageType::toString() const
|
||||||
|
{
|
||||||
|
auto&& metaEnum = QMetaEnum::fromType<MessageType>();
|
||||||
|
return metaEnum.valueToKey(static_cast<int>(_type));
|
||||||
|
}
|
||||||
34
ircmessagetype.hpp
Normal file
34
ircmessagetype.hpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef IRCMESSAGETYPE_HPP
|
||||||
|
#define IRCMESSAGETYPE_HPP
|
||||||
|
|
||||||
|
#include <QMetaObject>
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
|
class IrcMessageType
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
public:
|
||||||
|
enum MessageType
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
PRIVMSG,
|
||||||
|
PING
|
||||||
|
};
|
||||||
|
Q_ENUM(MessageType);
|
||||||
|
Q_PROPERTY(MessageType type READ getType)
|
||||||
|
static IrcMessageType Unknown() { return UNKNOWN; }
|
||||||
|
constexpr IrcMessageType(MessageType type) : _type(type) { }
|
||||||
|
IrcMessageType(int type);
|
||||||
|
IrcMessageType(const IrcMessageType& other);
|
||||||
|
bool operator ==(const IrcMessageType& other)
|
||||||
|
{ return this->_type == other._type; }
|
||||||
|
static IrcMessageType parse(QString str);
|
||||||
|
MessageType getType() const;
|
||||||
|
QString toString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const MessageType _type;
|
||||||
|
};
|
||||||
|
Q_DECLARE_METATYPE(IrcMessageType)
|
||||||
|
|
||||||
|
#endif // IRCMESSAGETYPE_HPP
|
||||||
17
messagetype.cpp
Normal file
17
messagetype.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#include "messagetype.hpp"
|
||||||
|
|
||||||
|
MessageType::MessageType(QObject *parent)
|
||||||
|
: QObject{parent}
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageType::setType(MsgType type)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageType::MsgType MessageType::type() const
|
||||||
|
{
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
25
messagetype.hpp
Normal file
25
messagetype.hpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef MESSAGETYPE_HPP
|
||||||
|
#define MESSAGETYPE_HPP
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class MessageType : public QObject
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
public:
|
||||||
|
explicit MessageType(QObject *parent = nullptr);
|
||||||
|
MessageType(MessageType& other);
|
||||||
|
enum MsgType
|
||||||
|
{
|
||||||
|
UNKNOWN,
|
||||||
|
PRIVMSG,
|
||||||
|
};
|
||||||
|
Q_ENUM(MsgType)
|
||||||
|
MessageType(MsgType type);
|
||||||
|
void setType(MsgType type);
|
||||||
|
MsgType type() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MESSAGETYPE_HPP
|
||||||
Reference in New Issue
Block a user