File indexing completed on 2024-05-05 17:32:28

0001 // SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im>
0002 //
0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 
0005 #pragma once
0006 
0007 #include <QDateTime>
0008 #include <QObject>
0009 #include <QSqlDatabase>
0010 #include <QSqlQuery>
0011 
0012 #include <ThreadedDatabase>
0013 
0014 #include <QCoroTask>
0015 
0016 #include <global.h>
0017 #include <phonenumberlist.h>
0018 
0019 enum MessageState {
0020     Unknown = false,
0021     Sent = true,
0022     Pending,
0023     Failed,
0024     Received,
0025 };
0026 Q_DECLARE_METATYPE(MessageState)
0027 
0028 inline MessageState parseMessageState(const QString &state)
0029 {
0030     if (state == SL("pending")) {
0031         return MessageState::Pending;
0032     } else if (state == SL("sent")) {
0033         return MessageState::Sent;
0034     } else if (state == SL("failed")) {
0035         return MessageState::Failed;
0036     }
0037 
0038     Q_UNREACHABLE();
0039 }
0040 
0041 struct Message {
0042     using ColumnTypes =
0043         std::tuple<QString, QString, QString, qint64, bool, int, bool, QString, QString, QString, QString, int, QString, bool, QString, qint64, int, QString>;
0044 
0045     static Message fromSql(ColumnTypes &&tuple);
0046 
0047     QString id;
0048     PhoneNumberList phoneNumberList;
0049     QString text;
0050     QDateTime datetime;
0051     bool read;
0052     MessageState deliveryStatus;
0053     bool sentByMe;
0054     QString attachments;
0055     QString smil;
0056     QString fromNumber;
0057     QString messageId;
0058     int deliveryReport = 0;
0059     QString readReport;
0060     bool pendingDownload = false;
0061     QString contentLocation;
0062     QDateTime expires;
0063     int size = 0;
0064     QString tapbacks;
0065 };
0066 Q_DECLARE_METATYPE(Message)
0067 
0068 struct Chat {
0069     PhoneNumberList phoneNumberList;
0070     int unreadMessages = 0;
0071     QString lastMessage;
0072     QDateTime lastDateTime;
0073     bool lastSentByMe = false;
0074     QString lastAttachment;
0075 };
0076 Q_DECLARE_METATYPE(Chat)
0077 
0078 class Database : public QObject
0079 {
0080     Q_OBJECT
0081 
0082 public:
0083     explicit Database(QObject *parent = nullptr);
0084 
0085     // Messages
0086     QCoro::Task<> addMessage(const Message &message);
0087     QFuture<void> deleteMessage(const QString &id);
0088     QFuture<std::vector<Message>> messagesForNumber(const PhoneNumberList &phoneNumberList, const QString &id = QString(), const int limit = 0) const;
0089     QFuture<void> updateMessageDeliveryState(const QString &id, const MessageState state);
0090     QFuture<void> updateMessageSent(const QString &id, const QString &messageId, const QString &contentLocation);
0091     QFuture<void> updateMessageDeliveryReport(const QString &messageId);
0092     QFuture<void> updateMessageReadReport(const QString &messageId, const PhoneNumber &fromNumber);
0093     QFuture<void> markMessageRead(const int id);
0094     QFuture<void> updateMessageTapbacks(const QString &id, const QString tapbacks);
0095     QCoro::Task<std::optional<QString>> lastMessageWithText(const PhoneNumberList &phoneNumberList, const QString &text);
0096     QCoro::Task<std::optional<QString>> lastMessageWithAttachment(const PhoneNumberList &phoneNumberList);
0097 
0098     // Chats
0099     QCoro::Task<QVector<Chat>> chats(const PhoneNumberList &phoneNumberList) const;
0100     QCoro::Task<std::optional<int>> unreadMessagesForNumber(const PhoneNumberList &phoneNumberList) const;
0101     QFuture<void> markChatAsRead(const PhoneNumberList &phoneNumberList);
0102     QFuture<void> deleteChat(const PhoneNumberList &phoneNumberList);
0103     QCoro::Task<> mergeChats(const QString &fromNumbers, const QString toNumbers);
0104 
0105     static QString generateRandomId();
0106 
0107     static void exec(QSqlQuery &query);
0108 
0109     QCoro::Task<> migrate();
0110 
0111 private:
0112     // Ran on the database thread
0113     void migrationV1(const QSqlDatabase &db, uint current);
0114     void migrationV2(const QSqlDatabase &db, uint current);
0115     void migrationV3(const QSqlDatabase &db, uint current);
0116     void migrationV4(const QSqlDatabase &db, uint current);
0117     void migrationV5(const QSqlDatabase &db, uint current);
0118     void migrationV6(const QSqlDatabase &db, uint current);
0119     void migrationV7(const QSqlDatabase &db, uint current);
0120     void migrationV8(const QSqlDatabase &db, uint current);
0121 
0122     std::unique_ptr<ThreadedDatabase> m_database;
0123 };