-
Notifications
You must be signed in to change notification settings - Fork 270
Expand file tree
/
Copy pathdiscord.go
More file actions
156 lines (133 loc) · 5.27 KB
/
discord.go
File metadata and controls
156 lines (133 loc) · 5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package discord
import (
"context"
"fmt"
"github.com/bwmarrin/discordgo"
)
//go:generate mockery --name=discordSession --output=. --case=underscore --inpackage
type discordSession interface {
ChannelMessageSend(channelID string, content string, options ...discordgo.RequestOption) (*discordgo.Message, error)
}
// Compile-time check to ensure that discordgo.Session implements the discordSession interface.
var _ discordSession = new(discordgo.Session)
// Discord struct holds necessary data to communicate with the Discord API.
type Discord struct {
client discordSession
channelIDs []string
}
// New returns a new instance of a Discord notification service.
// The instance is created with a default Discord session. For advanced configuration
// such as proxy support or custom timeouts, use SetClient to provide a custom session
// before calling the authentication methods.
func New() *Discord {
return &Discord{
client: &discordgo.Session{},
channelIDs: []string{},
}
}
// authenticate will configure authentication on the existing Discord session.
// If a custom session was set via SetClient, it preserves all custom configuration
// (HTTP client, proxy settings, etc.) while setting the authentication token.
func (d *Discord) authenticate(token string) error {
// If we have an existing session, configure it in-place
if d.client != nil {
if session, ok := d.client.(*discordgo.Session); ok {
session.Token = token
session.Identify.Token = token
session.Identify.Intents = discordgo.IntentsGuildMessageTyping
return nil
}
}
// Fallback: create new session (only if client is nil or not a Session)
client, err := discordgo.New(token)
if err != nil {
return err
}
client.Identify.Intents = discordgo.IntentsGuildMessageTyping
d.client = client
return nil
}
// DefaultSession returns a new Discord session with default configuration.
// This allows configuring a custom session without importing the discordgo package.
// The session is created with Discord's standard defaults and can be customized before
// passing it to SetClient.
//
// Example - Configure proxy without importing discordgo:
//
// session := discord.DefaultSession()
// session.Client = &http.Client{
// Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
// }
// d := discord.New()
// d.SetClient(session)
// d.AuthenticateWithBotToken(token)
func DefaultSession() *discordgo.Session {
// Use discordgo.New with empty token to get proper defaults
session, _ := discordgo.New("")
return session
}
// SetClient sets a custom Discord session, allowing full control over the
// session configuration including HTTP client, proxy settings, intents, and
// other Discord session options.
//
// This is useful for advanced use cases like proxy configuration or custom timeouts.
// After calling SetClient, you can still use the AuthenticateWith* methods to set
// the authentication token while preserving your custom configuration.
//
// Use DefaultSession() to get a session instance without importing discordgo.
//
// Example - Configure proxy, then authenticate:
//
// session := discord.DefaultSession()
// session.Client = &http.Client{
// Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)},
// }
// d := discord.New()
// d.SetClient(session)
// d.AuthenticateWithBotToken(token) // Preserves proxy configuration
func (d *Discord) SetClient(client *discordgo.Session) {
d.client = client
}
// AuthenticateWithBotToken authenticates you as a bot to Discord via the given access token.
// For more info, see here: https://pkg.go.dev/github.com/bwmarrin/discordgo@v0.22.1#New
func (d *Discord) AuthenticateWithBotToken(token string) error {
token = parseBotToken(token)
return d.authenticate(token)
}
// AuthenticateWithOAuth2Token authenticates you to Discord via the given OAUTH2 token.
// For more info, see here: https://pkg.go.dev/github.com/bwmarrin/discordgo@v0.22.1#New
func (d *Discord) AuthenticateWithOAuth2Token(token string) error {
token = parseOAuthToken(token)
return d.authenticate(token)
}
// parseBotToken parses a regular token to a bot token that is understandable for discord.
// For more info, see here: https://pkg.go.dev/github.com/bwmarrin/discordgo@v0.22.1#New
func parseBotToken(token string) string {
return "Bot " + token
}
// parseBotToken parses a regular token to a OAUTH2 token that is understandable for discord.
// For more info, see here: https://pkg.go.dev/github.com/bwmarrin/discordgo@v0.22.1#New
func parseOAuthToken(token string) string {
return "Bearer " + token
}
// AddReceivers takes Discord channel IDs and adds them to the internal channel ID list. The Send method will send
// a given message to all those channels.
func (d *Discord) AddReceivers(channelIDs ...string) {
d.channelIDs = append(d.channelIDs, channelIDs...)
}
// Send takes a message subject and a message body and sends them to all previously set chats.
func (d Discord) Send(ctx context.Context, subject, message string) error {
fullMessage := subject + "\n" + message // Treating subject as message title
for _, channelID := range d.channelIDs {
select {
case <-ctx.Done():
return ctx.Err()
default:
_, err := d.client.ChannelMessageSend(channelID, fullMessage)
if err != nil {
return fmt.Errorf("send message to Discord channel %q: %w", channelID, err)
}
}
}
return nil
}