From d719e87fb94a21dad4fec00e18a0b4c0c81a721a Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Fri, 15 Jan 2021 16:15:48 -0700 Subject: [PATCH] mostly nsfw owner stuff and kvstore persistence. --- adapters.go | 62 ++++++++++++++++++++++++++++++++++++++++++++ args.go | 10 ++++++++ cmd/boobs.go | 33 ++++++++++++++++++++++++ go.mod | 7 +++-- go.sum | 14 ++++++++++ main.go | 54 +++++++++++++++++++++++++++++++++++++- ownerCommands.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 adapters.go create mode 100644 cmd/boobs.go create mode 100644 ownerCommands.go diff --git a/adapters.go b/adapters.go new file mode 100644 index 0000000..f21f84d --- /dev/null +++ b/adapters.go @@ -0,0 +1,62 @@ +package main + +import ( + "fmt" + + "github.com/kf5grd/keybasebot" + "samhofi.us/x/keybase/v2" + "samhofi.us/x/keybase/v2/types/chat1" +) + +func nsfwFilter() keybasebot.Adapter { + return func(action keybasebot.BotAction) keybasebot.BotAction { + return func(m chat1.MsgSummary, b *keybasebot.Bot) (bool, error) { + // if its not a team, nsfw is always allowed + if m.Channel.MembersType == keybase.USER { + b.Logger.Debug("boobs are allowed in %s", m.Channel.Name) + return action(m, b) + } + + // if the team is in the allowed list, nsfw is allowed + if m.Channel.MembersType == keybase.TEAM { + data, ok := b.Meta["nsfwAllowed"] + if !ok { + err := fmt.Errorf("Unable to fetch allowed teams from meta") + return false, err + } + allowedTeams := data.(map[chat1.ConvIDStr]bool) + if isAllowed := allowedTeams[m.ConvID]; isAllowed { + return action(m, b) + } + } + + // if the team is not allowed, fail silently + b.Logger.Debug("boobs are not allowed in %s", m.Channel.Name) + return true, nil + } + } +} + +func requireOwner() keybasebot.Adapter { + return func(action keybasebot.BotAction) keybasebot.BotAction { + return func(m chat1.MsgSummary, b *keybasebot.Bot) (bool, error) { + b.Logger.Debug("checking owner command auth") + // if the team is in the allowed list, nsfw is allowed + data, ok := b.Meta["owner"] + if !ok { + b.Logger.Debug("unable to fetch owner from meta") + err := fmt.Errorf("owner command used without owner set") + return false, err + } + myOwner := data.(string) + if m.Sender.Username == myOwner { + b.Logger.Debug("owner command approved") + return action(m, b) + } + + // if the team is not allowed, fail silently + b.Logger.Info("@%s tried to user owner command without auth.", m.Sender.Username) + return true, nil + } + } +} diff --git a/args.go b/args.go index a6cf053..7e54414 100644 --- a/args.go +++ b/args.go @@ -14,6 +14,8 @@ type botOptions struct { JSON bool `env:"BOT_LOG_JSON" envDefault:"false"` RedditUser string `env:"BOT_REDDIT_USER" envDefault:""` RedditPass string `env:"BOT_REDDIT_PASS" envDefault:""` + Owner string `env:"BOT_OWNER" envDefault:""` + KvStoreTeam string `env:"BOT_KVSTORE_TEAM" envDefault:""` } func parseArgs(args []string) botOptions { @@ -31,6 +33,8 @@ func parseArgs(args []string) botOptions { flags.StringVar(&cliOpts.HomePath, "kbhome", "", "sets alternate keybase home folder for debugging") flags.StringVar(&cliOpts.RedditUser, "reddit-user", "", "sets the reddit auth user") flags.StringVar(&cliOpts.RedditPass, "reddit-pass", "", "sets the reddit auth password") + flags.StringVar(&cliOpts.Owner, "owner", "", "sets the keybase username of the bot owner") + flags.StringVar(&cliOpts.KvStoreTeam, "kvstore-team", "", "sets the kvstore team if you want to save configs") if err := flags.Parse(args[1:]); err != nil { log.Fatalf("Unable to parse cli args: %+v", err) } @@ -54,6 +58,12 @@ func parseArgs(args []string) botOptions { if cliOpts.RedditPass != "" { opts.RedditPass = cliOpts.RedditPass } + if cliOpts.Owner != "" { + opts.Owner = cliOpts.Owner + } + if cliOpts.KvStoreTeam != "" { + opts.KvStoreTeam = cliOpts.KvStoreTeam + } } return opts } diff --git a/cmd/boobs.go b/cmd/boobs.go new file mode 100644 index 0000000..1c96871 --- /dev/null +++ b/cmd/boobs.go @@ -0,0 +1,33 @@ +package cmd + +import ( + "os" + + "github.com/kf5grd/keybasebot" + "github.com/teris-io/shortid" + "samhofi.us/x/keybase/v2/types/chat1" +) + +/*var BoobsAd = chat1.UserBotCommandInput{ + Name: "eyebleach", + Usage: "", + Description: "Sends some cute critters", +}*/ + +func Boobs(m chat1.MsgSummary, b *keybasebot.Bot) (bool, error) { + path, desc, err := getRandomRedditMedia(b, "boobs", "top", 100) + if err != nil { + eid := shortid.MustGenerate() + b.Logger.Error("%s: %+v", eid, err) + b.KB.ReactByConvID(m.ConvID, m.Id, "Error: %s", eid) + return true, nil + } + // upload the image + b.KB.UploadToConversation(m.ConvID, desc, path) + // delete the file + err = os.Remove(path) + if err != nil { + b.Logger.Error("Unable to remove file %s", path) + } + return true, nil +} diff --git a/go.mod b/go.mod index af18433..da22aa9 100644 --- a/go.mod +++ b/go.mod @@ -4,15 +4,18 @@ go 1.15 require ( github.com/PuerkitoBio/goquery v1.6.1 + github.com/andybalholm/cascadia v1.2.0 // indirect github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47 // indirect github.com/caarlos0/env v3.5.0+incompatible + github.com/golang/protobuf v1.4.3 // indirect github.com/google/go-querystring v1.0.0 // indirect github.com/google/uuid v1.1.5 github.com/jzelinskie/geddit v0.0.0-20200521013404-78c28c13fba2 - github.com/kf5grd/keybasebot v1.3.1-0.20210115153557-55a46e5206dc + github.com/kf5grd/keybasebot v1.4.1 github.com/stretchr/testify v1.7.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3 // indirect - samhofi.us/x/keybase/v2 v2.0.6 + google.golang.org/appengine v1.6.7 // indirect + samhofi.us/x/keybase/v2 v2.0.8 ) diff --git a/go.sum b/go.sum index 4650558..129d8be 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ github.com/PuerkitoBio/goquery v1.6.1 h1:FgjbQZKl5HTmcn4sKBgvx8vv63nhyhIpv7lJpFG github.com/PuerkitoBio/goquery v1.6.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/andybalholm/cascadia v1.2.0 h1:vuRCkM5Ozh/BfmsaTm26kbjm0mIOM3yS5Ek/F5h18aE= +github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY= github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47 h1:M57m0xQqZIhx7CEJgeLSvRFKEK1RjzRuIXiA3HfYU7g= github.com/beefsack/go-rate v0.0.0-20200827232406-6cde80facd47/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA= github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= @@ -81,6 +83,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -137,6 +141,12 @@ github.com/kf5grd/keybasebot v1.3.1-0.20210115152456-e9098b6373e7 h1:uUjyh919Gup github.com/kf5grd/keybasebot v1.3.1-0.20210115152456-e9098b6373e7/go.mod h1:aLjlXVBN7JQuBkKfUK/VT6fgXY8Gt4TlnNZGd3iPQXg= github.com/kf5grd/keybasebot v1.3.1-0.20210115153557-55a46e5206dc h1:vO5YkfgOxBLdpOLHewDBOcZdRolQLMJbh0aoQJIyiI4= github.com/kf5grd/keybasebot v1.3.1-0.20210115153557-55a46e5206dc/go.mod h1:aLjlXVBN7JQuBkKfUK/VT6fgXY8Gt4TlnNZGd3iPQXg= +github.com/kf5grd/keybasebot v1.3.1-0.20210115215309-970123606dc4 h1:ONxFFsoV0AYMbpt5G1hCDh3ZWMGI82JLD80i4a2cwOQ= +github.com/kf5grd/keybasebot v1.3.1-0.20210115215309-970123606dc4/go.mod h1:8T07cWZZrl2G6hTRsL9x2SBwaH8gEZocF9NRknSU3dY= +github.com/kf5grd/keybasebot v1.3.1-0.20210115222331-9060677d0119 h1:t2INVIjxt/kq4AszGOYCl0LmHJnvU7f28UA+1ouimVA= +github.com/kf5grd/keybasebot v1.3.1-0.20210115222331-9060677d0119/go.mod h1:8T07cWZZrl2G6hTRsL9x2SBwaH8gEZocF9NRknSU3dY= +github.com/kf5grd/keybasebot v1.4.1 h1:6VTcDnCiYWtEtxSOEFvKF5R7VwabR3pSEONWV81WS+Q= +github.com/kf5grd/keybasebot v1.4.1/go.mod h1:8T07cWZZrl2G6hTRsL9x2SBwaH8gEZocF9NRknSU3dY= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -341,6 +351,8 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -411,3 +423,5 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= samhofi.us/x/keybase/v2 v2.0.6 h1:gLluTcyjbwckQxSarF1ig2klL4Li7O/THdxsgo1dUvw= samhofi.us/x/keybase/v2 v2.0.6/go.mod h1:lJivwhzMSV+WUg+XUbatszStjjFVcuLGl+xcQpqQ5GQ= +samhofi.us/x/keybase/v2 v2.0.8 h1:hmGZa8v1peHuWBvePI09EXh5vahxbDPqNAXtztLDQzM= +samhofi.us/x/keybase/v2 v2.0.8/go.mod h1:lJivwhzMSV+WUg+XUbatszStjjFVcuLGl+xcQpqQ5GQ= diff --git a/main.go b/main.go index b281471..acd805e 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "app/cmd" "github.com/kf5grd/keybasebot" + "github.com/kf5grd/keybasebot/pkg/kvstore" "samhofi.us/x/keybase/v2" "samhofi.us/x/keybase/v2/types/chat1" ) @@ -21,6 +22,15 @@ func main() { b.JSON = opts.JSON b.LogWriter = os.Stdout b.LogConv = chat1.ConvIDStr(opts.LogConvIDStr) + // set the bot owner for private commands + if opts.Owner != "" { + b.Meta["owner"] = opts.Owner + } + if opts.KvStoreTeam != "" { + b.Meta["kvstore"] = opts.KvStoreTeam + loadNsfwAllowed(b) + } + // set reddit login, which enables reddit commands if opts.RedditUser != "" && opts.RedditPass != "" { b.Meta["reddit-user"] = opts.RedditUser b.Meta["reddit-pass"] = opts.RedditPass @@ -64,6 +74,16 @@ func main() { keybasebot.CommandPrefix("!price"), ), }, + keybasebot.BotCommand{ + Name: "nsfw", + Ad: nil, + Run: keybasebot.Adapt( + setNsfw, + keybasebot.MessageType("text"), + keybasebot.CommandPrefix("!nsfw"), + requireOwner(), + ), + }, ) // if there are reddit credentials add the reddit commands if opts.RedditPass != "" && opts.RedditUser != "" { @@ -71,7 +91,21 @@ func main() { keybasebot.BotCommand{ Name: "eyebleach", Ad: &cmd.EyebleachAd, - Run: keybasebot.Adapt(cmd.Eyebleach, keybasebot.MessageType("text"), keybasebot.CommandPrefix("!eyebleach")), + Run: keybasebot.Adapt( + cmd.Eyebleach, + keybasebot.MessageType("text"), + keybasebot.CommandPrefix("!eyebleach"), + ), + }, + keybasebot.BotCommand{ + Name: "boobs", + Ad: nil, + Run: keybasebot.Adapt( + cmd.Boobs, + keybasebot.MessageType("text"), + keybasebot.CommandPrefix("!boobs"), + nsfwFilter(), + ), }, ) fmt.Printf("%+v\n", opts) @@ -91,3 +125,21 @@ func main() { // then run b.Run() } + +func loadNsfwAllowed(b *keybasebot.Bot) { + // get the team from meta + data, ok := b.Meta["kvstore"] + if ok { + // make something to fill + allowedTeams := make(map[chat1.ConvIDStr]bool) + team := data.(string) + kvKey := kvstore.New("nsfwAllowed", &allowedTeams, -1) + err := kvstore.Get(b.KB, team, "ssh0le", &kvKey) + if err != nil { + return + } + // set the allowed teams into meta + b.Meta["nsfwAllowed"] = allowedTeams + } + return +} \ No newline at end of file diff --git a/ownerCommands.go b/ownerCommands.go new file mode 100644 index 0000000..4c174de --- /dev/null +++ b/ownerCommands.go @@ -0,0 +1,67 @@ +package main + +import ( + "github.com/kf5grd/keybasebot" + "github.com/kf5grd/keybasebot/pkg/kvstore" + "samhofi.us/x/keybase/v2/types/chat1" +) + +func setNsfw(m chat1.MsgSummary, b *keybasebot.Bot) (bool, error) { + b.KB.SendMessageByConvID(m.ConvID, "Pong!") + b.Logger.Info("owner command in convid %s", m.ConvID) + return true, nil +} + +func addNsfwTeam(b *keybasebot.Bot, c chat1.ConvIDStr) bool { + allowedTeams := make(map[chat1.ConvIDStr]bool) + // get the allowed teams + data, ok := b.Meta["nsfwAllowed"] + if !ok { + // the key doesn't exist yet so go ahead and create it + allowedTeams[c] = true + } else { + // the key exists and needs to be updated + allowedTeams := data.(map[chat1.ConvIDStr]bool) + allowedTeams[c] = true + } + // write the key to meta + b.Meta["nsfwAllowed"] = allowedTeams + // write the key to kvStore if enabled + data, ok = b.Meta["kvstore"] + if ok { + team := data.(string) + kvKey := kvstore.New("nsfwAllowed", allowedTeams, -1) + err := kvstore.Put(b.KB, team, "ssh0le", kvKey) + if err != nil { + return false + } + } + return true +} + +func delNsfwTeam(b *keybasebot.Bot, c chat1.ConvIDStr) bool { + allowedTeams := make(map[chat1.ConvIDStr]bool) + // get the allowed teams + data, ok := b.Meta["nsfwAllowed"] + if !ok { + // the key doesn't exist yet so go return + return true + } else { + // the key exists and needs to be updated + allowedTeams := data.(map[chat1.ConvIDStr]bool) + delete(allowedTeams, c) + } + // write the key to meta + b.Meta["nsfwAllowed"] = allowedTeams + // write the key to kvStore if enabled + data, ok = b.Meta["kvstore"] + if ok { + team := data.(string) + kvKey := kvstore.New("nsfwAllowed", allowedTeams, -1) + err := kvstore.Put(b.KB, team, "ssh0le", kvKey) + if err != nil { + return false + } + } + return true +}