hampbot/internal/commands/studentlife/where.go

304 lines
10 KiB
Go
Raw Normal View History

2023-09-07 10:39:57 -07:00
package studentlife
import (
"bytes"
"fmt"
"image/color"
"image/png"
"os"
"regexp"
"strings"
"github.com/bwmarrin/discordgo"
sm "github.com/flopp/go-staticmaps"
"github.com/golang/geo/s2"
mapbox "github.com/jackmerrill/go-mapbox/lib"
"github.com/jackmerrill/go-mapbox/lib/base"
"github.com/jackmerrill/go-mapbox/lib/directions"
"github.com/jackmerrill/hampbot/internal/utils/config"
"github.com/jackmerrill/hampbot/internal/utils/embed"
"github.com/zekroTJA/shireikan"
)
// string is the name of the building in regex, []float64 is the lat/long
type Location map[string][]float64
var LOCATIONS = Location{
"^(kern|\"kern kafe\"|\"kern cafe\"|\"kern center\"|\"r\\.w\\. kern center\"|\"rw kern center\"|admissions|\"financial aid\"|finaid)$": []float64{42.325490, -72.530425},
"^(bridge|\"bridge cafe\"|the bridge)$": []float64{42.32560055268511, -72.53171782489403},
"^(rcc|\"robert crown center\"|gym)$": []float64{42.3259021736783, -72.53138568980566},
"^(library|\"harold f. johnson library center\"|\"mail room\"|\"post office\"|hampstore|\"hamp store\"|\"campus store\"|duplications|it|\"art gallery\"|\"hampshire college art gallery\"|sparc)$": []float64{42.325503815980404, -72.53234665636477},
"^(cole|\"the cole\"|\"cole science center\"|csc)$": []float64{42.325005132910455, -72.53264274547023},
"^(\"mixed nuts\")$": []float64{42.32438520935449, -72.53314741618625},
"^(prescott)$": []float64{42.32370121438042, -72.53400755941487},
"^(\"prescott tavern\"|tavern)$": []float64{42.32330551141666, -72.53410313088433},
"^(c4d|\"center for design\"|\"lemelson building\")$": []float64{42.323653164859145, -72.53277277596145},
"^(\"central records\"|casa)$": []float64{42.32400565840685, -72.53267685200223},
"^(\"arts barn\"|\"art barn\"|art)$": []float64{42.323484930985096, -72.53270230871183},
"^(jlc|\"jerome liebling center\")$": []float64{42.32343637951593, -72.53186281901529},
"^(\"solar canopy\")$": []float64{42.3231160046793, -72.5323111913881},
"^(\"music and dance building\"|mdb|music|dance)$": []float64{42.32296880488658, -72.53257385728799},
"^(ash|\"adele simmons hall\")$": []float64{42.32286199484466, -72.53189407069387},
"^(carle|\"the carle\"|\"the eric carle museum\"|\"the eric carle museum of picture book art\")$": []float64{42.32109682435725, -72.53332586596198},
"^(elc|early learning center)$": []float64{42.32130800774271, -72.53485513102083},
"^(\"multisport center\"|multisport|weight room|msc)$": []float64{42.32138500151223, -72.53614340300827},
"^(\"dakin student life center\"|dslc)$": []float64{42.32313128927387, -72.53022445236283},
"^(\"merrill student life center\"|mslc)$": []float64{42.32347857352905, -72.53034306624653},
"^(\"merrill pavillion\"|pavillion)$": []float64{42.323322471247494, -72.53030510980373},
"^(dakin|hell|\"dakin house\")$": []float64{42.322597743840625, -72.53027825479788},
"^(merrill|\"merrill house\")$": []float64{42.323732718386175, -72.52977892147766},
"^(\"dining commons\"|dc|saga)$": []float64{42.32319356233955, -72.52917576638322},
"^(\"yiddish book center\"|ybc)$": []float64{42.32175452980474, -72.5276151025249},
"^(\"franklin patterson hall\"|fph)$": []float64{42.324221538083805, -72.5306271019939},
"^(\"the yurt\"|yurt|radio)$": []float64{42.324071744881785, -72.53136719263956},
"^(enfield|\"enfield mods\"|\"enfield house\")$": []float64{42.32646094303269, -72.52929170510444},
"^(\"wellness center\")$": []float64{42.32709812095117, -72.5291661607627},
"^(\"spiritual life center\"|slc)$": []float64{42.32705614551552, -72.52973716786117},
"^(edh|\"emily dickinson hall\"|theatre|theater)$": []float64{42.327652942240896, -72.53062317253445},
"^(\"writing center\")$": []float64{42.32780110830725, -72.53112929268784},
"^(greenwich|\"greenwich mods\"|\"greenwich house\")$": []float64{42.32748781455265, -72.53192281696715},
"^(soccer|\"soccer field\"|\"hampshire college soccer field\")$": []float64{42.32651025401564, -72.53454675256307},
"^(\"cultural center\"|cc|\"lebron-wiggins-pran cultural center\"|\"Lebrón-Wiggins-Pran Cultural Center\")$": []float64{42.32487763771362, -72.5339769868106},
"^(basketball|\"basketball courts\"|\"basketball court\"|\"tennis courts\"|\"tennis court\")$": []float64{42.32557748709811, -72.53720546848393},
"^(\"red barn\"|\"the red barn\"|barn)$": []float64{42.32642633315529, -72.52551730246282},
"^(\"the hitchcock center\"|\"hitchcock center\"|\"hitchcock center for the environment\")$": []float64{42.32771760017527, -72.52570886249646},
"^(csa|farm|\"hampshire college farm center\"|\"hampshire college farm\")$": []float64{42.32903799744424, -72.52573139895138},
"^(\"health services\"|\"hampshire college health services\")$": []float64{42.32666929509394, -72.52524995366625},
"^(atkins|\"atkins farms country market\")$": []float64{42.319355104827295, -72.52927125654328},
"^(res|\"the res\"|the reservoir|reservoir)$": []float64{42.317285834368995, -72.5406219720153},
2023-09-07 10:39:57 -07:00
}
type Where struct {
}
var mapboxToken = os.Getenv("MAPBOX_TOKEN")
var mapBox, _ = mapbox.NewMapbox(mapboxToken)
func (c *Where) GetInvokes() []string {
return []string{"where"}
}
func (c *Where) GetDescription() string {
return "Where is this building?"
}
func (c *Where) GetHelp() string {
return "`where <building>` - Where is this building?"
}
func (c *Where) GetGroup() string {
return config.GroupStudentLife
}
func (c *Where) GetDomainName() string {
return "hamp.studentlife.where"
}
func (c *Where) GetSubPermissionRules() []shireikan.SubPermission {
return nil
}
func (c *Where) IsExecutableInDMChannels() bool {
return true
}
func (c *Where) Exec(ctx shireikan.Context) error {
if len(ctx.GetArgs()) < 1 {
// return all buildings
e := embed.NewSuccessEmbed(ctx)
e.SetTitle("Buildings")
desc := ""
locs := []string{}
for regex := range LOCATIONS {
l := strings.TrimLeft(regex, "^(")
l = strings.TrimRight(l, ")$")
ls := strings.Split(l, "|")
for _, l := range ls {
locs = append(locs, l)
}
desc += fmt.Sprintf("`%s`, ", strings.Join(ls, "`, `"))
}
e.SetDescription(desc)
_, err := ctx.GetSession().ChannelMessageSendComplex(ctx.GetChannel().ID, &discordgo.MessageSend{
Embed: e.MessageEmbed,
Reference: ctx.GetMessage().Reference(),
})
return err
2023-09-07 10:39:57 -07:00
}
to := strings.ToLower(ctx.GetArgs().Get(0).AsString())
from := strings.ToLower(ctx.GetArgs().Get(1).AsString())
e := embed.NewSuccessEmbed(ctx)
e.SetTitle("Where is " + to + "?")
if from != "" {
e.SetTitle("Directions from " + to + " to " + from)
}
e.SetDescription("It's right here!")
mapCtx := sm.NewContext()
mapCtx.SetSize(600, 600)
mapCtx.SetTileProvider(sm.NewTileProviderOpenStreetMaps())
if from == "" {
mapCtx.SetZoom(17)
}
var toCoord []float64
var fromCoord []float64
for regex, coords := range LOCATIONS {
toMatch, err := regexp.MatchString(regex, to)
if err != nil {
return err
}
fromMatch, err := regexp.MatchString(regex, from)
if err != nil {
return err
}
if toMatch || fromMatch {
lat := coords[0]
long := coords[1]
if toMatch {
toCoord = coords
mapCtx.AddObject(
sm.NewMarker(
s2.LatLngFromDegrees(lat, long),
color.RGBA{R: 0, G: 255, B: 0, A: 255},
16.0,
),
)
} else if fromMatch {
fromCoord = coords
mapCtx.AddObject(
sm.NewMarker(
s2.LatLngFromDegrees(lat, long),
color.RGBA{R: 255, G: 0, B: 0, A: 255},
16.0,
),
)
}
}
}
if len(toCoord) == 0 {
errorEmbed := embed.NewErrorEmbed(ctx)
errorEmbed.SetTitle("Error")
errorEmbed.SetDescription(fmt.Sprintf("Building `%s` not found.", to))
_, err := ctx.GetSession().ChannelMessageSendComplex(ctx.GetChannel().ID, &discordgo.MessageSend{
Embed: errorEmbed.MessageEmbed,
Reference: ctx.GetMessage().Reference(),
})
return err
}
if len(fromCoord) == 0 && from != "" {
errorEmbed := embed.NewErrorEmbed(ctx)
errorEmbed.SetTitle("Error")
errorEmbed.SetDescription(fmt.Sprintf("Building `%s` not found.", from))
_, err := ctx.GetSession().ChannelMessageSendComplex(ctx.GetChannel().ID, &discordgo.MessageSend{
Embed: errorEmbed.MessageEmbed,
Reference: ctx.GetMessage().Reference(),
})
return err
}
if from != "" {
// get mapbox directions
dir, err := mapBox.Directions.GetDirections([]base.Location{
{
Latitude: toCoord[0],
Longitude: toCoord[1],
},
{
Latitude: fromCoord[0],
Longitude: fromCoord[1],
},
}, directions.RoutingWalking, &directions.RequestOpts{
Steps: false,
Alternatives: false,
})
if err != nil {
return err
}
var latLngs []s2.LatLng
// add route to map
for _, coord := range dir.Routes[0].Geometry.Coordinates {
latLngs = append(latLngs, s2.LatLngFromDegrees(coord[1], coord[0]))
}
mapCtx.AddObject(
sm.NewPath(
latLngs,
color.RGBA{R: 0, G: 0, B: 255, A: 255},
3.0,
),
)
// set the zoom accordingly to the route length
if dir.Routes[0].Distance > 1000 {
mapCtx.SetZoom(15)
}
}
img, err := mapCtx.Render()
if err != nil {
return err
}
buf := new(bytes.Buffer)
// convert to base64
err = png.Encode(buf, img)
if err != nil {
return err
}
e.SetImage("attachment://map.png")
if err != nil {
return err
}
_, err = ctx.GetSession().ChannelMessageSendComplex(ctx.GetChannel().ID, &discordgo.MessageSend{
Embed: e.MessageEmbed,
Reference: ctx.GetMessage().Reference(),
Files: []*discordgo.File{
{
Name: "map.png",
ContentType: "image/png",
Reader: buf,
},
},
})
return err
}