Adds a `timer` command that immediately confirms the timer and posts a notification back to Campfire when it fires, using CAMPFIRE_URL and CAMPFIRE_TOKEN. Adds godotenv so the bot loads a .env file automatically on startup. Includes a .env.example documenting all env vars. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
62 lines
1.6 KiB
Go
62 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type TimerPlugin struct{}
|
|
|
|
func (p TimerPlugin) Name() string { return "timer" }
|
|
|
|
func (p TimerPlugin) ShortHelp() string { return "set a timer" }
|
|
|
|
func (p TimerPlugin) DetailedHelp() string {
|
|
return "Usage: timer <duration>\nSets a timer. When it goes off, posts a message to the room.\nExamples: timer 5m, timer 1h30m, timer 90s"
|
|
}
|
|
|
|
func (p TimerPlugin) Execute(msg BotMessage, args string) string {
|
|
d, err := time.ParseDuration(strings.TrimSpace(args))
|
|
if err != nil || d <= 0 {
|
|
return "Usage: timer <duration> (e.g. timer 5m, timer 1h30m)"
|
|
}
|
|
|
|
if os.Getenv("CAMPFIRE_URL") == "" || os.Getenv("CAMPFIRE_TOKEN") == "" {
|
|
return "Cannot set timer: CAMPFIRE_URL and CAMPFIRE_TOKEN must be configured."
|
|
}
|
|
|
|
firesAt := time.Now().Add(d)
|
|
|
|
go func() {
|
|
time.Sleep(d)
|
|
sendTimerNotification(msg, d)
|
|
}()
|
|
|
|
return fmt.Sprintf("Timer set for %s. Will go off at %s.", d, firesAt.Format("15:04:05"))
|
|
}
|
|
|
|
func sendTimerNotification(msg BotMessage, d time.Duration) {
|
|
baseURL := os.Getenv("CAMPFIRE_URL")
|
|
token := os.Getenv("CAMPFIRE_TOKEN")
|
|
if baseURL == "" || token == "" {
|
|
log.Println("timer: CAMPFIRE_URL or CAMPFIRE_TOKEN not set, cannot send notification")
|
|
return
|
|
}
|
|
|
|
url := fmt.Sprintf("%s/rooms/%d/%s/messages", baseURL, msg.Room.ID, token)
|
|
body := fmt.Sprintf("%s your %s timer is done!", msg.User.Name, d)
|
|
|
|
resp, err := http.Post(url, "text/plain", strings.NewReader(body))
|
|
if err != nil {
|
|
log.Printf("timer: failed to send notification: %v", err)
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
io.Copy(io.Discard, resp.Body)
|
|
}
|