All checks were successful
release-tag / release-image (push) Successful in 2m3s
94 lines
3.6 KiB
Go
94 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
|
|
"releasewatcher/internal/auth"
|
|
"releasewatcher/internal/discordbot"
|
|
"releasewatcher/internal/notify"
|
|
"releasewatcher/internal/store"
|
|
"releasewatcher/internal/web"
|
|
)
|
|
|
|
func main() {
|
|
addr := flag.String("addr", env("RW_ADDR", ":8080"), "HTTP listen address")
|
|
dataFile := flag.String("data", env("RW_DATA", "/data/releasewatcher.json"), "JSON data file")
|
|
adminEmail := flag.String("admin-email", env("RW_ADMIN_EMAIL", "admin@example.local"), "initial admin email")
|
|
adminPass := flag.String("admin-pass", env("RW_ADMIN_PASSWORD", "admin12345"), "initial admin password")
|
|
secret := flag.String("secret", env("RW_SECRET", "change-me-in-production"), "session secret")
|
|
discordToken := flag.String("discord-token", env("RW_DISCORD_TOKEN", ""), "Discord bot token; empty disables Discord")
|
|
discordAppID := flag.String("discord-app-id", env("RW_DISCORD_APP_ID", ""), "Discord application ID for command registration")
|
|
discordGuildID := flag.String("discord-guild-id", env("RW_DISCORD_GUILD_ID", ""), "Discord guild/server ID for release channels")
|
|
discordCategoryID := flag.String("discord-category-id", env("RW_DISCORD_CATEGORY_ID", ""), "Discord category ID for software release channels; empty creates/uses category name")
|
|
discordCategoryName := flag.String("discord-category-name", env("RW_DISCORD_CATEGORY_NAME", "ReleaseWatcher"), "Discord category name for software release channels")
|
|
discordReleaseMention := flag.String("discord-release-mention", env("RW_DISCORD_RELEASE_MENTION", "@here"), "Mention text for release channel pings, e.g. @here or <@&ROLE_ID>; empty disables pings")
|
|
discordSendDMs := flag.Bool("discord-send-dms", envBool("RW_DISCORD_SEND_DMS", true), "also send release notifications as DMs to subscribers")
|
|
flag.Parse()
|
|
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
st, err := store.Open(*dataFile)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if err := st.EnsureUser(store.User{Email: *adminEmail, DisplayName: "Administrator", Role: store.RoleAdmin, PasswordHash: auth.HashPassword(*adminPass)}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
am := auth.New(*secret, st)
|
|
var notifier notify.ReleaseNotifier = notify.LoggingNotifier{Log: logger}
|
|
if *discordToken != "" {
|
|
dg, err := discordbot.NewDiscordSession(*discordToken)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
discordServices := discordbot.NewServices(st, dg, logger, discordbot.Config{
|
|
GuildID: *discordGuildID,
|
|
CategoryID: *discordCategoryID,
|
|
CategoryName: *discordCategoryName,
|
|
ReleaseMention: *discordReleaseMention,
|
|
SendDMs: *discordSendDMs,
|
|
})
|
|
discordbot.AttachDiscordHandlers(dg, discordServices)
|
|
if err := dg.Open(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer dg.Close()
|
|
if *discordAppID != "" {
|
|
if err := discordbot.UpsertCommands(dg, *discordAppID); err != nil {
|
|
logger.Warn("Discord commands konnten nicht registriert werden", "error", err)
|
|
}
|
|
} else {
|
|
logger.Warn("RW_DISCORD_APP_ID fehlt; Slash-Commands werden nicht registriert")
|
|
}
|
|
notifier = discordServices
|
|
logger.Info("Discord-Bot gestartet")
|
|
}
|
|
srv, err := web.New(st, am, notifier, logger)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
logger.Info("ReleaseWatcher gestartet", "addr", *addr, "admin", *adminEmail)
|
|
log.Fatal(http.ListenAndServe(*addr, srv.Routes()))
|
|
}
|
|
|
|
func env(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func envBool(key string, fallback bool) bool {
|
|
switch os.Getenv(key) {
|
|
case "1", "true", "TRUE", "yes", "YES", "on", "ON":
|
|
return true
|
|
case "0", "false", "FALSE", "no", "NO", "off", "OFF":
|
|
return false
|
|
default:
|
|
return fallback
|
|
}
|
|
}
|