Skip to content

Commit

Permalink
feat: polls
Browse files Browse the repository at this point in the history
  • Loading branch information
TheTipo01 committed Oct 8, 2022
1 parent 828d60c commit 7c4096c
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 11 deletions.
168 changes: 168 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,72 @@ var (
},
},
},
{
Name: "poll",
Description: "Creates a poll",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "question",
Description: "The question to ask",
Required: true,
},
{
Type: discordgo.ApplicationCommandOptionString,
Name: "group",
Description: "A group of people to poll",
Required: true,
},
},
},
{
Name: "creategroup",
Description: "Creates a group of people to poll",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "name",
Description: "The name of the group",
Required: true,
},
},
},
{
Name: "deletegroup",
Description: "Deletes a group of people to poll",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionString,
Name: "name",
Description: "The name of the group",
Required: true,
},
},
},
{
Name: "addmember",
Description: "Adds a member to a group",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "member",
Description: "The member to add",
Required: true,
},
},
},
{
Name: "removemember",
Description: "Removes a member to a group",
Options: []*discordgo.ApplicationCommandOption{
{
Type: discordgo.ApplicationCommandOptionUser,
Name: "member",
Description: "The member to remove",
Required: true,
},
},
},
}

// Handler
Expand Down Expand Up @@ -640,5 +706,107 @@ var (

sendEmbedInteraction(s, embed.MessageEmbed, i.Interaction)
},
"poll": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
var n int
question := i.ApplicationCommandData().Options[0].StringValue()
group := i.ApplicationCommandData().Options[1].StringValue()

// If the group doesn't exist, just quit
_ = db.QueryRow("SELECT COUNT(*) FROM pollsGroup WHERE serverID=? AND name=?", i.GuildID, group).Scan(&n)
if n == 0 {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "Group not found!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
return
}

// Create the poll message
msg, _ := s.ChannelMessageSendEmbed(i.ChannelID, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", question).MessageEmbed)

// Adds the message to the db
_, _ = db.Exec("INSERT INTO pollState (messageID, question, groupName, guildID) VALUES (?, ?, ?, ?)", msg.ID, question, group, i.GuildID)

// And the map
server[i.GuildID].polls[msg.ID] = true

// Add the reactions
_ = s.MessageReactionAdd(i.GuildID, msg.ID, "👍")
_ = s.MessageReactionAdd(i.GuildID, msg.ID, "👎")
},

"creategroup": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
var n int
_ = db.QueryRow("SELECT COUNT(*) FROM pollsGroup WHERE serverID=? AND name=?", i.GuildID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&n)
if n == 0 {
_, _ = db.Exec("INSERT INTO pollsGroup (serverID, name, createdBy) VALUES (?, ?, ?)", i.GuildID, i.ApplicationCommandData().Options[0].StringValue(), i.Member.User.ID)
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "Group created!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
} else {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "Group already exists!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
}
},

"deletegroup": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
var userID string
_ = db.QueryRow("SELECT createdBy FROM pollsGroup WHERE serverID=? AND name=?", i.GuildID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&userID)

if userID == "" {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "Group not found!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
}

if userID == i.Member.User.ID {
_, _ = db.Exec("DELETE FROM pollsGroup WHERE serverID=? AND name=?", i.GuildID, i.ApplicationCommandData().Options[0].StringValue())
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "Group deleted!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
} else {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "You are not the owner of this group!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
}
},

// Adds a member to a group. Only the creator of the group can add people
"addmember": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
var createdBy, userIDs string
_ = db.QueryRow("SELECT createdBy, userIDs FROM pollsGroup WHERE serverID=? AND name=?", i.GuildID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&createdBy, &userIDs)

if createdBy == "" {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "Group not found!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
}

if createdBy == i.Member.User.ID {
// Gets the old members, and adds the new one
userIDs += "," + i.ApplicationCommandData().Options[0].UserValue(nil).ID

_, _ = db.Exec("UPDATE pollsGroup SET userIDs=? WHERE serverID=? AND name=?", userIDs, i.GuildID, i.ApplicationCommandData().Options[0].StringValue())

} else {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "You are not the owner of this group!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
}
},

// Removes a member from a group. Only the creator of the group can remove people
"removemember": func(s *discordgo.Session, i *discordgo.InteractionCreate) {
var createdBy, userIDs string
_ = db.QueryRow("SELECT createdBy, userIDs FROM pollsGroup WHERE serverID=? AND name=?", i.GuildID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&createdBy, &userIDs)

if createdBy == "" {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "Group not found!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
}

if createdBy == i.Member.User.ID {
// Gets the old members, and adds the new one
userIDs = strings.Replace(userIDs, ","+i.ApplicationCommandData().Options[0].UserValue(nil).ID, "", -1)

_, _ = db.Exec("UPDATE pollsGroup SET userIDs=? WHERE serverID=? AND name=?", userIDs, i.GuildID, i.ApplicationCommandData().Options[0].StringValue())

} else {
sendEmbedInteraction(s, NewEmbed().SetTitle(s.State.User.Username).AddField("Poll", "You are not the owner of this group!").
SetColor(0x7289DA).MessageEmbed, i.Interaction)
}
},
}
)
13 changes: 13 additions & 0 deletions database.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,16 @@ func sendQuoteToServer(s *discordgo.Session, guildID, channelID, channelToID str
return
}
}

// Returns the nickname of a person given its ID
func getNickname(id string) string {
var nickname string

err := db.QueryRow("SELECT nickname FROM users WHERE id=?", id).Scan(&nickname)
if err != nil {
lit.Error("Can't get nickname, %s", err)
return ""
}

return nickname
}
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/psykhi/wordclouds v0.0.0-20220728072901-2d77dabdd4fd
golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7 // indirect
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b // indirect
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7 // indirect
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect
golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,21 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7 h1:WJywXQVIb56P2kAvXeMGTIgQ1ZHQxR60+F9dLsodECc=
golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0=
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7 h1:ZrnxWX62AgTKOSagEqxvb3ffipvEDX2pl7E1TdqLqIc=
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 h1:AzgQNqF+FKwyQ5LbVrVqOcuuFB67N47F9+htZYH0wFM=
golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down
58 changes: 58 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"database/sql"
"fmt"
"github.com/bwmarrin/discordgo"
"github.com/bwmarrin/lit"
_ "github.com/go-sql-driver/mysql"
Expand Down Expand Up @@ -83,6 +84,8 @@ func main() {
dg.AddHandler(messageUpdate)
dg.AddHandler(guildCreate)
dg.AddHandler(ready)
dg.AddHandler(reactionAdd)
dg.AddHandler(reactionRemove)

// Add commands handler
dg.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) {
Expand Down Expand Up @@ -245,3 +248,58 @@ func ready(s *discordgo.Session, _ *discordgo.Ready) {
}
}
}

func reactionAdd(s *discordgo.Session, r *discordgo.MessageReactionAdd) {
if r.UserID == s.State.User.ID {
return
}

reactionUpdate(s, r.MessageReaction, false)
}

func reactionRemove(s *discordgo.Session, r *discordgo.MessageReactionRemove) {
if r.UserID == s.State.User.ID {
return
}

reactionUpdate(s, r.MessageReaction, true)
}

func reactionUpdate(s *discordgo.Session, r *discordgo.MessageReaction, removed bool) {
// Checks if the message is a poll
if _, ok := server[r.GuildID].polls[r.MessageID]; ok && (r.Emoji.Name == "👍" || r.Emoji.Name == "👎") {
var tmp, question, userAnswered string
// Checks if the user is in the group for that poll
_ = db.QueryRow("SELECT userIDs, question, userAnswered FROM pollState, pollsGroup WHERE messageID = ? AND serverID = ? AND pollsGroup.name = pollState.groupName", r.MessageID, r.GuildID).Scan(&tmp, &question, &userAnswered)

if tmp != "" {
// Group found
userIDs := strings.Split(tmp, ",")

// Checks if the user is in the group
for _, id := range userIDs {
if id == r.UserID {
// User found, we modify the message

// Removed or adds the user accordingly
var userAnsweredUpdated []string
if removed {
userAnsweredUpdated = removeString(strings.Split(userAnswered, ","), r.UserID)
} else {
userAnsweredUpdated = append(strings.Split(userAnswered, ","), r.UserID)
}

answerNumber := len(userAnsweredUpdated)
message := fmt.Sprintf("%s\nNumber of people who answered: %d\nPeople who still need to answer: %s\n", question, answerNumber, formatUsers(userIDs, userAnsweredUpdated))
message += fmt.Sprintf("\nPercentage of people who answered yes: %.2f%%", float64(answerNumber)/float64(len(userIDs))*100)
// We update the message
_, _ = s.ChannelMessageEdit(r.ChannelID, r.MessageID, message)

// And the database
_, _ = db.Exec("UPDATE pollState SET userAnswered = ? WHERE messageID = ?", strings.Join(userAnsweredUpdated, ","), r.MessageID)
break
}
}
}
}
}
14 changes: 12 additions & 2 deletions markov.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ func saveAllModels() {
// loadModel loads the model from the db
func loadModel() {
var (
data []byte
guildID string
data []byte
guildID, messageID string
)

rows, _ := db.Query("SELECT model, id FROM servers")
Expand All @@ -91,5 +91,15 @@ func loadModel() {
} else {
_ = json.Unmarshal(data, &server[guildID].model)
}

server[guildID].polls = make(map[string]bool)

// Also load every poll
polls, _ := db.Query("SELECT messageID FROM pollState WHERE guildID = ?", guildID)
for polls.Next() {
_ = polls.Scan(&messageID)

server[guildID].polls[messageID] = true
}
}
}
36 changes: 36 additions & 0 deletions stringutils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

// Returns a string with the name of people who still need to answer, excluding people from the second slice
func formatUsers(groupIDs []string, answeredIDs []string) string {
var s string
for _, d := range groupIDs {
if !contains(answeredIDs, d) {
s += getNickname(d) + ", "
}
}

// Deletes the last comma
return s[:len(s)-2]
}

// Returns true if the slice contains the element d
func contains(slice []string, d string) bool {
for _, u := range slice {
if u == d {
return true
}
}

return false
}

// Returns the original slice minus the element str
func removeString(slice []string, str string) []string {
for i, v := range slice {
if v == str {
return append(slice[:i], slice[i+1:]...)
}
}

return slice
}
1 change: 1 addition & 0 deletions structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "github.com/mb-14/gomarkov"
type Server struct {
numberOfMessages int
model *gomarkov.Chain
polls map[string]bool
}

type kv struct {
Expand Down

0 comments on commit 7c4096c

Please sign in to comment.