Compare commits

..

1 commit

Author SHA1 Message Date
10e94c8257
Add command 2025-06-23 21:15:01 +12:00
5 changed files with 27 additions and 70 deletions

View file

@ -15,4 +15,3 @@ Discord bot to measure emoji usage
/show-top-emojis /show-top-emojis
# Shows top 5 emojis and their 3 biggest users # Shows top 5 emojis and their 3 biggest users
``` ```

View file

@ -69,7 +69,7 @@ var (
commandHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){ commandHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){
"show-top-emojis": showTopEmojis, "show-top-emojis": showTopEmojis,
"show-top-users": showTopUsers, "show-top-users": showTopUsers,
"purge-recent-emojis": purgeRecentEmojis, "purge-emojis": purgeRecentEmojis,
} }
) )
@ -137,12 +137,7 @@ func showTopEmojis(s *discordgo.Session, i *discordgo.InteractionCreate) {
sort.Ints(subkeys) sort.Ints(subkeys)
users := []string{} users := []string{}
if top[v].EmojiID == top[v].EmojiName { msg += fmt.Sprintf("%s: %d", top[v].EmojiID, top[v].Count)
// Handle bad data with stock emojis
msg += fmt.Sprintf(":%s: %d", top[v].EmojiName, top[v].Count)
} else {
msg += fmt.Sprintf("<:%s:%s> %d", top[v].EmojiName, top[v].EmojiID, top[v].Count)
}
for _, sv := range subkeys { for _, sv := range subkeys {
users = append(users, fmt.Sprintf("<@%s>: %d", topUsers[sv].EmojiID, topUsers[sv].Count)) users = append(users, fmt.Sprintf("<@%s>: %d", topUsers[sv].EmojiID, topUsers[sv].Count))
} }
@ -202,12 +197,7 @@ func showTopUsers(s *discordgo.Session, i *discordgo.InteractionCreate) {
users := []string{} users := []string{}
msg += fmt.Sprintf("<@%s>: %d", top[v].EmojiID, top[v].Count) msg += fmt.Sprintf("<@%s>: %d", top[v].EmojiID, top[v].Count)
for _, sv := range subkeys { for _, sv := range subkeys {
if topUsers[sv].EmojiID == topUsers[sv].EmojiName { users = append(users, fmt.Sprintf("%s: %d", topUsers[sv].EmojiID, topUsers[sv].Count))
// Handle bad data with stock emojis
users = append(users, fmt.Sprintf(":%s: %d", topUsers[sv].EmojiName, topUsers[sv].Count))
} else {
users = append(users, fmt.Sprintf("<:%s:%s> %d", topUsers[sv].EmojiName, topUsers[sv].EmojiID, topUsers[sv].Count))
}
} }
msg += " (" + strings.Join(users, ", ") + ")\n" msg += " (" + strings.Join(users, ", ") + ")\n"
} }
@ -245,24 +235,9 @@ func purgeRecentEmojis(s *discordgo.Session, i *discordgo.InteractionCreate) {
return return
} }
hours := int64(24) emojis, err := b.Db.GetRecentEmojisForUser(i.GuildID, user.ID, 1)
if opt, ok := optionMap["hours"]; ok {
hours = opt.IntValue()
} else {
slog.Error("Invalid hours option provided")
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: "No hours specified",
AllowedMentions: &discordgo.MessageAllowedMentions{},
},
})
return
}
emojis, err := b.Db.GetRecentEmojisForUser(i.GuildID, user.ID, hours)
if err != nil { if err != nil {
slog.Error("Error getting recent emojis for user", "err", err) slog.Error("Error getting top users", "err", err)
return return
} }

View file

@ -88,7 +88,7 @@ func (bot *Bot) HandleAddReaction(discord *discordgo.Session, reaction *discordg
return return
} }
err := bot.Db.LogEmojiUsage(reaction.GuildID, reaction.ChannelID, reaction.MessageID, reaction.UserID, reaction.Emoji.ID, reaction.Emoji.Name) err := bot.Db.LogEmojiUsage(reaction.GuildID, reaction.ChannelID, reaction.MessageID, reaction.UserID, reaction.Emoji.Name)
if err != nil { if err != nil {
slog.Error("Failed to log emoji usage", "err", err) slog.Error("Failed to log emoji usage", "err", err)
} }
@ -101,7 +101,7 @@ func (bot *Bot) HandleRemoveReaction(discord *discordgo.Session, reaction *disco
return return
} }
err := bot.Db.DeleteEmojiUsage(reaction.GuildID, reaction.ChannelID, reaction.MessageID, reaction.UserID, reaction.Emoji.ID) err := bot.Db.DeleteEmojiUsage(reaction.GuildID, reaction.ChannelID, reaction.MessageID, reaction.UserID, reaction.Emoji.Name)
if err != nil { if err != nil {
slog.Error("Failed to delete single emoji usage", "err", err) slog.Error("Failed to delete single emoji usage", "err", err)
} }

View file

@ -44,7 +44,6 @@ func (db *Database) runMigrations() (*Database, error) {
"`message_id` TEXT, " + "`message_id` TEXT, " +
"`user_id` TEXT, " + "`user_id` TEXT, " +
"`emoji_id` TEXT, " + "`emoji_id` TEXT, " +
"`emoji_name` TEXT, " +
"`timestamp` DATETIME" + "`timestamp` DATETIME" +
")") ")")
if err != nil { if err != nil {
@ -61,21 +60,9 @@ func (db *Database) runMigrations() (*Database, error) {
return db, err return db, err
} }
// emojitest := map[string]string{ _, err = db.db.Exec("CREATE INDEX IF NOT EXISTS `idx_emoji_usage_emoji_id,guild_id` ON `emoji_usage` (`guild_id`, `emoji_id`)")
// "pepe_analyze": "579431592624390147",
// "kekw": "1317987954102112347",
// "pepe_kek": "1300985103182336010",
// "KEKW": "649918246119669770",
// }
// for name, id := range emojitest { return db, err
// _, err = db.db.Exec("UPDATE `emoji_usage` SET `emoji_id` = '" + id + "' WHERE `emoji_name` = '" + name + "'")
// if err != nil {
// return db, err
// }
// }
return db, nil
} }
// CloseDbConn - Closes DB connection // CloseDbConn - Closes DB connection

View file

@ -1,10 +1,7 @@
package db package db
import "fmt"
type EmojiMap struct { type EmojiMap struct {
EmojiID string EmojiID string
EmojiName string
Count int64 Count int64
} }
@ -18,10 +15,10 @@ type EmojiUsage struct {
} }
// LogEmojiUsage - Log usage // LogEmojiUsage - Log usage
func (db *Database) LogEmojiUsage(guildID, channelID, messageID, userID, emojiID, emojiName string) error { func (db *Database) LogEmojiUsage(guildID, channelID, messageID, userID, emojiID string) error {
_, err := db.db.Exec( _, err := db.db.Exec(
"INSERT INTO `emoji_usage` (`guild_id`, `channel_id`, `message_id`, `user_id`, `emoji_id`, `emoji_name`, `timestamp`) VALUES (?,?,?,?,?,?, datetime())", "INSERT INTO `emoji_usage` (`guild_id`, `channel_id`, `message_id`, `user_id`, `emoji_id`, `timestamp`) VALUES (?,?,?,?,?, datetime())",
guildID, channelID, messageID, userID, emojiID, emojiName, guildID, channelID, messageID, userID, emojiID,
) )
return err return err
@ -103,7 +100,7 @@ func (db *Database) GetTopUsersForGuildEmoji(guildID string, emojiID string, num
func (db *Database) GetTopEmojisForGuild(guildID string, num int64) (map[int]EmojiMap, error) { func (db *Database) GetTopEmojisForGuild(guildID string, num int64) (map[int]EmojiMap, error) {
data := make(map[int]EmojiMap) data := make(map[int]EmojiMap)
row, err := db.db.Query( row, err := db.db.Query(
"SELECT emoji_name, emoji_id, count(*) FROM `emoji_usage` WHERE `guild_id` = ? GROUP BY emoji_id ORDER BY count(*) DESC LIMIT ?", "SELECT emoji_id, count(*) FROM `emoji_usage` WHERE `guild_id` = ? GROUP BY emoji_id ORDER BY count(*) DESC LIMIT ?",
guildID, guildID,
num, num,
) )
@ -115,11 +112,10 @@ func (db *Database) GetTopEmojisForGuild(guildID string, num int64) (map[int]Emo
defer row.Close() defer row.Close()
i := 0 i := 0
for row.Next() { for row.Next() {
var emojiName string var emoji string
var emojiID string
var count int64 var count int64
row.Scan(&emojiName, &emojiID, &count) row.Scan(&emoji, &count)
data[i] = EmojiMap{EmojiID: emojiID, EmojiName: emojiName, Count: count} data[i] = EmojiMap{EmojiID: emoji, Count: count}
i++ i++
} }
@ -130,7 +126,7 @@ func (db *Database) GetTopEmojisForGuild(guildID string, num int64) (map[int]Emo
func (db *Database) GetTopEmojisForGuildUser(guildID string, userID string, num int) (map[int]EmojiMap, error) { func (db *Database) GetTopEmojisForGuildUser(guildID string, userID string, num int) (map[int]EmojiMap, error) {
data := make(map[int]EmojiMap) data := make(map[int]EmojiMap)
row, err := db.db.Query( row, err := db.db.Query(
"SELECT emoji_name, emoji_id, count(*) FROM `emoji_usage` WHERE `guild_id` = ? AND `user_id` = ? GROUP BY emoji_name ORDER BY count(*) DESC LIMIT ?", "SELECT emoji_id, count(*) FROM `emoji_usage` WHERE `guild_id` = ? AND `user_id` = ? GROUP BY emoji_id ORDER BY count(*) DESC LIMIT ?",
guildID, guildID,
userID, userID,
num, num,
@ -143,11 +139,10 @@ func (db *Database) GetTopEmojisForGuildUser(guildID string, userID string, num
defer row.Close() defer row.Close()
i := 0 i := 0
for row.Next() { for row.Next() {
var emojiName string var emoji string
var emojiID string
var count int64 var count int64
row.Scan(&emojiName, &emojiID, &count) row.Scan(&emoji, &count)
data[i] = EmojiMap{EmojiID: emojiID, EmojiName: emojiName, Count: count} data[i] = EmojiMap{EmojiID: emoji, Count: count}
i++ i++
} }
@ -158,11 +153,12 @@ func (db *Database) GetTopEmojisForGuildUser(guildID string, userID string, num
func (db *Database) GetRecentEmojisForUser(guildID string, userID string, hours int64) ([]EmojiUsage, error) { func (db *Database) GetRecentEmojisForUser(guildID string, userID string, hours int64) ([]EmojiUsage, error) {
var data []EmojiUsage var data []EmojiUsage
row, err := db.db.Query( row, err := db.db.Query(
"SELECT guild_id, channel_id, message_id, user_id, emoji_id, timestamp "+ "SELECT emoji_id, channel_id, message_id, user_id, emoji_id, timestamp "+
"FROM `emoji_usage` WHERE `guild_id` = ? AND `user_id` = ? AND timestamp >= datetime('now', '-"+fmt.Sprintf("%d", hours)+" hours') "+ "FROM `emoji_usage` WHERE `guild_id` = ? AND `user_id` = ? AND timestamp >= NOW() - INTERVAL ? HOUR "+
"ORDER BY timestamp DESC", "ORDER BY timestamp DESC",
guildID, guildID,
userID, userID,
hours,
) )
if err != nil { if err != nil {