commit 0dee5072214f1ee70ca0da10f72e929049994497 Author: fdvkey Date: Thu Aug 13 16:47:43 2026 +0700 feat: init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..71ce6b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +docs/superpowers +pois \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..92ef0d6 --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module git.fdvky.me/Fd/pois + +go 1.25.5 + +require github.com/bwmarrin/discordgo v0.29.0 + +require ( + github.com/cloudflare/circl v1.6.3 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/sys v0.29.0 // indirect +) + +replace github.com/bwmarrin/discordgo => github.com/yeongaori/discordgo-fork v0.0.0-20260627070107-c65bda26a53b diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7dc4bac --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= +github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/yeongaori/discordgo-fork v0.0.0-20260627070107-c65bda26a53b h1:TCA/Uk1bfWuMbAWDQb+qBjryXEkZ/4z6RJ4yPvr2Qrc= +github.com/yeongaori/discordgo-fork v0.0.0-20260627070107-c65bda26a53b/go.mod h1:A0FcMFJKJ9fRjgSuZ2o+pIQ6mPS81SVuiLN2vYTa7Ao= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/main.go b/main.go new file mode 100644 index 0000000..9ef4b56 --- /dev/null +++ b/main.go @@ -0,0 +1,93 @@ +package main + +import ( + "context" + "log" + "os" + "os/signal" + "sync" + "syscall" + "time" + + "github.com/bwmarrin/discordgo" +) + +func main() { + token := os.Getenv("DISCORD_TOKEN") + channelID := os.Getenv("CHANNEL_ID") + if token == "" || channelID == "" { + log.Fatal("DISCORD_TOKEN and CHANNEL_ID are required") + } + + session, err := discordgo.New("Bot " + token) + if err != nil { + log.Fatal(err) + } + session.Identify.Intents = discordgo.IntentsGuilds | discordgo.IntentsGuildVoiceStates + + if err := session.Open(); err != nil { + log.Fatal(err) + } + defer session.Close() + + channel, err := session.Channel(channelID) + if err != nil { + log.Fatal(err) + } + if channel.Type != discordgo.ChannelTypeGuildVoice { + log.Fatal("CHANNEL_ID must identify a guild voice channel") + } + + var joinMu sync.Mutex + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + join := func() { + joinMu.Lock() + defer joinMu.Unlock() + + for { + select { + case <-ctx.Done(): + return + default: + } + + if _, err := session.ChannelVoiceJoin(ctx, channel.GuildID, channelID, false, true); err == nil { + log.Printf("joined voice channel %s", channelID) + return + } else { + log.Printf("voice join failed: %v; retrying in 5s", err) + } + + select { + case <-ctx.Done(): + return + case <-time.After(5 * time.Second): + } + } + } + + session.AddHandler(func(s *discordgo.Session, update *discordgo.VoiceStateUpdate) { + if s.State.User == nil || update.UserID != s.State.User.ID || update.ChannelID == channelID { + return + } + log.Print("bot left target voice channel; reconnecting") + go join() + }) + + join() + + signals := make(chan os.Signal, 1) + signal.Notify(signals, os.Interrupt, syscall.SIGTERM) + <-signals + cancel() + + session.RLock() + voice := session.VoiceConnections[channel.GuildID] + session.RUnlock() + if voice != nil { + _ = voice.Disconnect(context.Background()) + } + log.Print("bot stopped") +}