diff --git a/EsefexApi/api/api.go b/EsefexApi/api/api.go
index a0d1cff..c766e9c 100644
--- a/EsefexApi/api/api.go
+++ b/EsefexApi/api/api.go
@@ -4,6 +4,7 @@ import (
"esefexapi/api/middleware"
"esefexapi/api/routes"
"esefexapi/audioplayer"
+ "esefexapi/clientnotifiy"
"esefexapi/db"
"esefexapi/service"
@@ -22,19 +23,21 @@ type HttpApi struct {
handlers *routes.RouteHandlers
mw *middleware.Middleware
a audioplayer.IAudioPlayer
- apiPort int
+ port int
cProto string
+ domain string
stop chan struct{}
ready chan struct{}
}
-func NewHttpApi(dbs *db.Databases, plr audioplayer.IAudioPlayer, ds *discordgo.Session, apiPort int, cProto string) *HttpApi {
+func NewHttpApi(dbs *db.Databases, plr audioplayer.IAudioPlayer, ds *discordgo.Session, apiPort int, cProto string, wsCN *clientnotifiy.WsClientNotifier, domain string) *HttpApi {
return &HttpApi{
- handlers: routes.NewRouteHandlers(dbs, plr, ds, cProto),
+ handlers: routes.NewRouteHandlers(dbs, plr, ds, cProto, wsCN),
mw: middleware.NewMiddleware(dbs, ds),
a: plr,
- apiPort: apiPort,
+ port: apiPort,
cProto: cProto,
+ domain: domain,
stop: make(chan struct{}, 1),
ready: make(chan struct{}),
}
@@ -67,10 +70,12 @@ func (api *HttpApi) run() {
router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./api/public/"))))
- log.Printf("Webserver started on port %d (http://localhost:%d)\n", api.apiPort, api.apiPort)
+ router.Handle("/api/ws", cors(auth(h.GetWs()))).Methods("GET")
+
+ log.Printf("Webserver started on port %d (%s)\n", api.port, api.domain)
// nolint:errcheck
- go http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", api.apiPort), router)
+ go http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", api.port), router)
close(api.ready)
<-api.stop
diff --git a/EsefexApi/api/middleware/auth.go b/EsefexApi/api/middleware/auth.go
index 78302c4..fca4570 100644
--- a/EsefexApi/api/middleware/auth.go
+++ b/EsefexApi/api/middleware/auth.go
@@ -29,8 +29,10 @@ func (m *Middleware) Auth(next http.Handler) http.Handler {
return
}
+ userID := Ouser.Unwrap().ID
+
// Inject the user into the request context
- ctx := context.WithValue(r.Context(), "user", Ouser)
+ ctx := context.WithValue(r.Context(), "user", userID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
diff --git a/EsefexApi/api/public/simpleui/index.html b/EsefexApi/api/public/simpleui/index.html
index f05ac27..2e23b7e 100644
--- a/EsefexApi/api/public/simpleui/index.html
+++ b/EsefexApi/api/public/simpleui/index.html
@@ -4,7 +4,7 @@
Esefex Simple UI
-
+
diff --git a/EsefexApi/api/public/simpleui/index.js b/EsefexApi/api/public/simpleui/index.js
index f205124..ca853ce 100644
--- a/EsefexApi/api/public/simpleui/index.js
+++ b/EsefexApi/api/public/simpleui/index.js
@@ -1,4 +1,18 @@
async function init() {
+ // create a websocket connection to the server
+ let socket = new WebSocket(`ws://${window.location.host}/api/ws`);
+ socket.onopen = () => {
+ console.log('websocket connection established');
+ };
+ socket.addEventListener('message', async (event) => {
+ if (event.data != 'update') {
+ return;
+ }
+
+ // reload the page
+ window.location.reload();
+ });
+
const soundsDiv = document.getElementById('sounds');
let guildRequest = await fetch('/api/guild', {
diff --git a/EsefexApi/api/routes/getws.go b/EsefexApi/api/routes/getws.go
new file mode 100644
index 0000000..20fb3d6
--- /dev/null
+++ b/EsefexApi/api/routes/getws.go
@@ -0,0 +1,29 @@
+package routes
+
+import (
+ "esefexapi/types"
+ "log"
+ "net/http"
+
+ "github.com/gorilla/websocket"
+)
+
+var wsUpgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+}
+
+// api/ws
+func (h *RouteHandlers) GetWs() http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ userID := r.Context().Value("user").(types.UserID)
+
+ conn, err := wsUpgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Printf("Error upgrading websocket: %v", err)
+ return
+ }
+
+ h.wsCN.AddConnection(userID, conn)
+ })
+}
diff --git a/EsefexApi/api/routes/routes.go b/EsefexApi/api/routes/routes.go
index a3dafdd..8ab9627 100644
--- a/EsefexApi/api/routes/routes.go
+++ b/EsefexApi/api/routes/routes.go
@@ -2,6 +2,7 @@ package routes
import (
"esefexapi/audioplayer"
+ "esefexapi/clientnotifiy"
"esefexapi/db"
"github.com/bwmarrin/discordgo"
@@ -11,14 +12,16 @@ type RouteHandlers struct {
dbs *db.Databases
a audioplayer.IAudioPlayer
ds *discordgo.Session
+ wsCN *clientnotifiy.WsClientNotifier
cProto string
}
-func NewRouteHandlers(dbs *db.Databases, a audioplayer.IAudioPlayer, ds *discordgo.Session, cProto string) *RouteHandlers {
+func NewRouteHandlers(dbs *db.Databases, a audioplayer.IAudioPlayer, ds *discordgo.Session, cProto string, wsCN *clientnotifiy.WsClientNotifier) *RouteHandlers {
return &RouteHandlers{
a: a,
dbs: dbs,
ds: ds,
cProto: cProto,
+ wsCN: wsCN,
}
}
diff --git a/EsefexApi/bot/bot.go b/EsefexApi/bot/bot.go
index 5dbef1a..b8b158b 100644
--- a/EsefexApi/bot/bot.go
+++ b/EsefexApi/bot/bot.go
@@ -2,6 +2,7 @@ package bot
import (
"esefexapi/bot/commands"
+ "esefexapi/clientnotifiy"
"esefexapi/db"
"esefexapi/service"
@@ -16,14 +17,16 @@ var _ service.IService = &DiscordBot{}
type DiscordBot struct {
ds *discordgo.Session
cmdh *commands.CommandHandlers
+ cn clientnotifiy.IClientNotifier
stop chan struct{}
ready chan struct{}
}
-func NewDiscordBot(ds *discordgo.Session, dbs *db.Databases, domain string) *DiscordBot {
+func NewDiscordBot(ds *discordgo.Session, dbs *db.Databases, domain string, cn clientnotifiy.IClientNotifier) *DiscordBot {
return &DiscordBot{
ds: ds,
- cmdh: commands.NewCommandHandlers(ds, dbs, domain),
+ cmdh: commands.NewCommandHandlers(ds, dbs, domain, cn),
+ cn: cn,
stop: make(chan struct{}, 1),
ready: make(chan struct{}),
}
@@ -40,6 +43,7 @@ func (b *DiscordBot) run() {
ready := b.WaitReady()
b.cmdh.RegisterComandHandlers()
+ b.RegisterClientUpdateHandlers()
err := ds.Open()
if err != nil {
diff --git a/EsefexApi/bot/clientupdate.go b/EsefexApi/bot/clientupdate.go
new file mode 100644
index 0000000..29c0516
--- /dev/null
+++ b/EsefexApi/bot/clientupdate.go
@@ -0,0 +1,27 @@
+package bot
+
+import (
+ "esefexapi/types"
+ "log"
+
+ "github.com/bwmarrin/discordgo"
+)
+
+func (b *DiscordBot) RegisterClientUpdateHandlers() {
+ b.ds.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) {
+ err := b.cn.UpdateNotificationUsers()
+ if err != nil {
+ log.Printf("Error notifying clients: %+v", err)
+ }
+ })
+
+ b.ds.AddHandler(func(s *discordgo.Session, r *discordgo.VoiceStateUpdate) {
+ userID := types.UserID(r.UserID)
+
+ err := b.cn.UpdateNotificationUsers(userID)
+ if err != nil {
+ log.Printf("Error notifying clients: %+v", err)
+ }
+ })
+
+}
diff --git a/EsefexApi/bot/commands/cmdhashstore/cmdhashstore.go b/EsefexApi/bot/commands/cmdhashstore/cmdhashstore.go
index 5afeb1b..ea9fd2a 100644
--- a/EsefexApi/bot/commands/cmdhashstore/cmdhashstore.go
+++ b/EsefexApi/bot/commands/cmdhashstore/cmdhashstore.go
@@ -4,9 +4,11 @@ import (
"esefexapi/util"
"io"
"os"
+
+ "github.com/pkg/errors"
)
-type CommandHashStore interface {
+type ICommandHashStore interface {
GetCommandHash() (string, error)
SetCommandHash(hash string) error
}
@@ -39,13 +41,13 @@ func (f *FileCmdHashStore) GetCommandHash() (string, error) {
func (f *FileCmdHashStore) SetCommandHash(hash string) error {
file, err := os.Create(f.FilePath)
if err != nil {
- return err
+ return errors.Wrap(err, "error creating file")
}
defer file.Close()
_, err = file.WriteString(hash)
if err != nil {
- return err
+ return errors.Wrap(err, "error writing to file")
}
return nil
diff --git a/EsefexApi/bot/commands/commands.go b/EsefexApi/bot/commands/commands.go
index 630c845..286ed66 100644
--- a/EsefexApi/bot/commands/commands.go
+++ b/EsefexApi/bot/commands/commands.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"esefexapi/bot/commands/cmdhandler"
"esefexapi/bot/commands/middleware"
+ "esefexapi/clientnotifiy"
"esefexapi/db"
"fmt"
"log"
@@ -29,16 +30,18 @@ type CommandHandlers struct {
dbs *db.Databases
domain string
mw *middleware.CommandMiddleware
+ cn clientnotifiy.IClientNotifier
Commands map[string]*discordgo.ApplicationCommand
Handlers map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate)
}
-func NewCommandHandlers(ds *discordgo.Session, dbs *db.Databases, domain string) *CommandHandlers {
+func NewCommandHandlers(ds *discordgo.Session, dbs *db.Databases, domain string, cn clientnotifiy.IClientNotifier) *CommandHandlers {
c := &CommandHandlers{
ds: ds,
dbs: dbs,
domain: domain,
mw: middleware.NewCommandMiddleware(dbs),
+ cn: cn,
Commands: map[string]*discordgo.ApplicationCommand{},
Handlers: map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){},
}
diff --git a/EsefexApi/bot/commands/sound.go b/EsefexApi/bot/commands/sound.go
index 475463a..cd0c900 100644
--- a/EsefexApi/bot/commands/sound.go
+++ b/EsefexApi/bot/commands/sound.go
@@ -103,6 +103,9 @@ func (c *CommandHandlers) SoundUpload(s *discordgo.Session, i *discordgo.Interac
return nil, errors.Wrap(err, "Error adding sound")
}
+ guildID := types.GuildID(i.GuildID)
+ c.cn.UpdateNotificationGuilds(guildID)
+
log.Printf("Uploaded sound effect %v to guild %v", uid.SoundID, i.GuildID)
return &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
diff --git a/EsefexApi/clientnotifiy/clientnotifiy.go b/EsefexApi/clientnotifiy/clientnotifiy.go
new file mode 100644
index 0000000..4d71e49
--- /dev/null
+++ b/EsefexApi/clientnotifiy/clientnotifiy.go
@@ -0,0 +1,124 @@
+package clientnotifiy
+
+import (
+ "esefexapi/types"
+ "esefexapi/util/dcgoutil"
+
+ "github.com/bwmarrin/discordgo"
+ "github.com/gorilla/websocket"
+ "github.com/pkg/errors"
+)
+
+type IClientNotifier interface {
+ // UpdateNotificationUsers notifies the clients that some data has been updated
+ // This should cause the client to refetch the data
+ // if users is empty, then all clients should be notified
+ // this function will handle the case where a user does not have any connections
+ UpdateNotificationUsers(users ...types.UserID) error
+ UpdateNotificationGuilds(guilds ...types.GuildID) error
+ UpdateNotificationChannels(channels ...types.ChannelID) error
+}
+
+var _ IClientNotifier = &WsClientNotifier{}
+
+// implements ClientNotifier
+type WsClientNotifier struct {
+ userConnections map[types.UserID][]*websocket.Conn
+ ds *discordgo.Session
+ stop chan struct{}
+ ready chan struct{}
+}
+
+func NewWsClientNotifier(ds *discordgo.Session) *WsClientNotifier {
+ return &WsClientNotifier{
+ userConnections: make(map[types.UserID][]*websocket.Conn),
+ ds: ds,
+ stop: make(chan struct{}),
+ ready: make(chan struct{}),
+ }
+}
+
+// UpdateNotificationChannels implements IClientNotifier.
+func (w *WsClientNotifier) UpdateNotificationChannels(channels ...types.ChannelID) error {
+ for _, channel := range channels {
+ users, err := dcgoutil.ChannelUserIDs(w.ds, channel)
+ if err != nil {
+ return errors.Wrap(err, "error getting channel user ids")
+ }
+
+ err = w.UpdateNotificationUsers(users...)
+ if err != nil {
+ return errors.Wrap(err, "error updating notification")
+ }
+ }
+
+ return nil
+}
+
+// UpdateNotificationGuilds implements IClientNotifier.
+func (w *WsClientNotifier) UpdateNotificationGuilds(guilds ...types.GuildID) error {
+ for _, guild := range guilds {
+ users, err := dcgoutil.GuildUserIDs(w.ds, guild)
+ if err != nil {
+ return errors.Wrap(err, "error getting channel user ids")
+ }
+
+ err = w.UpdateNotificationUsers(users...)
+ if err != nil {
+ return errors.Wrap(err, "error updating notification")
+ }
+ }
+
+ return nil
+}
+
+func (w *WsClientNotifier) UpdateNotificationUsers(users ...types.UserID) error {
+ if len(users) == 0 {
+ for k := range w.userConnections {
+ err := w.writeUpdate(k)
+ if err != nil {
+ return errors.Wrap(err, "error writing update")
+ }
+ }
+ return nil
+ }
+
+ for _, user := range users {
+ if _, ok := w.userConnections[user]; !ok {
+ continue
+ }
+
+ err := w.writeUpdate(user)
+ if err != nil {
+ return errors.Wrap(err, "error writing update")
+ }
+ }
+ return nil
+}
+
+func (w *WsClientNotifier) writeUpdate(user types.UserID) error {
+ var causedError error = nil
+
+ for _, conn := range w.userConnections[user] {
+ err := conn.WriteMessage(websocket.TextMessage, []byte("update"))
+ if err != nil {
+ conn.Close()
+ w.RemoveConnection(user, conn)
+ causedError = errors.Wrap(err, "error writing message to websocket, removing connection")
+ }
+ }
+ return causedError
+}
+
+func (w *WsClientNotifier) AddConnection(user types.UserID, conn *websocket.Conn) {
+ w.userConnections[user] = append(w.userConnections[user], conn)
+}
+
+func (w *WsClientNotifier) RemoveConnection(user types.UserID, conn *websocket.Conn) {
+ for i, c := range w.userConnections[user] {
+ if c == conn {
+ w.userConnections[user] = append(w.userConnections[user][:i], w.userConnections[user][i+1:]...)
+ break
+ }
+ }
+}
diff --git a/EsefexApi/cmd/testing/websocket/websocket.go b/EsefexApi/cmd/testing/websocket/websocket.go
new file mode 100644
index 0000000..964ea02
--- /dev/null
+++ b/EsefexApi/cmd/testing/websocket/websocket.go
@@ -0,0 +1,41 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+
+ "github.com/gorilla/websocket"
+)
+
+func main() {
+ log.Println("Starting server on port 8080")
+
+ http.HandleFunc("/", index)
+ http.HandleFunc("/ws", ws)
+ http.ListenAndServe(":8080", nil)
+}
+
+var upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+}
+
+func index(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "Hello World")
+}
+
+func ws(w http.ResponseWriter, r *http.Request) {
+ conn, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ panic(err)
+ }
+
+ for {
+ _, msg, err := conn.ReadMessage()
+ if err != nil {
+ panic(err)
+ }
+ conn.WriteMessage(websocket.TextMessage, msg)
+ }
+}
diff --git a/EsefexApi/db/db.go b/EsefexApi/db/db.go
index ed0b518..fe95c5e 100644
--- a/EsefexApi/db/db.go
+++ b/EsefexApi/db/db.go
@@ -12,8 +12,8 @@ type Databases struct {
SoundDB sounddb.ISoundDB
UserDB userdb.IUserDB
LinkTokenStore linktokenstore.ILinkTokenStore
- PermissionDB permissiondb.PermissionDB
- CmdHashStore cmdhashstore.CommandHashStore
+ PermissionDB permissiondb.IPermissionDB
+ CmdHashStore cmdhashstore.ICommandHashStore
}
// func CreateDatabases(cfg *config.Config, ds *discordgo.Session) (*Databases, error) {
diff --git a/EsefexApi/go.mod b/EsefexApi/go.mod
index 62625c6..c5a779c 100644
--- a/EsefexApi/go.mod
+++ b/EsefexApi/go.mod
@@ -27,12 +27,13 @@ require (
github.com/rogpeppe/go-internal v1.11.0 // indirect
go.mongodb.org/mongo-driver v1.13.1 // indirect
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect
+ golang.org/x/net v0.17.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
require (
- github.com/gorilla/websocket v1.4.2 // indirect
+ github.com/gorilla/websocket v1.5.1 // indirect
github.com/jedib0t/go-pretty v4.3.0+incompatible
github.com/jedib0t/go-pretty/v6 v6.5.3
github.com/pkg/errors v0.9.1
diff --git a/EsefexApi/go.sum b/EsefexApi/go.sum
index 32564ad..db08e00 100644
--- a/EsefexApi/go.sum
+++ b/EsefexApi/go.sum
@@ -18,6 +18,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
github.com/jedib0t/go-pretty/v6 v6.5.3 h1:GIXn6Er/anHTkVUoufs7ptEvxdD6KIhR7Axa2wYCPF0=
@@ -75,6 +77,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/EsefexApi/main.go b/EsefexApi/main.go
index 11ace9c..d15de58 100644
--- a/EsefexApi/main.go
+++ b/EsefexApi/main.go
@@ -5,6 +5,7 @@ import (
"esefexapi/audioplayer/discordplayer"
"esefexapi/bot"
"esefexapi/bot/commands/cmdhashstore"
+ "esefexapi/clientnotifiy"
"esefexapi/config"
"esefexapi/db"
"esefexapi/linktokenstore/memorylinktokenstore"
@@ -69,8 +70,10 @@ func main() {
botT := time.Duration(cfg.Bot.Timeout * float32(time.Minute))
plr := discordplayer.NewDiscordPlayer(ds, dbs, cfg.Bot.UseTimeouts, botT)
- api := api.NewHttpApi(dbs, plr, ds, cfg.HttpApi.Port, cfg.HttpApi.CustomProtocol)
- bot := bot.NewDiscordBot(ds, dbs, domain)
+ wsCN := clientnotifiy.NewWsClientNotifier(ds)
+
+ api := api.NewHttpApi(dbs, plr, ds, cfg.HttpApi.Port, cfg.HttpApi.CustomProtocol, wsCN, domain)
+ bot := bot.NewDiscordBot(ds, dbs, domain, wsCN)
log.Println("Components bootstraped, starting...")
diff --git a/EsefexApi/permissiondb/filepermisssiondb/filepermisssiondb.go b/EsefexApi/permissiondb/filepermisssiondb/filepermisssiondb.go
index 3d7ca8a..5b781ce 100644
--- a/EsefexApi/permissiondb/filepermisssiondb/filepermisssiondb.go
+++ b/EsefexApi/permissiondb/filepermisssiondb/filepermisssiondb.go
@@ -14,7 +14,7 @@ import (
"github.com/pkg/errors"
)
-var _ permissiondb.PermissionDB = &FilePermissionDB{}
+var _ permissiondb.IPermissionDB = &FilePermissionDB{}
type FilePermissionDB struct {
file *os.File
diff --git a/EsefexApi/permissiondb/permissiondb.go b/EsefexApi/permissiondb/permissiondb.go
index 2204e5c..902b044 100644
--- a/EsefexApi/permissiondb/permissiondb.go
+++ b/EsefexApi/permissiondb/permissiondb.go
@@ -5,7 +5,7 @@ import (
"esefexapi/types"
)
-type PermissionDB interface {
+type IPermissionDB interface {
GetUser(guild types.GuildID, userID types.UserID) (permissions.Permissions, error)
GetRole(guild types.GuildID, roleID types.RoleID) (permissions.Permissions, error)
GetChannel(guild types.GuildID, channelID types.ChannelID) (permissions.Permissions, error)
diff --git a/EsefexApi/util/dcgoutil/dcgoutil.go b/EsefexApi/util/dcgoutil/dcgoutil.go
index de03b7f..b8a92b2 100644
--- a/EsefexApi/util/dcgoutil/dcgoutil.go
+++ b/EsefexApi/util/dcgoutil/dcgoutil.go
@@ -167,3 +167,31 @@ func UserIsOwner(ds *discordgo.Session, guildID types.GuildID, userID types.User
return guild.OwnerID == userID.String(), nil
}
+
+func ChannelUserIDs(ds *discordgo.Session, channelID types.ChannelID) ([]types.UserID, error) {
+ channel, err := ds.State.Channel(channelID.String())
+ if err != nil {
+ return nil, errors.Wrap(err, "Error getting channel members")
+ }
+
+ userIDs := []types.UserID{}
+ for _, member := range channel.Members {
+ userIDs = append(userIDs, types.UserID(member.UserID))
+ }
+
+ return userIDs, nil
+}
+
+func GuildUserIDs(ds *discordgo.Session, guildID types.GuildID) ([]types.UserID, error) {
+ guild, err := ds.State.Guild(guildID.String())
+ if err != nil {
+ return nil, errors.Wrap(err, "Error getting guild members")
+ }
+
+ userIDs := []types.UserID{}
+ for _, member := range guild.Members {
+ userIDs = append(userIDs, types.UserID(member.User.ID))
+ }
+
+ return userIDs, nil
+}