From 9d84d5d8e7f61a02c01eef021ea5e8b2f49dcf8f Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 28 Apr 2018 15:31:27 +0200 Subject: Connect channels to database, currently only locally --- depends/odhtdb | 2 +- include/Channel.hpp | 30 +++++++++++++--- include/ChannelSidePanel.hpp | 2 ++ include/MessageBoard.hpp | 9 +++-- include/User.hpp | 35 ++++++++++++++++-- include/UsersSidePanel.hpp | 7 ++-- src/Cache.cpp | 2 +- src/Channel.cpp | 77 +++++++++++++++++++++++++++++++++------ src/ChannelSidePanel.cpp | 5 +++ src/Chatbar.cpp | 2 +- src/User.cpp | 34 ++++++++++++++++++ src/UsersSidePanel.cpp | 16 ++++++--- src/main.cpp | 85 +++++++++++++++++++++++++++++++++++++------- 13 files changed, 264 insertions(+), 42 deletions(-) diff --git a/depends/odhtdb b/depends/odhtdb index 54d8ae4..97fd90f 160000 --- a/depends/odhtdb +++ b/depends/odhtdb @@ -1 +1 @@ -Subproject commit 54d8ae4c335c21290dc41e5ba4701b3c19bba601 +Subproject commit 97fd90f4c3319e3e789416155c1a462ab179875c diff --git a/include/Channel.hpp b/include/Channel.hpp index 4bdb4b5..6f5495f 100644 --- a/include/Channel.hpp +++ b/include/Channel.hpp @@ -4,25 +4,45 @@ #include "Chatbar.hpp" #include "User.hpp" #include "Channel.hpp" +#include +#include +#include + +namespace odhtdb +{ + class Database; +} namespace dchat { class Channel { public: - Channel(const std::string &name); - ~Channel(); + Channel(const std::string &name, const odhtdb::DatabaseNode &databaseNodeInfo = odhtdb::DatabaseNode(), User *localUser = nullptr, odhtdb::Database *database = nullptr); + virtual ~Channel(); User* getLocalUser(); MessageBoard& getMessageBoard(); + const std::string& getName() const; + const std::vector getUsers() const; + User* getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey); + + void addLocalMessage(const std::string &msg, User *owner); + void addMessage(const std::string &msg); + void addUser(User *user); void processEvent(const sf::Event &event); void draw(sf::RenderWindow &window, Cache &cache); - private: + protected: + odhtdb::Database *database; + odhtdb::DatabaseNode databaseNodeInfo; + std::string name; MessageBoard messageBoard; Chatbar chatbar; - OfflineUser localOfflineUser; - std::string name; + User *localUser; + SystemUser systemUser; + std::vector users; + odhtdb::Signature::MapPublicKey publicKeyOnlineUsersMap; }; } diff --git a/include/ChannelSidePanel.hpp b/include/ChannelSidePanel.hpp index c1ed5d6..9cee907 100644 --- a/include/ChannelSidePanel.hpp +++ b/include/ChannelSidePanel.hpp @@ -10,6 +10,8 @@ namespace dchat { public: static void addChannel(Channel *channel); + static void removeAllChannels(); + static void draw(sf::RenderWindow &window); static float getWidth(); }; diff --git a/include/MessageBoard.hpp b/include/MessageBoard.hpp index ca1405f..b431af8 100644 --- a/include/MessageBoard.hpp +++ b/include/MessageBoard.hpp @@ -10,17 +10,20 @@ namespace dchat { + class Channel; + class MessageBoard { + friend class Channel; public: MessageBoard(const sf::Vector2u &size); ~MessageBoard(); - void updateStaticContentTexture(const sf::Vector2u &newSize); - void addMessage(Message *message); - void processEvent(const sf::Event &event); void draw(sf::RenderWindow &window, Cache &cache); + private: + void updateStaticContentTexture(const sf::Vector2u &newSize); + void addMessage(Message *message); private: sf::RenderTexture staticContentTexture; bool dirty; diff --git a/include/User.hpp b/include/User.hpp index 2a8f46b..e9e334a 100644 --- a/include/User.hpp +++ b/include/User.hpp @@ -2,13 +2,37 @@ #include +namespace odhtdb +{ + class User; +} + namespace dchat { class User { public: + enum class Type + { + ONLINE, + OFFLINE, + SYSTEM + }; + + User(Type type); virtual ~User(){} virtual const std::string& getName() const = 0; + + const Type type; + }; + + class OnlineUser : public User + { + public: + OnlineUser(const odhtdb::User *databaseUser); + virtual const std::string& getName() const override; + + const odhtdb::User *databaseUser; }; class OfflineUser : public User @@ -16,7 +40,14 @@ namespace dchat public: OfflineUser(const std::string &name); virtual const std::string& getName() const override; - - std::string name; + + const std::string name; + }; + + class SystemUser : public User + { + public: + SystemUser(); + virtual const std::string& getName() const override; }; } diff --git a/include/UsersSidePanel.hpp b/include/UsersSidePanel.hpp index aebdb34..b2855bb 100644 --- a/include/UsersSidePanel.hpp +++ b/include/UsersSidePanel.hpp @@ -1,14 +1,17 @@ #pragma once -#include "User.hpp" #include namespace dchat { + class Channel; + class UsersSidePanel { public: - static void addUser(User *user); + static void setCurrentChannel(Channel *channel); + static Channel* getCurrentChannel(); + static void draw(sf::RenderWindow &window); static float getWidth(); }; diff --git a/src/Cache.cpp b/src/Cache.cpp index abfa1dd..bfa3df4 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -55,7 +55,7 @@ namespace dchat boost::filesystem::path Cache::getDchatDir() { - boost::filesystem::path dchatHomeDir = getHomeDir() / ".dchat"; + boost::filesystem::path dchatHomeDir = getHomeDir() / ".local" / "share" / "dchat"; boost::filesystem::create_directories(dchatHomeDir); return dchatHomeDir; } diff --git a/src/Channel.cpp b/src/Channel.cpp index f02b97a..ef252f6 100644 --- a/src/Channel.cpp +++ b/src/Channel.cpp @@ -1,61 +1,75 @@ #include "../include/Channel.hpp" #include "../include/UsersSidePanel.hpp" #include "../include/ChannelSidePanel.hpp" +#include +#include #include using namespace std; namespace dchat { - Channel::Channel(const std::string &_name) : + Channel::Channel(const string &_name, const odhtdb::DatabaseNode &_databaseNodeInfo, User *_localUser, odhtdb::Database *_database) : + database(_database), + databaseNodeInfo(_databaseNodeInfo), + name(_name), messageBoard(sf::Vector2u(1.0f, 1.0f)), - localOfflineUser("You"), - name(_name) + localUser(_localUser ? _localUser : new OfflineUser("You")) { + addUser(localUser); { - Message *message = new Message(&localOfflineUser, u8"hello, worldåäö1![emoji](https://discordemoji.com/assets/emoji/playtime.png)"); + Message *message = new Message(&systemUser, u8"hello, worldåäö1![emoji](https://discordemoji.com/assets/emoji/playtime.png)"); messageBoard.addMessage(message); } { - Message *message = new Message(&localOfflineUser, u8"hello, world2![emoji](https://discordemoji.com/assets/emoji/Feels3DMan.gif)"); + Message *message = new Message(&systemUser, u8"hello, world2![emoji](https://discordemoji.com/assets/emoji/Feels3DMan.gif)"); messageBoard.addMessage(message); } { - Message *message = new Message(&localOfflineUser, u8"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); + Message *message = new Message(&systemUser, u8"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); messageBoard.addMessage(message); } { - Message *message = new Message(&localOfflineUser, u8"Lorem ipsumdolorsitamet,consecteturadipiscingelit,seddoeiusmodtemporincididuntutaboreetdoloremagnaaliqua.Utenimadminimveniam"); + Message *message = new Message(&systemUser, u8"Lorem ipsumdolorsitamet,consecteturadipiscingelit,seddoeiusmodtemporincididuntutaboreetdoloremagnaaliqua.Utenimadminimveniam"); messageBoard.addMessage(message); } { - Message *message = new Message(&localOfflineUser, u8"xddd"); + Message *message = new Message(&systemUser, u8"xddd"); messageBoard.addMessage(message); } { - Message *message = new Message(&localOfflineUser, u8"[emoji](https://discordemoji.com/assets/emoji/SlowbroDumb.png)"); + Message *message = new Message(&systemUser, u8"[emoji](https://discordemoji.com/assets/emoji/SlowbroDumb.png)"); messageBoard.addMessage(message); } { - Message *message = new Message(&localOfflineUser, u8"Message after big emoji"); + Message *message = new Message(&systemUser, u8"Message after big emoji"); messageBoard.addMessage(message); } + + if(database) + database->seed(databaseNodeInfo); } Channel::~Channel() { + if(database) + database->stopSeeding(*databaseNodeInfo.getRequestHash()); + for(User *user : users) + { + delete user; + } } User* Channel::getLocalUser() { - return &localOfflineUser; + return localUser; } MessageBoard& Channel::getMessageBoard() @@ -68,6 +82,47 @@ namespace dchat return name; } + const vector Channel::getUsers() const + { + return users; + } + + User* Channel::getUserByPublicKey(const odhtdb::Signature::PublicKey &publicKey) + { + auto userIt = publicKeyOnlineUsersMap.find(publicKey); + if(userIt != publicKeyOnlineUsersMap.end()) + return userIt->second; + return nullptr; + } + + void Channel::addLocalMessage(const std::string &msg, User *owner) + { + assert(owner); + messageBoard.addMessage(new Message(owner, msg)); + } + + void Channel::addMessage(const std::string &msg) + { + messageBoard.addMessage(new Message(localUser, msg)); + if(database && localUser->type == User::Type::ONLINE) + { + auto onlineUser = static_cast(localUser); + assert(onlineUser->databaseUser->getType() == odhtdb::User::Type::LOCAL); + database->addData(databaseNodeInfo, static_cast(onlineUser->databaseUser), odhtdb::DataView((void*)msg.data(), msg.size())); + database->commit(); + } + } + + void Channel::addUser(User *user) + { + users.push_back(user); + if(user->type == User::Type::ONLINE) + { + auto onlineUser = static_cast(user); + publicKeyOnlineUsersMap[onlineUser->databaseUser->getPublicKey()] = onlineUser; + } + } + void Channel::processEvent(const sf::Event &event) { chatbar.processEvent(event, this); diff --git a/src/ChannelSidePanel.cpp b/src/ChannelSidePanel.cpp index a85dbdc..eb5c74c 100644 --- a/src/ChannelSidePanel.cpp +++ b/src/ChannelSidePanel.cpp @@ -20,6 +20,11 @@ namespace dchat channels.push_back(channel); } + void ChannelSidePanel::removeAllChannels() + { + channels.clear(); + } + void ChannelSidePanel::draw(sf::RenderWindow &window) { auto windowSize = window.getSize(); diff --git a/src/Chatbar.cpp b/src/Chatbar.cpp index 51ab9f5..241a808 100644 --- a/src/Chatbar.cpp +++ b/src/Chatbar.cpp @@ -235,7 +235,7 @@ namespace dchat if(msg[0] == '/') processChatCommand(StringView(msg.data() + 1, msg.size() - 1)); else - channel->getMessageBoard().addMessage(new Message(channel->getLocalUser(), msg)); + channel->addMessage(msg); clear(); } } diff --git a/src/User.cpp b/src/User.cpp index 6b07b5b..2908fd4 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -1,8 +1,31 @@ #include "../include/User.hpp" +#include +#include namespace dchat { + const static std::string SYSTEM_USER_NAME = "System"; + + User::User(Type _type) : + type(_type) + { + + } + + OnlineUser::OnlineUser(const odhtdb::User *_databaseUser) : + User(Type::ONLINE), + databaseUser(_databaseUser) + { + assert(databaseUser); + } + + const std::string& OnlineUser::getName() const + { + return databaseUser->getName(); + } + OfflineUser::OfflineUser(const std::string &_name) : + User(Type::OFFLINE), name(_name) { @@ -12,4 +35,15 @@ namespace dchat { return name; } + + SystemUser::SystemUser() : + User(Type::SYSTEM) + { + + } + + const std::string& SystemUser::getName() const + { + return SYSTEM_USER_NAME; + } } diff --git a/src/UsersSidePanel.cpp b/src/UsersSidePanel.cpp index 5af01bc..39c0b86 100644 --- a/src/UsersSidePanel.cpp +++ b/src/UsersSidePanel.cpp @@ -1,6 +1,7 @@ #include "../include/UsersSidePanel.hpp" #include "../include/ResourceCache.hpp" #include "../include/Settings.hpp" +#include "../include/Channel.hpp" #include #include #include @@ -10,13 +11,18 @@ using namespace std; namespace dchat { - vector users; + Channel *currentChannel = nullptr; const float width = 200.0f; const unsigned int FONT_SIZE = 20; - void UsersSidePanel::addUser(User *user) + void UsersSidePanel::setCurrentChannel(Channel *channel) { - users.push_back(user); + currentChannel = channel; + } + + Channel* UsersSidePanel::getCurrentChannel() + { + return currentChannel; } void UsersSidePanel::draw(sf::RenderWindow &window) @@ -27,9 +33,11 @@ namespace dchat rect.setPosition(windowSize.x - width, 0.0f); window.draw(rect); + if(!currentChannel) return; + const sf::Font &font = ResourceCache::getFont("fonts/Roboto-Regular.ttf"); sf::Vector2f position(rect.getPosition().x + 10.0f, 10.0f); - for(User *user : users) + for(User *user : currentChannel->getUsers()) { // TODO: Remove this shit sf::String str = sf::String::fromUtf8(user->getName().begin(), user->getName().end()); diff --git a/src/main.cpp b/src/main.cpp index 52a19b9..6f54820 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,6 +43,24 @@ odhtdb::DatabaseNode createDatabaseNodeFromJoinKey(const string &joinKey) return result; } +void channelAddStoredMessages(Channel *channel, const odhtdb::DatabaseStorageObjectList *nodeStorage) +{ + for(auto nodeStorageAddedObject : nodeStorage->objects) + { + if(nodeStorageAddedObject->decryptedObject.operation == odhtdb::DatabaseOperation::ADD_DATA) + { + User *user = channel->getUserByPublicKey(nodeStorageAddedObject->creatorPublicKey); + if(!user) + { + fprintf(stderr, "Missing user? %s\n", nodeStorageAddedObject->creatorPublicKey.toString().c_str()); + continue; + } + string msg((const char*)nodeStorageAddedObject->decryptedObject.data.data, nodeStorageAddedObject->decryptedObject.data.size); + channel->addLocalMessage(msg, user); + } + } +} + int main(int argc, char **argv) { /* @@ -77,16 +95,18 @@ int main(int argc, char **argv) Cache cache; - Channel channel("latenightshiendjs"); - ChannelSidePanel::addChannel(&channel); - UsersSidePanel::addUser(channel.getLocalUser()); + Channel offlineChannel("Offline"); + ChannelSidePanel::addChannel(&offlineChannel); + UsersSidePanel::setCurrentChannel(&offlineChannel); + + vector channels; odhtdb::Signature::KeyPair *currentUserKeyPair = nullptr; vector localNodeUsers; string currentUserName; string currentUserPassword; - Command::add("login", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &localNodeUsers, &database](const vector &args) + Command::add("login", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &localNodeUsers, &database, &channels](const vector &args) { if(args.size() != 2) { @@ -99,10 +119,39 @@ int main(int argc, char **argv) odhtdb::Signature::KeyPair keyPair = database.getStorage().decryptLocalEncryptedUser(args[0], args[1]); localNodeUsers = database.getStorage().getLocalNodeUsers(keyPair); + ChannelSidePanel::removeAllChannels(); + for(Channel *channel : channels) + { + delete channel; + } + channels.clear(); + for(auto localNodeUser : localNodeUsers) { - //const odhtdb::DatabaseStorageObjectList *nodeStorage = database.getStorage().getStorage(localNodeUser.nodeHash); - //Channel *channel = new Channel() + auto nodeStorage = database.getStorage().getStorage(localNodeUser.nodeHash); + if(!nodeStorage) continue; + + auto nodeDecryptionKeyResult = database.getStorage().getNodeDecryptionKey(localNodeUser.nodeHash); + if(!nodeDecryptionKeyResult.first) continue; + + User *newLocalUser = new OnlineUser(localNodeUser.localUser); + odhtdb::DatabaseNode databaseNode(nodeDecryptionKeyResult.second, make_shared(localNodeUser.nodeHash)); + Channel *channel = new Channel(nodeStorage->nodeName, databaseNode, newLocalUser, &database); + + auto nodeUserMapByPublicKey = database.getStorage().getNodeUsers(localNodeUser.nodeHash); + for(auto nodeUserIt : *nodeUserMapByPublicKey) + { + if(nodeUserIt.second != localNodeUser.localUser) + { + User *newRemoteUser = new OnlineUser(nodeUserIt.second); + channel->addUser(newRemoteUser); + } + } + + ChannelSidePanel::addChannel(channel); + channels.push_back(channel); + UsersSidePanel::setCurrentChannel(channel); + channelAddStoredMessages(channel, nodeStorage); } printf("Successfully logged into user %s\n", args[0].c_str()); @@ -119,7 +168,7 @@ int main(int argc, char **argv) } }); - Command::add("register", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &database](const vector &args) + Command::add("register", [¤tUserKeyPair, ¤tUserName, ¤tUserPassword, &localNodeUsers, &database](const vector &args) { if(args.size() != 2) { @@ -127,6 +176,12 @@ int main(int argc, char **argv) return; } + if(currentUserKeyPair) + { + fprintf(stderr, "You can't register a new account when you are logged in, please logout first\n"); + return; + } + odhtdb::Signature::KeyPair keyPair; if(!database.getStorage().storeLocalUser(args[0], keyPair, args[1])) { @@ -140,12 +195,13 @@ int main(int argc, char **argv) if(currentUserKeyPair) delete currentUserKeyPair; currentUserKeyPair = new odhtdb::Signature::KeyPair(keyPair); + localNodeUsers.clear(); currentUserName = args[0]; currentUserPassword = args[1]; }); - Command::add("cc", [¤tUserKeyPair, ¤tUserName, &database](const vector &args) + Command::add("cc", [¤tUserKeyPair, ¤tUserName, &database, &channels](const vector &args) { if(args.size() != 1) { @@ -161,9 +217,14 @@ int main(int argc, char **argv) auto createResponse = database.create(currentUserName, *currentUserKeyPair, args[0]); database.commit(); - odhtdb::DatabaseNode databaseNode(createResponse->getNodeEncryptionKey(), createResponse->getRequestHash()); - database.seed(databaseNode); printf("Created database '%s', join key: '%s'\n", args[0].c_str(), createChannelJoinKey(createResponse).c_str()); + + User *newLocalUser = new OnlineUser(createResponse->getNodeAdminUser()); + odhtdb::DatabaseNode databaseNode(createResponse->getNodeEncryptionKey(), createResponse->getRequestHash()); + Channel *channel = new Channel(args[0], databaseNode, newLocalUser, &database); + ChannelSidePanel::addChannel(channel); + channels.push_back(channel); + UsersSidePanel::setCurrentChannel(channel); }); Command::add("jc", [¤tUserKeyPair, &database](const vector &args) @@ -210,11 +271,11 @@ int main(int argc, char **argv) sf::View view(viewRect); window.setView(view); } - channel.processEvent(event); + UsersSidePanel::getCurrentChannel()->processEvent(event); } window.clear(sf::Color(40, 40, 40)); - channel.draw(window, cache); + UsersSidePanel::getCurrentChannel()->draw(window, cache); //video.draw(window); window.display(); } -- cgit v1.2.3