porting all github actions from bluesky-social/indigo to tangled CI
at main 4.3 kB view raw
1package main 2 3import ( 4 "context" 5 "fmt" 6 "os" 7 "strings" 8 "time" 9 10 comatproto "github.com/bluesky-social/indigo/api/atproto" 11 toolsozone "github.com/bluesky-social/indigo/api/ozone" 12 "github.com/bluesky-social/indigo/util" 13 "github.com/bluesky-social/indigo/xrpc" 14 15 "github.com/urfave/cli/v2" 16) 17 18func pollNewReports(cctx *cli.Context) error { 19 ctx := context.Background() 20 logger := configLogger(cctx, os.Stdout) 21 slackWebhookURL := cctx.String("slack-webhook-url") 22 23 // record last-seen report timestamp 24 since := time.Now() 25 // NOTE: uncomment this for testing 26 //since = time.Now().Add(time.Duration(-12) * time.Hour) 27 period := time.Duration(cctx.Int("poll-period")) * time.Second 28 29 // create a new session 30 xrpcc := &xrpc.Client{ 31 Client: util.RobustHTTPClient(), 32 Host: cctx.String("pds-host"), 33 Auth: &xrpc.AuthInfo{Handle: cctx.String("handle")}, 34 } 35 36 auth, err := comatproto.ServerCreateSession(ctx, xrpcc, &comatproto.ServerCreateSession_Input{ 37 Identifier: xrpcc.Auth.Handle, 38 Password: cctx.String("password"), 39 }) 40 if err != nil { 41 return err 42 } 43 xrpcc.Auth.AccessJwt = auth.AccessJwt 44 xrpcc.Auth.RefreshJwt = auth.RefreshJwt 45 xrpcc.Auth.Did = auth.Did 46 xrpcc.Auth.Handle = auth.Handle 47 48 adminToken := cctx.String("admin-password") 49 if len(adminToken) > 0 { 50 xrpcc.AdminToken = &adminToken 51 } 52 logger.Info("report polling bot starting up...") 53 // can flip this bool to false to prevent spamming slack channel on startup 54 if true { 55 err := sendSlackMsg(ctx, fmt.Sprintf("restarted bot, monitoring for reports since `%s`...", since.Format(time.RFC3339)), slackWebhookURL) 56 if err != nil { 57 return err 58 } 59 } 60 for { 61 // refresh session 62 xrpcc.Auth.AccessJwt = xrpcc.Auth.RefreshJwt 63 refresh, err := comatproto.ServerRefreshSession(ctx, xrpcc) 64 if err != nil { 65 return err 66 } 67 xrpcc.Auth.AccessJwt = refresh.AccessJwt 68 xrpcc.Auth.RefreshJwt = refresh.RefreshJwt 69 70 // query just new reports (regardless of resolution state) 71 var limit int64 = 50 72 me, err := toolsozone.ModerationQueryEvents( 73 cctx.Context, 74 xrpcc, 75 nil, // addedLabels []string 76 nil, // addedTags []string 77 "", // ageAssuranceState 78 nil, // collections []string 79 "", // comment string 80 "", // createdAfter string 81 "", // createdBefore string 82 "", // createdBy string 83 "", // cursor string 84 false, // hasComment bool 85 true, // includeAllUserRecords bool 86 limit, // limit int64 87 nil, // modTool 88 nil, // policies []string 89 nil, // removedLabels []string 90 nil, // removedTags []string 91 nil, // reportTypes []string 92 "", // sortDirection string 93 "", // subject string 94 "", // subjectType string 95 []string{"tools.ozone.moderation.defs#modEventReport"}, // types []string 96 ) 97 if err != nil { 98 return err 99 } 100 // this works out to iterate from newest to oldest, which is the behavior we want (report only newest, then break) 101 for _, evt := range me.Events { 102 report := evt.Event.ModerationDefs_ModEventReport 103 // TODO: filter out based on subject state? similar to old "report.ResolvedByActionIds" 104 createdAt, err := time.Parse(time.RFC3339, evt.CreatedAt) 105 if err != nil { 106 return fmt.Errorf("invalid time format for 'createdAt': %w", err) 107 } 108 if createdAt.After(since) { 109 shortType := "" 110 if report.ReportType != nil && strings.Contains(*report.ReportType, "#") { 111 shortType = strings.SplitN(*report.ReportType, "#", 2)[1] 112 } 113 // ok, we found a "new" report, need to notify 114 msg := fmt.Sprintf("⚠️ New report at `%s` ⚠️\n", evt.CreatedAt) 115 msg += fmt.Sprintf("report id: `%d`\t", evt.Id) 116 msg += fmt.Sprintf("instance: `%s`\n", cctx.String("pds-host")) 117 msg += fmt.Sprintf("reasonType: `%s`\t", shortType) 118 msg += fmt.Sprintf("Admin: %s/reports/%d\n", cctx.String("admin-host"), evt.Id) 119 //msg += fmt.Sprintf("reportedByDid: `%s`\n", report.ReportedByDid) 120 logger.Info("found new report, notifying slack", "report", report) 121 err := sendSlackMsg(ctx, msg, slackWebhookURL) 122 if err != nil { 123 return fmt.Errorf("failed to send slack message: %w", err) 124 } 125 since = createdAt 126 break 127 } else { 128 logger.Debug("skipping report", "report", report) 129 } 130 } 131 logger.Info("... sleeping", "period", period) 132 time.Sleep(period) 133 } 134}