diff --git a/.gitignore b/.gitignore index 9e805d9..791c404 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,7 @@ bin/ go.work .env -nourybot-matrix \ No newline at end of file +nourybot-matrix +nourybot-matrix.out +Nourybot-Matrix +Nourybot-Matrix.out diff --git a/Makefile b/Makefile index 839de2d..a5c18e1 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,9 @@ +BINARY_NAME=Nourybot-Matrix.out + +dev: + go build -o ${BINARY_NAME} cmd/bot/* + ./${BINARY_NAME} + rebuild: docker compose down - docker-compose up --force-recreate --no-deps --build nourybot-matrix \ No newline at end of file + docker-compose up --force-recreate --no-deps --build nourybot-matrix diff --git a/cmd/bot/commands.go b/cmd/bot/commands.go index c254114..1dd7809 100644 --- a/cmd/bot/commands.go +++ b/cmd/bot/commands.go @@ -9,7 +9,7 @@ import ( func (app *application) ParseCommand(evt *event.Event) { // commandName is the actual name of the command without the prefix. // e.g. `!ping` would be `ping`. - //commandName := strings.ToLower(strings.SplitN(evt.Content.AsMessage().Body, " ", 2)[0][1:]) + commandName := strings.ToLower(strings.SplitN(evt.Content.AsMessage().Body, " ", 2)[0][1:]) // cmdParams are additional command parameters. // e.g. `!weather san antonio` @@ -23,11 +23,13 @@ func (app *application) ParseCommand(evt *event.Event) { app.Log.Info().Msgf("Command: %s", evt.Content.AsMessage().Body) - switch evt.Content.AsMessage().Body { - case "!xd": + //message := evt.Content.AsMessage().Body + switch commandName { + case "xd": app.SendText(evt, "xd !") return - - case "!yaf": + case "yaf": + app.NewDownload("yaf", evt, cmdParams[1]) + return } } diff --git a/cmd/bot/download.go b/cmd/bot/download.go new file mode 100644 index 0000000..80eaeb6 --- /dev/null +++ b/cmd/bot/download.go @@ -0,0 +1,77 @@ +package main + +import ( + "context" + "fmt" + "io" + "os" + "strings" + + "github.com/google/uuid" + "github.com/wader/goutubedl" + "maunium.net/go/mautrix/event" +) + +const ( + //CATBOX_ENDPOINT = "https://litterbox.catbox.moe/resources/internals/api.php" + //GOFILE_ENDPOINT = "https://store1.gofile.io/uploadFile" + //KAPPA_ENDPOINT = "https://kappa.lol/api/upload" + YAF_ENDPOINT = "https://i.yaf.li/upload" +) + +func (app *application) NewDownload(destination string, evt *event.Event, link string) { + uuid := uuid.NewString() + + app.Log.Info().Msgf("Link: %s", link) + switch destination { + case "yaf": + app.YafDownload(evt, link, uuid) + // case "catbox": + // app.CatboxDownload(target, link, identifier, msg) + //case "kappa": + // app.KappaDownload(target, link, identifier, msg) + //case "gofile": + // app.GofileDownload(target, link, identifier, msg) + } +} + +func (app *application) YafDownload(evt *event.Event, link, uuid string) { + goutubedl.Path = "yt-dlp" + var rExt string + + app.SendText(evt, "Downloading...") + result, err := goutubedl.New(context.Background(), link, goutubedl.Options{}) + if err != nil { + app.Log.Error().Err(err).Msg("Failed to download") + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + + // For some reason youtube links return webm as result.Info.Ext but + // are in reality mp4. + if strings.HasPrefix(link, "https://www.youtube.com/") { + rExt = "mp4" + } else { + rExt = result.Info.Ext + } + + downloadResult, err := result.Download(context.TODO(), "best") + if err != nil { + app.Log.Error().Err(err).Msg("Failed to download") + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + defer downloadResult.Close() + + fileName := fmt.Sprintf("%s.%s", uuid, rExt) + f, err := os.Create(fileName) + if err != nil { + app.Log.Error().Err(err).Msg("Failed to download") + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + defer f.Close() + io.Copy(f, downloadResult) + + app.NewUpload("yaf", evt, fileName) +} diff --git a/cmd/bot/upload.go b/cmd/bot/upload.go new file mode 100644 index 0000000..1bbb440 --- /dev/null +++ b/cmd/bot/upload.go @@ -0,0 +1,102 @@ +package main + +import ( + "fmt" + "io" + "mime/multipart" + "net/http" + "os" + "time" + + "maunium.net/go/mautrix/event" +) + +func (app *application) NewUpload(destination string, evt *event.Event, fileName string) { + switch destination { + case "yaf": + go app.YafUpload(evt, fileName) + //case "catbox": + // go app.CatboxUpload(target, fileName, identifier, msg) + //case "kappa": + // go app.KappaUpload(target, fileName, identifier, msg) + //case "gofile": + // go app.GofileUpload(target, fileName, identifier, msg) + } +} + +func (app *application) YafUpload(evt *event.Event, fileName string) { + defer os.Remove(fileName) + app.SendText(evt, "Uploading to yaf.li...") + pr, pw := io.Pipe() + form := multipart.NewWriter(pw) + + go func() { + defer pw.Close() + + err := form.WriteField("name", "xd") + if err != nil { + app.Log.Error().Err(err).Msg("Failed to upload") + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + + file, err := os.Open(fileName) // path to image file + if err != nil { + app.Log.Error().Err(err).Msg("Failed to upload") + os.Remove(fileName) + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + + w, err := form.CreateFormFile("file", fileName) + if err != nil { + app.Log.Error().Err(err).Msg("Failed to upload") + os.Remove(fileName) + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + + _, err = io.Copy(w, file) + if err != nil { + app.Log.Error().Err(err).Msg("Failed to upload") + os.Remove(fileName) + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + + form.Close() + }() + + req, err := http.NewRequest(http.MethodPost, YAF_ENDPOINT, pr) + if err != nil { + app.Log.Error().Err(err).Msg("Failed to upload") + os.Remove(fileName) + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + req.Header.Set("Content-Type", form.FormDataContentType()) + + httpClient := http.Client{ + Timeout: 300 * time.Second, + } + resp, err := httpClient.Do(req) + if err != nil { + app.Log.Error().Err(err).Msg("Failed to upload") + os.Remove(fileName) + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + return + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + app.Log.Error().Err(err).Msg("Failed to upload") + app.SendText(evt, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err)) + os.Remove(fileName) + return + } + + var reply = string(body[:]) + + app.SendText(evt, reply) +} diff --git a/go.mod b/go.mod index 1509cdc..f28b663 100644 --- a/go.mod +++ b/go.mod @@ -11,12 +11,14 @@ require ( ) require ( + github.com/google/uuid v1.5.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/tidwall/gjson v1.17.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/wader/goutubedl v0.0.0-20240110164636-adddb11ead1b // indirect go.mau.fi/util v0.2.1 // indirect golang.org/x/crypto v0.15.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect diff --git a/go.sum b/go.sum index 99be258..7426b3e 100644 --- a/go.sum +++ b/go.sum @@ -7,7 +7,10 @@ github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -32,6 +35,9 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/wader/goutubedl v0.0.0-20240110164636-adddb11ead1b h1:xSddyANsGzMEoClwwZzuesuWPnwkmmtSsERFrOodMT8= +github.com/wader/goutubedl v0.0.0-20240110164636-adddb11ead1b/go.mod h1:5KXd5tImdbmz4JoVhePtbIokCwAfEhUVVx3WLHmjYuw= +github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071/go.mod h1:XD6emOFPHVzb0+qQpiNOdPL2XZ0SRUM0N5JHuq6OmXo= go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw= go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=