From 500effe8e451f79c30207b35241c5fe4f750dd79 Mon Sep 17 00:00:00 2001 From: Tadeusz Magura-Witkowski Date: Thu, 4 Dec 2025 12:06:40 +0100 Subject: [PATCH 1/6] MediaServer: Current functionality + MINIO support 42wim#2213 GH-39 --- gateway/gateway.go | 25 +++-- gateway/handlers.go | 75 ++------------ gateway/mediaserver.go | 215 +++++++++++++++++++++++++++++++++++++++++ go.mod | 47 ++++----- go.sum | 112 ++++++++++----------- 5 files changed, 316 insertions(+), 158 deletions(-) create mode 100644 gateway/mediaserver.go diff --git a/gateway/gateway.go b/gateway/gateway.go index 51d151a02f..8e4fa3bdb0 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -22,6 +22,7 @@ type Gateway struct { config.Config Router *Router + mediaServer mediaServer MyConfig *config.Gateway Bridges map[string]*bridge.Bridge Channels map[string]*config.ChannelInfo @@ -46,15 +47,25 @@ const apiProtocol = "api" func New(rootLogger *logrus.Logger, cfg *config.Gateway, r *Router) *Gateway { logger := rootLogger.WithFields(logrus.Fields{"prefix": "gateway"}) + mediaServer, err := createMediaServer(r.Config.BridgeValues(), rootLogger.WithField("prefix", "mediaserver")) + if err != nil { + logger.Errorf("Failed to configure media server for gateway: %#v", err) + } + + if mediaServer == nil { + logger.Warn("Media server is disabled") + } + cache, _ := lru.New(5000) gw := &Gateway{ - Channels: make(map[string]*config.ChannelInfo), - Message: r.Message, - Router: r, - Bridges: make(map[string]*bridge.Bridge), - Config: r.Config, - Messages: cache, - logger: logger, + Channels: make(map[string]*config.ChannelInfo), + Message: r.Message, + Router: r, + Bridges: make(map[string]*bridge.Bridge), + Config: r.Config, + Messages: cache, + logger: logger, + mediaServer: mediaServer, } if err := gw.AddConfig(cfg); err != nil { logger.Errorf("Failed to add configuration to gateway: %#v", err) diff --git a/gateway/handlers.go b/gateway/handlers.go index 44cefe4506..340f63ca49 100644 --- a/gateway/handlers.go +++ b/gateway/handlers.go @@ -1,16 +1,11 @@ package gateway import ( - "bytes" "crypto/sha1" //nolint:gosec "fmt" - "io/ioutil" - "net/http" - "os" "path/filepath" "regexp" "strings" - "time" "github.com/42wim/matterbridge/bridge" "github.com/42wim/matterbridge/bridge/config" @@ -73,8 +68,7 @@ func (gw *Gateway) handleFiles(msg *config.Message) { // If we don't have a attachfield or we don't have a mediaserver configured return if msg.Extra == nil || - (gw.BridgeValues().General.MediaServerUpload == "" && - gw.BridgeValues().General.MediaDownloadPath == "") { + gw.mediaServer == nil { return } @@ -92,78 +86,23 @@ func (gw *Gateway) handleFiles(msg *config.Message) { sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec - if gw.BridgeValues().General.MediaServerUpload != "" { - // Use MediaServerUpload. Upload using a PUT HTTP request and basicauth. - if err := gw.handleFilesUpload(&fi); err != nil { - gw.logger.Error(err) - continue - } - } else { - // Use MediaServerPath. Place the file on the current filesystem. - if err := gw.handleFilesLocal(&fi); err != nil { - gw.logger.Error(err) - continue - } + downloadURL, err := gw.mediaServer.handleFilesUpload(&fi) + if err != nil { + gw.logger.Error(err) + continue } // Download URL. - durl := gw.BridgeValues().General.MediaServerDownload + "/" + sha1sum + "/" + fi.Name - - gw.logger.Debugf("mediaserver download URL = %s", durl) + gw.logger.Debugf("mediaserver download URL = %s", downloadURL) // We uploaded/placed the file successfully. Add the SHA and URL. extra := msg.Extra["file"][i].(config.FileInfo) - extra.URL = durl + extra.URL = downloadURL extra.SHA = sha1sum msg.Extra["file"][i] = extra } } -// handleFilesUpload uses MediaServerUpload configuration to upload the file. -// Returns error on failure. -func (gw *Gateway) handleFilesUpload(fi *config.FileInfo) error { - client := &http.Client{ - Timeout: time.Second * 5, - } - // Use MediaServerUpload. Upload using a PUT HTTP request and basicauth. - sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec - url := gw.BridgeValues().General.MediaServerUpload + "/" + sha1sum + "/" + fi.Name - - req, err := http.NewRequest("PUT", url, bytes.NewReader(*fi.Data)) - if err != nil { - return fmt.Errorf("mediaserver upload failed, could not create request: %#v", err) - } - - gw.logger.Debugf("mediaserver upload url: %s", url) - - req.Header.Set("Content-Type", "binary/octet-stream") - _, err = client.Do(req) - if err != nil { - return fmt.Errorf("mediaserver upload failed, could not Do request: %#v", err) - } - return nil -} - -// handleFilesLocal use MediaServerPath configuration, places the file on the current filesystem. -// Returns error on failure. -func (gw *Gateway) handleFilesLocal(fi *config.FileInfo) error { - sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec - dir := gw.BridgeValues().General.MediaDownloadPath + "/" + sha1sum - err := os.Mkdir(dir, os.ModePerm) - if err != nil && !os.IsExist(err) { - return fmt.Errorf("mediaserver path failed, could not mkdir: %s %#v", err, err) - } - - path := dir + "/" + fi.Name - gw.logger.Debugf("mediaserver path placing file: %s", path) - - err = ioutil.WriteFile(path, *fi.Data, os.ModePerm) - if err != nil { - return fmt.Errorf("mediaserver path failed, could not writefile: %s %#v", err, err) - } - return nil -} - // ignoreEvent returns true if we need to ignore this event for the specified destination bridge. func (gw *Gateway) ignoreEvent(event string, dest *bridge.Bridge) bool { switch event { diff --git a/gateway/mediaserver.go b/gateway/mediaserver.go new file mode 100644 index 0000000000..7ebd59cdbb --- /dev/null +++ b/gateway/mediaserver.go @@ -0,0 +1,215 @@ +package gateway + +import ( + "bytes" + "context" + "crypto/sha1" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "os" + "strconv" + "strings" + "time" + + "github.com/42wim/matterbridge/bridge/config" + "github.com/sirupsen/logrus" + + "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/credentials" +) + +type mediaServer interface { + handleFilesUpload(fi *config.FileInfo) (string, error) +} + +type commonMediaServer struct { + logger *logrus.Entry +} + +type httpPutMediaServer struct { + commonMediaServer + + httpUploadPath string + httpDownloadPrefix string +} + +type localMediaServer struct { + commonMediaServer + + localPath string + httpDownloadPrefix string +} + +type minioMediaServer struct { + commonMediaServer + + minio *minio.Client + bucket string + uploadPrefix string + downloadPrefix string + + ctx context.Context +} + +var _ mediaServer = (*httpPutMediaServer)(nil) +var _ mediaServer = (*localMediaServer)(nil) +var _ mediaServer = (*minioMediaServer)(nil) + +func createMediaServer(bg *config.BridgeValues, logger *logrus.Entry) (mediaServer, error) { + if bg.General.MediaServerUpload == "" && bg.General.MediaDownloadPath == "" { + return nil, nil // we don't have a attachfield or we don't have a mediaserver configured return + } + + if bg.General.MediaServerUpload != "" { + parsed, err := url.Parse(bg.General.MediaServerUpload) + if err != nil { + return nil, fmt.Errorf("failed parsing mediaServerUpload URL: %w", err) + } + + if parsed.Scheme == "http" || parsed.Scheme == "https" { + return &httpPutMediaServer{ + commonMediaServer: commonMediaServer{ + logger: logger, + }, + + httpUploadPath: bg.General.MediaServerUpload, + httpDownloadPrefix: bg.General.MediaServerDownload, + }, nil + } + + if parsed.Scheme == "minio" { + optionsFromURL := parsed.Query() + secretAccessKey, _ := parsed.User.Password() + pathSplitted := strings.Split(strings.TrimLeft(parsed.Path, "/"), "/") + + useSSL, err := strconv.ParseBool(optionsFromURL.Get("useSSL")) + if err != nil { + logger.Warn("error while parsing useSSL boolean, assuming false: ", err) + useSSL = false + } + + if len(pathSplitted) == 0 { + return nil, fmt.Errorf("no bucket specified") + } + + bucketName := pathSplitted[0] + uploadPrefix := strings.Join(pathSplitted[1:], "/") + + ctx := context.Background() + + minioClient, err := minio.New(parsed.Host, &minio.Options{ + Creds: credentials.NewStaticV4(parsed.User.Username(), secretAccessKey, ""), + Secure: useSSL, + }) + if err != nil { + return nil, fmt.Errorf("failed to initialize minio client: %w", err) + } + + logger.WithFields(logrus.Fields{ + "bucket": bucketName, + "uploadPrefix": uploadPrefix, + }).Debug("configured minio client") + + exist, err := minioClient.BucketExists(ctx, bucketName) + if err != nil { + return nil, fmt.Errorf("failed checking if bucket exists: %w", err) + } + if !exist { + return nil, fmt.Errorf("specified bucket does not exists") + } + + return &minioMediaServer{ + commonMediaServer: commonMediaServer{ + logger: logger, + }, + + ctx: ctx, + minio: minioClient, + + bucket: bucketName, + uploadPrefix: uploadPrefix, + downloadPrefix: bg.General.MediaServerDownload, + }, nil + } + + return nil, fmt.Errorf("unknown schema (protocol) for mediaServerUpload: '%s'", parsed.Scheme) + } + + if bg.General.MediaDownloadPath != "" { + return &localMediaServer{ + commonMediaServer: commonMediaServer{ + logger: logger, + }, + + localPath: bg.General.MediaDownloadPath, + httpDownloadPrefix: bg.General.MediaServerDownload, + }, nil + } + + return nil, nil // never reached +} + +// handleFilesUpload which uses MediaServerUpload configuration to upload the file via HTTP PUT request. +// Returns error on failure. +func (h *httpPutMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { + client := &http.Client{ + Timeout: time.Second * 5, + } + // Use MediaServerUpload. Upload using a PUT HTTP request and basicauth. + sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec + url := h.httpUploadPath + "/" + sha1sum + "/" + fi.Name + + req, err := http.NewRequest("PUT", url, bytes.NewReader(*fi.Data)) + if err != nil { + return "", fmt.Errorf("mediaserver upload failed, could not create request: %#v", err) + } + + h.logger.Debugf("mediaserver upload url: %s", url) + + req.Header.Set("Content-Type", "binary/octet-stream") + _, err = client.Do(req) + if err != nil { + return "", fmt.Errorf("mediaserver upload failed, could not Do request: %#v", err) + } + + return h.httpDownloadPrefix + "/" + sha1sum + "/" + fi.Name, nil +} + +// handleFilesUpload which uses MediaServerPath configuration, places the file on the current filesystem. +// Returns error on failure. +func (h *localMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { + sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec + dir := h.localPath + "/" + sha1sum + err := os.Mkdir(dir, os.ModePerm) + if err != nil && !os.IsExist(err) { + return "", fmt.Errorf("mediaserver path failed, could not mkdir: %s %#v", err, err) + } + + path := dir + "/" + fi.Name + h.logger.Debugf("mediaserver path placing file: %s", path) + + err = ioutil.WriteFile(path, *fi.Data, os.ModePerm) + if err != nil { + return "", fmt.Errorf("mediaserver path failed, could not writefile: %s %#v", err, err) + } + + return h.httpDownloadPrefix + "/" + sha1sum + "/" + fi.Name, nil +} + +// handleFilesUpload which uploads media to minio compatible server (S3) +// Returns error on failure. +func (h *minioMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { + sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] + url := h.uploadPrefix + "/" + sha1sum + "/" + fi.Name + objectSize := int64(len(*fi.Data)) // TODO: Using this, since we got this in memory anyway. Would be nicer to use fi.Size, but it is 0 + + info, err := h.minio.PutObject(h.ctx, h.bucket, url, bytes.NewReader(*fi.Data), objectSize, minio.PutObjectOptions{ContentType: "application/octet-stream"}) + if err != nil { + return "", fmt.Errorf("mediaserver putfile failed: %w", err) + } + + h.logger.Debugf("successfully uploaded %v, etag: %v", url, info.ETag) + return h.downloadPrefix + url, nil +} diff --git a/go.mod b/go.mod index d7114d6566..d568ea72ac 100644 --- a/go.mod +++ b/go.mod @@ -24,8 +24,10 @@ require ( github.com/matterbridge/matterclient v0.0.0-20240817214420-3d4c3aef3dc1 github.com/matterbridge/telegram-bot-api/v6 v6.5.0 github.com/mattermost/mattermost/server/public v0.1.6 + github.com/mattn/go-mastodon v0.0.10 github.com/mattn/godown v0.0.1 github.com/mdp/qrterminal v1.0.1 + github.com/minio/minio-go/v7 v7.0.97 github.com/mitchellh/mapstructure v1.5.0 github.com/nelsonken/gomf v0.0.0-20190423072027-c65cc0469e94 github.com/olahol/melody v1.2.1 @@ -37,39 +39,35 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/slack-go/slack v0.14.0 github.com/spf13/viper v1.19.0 - github.com/stretchr/testify v1.11.1 + github.com/stretchr/testify v1.9.0 github.com/vincent-petithory/dataurl v1.0.0 github.com/writeas/go-strip-markdown v2.0.1+incompatible github.com/xmppo/go-xmpp v0.2.18 github.com/yaegashi/msgraph.go v0.1.4 github.com/zfjagann/golang-ring v0.0.0-20220330170733-19bcea1b6289 - go.mau.fi/whatsmeow v0.0.0-20251116104239-3aca43070cd4 + go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7 golang.org/x/image v0.19.0 golang.org/x/oauth2 v0.22.0 - golang.org/x/text v0.31.0 + golang.org/x/text v0.30.0 gomod.garykim.dev/nc-talk v0.3.0 - google.golang.org/protobuf v1.36.10 + google.golang.org/protobuf v1.34.2 layeh.com/gumble v0.0.0-20221205141517-d1df60a3cc14 modernc.org/sqlite v1.32.0 - github.com/mattn/go-mastodon v0.0.10 ) require ( - github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/Benau/go_rlottie v0.0.0-20210807002906-98c1b2421989 // indirect github.com/Jeffail/gabs v1.4.0 // indirect github.com/apex/log v1.9.0 // indirect github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf // indirect - github.com/beeper/argo-go v1.1.2 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/coder/websocket v1.8.14 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect - github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect github.com/fatih/color v1.17.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect + github.com/go-ini/ini v1.67.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect @@ -83,16 +81,20 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/kettek/apng v0.0.0-20191108220231-414630eed80f // indirect - github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.2.11 // indirect + github.com/klauspost/crc32 v1.3.0 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 // indirect github.com/mattermost/logr/v2 v2.0.21 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/minio/crc64nvme v1.1.0 // indirect + github.com/minio/md5-simd v1.1.2 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/monaco-io/request v1.0.5 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect @@ -101,15 +103,14 @@ require ( github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 // indirect - github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect + github.com/philhofer/fwd v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rickb777/date v1.12.4 // indirect github.com/rickb777/plural v1.2.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rs/zerolog v1.34.0 // indirect + github.com/rs/zerolog v1.33.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 // indirect @@ -120,22 +121,22 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/tinylib/msgp v1.2.0 // indirect + github.com/tinylib/msgp v1.3.0 // indirect + github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/vektah/gqlparser/v2 v2.5.31 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wiggin77/merror v1.0.5 // indirect github.com/wiggin77/srslog v1.0.1 // indirect - go.mau.fi/libsignal v0.2.1 // indirect - go.mau.fi/util v0.9.3 // indirect + go.mau.fi/libsignal v0.1.1 // indirect + go.mau.fi/util v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.44.0 // indirect - golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 // indirect - golang.org/x/net v0.47.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect + golang.org/x/crypto v0.43.0 // indirect + golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect + golang.org/x/net v0.46.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/go.sum b/go.sum index b7518fedaf..1fe7a82090 100644 --- a/go.sum +++ b/go.sum @@ -16,19 +16,13 @@ github.com/Benau/go_rlottie v0.0.0-20210807002906-98c1b2421989/go.mod h1:aDWSWjs github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f h1:aUkwZDEMJIGRcWlSDifSLoKG37UCOH/DPeG52/xwois= github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f/go.mod h1:AQiQKKI/YIIctvDt3hI3c1S05/JXMM7v/sQcRd0paVE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= -github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c h1:4mIZQXKYBymQ9coA82nNyG/CjicMNLBZ8cPVrhNUM3g= github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c/go.mod h1:DNSFRLFDFIqm2+0aJzSOVfn25020vldM4SRqz6YtLgI= github.com/SevereCloud/vksdk/v2 v2.17.0 h1:Wll63JSuBTdE0L7+V/PMn9PyhLrWSWIjX76XpWbXTFw= github.com/SevereCloud/vksdk/v2 v2.17.0/go.mod h1:y3q3XAdqnQ2Wf0B+Wi7qNdqJc5ZZsz4ve+DoSQsrChk= -github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= -github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58/go.mod h1:YNfsMyWSs+h+PaYkxGeMVmVCX75Zj/pqdjbu12ciCYE= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= @@ -39,8 +33,6 @@ github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf h1 github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf/go.mod h1:POPnOeaYF7U9o3PjLTb9icRfEOxjBNLRXh9BLximJGM= github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= -github.com/beeper/argo-go v1.1.2 h1:UQI2G8F+NLfGTOmTUI0254pGKx/HUU/etbUGTJv91Fs= -github.com/beeper/argo-go v1.1.2/go.mod h1:M+LJAnyowKVQ6Rdj6XYGEn+qcVFkb3R/MUpqkGR0hM4= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -52,8 +44,6 @@ github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/d5/tengo/v2 v2.17.0 h1:BWUN9NoJzw48jZKiYDXDIF3QrIVZRm1uV1gTzeZ2lqM= @@ -68,8 +58,6 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a h1:etIrTD8BQqzColk9nKRusM9um5+1q0iOEJLqfBMIK64= github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a/go.mod h1:emQhSYTXqB0xxjLITTw4EaWZ+8IIQYw+kx9GqNUKdLg= -github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg= -github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -90,6 +78,8 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk= github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -121,8 +111,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gops v0.3.27 h1:BDdWfedShsBbeatZ820oA4DbVOC8yJ4NI8xAlDFWfgI= @@ -180,8 +170,13 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/kettek/apng v0.0.0-20191108220231-414630eed80f h1:dnCYnTSltLuPMfc7dMrkz2uBUcEf/OFBR8yRh3oRT98= github.com/kettek/apng v0.0.0-20191108220231-414630eed80f/go.mod h1:x78/VRQYKuCftMWS0uK5e+F5RJ7S4gSlESRWI0Prl6Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU= +github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM= +github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -228,9 +223,8 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= @@ -244,8 +238,6 @@ github.com/mattn/go-mastodon v0.0.10/go.mod h1:YBofeqh7G6s787787NQR8erBYz6fKDu+K github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= -github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/godown v0.0.1 h1:39uk50ufLVQFs0eapIJVX5fCS74a1Fs2g5f1MVqIHdE= github.com/mattn/godown v0.0.1/go.mod h1:/ivCKurgV/bx6yqtP/Jtc2Xmrv3beCYBvlfAUl4X5g4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -255,6 +247,12 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyex github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/minio/crc64nvme v1.1.0 h1:e/tAguZ+4cw32D+IO/8GSf5UVr9y+3eJcxZI2WOO/7Q= +github.com/minio/crc64nvme v1.1.0/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg= +github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= +github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= +github.com/minio/minio-go/v7 v7.0.97 h1:lqhREPyfgHTB/ciX8k2r8k0D93WaFqxbJX36UZq5occ= +github.com/minio/minio-go/v7 v7.0.97/go.mod h1:re5VXuo0pwEtoNLsNuSr0RrLfT/MBtohwdaSmPPSRSk= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -291,10 +289,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 h1:QTvNkZ5ylY0PGgA+Lih+GdboMLY/G9SEGLMEGVjTVA4= -github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= -github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -318,10 +314,11 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= -github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= -github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= @@ -332,8 +329,6 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 h1:zwQ1HBo5FYwn1ksMd19qBCKO8JAWE9wmHivEpkw/DvE= github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI= github.com/shazow/ssh-chat v1.10.1 h1:ePS+ngEYqm+yUuXegDPutysqLV2WoI22XDOeRgI6CE0= @@ -395,14 +390,13 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= -github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= +github.com/tinylib/msgp v1.3.0 h1:ULuf7GPooDaIlbyvgAxBV/FI7ynli6LZ1/nVUNu+0ww= +github.com/tinylib/msgp v1.3.0/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= @@ -416,8 +410,6 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/vektah/gqlparser/v2 v2.5.31 h1:YhWGA1mfTjID7qJhd1+Vxhpk5HTgydrGU9IgkWBTJ7k= -github.com/vektah/gqlparser/v2 v2.5.31/go.mod h1:c1I28gSOVNzlfc4WuDlqU7voQnsqI6OG2amkBAFmgts= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= @@ -443,12 +435,12 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zfjagann/golang-ring v0.0.0-20220330170733-19bcea1b6289 h1:dEdcEes8Aki8XrgZFyrZvtazFlW4U7eNvX9NuyFJAtQ= github.com/zfjagann/golang-ring v0.0.0-20220330170733-19bcea1b6289/go.mod h1:0MsIttMJIF/8Y7x0XjonJP7K99t3sR6bjj4m5S4JmqU= -go.mau.fi/libsignal v0.2.1 h1:vRZG4EzTn70XY6Oh/pVKrQGuMHBkAWlGRC22/85m9L0= -go.mau.fi/libsignal v0.2.1/go.mod h1:iVvjrHyfQqWajOUaMEsIfo3IqgVMrhWcPiiEzk7NgoU= -go.mau.fi/util v0.9.3 h1:aqNF8KDIN8bFpFbybSk+mEBil7IHeBwlujfyTnvP0uU= -go.mau.fi/util v0.9.3/go.mod h1:krWWfBM1jWTb5f8NCa2TLqWMQuM81X7TGQjhMjBeXmQ= -go.mau.fi/whatsmeow v0.0.0-20251116104239-3aca43070cd4 h1:7hXdxCFs2Me4nypiWjdBNonaFrPfmYJvEtTOwLctSHU= -go.mau.fi/whatsmeow v0.0.0-20251116104239-3aca43070cd4/go.mod h1:5aYaEa3FF5e5XWsA8Xa80ttUXZvb6HyaBGgo2SfzUkE= +go.mau.fi/libsignal v0.1.1 h1:m/0PGBh4QKP/I1MQ44ti4C0fMbLMuHb95cmDw01FIpI= +go.mau.fi/libsignal v0.1.1/go.mod h1:QLs89F/OA3ThdSL2Wz2p+o+fi8uuQUz0e1BRa6ExdBw= +go.mau.fi/util v0.6.0 h1:W6SyB3Bm/GjenQ5iq8Z8WWdN85Gy2xS6L0wmnR7SVjg= +go.mau.fi/util v0.6.0/go.mod h1:ljYdq3sPfpICc3zMU+/mHV/sa4z0nKxc67hSBwnrk8U= +go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7 h1:Aa4uov0rM0SQQ7Fc/TZZpmQEGksie2SVTv/UuCJwViI= +go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7/go.mod h1:BhHKalSq0qNtSCuGIUIvoJyU5KbT4a7k8DQ5yw1Ssk4= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -462,11 +454,11 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= -golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 h1:zfMcR1Cs4KNuomFFgGefv5N0czO2XZpUbxGUy8i8ug0= -golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ= golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -475,8 +467,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= -golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -493,8 +485,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= -golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -510,8 +502,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -534,20 +526,20 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -562,8 +554,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200529172331-a64b76657301/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -601,8 +593,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 6c41effb3841fc98a2d0fa0ace6867dbf3c263f8 Mon Sep 17 00:00:00 2001 From: Tadeusz Magura-Witkowski Date: Thu, 4 Dec 2025 21:10:49 +0100 Subject: [PATCH 2/6] MediaServer: remove minio client, which appears to bring dependencies back in time, use proper S3 client --- gateway/mediaserver.go | 173 ++++++++++++++++++++++++++--------------- go.mod | 55 +++++++------ go.sum | 136 +++++++++++++++++++------------- 3 files changed, 226 insertions(+), 138 deletions(-) diff --git a/gateway/mediaserver.go b/gateway/mediaserver.go index 7ebd59cdbb..6a9fc54fd8 100644 --- a/gateway/mediaserver.go +++ b/gateway/mediaserver.go @@ -13,11 +13,13 @@ import ( "strings" "time" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/credentials" + "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/aws/smithy-go/logging" + "github.com/42wim/matterbridge/bridge/config" "github.com/sirupsen/logrus" - - "github.com/minio/minio-go/v7" - "github.com/minio/minio-go/v7/pkg/credentials" ) type mediaServer interface { @@ -42,10 +44,10 @@ type localMediaServer struct { httpDownloadPrefix string } -type minioMediaServer struct { +type s3MediaServer struct { commonMediaServer - minio *minio.Client + s3client *s3.Client bucket string uploadPrefix string downloadPrefix string @@ -55,7 +57,88 @@ type minioMediaServer struct { var _ mediaServer = (*httpPutMediaServer)(nil) var _ mediaServer = (*localMediaServer)(nil) -var _ mediaServer = (*minioMediaServer)(nil) +var _ mediaServer = (*s3MediaServer)(nil) + +func simpleS3Config(access_key, secret_access_key string, endpoint_url string) aws.Config { + return aws.Config{ + Region: "custom", + Credentials: credentials.NewStaticCredentialsProvider(access_key, secret_access_key, ""), + Logger: logging.Nop{}, + BaseEndpoint: aws.String(endpoint_url), + } +} + +func createS3MediaServer(bg *config.BridgeValues, parsed *url.URL, logger *logrus.Entry) (*s3MediaServer, error) { + optionsFromURL := parsed.Query() + secretAccessKey, _ := parsed.User.Password() + pathSplitted := strings.Split(strings.TrimLeft(parsed.Path, "/"), "/") + + useSSL, err := strconv.ParseBool(optionsFromURL.Get("useSSL")) + if err != nil { + logger.Warn("error while parsing useSSL boolean, assuming false: ", err) + useSSL = false + } + + pathStyle := true + if optionsFromURL.Has("pathStyle") { + pathStyle, err = strconv.ParseBool(optionsFromURL.Get("pathStyle")) + if err != nil { + logger.Warn("error while parsing pathStyle boolean, assuming false: ", err) + pathStyle = false + } + } + + if len(pathSplitted) == 0 { + return nil, fmt.Errorf("no bucket specified") + } + + bucketName := pathSplitted[0] + uploadPrefix := strings.Join(pathSplitted[1:], "/") + + ctx := context.Background() + + var s3BaseUrl string + if useSSL { + s3BaseUrl = "https://" + parsed.Host + } else { + s3BaseUrl = "http://" + parsed.Host + } + + s3cfg := simpleS3Config(parsed.User.Username(), secretAccessKey, s3BaseUrl) + client := s3.NewFromConfig(s3cfg, func(o *s3.Options) { + o.UsePathStyle = pathStyle + }) + + logger.WithFields(logrus.Fields{ + "bucket": bucketName, + "uploadPrefix": uploadPrefix, + }).Debug("configured minio client") + + // This will return an error if the bucket does not exist + headBucketResult, err := client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: aws.String(bucketName)}) + if err != nil { + return nil, fmt.Errorf("failed checking if bucket exists: %w", err) + } + + logger.WithFields(logrus.Fields{ + "bucket": bucketName, + "uploadPrefix": uploadPrefix, + "headBucketResult": headBucketResult, + }).Debug("checked destination bucket") + + return &s3MediaServer{ + commonMediaServer: commonMediaServer{ + logger: logger, + }, + + ctx: ctx, + s3client: client, + + bucket: bucketName, + uploadPrefix: uploadPrefix, + downloadPrefix: bg.General.MediaServerDownload, + }, nil +} func createMediaServer(bg *config.BridgeValues, logger *logrus.Entry) (mediaServer, error) { if bg.General.MediaServerUpload == "" && bg.General.MediaDownloadPath == "" { @@ -79,59 +162,13 @@ func createMediaServer(bg *config.BridgeValues, logger *logrus.Entry) (mediaServ }, nil } - if parsed.Scheme == "minio" { - optionsFromURL := parsed.Query() - secretAccessKey, _ := parsed.User.Password() - pathSplitted := strings.Split(strings.TrimLeft(parsed.Path, "/"), "/") - - useSSL, err := strconv.ParseBool(optionsFromURL.Get("useSSL")) - if err != nil { - logger.Warn("error while parsing useSSL boolean, assuming false: ", err) - useSSL = false - } - - if len(pathSplitted) == 0 { - return nil, fmt.Errorf("no bucket specified") - } - - bucketName := pathSplitted[0] - uploadPrefix := strings.Join(pathSplitted[1:], "/") - - ctx := context.Background() - - minioClient, err := minio.New(parsed.Host, &minio.Options{ - Creds: credentials.NewStaticV4(parsed.User.Username(), secretAccessKey, ""), - Secure: useSSL, - }) - if err != nil { - return nil, fmt.Errorf("failed to initialize minio client: %w", err) - } - - logger.WithFields(logrus.Fields{ - "bucket": bucketName, - "uploadPrefix": uploadPrefix, - }).Debug("configured minio client") - - exist, err := minioClient.BucketExists(ctx, bucketName) - if err != nil { - return nil, fmt.Errorf("failed checking if bucket exists: %w", err) - } - if !exist { - return nil, fmt.Errorf("specified bucket does not exists") + if parsed.Scheme == "s3" { + s3MediaServer, err := createS3MediaServer(bg, parsed, logger) + if err == nil { + return s3MediaServer, nil } - return &minioMediaServer{ - commonMediaServer: commonMediaServer{ - logger: logger, - }, - - ctx: ctx, - minio: minioClient, - - bucket: bucketName, - uploadPrefix: uploadPrefix, - downloadPrefix: bg.General.MediaServerDownload, - }, nil + return nil, fmt.Errorf("failed to configure s3 media server: %w", err) } return nil, fmt.Errorf("unknown schema (protocol) for mediaServerUpload: '%s'", parsed.Scheme) @@ -198,18 +235,26 @@ func (h *localMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error return h.httpDownloadPrefix + "/" + sha1sum + "/" + fi.Name, nil } -// handleFilesUpload which uploads media to minio compatible server (S3) +// handleFilesUpload which uploads media to s3 compatible server. // Returns error on failure. -func (h *minioMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { +func (h *s3MediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] - url := h.uploadPrefix + "/" + sha1sum + "/" + fi.Name + key := h.uploadPrefix + "/" + sha1sum + "/" + fi.Name objectSize := int64(len(*fi.Data)) // TODO: Using this, since we got this in memory anyway. Would be nicer to use fi.Size, but it is 0 - info, err := h.minio.PutObject(h.ctx, h.bucket, url, bytes.NewReader(*fi.Data), objectSize, minio.PutObjectOptions{ContentType: "application/octet-stream"}) + // We do not bother with multipart uploads for now, as files are expected to be small (less than 5GB). + // If needed, we can implement that later. + info, err := h.s3client.PutObject(h.ctx, &s3.PutObjectInput{ + Bucket: aws.String(h.bucket), + Key: aws.String(key), + Body: bytes.NewReader(*fi.Data), + ContentLength: aws.Int64(objectSize), + ContentType: aws.String("application/octet-stream"), + }) if err != nil { - return "", fmt.Errorf("mediaserver putfile failed: %w", err) + return "", fmt.Errorf("mediaserver s3 putfile failed: %w", err) } - h.logger.Debugf("successfully uploaded %v, etag: %v", url, info.ETag) - return h.downloadPrefix + url, nil + h.logger.Debugf("successfully uploaded %v, etag: %v", key, info.ETag) + return h.downloadPrefix + key, nil } diff --git a/go.mod b/go.mod index d568ea72ac..0ebced4cd4 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,10 @@ require ( github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c github.com/SevereCloud/vksdk/v2 v2.17.0 + github.com/aws/aws-sdk-go-v2 v1.40.1 + github.com/aws/aws-sdk-go-v2/credentials v1.19.3 + github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 + github.com/aws/smithy-go v1.24.0 github.com/bwmarrin/discordgo v0.28.1 github.com/d5/tengo/v2 v2.17.0 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc @@ -27,7 +31,6 @@ require ( github.com/mattn/go-mastodon v0.0.10 github.com/mattn/godown v0.0.1 github.com/mdp/qrterminal v1.0.1 - github.com/minio/minio-go/v7 v7.0.97 github.com/mitchellh/mapstructure v1.5.0 github.com/nelsonken/gomf v0.0.0-20190423072027-c65cc0469e94 github.com/olahol/melody v1.2.1 @@ -39,18 +42,18 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/slack-go/slack v0.14.0 github.com/spf13/viper v1.19.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.11.1 github.com/vincent-petithory/dataurl v1.0.0 github.com/writeas/go-strip-markdown v2.0.1+incompatible github.com/xmppo/go-xmpp v0.2.18 github.com/yaegashi/msgraph.go v0.1.4 github.com/zfjagann/golang-ring v0.0.0-20220330170733-19bcea1b6289 - go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7 + go.mau.fi/whatsmeow v0.0.0-20251116104239-3aca43070cd4 golang.org/x/image v0.19.0 golang.org/x/oauth2 v0.22.0 - golang.org/x/text v0.30.0 + golang.org/x/text v0.31.0 gomod.garykim.dev/nc-talk v0.3.0 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.36.10 layeh.com/gumble v0.0.0-20221205141517-d1df60a3cc14 modernc.org/sqlite v1.32.0 ) @@ -61,13 +64,23 @@ require ( github.com/Jeffail/gabs v1.4.0 // indirect github.com/apex/log v1.9.0 // indirect github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 // indirect + github.com/beeper/argo-go v1.1.2 // indirect github.com/blang/semver/v4 v4.0.0 // indirect + github.com/coder/websocket v1.8.14 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a // indirect + github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect github.com/fatih/color v1.17.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect - github.com/go-ini/ini v1.67.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect @@ -81,20 +94,16 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/kettek/apng v0.0.0-20191108220231-414630eed80f // indirect - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.2.11 // indirect - github.com/klauspost/crc32 v1.3.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect github.com/mattermost/ldap v0.0.0-20231116144001-0f480c025956 // indirect github.com/mattermost/logr/v2 v2.0.21 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect - github.com/minio/crc64nvme v1.1.0 // indirect - github.com/minio/md5-simd v1.1.2 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/monaco-io/request v1.0.5 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect @@ -103,14 +112,15 @@ require ( github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect - github.com/philhofer/fwd v1.2.0 // indirect + github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 // indirect + github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rickb777/date v1.12.4 // indirect github.com/rickb777/plural v1.2.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/rs/zerolog v1.33.0 // indirect + github.com/rs/zerolog v1.34.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 // indirect @@ -121,22 +131,23 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/tinylib/msgp v1.3.0 // indirect + github.com/tinylib/msgp v1.2.0 // indirect github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect + github.com/vektah/gqlparser/v2 v2.5.31 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/wiggin77/merror v1.0.5 // indirect github.com/wiggin77/srslog v1.0.1 // indirect - go.mau.fi/libsignal v0.1.1 // indirect - go.mau.fi/util v0.6.0 // indirect + go.mau.fi/libsignal v0.2.1 // indirect + go.mau.fi/util v0.9.3 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect - golang.org/x/net v0.46.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/term v0.36.0 // indirect + golang.org/x/crypto v0.44.0 // indirect + golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/go.sum b/go.sum index 1fe7a82090..d89595135e 100644 --- a/go.sum +++ b/go.sum @@ -16,13 +16,19 @@ github.com/Benau/go_rlottie v0.0.0-20210807002906-98c1b2421989/go.mod h1:aDWSWjs github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f h1:aUkwZDEMJIGRcWlSDifSLoKG37UCOH/DPeG52/xwois= github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f/go.mod h1:AQiQKKI/YIIctvDt3hI3c1S05/JXMM7v/sQcRd0paVE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c h1:4mIZQXKYBymQ9coA82nNyG/CjicMNLBZ8cPVrhNUM3g= github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c/go.mod h1:DNSFRLFDFIqm2+0aJzSOVfn25020vldM4SRqz6YtLgI= github.com/SevereCloud/vksdk/v2 v2.17.0 h1:Wll63JSuBTdE0L7+V/PMn9PyhLrWSWIjX76XpWbXTFw= github.com/SevereCloud/vksdk/v2 v2.17.0/go.mod h1:y3q3XAdqnQ2Wf0B+Wi7qNdqJc5ZZsz4ve+DoSQsrChk= +github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM= +github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU= github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58/go.mod h1:YNfsMyWSs+h+PaYkxGeMVmVCX75Zj/pqdjbu12ciCYE= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= @@ -32,7 +38,33 @@ github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3st github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf h1:csfEAyvOG4/498Q4SyF48ysFqQC9ESj3o8ppRtg+Rog= github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf/go.mod h1:POPnOeaYF7U9o3PjLTb9icRfEOxjBNLRXh9BLximJGM= github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v1.40.1 h1:difXb4maDZkRH0x//Qkwcfpdg1XQVXEAEs2DdXldFFc= +github.com/aws/aws-sdk-go-v2 v1.40.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= +github.com/aws/aws-sdk-go-v2/credentials v1.19.3 h1:01Ym72hK43hjwDeJUfi1l2oYLXBAOR8gNSZNmXmvuas= +github.com/aws/aws-sdk-go-v2/credentials v1.19.3/go.mod h1:55nWF/Sr9Zvls0bGnWkRxUdhzKqj9uRNlPvgV1vgxKc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15 h1:Y5YXgygXwDI5P4RkteB5yF7v35neH7LfJKBG+hzIons= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.15/go.mod h1:K+/1EpG42dFSY7CBj+Fruzm8PsCGWTXJ3jdeJ659oGQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15 h1:AvltKnW9ewxX2hFmQS0FyJH93aSvJVUEFvXfU+HWtSE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.15/go.mod h1:3I4oCdZdmgrREhU74qS1dK9yZ62yumob+58AbFR4cQA= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15 h1:NLYTEyZmVZo0Qh183sC8nC+ydJXOOeIL/qI/sS3PdLY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.15/go.mod h1:Z803iB3B0bc8oJV8zH2PERLRfQUJ2n2BXISpsA4+O1M= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6 h1:P1MU/SuhadGvg2jtviDXPEejU3jBNhoeeAlRadHzvHI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.6/go.mod h1:5KYaMG6wmVKMFBSfWoyG/zH8pWwzQFnKgpoSRlXHKdQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15 h1:3/u/4yZOffg5jdNk1sDpOQ4Y+R6Xbh+GzpDrSZjuy3U= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.15/go.mod h1:4Zkjq0FKjE78NKjabuM4tRXKFzUJWXgP0ItEZK8l7JU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15 h1:wsSQ4SVz5YE1crz0Ap7VBZrV4nNqZt4CIBBT8mnwoNc= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.15/go.mod h1:I7sditnFGtYMIqPRU1QoHZAUrXkGp4SczmlLwrNPlD0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0 h1:IrbE3B8O9pm3lsg96AXIN5MXX4pECEuExh/A0Du3AuI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.93.0/go.mod h1:/sJLzHtiiZvs6C1RbxS/anSAFwZD6oC6M/kotQzOiLw= +github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= +github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= +github.com/beeper/argo-go v1.1.2 h1:UQI2G8F+NLfGTOmTUI0254pGKx/HUU/etbUGTJv91Fs= +github.com/beeper/argo-go v1.1.2/go.mod h1:M+LJAnyowKVQ6Rdj6XYGEn+qcVFkb3R/MUpqkGR0hM4= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -44,6 +76,8 @@ github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= +github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/d5/tengo/v2 v2.17.0 h1:BWUN9NoJzw48jZKiYDXDIF3QrIVZRm1uV1gTzeZ2lqM= @@ -58,6 +92,8 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a h1:etIrTD8BQqzColk9nKRusM9um5+1q0iOEJLqfBMIK64= github.com/dyatlov/go-opengraph/opengraph v0.0.0-20220524092352-606d7b1e5f8a/go.mod h1:emQhSYTXqB0xxjLITTw4EaWZ+8IIQYw+kx9GqNUKdLg= +github.com/elliotchance/orderedmap/v3 v3.1.0 h1:j4DJ5ObEmMBt/lcwIecKcoRxIQUEnw0L804lXYDt/pg= +github.com/elliotchance/orderedmap/v3 v3.1.0/go.mod h1:G+Hc2RwaZvJMcS4JpGCOyViCnGeKf0bTYCGTO4uhjSo= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -78,8 +114,6 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk= github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= -github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -111,8 +145,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gops v0.3.27 h1:BDdWfedShsBbeatZ820oA4DbVOC8yJ4NI8xAlDFWfgI= @@ -170,13 +204,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/kettek/apng v0.0.0-20191108220231-414630eed80f h1:dnCYnTSltLuPMfc7dMrkz2uBUcEf/OFBR8yRh3oRT98= github.com/kettek/apng v0.0.0-20191108220231-414630eed80f/go.mod h1:x78/VRQYKuCftMWS0uK5e+F5RJ7S4gSlESRWI0Prl6Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU= -github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM= -github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -223,8 +252,9 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= @@ -238,6 +268,8 @@ github.com/mattn/go-mastodon v0.0.10/go.mod h1:YBofeqh7G6s787787NQR8erBYz6fKDu+K github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= +github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/godown v0.0.1 h1:39uk50ufLVQFs0eapIJVX5fCS74a1Fs2g5f1MVqIHdE= github.com/mattn/godown v0.0.1/go.mod h1:/ivCKurgV/bx6yqtP/Jtc2Xmrv3beCYBvlfAUl4X5g4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -247,12 +279,6 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyex github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/minio/crc64nvme v1.1.0 h1:e/tAguZ+4cw32D+IO/8GSf5UVr9y+3eJcxZI2WOO/7Q= -github.com/minio/crc64nvme v1.1.0/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg= -github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= -github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.97 h1:lqhREPyfgHTB/ciX8k2r8k0D93WaFqxbJX36UZq5occ= -github.com/minio/minio-go/v7 v7.0.97/go.mod h1:re5VXuo0pwEtoNLsNuSr0RrLfT/MBtohwdaSmPPSRSk= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -289,8 +315,10 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= -github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= +github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490 h1:QTvNkZ5ylY0PGgA+Lih+GdboMLY/G9SEGLMEGVjTVA4= +github.com/petermattis/goid v0.0.0-20250904145737-900bdf8bb490/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -314,11 +342,10 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= @@ -329,6 +356,8 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 h1:zwQ1HBo5FYwn1ksMd19qBCKO8JAWE9wmHivEpkw/DvE= github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI= github.com/shazow/ssh-chat v1.10.1 h1:ePS+ngEYqm+yUuXegDPutysqLV2WoI22XDOeRgI6CE0= @@ -390,13 +419,14 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tinylib/msgp v1.3.0 h1:ULuf7GPooDaIlbyvgAxBV/FI7ynli6LZ1/nVUNu+0ww= -github.com/tinylib/msgp v1.3.0/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0= +github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= +github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= @@ -410,6 +440,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/vektah/gqlparser/v2 v2.5.31 h1:YhWGA1mfTjID7qJhd1+Vxhpk5HTgydrGU9IgkWBTJ7k= +github.com/vektah/gqlparser/v2 v2.5.31/go.mod h1:c1I28gSOVNzlfc4WuDlqU7voQnsqI6OG2amkBAFmgts= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= @@ -435,12 +467,12 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zfjagann/golang-ring v0.0.0-20220330170733-19bcea1b6289 h1:dEdcEes8Aki8XrgZFyrZvtazFlW4U7eNvX9NuyFJAtQ= github.com/zfjagann/golang-ring v0.0.0-20220330170733-19bcea1b6289/go.mod h1:0MsIttMJIF/8Y7x0XjonJP7K99t3sR6bjj4m5S4JmqU= -go.mau.fi/libsignal v0.1.1 h1:m/0PGBh4QKP/I1MQ44ti4C0fMbLMuHb95cmDw01FIpI= -go.mau.fi/libsignal v0.1.1/go.mod h1:QLs89F/OA3ThdSL2Wz2p+o+fi8uuQUz0e1BRa6ExdBw= -go.mau.fi/util v0.6.0 h1:W6SyB3Bm/GjenQ5iq8Z8WWdN85Gy2xS6L0wmnR7SVjg= -go.mau.fi/util v0.6.0/go.mod h1:ljYdq3sPfpICc3zMU+/mHV/sa4z0nKxc67hSBwnrk8U= -go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7 h1:Aa4uov0rM0SQQ7Fc/TZZpmQEGksie2SVTv/UuCJwViI= -go.mau.fi/whatsmeow v0.0.0-20240821142752-3d63c6fcc1a7/go.mod h1:BhHKalSq0qNtSCuGIUIvoJyU5KbT4a7k8DQ5yw1Ssk4= +go.mau.fi/libsignal v0.2.1 h1:vRZG4EzTn70XY6Oh/pVKrQGuMHBkAWlGRC22/85m9L0= +go.mau.fi/libsignal v0.2.1/go.mod h1:iVvjrHyfQqWajOUaMEsIfo3IqgVMrhWcPiiEzk7NgoU= +go.mau.fi/util v0.9.3 h1:aqNF8KDIN8bFpFbybSk+mEBil7IHeBwlujfyTnvP0uU= +go.mau.fi/util v0.9.3/go.mod h1:krWWfBM1jWTb5f8NCa2TLqWMQuM81X7TGQjhMjBeXmQ= +go.mau.fi/whatsmeow v0.0.0-20251116104239-3aca43070cd4 h1:7hXdxCFs2Me4nypiWjdBNonaFrPfmYJvEtTOwLctSHU= +go.mau.fi/whatsmeow v0.0.0-20251116104239-3aca43070cd4/go.mod h1:5aYaEa3FF5e5XWsA8Xa80ttUXZvb6HyaBGgo2SfzUkE= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -454,11 +486,11 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 h1:zfMcR1Cs4KNuomFFgGefv5N0czO2XZpUbxGUy8i8ug0= +golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0= golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ= golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -467,8 +499,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -485,8 +517,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -502,8 +534,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -526,20 +558,20 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -554,8 +586,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200529172331-a64b76657301/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -593,8 +625,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From d4f2e92f835c08bcc82ac6ab3afa03542e046ea5 Mon Sep 17 00:00:00 2001 From: Tadeusz Magura-Witkowski Date: Fri, 5 Dec 2025 19:18:07 +0100 Subject: [PATCH 3/6] Fix imports, to match current master --- gateway/mediaserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gateway/mediaserver.go b/gateway/mediaserver.go index 6a9fc54fd8..ddeffc60e0 100644 --- a/gateway/mediaserver.go +++ b/gateway/mediaserver.go @@ -18,7 +18,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/smithy-go/logging" - "github.com/42wim/matterbridge/bridge/config" + "github.com/matterbridge-org/matterbridge/bridge/config" "github.com/sirupsen/logrus" ) From b9152ea365e488b708083a19f3eaf47c0e88bb84 Mon Sep 17 00:00:00 2001 From: Tadeusz Magura-Witkowski Date: Fri, 5 Dec 2025 19:37:14 +0100 Subject: [PATCH 4/6] MediaServer: Some of linter suggestions --- gateway/mediaserver.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/gateway/mediaserver.go b/gateway/mediaserver.go index ddeffc60e0..a0e98c71c8 100644 --- a/gateway/mediaserver.go +++ b/gateway/mediaserver.go @@ -5,7 +5,6 @@ import ( "context" "crypto/sha1" "fmt" - "io/ioutil" "net/http" "net/url" "os" @@ -51,8 +50,6 @@ type s3MediaServer struct { bucket string uploadPrefix string downloadPrefix string - - ctx context.Context } var _ mediaServer = (*httpPutMediaServer)(nil) @@ -95,8 +92,6 @@ func createS3MediaServer(bg *config.BridgeValues, parsed *url.URL, logger *logru bucketName := pathSplitted[0] uploadPrefix := strings.Join(pathSplitted[1:], "/") - ctx := context.Background() - var s3BaseUrl string if useSSL { s3BaseUrl = "https://" + parsed.Host @@ -115,7 +110,7 @@ func createS3MediaServer(bg *config.BridgeValues, parsed *url.URL, logger *logru }).Debug("configured minio client") // This will return an error if the bucket does not exist - headBucketResult, err := client.HeadBucket(ctx, &s3.HeadBucketInput{Bucket: aws.String(bucketName)}) + headBucketResult, err := client.HeadBucket(context.TODO(), &s3.HeadBucketInput{Bucket: aws.String(bucketName)}) if err != nil { return nil, fmt.Errorf("failed checking if bucket exists: %w", err) } @@ -131,7 +126,6 @@ func createS3MediaServer(bg *config.BridgeValues, parsed *url.URL, logger *logru logger: logger, }, - ctx: ctx, s3client: client, bucket: bucketName, @@ -196,20 +190,22 @@ func (h *httpPutMediaServer) handleFilesUpload(fi *config.FileInfo) (string, err } // Use MediaServerUpload. Upload using a PUT HTTP request and basicauth. sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec - url := h.httpUploadPath + "/" + sha1sum + "/" + fi.Name + uploadUrl := h.httpUploadPath + "/" + sha1sum + "/" + fi.Name - req, err := http.NewRequest("PUT", url, bytes.NewReader(*fi.Data)) + req, err := http.NewRequest(http.MethodPut, uploadUrl, bytes.NewReader(*fi.Data)) if err != nil { return "", fmt.Errorf("mediaserver upload failed, could not create request: %#v", err) } - h.logger.Debugf("mediaserver upload url: %s", url) + h.logger.Debugf("mediaserver upload url: %s", uploadUrl) req.Header.Set("Content-Type", "binary/octet-stream") - _, err = client.Do(req) + + resp, err := client.Do(req) if err != nil { return "", fmt.Errorf("mediaserver upload failed, could not Do request: %#v", err) } + defer resp.Body.Close() return h.httpDownloadPrefix + "/" + sha1sum + "/" + fi.Name, nil } @@ -227,7 +223,7 @@ func (h *localMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error path := dir + "/" + fi.Name h.logger.Debugf("mediaserver path placing file: %s", path) - err = ioutil.WriteFile(path, *fi.Data, os.ModePerm) + err = os.WriteFile(path, *fi.Data, os.ModePerm) if err != nil { return "", fmt.Errorf("mediaserver path failed, could not writefile: %s %#v", err, err) } @@ -244,7 +240,7 @@ func (h *s3MediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { // We do not bother with multipart uploads for now, as files are expected to be small (less than 5GB). // If needed, we can implement that later. - info, err := h.s3client.PutObject(h.ctx, &s3.PutObjectInput{ + info, err := h.s3client.PutObject(context.TODO(), &s3.PutObjectInput{ Bucket: aws.String(h.bucket), Key: aws.String(key), Body: bytes.NewReader(*fi.Data), From 77296894b5e7161941c273efa7b172bbc89a3bc8 Mon Sep 17 00:00:00 2001 From: Tadeusz Magura-Witkowski Date: Mon, 8 Dec 2025 21:27:11 +0100 Subject: [PATCH 5/6] MediaServer: Improved logging, removed almost useless `simpleS3Config` function added missing nolint:gosec for sha1, changed the way this feature is configured, added documentation, improved error handling, added presigned urls --- bridge/config/config.go | 6 ++ docs/advanced/mediaserver.md | 34 +++++++ gateway/gateway.go | 16 ++-- gateway/mediaserver.go | 180 +++++++++++++++++++---------------- 4 files changed, 150 insertions(+), 86 deletions(-) diff --git a/bridge/config/config.go b/bridge/config/config.go index 37f37c7a21..8f4e38eba9 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -216,6 +216,12 @@ type Protocol struct { VerboseJoinPart bool // IRC WebhookBindAddress string // mattermost, slack WebhookURL string // mattermost, slack + + S3Endpoint string // general, mediaserver configuration + S3AccessKey string // general, mediaserver configuration + S3SecretKey string // general, mediaserver configuration + S3ForcePathStyle bool // general, mediaserver configuration + S3Presign bool // general, mediaserver configuration } type ChannelOptions struct { diff --git a/docs/advanced/mediaserver.md b/docs/advanced/mediaserver.md index 2f2bbc82bd..d626553f3f 100644 --- a/docs/advanced/mediaserver.md +++ b/docs/advanced/mediaserver.md @@ -6,10 +6,44 @@ There are 2 options to set this up: * You already have a webserver running * Matterbridge runs on the same server see [local download](#use-local-download) * Matterbridge runs on another server. If the webserver is using caddy, see [caddy](#use-remote-upload) +* You already have a S3-compatible storage, then you could use [S3](#s3-minio--remote-upload-using-s3-compatible-storage) * You don't have a webserver running * See [caddy](#use-remote-upload) # Use remote upload + +# S3 (MinIO) — remote upload using S3-compatible storage + +Matterbridge can upload media to S3-compatible object stores. This is useful when you want a hosted, scalable Mediaserver and you have (or run) an S3 endpoint such as MinIO. + +Key points +* Use an s3:// bucket path for uploads; Matterbridge will put objects into that bucket and return URLs based on MediaServerDownload (or the S3 public endpoint). Additional part in s3:// are treated as a prefix to a file (same behaviour as in `awscli-v2`) +* For MinIO you normally enable path-style requests and provide the endpoint + credentials. + +Sample matterbridge configuration (in [general]) +``` +[general] +# tell matterbridge to upload to the bucket +MediaServerUpload="s3://matterbridge" +# public URL base where objects will be served from (path style, this will be treated as a prefix to URL) +MediaServerDownload="https://minio.example.com/matterbridge" + +# S3 / MinIO connection settings (common names used by many S3 clients) +S3Endpoint="https://minio.example.com:9000" +S3AccessKey="minioadmin" +S3SecretKey="minioadmin" +# MinIO typically requires path style for bucket paths +S3ForcePathStyle=true +# To use presigned URLs instead of public buckets. Presigned URL will be valid for 7 days. +# when using this setting MediaServerDownload is ignored. +# Please note that this produces awful, long links. +S3Presign=false +``` + +Notes and recommendations +* Public buckets are required for links to work, since users need to have permission to read files that were submitted by matterbridge. +* Adjust credentials and endpoints for your environment. For MinIO on a nonstandard port or local testing, use the correct host:port in S3Endpoint and in MediaServerDownload. + ## Caddy In this case we're using caddy for upload/downloading media. Caddy has automatic https support, so I'm going to describe this for https only. diff --git a/gateway/gateway.go b/gateway/gateway.go index 9c1dbdeede..4f3e352f48 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -1,6 +1,7 @@ package gateway import ( + "errors" "fmt" "io/ioutil" "os" @@ -47,13 +48,16 @@ const apiProtocol = "api" func New(rootLogger *logrus.Logger, cfg *config.Gateway, r *Router) *Gateway { logger := rootLogger.WithFields(logrus.Fields{"prefix": "gateway"}) - mediaServer, err := createMediaServer(r.Config.BridgeValues(), rootLogger.WithField("prefix", "mediaserver")) + mediaServerInstance, err := createMediaServer(r.BridgeValues(), rootLogger.WithField("prefix", "mediaserver")) if err != nil { - logger.Errorf("Failed to configure media server for gateway: %#v", err) - } + if errors.Is(err, ErrMediaConfigurationNotWanted) { + // media server not wanted, ignore + mediaServerInstance = nil - if mediaServer == nil { - logger.Warn("Media server is disabled") + logger.Info("Media server not configured, skipping media server setup") + } else { + logger.WithError(err).Error("Failed to configure media server for gateway") + } } cache, _ := lru.New(5000) @@ -65,7 +69,7 @@ func New(rootLogger *logrus.Logger, cfg *config.Gateway, r *Router) *Gateway { Config: r.Config, Messages: cache, logger: logger, - mediaServer: mediaServer, + mediaServer: mediaServerInstance, } if err := gw.AddConfig(cfg); err != nil { logger.Errorf("Failed to add configuration to gateway: %#v", err) diff --git a/gateway/mediaserver.go b/gateway/mediaserver.go index a0e98c71c8..b5472d50e6 100644 --- a/gateway/mediaserver.go +++ b/gateway/mediaserver.go @@ -3,12 +3,13 @@ package gateway import ( "bytes" "context" - "crypto/sha1" + "crypto/sha1" //nolint:gosec + "errors" "fmt" "net/http" "net/url" "os" - "strconv" + "path" "strings" "time" @@ -46,78 +47,72 @@ type localMediaServer struct { type s3MediaServer struct { commonMediaServer - s3client *s3.Client - bucket string - uploadPrefix string - downloadPrefix string + s3Client *s3.Client + presignS3Client *s3.PresignClient + + bucket string + uploadPrefix string + httpDownloadPrefix string } var _ mediaServer = (*httpPutMediaServer)(nil) var _ mediaServer = (*localMediaServer)(nil) var _ mediaServer = (*s3MediaServer)(nil) -func simpleS3Config(access_key, secret_access_key string, endpoint_url string) aws.Config { - return aws.Config{ - Region: "custom", - Credentials: credentials.NewStaticCredentialsProvider(access_key, secret_access_key, ""), - Logger: logging.Nop{}, - BaseEndpoint: aws.String(endpoint_url), - } -} +const mediaUploadTimeout = 5 * time.Second +const mediaUploadPresignDuration = 7 * 24 * time.Hour // presigned URL valid duration -func createS3MediaServer(bg *config.BridgeValues, parsed *url.URL, logger *logrus.Entry) (*s3MediaServer, error) { - optionsFromURL := parsed.Query() - secretAccessKey, _ := parsed.User.Password() - pathSplitted := strings.Split(strings.TrimLeft(parsed.Path, "/"), "/") +var ErrMediaConfiguration = errors.New("media server is not properly configured") +var ErrMediaConfigurationNotWanted = errors.New("media server is not configured and not wanted") - useSSL, err := strconv.ParseBool(optionsFromURL.Get("useSSL")) - if err != nil { - logger.Warn("error while parsing useSSL boolean, assuming false: ", err) - useSSL = false - } +var ErrMediaServerRuntime = errors.New("media server error") +var errUploadFailed = fmt.Errorf("%w: upload failed", ErrMediaServerRuntime) - pathStyle := true - if optionsFromURL.Has("pathStyle") { - pathStyle, err = strconv.ParseBool(optionsFromURL.Get("pathStyle")) - if err != nil { - logger.Warn("error while parsing pathStyle boolean, assuming false: ", err) - pathStyle = false - } +func createS3MediaServer(bg *config.BridgeValues, bucketName string, uploadPrefix string, logger *logrus.Entry) (*s3MediaServer, error) { + if bucketName == "" { + return nil, fmt.Errorf("%w: invalid s3 upload prefix, must be in format s3://bucketname/prefix", ErrMediaConfiguration) } - if len(pathSplitted) == 0 { - return nil, fmt.Errorf("no bucket specified") + if bg.General.S3Endpoint == "" { + return nil, fmt.Errorf("%w: s3 endpoint is not configured", ErrMediaConfiguration) } - bucketName := pathSplitted[0] - uploadPrefix := strings.Join(pathSplitted[1:], "/") + if bg.General.S3AccessKey == "" { + return nil, fmt.Errorf("%w: s3 access key is not configured", ErrMediaConfiguration) + } - var s3BaseUrl string - if useSSL { - s3BaseUrl = "https://" + parsed.Host - } else { - s3BaseUrl = "http://" + parsed.Host + if bg.General.S3SecretKey == "" { + return nil, fmt.Errorf("%w: s3 secret key is not configured", ErrMediaConfiguration) } - s3cfg := simpleS3Config(parsed.User.Username(), secretAccessKey, s3BaseUrl) - client := s3.NewFromConfig(s3cfg, func(o *s3.Options) { - o.UsePathStyle = pathStyle + uploadPrefix = strings.Trim(uploadPrefix, "/") + + client := s3.NewFromConfig(aws.Config{ + Region: "custom", + Credentials: credentials.NewStaticCredentialsProvider(bg.General.S3AccessKey, bg.General.S3SecretKey, ""), + Logger: logging.Nop{}, + BaseEndpoint: aws.String(bg.General.S3Endpoint), + HTTPClient: &http.Client{Timeout: mediaUploadTimeout}, + }, func(o *s3.Options) { + o.UsePathStyle = bg.General.S3ForcePathStyle }) - logger.WithFields(logrus.Fields{ - "bucket": bucketName, - "uploadPrefix": uploadPrefix, - }).Debug("configured minio client") + var presignClient *s3.PresignClient + if bg.General.S3Presign { + presignClient = s3.NewPresignClient(client) + } // This will return an error if the bucket does not exist headBucketResult, err := client.HeadBucket(context.TODO(), &s3.HeadBucketInput{Bucket: aws.String(bucketName)}) if err != nil { - return nil, fmt.Errorf("failed checking if bucket exists: %w", err) + return nil, fmt.Errorf("%w: failed to check if bucket exists: %w", ErrMediaServerRuntime, err) } logger.WithFields(logrus.Fields{ "bucket": bucketName, "uploadPrefix": uploadPrefix, + "baseUrl": bg.General.S3Endpoint, + "pathStyle": bg.General.S3ForcePathStyle, "headBucketResult": headBucketResult, }).Debug("checked destination bucket") @@ -126,29 +121,30 @@ func createS3MediaServer(bg *config.BridgeValues, parsed *url.URL, logger *logru logger: logger, }, - s3client: client, + s3Client: client, + presignS3Client: presignClient, - bucket: bucketName, - uploadPrefix: uploadPrefix, - downloadPrefix: bg.General.MediaServerDownload, + bucket: bucketName, + uploadPrefix: uploadPrefix, + httpDownloadPrefix: bg.General.MediaServerDownload, }, nil } func createMediaServer(bg *config.BridgeValues, logger *logrus.Entry) (mediaServer, error) { if bg.General.MediaServerUpload == "" && bg.General.MediaDownloadPath == "" { - return nil, nil // we don't have a attachfield or we don't have a mediaserver configured return + return nil, ErrMediaConfigurationNotWanted // we don't have a attachfield or we don't have a mediaserver configured return } if bg.General.MediaServerUpload != "" { parsed, err := url.Parse(bg.General.MediaServerUpload) if err != nil { - return nil, fmt.Errorf("failed parsing mediaServerUpload URL: %w", err) + return nil, fmt.Errorf("%w: invalid media server upload URL: %w", ErrMediaConfiguration, err) } if parsed.Scheme == "http" || parsed.Scheme == "https" { return &httpPutMediaServer{ commonMediaServer: commonMediaServer{ - logger: logger, + logger: logger.WithField("component", "httpputmediaserver"), }, httpUploadPath: bg.General.MediaServerUpload, @@ -157,21 +153,21 @@ func createMediaServer(bg *config.BridgeValues, logger *logrus.Entry) (mediaServ } if parsed.Scheme == "s3" { - s3MediaServer, err := createS3MediaServer(bg, parsed, logger) + s3MediaServer, err := createS3MediaServer(bg, parsed.Host, parsed.Path, logger.WithField("component", "s3mediaserver")) if err == nil { return s3MediaServer, nil } - return nil, fmt.Errorf("failed to configure s3 media server: %w", err) + return nil, fmt.Errorf("%w: %w", ErrMediaConfiguration, err) } - return nil, fmt.Errorf("unknown schema (protocol) for mediaServerUpload: '%s'", parsed.Scheme) + return nil, fmt.Errorf("%w: unknown schema (protocol) for mediaServerUpload: '%s'", ErrMediaConfiguration, parsed.Scheme) } if bg.General.MediaDownloadPath != "" { return &localMediaServer{ commonMediaServer: commonMediaServer{ - logger: logger, + logger: logger.WithField("component", "localmediaserver"), }, localPath: bg.General.MediaDownloadPath, @@ -179,22 +175,22 @@ func createMediaServer(bg *config.BridgeValues, logger *logrus.Entry) (mediaServ }, nil } - return nil, nil // never reached + return nil, ErrMediaConfigurationNotWanted // never reached } // handleFilesUpload which uses MediaServerUpload configuration to upload the file via HTTP PUT request. // Returns error on failure. func (h *httpPutMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { client := &http.Client{ - Timeout: time.Second * 5, + Timeout: mediaUploadTimeout, } // Use MediaServerUpload. Upload using a PUT HTTP request and basicauth. sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec - uploadUrl := h.httpUploadPath + "/" + sha1sum + "/" + fi.Name + uploadUrl := h.httpUploadPath + "/" + path.Join(sha1sum, fi.Name) req, err := http.NewRequest(http.MethodPut, uploadUrl, bytes.NewReader(*fi.Data)) if err != nil { - return "", fmt.Errorf("mediaserver upload failed, could not create request: %#v", err) + return "", fmt.Errorf("%w: could not create request: %w", errUploadFailed, err) } h.logger.Debugf("mediaserver upload url: %s", uploadUrl) @@ -203,44 +199,49 @@ func (h *httpPutMediaServer) handleFilesUpload(fi *config.FileInfo) (string, err resp, err := client.Do(req) if err != nil { - return "", fmt.Errorf("mediaserver upload failed, could not Do request: %#v", err) + return "", fmt.Errorf("%w: could not Do request: %w", errUploadFailed, err) } - defer resp.Body.Close() - return h.httpDownloadPrefix + "/" + sha1sum + "/" + fi.Name, nil + err = resp.Body.Close() + if err != nil { + h.logger.WithError(err).Error("failed to close response body") + } + + return h.httpDownloadPrefix + "/" + path.Join(sha1sum, fi.Name), nil } // handleFilesUpload which uses MediaServerPath configuration, places the file on the current filesystem. // Returns error on failure. func (h *localMediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec - dir := h.localPath + "/" + sha1sum - err := os.Mkdir(dir, os.ModePerm) + dir := path.Join(h.localPath, sha1sum) + + err := os.Mkdir(dir, 0755) //nolint:gosec // this is for writing media files, so 0755 is fine, we want them to be accesible by webserver if err != nil && !os.IsExist(err) { - return "", fmt.Errorf("mediaserver path failed, could not mkdir: %s %#v", err, err) + return "", fmt.Errorf("%w: could not mkdir: %w", errUploadFailed, err) } - path := dir + "/" + fi.Name - h.logger.Debugf("mediaserver path placing file: %s", path) + fileWritePath := path.Join(dir, fi.Name) + h.logger.WithField("fileWritePath", fileWritePath).Debug("mediaserver path placing file") - err = os.WriteFile(path, *fi.Data, os.ModePerm) + err = os.WriteFile(fileWritePath, *fi.Data, 0644) //nolint:gosec // this is for writing media files, so 0644 is fine, we want them to be accesible by webserver if err != nil { - return "", fmt.Errorf("mediaserver path failed, could not writefile: %s %#v", err, err) + return "", fmt.Errorf("%w: could not writefile: %w", errUploadFailed, err) } - return h.httpDownloadPrefix + "/" + sha1sum + "/" + fi.Name, nil + return h.httpDownloadPrefix + "/" + path.Join(sha1sum, fi.Name), nil } // handleFilesUpload which uploads media to s3 compatible server. // Returns error on failure. func (h *s3MediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { - sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] - key := h.uploadPrefix + "/" + sha1sum + "/" + fi.Name - objectSize := int64(len(*fi.Data)) // TODO: Using this, since we got this in memory anyway. Would be nicer to use fi.Size, but it is 0 + sha1sum := fmt.Sprintf("%x", sha1.Sum(*fi.Data))[:8] //nolint:gosec + key := path.Join(h.uploadPrefix, sha1sum, fi.Name) + objectSize := int64(len(*fi.Data)) // TODO: Using this, sine we got this in memory anyway. Would be nicer to use fi.Size, but it is 0 // We do not bother with multipart uploads for now, as files are expected to be small (less than 5GB). // If needed, we can implement that later. - info, err := h.s3client.PutObject(context.TODO(), &s3.PutObjectInput{ + info, err := h.s3Client.PutObject(context.TODO(), &s3.PutObjectInput{ Bucket: aws.String(h.bucket), Key: aws.String(key), Body: bytes.NewReader(*fi.Data), @@ -248,9 +249,28 @@ func (h *s3MediaServer) handleFilesUpload(fi *config.FileInfo) (string, error) { ContentType: aws.String("application/octet-stream"), }) if err != nil { - return "", fmt.Errorf("mediaserver s3 putfile failed: %w", err) + return "", fmt.Errorf("%w: mediaserver s3 PutObject failed: %w", errUploadFailed, err) } - h.logger.Debugf("successfully uploaded %v, etag: %v", key, info.ETag) - return h.downloadPrefix + key, nil + downloadURL := h.httpDownloadPrefix + "/" + key + // If presign is enabled, generate a presigned URL, otherwise use the standard download URL. + if h.presignS3Client != nil { + downloadReq, err := h.presignS3Client.PresignGetObject(context.TODO(), &s3.GetObjectInput{ + Bucket: aws.String(h.bucket), + Key: aws.String(key), + }, s3.WithPresignExpires(mediaUploadPresignDuration)) + if err != nil { + return "", fmt.Errorf("%w: mediaserver s3 presign request creation failed: %w", errUploadFailed, err) + } + + downloadURL = downloadReq.URL + } + + h.logger.WithFields(logrus.Fields{ + "key": key, + "etag": info.ETag, + "downloadURL": downloadURL, + }).Debug("successfully uploaded") + + return downloadURL, nil } From 5d41e18b4e57849ca5f963f84a1926f7b9a567a8 Mon Sep 17 00:00:00 2001 From: Tadeusz Magura-Witkowski Date: Wed, 14 Jan 2026 23:09:06 +0100 Subject: [PATCH 6/6] MediaServer: Missing S3 region configuration --- bridge/config/config.go | 1 + gateway/mediaserver.go | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bridge/config/config.go b/bridge/config/config.go index 8f4e38eba9..c5a61b6f46 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -222,6 +222,7 @@ type Protocol struct { S3SecretKey string // general, mediaserver configuration S3ForcePathStyle bool // general, mediaserver configuration S3Presign bool // general, mediaserver configuration + S3Region string // general, mediaserver configuration } type ChannelOptions struct { diff --git a/gateway/mediaserver.go b/gateway/mediaserver.go index b5472d50e6..e930760aa5 100644 --- a/gateway/mediaserver.go +++ b/gateway/mediaserver.go @@ -85,10 +85,14 @@ func createS3MediaServer(bg *config.BridgeValues, bucketName string, uploadPrefi return nil, fmt.Errorf("%w: s3 secret key is not configured", ErrMediaConfiguration) } + if bg.General.S3Region == "" { + return nil, fmt.Errorf("%w: s3 region is not configured", ErrMediaConfiguration) + } + uploadPrefix = strings.Trim(uploadPrefix, "/") client := s3.NewFromConfig(aws.Config{ - Region: "custom", + Region: bg.General.S3Region, Credentials: credentials.NewStaticCredentialsProvider(bg.General.S3AccessKey, bg.General.S3SecretKey, ""), Logger: logging.Nop{}, BaseEndpoint: aws.String(bg.General.S3Endpoint),