Getting started¶
A bot that reads a Discord channel and answers in a thread, without a Discord SDK anywhere in your own code.
Install¶
The contract and the provider are separate modules. You depend on the contract; the provider is a blank import.
go get gitlab.com/phpboyscout/go/chat-platform
go get gitlab.com/phpboyscout/go/chat-platform-discord
Connect and read¶
package main
import (
"context"
"log"
"os"
chatplatform "gitlab.com/phpboyscout/go/chat-platform"
_ "gitlab.com/phpboyscout/go/chat-platform-discord"
)
func main() {
factory, ok := chatplatform.Lookup("discord")
if !ok {
log.Fatal("no discord provider registered")
}
p, err := factory(chatplatform.Config{
Token: os.Getenv("DISCORD_TOKEN"),
Space: "1531227937678954747",
AllowedChannels: []chatplatform.ID{"1531227938622800055"},
})
if err != nil {
log.Fatal(err)
}
defer p.Reader.Close()
ctx := context.Background()
if err := p.Reader.Connect(ctx); err != nil {
log.Fatal(err)
}
for msg := range p.Reader.Messages() {
if _, err := p.Actor.ReplyInThread(ctx, msg.Ref(), "Re: "+msg.Author.Name, "Looking into it."); err != nil {
log.Print(err)
}
}
}
Three things are worth noticing.
Lookup takes a string. The provider registered itself when it was
imported. Swapping platforms is a configuration change and an import, not a
code change.
AllowedChannels is enforced by the provider. An empty allowlist permits
nothing. A watchlist that silently means everywhere is the wrong default for
reading people's messages, so it fails closed.
Connect is where the network happens. factory validates configuration
and nothing else, so you can construct a provider, inspect what it supports, and
test all of it without credentials.
Read without being able to write¶
Set ReadOnly and the provider comes back with no Actor at all.
p, _ := factory(chatplatform.Config{
Token: os.Getenv("DISCORD_TOKEN"),
Space: guild,
AllowedChannels: channels,
ReadOnly: true,
})
p.Actor == nil // always
There is no flag to check and no method that refuses at call time. A deployment that cannot post cannot delete a message either, and that is a property of the types rather than of a check somebody remembers to write.
Use a capability¶
Moderation, member lookup, interactive components and slash commands are optional. Ask for them by type assertion:
A provider that has none of them is legitimate, which is why they are not part
of Actor. See Optional capabilities.
Notice a reconnect that lost messages¶
if st := p.Reader.State(); st.LastReconnectLostEvents {
log.Print("reconnect re-identified; messages during the gap were dropped")
}
This is the failure worth alerting on, and it is invisible without being told. See Reconnects and lost events.
Next¶
- Author a provider for a platform not covered yet.
- Run the conformance harness against it.