aboutsummaryrefslogtreecommitdiffstats
path: root/dashboard/app
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2025-12-19 12:52:30 +0100
committerAleksandr Nogikh <nogikh@google.com>2025-12-22 02:13:00 +0000
commita83befa0d111a0ba6fac52d763e93c76a2ef94d4 (patch)
tree7d3c28b24229429936a631e8ceb24135856b257d /dashboard/app
parent8fb7048c5117ccb592deb5e8e4a62027e6d399cf (diff)
all: use any instead of interface{}
Any is the preferred over interface{} now in Go.
Diffstat (limited to 'dashboard/app')
-rw-r--r--dashboard/app/api.go58
-rw-r--r--dashboard/app/coverage.go2
-rw-r--r--dashboard/app/entities_spanner.go2
-rw-r--r--dashboard/app/handler.go2
-rw-r--r--dashboard/app/jobs.go2
-rw-r--r--dashboard/app/label.go4
-rw-r--r--dashboard/app/main.go4
-rw-r--r--dashboard/app/public_json_api.go4
-rw-r--r--dashboard/app/reporting_external.go10
-rw-r--r--dashboard/app/subsystem.go2
-rw-r--r--dashboard/app/tree.go6
-rw-r--r--dashboard/app/util_test.go10
12 files changed, 53 insertions, 53 deletions
diff --git a/dashboard/app/api.go b/dashboard/app/api.go
index 1e7d655c4..c7539c5f5 100644
--- a/dashboard/app/api.go
+++ b/dashboard/app/api.go
@@ -77,8 +77,8 @@ var apiHandlers = map[string]APIHandler{
"log_to_repro": nsHandler(apiLogToReproduce),
}
-type JSONHandler func(c context.Context, r *http.Request) (interface{}, error)
-type APIHandler func(c context.Context, payload io.Reader) (interface{}, error)
+type JSONHandler func(c context.Context, r *http.Request) (any, error)
+type APIHandler func(c context.Context, payload io.Reader) (any, error)
const (
maxReproPerBug = 10
@@ -126,7 +126,7 @@ func handleJSON(fn JSONHandler) http.Handler {
})
}
-func handleAPI(c context.Context, r *http.Request) (interface{}, error) {
+func handleAPI(c context.Context, r *http.Request) (any, error) {
client := r.PostFormValue("client")
method := r.PostFormValue("method")
log.Infof(c, "api %q from %q", method, client)
@@ -178,7 +178,7 @@ func contextNamespace(c context.Context) string {
// gcsPayloadHandler json.Decode the gcsURL from payload and stream pointed content.
// This function streams ungzipped content in order to be aligned with other wrappers/handlers.
func gcsPayloadHandler(handler APIHandler) APIHandler {
- return func(c context.Context, payload io.Reader) (interface{}, error) {
+ return func(c context.Context, payload io.Reader) (any, error) {
var gcsURL string
if err := json.NewDecoder(payload).Decode(&gcsURL); err != nil {
return nil, fmt.Errorf("json.NewDecoder(payload).Decode(&gcsURL): %w", err)
@@ -216,7 +216,7 @@ func nsHandler[Req any](handler func(context.Context, string, *Req) (any, error)
}
func typedHandler[Req any](handler func(context.Context, *Req) (any, error)) APIHandler {
- return func(ctx context.Context, payload io.Reader) (interface{}, error) {
+ return func(ctx context.Context, payload io.Reader) (any, error) {
req := new(Req)
if payload != nil {
if err := json.NewDecoder(payload).Decode(req); err != nil {
@@ -227,12 +227,12 @@ func typedHandler[Req any](handler func(context.Context, *Req) (any, error)) API
}
}
-func apiLogError(c context.Context, req *dashapi.LogEntry) (interface{}, error) {
+func apiLogError(c context.Context, req *dashapi.LogEntry) (any, error) {
log.Errorf(c, "%v: %v", req.Name, req.Text)
return nil, nil
}
-func apiBuilderPoll(c context.Context, ns string, req *dashapi.BuilderPollReq) (interface{}, error) {
+func apiBuilderPoll(c context.Context, ns string, req *dashapi.BuilderPollReq) (any, error) {
bugs, _, err := loadAllBugs(c, func(query *db.Query) *db.Query {
return query.Filter("Namespace=", ns).
Filter("Status<", BugStatusFixed)
@@ -277,7 +277,7 @@ func reportEmail(c context.Context, ns string) string {
return ""
}
-func apiCommitPoll(c context.Context, ns string, req *any) (interface{}, error) {
+func apiCommitPoll(c context.Context, ns string, req *any) (any, error) {
resp := &dashapi.CommitPollResp{
ReportEmail: reportEmail(c, ns),
}
@@ -343,7 +343,7 @@ func pollBackportCommits(c context.Context, ns string, count int) ([]string, err
return backportTitles, nil
}
-func apiUploadCommits(c context.Context, ns string, req *dashapi.CommitPollResultReq) (interface{}, error) {
+func apiUploadCommits(c context.Context, ns string, req *dashapi.CommitPollResultReq) (any, error) {
// This adds fixing commits to bugs.
err := addCommitsToBugs(c, ns, "", nil, req.Commits)
if err != nil {
@@ -444,7 +444,7 @@ func addCommitInfoToBugImpl(c context.Context, bug *Bug, com dashapi.Commit) (bo
return changed, nil
}
-func apiJobPoll(c context.Context, req *dashapi.JobPollReq) (interface{}, error) {
+func apiJobPoll(c context.Context, req *dashapi.JobPollReq) (any, error) {
if stop, err := emergentlyStopped(c); err != nil || stop {
// The bot's operation was aborted. Don't accept new crash reports.
return &dashapi.JobPollResp{}, err
@@ -455,17 +455,17 @@ func apiJobPoll(c context.Context, req *dashapi.JobPollReq) (interface{}, error)
return pollPendingJobs(c, req.Managers)
}
-func apiJobDone(c context.Context, req *dashapi.JobDoneReq) (interface{}, error) {
+func apiJobDone(c context.Context, req *dashapi.JobDoneReq) (any, error) {
err := doneJob(c, req)
return nil, err
}
-func apiJobReset(c context.Context, req *dashapi.JobResetReq) (interface{}, error) {
+func apiJobReset(c context.Context, req *dashapi.JobResetReq) (any, error) {
err := resetJobs(c, req)
return nil, err
}
-func apiUploadBuild(c context.Context, ns string, req *dashapi.Build) (interface{}, error) {
+func apiUploadBuild(c context.Context, ns string, req *dashapi.Build) (any, error) {
now := timeNow(c)
_, isNewBuild, err := uploadBuild(c, now, ns, req, BuildNormal)
if err != nil {
@@ -732,7 +732,7 @@ func managerList(c context.Context, ns string) ([]string, error) {
return managers, nil
}
-func apiReportBuildError(c context.Context, ns string, req *dashapi.BuildErrorReq) (interface{}, error) {
+func apiReportBuildError(c context.Context, ns string, req *dashapi.BuildErrorReq) (any, error) {
now := timeNow(c)
build, _, err := uploadBuild(c, now, ns, &req.Build, BuildFailed)
if err != nil {
@@ -762,7 +762,7 @@ const (
suppressedReportTitle = "suppressed report"
)
-func apiReportCrash(c context.Context, ns string, req *dashapi.Crash) (interface{}, error) {
+func apiReportCrash(c context.Context, ns string, req *dashapi.Crash) (any, error) {
if stop, err := emergentlyStopped(c); err != nil || stop {
// The bot's operation was aborted. Don't accept new crash reports.
return &dashapi.ReportCrashResp{}, err
@@ -1067,7 +1067,7 @@ func purgeOldCrashes(c context.Context, bug *Bug, bugKey *db.Key) {
log.Infof(c, "deleted %v crashes for bug %q", deleted, bug.Title)
}
-func apiReportFailedRepro(c context.Context, ns string, req *dashapi.CrashID) (interface{}, error) {
+func apiReportFailedRepro(c context.Context, ns string, req *dashapi.CrashID) (any, error) {
req.Title = canonicalizeCrashTitle(req.Title, req.Corrupted, req.Suppressed)
bug, err := findExistingBugForCrash(c, ns, []string{req.Title})
if err != nil {
@@ -1134,7 +1134,7 @@ func saveReproAttempt(c context.Context, bug *Bug, build *Build, log []byte) err
return nil
}
-func apiNeedRepro(c context.Context, ns string, req *dashapi.CrashID) (interface{}, error) {
+func apiNeedRepro(c context.Context, ns string, req *dashapi.CrashID) (any, error) {
if req.Corrupted {
resp := &dashapi.NeedReproResp{
NeedRepro: false,
@@ -1182,7 +1182,7 @@ func normalizeCrashTitle(title string) string {
return strings.TrimSpace(limitLength(title, maxTextLen))
}
-func apiManagerStats(c context.Context, ns string, req *dashapi.ManagerStatsReq) (interface{}, error) {
+func apiManagerStats(c context.Context, ns string, req *dashapi.ManagerStatsReq) (any, error) {
now := timeNow(c)
err := updateManager(c, ns, req.Name, func(mgr *Manager, stats *ManagerStats) error {
mgr.Link = req.Addr
@@ -1203,7 +1203,7 @@ func apiManagerStats(c context.Context, ns string, req *dashapi.ManagerStatsReq)
return nil, err
}
-func apiUpdateReport(c context.Context, ns string, req *dashapi.UpdateReportReq) (interface{}, error) {
+func apiUpdateReport(c context.Context, ns string, req *dashapi.UpdateReportReq) (any, error) {
bug := new(Bug)
bugKey := db.NewKey(c, "Bug", req.BugID, 0, nil)
if err := db.Get(c, bugKey, bug); err != nil {
@@ -1229,7 +1229,7 @@ func apiUpdateReport(c context.Context, ns string, req *dashapi.UpdateReportReq)
return nil, runInTransaction(c, tx, nil)
}
-func apiBugList(c context.Context, ns string, req *any) (interface{}, error) {
+func apiBugList(c context.Context, ns string, req *any) (any, error) {
keys, err := db.NewQuery("Bug").
Filter("Namespace=", ns).
KeysOnly().
@@ -1244,7 +1244,7 @@ func apiBugList(c context.Context, ns string, req *any) (interface{}, error) {
return resp, nil
}
-func apiLoadBug(c context.Context, ns string, req *dashapi.LoadBugReq) (interface{}, error) {
+func apiLoadBug(c context.Context, ns string, req *dashapi.LoadBugReq) (any, error) {
bug := new(Bug)
bugKey := db.NewKey(c, "Bug", req.ID, 0, nil)
if err := db.Get(c, bugKey, bug); err != nil {
@@ -1256,7 +1256,7 @@ func apiLoadBug(c context.Context, ns string, req *dashapi.LoadBugReq) (interfac
return loadBugReport(c, bug)
}
-func apiLoadFullBug(c context.Context, req *dashapi.LoadFullBugReq) (interface{}, error) {
+func apiLoadFullBug(c context.Context, req *dashapi.LoadFullBugReq) (any, error) {
bug, bugKey, err := findBugByReportingID(c, req.BugID)
if err != nil {
return nil, fmt.Errorf("failed to find the bug: %w", err)
@@ -1282,7 +1282,7 @@ func loadBugReport(c context.Context, bug *Bug) (*dashapi.BugReport, error) {
return createBugReport(c, bug, crash, crashKey, bugReporting, reporting)
}
-func apiAddBuildAssets(c context.Context, ns string, req *dashapi.AddBuildAssetsReq) (interface{}, error) {
+func apiAddBuildAssets(c context.Context, ns string, req *dashapi.AddBuildAssetsReq) (any, error) {
assets := []Asset{}
for i, toAdd := range req.Assets {
asset, err := parseIncomingAsset(c, toAdd, ns)
@@ -1323,7 +1323,7 @@ func parseIncomingAsset(c context.Context, newAsset dashapi.NewAsset, ns string)
}, nil
}
-func apiNeededAssetsList(c context.Context, req *any) (interface{}, error) {
+func apiNeededAssetsList(c context.Context, req *any) (any, error) {
return queryNeededAssets(c)
}
@@ -1704,7 +1704,7 @@ func handleRefreshSubsystems(w http.ResponseWriter, r *http.Request) {
}
}
-func apiSaveDiscussion(c context.Context, req *dashapi.SaveDiscussionReq) (interface{}, error) {
+func apiSaveDiscussion(c context.Context, req *dashapi.SaveDiscussionReq) (any, error) {
d := req.Discussion
newBugIDs := []string{}
for _, id := range d.BugIDs {
@@ -1743,7 +1743,7 @@ func recordEmergencyStop(c context.Context) error {
// Share crash logs for non-reproduced bugs with syz-managers.
// In future, this can also take care of repro exchange between instances
// in the place of syz-hub.
-func apiLogToReproduce(c context.Context, ns string, req *dashapi.LogToReproReq) (interface{}, error) {
+func apiLogToReproduce(c context.Context, ns string, req *dashapi.LogToReproReq) (any, error) {
build, err := loadBuild(c, ns, req.BuildID)
if err != nil {
return nil, err
@@ -1863,7 +1863,7 @@ func takeReproTask(c context.Context, ns, manager string) ([]byte, error) {
return log, err
}
-func apiCreateUploadURL(c context.Context, req *any) (interface{}, error) {
+func apiCreateUploadURL(c context.Context, req *any) (any, error) {
bucket := getConfig(c).UploadBucket
if bucket == "" {
return nil, errors.New("not configured")
@@ -1871,7 +1871,7 @@ func apiCreateUploadURL(c context.Context, req *any) (interface{}, error) {
return fmt.Sprintf("%s/%s.upload", bucket, uuid.New().String()), nil
}
-func apiSendEmail(c context.Context, req *dashapi.SendEmailReq) (interface{}, error) {
+func apiSendEmail(c context.Context, req *dashapi.SendEmailReq) (any, error) {
var headers mail.Header
if req.InReplyTo != "" {
headers = mail.Header{"In-Reply-To": []string{req.InReplyTo}}
@@ -1889,7 +1889,7 @@ func apiSendEmail(c context.Context, req *dashapi.SendEmailReq) (interface{}, er
// apiSaveCoverage reads jsonl data from payload and stores it to coveragedb.
// First payload jsonl line is a coveragedb.HistoryRecord (w/o session and time).
// Second+ records are coveragedb.JSONLWrapper.
-func apiSaveCoverage(c context.Context, payload io.Reader) (interface{}, error) {
+func apiSaveCoverage(c context.Context, payload io.Reader) (any, error) {
descr := new(coveragedb.HistoryRecord)
jsonDec := json.NewDecoder(payload)
if err := jsonDec.Decode(descr); err != nil {
diff --git a/dashboard/app/coverage.go b/dashboard/app/coverage.go
index 67a4494e0..d10651fef 100644
--- a/dashboard/app/coverage.go
+++ b/dashboard/app/coverage.go
@@ -111,7 +111,7 @@ func getParam[T int | string | bool | civil.Date](r *http.Request, name string,
return extractVal(t, r.FormValue(name)).(T)
}
-func extractVal(t interface{}, val string) interface{} {
+func extractVal(t any, val string) any {
switch t.(type) {
case int:
res, _ := strconv.Atoi(val)
diff --git a/dashboard/app/entities_spanner.go b/dashboard/app/entities_spanner.go
index df1bfeed7..cf21e43eb 100644
--- a/dashboard/app/entities_spanner.go
+++ b/dashboard/app/entities_spanner.go
@@ -44,7 +44,7 @@ from merge_history join files
on merge_history.session = files.session
where namespace=$1 and duration>=$2 and duration<=$3 and manager='*'
group by dateto, duration`,
- Params: map[string]interface{}{
+ Params: map[string]any{
"p1": ns,
"p2": minDays,
"p3": maxDays,
diff --git a/dashboard/app/handler.go b/dashboard/app/handler.go
index 157e33383..bda86eb30 100644
--- a/dashboard/app/handler.go
+++ b/dashboard/app/handler.go
@@ -203,7 +203,7 @@ func handleAuth(fn contextHandler) contextHandler {
}
}
-func serveTemplate(w http.ResponseWriter, name string, data interface{}) error {
+func serveTemplate(w http.ResponseWriter, name string, data any) error {
buf := new(bytes.Buffer)
if err := templates.ExecuteTemplate(buf, name, data); err != nil {
return err
diff --git a/dashboard/app/jobs.go b/dashboard/app/jobs.go
index b7ff881a3..9c1a9001e 100644
--- a/dashboard/app/jobs.go
+++ b/dashboard/app/jobs.go
@@ -1258,7 +1258,7 @@ func pollCompletedJobs(c context.Context, typ string) ([]*dashapi.BugReport, err
return reports, nil
}
-func createBugReportForJob(c context.Context, job *Job, jobKey *db.Key, config interface{}) (
+func createBugReportForJob(c context.Context, job *Job, jobKey *db.Key, config any) (
*dashapi.BugReport, error) {
reportingConfig, err := json.Marshal(config)
if err != nil {
diff --git a/dashboard/app/label.go b/dashboard/app/label.go
index cbff8c33e..807951f48 100644
--- a/dashboard/app/label.go
+++ b/dashboard/app/label.go
@@ -32,7 +32,7 @@ type subsetOf []string
type trueFalse struct{}
func makeLabelSet(c context.Context, ns string) *labelSet {
- ret := map[BugLabelType]interface{}{
+ ret := map[BugLabelType]any{
PriorityLabel: oneOf([]string{
string(LowPrioBug),
string(NormalPrioBug),
@@ -74,7 +74,7 @@ func makeLabelSet(c context.Context, ns string) *labelSet {
type labelSet struct {
c context.Context
ns string
- labels map[BugLabelType]interface{}
+ labels map[BugLabelType]any
}
func (s *labelSet) FindLabel(label BugLabelType) bool {
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index 0d2e588b1..3b1749a45 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -318,7 +318,7 @@ type uiCollapsible struct {
Title string
Show bool // By default it's collapsed.
Type string // Template system understands it.
- Value interface{}
+ Value any
}
func makeCollapsibleBugJobs(title string, jobs []*uiJob) *uiCollapsible {
@@ -1411,7 +1411,7 @@ func handleBugSummaries(c context.Context, w http.ResponseWriter, r *http.Reques
return json.NewEncoder(w).Encode(list)
}
-func writeJSONVersionOf(writer http.ResponseWriter, page interface{}) error {
+func writeJSONVersionOf(writer http.ResponseWriter, page any) error {
data, err := GetJSONDescrFor(page)
if err != nil {
return err
diff --git a/dashboard/app/public_json_api.go b/dashboard/app/public_json_api.go
index 5905ec8c6..75c688954 100644
--- a/dashboard/app/public_json_api.go
+++ b/dashboard/app/public_json_api.go
@@ -161,8 +161,8 @@ func getExtAPIDescrForBackports(groups []*uiBackportGroup) *publicAPIBackports {
}
}
-func GetJSONDescrFor(page interface{}) ([]byte, error) {
- var res interface{}
+func GetJSONDescrFor(page any) ([]byte, error) {
+ var res any
switch i := page.(type) {
case *uiBugPage:
res = getExtAPIDescrForBugPage(i)
diff --git a/dashboard/app/reporting_external.go b/dashboard/app/reporting_external.go
index 8dd4eb444..3bfc5f445 100644
--- a/dashboard/app/reporting_external.go
+++ b/dashboard/app/reporting_external.go
@@ -15,7 +15,7 @@ import (
// The external system is meant to poll for new bugs with apiReportingPoll,
// and report back bug status updates with apiReportingUpdate.
-func apiReportingPollBugs(c context.Context, req *dashapi.PollBugsRequest) (interface{}, error) {
+func apiReportingPollBugs(c context.Context, req *dashapi.PollBugsRequest) (any, error) {
if stop, err := emergentlyStopped(c); err != nil || stop {
return &dashapi.PollBugsResponse{}, err
}
@@ -32,7 +32,7 @@ func apiReportingPollBugs(c context.Context, req *dashapi.PollBugsRequest) (inte
}
func apiReportingPollNotifications(c context.Context, req *dashapi.PollNotificationsRequest) (
- interface{}, error) {
+ any, error) {
if stop, err := emergentlyStopped(c); err != nil || stop {
return &dashapi.PollNotificationsResponse{}, err
}
@@ -43,7 +43,7 @@ func apiReportingPollNotifications(c context.Context, req *dashapi.PollNotificat
return resp, nil
}
-func apiReportingPollClosed(c context.Context, req *dashapi.PollClosedRequest) (interface{}, error) {
+func apiReportingPollClosed(c context.Context, req *dashapi.PollClosedRequest) (any, error) {
if stop, err := emergentlyStopped(c); err != nil || stop {
return &dashapi.PollClosedResponse{}, err
}
@@ -57,7 +57,7 @@ func apiReportingPollClosed(c context.Context, req *dashapi.PollClosedRequest) (
return resp, nil
}
-func apiReportingUpdate(c context.Context, req *dashapi.BugUpdate) (interface{}, error) {
+func apiReportingUpdate(c context.Context, req *dashapi.BugUpdate) (any, error) {
if req.JobID != "" {
resp := &dashapi.BugUpdateReply{
OK: true,
@@ -78,7 +78,7 @@ func apiReportingUpdate(c context.Context, req *dashapi.BugUpdate) (interface{},
}, nil
}
-func apiNewTestJob(c context.Context, req *dashapi.TestPatchRequest) (interface{}, error) {
+func apiNewTestJob(c context.Context, req *dashapi.TestPatchRequest) (any, error) {
resp := &dashapi.TestPatchReply{}
err := handleExternalTestRequest(c, req)
if err != nil {
diff --git a/dashboard/app/subsystem.go b/dashboard/app/subsystem.go
index c49bc081b..48ee1f785 100644
--- a/dashboard/app/subsystem.go
+++ b/dashboard/app/subsystem.go
@@ -108,7 +108,7 @@ type (
)
func updateBugSubsystems(c context.Context, bugKey *db.Key,
- list []*subsystem.Subsystem, info interface{}) error {
+ list []*subsystem.Subsystem, info any) error {
now := timeNow(c)
return updateSingleBug(c, bugKey, func(bug *Bug) error {
switch v := info.(type) {
diff --git a/dashboard/app/tree.go b/dashboard/app/tree.go
index a6a9e9e30..b6261e289 100644
--- a/dashboard/app/tree.go
+++ b/dashboard/app/tree.go
@@ -94,7 +94,7 @@ func treeOriginJobDone(cGlobal context.Context, jobKey *db.Key, job *Job) error
return runInTransaction(cGlobal, tx, &db.TransactionOptions{XG: true})
}
-type pollTreeJobResult interface{}
+type pollTreeJobResult any
// pollResultPending is returned when we wait some job to finish.
type pollResultPending struct{}
@@ -371,7 +371,7 @@ func (ctx *bugTreeContext) groupResults(results []pollTreeJobResult) pollTreeJob
return pollResultSkip{}
}
-type expectedResult interface{}
+type expectedResult any
// resultFreshness subtypes.
type wantFirstOK struct{}
@@ -379,7 +379,7 @@ type wantFirstCrash struct{}
type wantFirstAny struct{}
type wantNewAny time.Time
-type runReproOn interface{}
+type runReproOn any
// runReproOn subtypes.
type runOnAny struct{} // attempts to find any result, if unsuccessful, runs on HEAD
diff --git a/dashboard/app/util_test.go b/dashboard/app/util_test.go
index 199573cf0..9fd4d3b81 100644
--- a/dashboard/app/util_test.go
+++ b/dashboard/app/util_test.go
@@ -125,14 +125,14 @@ func (c *Ctx) expectBadReqest(err error) {
expectFailureStatus(c.t, err, http.StatusBadRequest)
}
-func (c *Ctx) expectEQ(got, want interface{}) {
+func (c *Ctx) expectEQ(got, want any) {
if diff := cmp.Diff(got, want); diff != "" {
c.t.Helper()
c.t.Fatal(diff)
}
}
-func (c *Ctx) expectNE(got, want interface{}) {
+func (c *Ctx) expectNE(got, want any) {
if reflect.DeepEqual(got, want) {
c.t.Helper()
c.t.Fatalf("equal: %#v", got)
@@ -504,8 +504,8 @@ type apiClient struct {
}
func (c *Ctx) makeClient(client, key string, failOnErrors bool) *apiClient {
- logger := func(msg string, args ...interface{}) {
- c.t.Logf("%v: "+msg, append([]interface{}{caller(3)}, args...)...)
+ logger := func(msg string, args ...any) {
+ c.t.Logf("%v: "+msg, append([]any{caller(3)}, args...)...)
}
errorHandler := func(err error) {
if failOnErrors {
@@ -628,7 +628,7 @@ type (
EmailOptSender string
)
-func (c *Ctx) incomingEmail(to, body string, opts ...interface{}) {
+func (c *Ctx) incomingEmail(to, body string, opts ...any) {
id := 0
subject := "crash1"
from := "default@sender.com"