Skip to content

Commit

Permalink
(blissfest) Add ticket info, slight rephrasing. Fix some discord rela…
Browse files Browse the repository at this point in the history
…ted bugs
  • Loading branch information
h3mmy committed Apr 13, 2024
1 parent e7b5541 commit 71d5a3c
Show file tree
Hide file tree
Showing 15 changed files with 367 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .envrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
source .config.test
source .config.dev
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

*.env.*
*.config.(^sample)
.config.dev
config.yaml
bloopyboi_dev
bloopyboii_dev
Expand Down
2 changes: 1 addition & 1 deletion bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (bot *BloopyBoi) Run(ctx context.Context) error {
}

bot.log.Debug(fmt.Sprintf("FeatureMap contains %d entries", len(providers.GetFeatures())))
bot.log.Debug(fmt.Sprintf("Experimental is enabled: %v", providers.IsFeaturedConfigured("experimental")))
bot.log.Debug(fmt.Sprintf("Experimental is enabled: %v", providers.IsFeatureEnabled("experimental")))

errGroup, ctx := errgroup.WithContext(ctx)
errGroup.Go(func() error {
Expand Down
1 change: 1 addition & 0 deletions bot/discord/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func (d *DiscordManager) Start(ctx context.Context) error {
if err != nil {
return fmt.Errorf("While opening a connection: %w", err)
}
// d.discordSvc.GetSession().LogLevel = discordgo.LogDebug

d.log.Info("Registering App Commands")
for _, v := range providers.GetDiscordAppCommands(d.discordCfg.GuildConfigs) {
Expand Down
63 changes: 48 additions & 15 deletions bot/handlers/blissfest.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ type BlissfestCommand struct {
blissSvc *services.BlissfestService
// GuildID for which this command will be active
// For global commands, set to ""
guildId string
roles []int64
guildId string
roles []int64
}

func NewBlissfestCommand(svc *services.BlissfestService) *BlissfestCommand {
Expand All @@ -32,11 +32,12 @@ func NewBlissfestCommand(svc *services.BlissfestService) *BlissfestCommand {
logger: log.NewZapLogger().Named("blissfest_command"),
blissSvc: svc,
guildId: "",
roles: []int64{},
roles: []int64{},
}
}

func (p *BlissfestCommand) WithGuild(guildId string) *BlissfestCommand {
p.logger.Debug("setting guild", zap.String("guildId", guildId))
p.guildId = guildId
return p
}
Expand Down Expand Up @@ -67,6 +68,7 @@ func (p *BlissfestCommand) GetAppCommand() *discordgo.ApplicationCommand {

func (p *BlissfestCommand) GetAppCommandHandler() func(s *discordgo.Session, i *discordgo.InteractionCreate) {
return func(s *discordgo.Session, i *discordgo.InteractionCreate) {
p.logger.Debug("received interaction", zap.String("interactionID", i.ID), zap.String("username", GetDiscordUserFromInteraction(i).Username))
getLineUp := false
// Access options in the order provided by the user.
options := i.ApplicationCommandData().Options
Expand All @@ -79,30 +81,61 @@ func (p *BlissfestCommand) GetAppCommandHandler() func(s *discordgo.Session, i *
bsvc := p.blissSvc
var resData discordgo.InteractionResponseData

if getLineUp {
resData = discordgo.InteractionResponseData{
Embeds: []*discordgo.MessageEmbed{
resEmbeds := []*discordgo.MessageEmbed{}

adultWeekendPriceLevel, err := bsvc.GetAdultWeekendPriceLevel()
var adultWeekendPriceLevelEmbed *discordgo.MessageEmbed
if err != nil {
p.logger.Warn("error getting adult weekend price level. Not including in response", zap.Error(err))
} else {
adultWeekendPriceLevelEmbed = &discordgo.MessageEmbed{
Title: "Adult Weekend (18+) Ticket Info",
Fields: []*discordgo.MessageEmbedField{
{
Author: &discordgo.MessageEmbedAuthor{},
Image: &discordgo.MessageEmbedImage{
URL: bsvc.GetLineupImageURI(),
},
Name: "Active",
Value: fmt.Sprintf("%t", adultWeekendPriceLevel.Active == "1"),
},
{
Name: "Price",
Value: adultWeekendPriceLevel.Price, //fmt.Sprintf("%.2f",adultWeekendPriceLevel.Price),
},
{
Name: "Transaction Limit",
Value: adultWeekendPriceLevel.TransactionLimit, //fmt.Sprintf("%d", adultWeekendPriceLevel.TransactionLimit),
},
},
Title: "Blissfest",
}
resEmbeds = append(resEmbeds, adultWeekendPriceLevelEmbed)
}

if getLineUp {
resEmbeds = append(resEmbeds, &discordgo.MessageEmbed{
Title: fmt.Sprintf("%d Blissfest Lineup", bsvc.GetStartTime().Year()),
Author: &discordgo.MessageEmbedAuthor{},
Image: &discordgo.MessageEmbedImage{
URL: bsvc.GetLineupImageURI(),
},
})
}
if len(resEmbeds) > 0 {
resData = discordgo.InteractionResponseData{
Embeds: resEmbeds,
Title: "Blissfest",
// pending https://github.com/dustin/go-humanize/pull/92
// Content: fmt.Sprintf("%s left", humanize.Time(bsvc.GetTimeUntilStart(nil))),
Content: fmt.Sprintf("blissfest starts in %s", humanize.Time(*bsvc.GetStartTime())),
Content: fmt.Sprintf("blissfest starts %s", humanize.Time(*bsvc.GetStartTime())),
}

} else {
resData = discordgo.InteractionResponseData{
Title: "Blissfest",
Content: fmt.Sprintf("blissfest starts in %s", humanize.Time(*bsvc.GetStartTime())),
// pending https://github.com/dustin/go-humanize/pull/92
// Content: fmt.Sprintf("%s left", humanize.Time(bsvc.GetTimeUntilStart(nil))),
Content: fmt.Sprintf("blissfest start %s", humanize.Time(*bsvc.GetStartTime())),
}
}
p.logger.Debug("finished constructing response", zap.Bool("getLineup", getLineUp))

err := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
err = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &resData,
})
Expand Down
9 changes: 9 additions & 0 deletions bot/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,12 @@ func (myConfig *AppConfig) GetConfiguredFeatureNames() []string {
}
return names
}

// Checks FeatureConfigs for key
func (myConfig *AppConfig) IsFeaturedEnabled(key string) bool {
fCfg, ok := myConfig.FeatureMap[key]
if !ok {
return false
}
return fCfg.Enabled
}
21 changes: 13 additions & 8 deletions bot/providers/app_command_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/h3mmy/bloopyboi/bot/handlers"
"github.com/h3mmy/bloopyboi/bot/internal/config"
"github.com/h3mmy/bloopyboi/bot/internal/models"
pkgmodels "github.com/h3mmy/bloopyboi/internal/models"
"go.uber.org/zap"
)

Expand All @@ -12,18 +13,18 @@ func GetDiscordAppCommands(cfgs []config.DiscordGuildConfig) []models.DiscordApp
handls = append(handls, handlers.NewInspiroCommand(GetInspiroService()))
handls = append(handls, GetGuildAppCommands(cfgs)...)
logger.Debug("got discord commands", zap.Int("count", len(handls)))
return handls
return handls
}

func GetGuildAppCommands(cfgs []config.DiscordGuildConfig) []models.DiscordAppCommand {
handls := make([]models.DiscordAppCommand, 0, 3)
logger.Debug("getting configs for guilds", zap.Int("count", len(cfgs)))
for _, guild := range cfgs {
logger.Debug("getting guild commands", zap.Int("count", len(guild.GuildCommandConfig)))
for _,v := range guild.GuildCommandConfig {
for _, v := range guild.GuildCommandConfig {
logger.Debug("getting guild command", zap.String("name", v.Name), zap.Bool("enabled", v.Enabled))
if v.Enabled {
cmd := GetCommandWithConfig(guild.GuildId, v)
cmd := GetCommandWithConfig(guild.GuildId, v)
if cmd != nil {
handls = append(handls, cmd)
}
Expand All @@ -35,25 +36,29 @@ func GetGuildAppCommands(cfgs []config.DiscordGuildConfig) []models.DiscordAppCo
}

func GetCommandWithConfig(guildId string, cfg config.GuildCommandConfig) models.DiscordAppCommand {
flogger := logger.With(zap.String("guild_app_command", cfg.Name), zap.String("guild_id", guildId))
// get from repository TODO
if cfg.Name == "blissfest" {
logger.Debug("adding blissfest command")
return handlers.NewBlissfestCommand(GetBlissfestService()).WithGuild(guildId).WithRoles(cfg.Roles...)
flogger.Debug("Checking if feature enabled")
if IsFeatureEnabled(pkgmodels.BlissfestFeatureKey) {
return handlers.NewBlissfestCommand(GetBlissfestService()).WithGuild(guildId).WithRoles(cfg.Roles...)
}
flogger.Warn("blissfest guild command exists but feature is disabled")
} else if cfg.Name == "book" {
bookSvc, err := GetBookService()
if err != nil {
logger.Error("failed to create book svc", zap.Error(err))
flogger.Error("failed to create book svc", zap.Error(err))
} else {
return handlers.NewBookCommand(bookSvc).WithRoles(cfg.Roles...).WithGuild(guildId)
}
} else if cfg.Name == "requests" {
bookSvc, err := GetBookService()
if err != nil {
logger.Error("failed to create book svc", zap.Error(err))
flogger.Error("failed to create book svc", zap.Error(err))
} else {
return handlers.NewUserRequestCommand(bookSvc).WithRoles(cfg.Roles...).WithGuild(guildId)
}
}
logger.Warn("not adding command", zap.String("name", cfg.Name))
flogger.Warn("not adding command", zap.String("name", cfg.Name))
return nil
}
58 changes: 51 additions & 7 deletions bot/providers/blissfest.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,62 @@
package providers

import (
"fmt"
"time"

pkgmodels "github.com/h3mmy/bloopyboi/internal/models"
"github.com/h3mmy/bloopyboi/bot/internal/config"
"github.com/h3mmy/bloopyboi/bot/services"
pkgmodels "github.com/h3mmy/bloopyboi/internal/models"
"go.uber.org/zap"
)

const BlissfestStartDateKey = "start_date"
const BlissfestHomepage = "https://www.blissfest.org/"

// Blissfest is in MI and bound to the US Eastern Timezone
// Since it always happens in the summer we can assume EDT
var blissfestTZ = time.FixedZone("UTC-4", -4*60*60)
var defaultBlissfestStartDate = time.Date(2024, 7, 12, 0, 0, 0, 0, blissfestTZ)

func GetBlissfestService() *services.BlissfestService {
location, _ := time.LoadLocation("America/Detroit")
config := pkgmodels.BlissfestConfig{
Start: time.Date(2024, 7, 12, 9, 0, 0, 0, location),
End: time.Date(2024, 7, 14, 9, 0, 0, 0, location),
Homepage: "https://www.blissfest.org/",
// Blissfest is in MI and bound to the US Eastern Timezone
if IsFeatureEnabled(pkgmodels.BlissfestFeatureKey) {
// check for provided start date
cfg := GetFeatures()[pkgmodels.BlissfestFeatureKey]
startDate := getBlissfestStartDate(cfg)

year, month, day := startDate.Date()
logger.Debug(fmt.Sprintf("startDate year: %d, month: %d, day: %d", year, month, day))
// blissfest always starts at 9am on a Friday
finalStartDate := time.Date(year, month, day, 9, 0, 0, 0, blissfestTZ)
logger.Debug("finalized blissfest start date", zap.Time("startDate", finalStartDate))
// everyone is supposed to be out by noon on the following Monday (3 days + 3 hours => 4500min => 75 hours)
finalEndDate := finalStartDate.Add(75 * time.Hour)
logger.Debug("finalized blissfest end date", zap.Time("endDate", finalEndDate))
return services.NewBlissfestService(pkgmodels.BlissfestConfig{
Start: finalStartDate,
End: finalEndDate,
Homepage: BlissfestHomepage,
})
}
logger.Warn("blissfest feature not enabled")

return nil
}

func getBlissfestStartDate(cfg config.FeatureConfig) time.Time {
if cfg.Data != nil {
startDateString, ok := cfg.Data[BlissfestStartDateKey]
if ok {
logger.Debug("parsing start date", zap.String("providedDate", startDateString))
startDate, err := time.Parse("2006-01-02", startDateString)
if err != nil {
logger.Error("error parsing configured start date", zap.Error(err))
startDate = defaultBlissfestStartDate
}
logger.Debug("finished parsing start date", zap.String("providedDate", startDateString), zap.Time("startDate", startDate))
return startDate
}
}
return services.NewBlissfestService(config)
return defaultBlissfestStartDate
}
3 changes: 1 addition & 2 deletions bot/providers/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"go.uber.org/zap/zapcore"
)


func GetDiscordConfig() *config.DiscordConfig {
AppConfig := config.GetConfig()
return AppConfig.DiscordConfig
Expand All @@ -28,7 +27,7 @@ func GetFeatures() map[string]config.FeatureConfig {
}

// Checks FeatureConfigs for key
func IsFeaturedConfigured(key string) bool {
func IsFeatureEnabled(key string) bool {
AppConfig := config.GetConfig()
fCfg, ok := AppConfig.FeatureMap[key]
if !ok {
Expand Down
4 changes: 3 additions & 1 deletion bot/providers/discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package providers
import (
"github.com/h3mmy/bloopyboi/bot/internal/config"
"github.com/h3mmy/bloopyboi/bot/services"
"go.uber.org/zap"
)

func NewDiscordServiceWithConfig(cfg *config.DiscordConfig) (*services.DiscordService, error) {
dsvc := services.NewDiscordService().WithConfig(cfg)
err := dsvc.RefreshDBConnection()
return dsvc, err
logger.Warn("encountered error refreshing db connection. persistence may not be available", zap.Error(err))
return dsvc, nil
}
55 changes: 55 additions & 0 deletions bot/services/blissfest_service.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package services

import (
"encoding/json"
"fmt"
"io"
"net/http"
"time"

"github.com/h3mmy/bloopyboi/bot/internal/log"
Expand All @@ -14,8 +18,16 @@ import (
// 2024: "https://www.blissfestfestival.org/wp-content/uploads/2024/04/Bliss24_IGAnnouncement3-2048x2048.jpg"
var lineupImageURI = "https://www.blissfestfestival.org/wp-content/uploads/2024/04/Bliss24_IGAnnouncement3-2048x2048.jpg"

// 2024 blissfest showclix "event_id": 9297272, "parent_event_id": 8615552,
// 2024 blissfest showclix venue_id = 64139

var blissfestShowclixEventID = 9297272

// 2024 blissfest logo art "https://www.blissfestfestival.org/wp-content/uploads/2024/01/Bliss_Logo_2024F3.png"

// var apiPrefix = "/wp-json/wp/v2"


type BlissfestService struct {
bloopymeta models.BloopyMeta
config pkgmodels.BlissfestConfig
Expand Down Expand Up @@ -81,3 +93,46 @@ func (bs *BlissfestService) IsInProgress() bool {
func (bs *BlissfestService) GetLineupImageURI() string {
return lineupImageURI
}


func (bs *BlissfestService) GetShowclixTicketData() (*[]pkgmodels.PriceLevel, error) {
resp, err := http.Get(fmt.Sprintf("%s%s/%d/all_levels",pkgmodels.ShowclixAPIURL, pkgmodels.ShowclixAPIEventPrefix, blissfestShowclixEventID))
if err != nil {
bs.logger.Error("error getting showclix ticket data", zap.Error(err))
return nil, err
}

defer resp.Body.Close()
result, err := io.ReadAll(resp.Body)
if err != nil {
bs.logger.Error("error reading showclix ticket data", zap.Error(err))
return nil, err
}
var priceLevels map[int]pkgmodels.PriceLevel
err = json.Unmarshal(result, &priceLevels)
if err != nil {
bs.logger.Error("error unmarshalling showclix ticket data", zap.Error(err), zap.ByteString("response", result))
return nil, err
}
priceLevelSlice := []pkgmodels.PriceLevel{}
for _, priceLevel := range priceLevels {
priceLevelSlice = append(priceLevelSlice, priceLevel)
}
return &priceLevelSlice, nil
}

func (bs *BlissfestService) GetAdultWeekendPriceLevel() (*pkgmodels.PriceLevel, error) {
priceLevelName := "Adult Weekend (18+)"
priceLevels, err := bs.GetShowclixTicketData()
if err != nil {
bs.logger.Error("error getting price levels", zap.Error(err))
return nil, err
}
for _, priceLevel := range *priceLevels {
if priceLevel.Level == priceLevelName {
return &priceLevel, nil
}
}
bs.logger.Warn("no price level found", zap.String("priceLevelName", priceLevelName))
return nil, nil
}
Loading

1 comment on commit 71d5a3c

@h3mmy
Copy link
Owner Author

@h3mmy h3mmy commented on 71d5a3c Apr 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to #35

Please sign in to comment.