town/cmd/towncon/main.go

217 lines
4.3 KiB
Go

package main
import (
"embed"
"fmt"
"math/rand"
"os"
"os/exec"
"os/user"
"path"
"strings"
"git.tilde.town/tildetown/town/email"
"github.com/charmbracelet/glamour"
"github.com/charmbracelet/huh"
"gopkg.in/yaml.v3"
)
//go:embed banners/*
var banners embed.FS
//go:embed md/*
var md embed.FS
func banner() (string, error) {
dirs, err := banners.ReadDir("banners")
if err != nil {
return "", err
}
mx := len(dirs)
ix := rand.Intn(mx)
content, err := banners.ReadFile(path.Join("banners", dirs[ix].Name()))
if err != nil {
return "", err
}
return string(content), nil
}
func info() error {
infoContent, err := md.ReadFile("md/info.md")
if err != nil {
return err
}
out, err := glamour.Render(string(infoContent), "dracula")
if err != nil {
return err
}
cmd := exec.Command("/usr/bin/bat")
cmd.Stdin = strings.NewReader(out)
cmd.Stdout = os.Stdout
return cmd.Run()
}
type physicalData struct {
Arriving string
Departing string
Transportation bool
Lodging bool
Allergies string
Couch bool
}
type rsvpData struct {
Being string
PhysicalData *physicalData `yaml:"PhysicalData,omitempty"`
Freeform string
}
func sendRSVPEmail(rd rsvpData) error {
bs, err := yaml.Marshal(rd)
if err != nil {
return err
}
return email.SendLocalEmail("vilmibm", "RSVP TOWNCON24", string(bs))
}
func rsvp(o opts) error {
var being string
var arriving string
var departing string
var transportation bool
lodging := true
var allergies string
couch := true
var freeform string
form := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().Title("How will you be attending?").
Options(
huh.NewOption("Digitally", "digital"),
huh.NewOption("Phyiscally", "physical"),
).Value(&being)),
// Physical attendee form
huh.NewGroup(
huh.NewInput().Title("When (day/time) are you arriving?").
Value(&arriving),
huh.NewInput().Title("When (day/time) are you departing?").
Value(&departing),
).WithHideFunc(func() bool {
return being != "physical"
}),
huh.NewGroup(
huh.NewConfirm().Title("Will you be staying overnight at the venue?").
Value(&lodging),
).WithHideFunc(func() bool {
return being != "physical"
}),
huh.NewGroup(
huh.NewConfirm().Title("If the need arises are you ok sleeping on a couch?").
Value(&couch),
).WithHideFunc(func() bool {
return being != "physical" && !lodging
}),
huh.NewGroup(
huh.NewInput().Title("Do you have any food allergies I should be aware of?").
Value(&allergies),
huh.NewConfirm().Title("Will you need any help getting to the venue?").
Description("I have a car and have some ability to help getting people to the venue").
Value(&transportation),
).WithHideFunc(func() bool {
return being != "physical"
}),
// Catch all freeform
huh.NewGroup(
huh.NewText().
Title("Anything you want me to know? Any questions?").
Value(&freeform)))
err := form.Run()
if err != nil {
return err
}
var pd *physicalData
if being == "physical" {
pd = &physicalData{
Arriving: arriving,
Departing: departing,
Transportation: transportation,
Lodging: lodging,
Allergies: allergies,
Couch: couch,
}
}
rd := rsvpData{
Being: being,
Freeform: freeform,
PhysicalData: pd}
return sendRSVPEmail(rd)
}
type opts struct {
Username string
}
func _main() error {
b, err := banner()
if err != nil {
return err
}
fmt.Println(b)
u, err := user.Current()
if err != nil {
return err
}
o := opts{
Username: u.Username,
}
fmt.Printf("\t\t^_^_^_^_^_^_^ hi ~%s ^_^_^_^_^_^_^\n", o.Username)
fmt.Println()
var mode string
huh.NewSelect[string]().Title("whuddyu wanna doo?").
Options(
huh.NewOption("Get an info dump", "info"),
huh.NewOption("RSVP", "rsvp"),
huh.NewOption("Submit a talk proposal or finished work", "submit"),
huh.NewOption("Propose a creative jam", "jam"),
huh.NewOption("Quit", "quit"),
).Value(&mode).Run()
switch mode {
case "info":
return info()
case "rsvp":
return rsvp(o)
case "submit":
case "jam":
case "quit":
default:
return fmt.Errorf("wtf '%s'", mode)
}
return nil
}
func main() {
if err := _main(); err != nil {
fmt.Fprintf(os.Stderr, ":( failed: %s\n", err.Error())
os.Exit(1)
}
}