Refactor chat system: Introduce ChatRoom and ChatUser classes
- Created ChatRoom class to manage chat room functionalities, including user management, message handling, and game mechanics. - Developed ChatUser class to represent individual users, handling user-specific actions and interactions within chat rooms. - Implemented a Config class for loading configuration settings from a JSON file. - Established a Server class to manage connections, handle requests, and facilitate communication between users and chat rooms. - Introduced a Database class for database interactions, utilizing PostgreSQL for user and room data management. - Added utility functions in the Base class for JSON handling and socket communication. - Created Object classes for Room and User to encapsulate their properties and behaviors. - Updated main function to initialize server and load chat rooms from configuration.
This commit is contained in:
@@ -4,6 +4,17 @@ project(YourChat VERSION 0.1)
|
|||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
include_directories(${PROJECT_SOURCE_DIR})
|
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||||
add_executable(yourchat main.cpp base.cpp config.cpp server.cpp chat_room.cpp tools.cpp chat_user.cpp database.cpp)
|
add_executable(yourchat
|
||||||
|
src/main.cpp
|
||||||
|
src/lib/base.cpp
|
||||||
|
src/core/config.cpp
|
||||||
|
src/core/server.cpp
|
||||||
|
src/core/chat_room.cpp
|
||||||
|
src/lib/tools.cpp
|
||||||
|
src/core/chat_user.cpp
|
||||||
|
src/lib/database.cpp
|
||||||
|
src/object/user.cpp
|
||||||
|
src/object/room.cpp
|
||||||
|
)
|
||||||
target_link_libraries(yourchat jsoncpp pthread pqxx)
|
target_link_libraries(yourchat jsoncpp pthread pqxx)
|
||||||
|
|||||||
175
chat_user.cpp
175
chat_user.cpp
@@ -1,175 +0,0 @@
|
|||||||
// entfernt: #include "user.h"
|
|
||||||
|
|
||||||
#include "chat_user.h"
|
|
||||||
#include <tools.h>
|
|
||||||
#include <json/json.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include "chat_room.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace Yc {
|
|
||||||
namespace Lib {
|
|
||||||
|
|
||||||
ChatUser::ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket) :
|
|
||||||
_parent(std::move(parent)),
|
|
||||||
_name(std::move(name)),
|
|
||||||
_color(std::move(color)),
|
|
||||||
_socket(socket),
|
|
||||||
_stop(false) {
|
|
||||||
_token = Yc::Lib::Tools::generateRandomString(32);
|
|
||||||
sendMsg(token, _token, "", "");
|
|
||||||
thread = std::make_unique<std::thread>(&ChatUser::checkerTask, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ChatUser::~ChatUser() {
|
|
||||||
_parent->addMessage(ChatUser::system, std::string("leaved_chat"), std::string(_name), std::string(_color));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ChatUser::name() const {
|
|
||||||
return _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatUser::validateToken(std::string token) {
|
|
||||||
return (token == _token);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChatUser::isUser(std::shared_ptr<ChatUser> toValidate) {
|
|
||||||
return (toValidate.get() == this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::sendMsg(MsgType type, const char *message, std::string userName, std::string color) {
|
|
||||||
sendMsg(type, std::string(message), userName, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::sendMsg(MsgType type, std::string message , std::string userName, std::string color) {
|
|
||||||
Json::Value sendMessage;
|
|
||||||
sendMessage["type"] = type;
|
|
||||||
sendMessage["message"] = message;
|
|
||||||
sendMessage["userName"] = userName;
|
|
||||||
sendMessage["color"] = color;
|
|
||||||
send(sendMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::sendMsg(ChatUser::MsgType type, Json::Value message, std::string userName, std::string color) {
|
|
||||||
Json::Value sendMessage;
|
|
||||||
sendMessage["type"] = type;
|
|
||||||
sendMessage["message"] = message;
|
|
||||||
sendMessage["userName"] = userName;
|
|
||||||
sendMessage["color"] = color;
|
|
||||||
send(sendMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::checkerTask() {
|
|
||||||
while (!_stop) {
|
|
||||||
fd_set readSd;
|
|
||||||
FD_ZERO(&readSd);
|
|
||||||
FD_SET(_socket, &readSd);
|
|
||||||
timeval tv;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 500;
|
|
||||||
int selectResult = select(_socket + 1, &readSd, NULL, NULL, &tv);
|
|
||||||
if (selectResult == 1 && FD_ISSET(_socket, &readSd) == 1) {
|
|
||||||
_parent->removeUser(_token);
|
|
||||||
_stop = true;
|
|
||||||
delete this;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string msg = readSocket(_socket);
|
|
||||||
if (msg == "") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
handleMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::stop() {
|
|
||||||
_stop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ChatUser::color() const {
|
|
||||||
return _color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::setParent(std::shared_ptr<ChatRoom> parent) {
|
|
||||||
_parent = std::move(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::send(std::string out) {
|
|
||||||
Base::send(_socket, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::send(Json::Value out) {
|
|
||||||
Base::send(_socket, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::handleMessage(std::string message) {
|
|
||||||
Json::Value jsonTree = getJsonTree(message);
|
|
||||||
if (jsonTree["token"].asString() != _token) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (jsonTree["type"].asString() == "message") {
|
|
||||||
checkString(jsonTree["message"].asString());
|
|
||||||
} else if (jsonTree["type"].asString() == "dice") {
|
|
||||||
doDice();
|
|
||||||
} else if (jsonTree["type"].asString() == "scream") {
|
|
||||||
_parent->addMessage(ChatUser::scream, jsonTree["message"].asString(), std::string(_name), std::string(_color));
|
|
||||||
} else if (jsonTree["type"].asString() == "do") {
|
|
||||||
_parent->addMessage(ChatUser::dosomething, jsonTree["message"].asString(), std::string(_name), std::string(_color));
|
|
||||||
} else if (jsonTree["type"].asString() == "join") {
|
|
||||||
changeRoom(jsonTree["newroom"].asString(), jsonTree["password"].asString());
|
|
||||||
} else if (jsonTree["type"].asString() == "userlist") {
|
|
||||||
sendUserList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::checkString(std::string message) {
|
|
||||||
if (message.substr(0, 6) == "/join ") {
|
|
||||||
message = message.substr(6);
|
|
||||||
if (message.find(" ") == std::string::npos) {
|
|
||||||
changeRoom(message, "");
|
|
||||||
} else {
|
|
||||||
std::string room = message.substr(0, message.find(" "));
|
|
||||||
std::string password = message.substr(message.find(" ") + 1);
|
|
||||||
changeRoom(room, password);
|
|
||||||
}
|
|
||||||
} else if (message == "/dice") {
|
|
||||||
doDice();
|
|
||||||
} else {
|
|
||||||
_parent->addMessage(ChatUser::message, std::string(message), std::string(_name), std::string(_color));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::sendUserList() {
|
|
||||||
Json::Value userList = _parent->userList();
|
|
||||||
Json::Value msg = Json::objectValue;
|
|
||||||
msg["userlist"] = userList;
|
|
||||||
sendMsg(userListe, msg, "", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::doDice() {
|
|
||||||
switch (_parent->addDice(shared_from_this(), (rand() % 6) + 1)) {
|
|
||||||
case 1:
|
|
||||||
sendMsg(system, "dice_not_possible", "", "");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
sendMsg(system, "dice_allready_done", "", "");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChatUser::changeRoom(std::string newRoom, std::string password) {
|
|
||||||
if (!_parent->userToNewRoom(shared_from_this(), newRoom, password)) {
|
|
||||||
sendMsg(ChatUser::system, "room_not_possible", "", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Lib
|
|
||||||
} // namespace Yc
|
|
||||||
65
chat_user.h
65
chat_user.h
@@ -1,65 +0,0 @@
|
|||||||
#ifndef YC_LIB_CHAT_USER_H
|
|
||||||
#define YC_LIB_CHAT_USER_H
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <set>
|
|
||||||
#include <json/json.h>
|
|
||||||
#include <thread>
|
|
||||||
#include "base.h"
|
|
||||||
|
|
||||||
namespace Yc {
|
|
||||||
namespace Lib {
|
|
||||||
|
|
||||||
class ChatRoom;
|
|
||||||
|
|
||||||
class ChatUser: public Base, public std::enable_shared_from_this<ChatUser> {
|
|
||||||
public:
|
|
||||||
enum MsgType {
|
|
||||||
error = -1,
|
|
||||||
token = 1,
|
|
||||||
userListe = 2,
|
|
||||||
roomList = 3,
|
|
||||||
message = 4,
|
|
||||||
system = 5,
|
|
||||||
scream = 6,
|
|
||||||
dosomething = 7,
|
|
||||||
dice = 8,
|
|
||||||
result = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket);
|
|
||||||
~ChatUser();
|
|
||||||
std::string name() const;
|
|
||||||
bool validateToken(std::string token);
|
|
||||||
bool isUser(std::shared_ptr<ChatUser> toValidate);
|
|
||||||
void sendMsg(MsgType type, std::string message, std::string userName, std::string color);
|
|
||||||
void sendMsg(MsgType type, const char *message, std::string userName, std::string color);
|
|
||||||
void sendMsg(MsgType type, Json::Value message, std::string userName, std::string color);
|
|
||||||
void checkerTask();
|
|
||||||
void stop();
|
|
||||||
std::string color() const;
|
|
||||||
void setParent(std::shared_ptr<ChatRoom> parent);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<ChatRoom> _parent;
|
|
||||||
std::string _name;
|
|
||||||
std::string _color;
|
|
||||||
int _socket;
|
|
||||||
std::string _token;
|
|
||||||
bool _stop;
|
|
||||||
std::unique_ptr<std::thread> thread;
|
|
||||||
|
|
||||||
void send(std::string out);
|
|
||||||
void send(Json::Value out);
|
|
||||||
void handleMessage(std::string message);
|
|
||||||
void doDice();
|
|
||||||
void changeRoom(std::string newRoom, std::string password);
|
|
||||||
void checkString(std::string message);
|
|
||||||
void sendUserList();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Lib
|
|
||||||
} // namespace Yc
|
|
||||||
|
|
||||||
#endif // YC_LIB_CHAT_USER_H
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <pqxx/pqxx>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
try {
|
|
||||||
pqxx::connection c{"dbname=your_db user=your_user password=your_pass host=localhost"};
|
|
||||||
pqxx::work txn{c};
|
|
||||||
pqxx::result r = txn.exec("SELECT version();");
|
|
||||||
for (auto row : r) {
|
|
||||||
std::cout << row[0].c_str() << std::endl;
|
|
||||||
}
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
std::cerr << "PostgreSQL error: " << e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
0
src/chat_room.cpp
Normal file
0
src/chat_room.cpp
Normal file
0
src/chat_room.h
Normal file
0
src/chat_room.h
Normal file
0
src/chat_user.cpp
Normal file
0
src/chat_user.cpp
Normal file
0
src/chat_user.h
Normal file
0
src/chat_user.h
Normal file
@@ -1,7 +1,7 @@
|
|||||||
#include "chat_room.h"
|
#include "chat_room.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <server.h>
|
#include "server.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -9,18 +9,22 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace Yc {
|
namespace Yc
|
||||||
namespace Lib {
|
{
|
||||||
|
namespace Lib
|
||||||
|
{
|
||||||
|
|
||||||
ChatRoom::ChatRoom(std::shared_ptr<Server> parent, Json::Value roomParams) :
|
ChatRoom::ChatRoom(std::shared_ptr<Server> parent, Json::Value roomParams)
|
||||||
|
: _room(roomParams),
|
||||||
_parent(std::move(parent)),
|
_parent(std::move(parent)),
|
||||||
_blocked(false),
|
_blocked(false),
|
||||||
_stop(false),
|
_stop(false),
|
||||||
_roundRunning(false) {
|
_roundRunning(false)
|
||||||
|
{
|
||||||
_name = roomParams["name"].asString();
|
_name = roomParams["name"].asString();
|
||||||
_password = roomParams["password"].asString();
|
_password = roomParams["password"].asString();
|
||||||
std::vector<std::string> allowedUsers;
|
for (auto &user : roomParams["allowed"])
|
||||||
for (auto &user: roomParams["allowed"]) {
|
{
|
||||||
_allowedUsers.push_back(user.asString());
|
_allowedUsers.push_back(user.asString());
|
||||||
}
|
}
|
||||||
_type = (RoomType)roomParams["type"].asInt();
|
_type = (RoomType)roomParams["type"].asInt();
|
||||||
@@ -31,28 +35,36 @@ namespace Yc {
|
|||||||
|
|
||||||
ChatRoom::~ChatRoom() = default;
|
ChatRoom::~ChatRoom() = default;
|
||||||
|
|
||||||
void ChatRoom::run() {
|
void ChatRoom::run()
|
||||||
while (!_stop) {
|
{
|
||||||
if (_msgQueue.size() > 0 && !_blocked) {
|
while (!_stop)
|
||||||
|
{
|
||||||
|
if (_msgQueue.size() > 0 && !_blocked)
|
||||||
|
{
|
||||||
_blocked = true;
|
_blocked = true;
|
||||||
while (_msgQueue.size() > 0) {
|
while (_msgQueue.size() > 0)
|
||||||
|
{
|
||||||
Message message = _msgQueue.front();
|
Message message = _msgQueue.front();
|
||||||
for (auto &user: _users) {
|
for (auto &user : _users)
|
||||||
|
{
|
||||||
user->sendMsg(message.type, message.messageTr, message.userName, message.color);
|
user->sendMsg(message.type, message.messageTr, message.userName, message.color);
|
||||||
}
|
}
|
||||||
_msgQueue.pop();
|
_msgQueue.pop();
|
||||||
}
|
}
|
||||||
_blocked = false;
|
_blocked = false;
|
||||||
}
|
}
|
||||||
if ((_type & dice) == dice) {
|
if ((_type & dice) == dice)
|
||||||
|
{
|
||||||
_handleDice();
|
_handleDice();
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::addUser(std::string _userName, std::string color, std::string _password, int socket) {
|
bool ChatRoom::addUser(std::string _userName, std::string color, std::string _password, int socket)
|
||||||
if (_password != "" && _password == _password && std::find(std::begin(_allowedUsers), std::end(_allowedUsers), _userName) == std::end(_allowedUsers)) {
|
{
|
||||||
|
if (_password != "" && _password == _password && std::find(std::begin(_allowedUsers), std::end(_allowedUsers), _userName) == std::end(_allowedUsers))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto newUser = std::make_shared<ChatUser>(shared_from_this(), _userName, color, socket);
|
auto newUser = std::make_shared<ChatUser>(shared_from_this(), _userName, color, socket);
|
||||||
@@ -63,8 +75,10 @@ namespace Yc {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::addUser(std::shared_ptr<ChatUser> user, std::string password) {
|
bool ChatRoom::addUser(std::shared_ptr<ChatUser> user, std::string password)
|
||||||
if (password == _password) {
|
{
|
||||||
|
if (password == _password)
|
||||||
|
{
|
||||||
_users.push_back(user);
|
_users.push_back(user);
|
||||||
user->setParent(shared_from_this());
|
user->setParent(shared_from_this());
|
||||||
_initRound();
|
_initRound();
|
||||||
@@ -73,19 +87,26 @@ namespace Yc {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::userNameExists(std::string userName) {
|
bool ChatRoom::userNameExists(std::string userName)
|
||||||
for (const auto &user: _users) {
|
{
|
||||||
if (user->name() == userName) {
|
for (const auto &user : _users)
|
||||||
|
{
|
||||||
|
if (user->name() == userName)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::removeUser(std::string _token, bool silent) {
|
void ChatRoom::removeUser(std::string _token, bool silent)
|
||||||
for (auto it = _users.begin(); it != _users.end(); ++it) {
|
{
|
||||||
if ((*it)->validateToken(_token)) {
|
for (auto it = _users.begin(); it != _users.end(); ++it)
|
||||||
if (!silent) {
|
{
|
||||||
|
if ((*it)->validateToken(_token))
|
||||||
|
{
|
||||||
|
if (!silent)
|
||||||
|
{
|
||||||
addMessage(ChatUser::system, (*it)->name(), (*it)->color());
|
addMessage(ChatUser::system, (*it)->name(), (*it)->color());
|
||||||
}
|
}
|
||||||
_users.erase(it);
|
_users.erase(it);
|
||||||
@@ -94,10 +115,14 @@ namespace Yc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::removeUser(std::shared_ptr<ChatUser> userToRemove, bool silent) {
|
void ChatRoom::removeUser(std::shared_ptr<ChatUser> userToRemove, bool silent)
|
||||||
for (auto it = _users.begin(); it != _users.end(); ++it) {
|
{
|
||||||
if (*it == userToRemove) {
|
for (auto it = _users.begin(); it != _users.end(); ++it)
|
||||||
if (!silent) {
|
{
|
||||||
|
if (*it == userToRemove)
|
||||||
|
{
|
||||||
|
if (!silent)
|
||||||
|
{
|
||||||
addMessage(ChatUser::system, (*it)->name(), (*it)->color());
|
addMessage(ChatUser::system, (*it)->name(), (*it)->color());
|
||||||
}
|
}
|
||||||
_users.erase(it);
|
_users.erase(it);
|
||||||
@@ -106,15 +131,18 @@ namespace Yc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::setStop() {
|
void ChatRoom::setStop()
|
||||||
|
{
|
||||||
_stop = true;
|
_stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::addMessage(ChatUser::MsgType type, const char *messageText, std::string userName, std::string color) {
|
void ChatRoom::addMessage(ChatUser::MsgType type, const char *messageText, std::string userName, std::string color)
|
||||||
|
{
|
||||||
addMessage(type, (std::string)messageText, userName, color);
|
addMessage(type, (std::string)messageText, userName, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::addMessage(ChatUser::MsgType type, std::string messageText, std::string userName, std::string color) {
|
void ChatRoom::addMessage(ChatUser::MsgType type, std::string messageText, std::string userName, std::string color)
|
||||||
|
{
|
||||||
Message message;
|
Message message;
|
||||||
message.type = type;
|
message.type = type;
|
||||||
message.messageTr = messageText;
|
message.messageTr = messageText;
|
||||||
@@ -123,33 +151,41 @@ namespace Yc {
|
|||||||
_msgQueue.push(message);
|
_msgQueue.push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::addMessage(ChatUser::MsgType type, Json::Value messageText, std::string userName, std::string color) {
|
void ChatRoom::addMessage(ChatUser::MsgType type, Json::Value messageText, std::string userName, std::string color)
|
||||||
|
{
|
||||||
addMessage(type, getJsonString(messageText), userName, color);
|
addMessage(type, getJsonString(messageText), userName, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::addUserWhenQueueEmpty(std::shared_ptr<ChatUser> user) {
|
void ChatRoom::addUserWhenQueueEmpty(std::shared_ptr<ChatUser> user)
|
||||||
while (_msgQueue.size() > 0) {
|
{
|
||||||
|
while (_msgQueue.size() > 0)
|
||||||
|
{
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
}
|
}
|
||||||
_users.push_back(user);
|
_users.push_back(user);
|
||||||
user->setParent(shared_from_this());
|
user->setParent(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::userToNewRoom(std::shared_ptr<ChatUser> user, std::string newRoom, std::string password) {
|
bool ChatRoom::userToNewRoom(std::shared_ptr<ChatUser> user, std::string newRoom, std::string password)
|
||||||
|
{
|
||||||
return _parent->changeRoom(user, newRoom, password);
|
return _parent->changeRoom(user, newRoom, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ChatRoom::flags() {
|
unsigned int ChatRoom::flags()
|
||||||
|
{
|
||||||
unsigned int value = (unsigned int)_type;
|
unsigned int value = (unsigned int)_type;
|
||||||
if (_password != "") {
|
if (_password != "")
|
||||||
|
{
|
||||||
value += (unsigned int)ChatRoom::password;
|
value += (unsigned int)ChatRoom::password;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value ChatRoom::userList() {
|
Json::Value ChatRoom::userList()
|
||||||
|
{
|
||||||
Json::Value users = Json::arrayValue;
|
Json::Value users = Json::arrayValue;
|
||||||
for (auto &user: _users) {
|
for (auto &user : _users)
|
||||||
|
{
|
||||||
Json::Value jsonUser = Json::objectValue;
|
Json::Value jsonUser = Json::objectValue;
|
||||||
jsonUser["name"] = user->name();
|
jsonUser["name"] = user->name();
|
||||||
users.append(jsonUser);
|
users.append(jsonUser);
|
||||||
@@ -157,24 +193,31 @@ namespace Yc {
|
|||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatRoom::RoomType ChatRoom::type() {
|
ChatRoom::RoomType ChatRoom::type()
|
||||||
|
{
|
||||||
return _type;
|
return _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::isType(ChatRoom::RoomType type) {
|
bool ChatRoom::isType(ChatRoom::RoomType type)
|
||||||
|
{
|
||||||
return ((_type & type) == type);
|
return ((_type & type) == type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::canDice() {
|
bool ChatRoom::canDice()
|
||||||
|
{
|
||||||
return (_roundRunning || (_type & rounds) == rounds) && (_type & dice) == dice;
|
return (_roundRunning || (_type & rounds) == rounds) && (_type & dice) == dice;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ChatRoom::addDice(std::shared_ptr<ChatUser> user, int diceValue) {
|
unsigned int ChatRoom::addDice(std::shared_ptr<ChatUser> user, int diceValue)
|
||||||
if (!canDice()) {
|
{
|
||||||
|
if (!canDice())
|
||||||
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (auto &listUser: _diceValues) {
|
for (auto &listUser : _diceValues)
|
||||||
if (listUser.first == user) {
|
{
|
||||||
|
if (listUser.first == user)
|
||||||
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,27 +226,36 @@ namespace Yc {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::accessAllowed(std::string userName, std::string password) {
|
bool ChatRoom::accessAllowed(std::string userName, std::string password)
|
||||||
|
{
|
||||||
return (_allowedUsers.size() == 0 || _password == "" || _password == password || std::find(_allowedUsers.begin(), _allowedUsers.end(), userName) != _allowedUsers.end());
|
return (_allowedUsers.size() == 0 || _password == "" || _password == password || std::find(_allowedUsers.begin(), _allowedUsers.end(), userName) != _allowedUsers.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatRoom::userIsInRoom(std::string userName) {
|
bool ChatRoom::userIsInRoom(std::string userName)
|
||||||
for (auto &user: _users) {
|
{
|
||||||
if (userName == user->name()) {
|
for (auto &user : _users)
|
||||||
|
{
|
||||||
|
if (userName == user->name())
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::_handleDice() {
|
void ChatRoom::_handleDice()
|
||||||
if (((_type & rounds) == rounds)) {
|
{
|
||||||
if (_roundRunning && (_users.size() < 2 || _roundStart + _roundLength >= time(NULL))) {
|
if (((_type & rounds) == rounds))
|
||||||
|
{
|
||||||
|
if (_roundRunning && (_users.size() < 2 || _roundStart + _roundLength >= time(NULL)))
|
||||||
|
{
|
||||||
_lastRoundEnd = time(NULL);
|
_lastRoundEnd = time(NULL);
|
||||||
_roundRunning = false;
|
_roundRunning = false;
|
||||||
addMessage(ChatUser::system, "round_ends");
|
addMessage(ChatUser::system, "round_ends");
|
||||||
_showDiceRoundResults();
|
_showDiceRoundResults();
|
||||||
} else if (!_roundRunning && _lastRoundEnd <= time(NULL) - 15 && _users.size() >= 2) {
|
}
|
||||||
|
else if (!_roundRunning && _lastRoundEnd <= time(NULL) - 15 && _users.size() >= 2)
|
||||||
|
{
|
||||||
_roundStart = time(NULL);
|
_roundStart = time(NULL);
|
||||||
_roundRunning = true;
|
_roundRunning = true;
|
||||||
_diceValues.clear();
|
_diceValues.clear();
|
||||||
@@ -212,19 +264,22 @@ namespace Yc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::_initRound() {
|
void ChatRoom::_initRound()
|
||||||
if (_users.size() == 2) {
|
{
|
||||||
|
if (_users.size() == 2)
|
||||||
|
{
|
||||||
_lastRoundEnd = time(NULL);
|
_lastRoundEnd = time(NULL);
|
||||||
addMessage(ChatUser::system, "next_round_starts_soon");
|
addMessage(ChatUser::system, "next_round_starts_soon");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatRoom::_showDiceRoundResults() {
|
void ChatRoom::_showDiceRoundResults()
|
||||||
std::sort(_diceValues.begin(), _diceValues.end(), [=](const std::pair<std::shared_ptr<ChatUser>, int>& val1, const std::pair<std::shared_ptr<ChatUser>, int>& val2) {
|
{
|
||||||
return (val1.second > val2.second);
|
std::sort(_diceValues.begin(), _diceValues.end(), [=](const std::pair<std::shared_ptr<ChatUser>, int> &val1, const std::pair<std::shared_ptr<ChatUser>, int> &val2)
|
||||||
});
|
{ return (val1.second > val2.second); });
|
||||||
Json::Value userList = Json::arrayValue;
|
Json::Value userList = Json::arrayValue;
|
||||||
for (auto &user: _diceValues) {
|
for (auto &user : _diceValues)
|
||||||
|
{
|
||||||
Json::Value entry = Json::objectValue;
|
Json::Value entry = Json::objectValue;
|
||||||
entry["name"] = user.first->name();
|
entry["name"] = user.first->name();
|
||||||
entry["value"] = user.second;
|
entry["value"] = user.second;
|
||||||
@@ -233,7 +288,8 @@ namespace Yc {
|
|||||||
addMessage(ChatUser::result, userList);
|
addMessage(ChatUser::result, userList);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ChatRoom::name() {
|
std::string ChatRoom::name()
|
||||||
|
{
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
#ifndef YC_LIB_CHAT_ROOM_H
|
#ifndef YC_LIB_CHAT_ROOM_H
|
||||||
#define YC_LIB_CHAT_ROOM_H
|
#define YC_LIB_CHAT_ROOM_H
|
||||||
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
@@ -11,18 +10,22 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <base.h>
|
#include "lib/base.h"
|
||||||
#include "chat_user.h"
|
#include "chat_user.h"
|
||||||
|
#include "object/room.h"
|
||||||
|
|
||||||
namespace Yc {
|
namespace Yc
|
||||||
namespace Lib {
|
{
|
||||||
|
namespace Lib
|
||||||
|
{
|
||||||
|
|
||||||
class Server;
|
class Server;
|
||||||
|
|
||||||
class ChatRoom: public Base, public std::enable_shared_from_this<ChatRoom> {
|
class ChatRoom : public Base, public std::enable_shared_from_this<ChatRoom>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
enum RoomType {
|
enum RoomType
|
||||||
|
{
|
||||||
none = 0,
|
none = 0,
|
||||||
dice = 1,
|
dice = 1,
|
||||||
poker = 2,
|
poker = 2,
|
||||||
@@ -32,6 +35,7 @@ namespace Yc {
|
|||||||
|
|
||||||
ChatRoom(std::shared_ptr<Server> parent, Json::Value roomParams);
|
ChatRoom(std::shared_ptr<Server> parent, Json::Value roomParams);
|
||||||
~ChatRoom();
|
~ChatRoom();
|
||||||
|
std::shared_ptr<Server> getServer() const { return _parent; }
|
||||||
void run();
|
void run();
|
||||||
std::string name();
|
std::string name();
|
||||||
bool addUser(std::string userName, std::string color, std::string password, int socket);
|
bool addUser(std::string userName, std::string color, std::string password, int socket);
|
||||||
@@ -40,7 +44,7 @@ namespace Yc {
|
|||||||
void removeUser(std::string _token, bool silent = false);
|
void removeUser(std::string _token, bool silent = false);
|
||||||
void removeUser(std::shared_ptr<ChatUser> user, bool silent = false);
|
void removeUser(std::shared_ptr<ChatUser> user, bool silent = false);
|
||||||
void setStop();
|
void setStop();
|
||||||
void addMessage(ChatUser::MsgType type, const char* messageText, std::string userName = "", std::string color = "");
|
void addMessage(ChatUser::MsgType type, const char *messageText, std::string userName = "", std::string color = "");
|
||||||
void addMessage(ChatUser::MsgType type, std::string messageText, std::string userName = "", std::string color = "");
|
void addMessage(ChatUser::MsgType type, std::string messageText, std::string userName = "", std::string color = "");
|
||||||
void addMessage(ChatUser::MsgType type, Json::Value messageText, std::string userName = "", std::string color = "");
|
void addMessage(ChatUser::MsgType type, Json::Value messageText, std::string userName = "", std::string color = "");
|
||||||
RoomType type();
|
RoomType type();
|
||||||
@@ -53,8 +57,10 @@ namespace Yc {
|
|||||||
bool userToNewRoom(std::shared_ptr<ChatUser> user, std::string newRoom, std::string password);
|
bool userToNewRoom(std::shared_ptr<ChatUser> user, std::string newRoom, std::string password);
|
||||||
unsigned int flags();
|
unsigned int flags();
|
||||||
Json::Value userList();
|
Json::Value userList();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Message {
|
struct Message
|
||||||
|
{
|
||||||
ChatUser::MsgType type;
|
ChatUser::MsgType type;
|
||||||
std::string messageTr;
|
std::string messageTr;
|
||||||
std::string userName;
|
std::string userName;
|
||||||
@@ -76,6 +82,7 @@ namespace Yc {
|
|||||||
time_t _lastRoundEnd;
|
time_t _lastRoundEnd;
|
||||||
int _roundLength;
|
int _roundLength;
|
||||||
std::vector<std::pair<std::shared_ptr<ChatUser>, int>> _diceValues;
|
std::vector<std::pair<std::shared_ptr<ChatUser>, int>> _diceValues;
|
||||||
|
Yc::Object::Room _room;
|
||||||
void _handleDice();
|
void _handleDice();
|
||||||
void _startDiceRound();
|
void _startDiceRound();
|
||||||
void _endDiceRound();
|
void _endDiceRound();
|
||||||
275
src/core/chat_user.cpp
Normal file
275
src/core/chat_user.cpp
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
// entfernt: #include "user.h"
|
||||||
|
|
||||||
|
#include "chat_user.h"
|
||||||
|
#include "server.h"
|
||||||
|
#include "lib/tools.h"
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "chat_room.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace Yc
|
||||||
|
{
|
||||||
|
namespace Lib
|
||||||
|
{
|
||||||
|
|
||||||
|
ChatUser::ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket)
|
||||||
|
: _parent(std::move(parent)),
|
||||||
|
_name(name),
|
||||||
|
_color(color),
|
||||||
|
_socket(socket),
|
||||||
|
_stop(false)
|
||||||
|
{
|
||||||
|
// Hole DB-Connection
|
||||||
|
auto server = _parent->getServer();
|
||||||
|
auto db = server->_database;
|
||||||
|
// Suche Community-User
|
||||||
|
std::string query = "SELECT * FROM community.\"user\" WHERE username = '" + name + "' LIMIT 1;";
|
||||||
|
auto result = db->exec(query);
|
||||||
|
Json::Value userJson;
|
||||||
|
if (result.empty()) {
|
||||||
|
// Kein Community-User, lege Dummy an
|
||||||
|
userJson["display_name"] = name;
|
||||||
|
userJson["color"] = "#000000";
|
||||||
|
} else {
|
||||||
|
const auto& row = result[0];
|
||||||
|
int falukant_user_id = row["id"].as<int>();
|
||||||
|
// Suche Chat-User
|
||||||
|
std::string chatUserQuery = "SELECT * FROM chat.\"user\" WHERE falukant_user_id = " + std::to_string(falukant_user_id) + " LIMIT 1;";
|
||||||
|
auto chatUserResult = db->exec(chatUserQuery);
|
||||||
|
if (chatUserResult.empty()) {
|
||||||
|
// Chat-User anlegen
|
||||||
|
std::string insert = "INSERT INTO chat.\"user\" (falukant_user_id, display_name, color, show_gender, show_age, created_at, updated_at) VALUES (" +
|
||||||
|
std::to_string(falukant_user_id) + ", '" + name + "', '#000000', true, true, NOW(), NOW()) RETURNING *;";
|
||||||
|
auto newUser = db->exec(insert);
|
||||||
|
if (!newUser.empty()) {
|
||||||
|
const auto& u = newUser[0];
|
||||||
|
userJson["id"] = u["id"].as<int>();
|
||||||
|
userJson["falukant_user_id"] = u["falukant_user_id"].as<int>();
|
||||||
|
userJson["display_name"] = u["display_name"].c_str();
|
||||||
|
userJson["color"] = u["color"].c_str();
|
||||||
|
userJson["show_gender"] = u["show_gender"].as<bool>();
|
||||||
|
userJson["show_age"] = u["show_age"].as<bool>();
|
||||||
|
userJson["created_at"] = u["created_at"].c_str();
|
||||||
|
userJson["updated_at"] = u["updated_at"].c_str();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto& u = chatUserResult[0];
|
||||||
|
userJson["id"] = u["id"].as<int>();
|
||||||
|
userJson["falukant_user_id"] = u["falukant_user_id"].as<int>();
|
||||||
|
userJson["display_name"] = u["display_name"].c_str();
|
||||||
|
userJson["color"] = u["color"].c_str();
|
||||||
|
userJson["show_gender"] = u["show_gender"].as<bool>();
|
||||||
|
userJson["show_age"] = u["show_age"].as<bool>();
|
||||||
|
userJson["created_at"] = u["created_at"].c_str();
|
||||||
|
userJson["updated_at"] = u["updated_at"].c_str();
|
||||||
|
}
|
||||||
|
// Rechte laden
|
||||||
|
std::string rightsQuery = "SELECT r.tr FROM chat.user_rights ur JOIN chat.rights r ON ur.chat_right_id = r.id WHERE ur.chat_user_id = " + std::to_string(userJson["id"].asInt()) + ";";
|
||||||
|
auto rightsResult = db->exec(rightsQuery);
|
||||||
|
Json::Value rights(Json::arrayValue);
|
||||||
|
for (const auto& r : rightsResult) {
|
||||||
|
rights.append(r["tr"].c_str());
|
||||||
|
}
|
||||||
|
userJson["rights"] = rights;
|
||||||
|
}
|
||||||
|
_user = Yc::Object::User(userJson);
|
||||||
|
_token = Yc::Lib::Tools::generateRandomString(32);
|
||||||
|
sendMsg(token, _token, "", "");
|
||||||
|
thread = std::make_unique<std::thread>(&ChatUser::checkerTask, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatUser::~ChatUser()
|
||||||
|
{
|
||||||
|
_parent->addMessage(ChatUser::system, std::string("leaved_chat"), std::string(_name), std::string(_color));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ChatUser::name() const
|
||||||
|
{
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatUser::validateToken(std::string token)
|
||||||
|
{
|
||||||
|
return (token == _token);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatUser::isUser(std::shared_ptr<ChatUser> toValidate)
|
||||||
|
{
|
||||||
|
return (toValidate.get() == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::sendMsg(MsgType type, const char *message, std::string userName, std::string color)
|
||||||
|
{
|
||||||
|
sendMsg(type, std::string(message), userName, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::sendMsg(MsgType type, std::string message, std::string userName, std::string color)
|
||||||
|
{
|
||||||
|
Json::Value sendMessage;
|
||||||
|
sendMessage["type"] = type;
|
||||||
|
sendMessage["message"] = message;
|
||||||
|
sendMessage["userName"] = userName;
|
||||||
|
sendMessage["color"] = color;
|
||||||
|
send(sendMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::sendMsg(MsgType type, Json::Value message, std::string userName, std::string color)
|
||||||
|
{
|
||||||
|
Json::Value sendMessage;
|
||||||
|
sendMessage["type"] = type;
|
||||||
|
sendMessage["message"] = message;
|
||||||
|
sendMessage["userName"] = userName;
|
||||||
|
sendMessage["color"] = color;
|
||||||
|
send(sendMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::checkerTask()
|
||||||
|
{
|
||||||
|
while (!_stop)
|
||||||
|
{
|
||||||
|
fd_set readSd;
|
||||||
|
FD_ZERO(&readSd);
|
||||||
|
FD_SET(_socket, &readSd);
|
||||||
|
timeval tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 500;
|
||||||
|
int selectResult = select(_socket + 1, &readSd, NULL, NULL, &tv);
|
||||||
|
if (selectResult == 1 && FD_ISSET(_socket, &readSd) == 1)
|
||||||
|
{
|
||||||
|
_parent->removeUser(_token);
|
||||||
|
_stop = true;
|
||||||
|
delete this;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string msg = readSocket(_socket);
|
||||||
|
if (msg == "")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
handleMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::stop()
|
||||||
|
{
|
||||||
|
_stop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ChatUser::color() const
|
||||||
|
{
|
||||||
|
return _color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::setParent(std::shared_ptr<ChatRoom> parent)
|
||||||
|
{
|
||||||
|
_parent = std::move(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::send(std::string out)
|
||||||
|
{
|
||||||
|
Base::send(_socket, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::send(Json::Value out)
|
||||||
|
{
|
||||||
|
Base::send(_socket, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::handleMessage(std::string message)
|
||||||
|
{
|
||||||
|
Json::Value jsonTree = getJsonTree(message);
|
||||||
|
if (jsonTree["token"].asString() != _token)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (jsonTree["type"].asString() == "message")
|
||||||
|
{
|
||||||
|
checkString(jsonTree["message"].asString());
|
||||||
|
}
|
||||||
|
else if (jsonTree["type"].asString() == "dice")
|
||||||
|
{
|
||||||
|
doDice();
|
||||||
|
}
|
||||||
|
else if (jsonTree["type"].asString() == "scream")
|
||||||
|
{
|
||||||
|
_parent->addMessage(ChatUser::scream, jsonTree["message"].asString(), std::string(_name), std::string(_color));
|
||||||
|
}
|
||||||
|
else if (jsonTree["type"].asString() == "do")
|
||||||
|
{
|
||||||
|
_parent->addMessage(ChatUser::dosomething, jsonTree["message"].asString(), std::string(_name), std::string(_color));
|
||||||
|
}
|
||||||
|
else if (jsonTree["type"].asString() == "join")
|
||||||
|
{
|
||||||
|
changeRoom(jsonTree["newroom"].asString(), jsonTree["password"].asString());
|
||||||
|
}
|
||||||
|
else if (jsonTree["type"].asString() == "userlist")
|
||||||
|
{
|
||||||
|
sendUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::checkString(std::string message)
|
||||||
|
{
|
||||||
|
if (message.substr(0, 6) == "/join ")
|
||||||
|
{
|
||||||
|
message = message.substr(6);
|
||||||
|
if (message.find(" ") == std::string::npos)
|
||||||
|
{
|
||||||
|
changeRoom(message, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string room = message.substr(0, message.find(" "));
|
||||||
|
std::string password = message.substr(message.find(" ") + 1);
|
||||||
|
changeRoom(room, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message == "/dice")
|
||||||
|
{
|
||||||
|
doDice();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_parent->addMessage(ChatUser::message, std::string(message), std::string(_name), std::string(_color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::sendUserList()
|
||||||
|
{
|
||||||
|
Json::Value userList = _parent->userList();
|
||||||
|
Json::Value msg = Json::objectValue;
|
||||||
|
msg["userlist"] = userList;
|
||||||
|
sendMsg(userListe, msg, "", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::doDice()
|
||||||
|
{
|
||||||
|
switch (_parent->addDice(shared_from_this(), (rand() % 6) + 1))
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
sendMsg(system, "dice_not_possible", "", "");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sendMsg(system, "dice_allready_done", "", "");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatUser::changeRoom(std::string newRoom, std::string password)
|
||||||
|
{
|
||||||
|
if (!_parent->userToNewRoom(shared_from_this(), newRoom, password))
|
||||||
|
{
|
||||||
|
sendMsg(ChatUser::system, "room_not_possible", "", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Lib
|
||||||
|
} // namespace Yc
|
||||||
71
src/core/chat_user.h
Normal file
71
src/core/chat_user.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#ifndef YC_LIB_CHAT_USER_H
|
||||||
|
#define YC_LIB_CHAT_USER_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <thread>
|
||||||
|
#include "lib/base.h"
|
||||||
|
#include "object/user.h"
|
||||||
|
|
||||||
|
namespace Yc
|
||||||
|
{
|
||||||
|
namespace Lib
|
||||||
|
{
|
||||||
|
|
||||||
|
class ChatRoom;
|
||||||
|
|
||||||
|
class ChatUser : public Base, public std::enable_shared_from_this<ChatUser>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum MsgType
|
||||||
|
{
|
||||||
|
error = -1,
|
||||||
|
token = 1,
|
||||||
|
userListe = 2,
|
||||||
|
roomList = 3,
|
||||||
|
message = 4,
|
||||||
|
system = 5,
|
||||||
|
scream = 6,
|
||||||
|
dosomething = 7,
|
||||||
|
dice = 8,
|
||||||
|
result = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
ChatUser(std::shared_ptr<ChatRoom> parent, std::string name, std::string color, int socket);
|
||||||
|
~ChatUser();
|
||||||
|
std::string name() const;
|
||||||
|
bool validateToken(std::string token);
|
||||||
|
bool isUser(std::shared_ptr<ChatUser> toValidate);
|
||||||
|
void sendMsg(MsgType type, std::string message, std::string userName, std::string color);
|
||||||
|
void sendMsg(MsgType type, const char *message, std::string userName, std::string color);
|
||||||
|
void sendMsg(MsgType type, Json::Value message, std::string userName, std::string color);
|
||||||
|
void checkerTask();
|
||||||
|
void stop();
|
||||||
|
std::string color() const;
|
||||||
|
void setParent(std::shared_ptr<ChatRoom> parent);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<ChatRoom> _parent;
|
||||||
|
Yc::Object::User _user;
|
||||||
|
std::string _name;
|
||||||
|
std::string _color;
|
||||||
|
int _socket;
|
||||||
|
std::string _token;
|
||||||
|
bool _stop;
|
||||||
|
std::unique_ptr<std::thread> thread;
|
||||||
|
|
||||||
|
void send(std::string out);
|
||||||
|
void send(Json::Value out);
|
||||||
|
void handleMessage(std::string message);
|
||||||
|
void doDice();
|
||||||
|
void changeRoom(std::string newRoom, std::string password);
|
||||||
|
void checkString(std::string message);
|
||||||
|
void sendUserList();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Lib
|
||||||
|
} // namespace Yc
|
||||||
|
|
||||||
|
#endif // YC_LIB_CHAT_USER_H
|
||||||
@@ -32,7 +32,6 @@ namespace Yc {
|
|||||||
std::cout << "bind not possible" << std::endl;
|
std::cout << "bind not possible" << std::endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
// createRooms wird jetzt außerhalb des Konstruktors aufgerufen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::run() {
|
void Server::run() {
|
||||||
@@ -114,8 +113,30 @@ namespace Yc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Server::createRooms(Json::Value roomList) {
|
void Server::createRooms(Json::Value roomList) {
|
||||||
|
// Ignoriere roomList, lade stattdessen aus der Datenbank
|
||||||
auto self = shared_from_this();
|
auto self = shared_from_this();
|
||||||
for (auto &room: roomList) {
|
std::string query = R"(
|
||||||
|
SELECT r.id, r.title, r.password_hash, r.room_type_id, r.is_public, r.owner_id, r.min_age, r.max_age, r.created_at, r.updated_at, rt.tr as room_type
|
||||||
|
FROM chat.room r
|
||||||
|
LEFT JOIN chat.room_type rt ON r.room_type_id = rt.id
|
||||||
|
)";
|
||||||
|
auto result = _database->exec(query);
|
||||||
|
for (const auto& row : result) {
|
||||||
|
Json::Value room;
|
||||||
|
room["id"] = row["id"].as<int>();
|
||||||
|
room["name"] = row["title"].c_str();
|
||||||
|
room["password"] = row["password_hash"].is_null() ? "" : row["password_hash"].c_str();
|
||||||
|
room["type"] = row["room_type_id"].is_null() ? 0 : row["room_type_id"].as<int>();
|
||||||
|
room["is_public"] = row["is_public"].as<bool>();
|
||||||
|
room["owner_id"] = row["owner_id"].is_null() ? 0 : row["owner_id"].as<int>();
|
||||||
|
room["min_age"] = row["min_age"].is_null() ? 0 : row["min_age"].as<int>();
|
||||||
|
room["max_age"] = row["max_age"].is_null() ? 0 : row["max_age"].as<int>();
|
||||||
|
room["created_at"] = row["created_at"].c_str();
|
||||||
|
room["updated_at"] = row["updated_at"].c_str();
|
||||||
|
room["room_type"] = row["room_type"].is_null() ? "" : row["room_type"].c_str();
|
||||||
|
// Platzhalter für Felder, die im Konstruktor benötigt werden
|
||||||
|
room["allowed"] = Json::arrayValue; // ggf. später befüllen
|
||||||
|
room["roundlength"] = 60; // Default-Wert
|
||||||
auto newRoom = std::make_shared<ChatRoom>(self, room);
|
auto newRoom = std::make_shared<ChatRoom>(self, room);
|
||||||
_rooms.push_back(newRoom);
|
_rooms.push_back(newRoom);
|
||||||
}
|
}
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
#define YP_LIB_SERVER_H
|
#define YP_LIB_SERVER_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "database.h"
|
#include "lib/database.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "chat_room.h"
|
#include "chat_room.h"
|
||||||
#include "base.h"
|
#include "lib/base.h"
|
||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
|
|
||||||
namespace Yc {
|
namespace Yc {
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <pqxx/pqxx>
|
#include <pqxx/pqxx>
|
||||||
#include "config.h"
|
#include "../core/config.h"
|
||||||
|
|
||||||
namespace Yc {
|
namespace Yc {
|
||||||
namespace Lib {
|
namespace Lib {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "core/config.h"
|
||||||
#include "server.h"
|
#include "core/server.h"
|
||||||
#include "database.h"
|
#include "lib/database.h"
|
||||||
|
|
||||||
// main function
|
// main function
|
||||||
int main(int, char **) {
|
int main(int, char **) {
|
||||||
42
src/object/room.cpp
Normal file
42
src/object/room.cpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#include "room.h"
|
||||||
|
|
||||||
|
namespace Yc
|
||||||
|
{
|
||||||
|
namespace Object
|
||||||
|
{
|
||||||
|
|
||||||
|
Room::Room(const Json::Value &roomJson)
|
||||||
|
{
|
||||||
|
_id = roomJson.isMember("id") && !roomJson["id"].isNull() ? roomJson["id"].asInt() : 0;
|
||||||
|
_title = roomJson.isMember("name") && !roomJson["name"].isNull() ? roomJson["name"].asString() : "";
|
||||||
|
_owner_id = roomJson.isMember("owner_id") && !roomJson["owner_id"].isNull() ? roomJson["owner_id"].asInt() : 0;
|
||||||
|
_is_public = roomJson.isMember("is_public") && !roomJson["is_public"].isNull() ? roomJson["is_public"].asBool() : true;
|
||||||
|
_gender_restriction_id = roomJson.isMember("gender_restriction_id") && !roomJson["gender_restriction_id"].isNull() ? roomJson["gender_restriction_id"].asInt() : 0;
|
||||||
|
_min_age = roomJson.isMember("min_age") && !roomJson["min_age"].isNull() ? roomJson["min_age"].asInt() : 0;
|
||||||
|
_max_age = roomJson.isMember("max_age") && !roomJson["max_age"].isNull() ? roomJson["max_age"].asInt() : 0;
|
||||||
|
_password_hash = roomJson.isMember("password") && !roomJson["password"].isNull() ? roomJson["password"].asString() : "";
|
||||||
|
_friends_of_owner_only = roomJson.isMember("friends_of_owner_only") && !roomJson["friends_of_owner_only"].isNull() ? roomJson["friends_of_owner_only"].asBool() : false;
|
||||||
|
_required_user_right_id = roomJson.isMember("required_user_right_id") && !roomJson["required_user_right_id"].isNull() ? roomJson["required_user_right_id"].asInt() : 0;
|
||||||
|
_created_at = roomJson.isMember("created_at") && !roomJson["created_at"].isNull() ? roomJson["created_at"].asString() : "";
|
||||||
|
_updated_at = roomJson.isMember("updated_at") && !roomJson["updated_at"].isNull() ? roomJson["updated_at"].asString() : "";
|
||||||
|
_room_type_id = roomJson.isMember("type") && !roomJson["type"].isNull() ? roomJson["type"].asInt() : 0;
|
||||||
|
_room_type_tr = roomJson.isMember("room_type") && !roomJson["room_type"].isNull() ? roomJson["room_type"].asString() : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
int Room::id() const { return _id; }
|
||||||
|
const std::string &Room::title() const { return _title; }
|
||||||
|
int Room::owner_id() const { return _owner_id; }
|
||||||
|
bool Room::is_public() const { return _is_public; }
|
||||||
|
int Room::gender_restriction_id() const { return _gender_restriction_id; }
|
||||||
|
int Room::min_age() const { return _min_age; }
|
||||||
|
int Room::max_age() const { return _max_age; }
|
||||||
|
const std::string &Room::password_hash() const { return _password_hash; }
|
||||||
|
bool Room::friends_of_owner_only() const { return _friends_of_owner_only; }
|
||||||
|
int Room::required_user_right_id() const { return _required_user_right_id; }
|
||||||
|
const std::string &Room::created_at() const { return _created_at; }
|
||||||
|
const std::string &Room::updated_at() const { return _updated_at; }
|
||||||
|
int Room::room_type_id() const { return _room_type_id; }
|
||||||
|
const std::string &Room::room_type_tr() const { return _room_type_tr; }
|
||||||
|
|
||||||
|
} // namespace Object
|
||||||
|
} // namespace Yc
|
||||||
48
src/object/room.h
Normal file
48
src/object/room.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
namespace Yc
|
||||||
|
{
|
||||||
|
namespace Object
|
||||||
|
{
|
||||||
|
|
||||||
|
class Room
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Room(const Json::Value &roomJson);
|
||||||
|
|
||||||
|
int id() const;
|
||||||
|
const std::string &title() const;
|
||||||
|
int owner_id() const;
|
||||||
|
bool is_public() const;
|
||||||
|
int gender_restriction_id() const;
|
||||||
|
int min_age() const;
|
||||||
|
int max_age() const;
|
||||||
|
const std::string &password_hash() const;
|
||||||
|
bool friends_of_owner_only() const;
|
||||||
|
int required_user_right_id() const;
|
||||||
|
const std::string &created_at() const;
|
||||||
|
const std::string &updated_at() const;
|
||||||
|
int room_type_id() const;
|
||||||
|
const std::string &room_type_tr() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _id = 0;
|
||||||
|
std::string _title;
|
||||||
|
int _owner_id = 0;
|
||||||
|
bool _is_public = true;
|
||||||
|
int _gender_restriction_id = 0;
|
||||||
|
int _min_age = 0;
|
||||||
|
int _max_age = 0;
|
||||||
|
std::string _password_hash;
|
||||||
|
bool _friends_of_owner_only = false;
|
||||||
|
int _required_user_right_id = 0;
|
||||||
|
std::string _created_at;
|
||||||
|
std::string _updated_at;
|
||||||
|
int _room_type_id = 0;
|
||||||
|
std::string _room_type_tr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Object
|
||||||
|
} // namespace Yc
|
||||||
37
src/object/user.cpp
Normal file
37
src/object/user.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include "user.h"
|
||||||
|
|
||||||
|
namespace Yc
|
||||||
|
{
|
||||||
|
namespace Object
|
||||||
|
{
|
||||||
|
|
||||||
|
User::User() = default;
|
||||||
|
|
||||||
|
User::User(const Json::Value& userJson) {
|
||||||
|
_id = userJson.isMember("id") && !userJson["id"].isNull() ? userJson["id"].asInt() : 0;
|
||||||
|
_falukant_user_id = userJson.isMember("falukant_user_id") && !userJson["falukant_user_id"].isNull() ? userJson["falukant_user_id"].asInt() : 0;
|
||||||
|
_display_name = userJson.isMember("display_name") && !userJson["display_name"].isNull() ? userJson["display_name"].asString() : "";
|
||||||
|
_color = userJson.isMember("color") && !userJson["color"].isNull() ? userJson["color"].asString() : "#000000";
|
||||||
|
_show_gender = userJson.isMember("show_gender") && !userJson["show_gender"].isNull() ? userJson["show_gender"].asBool() : true;
|
||||||
|
_show_age = userJson.isMember("show_age") && !userJson["show_age"].isNull() ? userJson["show_age"].asBool() : true;
|
||||||
|
_created_at = userJson.isMember("created_at") && !userJson["created_at"].isNull() ? userJson["created_at"].asString() : "";
|
||||||
|
_updated_at = userJson.isMember("updated_at") && !userJson["updated_at"].isNull() ? userJson["updated_at"].asString() : "";
|
||||||
|
if (userJson.isMember("rights") && userJson["rights"].isArray()) {
|
||||||
|
for (const auto& r : userJson["rights"]) {
|
||||||
|
_rights.push_back(r.asString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int User::id() const { return _id; }
|
||||||
|
int User::falukant_user_id() const { return _falukant_user_id; }
|
||||||
|
const std::string& User::display_name() const { return _display_name; }
|
||||||
|
const std::string& User::color() const { return _color; }
|
||||||
|
bool User::show_gender() const { return _show_gender; }
|
||||||
|
bool User::show_age() const { return _show_age; }
|
||||||
|
const std::string& User::created_at() const { return _created_at; }
|
||||||
|
const std::string& User::updated_at() const { return _updated_at; }
|
||||||
|
const std::vector<std::string>& User::rights() const { return _rights; }
|
||||||
|
|
||||||
|
} // namespace Object
|
||||||
|
} // namespace Yc
|
||||||
39
src/object/user.h
Normal file
39
src/object/user.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <json/value.h>
|
||||||
|
|
||||||
|
namespace Yc
|
||||||
|
{
|
||||||
|
namespace Object
|
||||||
|
{
|
||||||
|
|
||||||
|
class User {
|
||||||
|
public:
|
||||||
|
User();
|
||||||
|
User(const Json::Value& userJson);
|
||||||
|
|
||||||
|
int id() const;
|
||||||
|
int falukant_user_id() const;
|
||||||
|
const std::string& display_name() const;
|
||||||
|
const std::string& color() const;
|
||||||
|
bool show_gender() const;
|
||||||
|
bool show_age() const;
|
||||||
|
const std::string& created_at() const;
|
||||||
|
const std::string& updated_at() const;
|
||||||
|
const std::vector<std::string>& rights() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _id = 0;
|
||||||
|
int _falukant_user_id = 0;
|
||||||
|
std::string _display_name;
|
||||||
|
std::string _color = "#000000";
|
||||||
|
bool _show_gender = true;
|
||||||
|
bool _show_age = true;
|
||||||
|
std::string _created_at;
|
||||||
|
std::string _updated_at;
|
||||||
|
std::vector<std::string> _rights;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Object
|
||||||
|
} // namespace Yc
|
||||||
0
src/server.h
Normal file
0
src/server.h
Normal file
Reference in New Issue
Block a user