aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2024-10-18 12:54:50 -0400
committerXe Iaso <me@xeiaso.net>2024-10-18 12:54:50 -0400
commit0cf68872c0f726d0af169387d5c8e8060cec130d (patch)
treec00d74978671baf769715377f9fe10c7f430cb68 /cmd
parentc758d20777cfbccfe02115c78dc9c24c836ea17d (diff)
downloadx-0cf68872c0f726d0af169387d5c8e8060cec130d.tar.xz
x-0cf68872c0f726d0af169387d5c8e8060cec130d.zip
super yolo
Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/mi/services/twitchevents/twitchevents.go129
1 files changed, 90 insertions, 39 deletions
diff --git a/cmd/mi/services/twitchevents/twitchevents.go b/cmd/mi/services/twitchevents/twitchevents.go
index 3ff6563..20687e4 100644
--- a/cmd/mi/services/twitchevents/twitchevents.go
+++ b/cmd/mi/services/twitchevents/twitchevents.go
@@ -18,8 +18,14 @@ import (
"github.com/nicklaw5/helix/v2"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
+ "golang.org/x/sync/errgroup"
"within.website/x/cmd/mi/models"
"within.website/x/proto/mimi/announce"
+ "within.website/x/web/mastodon"
+)
+
+const (
+ streamAnnouncement = "Xe is live on Twitch! https://twitch.tv/princessxen"
)
var (
@@ -39,6 +45,8 @@ type Config struct {
BlueskyAuthkey string
BlueskyHandle string
BlueskyPDS string
+ MastodonToken string
+ MastodonURL string
MimiAnnounceURL string
}
@@ -58,10 +66,11 @@ func (c Config) BlueskyAgent(ctx context.Context) (*bsky.BskyAgent, error) {
}
type Server struct {
- dao *models.DAO
- mimi announce.Announce
- cfg Config
- twitch *helix.Client
+ dao *models.DAO
+ mimi announce.Post
+ mastodon *mastodon.Client
+ cfg Config
+ twitch *helix.Client
}
func New(ctx context.Context, dao *models.DAO, cfg Config) (*Server, error) {
@@ -83,11 +92,17 @@ func New(ctx context.Context, dao *models.DAO, cfg Config) (*Server, error) {
twitch.SetAppAccessToken(resp.Data.AccessToken)
+ mas, err := mastodon.Authenticated("mi_irl", "https://xeiaso.net", cfg.MastodonURL, cfg.MastodonToken)
+ if err != nil {
+ return nil, fmt.Errorf("failed to authenticate to mastodon: %w", err)
+ }
+
s := &Server{
- dao: dao,
- mimi: announce.NewAnnounceProtobufClient(cfg.MimiAnnounceURL, &http.Client{}),
- cfg: cfg,
- twitch: twitch,
+ dao: dao,
+ mimi: announce.NewPostProtobufClient(cfg.MimiAnnounceURL, &http.Client{}),
+ mastodon: mas,
+ cfg: cfg,
+ twitch: twitch,
}
if err := s.maybeCreateWebhookSubscription(); err != nil {
@@ -211,6 +226,8 @@ func (s *Server) handleNotification(ctx context.Context, lg *slog.Logger, w http
return fmt.Errorf("can't decode notification: %w", err)
}
+ lg = lg.With("event", data.Subscription.Type)
+
var err error
switch data.Subscription.Type {
case "stream.online":
@@ -235,41 +252,75 @@ func (s *Server) handleNotification(ctx context.Context, lg *slog.Logger, w http
func (s *Server) handleStreamUp(ctx context.Context, lg *slog.Logger, ev *helix.EventSubStreamOnlineEvent) error {
lg.Info("broadcaster went online!", "username", ev.BroadcasterUserLogin)
- bs, err := s.cfg.BlueskyAgent(ctx)
- if err != nil {
- return fmt.Errorf("can't create bluesky agent: %w", err)
- }
+ g, gCtx := errgroup.WithContext(ctx)
- u, err := url.Parse("https://twitch.tv/" + ev.BroadcasterUserLogin)
- if err != nil {
- return fmt.Errorf("[unexpected] can't create twitch URL: %w", err)
- }
+ g.Go(func() error {
+ post, err := s.mastodon.CreateStatus(gCtx, mastodon.CreateStatusParams{
+ Status: streamAnnouncement,
+ })
+ if err != nil {
+ slog.Error("failed to announce to mastodon", "err", err)
+ return err
+ }
+ slog.Info("posted to mastodon", "mastodon_url", post.URL)
+ return nil
+ })
- q := u.Query()
- q.Set("utm_campaign", "mi_irl")
- q.Set("utm_medium", "social")
- q.Set("utm_source", "bluesky")
- u.RawQuery = q.Encode()
-
- var sb strings.Builder
- fmt.Fprintln(&sb, "Xe is live on stream!")
- fmt.Fprintln(&sb)
- fmt.Fprint(&sb, u.String())
-
- post, err := bsky.NewPostBuilder(sb.String()).
- WithExternalLink("twitch.tv - princessxen", *u, "Xe on Twitch!").
- WithFacet(bsky.Facet_Link, u.String(), u.String()).
- Build()
- if err != nil {
- return fmt.Errorf("can't build post: %w", err)
- }
+ g.Go(func() error {
+ bs, err := s.cfg.BlueskyAgent(gCtx)
+ if err != nil {
+ return fmt.Errorf("can't create bluesky agent: %w", err)
+ }
- cid, uri, err := bs.PostToFeed(ctx, post)
- if err != nil {
- return fmt.Errorf("can't post to feed: %w", err)
- }
+ u, err := url.Parse("https://twitch.tv/" + ev.BroadcasterUserLogin)
+ if err != nil {
+ return fmt.Errorf("[unexpected] can't create twitch URL: %w", err)
+ }
- lg.Info("posted to bluesky", "bluesky_cid", cid, "bluesky_uri", uri, "body", sb.String())
+ q := u.Query()
+ q.Set("utm_campaign", "mi_irl")
+ q.Set("utm_medium", "social")
+ q.Set("utm_source", "bluesky")
+ u.RawQuery = q.Encode()
+
+ var sb strings.Builder
+ fmt.Fprintln(&sb, "Xe is live on stream!")
+ fmt.Fprintln(&sb)
+ fmt.Fprint(&sb, u.String())
+
+ post, err := bsky.NewPostBuilder(sb.String()).
+ WithExternalLink("twitch.tv - princessxen", *u, "Xe on Twitch!").
+ WithFacet(bsky.Facet_Link, u.String(), u.String()).
+ Build()
+ if err != nil {
+ return fmt.Errorf("can't build post: %w", err)
+ }
+
+ cid, uri, err := bs.PostToFeed(gCtx, post)
+ if err != nil {
+ return fmt.Errorf("can't post to feed: %w", err)
+ }
+
+ lg.Info("posted to bluesky", "bluesky_cid", cid, "bluesky_uri", uri, "body", sb.String())
+
+ return nil
+ })
+
+ g.Go(func() error {
+ if _, err := s.mimi.Post(gCtx, &announce.StatusUpdate{
+ Body: streamAnnouncement,
+ }); err != nil {
+ return fmt.Errorf("can't announce to Mimi: %w", err)
+ }
+
+ lg.Info("posted to Mimi")
+
+ return nil
+ })
+
+ if err := g.Wait(); err != nil {
+ return err
+ }
return nil
}