forked from nikoksr/notify
-
Notifications
You must be signed in to change notification settings - Fork 0
/
reddit.go
87 lines (76 loc) · 2.51 KB
/
reddit.go
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
// Package reddit implements a Reddit notifier, allowing messages to be sent to multiple recipients
package reddit
import (
"context"
"crypto/tls"
"net/http"
"github.com/pkg/errors"
"github.com/vartanbeno/go-reddit/v2/reddit"
)
//go:generate mockery --name=redditMessageClient --output=. --case=underscore --inpackage
type redditMessageClient interface {
Send(context.Context, *reddit.SendMessageRequest) (*reddit.Response, error)
}
// Compile-time check to ensure that reddit.MessageService implements the redditMessageClient interface.
var _ redditMessageClient = new(reddit.MessageService)
// Reddit struct holds necessary data to communicate with the Reddit API.
type Reddit struct {
client redditMessageClient
recipients []string
}
// New returns a new instance of a Reddit notification service.
// For more information on obtaining client credentials:
//
// -> https://github.com/reddit-archive/reddit/wiki/OAuth2
func New(clientID, clientSecret, username, password string) (*Reddit, error) {
// Disable HTTP2 in http client
// Details: https://www.reddit.com/r/redditdev/comments/t8e8hc/getting_nothing_but_429_responses_when_using_go/i18yga2/
h := http.Client{
Transport: &http.Transport{
TLSNextProto: map[string]func(authority string, c *tls.Conn) http.RoundTripper{},
},
}
rClient, err := reddit.NewClient(
reddit.Credentials{
ID: clientID,
Secret: clientSecret,
Username: username,
Password: password,
},
reddit.WithHTTPClient(&h),
reddit.WithUserAgent("github.com/heilmela/notify"),
)
if err != nil {
return nil, errors.Wrap(err, "failed to instantiate base Reddit client")
}
r := &Reddit{
client: rClient.Message,
recipients: []string{},
}
return r, nil
}
// AddReceivers takes Reddit usernames and adds them to the internal recipient list. The Send method will send
// a given message to all of those users.
func (r *Reddit) AddReceivers(recipients ...string) {
r.recipients = append(r.recipients, recipients...)
}
// Send takes a message subject and a message body and sends them to all previously set recipients.
func (r *Reddit) Send(ctx context.Context, subject, message string) error {
for i := range r.recipients {
select {
case <-ctx.Done():
return ctx.Err()
default:
m := reddit.SendMessageRequest{
To: r.recipients[i],
Subject: subject,
Text: message,
}
_, err := r.client.Send(ctx, &m)
if err != nil {
return errors.Wrapf(err, "failed to send message to Reddit recipient '%s'", r.recipients[i])
}
}
}
return nil
}