all: update to go1.18 and any interface

This commit is contained in:
Chris Sexton 2022-03-21 21:32:44 -04:00
parent 3af3633559
commit 471c3ecff4
41 changed files with 189 additions and 183 deletions

View File

@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.16
- name: Set up Go 1.18
uses: actions/setup-go@v1
with:
go-version: 1.16.x
go-version: 1.18.x
id: go
- name: Check out code into the Go module directory

1
.gitignore vendored
View File

@ -74,3 +74,4 @@ gus.sh
rathaus.sh
run.sh
impact.ttf
.env

View File

@ -21,7 +21,7 @@ import (
"github.com/velour/catbase/bot/msg"
)
func (b *bot) Receive(conn Connector, kind Kind, msg msg.Message, args ...interface{}) bool {
func (b *bot) Receive(conn Connector, kind Kind, msg msg.Message, args ...any) bool {
// msg := b.buildMessage(client, inMsg)
// do need to look up user and fix it
@ -64,7 +64,7 @@ func ParseValues(r *regexp.Regexp, body string) RegexValues {
return out
}
func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.Message, args ...interface{}) bool {
func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.Message, args ...any) bool {
t := reflect.TypeOf(plugin).String()
for _, spec := range b.callbacks[t][evt] {
if spec.Regex.MatchString(message.Body) {
@ -84,7 +84,7 @@ func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.M
}
// Send a message to the connection
func (b *bot) Send(conn Connector, kind Kind, args ...interface{}) (string, error) {
func (b *bot) Send(conn Connector, kind Kind, args ...any) (string, error) {
if b.quiet {
return "", nil
}
@ -269,14 +269,14 @@ func (b *bot) selfSaid(conn Connector, channel, message string, action bool) {
}
// PubToASub sends updates to subscribed URLs
func (b *bot) PubToASub(subject string, payload interface{}) {
func (b *bot) PubToASub(subject string, payload any) {
key := fmt.Sprintf("pubsub.%s.url", subject)
subs := b.config.GetArray(key, []string{})
if len(subs) == 0 {
return
}
encodedBody, _ := json.Marshal(struct {
Payload interface{} `json:"payload"`
Payload any `json:"payload"`
}{payload})
body := bytes.NewBuffer(encodedBody)
for _, url := range subs {

View File

@ -56,11 +56,11 @@ type Request struct {
Kind Kind
Msg msg.Message
Values RegexValues
Args []interface{}
Args []any
}
type Kind int
type Callback func(Connector, Kind, msg.Message, ...interface{}) bool
type Callback func(Connector, Kind, msg.Message, ...any) bool
type ResponseHandler func(Request) bool
type CallbackMap map[string]map[Kind][]HandlerSpec
@ -96,11 +96,11 @@ type Bot interface {
// Send transmits a message to a Connector.
// Kind is listed in the bot's enum, one of bot.Message/Reply/Action/etc
// Usually, the first vararg should be a channel ID, but refer to the Connector for info
Send(Connector, Kind, ...interface{}) (string, error)
Send(Connector, Kind, ...any) (string, error)
// bot receives from a Connector.
// The Kind arg should be one of bot.Message/Reply/Action/etc
Receive(Connector, Kind, msg.Message, ...interface{}) bool
Receive(Connector, Kind, msg.Message, ...any) bool
// Register a set of plugin callbacks
// Kind will be matched to the event for the callback
@ -174,7 +174,7 @@ type Bot interface {
CheckPassword(secret, password string) bool
// PubToASub publishes a message to any subscribers
PubToASub(subject string, payload interface{})
PubToASub(subject string, payload any)
}
// Connector represents a server connection to a chat service
@ -183,7 +183,7 @@ type Connector interface {
RegisterEvent(Callback)
// Send transmits a message on the connector
Send(Kind, ...interface{}) (string, error)
Send(Kind, ...any) (string, error)
// GetEmojiList returns a connector's known custom emoji
GetEmojiList() map[string]string
@ -221,7 +221,7 @@ type Connector interface {
// Plugin interface used for compatibility with the Plugin interface
// Uhh it turned empty, but we're still using it to ID plugins
type Plugin interface{}
type Plugin any
type Role struct {
ID string `json:"id"`

View File

@ -35,7 +35,7 @@ func (mb *MockBot) WhoAmI() string { return "tester" }
func (mb *MockBot) DefaultConnector() Connector { return nil }
func (mb *MockBot) GetPassword() string { return "12345" }
func (mb *MockBot) SetQuiet(bool) {}
func (mb *MockBot) Send(c Connector, kind Kind, args ...interface{}) (string, error) {
func (mb *MockBot) Send(c Connector, kind Kind, args ...any) (string, error) {
switch kind {
case Message:
mb.Messages = append(mb.Messages, args[1].(string))
@ -60,7 +60,7 @@ func (mb *MockBot) RegisterRegexCmd(p Plugin, kind Kind, r *regexp.Regexp, h Res
func (mb *MockBot) RegisterWebName(_ http.Handler, _, _ string) {}
func (mb *MockBot) RegisterWeb(_ http.Handler, _ string) {}
func (mb *MockBot) GetWebNavigation() []EndPoint { return nil }
func (mb *MockBot) Receive(c Connector, kind Kind, msg msg.Message, args ...interface{}) bool {
func (mb *MockBot) Receive(c Connector, kind Kind, msg msg.Message, args ...any) bool {
return false
}
func (mb *MockBot) Filter(msg msg.Message, s string) string { return s }
@ -118,12 +118,12 @@ func NewMockBot() *MockBot {
return &b
}
func (mb *MockBot) GetPluginNames() []string { return nil }
func (mb *MockBot) RefreshPluginBlacklist() error { return nil }
func (mb *MockBot) RefreshPluginWhitelist() error { return nil }
func (mb *MockBot) GetWhitelist() []string { return []string{} }
func (mb *MockBot) OnBlacklist(ch, p string) bool { return false }
func (mb *MockBot) URLFormat(title, url string) string { return title + url }
func (mb *MockBot) CheckPassword(secret, password string) bool { return true }
func (mb *MockBot) ListenAndServe() {}
func (mb *MockBot) PubToASub(subject string, payload interface{}) {}
func (mb *MockBot) GetPluginNames() []string { return nil }
func (mb *MockBot) RefreshPluginBlacklist() error { return nil }
func (mb *MockBot) RefreshPluginWhitelist() error { return nil }
func (mb *MockBot) GetWhitelist() []string { return []string{} }
func (mb *MockBot) OnBlacklist(ch, p string) bool { return false }
func (mb *MockBot) URLFormat(title, url string) string { return title + url }
func (mb *MockBot) CheckPassword(secret, password string) bool { return true }
func (mb *MockBot) ListenAndServe() {}
func (mb *MockBot) PubToASub(subject string, payload any) {}

View File

@ -20,7 +20,7 @@ type Message struct {
ChannelName string
Body string
IsIM bool
Raw interface{}
Raw any
Command bool
Action bool
Time time.Time

View File

@ -48,7 +48,7 @@ func (d *Discord) RegisterEvent(callback bot.Callback) {
d.event = callback
}
func (d Discord) Send(kind bot.Kind, args ...interface{}) (string, error) {
func (d Discord) Send(kind bot.Kind, args ...any) (string, error) {
switch kind {
case bot.Ephemeral:
@ -87,7 +87,7 @@ func (d Discord) Send(kind bot.Kind, args ...interface{}) (string, error) {
}
}
func (d *Discord) sendMessage(channel, message string, meMessage bool, args ...interface{}) (string, error) {
func (d *Discord) sendMessage(channel, message string, meMessage bool, args ...any) (string, error) {
if meMessage && !strings.HasPrefix(message, "_") && !strings.HasSuffix(message, "_") {
message = "_" + message + "_"
}

View File

@ -61,7 +61,7 @@ func (i *Irc) RegisterEvent(f bot.Callback) {
i.event = f
}
func (i *Irc) Send(kind bot.Kind, args ...interface{}) (string, error) {
func (i *Irc) Send(kind bot.Kind, args ...any) (string, error) {
switch kind {
case bot.Reply:
case bot.Message:
@ -78,7 +78,7 @@ func (i *Irc) JoinChannel(channel string) {
i.Client.Out <- irc.Msg{Cmd: irc.JOIN, Args: []string{channel}}
}
func (i *Irc) sendMessage(channel, message string, args ...interface{}) (string, error) {
func (i *Irc) sendMessage(channel, message string, args ...any) (string, error) {
for len(message) > 0 {
m := irc.Msg{
Cmd: "PRIVMSG",
@ -123,7 +123,7 @@ func (i *Irc) sendMessage(channel, message string, args ...interface{}) (string,
}
// Sends action to channel
func (i *Irc) sendAction(channel, message string, args ...interface{}) (string, error) {
func (i *Irc) sendAction(channel, message string, args ...any) (string, error) {
message = actionPrefix + " " + message + "\x01"
return i.sendMessage(channel, message, args...)

View File

@ -171,7 +171,7 @@ func (s *SlackApp) Serve() error {
// or false if the ts isn't yet in the ring (and adds it)
func (s *SlackApp) checkRingOrAdd(ts string) bool {
found := false
s.msgIDBuffer.Do(func(p interface{}) {
s.msgIDBuffer.Do(func(p any) {
if p == nil {
return
}
@ -237,7 +237,7 @@ func (s *SlackApp) msgReceivd(msg *slackevents.MessageEvent) {
s.msgBuffer = s.msgBuffer.Next()
}
func (s *SlackApp) Send(kind bot.Kind, args ...interface{}) (string, error) {
func (s *SlackApp) Send(kind bot.Kind, args ...any) (string, error) {
switch kind {
case bot.Message:
return s.sendMessage(args[0].(string), args[1].(string), false, args...)
@ -264,7 +264,7 @@ func (s *SlackApp) Send(kind bot.Kind, args ...interface{}) (string, error) {
return "", fmt.Errorf("No handler for message type %d", kind)
}
func (s *SlackApp) sendMessage(channel, message string, meMessage bool, args ...interface{}) (string, error) {
func (s *SlackApp) sendMessage(channel, message string, meMessage bool, args ...any) (string, error) {
ts, err := "", fmt.Errorf("")
nick := s.config.Get("Nick", "bot")
@ -667,7 +667,7 @@ func (s *SlackApp) reactionReceived(event *slackevents.ReactionAddedEvent) error
body := "unknown message"
// Iterate through the ring and print its contents
s.msgBuffer.Do(func(p interface{}) {
s.msgBuffer.Do(func(p any) {
switch m := p.(type) {
case nil:
case *slackevents.MessageEvent:

63
go.mod
View File

@ -1,73 +1,84 @@
module github.com/velour/catbase
go 1.16
go 1.18
require (
code.chrissexton.org/cws/getaoc v0.0.0-20191201043947-d5417d4b618d
github.com/AlekSi/pointer v1.1.0 // indirect
github.com/ChimeraCoder/anaconda v2.0.0+incompatible
github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7 // indirect
github.com/PuerkitoBio/goquery v1.5.0
github.com/bwmarrin/discordgo v0.23.2
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff
github.com/chrissexton/sentiment v0.0.0-20190927141846-d69c422ba035
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90
github.com/go-chi/chi/v5 v5.0.3
github.com/gocolly/colly v1.2.0
github.com/google/uuid v1.1.1
github.com/itchyny/gojq v0.12.3
github.com/james-bowman/nlp v0.0.0-20191016091239-d9dbfaff30c6
github.com/jmoiron/sqlx v1.2.0
github.com/kevinburke/twilio-go v0.0.0-20200424172635-4f0b2357b852
github.com/mattn/go-sqlite3 v1.14.8
github.com/mmcdole/gofeed v1.0.0-beta2
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254
github.com/rs/zerolog v1.15.0
github.com/slack-go/slack v0.9.4
github.com/stretchr/testify v1.4.0
github.com/trubitsyn/go-zero-width v1.0.1
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
gopkg.in/go-playground/webhooks.v5 v5.13.0
)
require (
github.com/AlekSi/pointer v1.1.0 // indirect
github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7 // indirect
github.com/andybalholm/cascadia v1.1.0 // indirect
github.com/antchfx/htmlquery v1.2.0 // indirect
github.com/antchfx/xmlquery v1.2.0 // indirect
github.com/antchfx/xpath v1.1.1 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/azr/backoff v0.0.0-20160115115103-53511d3c7330 // indirect
github.com/bwmarrin/discordgo v0.23.2
github.com/cdipaolo/goml v0.0.0-20190412180403-e1f51f713598
github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff
github.com/chrissexton/sentiment v0.0.0-20190927141846-d69c422ba035
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc // indirect
github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90
github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17 // indirect
github.com/go-chi/chi/v5 v5.0.3
github.com/go-stack/stack v1.8.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gocolly/colly v1.2.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 // indirect
github.com/golang/protobuf v1.3.1 // indirect
github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82 // indirect
github.com/gonum/internal v0.0.0-20181124074243-f884aa714029 // indirect
github.com/google/uuid v1.1.1
github.com/gorilla/websocket v1.4.2 // indirect
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1 // indirect
github.com/itchyny/gojq v0.12.3
github.com/james-bowman/nlp v0.0.0-20191016091239-d9dbfaff30c6
github.com/itchyny/timefmt-go v0.1.2 // indirect
github.com/james-bowman/sparse v0.0.0-20190423065201-80c6877364c7 // indirect
github.com/jmoiron/sqlx v1.2.0
github.com/kennygrant/sanitize v1.2.4 // indirect
github.com/kevinburke/go-types v0.0.0-20200309064045-f2d4aea18a7a // indirect
github.com/kevinburke/go.uuid v1.2.0 // indirect
github.com/kevinburke/rest v0.0.0-20200429221318-0d2892b400f8 // indirect
github.com/kevinburke/twilio-go v0.0.0-20200424172635-4f0b2357b852
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/mattn/go-sqlite3 v1.14.8
github.com/mmcdole/gofeed v1.0.0-beta2
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/olebedev/when v0.0.0-20190311101825-c3b538a97254
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d // indirect
github.com/rs/zerolog v1.15.0
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
github.com/slack-go/slack v0.9.4
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.4.0
github.com/temoto/robotstxt v1.1.1 // indirect
github.com/trubitsyn/go-zero-width v1.0.1
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
github.com/ttacon/libphonenumber v1.1.0 // indirect
github.com/velour/velour v0.0.0-20160303155839-8e090e68d158
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
golang.org/x/exp v0.0.0-20191014171548-69215a2ee97e // indirect
golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 // indirect
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect
golang.org/x/text v0.3.7 // indirect
gonum.org/v1/gonum v0.6.0 // indirect
google.golang.org/appengine v1.6.5 // indirect
gopkg.in/go-playground/webhooks.v5 v5.13.0
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

6
go.sum
View File

@ -174,7 +174,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4 h1:DZshvxDdVoeKIbudAdFEKi+f70l51luSy/7b76ibTY0=
golang.org/x/net v0.0.0-20211118161319-6a13c67c3ce4/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -186,16 +185,11 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -192,7 +192,7 @@ func (p *AchievementsPlugin) greatCmd(r bot.Request) bool {
return true
}
func (p *AchievementsPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *AchievementsPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
ch := message.Channel
me := p.bot.WhoAmI()
msg := "The achievements plugins awards trophies."

View File

@ -356,7 +356,7 @@ func (p *AdminPlugin) getConfigCmd(r bot.Request) bool {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *AdminPlugin) help(conn bot.Connector, kind bot.Kind, m msg.Message, args ...interface{}) bool {
func (p *AdminPlugin) help(conn bot.Connector, kind bot.Kind, m msg.Message, args ...any) bool {
p.bot.Send(conn, bot.Message, m.Channel, "This does super secret things that you're not allowed to know about.")
return true
}

View File

@ -181,7 +181,7 @@ func (p *BabblerPlugin) sayIt(r bot.Request, what string) bool {
return what != ""
}
func (p *BabblerPlugin) help(c bot.Connector, kind bot.Kind, msg msg.Message, args ...interface{}) bool {
func (p *BabblerPlugin) help(c bot.Connector, kind bot.Kind, msg msg.Message, args ...any) bool {
commands := []string{
"initialize babbler for seabass",
"merge babbler drseabass into seabass",

View File

@ -232,7 +232,7 @@ func (p *BeersPlugin) register() {
// This function returns true if the plugin responds in a meaningful way to the users message.
// Otherwise, the function returns false and the bot continues execution of other plugins.
// Help responds to help requests. Every plugin must implement a help function.
func (p *BeersPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *BeersPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
msg := "Beers: imbibe by using either beers +=,=,++ or with the !imbibe/drink " +
"commands. I'll keep a count of how many beers you've had and then if you want " +
"to reset, just !puke it all up!"
@ -305,9 +305,9 @@ type checkin struct {
Created_at string
Checkin_comment string
Rating_score float64
Beer map[string]interface{}
Brewery map[string]interface{}
Venue interface{}
Beer map[string]any
Brewery map[string]any
Venue any
User mrUntappd
Media struct {
Count int
@ -442,7 +442,7 @@ func (p *BeersPlugin) checkUntappd(c bot.Connector, channel string) {
func (p *BeersPlugin) sendCheckin(c bot.Connector, channel string, user untappdUser, checkin checkin) {
venue := ""
switch v := checkin.Venue.(type) {
case map[string]interface{}:
case map[string]any:
venue = " at " + v["venue_name"].(string)
}
beerName := checkin.Beer["beer_name"].(string)
@ -452,7 +452,7 @@ func (p *BeersPlugin) sendCheckin(c bot.Connector, channel string, user untappdU
Msgf("user.chanNick: %s, user.untappdUser: %s, checkin.User.User_name: %s",
user.chanNick, user.untappdUser, checkin.User.User_name)
args := []interface{}{}
args := []any{}
if checkin.Badges.Count > 0 {
for _, b := range checkin.Badges.Items {
args = append(args, bot.ImageAttachment{
@ -494,7 +494,7 @@ func (p *BeersPlugin) sendCheckin(c bot.Connector, channel string, user untappdU
msg, checkin.Checkin_comment)
}
args = append([]interface{}{channel, msg}, args...)
args = append([]any{channel, msg}, args...)
user.lastCheckin = checkin.Checkin_id
_, err := p.db.Exec(`update untappd set

View File

@ -107,7 +107,7 @@ func (p *CliPlugin) handleWeb(w http.ResponseWriter, r *http.Request) {
// Completing the Connector interface, but will not actually be a connector
func (p *CliPlugin) RegisterEvent(cb bot.Callback) {}
func (p *CliPlugin) Send(kind bot.Kind, args ...interface{}) (string, error) {
func (p *CliPlugin) Send(kind bot.Kind, args ...any) (string, error) {
switch kind {
case bot.Message:
fallthrough

View File

@ -672,7 +672,7 @@ func (p *CounterPlugin) removeFromCmd(r bot.Request) bool {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *CounterPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *CounterPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.b.Send(c, bot.Message, message.Channel, "You can set counters incrementally by using "+
"`<noun>++` and `<noun>--`. You can see all of your counters using "+
"`inspect`, erase them with `clear`, and view single counters with "+

View File

@ -59,7 +59,7 @@ func (p *DicePlugin) rollCmd(r bot.Request) bool {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *DicePlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *DicePlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.Bot.Send(c, bot.Message, message.Channel, "Roll dice using notation XdY. Try \"3d20\".")
return true
}

View File

@ -740,7 +740,7 @@ func (p *FactoidPlugin) register() {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *FactoidPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *FactoidPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.Bot.Send(c, bot.Message, message.Channel, "I can learn facts and spit them back out. You can say \"this is that\" or \"he <has> $5\". Later, trigger the factoid by just saying the trigger word, \"this\" or \"he\" in these examples.")
p.Bot.Send(c, bot.Message, message.Channel, "I can also figure out some variables including: $nonzero, $digit, $nick, and $someone.")
return true

View File

@ -343,7 +343,7 @@ func (p *FirstPlugin) announceFirst(c bot.Connector, first *FirstEntry) {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *FirstPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *FirstPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "You can ask 'who's on first?' to find out.")
return true
}

View File

@ -228,7 +228,7 @@ func (p *GoalsPlugin) checkGoal(c bot.Connector, ch, what, who string) {
return
}
func (p *GoalsPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *GoalsPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
ch := message.Channel
msg := "Goals can set goals and competition for your counters."
for _, cmd := range p.handlers {

View File

@ -95,15 +95,15 @@ func (p *GPT3Plugin) message(r bot.Request) bool {
}
type gpt3Request struct {
Prompt string `json:"prompt"`
MaxTokens int `json:"max_tokens"`
Temperature float64 `json:"temperature"`
TopP float64 `json:"top_p"`
N int `json:"n"`
Stream bool `json:"stream"`
Logprobs interface{} `json:"logprobs"`
Stop []string `json:"stop"`
Echo bool `json:"echo"`
Prompt string `json:"prompt"`
MaxTokens int `json:"max_tokens"`
Temperature float64 `json:"temperature"`
TopP float64 `json:"top_p"`
N int `json:"n"`
Stream bool `json:"stream"`
Logprobs any `json:"logprobs"`
Stop []string `json:"stop"`
Echo bool `json:"echo"`
}
type gpt3Response struct {
@ -112,9 +112,9 @@ type gpt3Response struct {
Created int `json:"created"`
Model string `json:"model"`
Choices []struct {
Text string `json:"text"`
Index int `json:"index"`
Logprobs interface{} `json:"logprobs"`
FinishReason string `json:"finish_reason"`
Text string `json:"text"`
Index int `json:"index"`
Logprobs any `json:"logprobs"`
FinishReason string `json:"finish_reason"`
} `json:"choices"`
}

View File

@ -43,7 +43,7 @@ func New(b bot.Bot) *Impossible {
return i
}
func (p *Impossible) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *Impossible) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.b.Send(c, bot.Message, message.Channel, "You don't need to do anything. I'll take care of it. But guess what I'm thinking.")
return true
}
@ -129,12 +129,12 @@ func (p *Impossible) refreshImpossible() bool {
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
var object map[string]interface{}
var object map[string]any
json.Unmarshal([]byte(body), &object)
pages := object["query"].(map[string]interface{})["pages"].(map[string]interface{})
pages := object["query"].(map[string]any)["pages"].(map[string]any)
for _, page := range pages {
descriptionText := page.(map[string]interface{})["extract"].(string)
descriptionText := page.(map[string]any)["extract"].(string)
sentences := strings.Split(strings.ReplaceAll(descriptionText, "\n", " "), ". ")
for _, sentence := range sentences {
trimmed := strings.ToLower(strings.TrimSpace(sentence))

View File

@ -99,7 +99,7 @@ func (p *MemePlugin) message(r bot.Request) bool {
return true
}
func (p *MemePlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *MemePlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
webRoot := p.c.Get("BaseURL", "https://catbase.velour.ninja")
formats := p.c.GetMap("meme.memes", defaultFormats)
msg := "Use `/meme [format] [text]` to create a meme.\nI know the following formats:"

View File

@ -129,7 +129,7 @@ func (p *NerdepediaPlugin) message(r bot.Request) bool {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *NerdepediaPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *NerdepediaPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "nerd stuff")
return true
}

View File

@ -115,7 +115,7 @@ func (p *PickerPlugin) parse(body string) (int, []string, error) {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *PickerPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *PickerPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "Choose from a list of options. Try \"pick {a,b,c}\".")
return true
}

View File

@ -99,7 +99,7 @@ func (p *RememberPlugin) rememberCmd(r bot.Request) bool {
return true
}
func (p *RememberPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *RememberPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
msg := "remember will let you quote your idiot friends. Just type " +
"!remember <nick> <snippet> to remember what they said. Snippet can " +
"be any part of their message. Later on, you can ask for a random " +

View File

@ -84,7 +84,7 @@ func New(b bot.Bot) *ReminderPlugin {
return plugin
}
func (p *ReminderPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *ReminderPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
channel := message.Channel
from := message.User.Name
@ -217,7 +217,7 @@ func (p *ReminderPlugin) message(c bot.Connector, kind bot.Kind, message msg.Mes
return false
}
func (p *ReminderPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *ReminderPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "Pester someone with a reminder. Try \"remind <user> in <duration> message\".\n\nUnsure about duration syntax? Check https://golang.org/pkg/time/#ParseDuration")
return true
}

View File

@ -29,11 +29,11 @@ type RestPlugin struct {
handlers bot.HandlerTable
}
type postProcessor func(interface{}) string
type postProcessor func(any) string
var postProcessors = map[string]postProcessor{
"gpt2": func(input interface{}) string {
values := input.(map[string]interface{})
"gpt2": func(input any) string {
values := input.(map[string]any)
text := values["text"].(string)
lastStop := strings.LastIndexAny(text, ".!?")
if lastStop > 0 {
@ -123,7 +123,7 @@ type ScanableRegexp struct {
*regexp.Regexp
}
func (s *ScanableRegexp) Scan(src interface{}) error {
func (s *ScanableRegexp) Scan(src any) error {
var source string
switch src.(type) {
case string:
@ -143,7 +143,7 @@ type ScanableURL struct {
*url.URL
}
func (s *ScanableURL) Scan(src interface{}) error {
func (s *ScanableURL) Scan(src any) error {
var source string
switch src.(type) {
case string:
@ -374,7 +374,7 @@ func (p *RestPlugin) mkHandler(w wire) bot.ResponseHandler {
return true
}
log.Debug().Str("body", string(body)).Msg("got a body back")
var returnValues interface{}
var returnValues any
json.Unmarshal(body, &returnValues)
var msg string

View File

@ -53,7 +53,7 @@ func (p *RolesPlugin) Register() {
Handler: p.lsRoles,
},
}
p.b.Register(p, bot.Help, func(c bot.Connector, k bot.Kind, m msg.Message, args ...interface{}) bool {
p.b.Register(p, bot.Help, func(c bot.Connector, k bot.Kind, m msg.Message, args ...any) bool {
return p.lsRoles(bot.Request{
Conn: c,
Kind: k,

View File

@ -108,7 +108,7 @@ func New(b bot.Bot) *RPGPlugin {
return rpg
}
func (p *RPGPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *RPGPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
if strings.ToLower(message.Body) == "start rpg" {
b := NewRandomBoard()
ts, _ := p.bot.Send(c, bot.Message, message.Channel, b.toMessageString())
@ -119,12 +119,12 @@ func (p *RPGPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message,
return false
}
func (p *RPGPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *RPGPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "Go find a walkthrough or something.")
return true
}
func (p *RPGPlugin) replyMessage(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *RPGPlugin) replyMessage(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
identifier := args[0].(string)
if strings.ToLower(message.User.Name) != strings.ToLower(p.bot.Config().Get("Nick", "bot")) {
if b, ok := p.listenFor[identifier]; ok {

View File

@ -61,7 +61,7 @@ func New(b bot.Bot) *RSSPlugin {
return rss
}
func (p *RSSPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *RSSPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
tokens := strings.Fields(message.Body)
numTokens := len(tokens)
@ -98,7 +98,7 @@ func (p *RSSPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message,
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *RSSPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *RSSPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "try '!rss http://rss.cnn.com/rss/edition.rss'")
return true
}

View File

@ -173,7 +173,7 @@ func New(b bot.Bot) *SisyphusPlugin {
return sp
}
func (p *SisyphusPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *SisyphusPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
if strings.ToLower(message.Body) == "start sisyphus" {
b := NewRandomGame(c, p.bot, message.Channel, message.User.Name)
p.listenFor[b.id] = b
@ -183,12 +183,12 @@ func (p *SisyphusPlugin) message(c bot.Connector, kind bot.Kind, message msg.Mes
return false
}
func (p *SisyphusPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *SisyphusPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "https://en.wikipedia.org/wiki/Sisyphus")
return true
}
func (p *SisyphusPlugin) replyMessage(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *SisyphusPlugin) replyMessage(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
identifier := args[0].(string)
if strings.ToLower(message.User.Name) != strings.ToLower(p.bot.Config().Get("Nick", "bot")) {
if g, ok := p.listenFor[identifier]; ok {

View File

@ -105,7 +105,7 @@ func (p *SMSPlugin) reg(c bot.Connector, ch, who, num string) bool {
return true
}
func (p *SMSPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *SMSPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
ch := message.Channel
m := fmt.Sprintf("You can register your number with: `%s`", regSelfRegex)
m += fmt.Sprintf("\nYou can register somebody else with: `%s`", regSomeoneRegex)

View File

@ -46,7 +46,7 @@ type StockInfo struct {
ChangePercent string `json:"changepercent"`
}
func (p *StockPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *StockPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
if !message.Command {
return false
}
@ -88,7 +88,7 @@ func (p *StockPlugin) message(c bot.Connector, kind bot.Kind, message msg.Messag
return false
}
func (p *StockPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *StockPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "try '!stock-price SYMBOL'")
return true
}

View File

@ -63,7 +63,7 @@ func New(b bot.Bot) *TalkerPlugin {
return tp
}
func (p *TalkerPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *TalkerPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
channel := message.Channel
body := message.Body
lowermessage := strings.ToLower(body)
@ -111,7 +111,7 @@ func (p *TalkerPlugin) message(c bot.Connector, kind bot.Kind, message msg.Messa
return false
}
func (p *TalkerPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *TalkerPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "Hi, this is talker. I like to talk about FredFelps!")
return true
}

View File

@ -101,7 +101,7 @@ func (t *TellPlugin) troll(who string) bool {
return false
}
func (t *TellPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (t *TellPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
if strings.HasPrefix(strings.ToLower(message.Body), "tell ") ||
strings.HasPrefix(strings.ToLower(message.Body), "tellah ") {
parts := strings.Split(message.Body, " ")

View File

@ -38,7 +38,7 @@ func New(b bot.Bot) *TLDRPlugin {
return plugin
}
func (p *TLDRPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *TLDRPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
timeLimit := time.Duration(p.bot.Config().GetInt("TLDR.HourLimit", 1))
lowercaseMessage := strings.ToLower(message.Body)
if lowercaseMessage == "tl;dr" && p.lastRequest.After(time.Now().Add(-timeLimit*time.Hour)) {
@ -162,7 +162,7 @@ func (p *TLDRPlugin) getTopics() []string {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *TLDRPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *TLDRPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "tl;dr")
return true
}

View File

@ -109,7 +109,7 @@ func (p *TwitchPlugin) serveStreaming(w http.ResponseWriter, r *http.Request) {
if twitcher.gameID != "" {
status = "YES."
}
context := map[string]interface{}{"Name": twitcher.name, "Status": status}
context := map[string]any{"Name": twitcher.name, "Status": status}
t, err := template.New("streaming").Parse(page)
if err != nil {
@ -122,7 +122,7 @@ func (p *TwitchPlugin) serveStreaming(w http.ResponseWriter, r *http.Request) {
}
}
func (p *TwitchPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *TwitchPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
body := strings.ToLower(message.Body)
if body == "twitch status" {
channel := message.Channel
@ -143,7 +143,7 @@ func (p *TwitchPlugin) message(c bot.Connector, kind bot.Kind, message msg.Messa
return false
}
func (p *TwitchPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *TwitchPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
msg := "You can set the templates for streams with\n"
msg += fmt.Sprintf("twitch.istpl (default: %s)\n", isStreamingTplFallback)
msg += fmt.Sprintf("twitch.nottpl (default: %s)\n", notStreamingTplFallback)

View File

@ -55,7 +55,7 @@ func (p *YourPlugin) message(r bot.Request) bool {
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *YourPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
func (p *YourPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...any) bool {
p.bot.Send(c, bot.Message, message.Channel, "Your corrects people's grammar.")
return true
}

View File

@ -204,56 +204,56 @@ type fileResp struct {
}
type slackFile struct {
ID string `json:"id"`
Created int `json:"created"`
Timestamp int `json:"timestamp"`
Name string `json:"name"`
Title string `json:"title"`
Mimetype string `json:"mimetype"`
Filetype string `json:"filetype"`
PrettyType string `json:"pretty_type"`
User string `json:"user"`
Editable bool `json:"editable"`
Size int `json:"size"`
Mode string `json:"mode"`
IsExternal bool `json:"is_external"`
ExternalType string `json:"external_type"`
IsPublic bool `json:"is_public"`
PublicURLShared bool `json:"public_url_shared"`
DisplayAsBot bool `json:"display_as_bot"`
Username string `json:"username"`
URLPrivate string `json:"url_private"`
URLPrivateDownload string `json:"url_private_download"`
Thumb64 string `json:"thumb_64"`
Thumb80 string `json:"thumb_80"`
Thumb360 string `json:"thumb_360"`
Thumb360W int `json:"thumb_360_w"`
Thumb360H int `json:"thumb_360_h"`
Thumb480 string `json:"thumb_480,omitempty"`
Thumb480W int `json:"thumb_480_w,omitempty"`
Thumb480H int `json:"thumb_480_h,omitempty"`
Thumb160 string `json:"thumb_160"`
Thumb720 string `json:"thumb_720,omitempty"`
Thumb720W int `json:"thumb_720_w,omitempty"`
Thumb720H int `json:"thumb_720_h,omitempty"`
Thumb800 string `json:"thumb_800,omitempty"`
Thumb800W int `json:"thumb_800_w,omitempty"`
Thumb800H int `json:"thumb_800_h,omitempty"`
Thumb960 string `json:"thumb_960,omitempty"`
Thumb960W int `json:"thumb_960_w,omitempty"`
Thumb960H int `json:"thumb_960_h,omitempty"`
Thumb1024 string `json:"thumb_1024,omitempty"`
Thumb1024W int `json:"thumb_1024_w,omitempty"`
Thumb1024H int `json:"thumb_1024_h,omitempty"`
ImageExifRotation int `json:"image_exif_rotation"`
OriginalW int `json:"original_w"`
OriginalH int `json:"original_h"`
Permalink string `json:"permalink"`
PermalinkPublic string `json:"permalink_public"`
Channels []string `json:"channels"`
Groups []interface{} `json:"groups"`
Ims []interface{} `json:"ims"`
CommentsCount int `json:"comments_count"`
ID string `json:"id"`
Created int `json:"created"`
Timestamp int `json:"timestamp"`
Name string `json:"name"`
Title string `json:"title"`
Mimetype string `json:"mimetype"`
Filetype string `json:"filetype"`
PrettyType string `json:"pretty_type"`
User string `json:"user"`
Editable bool `json:"editable"`
Size int `json:"size"`
Mode string `json:"mode"`
IsExternal bool `json:"is_external"`
ExternalType string `json:"external_type"`
IsPublic bool `json:"is_public"`
PublicURLShared bool `json:"public_url_shared"`
DisplayAsBot bool `json:"display_as_bot"`
Username string `json:"username"`
URLPrivate string `json:"url_private"`
URLPrivateDownload string `json:"url_private_download"`
Thumb64 string `json:"thumb_64"`
Thumb80 string `json:"thumb_80"`
Thumb360 string `json:"thumb_360"`
Thumb360W int `json:"thumb_360_w"`
Thumb360H int `json:"thumb_360_h"`
Thumb480 string `json:"thumb_480,omitempty"`
Thumb480W int `json:"thumb_480_w,omitempty"`
Thumb480H int `json:"thumb_480_h,omitempty"`
Thumb160 string `json:"thumb_160"`
Thumb720 string `json:"thumb_720,omitempty"`
Thumb720W int `json:"thumb_720_w,omitempty"`
Thumb720H int `json:"thumb_720_h,omitempty"`
Thumb800 string `json:"thumb_800,omitempty"`
Thumb800W int `json:"thumb_800_w,omitempty"`
Thumb800H int `json:"thumb_800_h,omitempty"`
Thumb960 string `json:"thumb_960,omitempty"`
Thumb960W int `json:"thumb_960_w,omitempty"`
Thumb960H int `json:"thumb_960_h,omitempty"`
Thumb1024 string `json:"thumb_1024,omitempty"`
Thumb1024W int `json:"thumb_1024_w,omitempty"`
Thumb1024H int `json:"thumb_1024_h,omitempty"`
ImageExifRotation int `json:"image_exif_rotation"`
OriginalW int `json:"original_w"`
OriginalH int `json:"original_h"`
Permalink string `json:"permalink"`
PermalinkPublic string `json:"permalink_public"`
Channels []string `json:"channels"`
Groups []any `json:"groups"`
Ims []any `json:"ims"`
CommentsCount int `json:"comments_count"`
InitialComment struct {
ID string `json:"id"`
Created int `json:"created"`