mirror of
https://github.com/automuteus/automuteus.git
synced 2025-03-14 10:29:29 +00:00
More rearranging, add basic API server
This commit is contained in:
@ -44,6 +44,8 @@ COPY --from=builder /app /app
|
||||
COPY ./locales/ /app/locales
|
||||
COPY ./storage/postgres.sql /app/storage/postgres.sql
|
||||
|
||||
# Port used for AMU API
|
||||
EXPOSE 5000
|
||||
# Port used for health/liveliness checks
|
||||
EXPOSE 8080
|
||||
# Port used for prometheus metrics
|
||||
|
12
TODO.md
12
TODO.md
@ -1,12 +0,0 @@
|
||||
- [ ] Search for unused functions/code relating to old command processing
|
||||
- [X] Reintegrate Redis-based user rate limiting on fast command invocation
|
||||
- [X] Restrict premium invites viewing to admins only
|
||||
- [X] Search for (and update) commands with higher guild permissions needed for invocation
|
||||
- [ ] Unit tests where appropriate (such as complex control flow for premium)
|
||||
- [X] Integrate subcommands where helpful (/link colors for starters)
|
||||
- [ ] Make commands package-private
|
||||
- [ ] Localization and i18n keys
|
||||
- [ ] Integrate concise/minimal responses (using emojis) to minimize translation efforts and increase readability
|
||||
- [X] Refactor `/privacy` to use command options and subcommands
|
||||
- [ ] Add galactus endpoints to allow website to fetch current command list
|
||||
- [ ] Migrate link/unlink functionality to right-click User context menu actions
|
29
discord/api.go
Normal file
29
discord/api.go
Normal file
@ -0,0 +1,29 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gorilla/mux"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (bot *Bot) StartAPIServer(port string) {
|
||||
r := mux.NewRouter()
|
||||
|
||||
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO For any higher-sensitivity info in the future, this should properly identify the origin specifically
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length")
|
||||
|
||||
info := bot.getInfo()
|
||||
data, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
} else {
|
||||
w.Write(data)
|
||||
}
|
||||
})
|
||||
|
||||
http.ListenAndServe(":"+port, r)
|
||||
}
|
@ -4,10 +4,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/amongus"
|
||||
"github.com/automuteus/automuteus/v7/discord/command"
|
||||
"github.com/automuteus/automuteus/v7/discord/tokenprovider"
|
||||
"github.com/automuteus/automuteus/v7/metrics"
|
||||
"github.com/automuteus/automuteus/v7/internal/server"
|
||||
"github.com/automuteus/automuteus/v7/pkg/amongus"
|
||||
"github.com/automuteus/automuteus/v7/pkg/discord"
|
||||
"github.com/automuteus/automuteus/v7/pkg/game"
|
||||
"github.com/automuteus/automuteus/v7/pkg/premium"
|
||||
@ -149,25 +149,7 @@ func (bot *Bot) InitTokenProvider(tp *tokenprovider.TokenProvider) {
|
||||
}
|
||||
|
||||
func (bot *Bot) StartMetricsServer(nodeID string) error {
|
||||
return metrics.PrometheusMetricsServer(bot.RedisInterface.client, nodeID, "2112")
|
||||
}
|
||||
|
||||
func (bot *Bot) StatsRefreshWorker(dur time.Duration) {
|
||||
for {
|
||||
users := rediskey.GetTotalUsers(context.Background(), bot.RedisInterface.client)
|
||||
if users == rediskey.NotFound {
|
||||
log.Println("Refreshing user stats with worker")
|
||||
rediskey.RefreshTotalUsers(context.Background(), bot.RedisInterface.client, bot.PostgresInterface.Pool)
|
||||
}
|
||||
|
||||
games := rediskey.GetTotalGames(context.Background(), bot.RedisInterface.client)
|
||||
if games == rediskey.NotFound {
|
||||
log.Println("Refreshing game stats with worker")
|
||||
rediskey.RefreshTotalGames(context.Background(), bot.RedisInterface.client, bot.PostgresInterface.Pool)
|
||||
}
|
||||
|
||||
time.Sleep(dur)
|
||||
}
|
||||
return server.PrometheusMetricsServer(bot.RedisInterface.client, nodeID, "2112")
|
||||
}
|
||||
|
||||
func (bot *Bot) Close() {
|
||||
@ -272,7 +254,7 @@ func (bot *Bot) forceEndGame(gsr GameStateRequest) {
|
||||
|
||||
deleted := dgs.DeleteGameStateMsg(bot.PrimarySession, true)
|
||||
if deleted {
|
||||
go metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageCreateDelete, 1)
|
||||
go server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageCreateDelete, 1)
|
||||
}
|
||||
|
||||
bot.RedisInterface.SetDiscordGameState(dgs, lock)
|
||||
@ -311,9 +293,9 @@ func (bot *Bot) RefreshGameStateMessage(gsr GameStateRequest, sett *settings.Gui
|
||||
created := dgs.CreateMessage(bot.PrimarySession, bot.gameStateResponse(dgs, sett), dgs.GameStateMsg.MessageChannelID, dgs.GameStateMsg.LeaderID)
|
||||
|
||||
if deleted && created {
|
||||
go metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageCreateDelete, 2)
|
||||
go server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageCreateDelete, 2)
|
||||
} else if deleted || created {
|
||||
go metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageCreateDelete, 1)
|
||||
go server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageCreateDelete, 1)
|
||||
}
|
||||
|
||||
bot.RedisInterface.SetDiscordGameState(dgs, lock)
|
||||
|
@ -2,7 +2,7 @@ package discord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/amongus"
|
||||
"github.com/automuteus/automuteus/v7/pkg/amongus"
|
||||
"github.com/automuteus/automuteus/v7/pkg/settings"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/amongus"
|
||||
"github.com/automuteus/automuteus/v7/metrics"
|
||||
"github.com/automuteus/automuteus/v7/internal/server"
|
||||
"github.com/automuteus/automuteus/v7/pkg/amongus"
|
||||
"github.com/automuteus/automuteus/v7/pkg/discord"
|
||||
"github.com/automuteus/automuteus/v7/pkg/game"
|
||||
"github.com/automuteus/automuteus/v7/pkg/settings"
|
||||
@ -127,7 +127,7 @@ func (bot *Bot) SubscribeToGameByConnectCode(guildID, connectCode string, endGam
|
||||
"VoiceChannel": discord.MentionByChannelID(readOnlyDgs.VoiceChannel),
|
||||
},
|
||||
))
|
||||
metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageCreateDelete, 1)
|
||||
server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageCreateDelete, 1)
|
||||
}
|
||||
correlatedUserID = userID
|
||||
case task.GameOverJob:
|
||||
@ -166,10 +166,10 @@ func (bot *Bot) SubscribeToGameByConnectCode(guildID, connectCode string, endGam
|
||||
}
|
||||
msg, err := bot.PrimarySession.ChannelMessageSendEmbed(channelID, embed)
|
||||
if delTime > 0 && err == nil {
|
||||
metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageCreateDelete, 2)
|
||||
server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageCreateDelete, 2)
|
||||
go MessageDeleteWorker(bot.PrimarySession, msg.ChannelID, msg.ID, time.Minute*time.Duration(delTime))
|
||||
} else if err == nil {
|
||||
metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageCreateDelete, 1)
|
||||
server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageCreateDelete, 1)
|
||||
}
|
||||
}
|
||||
go dumpGameToPostgres(*dgs, bot.PostgresInterface, gameOverResult)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"github.com/automuteus/automuteus/v7/metrics"
|
||||
"github.com/automuteus/automuteus/v7/internal/server"
|
||||
"github.com/automuteus/automuteus/v7/pkg/settings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -134,7 +134,7 @@ func (bot *Bot) DispatchRefreshOrEdit(readOnlyDgs *GameState, dgsRequest GameSta
|
||||
} else {
|
||||
edited := readOnlyDgs.dispatchEdit(bot.PrimarySession, bot.gameStateResponse(readOnlyDgs, sett))
|
||||
if edited {
|
||||
metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageEdit, 1)
|
||||
server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageEdit, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/metrics"
|
||||
"github.com/automuteus/automuteus/v7/internal/server"
|
||||
"github.com/automuteus/automuteus/v7/pkg/rediskey"
|
||||
"github.com/automuteus/automuteus/v7/storage"
|
||||
"github.com/bsm/redislock"
|
||||
@ -57,7 +57,7 @@ func (bot *Bot) refreshGameLiveness(code string) {
|
||||
|
||||
func (bot *Bot) rateLimitEventCallback(_ *discordgo.Session, rl *discordgo.RateLimit) {
|
||||
log.Println(rl.Message)
|
||||
metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.InvalidRequest, 1)
|
||||
server.RecordDiscordRequests(bot.RedisInterface.client, server.InvalidRequest, 1)
|
||||
}
|
||||
|
||||
func (redisInterface *RedisInterface) AddUniqueGuildCounter(guildID string) {
|
||||
|
@ -4,13 +4,13 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/discord/command"
|
||||
"github.com/automuteus/automuteus/v7/pkg/amongus"
|
||||
"github.com/automuteus/automuteus/v7/pkg/discord"
|
||||
"github.com/automuteus/automuteus/v7/pkg/settings"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/automuteus/automuteus/v7/amongus"
|
||||
"github.com/automuteus/automuteus/v7/discord/setting"
|
||||
"github.com/automuteus/automuteus/v7/pkg/game"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
|
@ -3,6 +3,7 @@ package discord
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/internal/server"
|
||||
"github.com/automuteus/automuteus/v7/pkg/storage"
|
||||
"log"
|
||||
"regexp"
|
||||
@ -13,7 +14,6 @@ import (
|
||||
redis_common "github.com/automuteus/automuteus/v7/common"
|
||||
"github.com/automuteus/automuteus/v7/discord/command"
|
||||
"github.com/automuteus/automuteus/v7/discord/setting"
|
||||
"github.com/automuteus/automuteus/v7/metrics"
|
||||
"github.com/automuteus/automuteus/v7/pkg/discord"
|
||||
"github.com/automuteus/automuteus/v7/pkg/premium"
|
||||
"github.com/automuteus/automuteus/v7/pkg/settings"
|
||||
@ -133,7 +133,7 @@ func (bot *Bot) slashCommandHandler(s *discordgo.Session, i *discordgo.Interacti
|
||||
if interactionLock == nil {
|
||||
return nil
|
||||
}
|
||||
defer metrics.RecordDiscordRequests(bot.RedisInterface.client, metrics.MessageCreateDelete, 1)
|
||||
defer server.RecordDiscordRequests(bot.RedisInterface.client, server.MessageCreateDelete, 1)
|
||||
defer interactionLock.Release(ctx)
|
||||
|
||||
sett := bot.StorageInterface.GetGuildSettings(i.GuildID)
|
||||
|
@ -3,7 +3,7 @@ package tokenprovider
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/automuteus/automuteus/v7/metrics"
|
||||
"github.com/automuteus/automuteus/v7/internal/server"
|
||||
"github.com/automuteus/automuteus/v7/pkg/rediskey"
|
||||
"github.com/automuteus/automuteus/v7/pkg/task"
|
||||
"github.com/go-redis/redis/v8"
|
||||
@ -11,10 +11,10 @@ import (
|
||||
)
|
||||
|
||||
func RecordDiscordRequestsByCounts(client *redis.Client, counts task.MuteDeafenSuccessCounts) {
|
||||
metrics.RecordDiscordRequests(client, metrics.MuteDeafenOfficial, counts.Official)
|
||||
metrics.RecordDiscordRequests(client, metrics.MuteDeafenWorker, counts.Worker)
|
||||
metrics.RecordDiscordRequests(client, metrics.MuteDeafenCapture, counts.Capture)
|
||||
metrics.RecordDiscordRequests(client, metrics.InvalidRequest, counts.RateLimit)
|
||||
server.RecordDiscordRequests(client, server.MuteDeafenOfficial, counts.Official)
|
||||
server.RecordDiscordRequests(client, server.MuteDeafenWorker, counts.Worker)
|
||||
server.RecordDiscordRequests(client, server.MuteDeafenCapture, counts.Capture)
|
||||
server.RecordDiscordRequests(client, server.InvalidRequest, counts.RateLimit)
|
||||
}
|
||||
|
||||
func (tokenProvider *TokenProvider) attemptOnSecondaryTokens(guildID, userID string, tokenSubset map[string]struct{}, request task.UserModify) string {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"github.com/automuteus/automuteus/v7/amongus"
|
||||
"github.com/automuteus/automuteus/v7/pkg/amongus"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
|
@ -2,9 +2,8 @@ package discord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/pkg/amongus"
|
||||
"strings"
|
||||
|
||||
"github.com/automuteus/automuteus/v7/amongus"
|
||||
)
|
||||
|
||||
type UserDataSet map[string]UserData
|
||||
|
@ -1,4 +1,4 @@
|
||||
package metrics
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/gorilla/mux"
|
@ -1,4 +1,4 @@
|
||||
package metrics
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
@ -3,18 +3,18 @@
|
||||
"commands.debug.clear.user.success" = "Successfully cleared cached usernames for {{.User}}"
|
||||
"commands.debug.view.error" = "Encountered an error trying to view debug information: {{.Error}}"
|
||||
"commands.debug.view.user.empty" = "I don't have any saved usernames for {{.User}}"
|
||||
"commands.debug.view.user.success" = "I have the following cached usernames for {{.User}}:\n```\n{{.Cached}}\n```"
|
||||
"commands.debug.view.user.success" = "I have the following cached usernames for {{.User}}:\\n```\\n{{.Cached}}\\n```"
|
||||
"commands.dm" = "Sorry, I don't respond to DMs. Please execute the command in a text channel instead."
|
||||
"commands.download.cooldown" = "Sorry, `{{.Category}}` data can only downloaded once every 24 hours!\n\nPlease wait {{.Duration}} and then try again"
|
||||
"commands.download.cooldown" = "Sorry, `{{.Category}}` data can only downloaded once every 24 hours!\\n\\nPlease wait {{.Duration}} and then try again"
|
||||
"commands.download.file.success" = "Here's that file for you!"
|
||||
"commands.download.guild.confirmation" = "⚠️**Are you sure?**⚠️\nIf you download the `{{.Category}}` data now, it will not be downloadable again for 24 hours!"
|
||||
"commands.download.guild.confirmation" = "⚠️**Are you sure?**⚠️\\nIf you download the `{{.Category}}` data now, it will not be downloadable again for 24 hours!"
|
||||
"commands.download.guild.error" = "I encountered an error fetching your stats for download: {{.Error}}"
|
||||
"commands.download.nogold" = "Downloading AutoMuteUs data is reserved for Gold subscribers only!"
|
||||
"commands.error" = "Error executing `{{.Command}}`: `{{.Error}}`"
|
||||
"commands.error.nogame" = "No game is currently running."
|
||||
"commands.error.reinvite" = "I'm missing the following required permissions to function properly in this server or channel:\n```\n{{.Perm}}```\nCheck the permissions for the Text/Voice channel {{.Channel}}, but you may also need to re-invite me [here](https://add.automute.us)"
|
||||
"commands.help.subtitle" = "[View the Github Project](https://github.com/automuteus/automuteus) or [Join our Discord](https://discord.gg/ZkqZSWF)\n\nType `/help <command>` to see more details on a command!"
|
||||
"commands.help.title" = "AutoMuteUs Bot Commands:\n"
|
||||
"commands.error.reinvite" = "I'm missing the following required permissions to function properly in this server or channel:\\n```\\n{{.Perm}}```\\nCheck the permissions for the Text/Voice channel {{.Channel}}, but you may also need to re-invite me [here](https://add.automute.us)"
|
||||
"commands.help.subtitle" = "[View the Github Project](https://github.com/automuteus/automuteus) or [Join our Discord](https://discord.gg/ZkqZSWF)\\n\\nType `/help <command>` to see more details on a command!"
|
||||
"commands.help.title" = "AutoMuteUs Bot Commands:\\n"
|
||||
"commands.info.activegames" = "Active Games"
|
||||
"commands.info.creator" = "Creator"
|
||||
"commands.info.footer" = "{{.Version}}-{{.Commit}} | Shard {{.ID}}/{{.Num}}"
|
||||
@ -30,26 +30,26 @@
|
||||
"commands.link.nogamedata" = "No game data found for the color `{{.Color}}`"
|
||||
"commands.link.noplayer" = "No player in the current game was detected for {{.UserMention}}"
|
||||
"commands.link.success" = "Successfully linked {{.UserMention}} to an in-game player with the color: `{{.Color}}`"
|
||||
"commands.new.lockout" = "If I start any more games, Discord will lock me out, or throttle the games I'm running! 😦\nPlease try again in a few minutes, or consider AutoMuteUs Premium (`/premium info`)\nCurrent Games: {{.Games}}"
|
||||
"commands.new.lockout" = "If I start any more games, Discord will lock me out, or throttle the games I'm running! 😦\\nPlease try again in a few minutes, or consider AutoMuteUs Premium (`/premium info`)\\nCurrent Games: {{.Games}}"
|
||||
"commands.new.nochannel" = "Please join a voice channel before starting a match!"
|
||||
"commands.new.success" = "Click the following link to link your capture: \n <{{.hyperlink}}>\n\nDon't have the capture installed? Latest version [here]({{.downloadURL}})\n\nTo link your capture manually:"
|
||||
"commands.new.success" = "Click the following link to link your capture: \\n <{{.hyperlink}}>\\n\\nDon't have the capture installed? Latest version [here]({{.downloadURL}})\\n\\nTo link your capture manually:"
|
||||
"commands.new.success.code" = "Code"
|
||||
"commands.new.success.url" = "URL"
|
||||
"commands.no_permissions" = "Sorry, you don't have the required permissions to issue that command."
|
||||
"commands.privacy.info" = "AutoMuteUs privacy and data collection details.\nMore details [here](https://github.com/automuteus/automuteus/blob/master/PRIVACY.md)"
|
||||
"commands.privacy.opt.error" = "❌ I encountered an error changing your opt in/out status:\n`{{.Error}}`"
|
||||
"commands.privacy.info" = "AutoMuteUs privacy and data collection details.\\nMore details [here](https://github.com/automuteus/automuteus/v7/blob/master/PRIVACY.md)"
|
||||
"commands.privacy.opt.error" = "❌ I encountered an error changing your opt in/out status:\\n`{{.Error}}`"
|
||||
"commands.privacy.opt.success" = "✅ I successfully changed your opt in/out status"
|
||||
"commands.privacy.showme.cache" = "❗ Here's your cached in-game names:"
|
||||
"commands.privacy.showme.nocache" = "❌ I don't have any cached player names stored for you!"
|
||||
"commands.privacy.showme.optin" = "❗ You are opted **in** to data collection for game statistics"
|
||||
"commands.privacy.showme.optout" = "❌ You are opted **out** of data collection for game statistics, or you haven't played a game yet"
|
||||
"commands.stats.guild.reset.confirmation" = "⚠️**Are you sure?**⚠️\nDo you really want to reset the stats for **{{.Guild}}**?\nThis process cannot be undone!"
|
||||
"commands.stats.guild.reset.confirmation" = "⚠️**Are you sure?**⚠️\\nDo you really want to reset the stats for **{{.Guild}}**?\\nThis process cannot be undone!"
|
||||
"commands.stats.guild.reset.error" = "Encountered an error resetting the stats for this guild: {{.Error}}"
|
||||
"commands.stats.guild.reset.success" = "Successfully reset the stats for **{{.Guild}}**!"
|
||||
"commands.stats.reset.button.cancel" = "Cancel"
|
||||
"commands.stats.reset.button.proceed" = "Confirm"
|
||||
"commands.stats.reset.canceled" = "Operation has been canceled"
|
||||
"commands.stats.user.reset.confirmation" = "⚠️**Are you sure?**⚠️\nDo you really want to reset the stats for {{.User}}?\nThis process cannot be undone!"
|
||||
"commands.stats.user.reset.confirmation" = "⚠️**Are you sure?**⚠️\\nDo you really want to reset the stats for {{.User}}?\\nThis process cannot be undone!"
|
||||
"commands.stats.user.reset.error" = "Encountered an error resetting the stats for {{.User}}: {{.Error}}"
|
||||
"commands.stats.user.reset.notfound" = "Failed to gather user from message!"
|
||||
"commands.stats.user.reset.success" = "Successfully reset the stats for {{.User}}!"
|
||||
@ -57,7 +57,7 @@
|
||||
"commands.unlink.success" = "Successfully unlinked {{.UserMention}}"
|
||||
"discordGameState.ToEmojiEmbedFields.Unlinked" = "Unlinked"
|
||||
"eventHandler.gameOver.deleteMessageFooter" = "Deleting message {{.Mins}} mins from:"
|
||||
"eventHandler.gameOver.matchID" = "Game Over! View the match's stats using Match ID: `{{.MatchID}}`\n{{.Winners}}"
|
||||
"eventHandler.gameOver.matchID" = "Game Over! View the match's stats using Match ID: `{{.MatchID}}`\\n{{.Winners}}"
|
||||
"locale.language.name" = "English"
|
||||
"processplayer.error" = "Error in muting or deafening {{.User}}. Does the bot have permissions to mute/deafen users in {{.VoiceChannel}}?"
|
||||
"responses.gameStatsEmbed.NoPremium" = "Detailed match stats are only available for AutoMuteUs Premium users; type `/premium` to learn more"
|
||||
@ -79,7 +79,7 @@
|
||||
"responses.lobbyMetaEmbedFields.Region" = "🌎 REGION"
|
||||
"responses.lobbyMetaEmbedFields.RoomCode" = "🔒 ROOM CODE"
|
||||
"responses.lobbyMetaEmbedFields.VoiceChannel" = "Voice Channel"
|
||||
"responses.makeDescription.GameNotRunning" = "\n⚠ **Bot is Paused!** ⚠\n\n"
|
||||
"responses.makeDescription.GameNotRunning" = "\\n⚠ **Bot is Paused!** ⚠\\n\\n"
|
||||
"responses.matchStatsEmbed.Title" = "Game `{{.MatchID}}`"
|
||||
"responses.menuMessage.Linked.FooterText" = "(Enter a game lobby in Among Us to start the match)"
|
||||
"responses.menuMessage.Title" = "Main Menu"
|
||||
@ -87,14 +87,14 @@
|
||||
"responses.nonPremiumSetting.Desc" = "Sorry, but that setting is reserved for AutoMuteUs Premium users! See `/premium` for details"
|
||||
"responses.premiumInviteResponse.Title" = "Premium Bot Invites"
|
||||
"responses.premiumInviteResponse.desc" = "{{.Tier}} users have access to {{.Count}} Priority mute bots: invites provided below!"
|
||||
"responses.premiumInviteResponseNoAccess.desc" = "{{.Tier}} users don't have access to Priority mute bots!\nPlease type `/premium` to see more details about AutoMuteUs Premium"
|
||||
"responses.premiumInviteResponseNoAccess.desc" = "{{.Tier}} users don't have access to Priority mute bots!\\nPlease type `/premium` to see more details about AutoMuteUs Premium"
|
||||
"responses.premiumResponse.FastMute" = "🙊 Fast Mute/Deafen"
|
||||
"responses.premiumResponse.FastMuteDesc" = "Premium users get access to \"helper\" bots that make sure muting is fast!"
|
||||
"responses.premiumResponse.FreeDescription" = "Check out the cool things that Premium AutoMuteUs has to offer!\n\n[Get AutoMuteUs Premium]({{.BaseURL}}{{.GuildID}})\n"
|
||||
"responses.premiumResponse.FreeDescription" = "Check out the cool things that Premium AutoMuteUs has to offer!\\n\\n[Get AutoMuteUs Premium]({{.BaseURL}}{{.GuildID}})\\n"
|
||||
"responses.premiumResponse.Invites" = "View a list of Premium bots you can invite with `/premium invites`!"
|
||||
"responses.premiumResponse.PremiumDescription" = "Looks like you have AutoMuteUs **{{.Tier}}**{{.DaysString}}! Thanks for the support!\n\nBelow are some of the benefits you can customize with your Premium status!"
|
||||
"responses.premiumResponse.PremiumDescription" = "Looks like you have AutoMuteUs **{{.Tier}}**{{.DaysString}}! Thanks for the support!\\n\\nBelow are some of the benefits you can customize with your Premium status!"
|
||||
"responses.premiumResponse.PremiumDescriptionDaysRemaining" = " for another {{.Days}} days"
|
||||
"responses.premiumResponse.PremiumDescriptionExpired" = "Oh no! It looks like you used to have AutoMuteUs **{{.Tier}}**, but it **expired {{.Days}} days ago**! 😦\n\nPlease consider re-subscribing here: [Get AutoMuteUs Premium]({{.BaseURL}}{{.GuildID}})"
|
||||
"responses.premiumResponse.PremiumDescriptionExpired" = "Oh no! It looks like you used to have AutoMuteUs **{{.Tier}}**, but it **expired {{.Days}} days ago**! 😦\\n\\nPlease consider re-subscribing here: [Get AutoMuteUs Premium]({{.BaseURL}}{{.GuildID}})"
|
||||
"responses.premiumResponse.PriorityGameAccess" = "👑 Priority Game Access"
|
||||
"responses.premiumResponse.PriorityGameAccessDesc" = "If the Bot is under heavy load, Premium users will always be able to make new games!"
|
||||
"responses.premiumResponse.Settings" = "🛠 Special Settings"
|
||||
@ -103,10 +103,10 @@
|
||||
"responses.premiumResponse.Stats" = "📊 Game Stats and Leaderboards"
|
||||
"responses.premiumResponse.StatsDesc" = "Premium users have access to a full suite of player stats and leaderboards!"
|
||||
"responses.premiumResponse.Title" = "💎 AutoMuteUs Premium 💎"
|
||||
"responses.premiumResponse.TopGG" = "or\n[Vote for the Bot on top.gg](https://top.gg/bot/753795015830011944) for 12 Hours of Free Premium!\n(One time per user)\n\n"
|
||||
"responses.premiumResponse.Trial" = "You're currently on a TRIAL of AutoMuteUs Premium\n\n"
|
||||
"responses.premiumResponse.TopGG" = "or\\n[Vote for the Bot on top.gg](https://top.gg/bot/753795015830011944) for 12 Hours of Free Premium!\\n(One time per user)\\n\\n"
|
||||
"responses.premiumResponse.Trial" = "You're currently on a TRIAL of AutoMuteUs Premium\\n\\n"
|
||||
"responses.settingResponse.Description" = "Type `/settings <setting>` to change a setting from those listed below"
|
||||
"responses.settingResponse.PremiumNoThanks" = "The following settings are only for AutoMuteUs premium users.\nType `/premium` to learn more!"
|
||||
"responses.settingResponse.PremiumNoThanks" = "The following settings are only for AutoMuteUs premium users.\\nType `/premium` to learn more!"
|
||||
"responses.settingResponse.PremiumThanks" = "Thanks for being an AutoMuteUs Premium user!"
|
||||
"responses.settingResponse.Title" = "Settings"
|
||||
"responses.stats.Exiled" = "Exiled"
|
||||
@ -142,7 +142,7 @@
|
||||
"responses.userStatsEmbed.WorstTeammateServerCrewmate" = "Worst Crewmate Team"
|
||||
"responses.userStatsEmbed.WorstTeammateServerImpostor" = "Worst Impostor Team"
|
||||
"settings.ConstructEmbedForSetting.Fields.CurrentValue" = "Current Value"
|
||||
"settings.ConstructEmbedForSetting.StarterDesc" = "Type `/settings {{.Command}}` to view or change this setting.\n\n"
|
||||
"settings.ConstructEmbedForSetting.StarterDesc" = "Type `/settings {{.Command}}` to view or change this setting.\\n\\n"
|
||||
"settings.SettingAdminUserIDs.alreadyBotAdmin" = "{{.User}} was already a bot admin!"
|
||||
"settings.SettingAdminUserIDs.clearAdmins" = "Clearing all AdminUserIDs!"
|
||||
"settings.SettingAdminUserIDs.newBotAdmin" = "{{.User}} is now a bot admin!"
|
||||
@ -154,7 +154,7 @@
|
||||
"settings.SettingAutoRefresh.Unrecognized" = "{{.Arg}} is not a true/false value. See `/settings auto-refresh` for usage"
|
||||
"settings.SettingDelays.Phase.UNINITIALIZED" = "I don't know what `{{.PhaseName}}` is. The list of game phases are `Lobby`, `Tasks` and `Discussion`."
|
||||
"settings.SettingDelays.delayBetweenPhases" = "Currently, the delay when passing from `{{.PhaseA}}` to `{{.PhaseB}}` is {{.OldDelay}}."
|
||||
"settings.SettingDelays.missingPhases" = "The list of game phases are `Lobby`, `Tasks` and `Discussion`.\nYou need to type both phases the game is transitioning from and to to change the delay."
|
||||
"settings.SettingDelays.missingPhases" = "The list of game phases are `Lobby`, `Tasks` and `Discussion`.\\nYou need to type both phases the game is transitioning from and to to change the delay."
|
||||
"settings.SettingDelays.setDelayBetweenPhases" = "The delay when passing from `{{.PhaseA}}` to `{{.PhaseB}}` changed from {{.OldDelay}} to {{.NewDelay}}."
|
||||
"settings.SettingDelays.wrongNumber" = "`{{.Number}}` is not a valid number! Please try again"
|
||||
"settings.SettingDisplayRoomCode.AlwaysOrNever" = "From now on, I will {{.Arg}} display the room code in the message"
|
||||
@ -163,7 +163,7 @@
|
||||
"settings.SettingLanguage.notFound" = "Language not found! Available language codes: {{.Langs}}"
|
||||
"settings.SettingLanguage.notLoaded" = "Localization files were not loaded! {{.Langs}}"
|
||||
"settings.SettingLanguage.set" = "Localization is set to `{{.LangCode}}`"
|
||||
"settings.SettingLanguage.set.needsTranslations" = "Localization is set to `{{.LangCode}}`, but it looks like the translations aren't complete!\n\nHelp us translate the bot [here](https://automuteus.crowdin.com/)!"
|
||||
"settings.SettingLanguage.set.needsTranslations" = "Localization is set to `{{.LangCode}}`, but it looks like the translations aren't complete!\\n\\nHelp us translate the bot [here](https://automuteus.crowdin.com/)!"
|
||||
"settings.SettingLanguage.tooShort" = "Sorry, the language code is short. Available language codes: {{.Langs}}."
|
||||
"settings.SettingLeaderboardMention.False" = "From now on, I'll use player nicknames/usernames in the leaderboard"
|
||||
"settings.SettingLeaderboardMention.True" = "From now on, I'll mention players directly in the leaderboard"
|
||||
@ -182,7 +182,7 @@
|
||||
"settings.SettingMatchSummaryChannel.invalidChannelID" = "{{.channelID}} is not a valid text channel ID or mention!"
|
||||
"settings.SettingMatchSummaryChannel.withChannelID" = "Match Summary text channel ID changed to {{.channelID}}!"
|
||||
"settings.SettingMuteSpectators.false_muteSpectators" = "I will no longer mute spectators like dead players"
|
||||
"settings.SettingMuteSpectators.true_noMuteSpectators" = "I will now mute spectators just like dead players. \n**Note, this can cause delays or slowdowns when not self-hosting, or using a Premium worker bot!**"
|
||||
"settings.SettingMuteSpectators.true_noMuteSpectators" = "I will now mute spectators just like dead players. \\n**Note, this can cause delays or slowdowns when not self-hosting, or using a Premium worker bot!**"
|
||||
"settings.SettingPermissionRoleIDs.alreadyBotOperator" = "That role was already a bot operator!"
|
||||
"settings.SettingPermissionRoleIDs.clearRoles" = "Clearing all PermissionRoleIDs!"
|
||||
"settings.SettingPermissionRoleIDs.newBotOperator" = "I successfully added that role as bot operators!"
|
||||
|
44
main.go
44
main.go
@ -5,10 +5,9 @@ import (
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/discord/command"
|
||||
"github.com/automuteus/automuteus/v7/discord/tokenprovider"
|
||||
"github.com/automuteus/automuteus/v7/metrics"
|
||||
"github.com/automuteus/automuteus/v7/internal/server"
|
||||
"github.com/automuteus/automuteus/v7/pkg/capture"
|
||||
"github.com/automuteus/automuteus/v7/pkg/locale"
|
||||
"github.com/automuteus/automuteus/v7/pkg/rediskey"
|
||||
storage2 "github.com/automuteus/automuteus/v7/pkg/storage"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"io"
|
||||
@ -181,7 +180,7 @@ func discordMainWrapper() error {
|
||||
sc := make(chan os.Signal, 1)
|
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
|
||||
|
||||
go metrics.StartHealthCheckServer("8080")
|
||||
go server.StartHealthCheckServer("8080")
|
||||
|
||||
topGGToken := os.Getenv("TOP_GG_TOKEN")
|
||||
|
||||
@ -223,14 +222,13 @@ func discordMainWrapper() error {
|
||||
}
|
||||
tokenProvider.PopulateAndStartSessions(extraTokens)
|
||||
// indicate to Kubernetes that we're ready to start receiving traffic
|
||||
metrics.GlobalReady = true
|
||||
server.GlobalReady = true
|
||||
|
||||
go bots[0].SetVersionAndCommit(version, commit)
|
||||
|
||||
go bots[0].StartMetricsServer(os.Getenv("SCW_NODE_ID"))
|
||||
|
||||
// TODO this is ugly. Should make a proper cronjob to refresh the stats regularly
|
||||
go bots[0].StatsRefreshWorker(rediskey.TotalUsersExpiration)
|
||||
go bots[0].StartAPIServer("5000")
|
||||
|
||||
// empty string entry = global
|
||||
slashCommandGuildIds := []string{""}
|
||||
@ -321,37 +319,3 @@ func parseShards(str string, maxShards int) (shards, error) {
|
||||
}
|
||||
return shards, nil
|
||||
}
|
||||
|
||||
//router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// // TODO For any higher-sensitivity info in the future, this should properly identify the origin specifically
|
||||
// w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
// w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
|
||||
// w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length")
|
||||
//
|
||||
// broker.connectionsLock.RLock()
|
||||
// activeConns := len(broker.connections)
|
||||
// broker.connectionsLock.RUnlock()
|
||||
//
|
||||
// // default to listing active games in the last 15 mins
|
||||
// activeGames := rediskey.GetActiveGames(context.Background(), broker.client, 900)
|
||||
// version, commit := rediskey.GetVersionAndCommit(context.Background(), broker.client)
|
||||
// totalGuilds := rediskey.GetGuildCounter(context.Background(), broker.client)
|
||||
// totalUsers := rediskey.GetTotalUsers(context.Background(), broker.client)
|
||||
// totalGames := rediskey.GetTotalGames(context.Background(), broker.client)
|
||||
//
|
||||
// data := map[string]interface{}{
|
||||
// "version": version,
|
||||
// "commit": commit,
|
||||
// "totalGuilds": totalGuilds,
|
||||
// "activeConnections": activeConns,
|
||||
// "activeGames": activeGames,
|
||||
// "totalUsers": totalUsers,
|
||||
// "totalGames": totalGames,
|
||||
// }
|
||||
//
|
||||
// jsonBytes, err := json.Marshal(data)
|
||||
// if err != nil {
|
||||
// log.Println(err)
|
||||
// }
|
||||
// w.Write(jsonBytes)
|
||||
//})
|
||||
|
@ -1,66 +0,0 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/automuteus/automuteus/v7/pkg/premium"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserModify struct {
|
||||
UserID uint64 `json:"userID"`
|
||||
Mute bool `json:"mute"`
|
||||
Deaf bool `json:"deaf"`
|
||||
}
|
||||
|
||||
type UserModifyRequest struct {
|
||||
Premium premium.Tier `json:"premium"`
|
||||
Users []UserModify `json:"users"`
|
||||
}
|
||||
|
||||
type ModifyTask struct {
|
||||
GuildID uint64 `json:"guildID"`
|
||||
UserID uint64 `json:"userID"`
|
||||
Parameters PatchParams `json:"parameters"`
|
||||
TaskID string `json:"taskID"`
|
||||
}
|
||||
|
||||
const IDLength = 10
|
||||
|
||||
func NewModifyTask(guildID, userID uint64, params PatchParams) ModifyTask {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(fmt.Sprintf("%d", guildID)))
|
||||
h.Write([]byte(fmt.Sprintf("%d", userID)))
|
||||
h.Write([]byte(fmt.Sprintf("%d", time.Now().Unix())))
|
||||
return ModifyTask{
|
||||
GuildID: guildID,
|
||||
UserID: userID,
|
||||
Parameters: params,
|
||||
TaskID: hex.EncodeToString(h.Sum(nil))[0:IDLength],
|
||||
}
|
||||
}
|
||||
|
||||
type PatchParams struct {
|
||||
Deaf bool `json:"deaf"`
|
||||
Mute bool `json:"mute"`
|
||||
}
|
||||
|
||||
func ApplyMuteDeaf(sess *discordgo.Session, guildID, userID string, mute, deaf bool) error {
|
||||
p := PatchParams{
|
||||
Deaf: deaf,
|
||||
Mute: mute,
|
||||
}
|
||||
|
||||
_, err := sess.RequestWithBucketID("PATCH", discordgo.EndpointGuildMember(guildID, userID), p, discordgo.EndpointGuildMember(guildID, ""))
|
||||
return err
|
||||
}
|
||||
|
||||
// a response indicating how the mutes/deafens were issued, and if ratelimits occurred
|
||||
type MuteDeafenSuccessCounts struct {
|
||||
Worker int64 `json:"worker"`
|
||||
Capture int64 `json:"capture"`
|
||||
Official int64 `json:"official"`
|
||||
RateLimit int64 `json:"ratelimit"`
|
||||
}
|
@ -40,21 +40,3 @@ func RefreshTotalGames(ctx context.Context, client *redis.Client, pool *pgxpool.
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func IsGameInVoiceChannel(ctx context.Context, client *redis.Client, guildID, voiceChannelID string) (bool, error) {
|
||||
res, err := client.Exists(ctx, VoiceChannelPtr(guildID, voiceChannelID)).Result()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return res == 1, nil
|
||||
}
|
||||
|
||||
func IsGameInTextChannel(ctx context.Context, client *redis.Client, guildID, textChannelID string) (bool, error) {
|
||||
res, err := client.Exists(ctx, TextChannelPtr(guildID, textChannelID)).Result()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return res == 1, nil
|
||||
}
|
||||
|
@ -67,10 +67,6 @@ func GuildTokenLock(guildID, hToken string) string {
|
||||
return "automuteus:muterequest:lock:" + hToken + ":" + guildID
|
||||
}
|
||||
|
||||
func RoomCodesForConnCode(connCode string) string {
|
||||
return "automuteus:roomcode:" + connCode
|
||||
}
|
||||
|
||||
func CachedUserInfoOnGuild(userID, guildID string) string {
|
||||
return "automuteus:cache:userinfo:" + guildID + ":" + userID
|
||||
}
|
||||
|
Reference in New Issue
Block a user