summaryrefslogtreecommitdiff
path: root/src/notifications/notifications.cpp
blob: 78ba53c1ca57d5c686d4e49132ade2bac5ca1326 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "notifications.hpp"
#include "discord/message.hpp"

Notifications::Notifications() {
}

bool CheckGuildMessage(const Message &message) {
    auto &discord = Abaddon::Get().GetDiscordClient();
    if (!message.GuildID.has_value()) return false;

    const auto guild = discord.GetGuild(*message.GuildID);
    if (!guild.has_value()) return false;

    const auto guild_settings = discord.GetSettingsForGuild(*message.GuildID);

    // if theres no guild settings then just use default message notifications level
    // (there will be no channel settings)
    if (!guild_settings.has_value()) {
        if (guild->DefaultMessageNotifications.has_value()) {
            switch (*guild->DefaultMessageNotifications) {
                case DefaultNotificationLevel::ALL_MESSAGES:
                    return true;
                case DefaultNotificationLevel::ONLY_MENTIONS:
                    return message.DoesMentionEveryoneOrUser(discord.GetUserData().ID);
                default:
                    return false;
            }
        }
        return false;
    } else if (guild_settings->Muted) {
        // if there are guild settings and the guild is muted then dont notify
        return false;
    }

    // if the channel category is muted then dont notify
    const auto channel = discord.GetChannel(message.ChannelID);
    std::optional<UserGuildSettingsChannelOverride> category_settings;
    if (channel.has_value() && channel->ParentID.has_value()) {
        category_settings = guild_settings->GetOverride(*channel->ParentID);
        if (category_settings.has_value() && category_settings->Muted) {
            return false;
        }
    }

    const auto channel_settings = guild_settings->GetOverride(message.ChannelID);

    // 🥴
    NotificationLevel level;
    if (channel_settings.has_value()) {
        if (channel_settings->MessageNotifications == NotificationLevel::USE_UPPER) {
            if (category_settings.has_value()) {
                if (category_settings->MessageNotifications == NotificationLevel::USE_UPPER) {
                    level = guild_settings->MessageNotifications;
                } else {
                    level = category_settings->MessageNotifications;
                }
            } else {
                level = guild_settings->MessageNotifications;
            }
        } else {
            level = channel_settings->MessageNotifications;
        }
    } else {
        if (category_settings.has_value()) {
            if (category_settings->MessageNotifications == NotificationLevel::USE_UPPER) {
                level = guild_settings->MessageNotifications;
            } else {
                level = category_settings->MessageNotifications;
            }
        } else {
            level = guild_settings->MessageNotifications;
        }
    }

    // there are channel settings, so use them
    switch (level) {
        case NotificationLevel::ALL_MESSAGES:
            return true;
        case NotificationLevel::ONLY_MENTIONS:
            return message.DoesMentionEveryoneOrUser(discord.GetUserData().ID);
        case NotificationLevel::NO_MESSAGES:
            return false;
        default:
            return false;
    }
}

void Notifications::CheckMessage(const Message &message) {
    // ignore if our status is do not disturb
    if (IsDND()) return;
    auto &discord = Abaddon::Get().GetDiscordClient();
    // ignore if the channel is muted
    if (discord.IsChannelMuted(message.ChannelID)) return;
    // ignore if focused and message's channel is active
    if (Abaddon::Get().IsMainWindowActive() && Abaddon::Get().GetActiveChannelID() == message.ChannelID) return;
    // ignore if its our own message
    if (message.Author.ID == Abaddon::Get().GetDiscordClient().GetUserData().ID) return;
    // notify messages in DMs
    const auto channel = discord.GetChannel(message.ChannelID);
    if (channel->IsDM()) {
        NotifyMessageDM(message);
    } else if (CheckGuildMessage(message)) {
        NotifyMessageGuild(message);
    }
}

void Notifications::NotifyMessageDM(const Message &message) {
    Glib::ustring default_action = "app.go-to-channel";
    default_action += "::";
    default_action += std::to_string(message.ChannelID);
    const auto title = message.Author.Username;
    const auto body = message.Content;

    Abaddon::Get().GetImageManager().GetCache().GetFileFromURL(message.Author.GetAvatarURL("png", "64"), [=](const std::string &path) {
        m_notifier.Notify(title, body, default_action, path);
    });
}

void Notifications::NotifyMessageGuild(const Message &message) {
    Glib::ustring default_action = "app.go-to-channel";
    default_action += "::";
    default_action += std::to_string(message.ChannelID);
    Glib::ustring title = message.Author.Username;
    if (const auto channel = Abaddon::Get().GetDiscordClient().GetChannel(message.ChannelID); channel.has_value() && channel->Name.has_value()) {
        if (channel->ParentID.has_value()) {
            const auto category = Abaddon::Get().GetDiscordClient().GetChannel(*channel->ParentID);
            if (category.has_value() && category->Name.has_value()) {
                title += " (#" + *channel->Name + ", " + *category->Name + ")";
            } else {
                title += " (#" + *channel->Name + ")";
            }
        } else {
            title += " (#" + *channel->Name + ")";
        }
    }
    const auto body = message.Content;
    Abaddon::Get().GetImageManager().GetCache().GetFileFromURL(message.Author.GetAvatarURL("png", "64"), [=](const std::string &path) {
        m_notifier.Notify(title, body, default_action, path);
    });
}

bool Notifications::IsDND() const {
    auto &discord = Abaddon::Get().GetDiscordClient();
    const auto status = discord.GetUserStatus(discord.GetUserData().ID);
    return status == PresenceStatus::DND;
}