mirror of
https://github.com/cjdenio/jia.git
synced 2024-11-21 15:13:40 +00:00
Events system
This commit is contained in:
parent
ad7207c15f
commit
4dec84e9a9
7 changed files with 147 additions and 1 deletions
|
@ -16,6 +16,6 @@ func main() {
|
||||||
config := jia.NewConfig()
|
config := jia.NewConfig()
|
||||||
|
|
||||||
// Start receiving messages
|
// Start receiving messages
|
||||||
fmt.Println(fmt.Sprintf("Listening on port %d", config.Port))
|
fmt.Printf("Listening on port %d\n", config.Port)
|
||||||
jia.StartServer(config)
|
jia.StartServer(config)
|
||||||
}
|
}
|
||||||
|
|
6
events.yaml
Normal file
6
events.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
- name: Test Event
|
||||||
|
start: 8:00 May 2, 2021 EDT
|
||||||
|
end: 7:59 May 3, 2021 EDT
|
||||||
|
- name: May Counting
|
||||||
|
start: 8:00 May 3, 2021 EDT
|
||||||
|
end: 20:00 May 31, 2021 EDT
|
1
go.mod
1
go.mod
|
@ -7,4 +7,5 @@ require (
|
||||||
github.com/joho/godotenv v1.3.0
|
github.com/joho/godotenv v1.3.0
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/slack-go/slack v0.6.5
|
github.com/slack-go/slack v0.6.5
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -18,3 +18,6 @@ github.com/slack-go/slack v0.6.4/go.mod h1:sGRjv3w+ERAUMMMbldHObQPBcNSyVB7KLKYfn
|
||||||
github.com/slack-go/slack v0.6.5 h1:IkDKtJ2IROJNoe3d6mW870/NRKvq2fhLB/Q5XmzWk00=
|
github.com/slack-go/slack v0.6.5 h1:IkDKtJ2IROJNoe3d6mW870/NRKvq2fhLB/Q5XmzWk00=
|
||||||
github.com/slack-go/slack v0.6.5/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM=
|
github.com/slack-go/slack v0.6.5/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
|
|
@ -3,23 +3,67 @@ package jia
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
StartTime time.Time
|
||||||
|
EndTime time.Time
|
||||||
|
|
||||||
|
StartString string `yaml:"start"`
|
||||||
|
EndString string `yaml:"end"`
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
BotToken string
|
BotToken string
|
||||||
ChannelID string
|
ChannelID string
|
||||||
Port int
|
Port int
|
||||||
RedisURL string
|
RedisURL string
|
||||||
VerificationToken string
|
VerificationToken string
|
||||||
|
|
||||||
|
Events []Event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) GetRunningEvents() []Event {
|
||||||
|
var running_events []Event
|
||||||
|
|
||||||
|
for _, event := range c.Events {
|
||||||
|
if time.Since(event.StartTime) > 0 && time.Until(event.EndTime) > 0 {
|
||||||
|
running_events = append(running_events, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return running_events
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
|
events_file, err := os.ReadFile("events.yaml")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var events []Event
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(events_file, &events)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, event := range events {
|
||||||
|
events[i].StartTime, _ = time.Parse("15:04 Jan 2, 2006 MST", event.StartString)
|
||||||
|
events[i].EndTime, _ = time.Parse("15:04 Jan 2, 2006 MST", event.EndString)
|
||||||
|
}
|
||||||
|
|
||||||
return &Config{
|
return &Config{
|
||||||
BotToken: getEnv("SLACK_BOT_TOKEN", ""),
|
BotToken: getEnv("SLACK_BOT_TOKEN", ""),
|
||||||
ChannelID: getEnv("SLACK_CHANNEL_ID", ""),
|
ChannelID: getEnv("SLACK_CHANNEL_ID", ""),
|
||||||
Port: getEnvAsInt("PORT", 3000),
|
Port: getEnvAsInt("PORT", 3000),
|
||||||
RedisURL: getEnv("REDIS_URL", "redis://localhost:6379/0"),
|
RedisURL: getEnv("REDIS_URL", "redis://localhost:6379/0"),
|
||||||
VerificationToken: getEnv("SLACK_VERIFICATION_TOKEN", ""),
|
VerificationToken: getEnv("SLACK_VERIFICATION_TOKEN", ""),
|
||||||
|
Events: events,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,11 @@ func onMessage(slackClient *slack.Client, event *slackevents.MessageEvent) {
|
||||||
|
|
||||||
// Increment the person's monthly count
|
// Increment the person's monthly count
|
||||||
redisClient.Incr(fmt.Sprintf("leaderboard:%d-%d:%s", year, month, event.User))
|
redisClient.Incr(fmt.Sprintf("leaderboard:%d-%d:%s", year, month, event.User))
|
||||||
|
|
||||||
|
// Increment the person's count for any running events
|
||||||
|
for _, counting_event := range jiaConfig.GetRunningEvents() {
|
||||||
|
redisClient.Incr(fmt.Sprintf("event:%s:%s", counting_event.Name, event.User))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleLeaderboardSlashCommand(w http.ResponseWriter, r *http.Request) {
|
func HandleLeaderboardSlashCommand(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -171,6 +176,76 @@ func HandleLeaderboardSlashCommand(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write(resp)
|
w.Write(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HandleEventsSlashCommand(w http.ResponseWriter, r *http.Request) {
|
||||||
|
events := jiaConfig.GetRunningEvents()
|
||||||
|
|
||||||
|
var blocks []slack.Block
|
||||||
|
|
||||||
|
if len(events) == 0 {
|
||||||
|
blocks = append(blocks, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn", "There aren't any counting events running right now.", false, false), nil, nil))
|
||||||
|
} else if len(events) == 1 {
|
||||||
|
blocks = append(blocks, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn", fmt.Sprintf(":calendar: Counting stats for event *%s*:", events[0].Name), false, false), nil, nil))
|
||||||
|
|
||||||
|
scan := redisClient.Scan(0, fmt.Sprintf("event:%s:*", events[0].Name), 10)
|
||||||
|
scanIterator := scan.Iterator()
|
||||||
|
|
||||||
|
type Entry struct {
|
||||||
|
Number int
|
||||||
|
User string
|
||||||
|
}
|
||||||
|
|
||||||
|
entries := []Entry{}
|
||||||
|
|
||||||
|
for scanIterator.Next() {
|
||||||
|
entry := redisClient.Get(scanIterator.Val())
|
||||||
|
entryInt, err := entry.Int()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, user, ok := parseEventEntry(scanIterator.Val()); ok {
|
||||||
|
entries = append(entries, Entry{
|
||||||
|
Number: entryInt,
|
||||||
|
User: user,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort entries
|
||||||
|
sort.Slice(entries, func(i, j int) bool {
|
||||||
|
return entries[i].Number > entries[j].Number
|
||||||
|
})
|
||||||
|
|
||||||
|
for i, v := range entries {
|
||||||
|
emoji := ""
|
||||||
|
if i == 0 {
|
||||||
|
emoji = ":first_place_medal:"
|
||||||
|
} else if i == 1 {
|
||||||
|
emoji = ":second_place_medal:"
|
||||||
|
} else if i == 2 {
|
||||||
|
emoji = ":third_place_medal:"
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks = append(blocks, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("%s <@%s> has counted *%d* so far", emoji, v.User, v.Number), false, false), nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(entries) > 10 {
|
||||||
|
entries = entries[:10]
|
||||||
|
}
|
||||||
|
blocks = append(blocks, slack.NewContextBlock("", slack.NewTextBlockObject("mrkdwn", fmt.Sprintf("Event will end at *<!date^%d^{time} on {date}|some date>*, your time", events[0].EndTime.Unix()), false, false)))
|
||||||
|
} else {
|
||||||
|
blocks = append(blocks, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn", "Something went wrong fetching the events leaderboard :cry:", false, false), nil, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, _ := json.Marshal(map[string]interface{}{
|
||||||
|
"blocks": blocks,
|
||||||
|
"response_type": "ephemeral",
|
||||||
|
})
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
w.Write(resp)
|
||||||
|
}
|
||||||
|
|
||||||
func parseLeaderboardEntry(key string) (string, bool) {
|
func parseLeaderboardEntry(key string) (string, bool) {
|
||||||
re := regexp.MustCompile(`leaderboard:\d+-\d+:(\w+)`)
|
re := regexp.MustCompile(`leaderboard:\d+-\d+:(\w+)`)
|
||||||
|
|
||||||
|
@ -180,3 +255,19 @@ func parseLeaderboardEntry(key string) (string, bool) {
|
||||||
}
|
}
|
||||||
return match[1], true
|
return match[1], true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseEventEntry(key string) (event_name string, user_id string, ok bool) {
|
||||||
|
re := regexp.MustCompile(`event:(.+):(\w+)`)
|
||||||
|
|
||||||
|
match := re.FindStringSubmatch(key)
|
||||||
|
if match == nil {
|
||||||
|
ok = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = true
|
||||||
|
event_name = match[1]
|
||||||
|
user_id = match[2]
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ func StartServer(config *Config) {
|
||||||
// Start receiving events
|
// Start receiving events
|
||||||
http.HandleFunc("/slack/events", handleSlackEvents)
|
http.HandleFunc("/slack/events", handleSlackEvents)
|
||||||
http.HandleFunc("/slack/leaderboard", HandleLeaderboardSlashCommand)
|
http.HandleFunc("/slack/leaderboard", HandleLeaderboardSlashCommand)
|
||||||
|
http.HandleFunc("/slack/eventsCommand", HandleEventsSlashCommand)
|
||||||
http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", config.Port), nil)
|
http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", config.Port), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue