1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Use Tox IDs internally as message author ID

Instead of names. Fixes #603

Groupchats still use names internally, since there's currently no way to get a chat member's public key throught the toxcore API
This commit is contained in:
Tux3 / Mlkj / !Lev.uXFMLA 2014-11-02 18:36:27 +01:00
parent 5bdbc3d6d0
commit 98f15af670
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
10 changed files with 226 additions and 58 deletions

View File

@ -991,7 +991,7 @@ void Core::removeGroup(int groupId)
tox_del_groupchat(tox, groupId); tox_del_groupchat(tox, groupId);
} }
QString Core::getUsername() QString Core::getUsername() const
{ {
QString sname; QString sname;
int size = tox_get_self_name_size(tox); int size = tox_get_self_name_size(tox);
@ -1034,21 +1034,21 @@ void Core::setAvatar(uint8_t format, const QByteArray& data)
tox_send_avatar_info(tox, i); tox_send_avatar_info(tox, i);
} }
ToxID Core::getSelfId() ToxID Core::getSelfId() const
{ {
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE]; uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox, friendAddress); tox_get_address(tox, friendAddress);
return ToxID::fromString(CFriendAddress::toString(friendAddress)); return ToxID::fromString(CFriendAddress::toString(friendAddress));
} }
QString Core::getIDString() QString Core::getIDString() const
{ {
return getSelfId().toString().left(12); return getSelfId().toString().left(12);
// 12 is the smallest multiple of four such that // 12 is the smallest multiple of four such that
// 16^n > 10^10 (which is roughly the planet's population) // 16^n > 10^10 (which is roughly the planet's population)
} }
QString Core::getStatusMessage() QString Core::getStatusMessage() const
{ {
QString sname; QString sname;
int size = tox_get_self_status_message_size(tox); int size = tox_get_self_status_message_size(tox);
@ -1715,3 +1715,27 @@ bool Core::isPasswordSet(PasswordType passtype)
return false; return false;
} }
QString Core::getPeerName(const ToxID& id) const
{
uint8_t cname[TOX_MAX_NAME_LENGTH];
QString name;
CUserId cid(id.toString());
int friendId = tox_get_friend_number(tox, (uint8_t*)cid.data());
if (friendId < 0)
{
qWarning() << "Core::getPeerName: No such peer "+id.toString();
return name;
}
int nameSize = tox_get_name(tox, friendId, cname);
if (nameSize < 0)
{
qWarning() << "Core::getPeerName: Can't get name of friend "+QString().setNum(friendId)+" ("+id.toString()+")";
return name;
}
name = name.fromLocal8Bit((char*)cname, nameSize);
return name;
}

View File

@ -46,6 +46,8 @@ public:
static const QString CONFIG_FILE_NAME; static const QString CONFIG_FILE_NAME;
static QString sanitize(QString name); static QString sanitize(QString name);
QString getPeerName(const ToxID& id) const;
int getGroupNumberPeers(int groupId) const; ///< Return the number of peers in the group chat on success, or -1 on failure int getGroupNumberPeers(int groupId) const; ///< Return the number of peers in the group chat on success, or -1 on failure
QString getGroupPeerName(int groupId, int peerId) const; ///< Get the name of a peer of a group QString getGroupPeerName(int groupId, int peerId) const; ///< Get the name of a peer of a group
QList<QString> getGroupPeerNames(int groupId) const; ///< Get the names of the peers of a group QList<QString> getGroupPeerNames(int groupId) const; ///< Get the names of the peers of a group
@ -57,11 +59,11 @@ public:
void saveConfiguration(); void saveConfiguration();
void saveConfiguration(const QString& path); void saveConfiguration(const QString& path);
QString getIDString(); ///< Get the 12 first characters of our Tox ID QString getIDString() const; ///< Get the 12 first characters of our Tox ID
QString getUsername(); ///< Returns our username, or an empty string on failure QString getUsername() const; ///< Returns our username, or an empty string on failure
QString getStatusMessage(); ///< Returns our status message, or an empty string on failure QString getStatusMessage() const; ///< Returns our status message, or an empty string on failure
ToxID getSelfId(); ///< Returns our Tox ID ToxID getSelfId() const; ///< Returns our Tox ID
VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source VideoSource* getVideoSourceFromCall(int callNumber); ///< Get a call's video source

View File

@ -1,4 +1,5 @@
#include "corestructs.h" #include "src/corestructs.h"
#include "src/core.h"
#include <QFile> #include <QFile>
ToxFile::ToxFile(int FileNum, int FriendId, QByteArray FileName, QString FilePath, FileDirection Direction) ToxFile::ToxFile(int FileNum, int FriendId, QByteArray FileName, QString FilePath, FileDirection Direction)
@ -17,3 +18,33 @@ bool ToxFile::open(bool write)
{ {
return write ? file->open(QIODevice::ReadWrite) : file->open(QIODevice::ReadOnly); return write ? file->open(QIODevice::ReadWrite) : file->open(QIODevice::ReadOnly);
} }
QString ToxID::toString() const
{
return publicKey + noSpam + checkSum;
}
ToxID ToxID::fromString(QString id)
{
ToxID toxID;
toxID.publicKey = id.left(TOX_ID_PUBLIC_KEY_LENGTH);
toxID.noSpam = id.mid(TOX_ID_PUBLIC_KEY_LENGTH, TOX_ID_NO_SPAM_LENGTH);
toxID.checkSum = id.right(TOX_ID_CHECKSUM_LENGTH);
return toxID;
}
bool ToxID::operator==(const ToxID& other) const
{
return publicKey == other.publicKey;
}
bool ToxID::operator!=(const ToxID& other) const
{
return publicKey != other.publicKey;
}
bool ToxID::isMine() const
{
return *this == Core::getInstance()->getSelfId();
}

View File

@ -20,20 +20,12 @@ struct ToxID
QString noSpam; QString noSpam;
QString checkSum; QString checkSum;
QString toString() const QString toString() const;
{ ToxID static fromString(QString id);
return publicKey + noSpam + checkSum;
}
ToxID static fromString(QString id)
{
ToxID toxID;
toxID.publicKey = id.left(TOX_ID_PUBLIC_KEY_LENGTH);
toxID.noSpam = id.mid(TOX_ID_PUBLIC_KEY_LENGTH, TOX_ID_NO_SPAM_LENGTH);
toxID.checkSum = id.right(TOX_ID_CHECKSUM_LENGTH);
return toxID;
}
bool operator==(const ToxID& other) const;
bool operator!=(const ToxID& other) const;
bool isMine() const;
}; };
struct DhtServer struct DhtServer

View File

@ -46,7 +46,12 @@ void Friend::setStatusMessage(QString message)
chatForm->setStatusMessage(message); chatForm->setStatusMessage(message);
} }
QString Friend::getName() QString Friend::getName() const
{ {
return widget->getName(); return widget->getName();
} }
ToxID Friend::getToxID() const
{
return ToxID::fromString(userId);
}

View File

@ -30,7 +30,8 @@ public:
~Friend(); ~Friend();
void setName(QString name); void setName(QString name);
void setStatusMessage(QString message); void setStatusMessage(QString message);
QString getName(); QString getName() const;
ToxID getToxID() const;
public: public:
FriendWidget* widget; FriendWidget* widget;

View File

@ -92,19 +92,19 @@ void ChatForm::onSendTriggered()
QString msg = msgEdit->toPlainText(); QString msg = msgEdit->toPlainText();
if (msg.isEmpty()) if (msg.isEmpty())
return; return;
QString name = Widget::getInstance()->getUsername();
QDateTime timestamp = QDateTime::currentDateTime(); QDateTime timestamp = QDateTime::currentDateTime();
HistoryKeeper::getInstance()->addChatEntry(f->userId, msg, Core::getInstance()->getSelfId().publicKey, timestamp); HistoryKeeper::getInstance()->addChatEntry(f->userId, msg, Core::getInstance()->getSelfId().publicKey, timestamp);
if (msg.startsWith("/me ")) if (msg.startsWith("/me "))
{ {
msg = msg.right(msg.length() - 4); msg = msg.right(msg.length() - 4);
addMessage(name, msg, true, timestamp); addSelfMessage(msg, true, timestamp);
emit sendAction(f->friendId, msg); emit sendAction(f->friendId, msg);
} }
else else
{ {
addMessage(name, msg, false, timestamp); addSelfMessage(msg, false, timestamp);
emit sendMessage(f->friendId, msg); emit sendMessage(f->friendId, msg);
} }
msgEdit->clear(); msgEdit->clear();
@ -150,10 +150,13 @@ void ChatForm::startFileSend(ToxFile file)
connect(Core::getInstance(), SIGNAL(fileTransferRemotePausedUnpaused(ToxFile,bool)), fileTrans, SLOT(onFileTransferRemotePausedUnpaused(ToxFile,bool))); connect(Core::getInstance(), SIGNAL(fileTransferRemotePausedUnpaused(ToxFile,bool)), fileTrans, SLOT(onFileTransferRemotePausedUnpaused(ToxFile,bool)));
connect(Core::getInstance(), SIGNAL(fileTransferBrokenUnbroken(ToxFile, bool)), fileTrans, SLOT(onFileTransferBrokenUnbroken(ToxFile, bool))); connect(Core::getInstance(), SIGNAL(fileTransferBrokenUnbroken(ToxFile, bool)), fileTrans, SLOT(onFileTransferBrokenUnbroken(ToxFile, bool)));
QString name = Widget::getInstance()->getUsername(); QString name;
if (name == previousName) if (!previousId.isMine())
name = ""; {
previousName = Widget::getInstance()->getUsername(); Core* core = Core::getInstance();
name = core->getUsername();
previousId = core->getSelfId();
}
chatWidget->insertMessage(ChatActionPtr(new FileTransferAction(fileTrans, getElidedName(name), chatWidget->insertMessage(ChatActionPtr(new FileTransferAction(fileTrans, getElidedName(name),
QTime::currentTime().toString("hh:mm"), true))); QTime::currentTime().toString("hh:mm"), true)));
@ -183,10 +186,13 @@ void ChatForm::onFileRecvRequest(ToxFile file)
f->widget->updateStatusLight(); f->widget->updateStatusLight();
} }
QString name = f->getName(); QString name;
if (name == previousName) ToxID friendId = f->getToxID();
name = ""; if (friendId != previousId)
previousName = f->getName(); {
name = f->getName();
previousId = friendId;
}
chatWidget->insertMessage(ChatActionPtr(new FileTransferAction(fileTrans, getElidedName(name), chatWidget->insertMessage(ChatActionPtr(new FileTransferAction(fileTrans, getElidedName(name),
QTime::currentTime().toString("hh:mm"), false))); QTime::currentTime().toString("hh:mm"), false)));
@ -655,20 +661,16 @@ void ChatForm::onLoadHistory()
auto msgs = HistoryKeeper::getInstance()->getChatHistory(HistoryKeeper::ctSingle, f->userId, fromTime, toTime); auto msgs = HistoryKeeper::getInstance()->getChatHistory(HistoryKeeper::ctSingle, f->userId, fromTime, toTime);
QString storedPrevName = previousName; ToxID storedPrevId;
previousName = ""; std::swap(storedPrevId, previousId);
QList<ChatActionPtr> historyMessages; QList<ChatActionPtr> historyMessages;
for (const auto &it : msgs) for (const auto &it : msgs)
{ {
QString name = f->getName(); ChatActionPtr ca = genMessageActionAction(ToxID::fromString(it.sender), it.message, false, it.timestamp.toLocalTime());
if (it.sender == Core::getInstance()->getSelfId().publicKey)
name = Core::getInstance()->getUsername();
ChatActionPtr ca = genMessageActionAction(name, it.message, false, it.timestamp.toLocalTime());
historyMessages.append(ca); historyMessages.append(ca);
} }
previousName = storedPrevName; std::swap(storedPrevId, previousId);
int savedSliderPos = chatWidget->verticalScrollBar()->maximum() - chatWidget->verticalScrollBar()->value(); int savedSliderPos = chatWidget->verticalScrollBar()->maximum() - chatWidget->verticalScrollBar()->value();

View File

@ -30,6 +30,7 @@
#include "src/widget/chatareawidget.h" #include "src/widget/chatareawidget.h"
#include "src/widget/tool/chattextedit.h" #include "src/widget/tool/chattextedit.h"
#include "src/widget/maskablepixmapwidget.h" #include "src/widget/maskablepixmapwidget.h"
#include "src/core.h"
GenericChatForm::GenericChatForm(QWidget *parent) : GenericChatForm::GenericChatForm(QWidget *parent) :
QWidget(parent), QWidget(parent),
@ -191,17 +192,42 @@ void GenericChatForm::onSaveLogClicked()
file.close(); file.close();
} }
void GenericChatForm::addMessage(const QString &author, const QString &message, bool isAction, const QDateTime &datetime) /// THIS FUNCTION IS DEPRECATED
/// The only reason it's still alive is because the groupchat API is a bit limited
void GenericChatForm::addMessage(const QString& author, const QString &message, bool isAction, const QDateTime &datetime)
{ {
ChatActionPtr ca = genMessageActionAction(author, message, isAction, datetime); ChatActionPtr ca = genMessageActionAction(author, message, isAction, datetime);
chatWidget->insertMessage(ca); chatWidget->insertMessage(ca);
} }
void GenericChatForm::addAlertMessage(QString author, QString message, QDateTime datetime) void GenericChatForm::addMessage(const ToxID& author, const QString &message, bool isAction, const QDateTime &datetime)
{
ChatActionPtr ca = genMessageActionAction(author, message, isAction, datetime);
chatWidget->insertMessage(ca);
}
void GenericChatForm::addSelfMessage(const QString &message, bool isAction, const QDateTime &datetime)
{
ChatActionPtr ca = genSelfActionAction(message, isAction, datetime);
chatWidget->insertMessage(ca);
}
/// THIS FUNCTION IS DEPRECATED
/// The only reason it's still alive is because the groupchat API is a bit limited
void GenericChatForm::addAlertMessage(const QString& author, QString message, QDateTime datetime)
{ {
QString date = datetime.toString(Settings::getInstance().getTimestampFormat()); QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
chatWidget->insertMessage(ChatActionPtr(new AlertAction(author, message, date))); chatWidget->insertMessage(ChatActionPtr(new AlertAction(author, message, date)));
previousName = author;
previousId.publicKey = author;
}
void GenericChatForm::addAlertMessage(const ToxID &author, QString message, QDateTime datetime)
{
QString authorStr = Core::getInstance()->getPeerName(author);
QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
chatWidget->insertMessage(ChatActionPtr(new AlertAction(authorStr, message, date)));
previousId = author;
} }
void GenericChatForm::onEmoteButtonClicked() void GenericChatForm::onEmoteButtonClicked()
@ -253,7 +279,7 @@ QString GenericChatForm::getElidedName(const QString& name)
void GenericChatForm::clearChatArea(bool notinform) void GenericChatForm::clearChatArea(bool notinform)
{ {
chatWidget->clearChatArea(); chatWidget->clearChatArea();
previousName = ""; previousId = ToxID();
if (!notinform) if (!notinform)
addSystemInfoMessage(tr("Cleared"), "white", QDateTime::currentDateTime()); addSystemInfoMessage(tr("Cleared"), "white", QDateTime::currentDateTime());
@ -265,6 +291,8 @@ void GenericChatForm::clearChatArea(bool notinform)
} }
} }
/// THIS FUNCTION IS DEPRECATED
/// The only reason it's still alive is because the groupchat API is a bit limited
ChatActionPtr GenericChatForm::genMessageActionAction(const QString &author, QString message, bool isAction, const QDateTime &datetime) ChatActionPtr GenericChatForm::genMessageActionAction(const QString &author, QString message, bool isAction, const QDateTime &datetime)
{ {
if (earliestMessage == nullptr) if (earliestMessage == nullptr)
@ -283,23 +311,99 @@ ChatActionPtr GenericChatForm::genMessageActionAction(const QString &author, QSt
if (isAction) if (isAction)
{ {
previousName = ""; // next msg has a name regardless previousId = ToxID(); // next msg has a name regardless
return ChatActionPtr(new ActionAction (getElidedName(author), message, date, isMe)); return ChatActionPtr(new ActionAction (getElidedName(author), message, date, isMe));
} }
ChatActionPtr res; ChatActionPtr res;
if (previousName == author) if (previousId.publicKey == author)
res = ChatActionPtr(new MessageAction("", message, date, isMe)); res = ChatActionPtr(new MessageAction(QString(), message, date, isMe));
else else
res = ChatActionPtr(new MessageAction(getElidedName(author), message, date, isMe)); res = ChatActionPtr(new MessageAction(getElidedName(author), message, date, isMe));
previousName = author; previousId.publicKey = author;
return res;
}
ChatActionPtr GenericChatForm::genMessageActionAction(const ToxID& author, QString message, bool isAction, const QDateTime &datetime)
{
if (earliestMessage == nullptr)
{
earliestMessage = new QDateTime(datetime);
}
const Core* core = Core::getInstance();
QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
bool isMe = (author == core->getSelfId());
QString authorStr;
if (isMe)
authorStr = core->getUsername();
else
authorStr = core->getPeerName(author);
if (authorStr.isEmpty()) // Fallback if we can't find a username
authorStr = author.toString();
if (!isAction && message.startsWith("/me "))
{ // always render actions regardless of what core thinks
isAction = true;
message = message.right(message.length()-4);
}
if (isAction)
{
previousId = ToxID(); // next msg has a name regardless
return ChatActionPtr(new ActionAction (getElidedName(authorStr), message, date, isMe));
}
ChatActionPtr res;
if (previousId == author)
res = ChatActionPtr(new MessageAction(QString(), message, date, isMe));
else
res = ChatActionPtr(new MessageAction(getElidedName(authorStr), message, date, isMe));
previousId = author;
return res;
}
ChatActionPtr GenericChatForm::genSelfActionAction(QString message, bool isAction, const QDateTime &datetime)
{
if (earliestMessage == nullptr)
{
earliestMessage = new QDateTime(datetime);
}
const Core* core = Core::getInstance();
QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
QString author = core->getUsername();;
if (!isAction && message.startsWith("/me "))
{ // always render actions regardless of what core thinks
isAction = true;
message = message.right(message.length()-4);
}
if (isAction)
{
previousId = ToxID(); // next msg has a name regardless
return ChatActionPtr(new ActionAction (getElidedName(author), message, date, true));
}
ChatActionPtr res;
if (previousId.isMine())
res = ChatActionPtr(new MessageAction(QString(), message, date, true));
else
res = ChatActionPtr(new MessageAction(getElidedName(author), message, date, true));
previousId = Core::getInstance()->getSelfId();
return res; return res;
} }
ChatActionPtr GenericChatForm::genSystemInfoAction(const QString &message, const QString &type, const QDateTime &datetime) ChatActionPtr GenericChatForm::genSystemInfoAction(const QString &message, const QString &type, const QDateTime &datetime)
{ {
previousName = ""; previousId = ToxID();
QString date = datetime.toString(Settings::getInstance().getTimestampFormat()); QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
return ChatActionPtr(new SystemMessageAction(message, type, date)); return ChatActionPtr(new SystemMessageAction(message, type, date));

View File

@ -22,6 +22,7 @@
#include <QDateTime> #include <QDateTime>
#include <QMenu> #include <QMenu>
#include "src/widget/tool/chatactions/chataction.h" #include "src/widget/tool/chatactions/chataction.h"
#include "src/corestructs.h"
// Spacing in px inserted when the author of the last message changes // Spacing in px inserted when the author of the last message changes
#define AUTHOR_CHANGE_SPACING 5 // why the hell is this a thing? surely the different font is enough? #define AUTHOR_CHANGE_SPACING 5 // why the hell is this a thing? surely the different font is enough?
@ -33,6 +34,7 @@ class CroppingLabel;
class ChatTextEdit; class ChatTextEdit;
class ChatAreaWidget; class ChatAreaWidget;
class MaskablePixmapWidget; class MaskablePixmapWidget;
struct ToxID;
namespace Ui { namespace Ui {
class MainWindow; class MainWindow;
@ -46,9 +48,12 @@ public:
virtual void setName(const QString &newName); virtual void setName(const QString &newName);
virtual void show(Ui::MainWindow &ui); virtual void show(Ui::MainWindow &ui);
void addMessage(const QString &author, const QString &message, bool isAction, const QDateTime &datetime); void addMessage(const QString& author, const QString &message, bool isAction, const QDateTime &datetime); ///< Deprecated
void addMessage(const ToxID& author, const QString &message, bool isAction, const QDateTime &datetime);
void addSelfMessage(const QString &message, bool isAction, const QDateTime &datetime);
void addSystemInfoMessage(const QString &message, const QString &type, const QDateTime &datetime); void addSystemInfoMessage(const QString &message, const QString &type, const QDateTime &datetime);
void addAlertMessage(QString author, QString message, QDateTime datetime); void addAlertMessage(const QString& author, QString message, QDateTime datetime); ///< Deprecated
void addAlertMessage(const ToxID& author, QString message, QDateTime datetime);
int getNumberOfMessages(); int getNumberOfMessages();
signals: signals:
@ -67,10 +72,14 @@ protected slots:
protected: protected:
QString getElidedName(const QString& name); QString getElidedName(const QString& name);
ChatActionPtr genMessageActionAction(const QString &author, QString message, bool isAction, const QDateTime &datetime); ChatActionPtr genMessageActionAction(const QString& author, QString message, bool isAction, const QDateTime &datetime); ///< Deprecated
ChatActionPtr genMessageActionAction(const ToxID& author, QString message, bool isAction, const QDateTime &datetime);
ChatActionPtr genSelfActionAction(QString message, bool isAction, const QDateTime &datetime);
ChatActionPtr genSystemInfoAction(const QString &message, const QString &type, const QDateTime &datetime); ChatActionPtr genSystemInfoAction(const QString &message, const QString &type, const QDateTime &datetime);
ToxID previousId;
QMenu menu; QMenu menu;
int curRow;
CroppingLabel *nameLabel; CroppingLabel *nameLabel;
MaskablePixmapWidget *avatar; MaskablePixmapWidget *avatar;
QWidget *headWidget; QWidget *headWidget;
@ -78,9 +87,7 @@ protected:
QVBoxLayout *headTextLayout; QVBoxLayout *headTextLayout;
ChatTextEdit *msgEdit; ChatTextEdit *msgEdit;
QPushButton *sendButton; QPushButton *sendButton;
QString previousName;
ChatAreaWidget *chatWidget; ChatAreaWidget *chatWidget;
int curRow;
QDateTime *earliestMessage; QDateTime *earliestMessage;
}; };

View File

@ -721,7 +721,7 @@ void Widget::onFriendMessageReceived(int friendId, const QString& message, bool
return; return;
QDateTime timestamp = QDateTime::currentDateTime(); QDateTime timestamp = QDateTime::currentDateTime();
f->chatForm->addMessage(f->getName(), message, isAction, timestamp); f->chatForm->addMessage(f->getToxID(), message, isAction, timestamp);
if (isAction) if (isAction)
HistoryKeeper::getInstance()->addChatEntry(f->userId, "/me " + message, f->userId, timestamp); HistoryKeeper::getInstance()->addChatEntry(f->userId, "/me " + message, f->userId, timestamp);