From bb64378c139583b9fa42c60d468f39c28b138673 Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 02:03:20 +0200 Subject: [PATCH 01/26] remove unfinished discord bot endpoints --- backend/routes.go | 2 - backend/routes/v1/bot/bot.go | 183 ----------------------------------- 2 files changed, 185 deletions(-) delete mode 100644 backend/routes/v1/bot/bot.go diff --git a/backend/routes.go b/backend/routes.go index f755929..406e05f 100644 --- a/backend/routes.go +++ b/backend/routes.go @@ -2,7 +2,6 @@ package backend import ( "codeberg.org/pronounscc/pronouns.cc/backend/routes/v1/auth" - "codeberg.org/pronounscc/pronouns.cc/backend/routes/v1/bot" "codeberg.org/pronounscc/pronouns.cc/backend/routes/v1/member" "codeberg.org/pronounscc/pronouns.cc/backend/routes/v1/meta" "codeberg.org/pronounscc/pronouns.cc/backend/routes/v1/mod" @@ -21,7 +20,6 @@ func mountRoutes(s *server.Server) { auth.Mount(s, r) user.Mount(s, r) member.Mount(s, r) - bot.Mount(s, r) meta.Mount(s, r) mod.Mount(s, r) }) diff --git a/backend/routes/v1/bot/bot.go b/backend/routes/v1/bot/bot.go deleted file mode 100644 index 1fa8f4c..0000000 --- a/backend/routes/v1/bot/bot.go +++ /dev/null @@ -1,183 +0,0 @@ -package bot - -import ( - "crypto/ed25519" - "encoding/hex" - "encoding/json" - "fmt" - "net/http" - "os" - - "codeberg.org/pronounscc/pronouns.cc/backend/db" - "codeberg.org/pronounscc/pronouns.cc/backend/log" - "codeberg.org/pronounscc/pronouns.cc/backend/server" - "github.com/bwmarrin/discordgo" - "github.com/go-chi/chi/v5" - "github.com/go-chi/render" -) - -type Bot struct { - *server.Server - - publicKey ed25519.PublicKey - baseURL string -} - -func (bot *Bot) UserAvatarURL(u db.User) string { - if u.Avatar == nil { - return "" - } - - return bot.baseURL + "/media/users/" + u.ID.String() + "/" + *u.Avatar + ".webp" -} - -func Mount(srv *server.Server, r chi.Router) { - publicKey, err := hex.DecodeString(os.Getenv("DISCORD_PUBLIC_KEY")) - if err != nil { - return - } - - b := &Bot{ - Server: srv, - publicKey: publicKey, - baseURL: os.Getenv("BASE_URL"), - } - - r.HandleFunc("/interactions", b.handle) -} - -func (bot *Bot) handle(w http.ResponseWriter, r *http.Request) { - if !discordgo.VerifyInteraction(r, bot.publicKey) { - http.Error(w, "Forbidden", http.StatusForbidden) - return - } - - var ev *discordgo.InteractionCreate - - if err := json.NewDecoder(r.Body).Decode(&ev); err != nil { - http.Error(w, "Bad Request", http.StatusBadRequest) - } - - // we can always respond to ping with pong - if ev.Type == discordgo.InteractionPing { - log.Debug("received ping interaction") - render.JSON(w, r, discordgo.InteractionResponse{ - Type: discordgo.InteractionResponsePong, - }) - return - } - - if ev.Type != discordgo.InteractionApplicationCommand { - return - } - data := ev.ApplicationCommandData() - - switch data.Name { - case "Show user's pronouns": - bot.userPronouns(w, r, ev) - case "Show author's pronouns": - } -} - -func (bot *Bot) userPronouns(w http.ResponseWriter, r *http.Request, ev *discordgo.InteractionCreate) { - ctx := r.Context() - - var du *discordgo.User - for _, user := range ev.ApplicationCommandData().Resolved.Users { - du = user - break - } - if du == nil { - return - } - - u, err := bot.DB.DiscordUser(ctx, du.ID) - if err != nil { - if err == db.ErrUserNotFound { - respond(w, r, &discordgo.MessageEmbed{ - Description: du.String() + " does not have any pronouns set.", - }) - return - } - - log.Errorf("getting discord user: %v", err) - return - } - - avatarURL := du.AvatarURL("") - if url := bot.UserAvatarURL(u); url != "" { - avatarURL = url - } - name := u.Username - if u.DisplayName != nil { - name = fmt.Sprintf("%s (%s)", *u.DisplayName, u.Username) - } - url := bot.baseURL - if url != "" { - url += "/@" + u.Username - } - - e := &discordgo.MessageEmbed{ - Author: &discordgo.MessageEmbedAuthor{ - Name: name, - IconURL: avatarURL, - URL: url, - }, - } - - if u.Bio != nil { - e.Fields = append(e.Fields, &discordgo.MessageEmbedField{ - Name: "Bio", - Value: *u.Bio, - }) - } - - fields, err := bot.DB.UserFields(ctx, u.ID) - if err != nil { - respond(w, r, e) - - log.Errorf("getting user fields: %v", err) - return - } - - for _, field := range fields { - var favs []db.FieldEntry - - for _, e := range field.Entries { - if e.Status == "favourite" { - favs = append(favs, e) - } - } - - if len(favs) == 0 { - continue - } - - var value string - for _, fav := range favs { - if len(fav.Value) > 500 { - break - } - - value += fav.Value + "\n" - } - - e.Fields = append(e.Fields, &discordgo.MessageEmbedField{ - Name: field.Name, - Value: value, - Inline: true, - }) - } - - respond(w, r, e) -} - -func respond(w http.ResponseWriter, r *http.Request, embeds ...*discordgo.MessageEmbed) { - render.JSON(w, r, discordgo.InteractionResponse{ - Type: discordgo.InteractionResponseChannelMessageWithSource, - Data: &discordgo.InteractionResponseData{ - Embeds: embeds, - Flags: discordgo.MessageFlagsEphemeral, - }, - }) -} From f424228fee98a71a8868cb1c4b32f2ed5f2e1d61 Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 02:29:06 +0200 Subject: [PATCH 02/26] update icons.js --- backend/icons/icons.go | 3916 ++++++++++++++++++++-------------------- frontend/icons.js | 12 +- 2 files changed, 1960 insertions(+), 1968 deletions(-) diff --git a/backend/icons/icons.go b/backend/icons/icons.go index 3bc0e80..84355f3 100644 --- a/backend/icons/icons.go +++ b/backend/icons/icons.go @@ -1,1968 +1,1964 @@ // Generated code. DO NOT EDIT package icons -var icons = [...]string{ - "123", - "alarm-fill", - "alarm", - "align-bottom", - "align-center", - "align-end", - "align-middle", - "align-start", - "align-top", - "alt", - "app-indicator", - "app", - "archive-fill", - "archive", - "arrow-90deg-down", - "arrow-90deg-left", - "arrow-90deg-right", - "arrow-90deg-up", - "arrow-bar-down", - "arrow-bar-left", - "arrow-bar-right", - "arrow-bar-up", - "arrow-clockwise", - "arrow-counterclockwise", - "arrow-down-circle-fill", - "arrow-down-circle", - "arrow-down-left-circle-fill", - "arrow-down-left-circle", - "arrow-down-left-square-fill", - "arrow-down-left-square", - "arrow-down-left", - "arrow-down-right-circle-fill", - "arrow-down-right-circle", - "arrow-down-right-square-fill", - "arrow-down-right-square", - "arrow-down-right", - "arrow-down-short", - "arrow-down-square-fill", - "arrow-down-square", - "arrow-down-up", - "arrow-down", - "arrow-left-circle-fill", - "arrow-left-circle", - "arrow-left-right", - "arrow-left-short", - "arrow-left-square-fill", - "arrow-left-square", - "arrow-left", - "arrow-repeat", - "arrow-return-left", - "arrow-return-right", - "arrow-right-circle-fill", - "arrow-right-circle", - "arrow-right-short", - "arrow-right-square-fill", - "arrow-right-square", - "arrow-right", - "arrow-up-circle-fill", - "arrow-up-circle", - "arrow-up-left-circle-fill", - "arrow-up-left-circle", - "arrow-up-left-square-fill", - "arrow-up-left-square", - "arrow-up-left", - "arrow-up-right-circle-fill", - "arrow-up-right-circle", - "arrow-up-right-square-fill", - "arrow-up-right-square", - "arrow-up-right", - "arrow-up-short", - "arrow-up-square-fill", - "arrow-up-square", - "arrow-up", - "arrows-angle-contract", - "arrows-angle-expand", - "arrows-collapse", - "arrows-expand", - "arrows-fullscreen", - "arrows-move", - "aspect-ratio-fill", - "aspect-ratio", - "asterisk", - "at", - "award-fill", - "award", - "back", - "backspace-fill", - "backspace-reverse-fill", - "backspace-reverse", - "backspace", - "badge-3d-fill", - "badge-3d", - "badge-4k-fill", - "badge-4k", - "badge-8k-fill", - "badge-8k", - "badge-ad-fill", - "badge-ad", - "badge-ar-fill", - "badge-ar", - "badge-cc-fill", - "badge-cc", - "badge-hd-fill", - "badge-hd", - "badge-tm-fill", - "badge-tm", - "badge-vo-fill", - "badge-vo", - "badge-vr-fill", - "badge-vr", - "badge-wc-fill", - "badge-wc", - "bag-check-fill", - "bag-check", - "bag-dash-fill", - "bag-dash", - "bag-fill", - "bag-plus-fill", - "bag-plus", - "bag-x-fill", - "bag-x", - "bag", - "bar-chart-fill", - "bar-chart-line-fill", - "bar-chart-line", - "bar-chart-steps", - "bar-chart", - "basket-fill", - "basket", - "basket2-fill", - "basket2", - "basket3-fill", - "basket3", - "battery-charging", - "battery-full", - "battery-half", - "battery", - "bell-fill", - "bell", - "bezier", - "bezier2", - "bicycle", - "binoculars-fill", - "binoculars", - "blockquote-left", - "blockquote-right", - "book-fill", - "book-half", - "book", - "bookmark-check-fill", - "bookmark-check", - "bookmark-dash-fill", - "bookmark-dash", - "bookmark-fill", - "bookmark-heart-fill", - "bookmark-heart", - "bookmark-plus-fill", - "bookmark-plus", - "bookmark-star-fill", - "bookmark-star", - "bookmark-x-fill", - "bookmark-x", - "bookmark", - "bookmarks-fill", - "bookmarks", - "bookshelf", - "bootstrap-fill", - "bootstrap-reboot", - "bootstrap", - "border-all", - "border-bottom", - "border-center", - "border-inner", - "border-left", - "border-middle", - "border-outer", - "border-right", - "border-style", - "border-top", - "border-width", - "border", - "bounding-box-circles", - "bounding-box", - "box-arrow-down-left", - "box-arrow-down-right", - "box-arrow-down", - "box-arrow-in-down-left", - "box-arrow-in-down-right", - "box-arrow-in-down", - "box-arrow-in-left", - "box-arrow-in-right", - "box-arrow-in-up-left", - "box-arrow-in-up-right", - "box-arrow-in-up", - "box-arrow-left", - "box-arrow-right", - "box-arrow-up-left", - "box-arrow-up-right", - "box-arrow-up", - "box-seam", - "box", - "braces", - "bricks", - "briefcase-fill", - "briefcase", - "brightness-alt-high-fill", - "brightness-alt-high", - "brightness-alt-low-fill", - "brightness-alt-low", - "brightness-high-fill", - "brightness-high", - "brightness-low-fill", - "brightness-low", - "broadcast-pin", - "broadcast", - "brush-fill", - "brush", - "bucket-fill", - "bucket", - "bug-fill", - "bug", - "building", - "bullseye", - "calculator-fill", - "calculator", - "calendar-check-fill", - "calendar-check", - "calendar-date-fill", - "calendar-date", - "calendar-day-fill", - "calendar-day", - "calendar-event-fill", - "calendar-event", - "calendar-fill", - "calendar-minus-fill", - "calendar-minus", - "calendar-month-fill", - "calendar-month", - "calendar-plus-fill", - "calendar-plus", - "calendar-range-fill", - "calendar-range", - "calendar-week-fill", - "calendar-week", - "calendar-x-fill", - "calendar-x", - "calendar", - "calendar2-check-fill", - "calendar2-check", - "calendar2-date-fill", - "calendar2-date", - "calendar2-day-fill", - "calendar2-day", - "calendar2-event-fill", - "calendar2-event", - "calendar2-fill", - "calendar2-minus-fill", - "calendar2-minus", - "calendar2-month-fill", - "calendar2-month", - "calendar2-plus-fill", - "calendar2-plus", - "calendar2-range-fill", - "calendar2-range", - "calendar2-week-fill", - "calendar2-week", - "calendar2-x-fill", - "calendar2-x", - "calendar2", - "calendar3-event-fill", - "calendar3-event", - "calendar3-fill", - "calendar3-range-fill", - "calendar3-range", - "calendar3-week-fill", - "calendar3-week", - "calendar3", - "calendar4-event", - "calendar4-range", - "calendar4-week", - "calendar4", - "camera-fill", - "camera-reels-fill", - "camera-reels", - "camera-video-fill", - "camera-video-off-fill", - "camera-video-off", - "camera-video", - "camera", - "camera2", - "capslock-fill", - "capslock", - "card-checklist", - "card-heading", - "card-image", - "card-list", - "card-text", - "caret-down-fill", - "caret-down-square-fill", - "caret-down-square", - "caret-down", - "caret-left-fill", - "caret-left-square-fill", - "caret-left-square", - "caret-left", - "caret-right-fill", - "caret-right-square-fill", - "caret-right-square", - "caret-right", - "caret-up-fill", - "caret-up-square-fill", - "caret-up-square", - "caret-up", - "cart-check-fill", - "cart-check", - "cart-dash-fill", - "cart-dash", - "cart-fill", - "cart-plus-fill", - "cart-plus", - "cart-x-fill", - "cart-x", - "cart", - "cart2", - "cart3", - "cart4", - "cash-stack", - "cash", - "cast", - "chat-dots-fill", - "chat-dots", - "chat-fill", - "chat-left-dots-fill", - "chat-left-dots", - "chat-left-fill", - "chat-left-quote-fill", - "chat-left-quote", - "chat-left-text-fill", - "chat-left-text", - "chat-left", - "chat-quote-fill", - "chat-quote", - "chat-right-dots-fill", - "chat-right-dots", - "chat-right-fill", - "chat-right-quote-fill", - "chat-right-quote", - "chat-right-text-fill", - "chat-right-text", - "chat-right", - "chat-square-dots-fill", - "chat-square-dots", - "chat-square-fill", - "chat-square-quote-fill", - "chat-square-quote", - "chat-square-text-fill", - "chat-square-text", - "chat-square", - "chat-text-fill", - "chat-text", - "chat", - "check-all", - "check-circle-fill", - "check-circle", - "check-square-fill", - "check-square", - "check", - "check2-all", - "check2-circle", - "check2-square", - "check2", - "chevron-bar-contract", - "chevron-bar-down", - "chevron-bar-expand", - "chevron-bar-left", - "chevron-bar-right", - "chevron-bar-up", - "chevron-compact-down", - "chevron-compact-left", - "chevron-compact-right", - "chevron-compact-up", - "chevron-contract", - "chevron-double-down", - "chevron-double-left", - "chevron-double-right", - "chevron-double-up", - "chevron-down", - "chevron-expand", - "chevron-left", - "chevron-right", - "chevron-up", - "circle-fill", - "circle-half", - "circle-square", - "circle", - "clipboard-check", - "clipboard-data", - "clipboard-minus", - "clipboard-plus", - "clipboard-x", - "clipboard", - "clock-fill", - "clock-history", - "clock", - "cloud-arrow-down-fill", - "cloud-arrow-down", - "cloud-arrow-up-fill", - "cloud-arrow-up", - "cloud-check-fill", - "cloud-check", - "cloud-download-fill", - "cloud-download", - "cloud-drizzle-fill", - "cloud-drizzle", - "cloud-fill", - "cloud-fog-fill", - "cloud-fog", - "cloud-fog2-fill", - "cloud-fog2", - "cloud-hail-fill", - "cloud-hail", - "cloud-haze-fill", - "cloud-haze", - "cloud-haze2-fill", - "cloud-lightning-fill", - "cloud-lightning-rain-fill", - "cloud-lightning-rain", - "cloud-lightning", - "cloud-minus-fill", - "cloud-minus", - "cloud-moon-fill", - "cloud-moon", - "cloud-plus-fill", - "cloud-plus", - "cloud-rain-fill", - "cloud-rain-heavy-fill", - "cloud-rain-heavy", - "cloud-rain", - "cloud-slash-fill", - "cloud-slash", - "cloud-sleet-fill", - "cloud-sleet", - "cloud-snow-fill", - "cloud-snow", - "cloud-sun-fill", - "cloud-sun", - "cloud-upload-fill", - "cloud-upload", - "cloud", - "clouds-fill", - "clouds", - "cloudy-fill", - "cloudy", - "code-slash", - "code-square", - "code", - "collection-fill", - "collection-play-fill", - "collection-play", - "collection", - "columns-gap", - "columns", - "command", - "compass-fill", - "compass", - "cone-striped", - "cone", - "controller", - "cpu-fill", - "cpu", - "credit-card-2-back-fill", - "credit-card-2-back", - "credit-card-2-front-fill", - "credit-card-2-front", - "credit-card-fill", - "credit-card", - "crop", - "cup-fill", - "cup-straw", - "cup", - "cursor-fill", - "cursor-text", - "cursor", - "dash-circle-dotted", - "dash-circle-fill", - "dash-circle", - "dash-square-dotted", - "dash-square-fill", - "dash-square", - "dash", - "diagram-2-fill", - "diagram-2", - "diagram-3-fill", - "diagram-3", - "diamond-fill", - "diamond-half", - "diamond", - "dice-1-fill", - "dice-1", - "dice-2-fill", - "dice-2", - "dice-3-fill", - "dice-3", - "dice-4-fill", - "dice-4", - "dice-5-fill", - "dice-5", - "dice-6-fill", - "dice-6", - "disc-fill", - "disc", - "discord", - "display-fill", - "display", - "distribute-horizontal", - "distribute-vertical", - "door-closed-fill", - "door-closed", - "door-open-fill", - "door-open", - "dot", - "download", - "droplet-fill", - "droplet-half", - "droplet", - "earbuds", - "easel-fill", - "easel", - "egg-fill", - "egg-fried", - "egg", - "eject-fill", - "eject", - "emoji-angry-fill", - "emoji-angry", - "emoji-dizzy-fill", - "emoji-dizzy", - "emoji-expressionless-fill", - "emoji-expressionless", - "emoji-frown-fill", - "emoji-frown", - "emoji-heart-eyes-fill", - "emoji-heart-eyes", - "emoji-laughing-fill", - "emoji-laughing", - "emoji-neutral-fill", - "emoji-neutral", - "emoji-smile-fill", - "emoji-smile-upside-down-fill", - "emoji-smile-upside-down", - "emoji-smile", - "emoji-sunglasses-fill", - "emoji-sunglasses", - "emoji-wink-fill", - "emoji-wink", - "envelope-fill", - "envelope-open-fill", - "envelope-open", - "envelope", - "eraser-fill", - "eraser", - "exclamation-circle-fill", - "exclamation-circle", - "exclamation-diamond-fill", - "exclamation-diamond", - "exclamation-octagon-fill", - "exclamation-octagon", - "exclamation-square-fill", - "exclamation-square", - "exclamation-triangle-fill", - "exclamation-triangle", - "exclamation", - "exclude", - "eye-fill", - "eye-slash-fill", - "eye-slash", - "eye", - "eyedropper", - "eyeglasses", - "facebook", - "file-arrow-down-fill", - "file-arrow-down", - "file-arrow-up-fill", - "file-arrow-up", - "file-bar-graph-fill", - "file-bar-graph", - "file-binary-fill", - "file-binary", - "file-break-fill", - "file-break", - "file-check-fill", - "file-check", - "file-code-fill", - "file-code", - "file-diff-fill", - "file-diff", - "file-earmark-arrow-down-fill", - "file-earmark-arrow-down", - "file-earmark-arrow-up-fill", - "file-earmark-arrow-up", - "file-earmark-bar-graph-fill", - "file-earmark-bar-graph", - "file-earmark-binary-fill", - "file-earmark-binary", - "file-earmark-break-fill", - "file-earmark-break", - "file-earmark-check-fill", - "file-earmark-check", - "file-earmark-code-fill", - "file-earmark-code", - "file-earmark-diff-fill", - "file-earmark-diff", - "file-earmark-easel-fill", - "file-earmark-easel", - "file-earmark-excel-fill", - "file-earmark-excel", - "file-earmark-fill", - "file-earmark-font-fill", - "file-earmark-font", - "file-earmark-image-fill", - "file-earmark-image", - "file-earmark-lock-fill", - "file-earmark-lock", - "file-earmark-lock2-fill", - "file-earmark-lock2", - "file-earmark-medical-fill", - "file-earmark-medical", - "file-earmark-minus-fill", - "file-earmark-minus", - "file-earmark-music-fill", - "file-earmark-music", - "file-earmark-person-fill", - "file-earmark-person", - "file-earmark-play-fill", - "file-earmark-play", - "file-earmark-plus-fill", - "file-earmark-plus", - "file-earmark-post-fill", - "file-earmark-post", - "file-earmark-ppt-fill", - "file-earmark-ppt", - "file-earmark-richtext-fill", - "file-earmark-richtext", - "file-earmark-ruled-fill", - "file-earmark-ruled", - "file-earmark-slides-fill", - "file-earmark-slides", - "file-earmark-spreadsheet-fill", - "file-earmark-spreadsheet", - "file-earmark-text-fill", - "file-earmark-text", - "file-earmark-word-fill", - "file-earmark-word", - "file-earmark-x-fill", - "file-earmark-x", - "file-earmark-zip-fill", - "file-earmark-zip", - "file-earmark", - "file-easel-fill", - "file-easel", - "file-excel-fill", - "file-excel", - "file-fill", - "file-font-fill", - "file-font", - "file-image-fill", - "file-image", - "file-lock-fill", - "file-lock", - "file-lock2-fill", - "file-lock2", - "file-medical-fill", - "file-medical", - "file-minus-fill", - "file-minus", - "file-music-fill", - "file-music", - "file-person-fill", - "file-person", - "file-play-fill", - "file-play", - "file-plus-fill", - "file-plus", - "file-post-fill", - "file-post", - "file-ppt-fill", - "file-ppt", - "file-richtext-fill", - "file-richtext", - "file-ruled-fill", - "file-ruled", - "file-slides-fill", - "file-slides", - "file-spreadsheet-fill", - "file-spreadsheet", - "file-text-fill", - "file-text", - "file-word-fill", - "file-word", - "file-x-fill", - "file-x", - "file-zip-fill", - "file-zip", - "file", - "files-alt", - "files", - "film", - "filter-circle-fill", - "filter-circle", - "filter-left", - "filter-right", - "filter-square-fill", - "filter-square", - "filter", - "flag-fill", - "flag", - "flower1", - "flower2", - "flower3", - "folder-check", - "folder-fill", - "folder-minus", - "folder-plus", - "folder-symlink-fill", - "folder-symlink", - "folder-x", - "folder", - "folder2-open", - "folder2", - "fonts", - "forward-fill", - "forward", - "front", - "fullscreen-exit", - "fullscreen", - "funnel-fill", - "funnel", - "gear-fill", - "gear-wide-connected", - "gear-wide", - "gear", - "gem", - "geo-alt-fill", - "geo-alt", - "geo-fill", - "geo", - "gift-fill", - "gift", - "github", - "globe", - "globe2", - "google", - "graph-down", - "graph-up", - "grid-1x2-fill", - "grid-1x2", - "grid-3x2-gap-fill", - "grid-3x2-gap", - "grid-3x2", - "grid-3x3-gap-fill", - "grid-3x3-gap", - "grid-3x3", - "grid-fill", - "grid", - "grip-horizontal", - "grip-vertical", - "hammer", - "hand-index-fill", - "hand-index-thumb-fill", - "hand-index-thumb", - "hand-index", - "hand-thumbs-down-fill", - "hand-thumbs-down", - "hand-thumbs-up-fill", - "hand-thumbs-up", - "handbag-fill", - "handbag", - "hash", - "hdd-fill", - "hdd-network-fill", - "hdd-network", - "hdd-rack-fill", - "hdd-rack", - "hdd-stack-fill", - "hdd-stack", - "hdd", - "headphones", - "headset", - "heart-fill", - "heart-half", - "heart", - "heptagon-fill", - "heptagon-half", - "heptagon", - "hexagon-fill", - "hexagon-half", - "hexagon", - "hourglass-bottom", - "hourglass-split", - "hourglass-top", - "hourglass", - "house-door-fill", - "house-door", - "house-fill", - "house", - "hr", - "hurricane", - "image-alt", - "image-fill", - "image", - "images", - "inbox-fill", - "inbox", - "inboxes-fill", - "inboxes", - "info-circle-fill", - "info-circle", - "info-square-fill", - "info-square", - "info", - "input-cursor-text", - "input-cursor", - "instagram", - "intersect", - "journal-album", - "journal-arrow-down", - "journal-arrow-up", - "journal-bookmark-fill", - "journal-bookmark", - "journal-check", - "journal-code", - "journal-medical", - "journal-minus", - "journal-plus", - "journal-richtext", - "journal-text", - "journal-x", - "journal", - "journals", - "joystick", - "justify-left", - "justify-right", - "justify", - "kanban-fill", - "kanban", - "key-fill", - "key", - "keyboard-fill", - "keyboard", - "ladder", - "lamp-fill", - "lamp", - "laptop-fill", - "laptop", - "layer-backward", - "layer-forward", - "layers-fill", - "layers-half", - "layers", - "layout-sidebar-inset-reverse", - "layout-sidebar-inset", - "layout-sidebar-reverse", - "layout-sidebar", - "layout-split", - "layout-text-sidebar-reverse", - "layout-text-sidebar", - "layout-text-window-reverse", - "layout-text-window", - "layout-three-columns", - "layout-wtf", - "life-preserver", - "lightbulb-fill", - "lightbulb-off-fill", - "lightbulb-off", - "lightbulb", - "lightning-charge-fill", - "lightning-charge", - "lightning-fill", - "lightning", - "link-45deg", - "link", - "linkedin", - "list-check", - "list-nested", - "list-ol", - "list-stars", - "list-task", - "list-ul", - "list", - "lock-fill", - "lock", - "mailbox", - "mailbox2", - "map-fill", - "map", - "markdown-fill", - "markdown", - "mask", - "megaphone-fill", - "megaphone", - "menu-app-fill", - "menu-app", - "menu-button-fill", - "menu-button-wide-fill", - "menu-button-wide", - "menu-button", - "menu-down", - "menu-up", - "mic-fill", - "mic-mute-fill", - "mic-mute", - "mic", - "minecart-loaded", - "minecart", - "moisture", - "moon-fill", - "moon-stars-fill", - "moon-stars", - "moon", - "mouse-fill", - "mouse", - "mouse2-fill", - "mouse2", - "mouse3-fill", - "mouse3", - "music-note-beamed", - "music-note-list", - "music-note", - "music-player-fill", - "music-player", - "newspaper", - "node-minus-fill", - "node-minus", - "node-plus-fill", - "node-plus", - "nut-fill", - "nut", - "octagon-fill", - "octagon-half", - "octagon", - "option", - "outlet", - "paint-bucket", - "palette-fill", - "palette", - "palette2", - "paperclip", - "paragraph", - "patch-check-fill", - "patch-check", - "patch-exclamation-fill", - "patch-exclamation", - "patch-minus-fill", - "patch-minus", - "patch-plus-fill", - "patch-plus", - "patch-question-fill", - "patch-question", - "pause-btn-fill", - "pause-btn", - "pause-circle-fill", - "pause-circle", - "pause-fill", - "pause", - "peace-fill", - "peace", - "pen-fill", - "pen", - "pencil-fill", - "pencil-square", - "pencil", - "pentagon-fill", - "pentagon-half", - "pentagon", - "people-fill", - "people", - "percent", - "person-badge-fill", - "person-badge", - "person-bounding-box", - "person-check-fill", - "person-check", - "person-circle", - "person-dash-fill", - "person-dash", - "person-fill", - "person-lines-fill", - "person-plus-fill", - "person-plus", - "person-square", - "person-x-fill", - "person-x", - "person", - "phone-fill", - "phone-landscape-fill", - "phone-landscape", - "phone-vibrate-fill", - "phone-vibrate", - "phone", - "pie-chart-fill", - "pie-chart", - "pin-angle-fill", - "pin-angle", - "pin-fill", - "pin", - "pip-fill", - "pip", - "play-btn-fill", - "play-btn", - "play-circle-fill", - "play-circle", - "play-fill", - "play", - "plug-fill", - "plug", - "plus-circle-dotted", - "plus-circle-fill", - "plus-circle", - "plus-square-dotted", - "plus-square-fill", - "plus-square", - "plus", - "power", - "printer-fill", - "printer", - "puzzle-fill", - "puzzle", - "question-circle-fill", - "question-circle", - "question-diamond-fill", - "question-diamond", - "question-octagon-fill", - "question-octagon", - "question-square-fill", - "question-square", - "question", - "rainbow", - "receipt-cutoff", - "receipt", - "reception-0", - "reception-1", - "reception-2", - "reception-3", - "reception-4", - "record-btn-fill", - "record-btn", - "record-circle-fill", - "record-circle", - "record-fill", - "record", - "record2-fill", - "record2", - "reply-all-fill", - "reply-all", - "reply-fill", - "reply", - "rss-fill", - "rss", - "rulers", - "save-fill", - "save", - "save2-fill", - "save2", - "scissors", - "screwdriver", - "search", - "segmented-nav", - "server", - "share-fill", - "share", - "shield-check", - "shield-exclamation", - "shield-fill-check", - "shield-fill-exclamation", - "shield-fill-minus", - "shield-fill-plus", - "shield-fill-x", - "shield-fill", - "shield-lock-fill", - "shield-lock", - "shield-minus", - "shield-plus", - "shield-shaded", - "shield-slash-fill", - "shield-slash", - "shield-x", - "shield", - "shift-fill", - "shift", - "shop-window", - "shop", - "shuffle", - "signpost-2-fill", - "signpost-2", - "signpost-fill", - "signpost-split-fill", - "signpost-split", - "signpost", - "sim-fill", - "sim", - "skip-backward-btn-fill", - "skip-backward-btn", - "skip-backward-circle-fill", - "skip-backward-circle", - "skip-backward-fill", - "skip-backward", - "skip-end-btn-fill", - "skip-end-btn", - "skip-end-circle-fill", - "skip-end-circle", - "skip-end-fill", - "skip-end", - "skip-forward-btn-fill", - "skip-forward-btn", - "skip-forward-circle-fill", - "skip-forward-circle", - "skip-forward-fill", - "skip-forward", - "skip-start-btn-fill", - "skip-start-btn", - "skip-start-circle-fill", - "skip-start-circle", - "skip-start-fill", - "skip-start", - "slack", - "slash-circle-fill", - "slash-circle", - "slash-square-fill", - "slash-square", - "slash", - "sliders", - "smartwatch", - "snow", - "snow2", - "snow3", - "sort-alpha-down-alt", - "sort-alpha-down", - "sort-alpha-up-alt", - "sort-alpha-up", - "sort-down-alt", - "sort-down", - "sort-numeric-down-alt", - "sort-numeric-down", - "sort-numeric-up-alt", - "sort-numeric-up", - "sort-up-alt", - "sort-up", - "soundwave", - "speaker-fill", - "speaker", - "speedometer", - "speedometer2", - "spellcheck", - "square-fill", - "square-half", - "square", - "stack", - "star-fill", - "star-half", - "star", - "stars", - "stickies-fill", - "stickies", - "sticky-fill", - "sticky", - "stop-btn-fill", - "stop-btn", - "stop-circle-fill", - "stop-circle", - "stop-fill", - "stop", - "stoplights-fill", - "stoplights", - "stopwatch-fill", - "stopwatch", - "subtract", - "suit-club-fill", - "suit-club", - "suit-diamond-fill", - "suit-diamond", - "suit-heart-fill", - "suit-heart", - "suit-spade-fill", - "suit-spade", - "sun-fill", - "sun", - "sunglasses", - "sunrise-fill", - "sunrise", - "sunset-fill", - "sunset", - "symmetry-horizontal", - "symmetry-vertical", - "table", - "tablet-fill", - "tablet-landscape-fill", - "tablet-landscape", - "tablet", - "tag-fill", - "tag", - "tags-fill", - "tags", - "telegram", - "telephone-fill", - "telephone-forward-fill", - "telephone-forward", - "telephone-inbound-fill", - "telephone-inbound", - "telephone-minus-fill", - "telephone-minus", - "telephone-outbound-fill", - "telephone-outbound", - "telephone-plus-fill", - "telephone-plus", - "telephone-x-fill", - "telephone-x", - "telephone", - "terminal-fill", - "terminal", - "text-center", - "text-indent-left", - "text-indent-right", - "text-left", - "text-paragraph", - "text-right", - "textarea-resize", - "textarea-t", - "textarea", - "thermometer-half", - "thermometer-high", - "thermometer-low", - "thermometer-snow", - "thermometer-sun", - "thermometer", - "three-dots-vertical", - "three-dots", - "toggle-off", - "toggle-on", - "toggle2-off", - "toggle2-on", - "toggles", - "toggles2", - "tools", - "tornado", - "trash-fill", - "trash", - "trash2-fill", - "trash2", - "tree-fill", - "tree", - "triangle-fill", - "triangle-half", - "triangle", - "trophy-fill", - "trophy", - "tropical-storm", - "truck-flatbed", - "truck", - "tsunami", - "tv-fill", - "tv", - "twitch", - "twitter", - "type-bold", - "type-h1", - "type-h2", - "type-h3", - "type-italic", - "type-strikethrough", - "type-underline", - "type", - "ui-checks-grid", - "ui-checks", - "ui-radios-grid", - "ui-radios", - "umbrella-fill", - "umbrella", - "union", - "unlock-fill", - "unlock", - "upc-scan", - "upc", - "upload", - "vector-pen", - "view-list", - "view-stacked", - "vinyl-fill", - "vinyl", - "voicemail", - "volume-down-fill", - "volume-down", - "volume-mute-fill", - "volume-mute", - "volume-off-fill", - "volume-off", - "volume-up-fill", - "volume-up", - "vr", - "wallet-fill", - "wallet", - "wallet2", - "watch", - "water", - "whatsapp", - "wifi-1", - "wifi-2", - "wifi-off", - "wifi", - "wind", - "window-dock", - "window-sidebar", - "window", - "wrench", - "x-circle-fill", - "x-circle", - "x-diamond-fill", - "x-diamond", - "x-octagon-fill", - "x-octagon", - "x-square-fill", - "x-square", - "x", - "youtube", - "zoom-in", - "zoom-out", - "bank", - "bank2", - "bell-slash-fill", - "bell-slash", - "cash-coin", - "check-lg", - "coin", - "currency-bitcoin", - "currency-dollar", - "currency-euro", - "currency-exchange", - "currency-pound", - "currency-yen", - "dash-lg", - "exclamation-lg", - "file-earmark-pdf-fill", - "file-earmark-pdf", - "file-pdf-fill", - "file-pdf", - "gender-ambiguous", - "gender-female", - "gender-male", - "gender-trans", - "headset-vr", - "info-lg", - "mastodon", - "messenger", - "piggy-bank-fill", - "piggy-bank", - "pin-map-fill", - "pin-map", - "plus-lg", - "question-lg", - "recycle", - "reddit", - "safe-fill", - "safe2-fill", - "safe2", - "sd-card-fill", - "sd-card", - "skype", - "slash-lg", - "translate", - "x-lg", - "safe", - "apple", - "microsoft", - "windows", - "behance", - "dribbble", - "line", - "medium", - "paypal", - "pinterest", - "signal", - "snapchat", - "spotify", - "stack-overflow", - "strava", - "wordpress", - "vimeo", - "activity", - "easel2-fill", - "easel2", - "easel3-fill", - "easel3", - "fan", - "fingerprint", - "graph-down-arrow", - "graph-up-arrow", - "hypnotize", - "magic", - "person-rolodex", - "person-video", - "person-video2", - "person-video3", - "person-workspace", - "radioactive", - "webcam-fill", - "webcam", - "yin-yang", - "bandaid-fill", - "bandaid", - "bluetooth", - "body-text", - "boombox", - "boxes", - "dpad-fill", - "dpad", - "ear-fill", - "ear", - "envelope-check-fill", - "envelope-check", - "envelope-dash-fill", - "envelope-dash", - "envelope-exclamation-fill", - "envelope-exclamation", - "envelope-plus-fill", - "envelope-plus", - "envelope-slash-fill", - "envelope-slash", - "envelope-x-fill", - "envelope-x", - "explicit-fill", - "explicit", - "git", - "infinity", - "list-columns-reverse", - "list-columns", - "meta", - "nintendo-switch", - "pc-display-horizontal", - "pc-display", - "pc-horizontal", - "pc", - "playstation", - "plus-slash-minus", - "projector-fill", - "projector", - "qr-code-scan", - "qr-code", - "quora", - "quote", - "robot", - "send-check-fill", - "send-check", - "send-dash-fill", - "send-dash", - "send-exclamation-fill", - "send-exclamation", - "send-fill", - "send-plus-fill", - "send-plus", - "send-slash-fill", - "send-slash", - "send-x-fill", - "send-x", - "send", - "steam", - "terminal-dash", - "terminal-plus", - "terminal-split", - "ticket-detailed-fill", - "ticket-detailed", - "ticket-fill", - "ticket-perforated-fill", - "ticket-perforated", - "ticket", - "tiktok", - "window-dash", - "window-desktop", - "window-fullscreen", - "window-plus", - "window-split", - "window-stack", - "window-x", - "xbox", - "ethernet", - "hdmi-fill", - "hdmi", - "usb-c-fill", - "usb-c", - "usb-fill", - "usb-plug-fill", - "usb-plug", - "usb-symbol", - "usb", - "boombox-fill", - "displayport", - "gpu-card", - "memory", - "modem-fill", - "modem", - "motherboard-fill", - "motherboard", - "optical-audio-fill", - "optical-audio", - "pci-card", - "router-fill", - "router", - "thunderbolt-fill", - "thunderbolt", - "usb-drive-fill", - "usb-drive", - "usb-micro-fill", - "usb-micro", - "usb-mini-fill", - "usb-mini", - "cloud-haze2", - "device-hdd-fill", - "device-hdd", - "device-ssd-fill", - "device-ssd", - "displayport-fill", - "mortarboard-fill", - "mortarboard", - "terminal-x", - "arrow-through-heart-fill", - "arrow-through-heart", - "badge-sd-fill", - "badge-sd", - "bag-heart-fill", - "bag-heart", - "balloon-fill", - "balloon-heart-fill", - "balloon-heart", - "balloon", - "box2-fill", - "box2-heart-fill", - "box2-heart", - "box2", - "braces-asterisk", - "calendar-heart-fill", - "calendar-heart", - "calendar2-heart-fill", - "calendar2-heart", - "chat-heart-fill", - "chat-heart", - "chat-left-heart-fill", - "chat-left-heart", - "chat-right-heart-fill", - "chat-right-heart", - "chat-square-heart-fill", - "chat-square-heart", - "clipboard-check-fill", - "clipboard-data-fill", - "clipboard-fill", - "clipboard-heart-fill", - "clipboard-heart", - "clipboard-minus-fill", - "clipboard-plus-fill", - "clipboard-pulse", - "clipboard-x-fill", - "clipboard2-check-fill", - "clipboard2-check", - "clipboard2-data-fill", - "clipboard2-data", - "clipboard2-fill", - "clipboard2-heart-fill", - "clipboard2-heart", - "clipboard2-minus-fill", - "clipboard2-minus", - "clipboard2-plus-fill", - "clipboard2-plus", - "clipboard2-pulse-fill", - "clipboard2-pulse", - "clipboard2-x-fill", - "clipboard2-x", - "clipboard2", - "emoji-kiss-fill", - "emoji-kiss", - "envelope-heart-fill", - "envelope-heart", - "envelope-open-heart-fill", - "envelope-open-heart", - "envelope-paper-fill", - "envelope-paper-heart-fill", - "envelope-paper-heart", - "envelope-paper", - "filetype-aac", - "filetype-ai", - "filetype-bmp", - "filetype-cs", - "filetype-css", - "filetype-csv", - "filetype-doc", - "filetype-docx", - "filetype-exe", - "filetype-gif", - "filetype-heic", - "filetype-html", - "filetype-java", - "filetype-jpg", - "filetype-js", - "filetype-jsx", - "filetype-key", - "filetype-m4p", - "filetype-md", - "filetype-mdx", - "filetype-mov", - "filetype-mp3", - "filetype-mp4", - "filetype-otf", - "filetype-pdf", - "filetype-php", - "filetype-png", - "filetype-ppt", - "filetype-psd", - "filetype-py", - "filetype-raw", - "filetype-rb", - "filetype-sass", - "filetype-scss", - "filetype-sh", - "filetype-svg", - "filetype-tiff", - "filetype-tsx", - "filetype-ttf", - "filetype-txt", - "filetype-wav", - "filetype-woff", - "filetype-xls", - "filetype-xml", - "filetype-yml", - "heart-arrow", - "heart-pulse-fill", - "heart-pulse", - "heartbreak-fill", - "heartbreak", - "hearts", - "hospital-fill", - "hospital", - "house-heart-fill", - "house-heart", - "incognito", - "magnet-fill", - "magnet", - "person-heart", - "person-hearts", - "phone-flip", - "plugin", - "postage-fill", - "postage-heart-fill", - "postage-heart", - "postage", - "postcard-fill", - "postcard-heart-fill", - "postcard-heart", - "postcard", - "search-heart-fill", - "search-heart", - "sliders2-vertical", - "sliders2", - "trash3-fill", - "trash3", - "valentine", - "valentine2", - "wrench-adjustable-circle-fill", - "wrench-adjustable-circle", - "wrench-adjustable", - "filetype-json", - "filetype-pptx", - "filetype-xlsx", - "1-circle-fill", - "1-circle", - "1-square-fill", - "1-square", - "2-circle-fill", - "2-circle", - "2-square-fill", - "2-square", - "3-circle-fill", - "3-circle", - "3-square-fill", - "3-square", - "4-circle-fill", - "4-circle", - "4-square-fill", - "4-square", - "5-circle-fill", - "5-circle", - "5-square-fill", - "5-square", - "6-circle-fill", - "6-circle", - "6-square-fill", - "6-square", - "7-circle-fill", - "7-circle", - "7-square-fill", - "7-square", - "8-circle-fill", - "8-circle", - "8-square-fill", - "8-square", - "9-circle-fill", - "9-circle", - "9-square-fill", - "9-square", - "airplane-engines-fill", - "airplane-engines", - "airplane-fill", - "airplane", - "alexa", - "alipay", - "android", - "android2", - "box-fill", - "box-seam-fill", - "browser-chrome", - "browser-edge", - "browser-firefox", - "browser-safari", - "c-circle-fill", - "c-circle", - "c-square-fill", - "c-square", - "capsule-pill", - "capsule", - "car-front-fill", - "car-front", - "cassette-fill", - "cassette", - "cc-circle-fill", - "cc-circle", - "cc-square-fill", - "cc-square", - "cup-hot-fill", - "cup-hot", - "currency-rupee", - "dropbox", - "escape", - "fast-forward-btn-fill", - "fast-forward-btn", - "fast-forward-circle-fill", - "fast-forward-circle", - "fast-forward-fill", - "fast-forward", - "filetype-sql", - "fire", - "google-play", - "h-circle-fill", - "h-circle", - "h-square-fill", - "h-square", - "indent", - "lungs-fill", - "lungs", - "microsoft-teams", - "p-circle-fill", - "p-circle", - "p-square-fill", - "p-square", - "pass-fill", - "pass", - "prescription", - "prescription2", - "r-circle-fill", - "r-circle", - "r-square-fill", - "r-square", - "repeat-1", - "repeat", - "rewind-btn-fill", - "rewind-btn", - "rewind-circle-fill", - "rewind-circle", - "rewind-fill", - "rewind", - "train-freight-front-fill", - "train-freight-front", - "train-front-fill", - "train-front", - "train-lightrail-front-fill", - "train-lightrail-front", - "truck-front-fill", - "truck-front", - "ubuntu", - "unindent", - "unity", - "universal-access-circle", - "universal-access", - "virus", - "virus2", - "wechat", - "yelp", - "sign-stop-fill", - "sign-stop-lights-fill", - "sign-stop-lights", - "sign-stop", - "sign-turn-left-fill", - "sign-turn-left", - "sign-turn-right-fill", - "sign-turn-right", - "sign-turn-slight-left-fill", - "sign-turn-slight-left", - "sign-turn-slight-right-fill", - "sign-turn-slight-right", - "sign-yield-fill", - "sign-yield", - "ev-station-fill", - "ev-station", - "fuel-pump-diesel-fill", - "fuel-pump-diesel", - "fuel-pump-fill", - "fuel-pump", - "0-circle-fill", - "0-circle", - "0-square-fill", - "0-square", - "rocket-fill", - "rocket-takeoff-fill", - "rocket-takeoff", - "rocket", - "stripe", - "subscript", - "superscript", - "trello", - "envelope-at-fill", - "envelope-at", - "regex", - "text-wrap", - "sign-dead-end-fill", - "sign-dead-end", - "sign-do-not-enter-fill", - "sign-do-not-enter", - "sign-intersection-fill", - "sign-intersection-side-fill", - "sign-intersection-side", - "sign-intersection-t-fill", - "sign-intersection-t", - "sign-intersection-y-fill", - "sign-intersection-y", - "sign-intersection", - "sign-merge-left-fill", - "sign-merge-left", - "sign-merge-right-fill", - "sign-merge-right", - "sign-no-left-turn-fill", - "sign-no-left-turn", - "sign-no-parking-fill", - "sign-no-parking", - "sign-no-right-turn-fill", - "sign-no-right-turn", - "sign-railroad-fill", - "sign-railroad", - "building-add", - "building-check", - "building-dash", - "building-down", - "building-exclamation", - "building-fill-add", - "building-fill-check", - "building-fill-dash", - "building-fill-down", - "building-fill-exclamation", - "building-fill-gear", - "building-fill-lock", - "building-fill-slash", - "building-fill-up", - "building-fill-x", - "building-fill", - "building-gear", - "building-lock", - "building-slash", - "building-up", - "building-x", - "buildings-fill", - "buildings", - "bus-front-fill", - "bus-front", - "ev-front-fill", - "ev-front", - "globe-americas", - "globe-asia-australia", - "globe-central-south-asia", - "globe-europe-africa", - "house-add-fill", - "house-add", - "house-check-fill", - "house-check", - "house-dash-fill", - "house-dash", - "house-down-fill", - "house-down", - "house-exclamation-fill", - "house-exclamation", - "house-gear-fill", - "house-gear", - "house-lock-fill", - "house-lock", - "house-slash-fill", - "house-slash", - "house-up-fill", - "house-up", - "house-x-fill", - "house-x", - "person-add", - "person-down", - "person-exclamation", - "person-fill-add", - "person-fill-check", - "person-fill-dash", - "person-fill-down", - "person-fill-exclamation", - "person-fill-gear", - "person-fill-lock", - "person-fill-slash", - "person-fill-up", - "person-fill-x", - "person-gear", - "person-lock", - "person-slash", - "person-up", - "scooter", - "taxi-front-fill", - "taxi-front", - "amd", - "database-add", - "database-check", - "database-dash", - "database-down", - "database-exclamation", - "database-fill-add", - "database-fill-check", - "database-fill-dash", - "database-fill-down", - "database-fill-exclamation", - "database-fill-gear", - "database-fill-lock", - "database-fill-slash", - "database-fill-up", - "database-fill-x", - "database-fill", - "database-gear", - "database-lock", - "database-slash", - "database-up", - "database-x", - "database", - "houses-fill", - "houses", - "nvidia", - "person-vcard-fill", - "person-vcard", - "sina-weibo", - "tencent-qq", - "wikipedia", +var icons = map[string]struct{}{ + "123": {}, + "alarm-fill": {}, + "alarm": {}, + "align-bottom": {}, + "align-center": {}, + "align-end": {}, + "align-middle": {}, + "align-start": {}, + "align-top": {}, + "alt": {}, + "app-indicator": {}, + "app": {}, + "archive-fill": {}, + "archive": {}, + "arrow-90deg-down": {}, + "arrow-90deg-left": {}, + "arrow-90deg-right": {}, + "arrow-90deg-up": {}, + "arrow-bar-down": {}, + "arrow-bar-left": {}, + "arrow-bar-right": {}, + "arrow-bar-up": {}, + "arrow-clockwise": {}, + "arrow-counterclockwise": {}, + "arrow-down-circle-fill": {}, + "arrow-down-circle": {}, + "arrow-down-left-circle-fill": {}, + "arrow-down-left-circle": {}, + "arrow-down-left-square-fill": {}, + "arrow-down-left-square": {}, + "arrow-down-left": {}, + "arrow-down-right-circle-fill": {}, + "arrow-down-right-circle": {}, + "arrow-down-right-square-fill": {}, + "arrow-down-right-square": {}, + "arrow-down-right": {}, + "arrow-down-short": {}, + "arrow-down-square-fill": {}, + "arrow-down-square": {}, + "arrow-down-up": {}, + "arrow-down": {}, + "arrow-left-circle-fill": {}, + "arrow-left-circle": {}, + "arrow-left-right": {}, + "arrow-left-short": {}, + "arrow-left-square-fill": {}, + "arrow-left-square": {}, + "arrow-left": {}, + "arrow-repeat": {}, + "arrow-return-left": {}, + "arrow-return-right": {}, + "arrow-right-circle-fill": {}, + "arrow-right-circle": {}, + "arrow-right-short": {}, + "arrow-right-square-fill": {}, + "arrow-right-square": {}, + "arrow-right": {}, + "arrow-up-circle-fill": {}, + "arrow-up-circle": {}, + "arrow-up-left-circle-fill": {}, + "arrow-up-left-circle": {}, + "arrow-up-left-square-fill": {}, + "arrow-up-left-square": {}, + "arrow-up-left": {}, + "arrow-up-right-circle-fill": {}, + "arrow-up-right-circle": {}, + "arrow-up-right-square-fill": {}, + "arrow-up-right-square": {}, + "arrow-up-right": {}, + "arrow-up-short": {}, + "arrow-up-square-fill": {}, + "arrow-up-square": {}, + "arrow-up": {}, + "arrows-angle-contract": {}, + "arrows-angle-expand": {}, + "arrows-collapse": {}, + "arrows-expand": {}, + "arrows-fullscreen": {}, + "arrows-move": {}, + "aspect-ratio-fill": {}, + "aspect-ratio": {}, + "asterisk": {}, + "at": {}, + "award-fill": {}, + "award": {}, + "back": {}, + "backspace-fill": {}, + "backspace-reverse-fill": {}, + "backspace-reverse": {}, + "backspace": {}, + "badge-3d-fill": {}, + "badge-3d": {}, + "badge-4k-fill": {}, + "badge-4k": {}, + "badge-8k-fill": {}, + "badge-8k": {}, + "badge-ad-fill": {}, + "badge-ad": {}, + "badge-ar-fill": {}, + "badge-ar": {}, + "badge-cc-fill": {}, + "badge-cc": {}, + "badge-hd-fill": {}, + "badge-hd": {}, + "badge-tm-fill": {}, + "badge-tm": {}, + "badge-vo-fill": {}, + "badge-vo": {}, + "badge-vr-fill": {}, + "badge-vr": {}, + "badge-wc-fill": {}, + "badge-wc": {}, + "bag-check-fill": {}, + "bag-check": {}, + "bag-dash-fill": {}, + "bag-dash": {}, + "bag-fill": {}, + "bag-plus-fill": {}, + "bag-plus": {}, + "bag-x-fill": {}, + "bag-x": {}, + "bag": {}, + "bar-chart-fill": {}, + "bar-chart-line-fill": {}, + "bar-chart-line": {}, + "bar-chart-steps": {}, + "bar-chart": {}, + "basket-fill": {}, + "basket": {}, + "basket2-fill": {}, + "basket2": {}, + "basket3-fill": {}, + "basket3": {}, + "battery-charging": {}, + "battery-full": {}, + "battery-half": {}, + "battery": {}, + "bell-fill": {}, + "bell": {}, + "bezier": {}, + "bezier2": {}, + "bicycle": {}, + "binoculars-fill": {}, + "binoculars": {}, + "blockquote-left": {}, + "blockquote-right": {}, + "book-fill": {}, + "book-half": {}, + "book": {}, + "bookmark-check-fill": {}, + "bookmark-check": {}, + "bookmark-dash-fill": {}, + "bookmark-dash": {}, + "bookmark-fill": {}, + "bookmark-heart-fill": {}, + "bookmark-heart": {}, + "bookmark-plus-fill": {}, + "bookmark-plus": {}, + "bookmark-star-fill": {}, + "bookmark-star": {}, + "bookmark-x-fill": {}, + "bookmark-x": {}, + "bookmark": {}, + "bookmarks-fill": {}, + "bookmarks": {}, + "bookshelf": {}, + "bootstrap-fill": {}, + "bootstrap-reboot": {}, + "bootstrap": {}, + "border-all": {}, + "border-bottom": {}, + "border-center": {}, + "border-inner": {}, + "border-left": {}, + "border-middle": {}, + "border-outer": {}, + "border-right": {}, + "border-style": {}, + "border-top": {}, + "border-width": {}, + "border": {}, + "bounding-box-circles": {}, + "bounding-box": {}, + "box-arrow-down-left": {}, + "box-arrow-down-right": {}, + "box-arrow-down": {}, + "box-arrow-in-down-left": {}, + "box-arrow-in-down-right": {}, + "box-arrow-in-down": {}, + "box-arrow-in-left": {}, + "box-arrow-in-right": {}, + "box-arrow-in-up-left": {}, + "box-arrow-in-up-right": {}, + "box-arrow-in-up": {}, + "box-arrow-left": {}, + "box-arrow-right": {}, + "box-arrow-up-left": {}, + "box-arrow-up-right": {}, + "box-arrow-up": {}, + "box-seam": {}, + "box": {}, + "braces": {}, + "bricks": {}, + "briefcase-fill": {}, + "briefcase": {}, + "brightness-alt-high-fill": {}, + "brightness-alt-high": {}, + "brightness-alt-low-fill": {}, + "brightness-alt-low": {}, + "brightness-high-fill": {}, + "brightness-high": {}, + "brightness-low-fill": {}, + "brightness-low": {}, + "broadcast-pin": {}, + "broadcast": {}, + "brush-fill": {}, + "brush": {}, + "bucket-fill": {}, + "bucket": {}, + "bug-fill": {}, + "bug": {}, + "building": {}, + "bullseye": {}, + "calculator-fill": {}, + "calculator": {}, + "calendar-check-fill": {}, + "calendar-check": {}, + "calendar-date-fill": {}, + "calendar-date": {}, + "calendar-day-fill": {}, + "calendar-day": {}, + "calendar-event-fill": {}, + "calendar-event": {}, + "calendar-fill": {}, + "calendar-minus-fill": {}, + "calendar-minus": {}, + "calendar-month-fill": {}, + "calendar-month": {}, + "calendar-plus-fill": {}, + "calendar-plus": {}, + "calendar-range-fill": {}, + "calendar-range": {}, + "calendar-week-fill": {}, + "calendar-week": {}, + "calendar-x-fill": {}, + "calendar-x": {}, + "calendar": {}, + "calendar2-check-fill": {}, + "calendar2-check": {}, + "calendar2-date-fill": {}, + "calendar2-date": {}, + "calendar2-day-fill": {}, + "calendar2-day": {}, + "calendar2-event-fill": {}, + "calendar2-event": {}, + "calendar2-fill": {}, + "calendar2-minus-fill": {}, + "calendar2-minus": {}, + "calendar2-month-fill": {}, + "calendar2-month": {}, + "calendar2-plus-fill": {}, + "calendar2-plus": {}, + "calendar2-range-fill": {}, + "calendar2-range": {}, + "calendar2-week-fill": {}, + "calendar2-week": {}, + "calendar2-x-fill": {}, + "calendar2-x": {}, + "calendar2": {}, + "calendar3-event-fill": {}, + "calendar3-event": {}, + "calendar3-fill": {}, + "calendar3-range-fill": {}, + "calendar3-range": {}, + "calendar3-week-fill": {}, + "calendar3-week": {}, + "calendar3": {}, + "calendar4-event": {}, + "calendar4-range": {}, + "calendar4-week": {}, + "calendar4": {}, + "camera-fill": {}, + "camera-reels-fill": {}, + "camera-reels": {}, + "camera-video-fill": {}, + "camera-video-off-fill": {}, + "camera-video-off": {}, + "camera-video": {}, + "camera": {}, + "camera2": {}, + "capslock-fill": {}, + "capslock": {}, + "card-checklist": {}, + "card-heading": {}, + "card-image": {}, + "card-list": {}, + "card-text": {}, + "caret-down-fill": {}, + "caret-down-square-fill": {}, + "caret-down-square": {}, + "caret-down": {}, + "caret-left-fill": {}, + "caret-left-square-fill": {}, + "caret-left-square": {}, + "caret-left": {}, + "caret-right-fill": {}, + "caret-right-square-fill": {}, + "caret-right-square": {}, + "caret-right": {}, + "caret-up-fill": {}, + "caret-up-square-fill": {}, + "caret-up-square": {}, + "caret-up": {}, + "cart-check-fill": {}, + "cart-check": {}, + "cart-dash-fill": {}, + "cart-dash": {}, + "cart-fill": {}, + "cart-plus-fill": {}, + "cart-plus": {}, + "cart-x-fill": {}, + "cart-x": {}, + "cart": {}, + "cart2": {}, + "cart3": {}, + "cart4": {}, + "cash-stack": {}, + "cash": {}, + "cast": {}, + "chat-dots-fill": {}, + "chat-dots": {}, + "chat-fill": {}, + "chat-left-dots-fill": {}, + "chat-left-dots": {}, + "chat-left-fill": {}, + "chat-left-quote-fill": {}, + "chat-left-quote": {}, + "chat-left-text-fill": {}, + "chat-left-text": {}, + "chat-left": {}, + "chat-quote-fill": {}, + "chat-quote": {}, + "chat-right-dots-fill": {}, + "chat-right-dots": {}, + "chat-right-fill": {}, + "chat-right-quote-fill": {}, + "chat-right-quote": {}, + "chat-right-text-fill": {}, + "chat-right-text": {}, + "chat-right": {}, + "chat-square-dots-fill": {}, + "chat-square-dots": {}, + "chat-square-fill": {}, + "chat-square-quote-fill": {}, + "chat-square-quote": {}, + "chat-square-text-fill": {}, + "chat-square-text": {}, + "chat-square": {}, + "chat-text-fill": {}, + "chat-text": {}, + "chat": {}, + "check-all": {}, + "check-circle-fill": {}, + "check-circle": {}, + "check-square-fill": {}, + "check-square": {}, + "check": {}, + "check2-all": {}, + "check2-circle": {}, + "check2-square": {}, + "check2": {}, + "chevron-bar-contract": {}, + "chevron-bar-down": {}, + "chevron-bar-expand": {}, + "chevron-bar-left": {}, + "chevron-bar-right": {}, + "chevron-bar-up": {}, + "chevron-compact-down": {}, + "chevron-compact-left": {}, + "chevron-compact-right": {}, + "chevron-compact-up": {}, + "chevron-contract": {}, + "chevron-double-down": {}, + "chevron-double-left": {}, + "chevron-double-right": {}, + "chevron-double-up": {}, + "chevron-down": {}, + "chevron-expand": {}, + "chevron-left": {}, + "chevron-right": {}, + "chevron-up": {}, + "circle-fill": {}, + "circle-half": {}, + "circle-square": {}, + "circle": {}, + "clipboard-check": {}, + "clipboard-data": {}, + "clipboard-minus": {}, + "clipboard-plus": {}, + "clipboard-x": {}, + "clipboard": {}, + "clock-fill": {}, + "clock-history": {}, + "clock": {}, + "cloud-arrow-down-fill": {}, + "cloud-arrow-down": {}, + "cloud-arrow-up-fill": {}, + "cloud-arrow-up": {}, + "cloud-check-fill": {}, + "cloud-check": {}, + "cloud-download-fill": {}, + "cloud-download": {}, + "cloud-drizzle-fill": {}, + "cloud-drizzle": {}, + "cloud-fill": {}, + "cloud-fog-fill": {}, + "cloud-fog": {}, + "cloud-fog2-fill": {}, + "cloud-fog2": {}, + "cloud-hail-fill": {}, + "cloud-hail": {}, + "cloud-haze-fill": {}, + "cloud-haze": {}, + "cloud-haze2-fill": {}, + "cloud-lightning-fill": {}, + "cloud-lightning-rain-fill": {}, + "cloud-lightning-rain": {}, + "cloud-lightning": {}, + "cloud-minus-fill": {}, + "cloud-minus": {}, + "cloud-moon-fill": {}, + "cloud-moon": {}, + "cloud-plus-fill": {}, + "cloud-plus": {}, + "cloud-rain-fill": {}, + "cloud-rain-heavy-fill": {}, + "cloud-rain-heavy": {}, + "cloud-rain": {}, + "cloud-slash-fill": {}, + "cloud-slash": {}, + "cloud-sleet-fill": {}, + "cloud-sleet": {}, + "cloud-snow-fill": {}, + "cloud-snow": {}, + "cloud-sun-fill": {}, + "cloud-sun": {}, + "cloud-upload-fill": {}, + "cloud-upload": {}, + "cloud": {}, + "clouds-fill": {}, + "clouds": {}, + "cloudy-fill": {}, + "cloudy": {}, + "code-slash": {}, + "code-square": {}, + "code": {}, + "collection-fill": {}, + "collection-play-fill": {}, + "collection-play": {}, + "collection": {}, + "columns-gap": {}, + "columns": {}, + "command": {}, + "compass-fill": {}, + "compass": {}, + "cone-striped": {}, + "cone": {}, + "controller": {}, + "cpu-fill": {}, + "cpu": {}, + "credit-card-2-back-fill": {}, + "credit-card-2-back": {}, + "credit-card-2-front-fill": {}, + "credit-card-2-front": {}, + "credit-card-fill": {}, + "credit-card": {}, + "crop": {}, + "cup-fill": {}, + "cup-straw": {}, + "cup": {}, + "cursor-fill": {}, + "cursor-text": {}, + "cursor": {}, + "dash-circle-dotted": {}, + "dash-circle-fill": {}, + "dash-circle": {}, + "dash-square-dotted": {}, + "dash-square-fill": {}, + "dash-square": {}, + "dash": {}, + "diagram-2-fill": {}, + "diagram-2": {}, + "diagram-3-fill": {}, + "diagram-3": {}, + "diamond-fill": {}, + "diamond-half": {}, + "diamond": {}, + "dice-1-fill": {}, + "dice-1": {}, + "dice-2-fill": {}, + "dice-2": {}, + "dice-3-fill": {}, + "dice-3": {}, + "dice-4-fill": {}, + "dice-4": {}, + "dice-5-fill": {}, + "dice-5": {}, + "dice-6-fill": {}, + "dice-6": {}, + "disc-fill": {}, + "disc": {}, + "discord": {}, + "display-fill": {}, + "display": {}, + "distribute-horizontal": {}, + "distribute-vertical": {}, + "door-closed-fill": {}, + "door-closed": {}, + "door-open-fill": {}, + "door-open": {}, + "dot": {}, + "download": {}, + "droplet-fill": {}, + "droplet-half": {}, + "droplet": {}, + "earbuds": {}, + "easel-fill": {}, + "easel": {}, + "egg-fill": {}, + "egg-fried": {}, + "egg": {}, + "eject-fill": {}, + "eject": {}, + "emoji-angry-fill": {}, + "emoji-angry": {}, + "emoji-dizzy-fill": {}, + "emoji-dizzy": {}, + "emoji-expressionless-fill": {}, + "emoji-expressionless": {}, + "emoji-frown-fill": {}, + "emoji-frown": {}, + "emoji-heart-eyes-fill": {}, + "emoji-heart-eyes": {}, + "emoji-laughing-fill": {}, + "emoji-laughing": {}, + "emoji-neutral-fill": {}, + "emoji-neutral": {}, + "emoji-smile-fill": {}, + "emoji-smile-upside-down-fill": {}, + "emoji-smile-upside-down": {}, + "emoji-smile": {}, + "emoji-sunglasses-fill": {}, + "emoji-sunglasses": {}, + "emoji-wink-fill": {}, + "emoji-wink": {}, + "envelope-fill": {}, + "envelope-open-fill": {}, + "envelope-open": {}, + "envelope": {}, + "eraser-fill": {}, + "eraser": {}, + "exclamation-circle-fill": {}, + "exclamation-circle": {}, + "exclamation-diamond-fill": {}, + "exclamation-diamond": {}, + "exclamation-octagon-fill": {}, + "exclamation-octagon": {}, + "exclamation-square-fill": {}, + "exclamation-square": {}, + "exclamation-triangle-fill": {}, + "exclamation-triangle": {}, + "exclamation": {}, + "exclude": {}, + "eye-fill": {}, + "eye-slash-fill": {}, + "eye-slash": {}, + "eye": {}, + "eyedropper": {}, + "eyeglasses": {}, + "facebook": {}, + "file-arrow-down-fill": {}, + "file-arrow-down": {}, + "file-arrow-up-fill": {}, + "file-arrow-up": {}, + "file-bar-graph-fill": {}, + "file-bar-graph": {}, + "file-binary-fill": {}, + "file-binary": {}, + "file-break-fill": {}, + "file-break": {}, + "file-check-fill": {}, + "file-check": {}, + "file-code-fill": {}, + "file-code": {}, + "file-diff-fill": {}, + "file-diff": {}, + "file-earmark-arrow-down-fill": {}, + "file-earmark-arrow-down": {}, + "file-earmark-arrow-up-fill": {}, + "file-earmark-arrow-up": {}, + "file-earmark-bar-graph-fill": {}, + "file-earmark-bar-graph": {}, + "file-earmark-binary-fill": {}, + "file-earmark-binary": {}, + "file-earmark-break-fill": {}, + "file-earmark-break": {}, + "file-earmark-check-fill": {}, + "file-earmark-check": {}, + "file-earmark-code-fill": {}, + "file-earmark-code": {}, + "file-earmark-diff-fill": {}, + "file-earmark-diff": {}, + "file-earmark-easel-fill": {}, + "file-earmark-easel": {}, + "file-earmark-excel-fill": {}, + "file-earmark-excel": {}, + "file-earmark-fill": {}, + "file-earmark-font-fill": {}, + "file-earmark-font": {}, + "file-earmark-image-fill": {}, + "file-earmark-image": {}, + "file-earmark-lock-fill": {}, + "file-earmark-lock": {}, + "file-earmark-lock2-fill": {}, + "file-earmark-lock2": {}, + "file-earmark-medical-fill": {}, + "file-earmark-medical": {}, + "file-earmark-minus-fill": {}, + "file-earmark-minus": {}, + "file-earmark-music-fill": {}, + "file-earmark-music": {}, + "file-earmark-person-fill": {}, + "file-earmark-person": {}, + "file-earmark-play-fill": {}, + "file-earmark-play": {}, + "file-earmark-plus-fill": {}, + "file-earmark-plus": {}, + "file-earmark-post-fill": {}, + "file-earmark-post": {}, + "file-earmark-ppt-fill": {}, + "file-earmark-ppt": {}, + "file-earmark-richtext-fill": {}, + "file-earmark-richtext": {}, + "file-earmark-ruled-fill": {}, + "file-earmark-ruled": {}, + "file-earmark-slides-fill": {}, + "file-earmark-slides": {}, + "file-earmark-spreadsheet-fill": {}, + "file-earmark-spreadsheet": {}, + "file-earmark-text-fill": {}, + "file-earmark-text": {}, + "file-earmark-word-fill": {}, + "file-earmark-word": {}, + "file-earmark-x-fill": {}, + "file-earmark-x": {}, + "file-earmark-zip-fill": {}, + "file-earmark-zip": {}, + "file-earmark": {}, + "file-easel-fill": {}, + "file-easel": {}, + "file-excel-fill": {}, + "file-excel": {}, + "file-fill": {}, + "file-font-fill": {}, + "file-font": {}, + "file-image-fill": {}, + "file-image": {}, + "file-lock-fill": {}, + "file-lock": {}, + "file-lock2-fill": {}, + "file-lock2": {}, + "file-medical-fill": {}, + "file-medical": {}, + "file-minus-fill": {}, + "file-minus": {}, + "file-music-fill": {}, + "file-music": {}, + "file-person-fill": {}, + "file-person": {}, + "file-play-fill": {}, + "file-play": {}, + "file-plus-fill": {}, + "file-plus": {}, + "file-post-fill": {}, + "file-post": {}, + "file-ppt-fill": {}, + "file-ppt": {}, + "file-richtext-fill": {}, + "file-richtext": {}, + "file-ruled-fill": {}, + "file-ruled": {}, + "file-slides-fill": {}, + "file-slides": {}, + "file-spreadsheet-fill": {}, + "file-spreadsheet": {}, + "file-text-fill": {}, + "file-text": {}, + "file-word-fill": {}, + "file-word": {}, + "file-x-fill": {}, + "file-x": {}, + "file-zip-fill": {}, + "file-zip": {}, + "file": {}, + "files-alt": {}, + "files": {}, + "film": {}, + "filter-circle-fill": {}, + "filter-circle": {}, + "filter-left": {}, + "filter-right": {}, + "filter-square-fill": {}, + "filter-square": {}, + "filter": {}, + "flag-fill": {}, + "flag": {}, + "flower1": {}, + "flower2": {}, + "flower3": {}, + "folder-check": {}, + "folder-fill": {}, + "folder-minus": {}, + "folder-plus": {}, + "folder-symlink-fill": {}, + "folder-symlink": {}, + "folder-x": {}, + "folder": {}, + "folder2-open": {}, + "folder2": {}, + "fonts": {}, + "forward-fill": {}, + "forward": {}, + "front": {}, + "fullscreen-exit": {}, + "fullscreen": {}, + "funnel-fill": {}, + "funnel": {}, + "gear-fill": {}, + "gear-wide-connected": {}, + "gear-wide": {}, + "gear": {}, + "gem": {}, + "geo-alt-fill": {}, + "geo-alt": {}, + "geo-fill": {}, + "geo": {}, + "gift-fill": {}, + "gift": {}, + "github": {}, + "globe": {}, + "globe2": {}, + "google": {}, + "graph-down": {}, + "graph-up": {}, + "grid-1x2-fill": {}, + "grid-1x2": {}, + "grid-3x2-gap-fill": {}, + "grid-3x2-gap": {}, + "grid-3x2": {}, + "grid-3x3-gap-fill": {}, + "grid-3x3-gap": {}, + "grid-3x3": {}, + "grid-fill": {}, + "grid": {}, + "grip-horizontal": {}, + "grip-vertical": {}, + "hammer": {}, + "hand-index-fill": {}, + "hand-index-thumb-fill": {}, + "hand-index-thumb": {}, + "hand-index": {}, + "hand-thumbs-down-fill": {}, + "hand-thumbs-down": {}, + "hand-thumbs-up-fill": {}, + "hand-thumbs-up": {}, + "handbag-fill": {}, + "handbag": {}, + "hash": {}, + "hdd-fill": {}, + "hdd-network-fill": {}, + "hdd-network": {}, + "hdd-rack-fill": {}, + "hdd-rack": {}, + "hdd-stack-fill": {}, + "hdd-stack": {}, + "hdd": {}, + "headphones": {}, + "headset": {}, + "heart-fill": {}, + "heart-half": {}, + "heart": {}, + "heptagon-fill": {}, + "heptagon-half": {}, + "heptagon": {}, + "hexagon-fill": {}, + "hexagon-half": {}, + "hexagon": {}, + "hourglass-bottom": {}, + "hourglass-split": {}, + "hourglass-top": {}, + "hourglass": {}, + "house-door-fill": {}, + "house-door": {}, + "house-fill": {}, + "house": {}, + "hr": {}, + "hurricane": {}, + "image-alt": {}, + "image-fill": {}, + "image": {}, + "images": {}, + "inbox-fill": {}, + "inbox": {}, + "inboxes-fill": {}, + "inboxes": {}, + "info-circle-fill": {}, + "info-circle": {}, + "info-square-fill": {}, + "info-square": {}, + "info": {}, + "input-cursor-text": {}, + "input-cursor": {}, + "instagram": {}, + "intersect": {}, + "journal-album": {}, + "journal-arrow-down": {}, + "journal-arrow-up": {}, + "journal-bookmark-fill": {}, + "journal-bookmark": {}, + "journal-check": {}, + "journal-code": {}, + "journal-medical": {}, + "journal-minus": {}, + "journal-plus": {}, + "journal-richtext": {}, + "journal-text": {}, + "journal-x": {}, + "journal": {}, + "journals": {}, + "joystick": {}, + "justify-left": {}, + "justify-right": {}, + "justify": {}, + "kanban-fill": {}, + "kanban": {}, + "key-fill": {}, + "key": {}, + "keyboard-fill": {}, + "keyboard": {}, + "ladder": {}, + "lamp-fill": {}, + "lamp": {}, + "laptop-fill": {}, + "laptop": {}, + "layer-backward": {}, + "layer-forward": {}, + "layers-fill": {}, + "layers-half": {}, + "layers": {}, + "layout-sidebar-inset-reverse": {}, + "layout-sidebar-inset": {}, + "layout-sidebar-reverse": {}, + "layout-sidebar": {}, + "layout-split": {}, + "layout-text-sidebar-reverse": {}, + "layout-text-sidebar": {}, + "layout-text-window-reverse": {}, + "layout-text-window": {}, + "layout-three-columns": {}, + "layout-wtf": {}, + "life-preserver": {}, + "lightbulb-fill": {}, + "lightbulb-off-fill": {}, + "lightbulb-off": {}, + "lightbulb": {}, + "lightning-charge-fill": {}, + "lightning-charge": {}, + "lightning-fill": {}, + "lightning": {}, + "link-45deg": {}, + "link": {}, + "linkedin": {}, + "list-check": {}, + "list-nested": {}, + "list-ol": {}, + "list-stars": {}, + "list-task": {}, + "list-ul": {}, + "list": {}, + "lock-fill": {}, + "lock": {}, + "mailbox": {}, + "mailbox2": {}, + "map-fill": {}, + "map": {}, + "markdown-fill": {}, + "markdown": {}, + "mask": {}, + "megaphone-fill": {}, + "megaphone": {}, + "menu-app-fill": {}, + "menu-app": {}, + "menu-button-fill": {}, + "menu-button-wide-fill": {}, + "menu-button-wide": {}, + "menu-button": {}, + "menu-down": {}, + "menu-up": {}, + "mic-fill": {}, + "mic-mute-fill": {}, + "mic-mute": {}, + "mic": {}, + "minecart-loaded": {}, + "minecart": {}, + "moisture": {}, + "moon-fill": {}, + "moon-stars-fill": {}, + "moon-stars": {}, + "moon": {}, + "mouse-fill": {}, + "mouse": {}, + "mouse2-fill": {}, + "mouse2": {}, + "mouse3-fill": {}, + "mouse3": {}, + "music-note-beamed": {}, + "music-note-list": {}, + "music-note": {}, + "music-player-fill": {}, + "music-player": {}, + "newspaper": {}, + "node-minus-fill": {}, + "node-minus": {}, + "node-plus-fill": {}, + "node-plus": {}, + "nut-fill": {}, + "nut": {}, + "octagon-fill": {}, + "octagon-half": {}, + "octagon": {}, + "option": {}, + "outlet": {}, + "paint-bucket": {}, + "palette-fill": {}, + "palette": {}, + "palette2": {}, + "paperclip": {}, + "paragraph": {}, + "patch-check-fill": {}, + "patch-check": {}, + "patch-exclamation-fill": {}, + "patch-exclamation": {}, + "patch-minus-fill": {}, + "patch-minus": {}, + "patch-plus-fill": {}, + "patch-plus": {}, + "patch-question-fill": {}, + "patch-question": {}, + "pause-btn-fill": {}, + "pause-btn": {}, + "pause-circle-fill": {}, + "pause-circle": {}, + "pause-fill": {}, + "pause": {}, + "peace-fill": {}, + "peace": {}, + "pen-fill": {}, + "pen": {}, + "pencil-fill": {}, + "pencil-square": {}, + "pencil": {}, + "pentagon-fill": {}, + "pentagon-half": {}, + "pentagon": {}, + "people-fill": {}, + "people": {}, + "percent": {}, + "person-badge-fill": {}, + "person-badge": {}, + "person-bounding-box": {}, + "person-check-fill": {}, + "person-check": {}, + "person-circle": {}, + "person-dash-fill": {}, + "person-dash": {}, + "person-fill": {}, + "person-lines-fill": {}, + "person-plus-fill": {}, + "person-plus": {}, + "person-square": {}, + "person-x-fill": {}, + "person-x": {}, + "person": {}, + "phone-fill": {}, + "phone-landscape-fill": {}, + "phone-landscape": {}, + "phone-vibrate-fill": {}, + "phone-vibrate": {}, + "phone": {}, + "pie-chart-fill": {}, + "pie-chart": {}, + "pin-angle-fill": {}, + "pin-angle": {}, + "pin-fill": {}, + "pin": {}, + "pip-fill": {}, + "pip": {}, + "play-btn-fill": {}, + "play-btn": {}, + "play-circle-fill": {}, + "play-circle": {}, + "play-fill": {}, + "play": {}, + "plug-fill": {}, + "plug": {}, + "plus-circle-dotted": {}, + "plus-circle-fill": {}, + "plus-circle": {}, + "plus-square-dotted": {}, + "plus-square-fill": {}, + "plus-square": {}, + "plus": {}, + "power": {}, + "printer-fill": {}, + "printer": {}, + "puzzle-fill": {}, + "puzzle": {}, + "question-circle-fill": {}, + "question-circle": {}, + "question-diamond-fill": {}, + "question-diamond": {}, + "question-octagon-fill": {}, + "question-octagon": {}, + "question-square-fill": {}, + "question-square": {}, + "question": {}, + "rainbow": {}, + "receipt-cutoff": {}, + "receipt": {}, + "reception-0": {}, + "reception-1": {}, + "reception-2": {}, + "reception-3": {}, + "reception-4": {}, + "record-btn-fill": {}, + "record-btn": {}, + "record-circle-fill": {}, + "record-circle": {}, + "record-fill": {}, + "record": {}, + "record2-fill": {}, + "record2": {}, + "reply-all-fill": {}, + "reply-all": {}, + "reply-fill": {}, + "reply": {}, + "rss-fill": {}, + "rss": {}, + "rulers": {}, + "save-fill": {}, + "save": {}, + "save2-fill": {}, + "save2": {}, + "scissors": {}, + "screwdriver": {}, + "search": {}, + "segmented-nav": {}, + "server": {}, + "share-fill": {}, + "share": {}, + "shield-check": {}, + "shield-exclamation": {}, + "shield-fill-check": {}, + "shield-fill-exclamation": {}, + "shield-fill-minus": {}, + "shield-fill-plus": {}, + "shield-fill-x": {}, + "shield-fill": {}, + "shield-lock-fill": {}, + "shield-lock": {}, + "shield-minus": {}, + "shield-plus": {}, + "shield-shaded": {}, + "shield-slash-fill": {}, + "shield-slash": {}, + "shield-x": {}, + "shield": {}, + "shift-fill": {}, + "shift": {}, + "shop-window": {}, + "shop": {}, + "shuffle": {}, + "signpost-2-fill": {}, + "signpost-2": {}, + "signpost-fill": {}, + "signpost-split-fill": {}, + "signpost-split": {}, + "signpost": {}, + "sim-fill": {}, + "sim": {}, + "skip-backward-btn-fill": {}, + "skip-backward-btn": {}, + "skip-backward-circle-fill": {}, + "skip-backward-circle": {}, + "skip-backward-fill": {}, + "skip-backward": {}, + "skip-end-btn-fill": {}, + "skip-end-btn": {}, + "skip-end-circle-fill": {}, + "skip-end-circle": {}, + "skip-end-fill": {}, + "skip-end": {}, + "skip-forward-btn-fill": {}, + "skip-forward-btn": {}, + "skip-forward-circle-fill": {}, + "skip-forward-circle": {}, + "skip-forward-fill": {}, + "skip-forward": {}, + "skip-start-btn-fill": {}, + "skip-start-btn": {}, + "skip-start-circle-fill": {}, + "skip-start-circle": {}, + "skip-start-fill": {}, + "skip-start": {}, + "slack": {}, + "slash-circle-fill": {}, + "slash-circle": {}, + "slash-square-fill": {}, + "slash-square": {}, + "slash": {}, + "sliders": {}, + "smartwatch": {}, + "snow": {}, + "snow2": {}, + "snow3": {}, + "sort-alpha-down-alt": {}, + "sort-alpha-down": {}, + "sort-alpha-up-alt": {}, + "sort-alpha-up": {}, + "sort-down-alt": {}, + "sort-down": {}, + "sort-numeric-down-alt": {}, + "sort-numeric-down": {}, + "sort-numeric-up-alt": {}, + "sort-numeric-up": {}, + "sort-up-alt": {}, + "sort-up": {}, + "soundwave": {}, + "speaker-fill": {}, + "speaker": {}, + "speedometer": {}, + "speedometer2": {}, + "spellcheck": {}, + "square-fill": {}, + "square-half": {}, + "square": {}, + "stack": {}, + "star-fill": {}, + "star-half": {}, + "star": {}, + "stars": {}, + "stickies-fill": {}, + "stickies": {}, + "sticky-fill": {}, + "sticky": {}, + "stop-btn-fill": {}, + "stop-btn": {}, + "stop-circle-fill": {}, + "stop-circle": {}, + "stop-fill": {}, + "stop": {}, + "stoplights-fill": {}, + "stoplights": {}, + "stopwatch-fill": {}, + "stopwatch": {}, + "subtract": {}, + "suit-club-fill": {}, + "suit-club": {}, + "suit-diamond-fill": {}, + "suit-diamond": {}, + "suit-heart-fill": {}, + "suit-heart": {}, + "suit-spade-fill": {}, + "suit-spade": {}, + "sun-fill": {}, + "sun": {}, + "sunglasses": {}, + "sunrise-fill": {}, + "sunrise": {}, + "sunset-fill": {}, + "sunset": {}, + "symmetry-horizontal": {}, + "symmetry-vertical": {}, + "table": {}, + "tablet-fill": {}, + "tablet-landscape-fill": {}, + "tablet-landscape": {}, + "tablet": {}, + "tag-fill": {}, + "tag": {}, + "tags-fill": {}, + "tags": {}, + "telegram": {}, + "telephone-fill": {}, + "telephone-forward-fill": {}, + "telephone-forward": {}, + "telephone-inbound-fill": {}, + "telephone-inbound": {}, + "telephone-minus-fill": {}, + "telephone-minus": {}, + "telephone-outbound-fill": {}, + "telephone-outbound": {}, + "telephone-plus-fill": {}, + "telephone-plus": {}, + "telephone-x-fill": {}, + "telephone-x": {}, + "telephone": {}, + "terminal-fill": {}, + "terminal": {}, + "text-center": {}, + "text-indent-left": {}, + "text-indent-right": {}, + "text-left": {}, + "text-paragraph": {}, + "text-right": {}, + "textarea-resize": {}, + "textarea-t": {}, + "textarea": {}, + "thermometer-half": {}, + "thermometer-high": {}, + "thermometer-low": {}, + "thermometer-snow": {}, + "thermometer-sun": {}, + "thermometer": {}, + "three-dots-vertical": {}, + "three-dots": {}, + "toggle-off": {}, + "toggle-on": {}, + "toggle2-off": {}, + "toggle2-on": {}, + "toggles": {}, + "toggles2": {}, + "tools": {}, + "tornado": {}, + "trash-fill": {}, + "trash": {}, + "trash2-fill": {}, + "trash2": {}, + "tree-fill": {}, + "tree": {}, + "triangle-fill": {}, + "triangle-half": {}, + "triangle": {}, + "trophy-fill": {}, + "trophy": {}, + "tropical-storm": {}, + "truck-flatbed": {}, + "truck": {}, + "tsunami": {}, + "tv-fill": {}, + "tv": {}, + "twitch": {}, + "twitter": {}, + "type-bold": {}, + "type-h1": {}, + "type-h2": {}, + "type-h3": {}, + "type-italic": {}, + "type-strikethrough": {}, + "type-underline": {}, + "type": {}, + "ui-checks-grid": {}, + "ui-checks": {}, + "ui-radios-grid": {}, + "ui-radios": {}, + "umbrella-fill": {}, + "umbrella": {}, + "union": {}, + "unlock-fill": {}, + "unlock": {}, + "upc-scan": {}, + "upc": {}, + "upload": {}, + "vector-pen": {}, + "view-list": {}, + "view-stacked": {}, + "vinyl-fill": {}, + "vinyl": {}, + "voicemail": {}, + "volume-down-fill": {}, + "volume-down": {}, + "volume-mute-fill": {}, + "volume-mute": {}, + "volume-off-fill": {}, + "volume-off": {}, + "volume-up-fill": {}, + "volume-up": {}, + "vr": {}, + "wallet-fill": {}, + "wallet": {}, + "wallet2": {}, + "watch": {}, + "water": {}, + "whatsapp": {}, + "wifi-1": {}, + "wifi-2": {}, + "wifi-off": {}, + "wifi": {}, + "wind": {}, + "window-dock": {}, + "window-sidebar": {}, + "window": {}, + "wrench": {}, + "x-circle-fill": {}, + "x-circle": {}, + "x-diamond-fill": {}, + "x-diamond": {}, + "x-octagon-fill": {}, + "x-octagon": {}, + "x-square-fill": {}, + "x-square": {}, + "x": {}, + "youtube": {}, + "zoom-in": {}, + "zoom-out": {}, + "bank": {}, + "bank2": {}, + "bell-slash-fill": {}, + "bell-slash": {}, + "cash-coin": {}, + "check-lg": {}, + "coin": {}, + "currency-bitcoin": {}, + "currency-dollar": {}, + "currency-euro": {}, + "currency-exchange": {}, + "currency-pound": {}, + "currency-yen": {}, + "dash-lg": {}, + "exclamation-lg": {}, + "file-earmark-pdf-fill": {}, + "file-earmark-pdf": {}, + "file-pdf-fill": {}, + "file-pdf": {}, + "gender-ambiguous": {}, + "gender-female": {}, + "gender-male": {}, + "gender-trans": {}, + "headset-vr": {}, + "info-lg": {}, + "mastodon": {}, + "messenger": {}, + "piggy-bank-fill": {}, + "piggy-bank": {}, + "pin-map-fill": {}, + "pin-map": {}, + "plus-lg": {}, + "question-lg": {}, + "recycle": {}, + "reddit": {}, + "safe-fill": {}, + "safe2-fill": {}, + "safe2": {}, + "sd-card-fill": {}, + "sd-card": {}, + "skype": {}, + "slash-lg": {}, + "translate": {}, + "x-lg": {}, + "safe": {}, + "apple": {}, + "microsoft": {}, + "windows": {}, + "behance": {}, + "dribbble": {}, + "line": {}, + "medium": {}, + "paypal": {}, + "pinterest": {}, + "signal": {}, + "snapchat": {}, + "spotify": {}, + "stack-overflow": {}, + "strava": {}, + "wordpress": {}, + "vimeo": {}, + "activity": {}, + "easel2-fill": {}, + "easel2": {}, + "easel3-fill": {}, + "easel3": {}, + "fan": {}, + "fingerprint": {}, + "graph-down-arrow": {}, + "graph-up-arrow": {}, + "hypnotize": {}, + "magic": {}, + "person-rolodex": {}, + "person-video": {}, + "person-video2": {}, + "person-video3": {}, + "person-workspace": {}, + "radioactive": {}, + "webcam-fill": {}, + "webcam": {}, + "yin-yang": {}, + "bandaid-fill": {}, + "bandaid": {}, + "bluetooth": {}, + "body-text": {}, + "boombox": {}, + "boxes": {}, + "dpad-fill": {}, + "dpad": {}, + "ear-fill": {}, + "ear": {}, + "envelope-check-fill": {}, + "envelope-check": {}, + "envelope-dash-fill": {}, + "envelope-dash": {}, + "envelope-exclamation-fill": {}, + "envelope-exclamation": {}, + "envelope-plus-fill": {}, + "envelope-plus": {}, + "envelope-slash-fill": {}, + "envelope-slash": {}, + "envelope-x-fill": {}, + "envelope-x": {}, + "explicit-fill": {}, + "explicit": {}, + "git": {}, + "infinity": {}, + "list-columns-reverse": {}, + "list-columns": {}, + "meta": {}, + "nintendo-switch": {}, + "pc-display-horizontal": {}, + "pc-display": {}, + "pc-horizontal": {}, + "pc": {}, + "playstation": {}, + "plus-slash-minus": {}, + "projector-fill": {}, + "projector": {}, + "qr-code-scan": {}, + "qr-code": {}, + "quora": {}, + "quote": {}, + "robot": {}, + "send-check-fill": {}, + "send-check": {}, + "send-dash-fill": {}, + "send-dash": {}, + "send-exclamation-fill": {}, + "send-exclamation": {}, + "send-fill": {}, + "send-plus-fill": {}, + "send-plus": {}, + "send-slash-fill": {}, + "send-slash": {}, + "send-x-fill": {}, + "send-x": {}, + "send": {}, + "steam": {}, + "terminal-dash": {}, + "terminal-plus": {}, + "terminal-split": {}, + "ticket-detailed-fill": {}, + "ticket-detailed": {}, + "ticket-fill": {}, + "ticket-perforated-fill": {}, + "ticket-perforated": {}, + "ticket": {}, + "tiktok": {}, + "window-dash": {}, + "window-desktop": {}, + "window-fullscreen": {}, + "window-plus": {}, + "window-split": {}, + "window-stack": {}, + "window-x": {}, + "xbox": {}, + "ethernet": {}, + "hdmi-fill": {}, + "hdmi": {}, + "usb-c-fill": {}, + "usb-c": {}, + "usb-fill": {}, + "usb-plug-fill": {}, + "usb-plug": {}, + "usb-symbol": {}, + "usb": {}, + "boombox-fill": {}, + "displayport": {}, + "gpu-card": {}, + "memory": {}, + "modem-fill": {}, + "modem": {}, + "motherboard-fill": {}, + "motherboard": {}, + "optical-audio-fill": {}, + "optical-audio": {}, + "pci-card": {}, + "router-fill": {}, + "router": {}, + "thunderbolt-fill": {}, + "thunderbolt": {}, + "usb-drive-fill": {}, + "usb-drive": {}, + "usb-micro-fill": {}, + "usb-micro": {}, + "usb-mini-fill": {}, + "usb-mini": {}, + "cloud-haze2": {}, + "device-hdd-fill": {}, + "device-hdd": {}, + "device-ssd-fill": {}, + "device-ssd": {}, + "displayport-fill": {}, + "mortarboard-fill": {}, + "mortarboard": {}, + "terminal-x": {}, + "arrow-through-heart-fill": {}, + "arrow-through-heart": {}, + "badge-sd-fill": {}, + "badge-sd": {}, + "bag-heart-fill": {}, + "bag-heart": {}, + "balloon-fill": {}, + "balloon-heart-fill": {}, + "balloon-heart": {}, + "balloon": {}, + "box2-fill": {}, + "box2-heart-fill": {}, + "box2-heart": {}, + "box2": {}, + "braces-asterisk": {}, + "calendar-heart-fill": {}, + "calendar-heart": {}, + "calendar2-heart-fill": {}, + "calendar2-heart": {}, + "chat-heart-fill": {}, + "chat-heart": {}, + "chat-left-heart-fill": {}, + "chat-left-heart": {}, + "chat-right-heart-fill": {}, + "chat-right-heart": {}, + "chat-square-heart-fill": {}, + "chat-square-heart": {}, + "clipboard-check-fill": {}, + "clipboard-data-fill": {}, + "clipboard-fill": {}, + "clipboard-heart-fill": {}, + "clipboard-heart": {}, + "clipboard-minus-fill": {}, + "clipboard-plus-fill": {}, + "clipboard-pulse": {}, + "clipboard-x-fill": {}, + "clipboard2-check-fill": {}, + "clipboard2-check": {}, + "clipboard2-data-fill": {}, + "clipboard2-data": {}, + "clipboard2-fill": {}, + "clipboard2-heart-fill": {}, + "clipboard2-heart": {}, + "clipboard2-minus-fill": {}, + "clipboard2-minus": {}, + "clipboard2-plus-fill": {}, + "clipboard2-plus": {}, + "clipboard2-pulse-fill": {}, + "clipboard2-pulse": {}, + "clipboard2-x-fill": {}, + "clipboard2-x": {}, + "clipboard2": {}, + "emoji-kiss-fill": {}, + "emoji-kiss": {}, + "envelope-heart-fill": {}, + "envelope-heart": {}, + "envelope-open-heart-fill": {}, + "envelope-open-heart": {}, + "envelope-paper-fill": {}, + "envelope-paper-heart-fill": {}, + "envelope-paper-heart": {}, + "envelope-paper": {}, + "filetype-aac": {}, + "filetype-ai": {}, + "filetype-bmp": {}, + "filetype-cs": {}, + "filetype-css": {}, + "filetype-csv": {}, + "filetype-doc": {}, + "filetype-docx": {}, + "filetype-exe": {}, + "filetype-gif": {}, + "filetype-heic": {}, + "filetype-html": {}, + "filetype-java": {}, + "filetype-jpg": {}, + "filetype-js": {}, + "filetype-jsx": {}, + "filetype-key": {}, + "filetype-m4p": {}, + "filetype-md": {}, + "filetype-mdx": {}, + "filetype-mov": {}, + "filetype-mp3": {}, + "filetype-mp4": {}, + "filetype-otf": {}, + "filetype-pdf": {}, + "filetype-php": {}, + "filetype-png": {}, + "filetype-ppt": {}, + "filetype-psd": {}, + "filetype-py": {}, + "filetype-raw": {}, + "filetype-rb": {}, + "filetype-sass": {}, + "filetype-scss": {}, + "filetype-sh": {}, + "filetype-svg": {}, + "filetype-tiff": {}, + "filetype-tsx": {}, + "filetype-ttf": {}, + "filetype-txt": {}, + "filetype-wav": {}, + "filetype-woff": {}, + "filetype-xls": {}, + "filetype-xml": {}, + "filetype-yml": {}, + "heart-arrow": {}, + "heart-pulse-fill": {}, + "heart-pulse": {}, + "heartbreak-fill": {}, + "heartbreak": {}, + "hearts": {}, + "hospital-fill": {}, + "hospital": {}, + "house-heart-fill": {}, + "house-heart": {}, + "incognito": {}, + "magnet-fill": {}, + "magnet": {}, + "person-heart": {}, + "person-hearts": {}, + "phone-flip": {}, + "plugin": {}, + "postage-fill": {}, + "postage-heart-fill": {}, + "postage-heart": {}, + "postage": {}, + "postcard-fill": {}, + "postcard-heart-fill": {}, + "postcard-heart": {}, + "postcard": {}, + "search-heart-fill": {}, + "search-heart": {}, + "sliders2-vertical": {}, + "sliders2": {}, + "trash3-fill": {}, + "trash3": {}, + "valentine": {}, + "valentine2": {}, + "wrench-adjustable-circle-fill": {}, + "wrench-adjustable-circle": {}, + "wrench-adjustable": {}, + "filetype-json": {}, + "filetype-pptx": {}, + "filetype-xlsx": {}, + "1-circle-fill": {}, + "1-circle": {}, + "1-square-fill": {}, + "1-square": {}, + "2-circle-fill": {}, + "2-circle": {}, + "2-square-fill": {}, + "2-square": {}, + "3-circle-fill": {}, + "3-circle": {}, + "3-square-fill": {}, + "3-square": {}, + "4-circle-fill": {}, + "4-circle": {}, + "4-square-fill": {}, + "4-square": {}, + "5-circle-fill": {}, + "5-circle": {}, + "5-square-fill": {}, + "5-square": {}, + "6-circle-fill": {}, + "6-circle": {}, + "6-square-fill": {}, + "6-square": {}, + "7-circle-fill": {}, + "7-circle": {}, + "7-square-fill": {}, + "7-square": {}, + "8-circle-fill": {}, + "8-circle": {}, + "8-square-fill": {}, + "8-square": {}, + "9-circle-fill": {}, + "9-circle": {}, + "9-square-fill": {}, + "9-square": {}, + "airplane-engines-fill": {}, + "airplane-engines": {}, + "airplane-fill": {}, + "airplane": {}, + "alexa": {}, + "alipay": {}, + "android": {}, + "android2": {}, + "box-fill": {}, + "box-seam-fill": {}, + "browser-chrome": {}, + "browser-edge": {}, + "browser-firefox": {}, + "browser-safari": {}, + "c-circle-fill": {}, + "c-circle": {}, + "c-square-fill": {}, + "c-square": {}, + "capsule-pill": {}, + "capsule": {}, + "car-front-fill": {}, + "car-front": {}, + "cassette-fill": {}, + "cassette": {}, + "cc-circle-fill": {}, + "cc-circle": {}, + "cc-square-fill": {}, + "cc-square": {}, + "cup-hot-fill": {}, + "cup-hot": {}, + "currency-rupee": {}, + "dropbox": {}, + "escape": {}, + "fast-forward-btn-fill": {}, + "fast-forward-btn": {}, + "fast-forward-circle-fill": {}, + "fast-forward-circle": {}, + "fast-forward-fill": {}, + "fast-forward": {}, + "filetype-sql": {}, + "fire": {}, + "google-play": {}, + "h-circle-fill": {}, + "h-circle": {}, + "h-square-fill": {}, + "h-square": {}, + "indent": {}, + "lungs-fill": {}, + "lungs": {}, + "microsoft-teams": {}, + "p-circle-fill": {}, + "p-circle": {}, + "p-square-fill": {}, + "p-square": {}, + "pass-fill": {}, + "pass": {}, + "prescription": {}, + "prescription2": {}, + "r-circle-fill": {}, + "r-circle": {}, + "r-square-fill": {}, + "r-square": {}, + "repeat-1": {}, + "repeat": {}, + "rewind-btn-fill": {}, + "rewind-btn": {}, + "rewind-circle-fill": {}, + "rewind-circle": {}, + "rewind-fill": {}, + "rewind": {}, + "train-freight-front-fill": {}, + "train-freight-front": {}, + "train-front-fill": {}, + "train-front": {}, + "train-lightrail-front-fill": {}, + "train-lightrail-front": {}, + "truck-front-fill": {}, + "truck-front": {}, + "ubuntu": {}, + "unindent": {}, + "unity": {}, + "universal-access-circle": {}, + "universal-access": {}, + "virus": {}, + "virus2": {}, + "wechat": {}, + "yelp": {}, + "sign-stop-fill": {}, + "sign-stop-lights-fill": {}, + "sign-stop-lights": {}, + "sign-stop": {}, + "sign-turn-left-fill": {}, + "sign-turn-left": {}, + "sign-turn-right-fill": {}, + "sign-turn-right": {}, + "sign-turn-slight-left-fill": {}, + "sign-turn-slight-left": {}, + "sign-turn-slight-right-fill": {}, + "sign-turn-slight-right": {}, + "sign-yield-fill": {}, + "sign-yield": {}, + "ev-station-fill": {}, + "ev-station": {}, + "fuel-pump-diesel-fill": {}, + "fuel-pump-diesel": {}, + "fuel-pump-fill": {}, + "fuel-pump": {}, + "0-circle-fill": {}, + "0-circle": {}, + "0-square-fill": {}, + "0-square": {}, + "rocket-fill": {}, + "rocket-takeoff-fill": {}, + "rocket-takeoff": {}, + "rocket": {}, + "stripe": {}, + "subscript": {}, + "superscript": {}, + "trello": {}, + "envelope-at-fill": {}, + "envelope-at": {}, + "regex": {}, + "text-wrap": {}, + "sign-dead-end-fill": {}, + "sign-dead-end": {}, + "sign-do-not-enter-fill": {}, + "sign-do-not-enter": {}, + "sign-intersection-fill": {}, + "sign-intersection-side-fill": {}, + "sign-intersection-side": {}, + "sign-intersection-t-fill": {}, + "sign-intersection-t": {}, + "sign-intersection-y-fill": {}, + "sign-intersection-y": {}, + "sign-intersection": {}, + "sign-merge-left-fill": {}, + "sign-merge-left": {}, + "sign-merge-right-fill": {}, + "sign-merge-right": {}, + "sign-no-left-turn-fill": {}, + "sign-no-left-turn": {}, + "sign-no-parking-fill": {}, + "sign-no-parking": {}, + "sign-no-right-turn-fill": {}, + "sign-no-right-turn": {}, + "sign-railroad-fill": {}, + "sign-railroad": {}, + "building-add": {}, + "building-check": {}, + "building-dash": {}, + "building-down": {}, + "building-exclamation": {}, + "building-fill-add": {}, + "building-fill-check": {}, + "building-fill-dash": {}, + "building-fill-down": {}, + "building-fill-exclamation": {}, + "building-fill-gear": {}, + "building-fill-lock": {}, + "building-fill-slash": {}, + "building-fill-up": {}, + "building-fill-x": {}, + "building-fill": {}, + "building-gear": {}, + "building-lock": {}, + "building-slash": {}, + "building-up": {}, + "building-x": {}, + "buildings-fill": {}, + "buildings": {}, + "bus-front-fill": {}, + "bus-front": {}, + "ev-front-fill": {}, + "ev-front": {}, + "globe-americas": {}, + "globe-asia-australia": {}, + "globe-central-south-asia": {}, + "globe-europe-africa": {}, + "house-add-fill": {}, + "house-add": {}, + "house-check-fill": {}, + "house-check": {}, + "house-dash-fill": {}, + "house-dash": {}, + "house-down-fill": {}, + "house-down": {}, + "house-exclamation-fill": {}, + "house-exclamation": {}, + "house-gear-fill": {}, + "house-gear": {}, + "house-lock-fill": {}, + "house-lock": {}, + "house-slash-fill": {}, + "house-slash": {}, + "house-up-fill": {}, + "house-up": {}, + "house-x-fill": {}, + "house-x": {}, + "person-add": {}, + "person-down": {}, + "person-exclamation": {}, + "person-fill-add": {}, + "person-fill-check": {}, + "person-fill-dash": {}, + "person-fill-down": {}, + "person-fill-exclamation": {}, + "person-fill-gear": {}, + "person-fill-lock": {}, + "person-fill-slash": {}, + "person-fill-up": {}, + "person-fill-x": {}, + "person-gear": {}, + "person-lock": {}, + "person-slash": {}, + "person-up": {}, + "scooter": {}, + "taxi-front-fill": {}, + "taxi-front": {}, + "amd": {}, + "database-add": {}, + "database-check": {}, + "database-dash": {}, + "database-down": {}, + "database-exclamation": {}, + "database-fill-add": {}, + "database-fill-check": {}, + "database-fill-dash": {}, + "database-fill-down": {}, + "database-fill-exclamation": {}, + "database-fill-gear": {}, + "database-fill-lock": {}, + "database-fill-slash": {}, + "database-fill-up": {}, + "database-fill-x": {}, + "database-fill": {}, + "database-gear": {}, + "database-lock": {}, + "database-slash": {}, + "database-up": {}, + "database-x": {}, + "database": {}, + "houses-fill": {}, + "houses": {}, + "nvidia": {}, + "person-vcard-fill": {}, + "person-vcard": {}, + "sina-weibo": {}, + "tencent-qq": {}, + "wikipedia": {}, } // IsValid returns true if the input is the name of a Bootstrap icon. func IsValid(name string) bool { - for i := range icons { - if icons[i] == name { - return true - } - } - return false + _, ok := icons[name] + return ok } diff --git a/frontend/icons.js b/frontend/icons.js index 6b0e67f..844d640 100644 --- a/frontend/icons.js +++ b/frontend/icons.js @@ -16,26 +16,22 @@ writeFileSync("src/icons.ts", `const icons = ${output};\nexport default icons;`) const goCode1 = `// Generated code. DO NOT EDIT package icons -var icons = [...]string{ +var icons = map[string]struct{}{ `; const goCode2 = `} // IsValid returns true if the input is the name of a Bootstrap icon. func IsValid(name string) bool { - for i := range icons { - if icons[i] == name { - return true - } - } - return false + _, ok := icons[name] + return ok } `; let goOutput = goCode1; keys.forEach((element) => { - goOutput += ` "${element}",\n`; + goOutput += ` "${element}": {},\n`; }); goOutput += goCode2; From b04ed68832704c4162239f2a199ab1e513b0be89 Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 02:39:14 +0200 Subject: [PATCH 03/26] feat(backend): add sentry integration --- backend/main.go | 9 +++++++ backend/routes/v1/auth/discord.go | 14 +++++----- backend/routes/v1/auth/fedi_mastodon.go | 12 ++++----- backend/routes/v1/auth/fedi_misskey.go | 10 +++---- backend/routes/v1/auth/google.go | 12 ++++----- backend/routes/v1/auth/tumblr.go | 12 ++++----- backend/routes/v1/member/create_member.go | 12 ++++----- backend/routes/v1/member/delete_member.go | 2 +- backend/routes/v1/member/get_member.go | 14 +++++----- backend/routes/v1/member/get_members.go | 5 ++-- backend/routes/v1/member/patch_member.go | 20 +++++++------- backend/routes/v1/user/export.go | 3 ++- backend/routes/v1/user/get_user.go | 17 ++++++------ backend/routes/v1/user/patch_user.go | 22 +++++++-------- backend/routes/v2/user/get_settings.go | 3 ++- backend/server/errors.go | 33 ++++++++++++++++++----- docs/api/errors.md | 13 ++++----- go.mod | 1 + go.sum | 6 ++++- 19 files changed, 130 insertions(+), 90 deletions(-) diff --git a/backend/main.go b/backend/main.go index 008e80f..0cb68a8 100644 --- a/backend/main.go +++ b/backend/main.go @@ -11,6 +11,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "github.com/davidbyttow/govips/v2/vips" + "github.com/getsentry/sentry-go" "github.com/go-chi/render" _ "github.com/joho/godotenv/autoload" "github.com/urfave/cli/v2" @@ -23,6 +24,14 @@ var Command = &cli.Command{ } func run(c *cli.Context) error { + // initialize sentry + if dsn := os.Getenv("SENTRY_DSN"); dsn != "" { + sentry.Init(sentry.ClientOptions{ + Dsn: dsn, + Release: server.Tag, + }) + } + // set vips log level to WARN, else it will spam logs on info level vips.LoggingSettings(nil, vips.LogLevelWarning) diff --git a/backend/routes/v1/auth/discord.go b/backend/routes/v1/auth/discord.go index f22518c..2084b52 100644 --- a/backend/routes/v1/auth/discord.go +++ b/backend/routes/v1/auth/discord.go @@ -61,7 +61,7 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { // if the state can't be validated, return if valid, err := s.validateCSRFState(ctx, decoded.State); !valid { if err != nil { - return err + return errors.Wrap(err, "validating state") } return server.APIError{Code: server.ErrInvalidState} @@ -79,7 +79,7 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { dg, _ := discordgo.New(token.Type() + " " + token.AccessToken) du, err := dg.User("@me") if err != nil { - return err + return errors.Wrap(err, "getting discord user") } u, err := s.DB.DiscordUser(ctx, du.ID) @@ -90,7 +90,7 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { err = s.saveUndeleteToken(ctx, u.ID, token) if err != nil { log.Errorf("saving undelete token: %v", err) - return err + return errors.Wrap(err, "saving undelete token") } render.JSON(w, r, discordCallbackResponse{ @@ -114,7 +114,7 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { tokenID := xid.New() token, err := s.Auth.CreateToken(u.ID, tokenID, u.IsAdmin, false, true) if err != nil { - return err + return errors.Wrap(err, "creating token") } // save token to database @@ -137,7 +137,7 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { return nil } else if err != db.ErrUserNotFound { // internal error - return err + return errors.Wrap(err, "getting user") } // no user found, so save a ticket + save their Discord info in Redis @@ -145,7 +145,7 @@ func (s *Server) discordCallback(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetJSON(ctx, "discord:"+ticket, du, "EX", "600") if err != nil { log.Errorf("setting Discord user for ticket %q: %v", ticket, err) - return err + return errors.Wrap(err, "caching discord user for ticket") } render.JSON(w, r, discordCallbackResponse{ @@ -278,7 +278,7 @@ func (s *Server) discordSignup(w http.ResponseWriter, r *http.Request) error { valid, taken, err := s.DB.UsernameTaken(ctx, req.Username) if err != nil { - return err + return errors.Wrap(err, "checking if username is taken") } if !valid { return server.APIError{Code: server.ErrInvalidUsername} diff --git a/backend/routes/v1/auth/fedi_mastodon.go b/backend/routes/v1/auth/fedi_mastodon.go index 1cae10b..bb07958 100644 --- a/backend/routes/v1/auth/fedi_mastodon.go +++ b/backend/routes/v1/auth/fedi_mastodon.go @@ -54,7 +54,7 @@ func (s *Server) mastodonCallback(w http.ResponseWriter, r *http.Request) error // if the state can't be validated, return if valid, err := s.validateCSRFState(ctx, decoded.State); !valid { if err != nil { - return err + return errors.Wrap(err, "validating state") } return server.APIError{Code: server.ErrInvalidState} @@ -111,7 +111,7 @@ func (s *Server) mastodonCallback(w http.ResponseWriter, r *http.Request) error err = s.saveUndeleteToken(ctx, u.ID, token) if err != nil { log.Errorf("saving undelete token: %v", err) - return err + return errors.Wrap(err, "saving undelete token") } render.JSON(w, r, fediCallbackResponse{ @@ -135,7 +135,7 @@ func (s *Server) mastodonCallback(w http.ResponseWriter, r *http.Request) error tokenID := xid.New() token, err := s.Auth.CreateToken(u.ID, tokenID, u.IsAdmin, false, true) if err != nil { - return err + return errors.Wrap(err, "creating token") } // save token to database @@ -158,7 +158,7 @@ func (s *Server) mastodonCallback(w http.ResponseWriter, r *http.Request) error return nil } else if err != db.ErrUserNotFound { // internal error - return err + return errors.Wrap(err, "getting user") } // no user found, so save a ticket + save their Mastodon info in Redis @@ -166,7 +166,7 @@ func (s *Server) mastodonCallback(w http.ResponseWriter, r *http.Request) error err = s.DB.SetJSON(ctx, "mastodon:"+ticket, mu, "EX", "600") if err != nil { log.Errorf("setting mastoAPI user for ticket %q: %v", ticket, err) - return err + return errors.Wrap(err, "setting user for ticket") } render.JSON(w, r, fediCallbackResponse{ @@ -306,7 +306,7 @@ func (s *Server) mastodonSignup(w http.ResponseWriter, r *http.Request) error { valid, taken, err := s.DB.UsernameTaken(ctx, req.Username) if err != nil { - return err + return errors.Wrap(err, "checking if username is taken") } if !valid { return server.APIError{Code: server.ErrInvalidUsername} diff --git a/backend/routes/v1/auth/fedi_misskey.go b/backend/routes/v1/auth/fedi_misskey.go index 864b852..ebf6e22 100644 --- a/backend/routes/v1/auth/fedi_misskey.go +++ b/backend/routes/v1/auth/fedi_misskey.go @@ -90,7 +90,7 @@ func (s *Server) misskeyCallback(w http.ResponseWriter, r *http.Request) error { err = s.saveUndeleteToken(ctx, u.ID, token) if err != nil { log.Errorf("saving undelete token: %v", err) - return err + return errors.Wrap(err, "saving undelete token") } render.JSON(w, r, fediCallbackResponse{ @@ -114,7 +114,7 @@ func (s *Server) misskeyCallback(w http.ResponseWriter, r *http.Request) error { tokenID := xid.New() token, err := s.Auth.CreateToken(u.ID, tokenID, u.IsAdmin, false, true) if err != nil { - return err + return errors.Wrap(err, "creating token") } // save token to database @@ -137,7 +137,7 @@ func (s *Server) misskeyCallback(w http.ResponseWriter, r *http.Request) error { return nil } else if err != db.ErrUserNotFound { // internal error - return err + return errors.Wrap(err, "getting user") } // no user found, so save a ticket + save their Misskey info in Redis @@ -145,7 +145,7 @@ func (s *Server) misskeyCallback(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetJSON(ctx, "misskey:"+ticket, mu.User, "EX", "600") if err != nil { log.Errorf("setting misskey user for ticket %q: %v", ticket, err) - return err + return errors.Wrap(err, "setting user for ticket") } render.JSON(w, r, fediCallbackResponse{ @@ -234,7 +234,7 @@ func (s *Server) misskeySignup(w http.ResponseWriter, r *http.Request) error { valid, taken, err := s.DB.UsernameTaken(ctx, req.Username) if err != nil { - return err + return errors.Wrap(err, "checking if username is taken") } if !valid { return server.APIError{Code: server.ErrInvalidUsername} diff --git a/backend/routes/v1/auth/google.go b/backend/routes/v1/auth/google.go index 182c8a6..026a6d1 100644 --- a/backend/routes/v1/auth/google.go +++ b/backend/routes/v1/auth/google.go @@ -60,7 +60,7 @@ func (s *Server) googleCallback(w http.ResponseWriter, r *http.Request) error { // if the state can't be validated, return if valid, err := s.validateCSRFState(ctx, decoded.State); !valid { if err != nil { - return err + return errors.Wrap(err, "validating state") } return server.APIError{Code: server.ErrInvalidState} @@ -109,7 +109,7 @@ func (s *Server) googleCallback(w http.ResponseWriter, r *http.Request) error { err = s.saveUndeleteToken(ctx, u.ID, token) if err != nil { log.Errorf("saving undelete token: %v", err) - return err + return errors.Wrap(err, "saving undelete token") } render.JSON(w, r, googleCallbackResponse{ @@ -133,7 +133,7 @@ func (s *Server) googleCallback(w http.ResponseWriter, r *http.Request) error { tokenID := xid.New() token, err := s.Auth.CreateToken(u.ID, tokenID, u.IsAdmin, false, true) if err != nil { - return err + return errors.Wrap(err, "creating token") } // save token to database @@ -156,7 +156,7 @@ func (s *Server) googleCallback(w http.ResponseWriter, r *http.Request) error { return nil } else if err != db.ErrUserNotFound { // internal error - return err + return errors.Wrap(err, "getting user") } // no user found, so save a ticket + save their Google info in Redis @@ -164,7 +164,7 @@ func (s *Server) googleCallback(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetJSON(ctx, "google:"+ticket, partialGoogleUser{ID: googleID, Email: googleUsername}, "EX", "600") if err != nil { log.Errorf("setting Google user for ticket %q: %v", ticket, err) - return err + return errors.Wrap(err, "setting user for ticket") } render.JSON(w, r, googleCallbackResponse{ @@ -281,7 +281,7 @@ func (s *Server) googleSignup(w http.ResponseWriter, r *http.Request) error { valid, taken, err := s.DB.UsernameTaken(ctx, req.Username) if err != nil { - return err + return errors.Wrap(err, "checking if username is taken") } if !valid { return server.APIError{Code: server.ErrInvalidUsername} diff --git a/backend/routes/v1/auth/tumblr.go b/backend/routes/v1/auth/tumblr.go index d35781a..52dcdec 100644 --- a/backend/routes/v1/auth/tumblr.go +++ b/backend/routes/v1/auth/tumblr.go @@ -77,7 +77,7 @@ func (s *Server) tumblrCallback(w http.ResponseWriter, r *http.Request) error { // if the state can't be validated, return if valid, err := s.validateCSRFState(ctx, decoded.State); !valid { if err != nil { - return err + return errors.Wrap(err, "validating state") } return server.APIError{Code: server.ErrInvalidState} @@ -142,7 +142,7 @@ func (s *Server) tumblrCallback(w http.ResponseWriter, r *http.Request) error { err = s.saveUndeleteToken(ctx, u.ID, token) if err != nil { log.Errorf("saving undelete token: %v", err) - return err + return errors.Wrap(err, "saving undelete token") } render.JSON(w, r, tumblrCallbackResponse{ @@ -166,7 +166,7 @@ func (s *Server) tumblrCallback(w http.ResponseWriter, r *http.Request) error { tokenID := xid.New() token, err := s.Auth.CreateToken(u.ID, tokenID, u.IsAdmin, false, true) if err != nil { - return err + return errors.Wrap(err, "creating token") } // save token to database @@ -189,7 +189,7 @@ func (s *Server) tumblrCallback(w http.ResponseWriter, r *http.Request) error { return nil } else if err != db.ErrUserNotFound { // internal error - return err + return errors.Wrap(err, "getting user") } // no user found, so save a ticket + save their Tumblr info in Redis @@ -197,7 +197,7 @@ func (s *Server) tumblrCallback(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetJSON(ctx, "tumblr:"+ticket, tumblrUserInfo{ID: tumblrID, Name: tumblrName}, "EX", "600") if err != nil { log.Errorf("setting Tumblr user for ticket %q: %v", ticket, err) - return err + return errors.Wrap(err, "setting user for ticket") } render.JSON(w, r, tumblrCallbackResponse{ @@ -314,7 +314,7 @@ func (s *Server) tumblrSignup(w http.ResponseWriter, r *http.Request) error { valid, taken, err := s.DB.UsernameTaken(ctx, req.Username) if err != nil { - return err + return errors.Wrap(err, "checking if username is taken") } if !valid { return server.APIError{Code: server.ErrInvalidUsername} diff --git a/backend/routes/v1/member/create_member.go b/backend/routes/v1/member/create_member.go index e26ab74..c94915a 100644 --- a/backend/routes/v1/member/create_member.go +++ b/backend/routes/v1/member/create_member.go @@ -127,14 +127,14 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error return server.APIError{Code: server.ErrMemberNameInUse} } - return err + return errors.Wrap(err, "creating member") } // set names, pronouns, fields err = s.DB.SetMemberNamesPronouns(ctx, tx, m.ID, db.NotNull(cmr.Names), db.NotNull(cmr.Pronouns)) if err != nil { log.Errorf("setting names and pronouns for member %v: %v", m.ID, err) - return err + return errors.Wrap(err, "setting names/pronouns") } m.Names = cmr.Names m.Pronouns = cmr.Pronouns @@ -142,7 +142,7 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error err = s.DB.SetMemberFields(ctx, tx, m.ID, cmr.Fields) if err != nil { log.Errorf("setting fields for member %v: %v", m.ID, err) - return err + return errors.Wrap(err, "setting fields") } if cmr.Avatar != "" { @@ -161,13 +161,13 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error } log.Errorf("converting member avatar: %v", err) - return err + return errors.Wrap(err, "converting avatar") } hash, err := s.DB.WriteMemberAvatar(ctx, m.ID, webp, jpg) if err != nil { log.Errorf("uploading member avatar: %v", err) - return err + return errors.Wrap(err, "uploading avatar") } err = tx.QueryRow(ctx, "UPDATE members SET avatar = $1 WHERE id = $2", hash, m.ID).Scan(&m.Avatar) @@ -180,7 +180,7 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error err = s.DB.UpdateActiveTime(ctx, tx, claims.UserID) if err != nil { log.Errorf("updating last active time for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "updating last active time") } err = tx.Commit(ctx) diff --git a/backend/routes/v1/member/delete_member.go b/backend/routes/v1/member/delete_member.go index 4c2abde..5c8e68a 100644 --- a/backend/routes/v1/member/delete_member.go +++ b/backend/routes/v1/member/delete_member.go @@ -66,7 +66,7 @@ func (s *Server) deleteMember(w http.ResponseWriter, r *http.Request) (err error err = s.DB.UpdateActiveTime(ctx, s.DB, claims.UserID) if err != nil { log.Errorf("updating last active time for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "updating last active time") } render.NoContent(w, r) diff --git a/backend/routes/v1/member/get_member.go b/backend/routes/v1/member/get_member.go index 2a7d5e6..ffea5d5 100644 --- a/backend/routes/v1/member/get_member.go +++ b/backend/routes/v1/member/get_member.go @@ -105,7 +105,7 @@ func (s *Server) getMember(w http.ResponseWriter, r *http.Request) (err error) { u, err := s.DB.User(ctx, m.UserID) if err != nil { - return err + return errors.Wrap(err, "getting user") } if u.DeletedAt != nil { @@ -119,12 +119,12 @@ func (s *Server) getMember(w http.ResponseWriter, r *http.Request) (err error) { fields, err := s.DB.MemberFields(ctx, m.ID) if err != nil { - return err + return errors.Wrap(err, "getting member fields") } flags, err := s.DB.MemberFlags(ctx, m.ID) if err != nil { - return err + return errors.Wrap(err, "getting member flags") } render.JSON(w, r, dbMemberToMember(u, m, fields, flags, isOwnMember)) @@ -159,12 +159,12 @@ func (s *Server) getUserMember(w http.ResponseWriter, r *http.Request) error { fields, err := s.DB.MemberFields(ctx, m.ID) if err != nil { - return err + return errors.Wrap(err, "getting member fields") } flags, err := s.DB.MemberFlags(ctx, m.ID) if err != nil { - return err + return errors.Wrap(err, "getting member flags") } render.JSON(w, r, dbMemberToMember(u, m, fields, flags, isOwnMember)) @@ -189,12 +189,12 @@ func (s *Server) getMeMember(w http.ResponseWriter, r *http.Request) error { fields, err := s.DB.MemberFields(ctx, m.ID) if err != nil { - return err + return errors.Wrap(err, "getting member fields") } flags, err := s.DB.MemberFlags(ctx, m.ID) if err != nil { - return err + return errors.Wrap(err, "getting member flags") } render.JSON(w, r, dbMemberToMember(u, m, fields, flags, true)) diff --git a/backend/routes/v1/member/get_members.go b/backend/routes/v1/member/get_members.go index 6dba566..2442d39 100644 --- a/backend/routes/v1/member/get_members.go +++ b/backend/routes/v1/member/get_members.go @@ -6,6 +6,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/common" "codeberg.org/pronounscc/pronouns.cc/backend/db" "codeberg.org/pronounscc/pronouns.cc/backend/server" + "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" "github.com/rs/xid" @@ -74,7 +75,7 @@ func (s *Server) getUserMembers(w http.ResponseWriter, r *http.Request) error { ms, err := s.DB.UserMembers(ctx, u.ID, isSelf) if err != nil { - return err + return errors.Wrap(err, "getting members") } render.JSON(w, r, membersToMemberList(ms, isSelf)) @@ -87,7 +88,7 @@ func (s *Server) getMeMembers(w http.ResponseWriter, r *http.Request) error { ms, err := s.DB.UserMembers(ctx, claims.UserID, true) if err != nil { - return err + return errors.Wrap(err, "getting members") } render.JSON(w, r, membersToMemberList(ms, true)) diff --git a/backend/routes/v1/member/patch_member.go b/backend/routes/v1/member/patch_member.go index 8d56a87..f8cee31 100644 --- a/backend/routes/v1/member/patch_member.go +++ b/backend/routes/v1/member/patch_member.go @@ -220,13 +220,13 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { } log.Errorf("converting member avatar: %v", err) - return err + return errors.Wrap(err, "converting member avatar") } hash, err := s.DB.WriteMemberAvatar(ctx, m.ID, webp, jpg) if err != nil { log.Errorf("uploading member avatar: %v", err) - return err + return errors.Wrap(err, "writing member avatar") } avatarHash = &hash @@ -244,7 +244,7 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { tx, err := s.DB.Begin(ctx) if err != nil { log.Errorf("creating transaction: %v", err) - return err + return errors.Wrap(err, "creating transaction") } defer tx.Rollback(ctx) @@ -275,7 +275,7 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetMemberNamesPronouns(ctx, tx, m.ID, names, pronouns) if err != nil { log.Errorf("setting names for member %v: %v", m.ID, err) - return err + return errors.Wrap(err, "setting names/pronouns") } m.Names = names m.Pronouns = pronouns @@ -286,14 +286,14 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetMemberFields(ctx, tx, m.ID, *req.Fields) if err != nil { log.Errorf("setting fields for member %v: %v", m.ID, err) - return err + return errors.Wrap(err, "setting fields") } fields = *req.Fields } else { fields, err = s.DB.MemberFields(ctx, m.ID) if err != nil { log.Errorf("getting fields for member %v: %v", m.ID, err) - return err + return errors.Wrap(err, "getting fields") } } @@ -306,7 +306,7 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { } log.Errorf("updating flags for member %v: %v", m.ID, err) - return err + return errors.Wrap(err, "updating flags") } } @@ -314,20 +314,20 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { err = s.DB.UpdateActiveTime(ctx, tx, claims.UserID) if err != nil { log.Errorf("updating last active time for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "updating last active time") } err = tx.Commit(ctx) if err != nil { log.Errorf("committing transaction: %v", err) - return err + return errors.Wrap(err, "committing transaction") } // get flags to return (we need to return full flag objects, not the array of IDs in the request body) flags, err := s.DB.MemberFlags(ctx, m.ID) if err != nil { log.Errorf("getting user flags: %v", err) - return err + return errors.Wrap(err, "getting flags") } // echo the updated member back on success diff --git a/backend/routes/v1/user/export.go b/backend/routes/v1/user/export.go index 2dde011..189b3bb 100644 --- a/backend/routes/v1/user/export.go +++ b/backend/routes/v1/user/export.go @@ -7,6 +7,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/db" "codeberg.org/pronounscc/pronouns.cc/backend/log" "codeberg.org/pronounscc/pronouns.cc/backend/server" + "emperror.dev/errors" "github.com/go-chi/render" ) @@ -71,7 +72,7 @@ func (s *Server) getExport(w http.ResponseWriter, r *http.Request) error { } log.Errorf("getting export for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "getting export") } render.JSON(w, r, dataExportResponse{ diff --git a/backend/routes/v1/user/get_user.go b/backend/routes/v1/user/get_user.go index af43a4b..297c469 100644 --- a/backend/routes/v1/user/get_user.go +++ b/backend/routes/v1/user/get_user.go @@ -8,6 +8,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/db" "codeberg.org/pronounscc/pronouns.cc/backend/log" "codeberg.org/pronounscc/pronouns.cc/backend/server" + "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" "github.com/rs/xid" @@ -146,7 +147,7 @@ func (s *Server) getUser(w http.ResponseWriter, r *http.Request) (err error) { } } else if err != nil { log.Errorf("Error getting user by username: %v", err) - return err + return errors.Wrap(err, "getting user") } } @@ -162,13 +163,13 @@ func (s *Server) getUser(w http.ResponseWriter, r *http.Request) (err error) { fields, err := s.DB.UserFields(ctx, u.ID) if err != nil { log.Errorf("Error getting user fields: %v", err) - return err + return errors.Wrap(err, "getting fields") } flags, err := s.DB.UserFlags(ctx, u.ID) if err != nil { log.Errorf("getting user flags: %v", err) - return err + return errors.Wrap(err, "getting flags") } var members []db.Member @@ -176,7 +177,7 @@ func (s *Server) getUser(w http.ResponseWriter, r *http.Request) (err error) { members, err = s.DB.UserMembers(ctx, u.ID, isSelf) if err != nil { log.Errorf("Error getting user members: %v", err) - return err + return errors.Wrap(err, "getting user members") } } @@ -191,25 +192,25 @@ func (s *Server) getMeUser(w http.ResponseWriter, r *http.Request) error { u, err := s.DB.User(ctx, claims.UserID) if err != nil { log.Errorf("Error getting user: %v", err) - return err + return errors.Wrap(err, "getting users") } fields, err := s.DB.UserFields(ctx, u.ID) if err != nil { log.Errorf("Error getting user fields: %v", err) - return err + return errors.Wrap(err, "getting fields") } members, err := s.DB.UserMembers(ctx, u.ID, true) if err != nil { log.Errorf("Error getting user members: %v", err) - return err + return errors.Wrap(err, "getting members") } flags, err := s.DB.UserFlags(ctx, u.ID) if err != nil { log.Errorf("getting user flags: %v", err) - return err + return errors.Wrap(err, "getting flags") } render.JSON(w, r, GetMeResponse{ diff --git a/backend/routes/v1/user/patch_user.go b/backend/routes/v1/user/patch_user.go index fc465b1..ca489ce 100644 --- a/backend/routes/v1/user/patch_user.go +++ b/backend/routes/v1/user/patch_user.go @@ -195,13 +195,13 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { } log.Errorf("converting user avatar: %v", err) - return err + return errors.Wrap(err, "converting avatar") } hash, err := s.DB.WriteUserAvatar(ctx, claims.UserID, webp, jpg) if err != nil { log.Errorf("uploading user avatar: %v", err) - return err + return errors.Wrap(err, "uploading avatar") } avatarHash = &hash @@ -219,7 +219,7 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { tx, err := s.DB.Begin(ctx) if err != nil { log.Errorf("creating transaction: %v", err) - return err + return errors.Wrap(err, "creating transaction") } defer tx.Rollback(ctx) @@ -243,7 +243,7 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { u, err = s.DB.UpdateUser(ctx, tx, claims.UserID, req.DisplayName, req.Bio, req.MemberTitle, req.ListPrivate, req.Links, avatarHash, req.Timezone, req.CustomPreferences) if err != nil && errors.Cause(err) != db.ErrNothingToUpdate { log.Errorf("updating user: %v", err) - return err + return errors.Wrap(err, "updating user") } if req.Names != nil || req.Pronouns != nil { @@ -260,7 +260,7 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetUserNamesPronouns(ctx, tx, claims.UserID, names, pronouns) if err != nil { log.Errorf("setting names for member %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "setting names/pronouns") } u.Names = names u.Pronouns = pronouns @@ -271,14 +271,14 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { err = s.DB.SetUserFields(ctx, tx, claims.UserID, *req.Fields) if err != nil { log.Errorf("setting fields for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "setting fields") } fields = *req.Fields } else { fields, err = s.DB.UserFields(ctx, claims.UserID) if err != nil { log.Errorf("getting fields for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "getting fields") } } @@ -291,7 +291,7 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { } log.Errorf("updating flags for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "updating flags") } } @@ -299,13 +299,13 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { err = s.DB.UpdateActiveTime(ctx, tx, claims.UserID) if err != nil { log.Errorf("updating last active time for user %v: %v", claims.UserID, err) - return err + return errors.Wrap(err, "updating last active time") } err = tx.Commit(ctx) if err != nil { log.Errorf("committing transaction: %v", err) - return err + return errors.Wrap(err, "committing transaction") } // get fedi instance name if the user has a linked fedi account @@ -321,7 +321,7 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { flags, err := s.DB.UserFlags(ctx, u.ID) if err != nil { log.Errorf("getting user flags: %v", err) - return err + return errors.Wrap(err, "getting flags") } // echo the updated user back on success diff --git a/backend/routes/v2/user/get_settings.go b/backend/routes/v2/user/get_settings.go index d618831..096c0e0 100644 --- a/backend/routes/v2/user/get_settings.go +++ b/backend/routes/v2/user/get_settings.go @@ -5,6 +5,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/log" "codeberg.org/pronounscc/pronouns.cc/backend/server" + "emperror.dev/errors" "github.com/go-chi/render" ) @@ -13,7 +14,7 @@ func (s *Server) GetSettings(w http.ResponseWriter, r *http.Request) (err error) u, err := s.DB.User(r.Context(), claims.UserID) if err != nil { log.Errorf("getting user: %v", err) - return err + return errors.Wrap(err, "getting user") } render.JSON(w, r, u.Settings) diff --git a/backend/server/errors.go b/backend/server/errors.go index b4b8b07..ba33050 100644 --- a/backend/server/errors.go +++ b/backend/server/errors.go @@ -1,10 +1,13 @@ package server import ( + "context" "fmt" "net/http" "codeberg.org/pronounscc/pronouns.cc/backend/log" + "github.com/getsentry/sentry-go" + "github.com/go-chi/chi/v5" "github.com/go-chi/render" ) @@ -12,6 +15,17 @@ import ( // The inner HandlerFunc additionally returns an error. func WrapHandler(hn func(w http.ResponseWriter, r *http.Request) error) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + hub := sentry.CurrentHub().Clone() + + defer func(hub *sentry.Hub, r *http.Request) { + if err := recover(); err != nil { + hub.RecoverWithContext( + context.WithValue(r.Context(), sentry.RequestContextKey, r), + err, + ) + } + }(hub, r) + err := hn(w, r) if err != nil { // if the function returned an API error, just render that verbatim @@ -24,10 +38,16 @@ func WrapHandler(hn func(w http.ResponseWriter, r *http.Request) error) http.Han return } - // otherwise, we log the error and return an internal server error message - log.Errorf("error in http handler: %v", err) + rctx := chi.RouteContext(r.Context()) + hub.ConfigureScope(func(scope *sentry.Scope) { + scope.SetTag("method", rctx.RouteMethod) + scope.SetTag("path", rctx.RoutePattern()) + }) - apiErr := APIError{Code: ErrInternalServerError} + log.Errorf("error in handler for %v %v: %v", rctx.RouteMethod, rctx.RoutePattern(), err) + + eventID := hub.CaptureException(err) + apiErr := APIError{ID: eventID, Code: ErrInternalServerError} apiErr.prepare() render.Status(r, apiErr.Status) @@ -39,9 +59,10 @@ func WrapHandler(hn func(w http.ResponseWriter, r *http.Request) error) http.Han // APIError is an object returned by the API when an error occurs. // It implements the error interface and can be returned by handlers. type APIError struct { - Code int `json:"code"` - Message string `json:"message,omitempty"` - Details string `json:"details,omitempty"` + Code int `json:"code"` + ID *sentry.EventID `json:"id,omitempty"` + Message string `json:"message,omitempty"` + Details string `json:"details,omitempty"` RatelimitReset *int `json:"ratelimit_reset,omitempty"` diff --git a/docs/api/errors.md b/docs/api/errors.md index afb5245..dbb6cc0 100644 --- a/docs/api/errors.md +++ b/docs/api/errors.md @@ -2,12 +2,13 @@ If there is an error in your request, or the server encounters an error while processing it, an error object will be returned. -| Field | Type | Description | -| --------------- | ------- | --------------------------------------------------------------- | -| code | int | an [error code](./errors#error-codes) | -| message | ?string | a human-readable description of the error | -| details | ?string | more details about the error, most often for bad request errors | -| ratelimit_reset | ?int | the unix time when an expired rate limit will reset | +| Field | Type | Description | +| --------------- | ------- | ------------------------------------------------------------------- | +| code | int | an [error code](./errors#error-codes) | +| id | ?string | an opaque Sentry event ID, only returned for internal server errors | +| message | ?string | a human-readable description of the error | +| details | ?string | more details about the error, most often for bad request errors | +| ratelimit_reset | ?int | the unix time when an expired rate limit will reset | ### Error codes diff --git a/go.mod b/go.mod index 360bd54..9a3c02c 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/bwmarrin/discordgo v0.27.1 github.com/davidbyttow/govips/v2 v2.13.0 github.com/georgysavva/scany/v2 v2.0.0 + github.com/getsentry/sentry-go v0.24.1 github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/cors v1.2.1 github.com/go-chi/httprate v0.7.1 diff --git a/go.sum b/go.sum index 3476804..00cfa6f 100644 --- a/go.sum +++ b/go.sum @@ -131,6 +131,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/georgysavva/scany/v2 v2.0.0 h1:RGXqxDv4row7/FYoK8MRXAZXqoWF/NM+NP0q50k3DKU= github.com/georgysavva/scany/v2 v2.0.0/go.mod h1:sigOdh+0qb/+aOs3TVhehVT10p8qJL7K/Zhyz8vWo38= +github.com/getsentry/sentry-go v0.24.1 h1:W6/0GyTy8J6ge6lVCc94WB6Gx2ZuLrgopnn9w8Hiwuk= +github.com/getsentry/sentry-go v0.24.1/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= @@ -140,6 +142,7 @@ github.com/go-chi/httprate v0.7.1 h1:d5kXARdms2PREQfU4pHvq44S6hJ1hPu4OXLeBKmCKWs github.com/go-chi/httprate v0.7.1/go.mod h1:6GOYBSwnpra4CQfAKXu8sQZg+nZ0M1g9QnyFvxrAB8A= github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg= github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -397,6 +400,7 @@ github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -481,8 +485,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= github.com/tilinna/clock v1.1.0 h1:6IQQQCo6KoBxVudv6gwtY8o4eDfhHo8ojA5dP0MfhSs= From 9f266ee1a85cbe6a9f7dfbbd572ae52132dbddd5 Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 03:40:07 +0200 Subject: [PATCH 04/26] feat(backend): also add sentry tracing --- backend/main.go | 8 +++- backend/server/errors.go | 15 ++----- backend/server/sentry.go | 89 ++++++++++++++++++++++++++++++++++++++++ backend/server/server.go | 3 ++ 4 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 backend/server/sentry.go diff --git a/backend/main.go b/backend/main.go index 0cb68a8..3d9395b 100644 --- a/backend/main.go +++ b/backend/main.go @@ -27,8 +27,12 @@ func run(c *cli.Context) error { // initialize sentry if dsn := os.Getenv("SENTRY_DSN"); dsn != "" { sentry.Init(sentry.ClientOptions{ - Dsn: dsn, - Release: server.Tag, + Dsn: dsn, + Debug: true, + Release: server.Tag, + EnableTracing: true, + TracesSampleRate: 1.0, + ProfilesSampleRate: 1.0, }) } diff --git a/backend/server/errors.go b/backend/server/errors.go index ba33050..299ea63 100644 --- a/backend/server/errors.go +++ b/backend/server/errors.go @@ -1,7 +1,6 @@ package server import ( - "context" "fmt" "net/http" @@ -15,16 +14,10 @@ import ( // The inner HandlerFunc additionally returns an error. func WrapHandler(hn func(w http.ResponseWriter, r *http.Request) error) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - hub := sentry.CurrentHub().Clone() - - defer func(hub *sentry.Hub, r *http.Request) { - if err := recover(); err != nil { - hub.RecoverWithContext( - context.WithValue(r.Context(), sentry.RequestContextKey, r), - err, - ) - } - }(hub, r) + hub := sentry.GetHubFromContext(r.Context()) + if hub == nil { + hub = sentry.CurrentHub().Clone() + } err := hn(w, r) if err != nil { diff --git a/backend/server/sentry.go b/backend/server/sentry.go new file mode 100644 index 0000000..9641dec --- /dev/null +++ b/backend/server/sentry.go @@ -0,0 +1,89 @@ +package server + +import ( + "context" + "fmt" + "net/http" + + "github.com/getsentry/sentry-go" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" +) + +func (s *Server) sentry(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) + + ctx := r.Context() + hub := sentry.GetHubFromContext(ctx) + if hub == nil { + hub = sentry.CurrentHub().Clone() + ctx = sentry.SetHubOnContext(ctx, hub) + } + + options := []sentry.SpanOption{ + sentry.WithOpName("http.server"), + sentry.ContinueFromRequest(r), + sentry.WithTransactionSource(sentry.SourceURL), + } + // We don't mind getting an existing transaction back so we don't need to + // check if it is. + transaction := sentry.StartTransaction(ctx, + fmt.Sprintf("%s %s", r.Method, r.URL.Path), + options..., + ) + defer transaction.Finish() + r = r.WithContext(transaction.Context()) + hub.Scope().SetRequest(r) + defer recoverWithSentry(hub, r) + handler.ServeHTTP(ww, r) + + transaction.Status = httpStatusToSentryStatus(ww.Status()) + rctx := chi.RouteContext(r.Context()) + transaction.Name = rctx.RouteMethod + " " + rctx.RoutePattern() + }) +} + +func recoverWithSentry(hub *sentry.Hub, r *http.Request) { + if err := recover(); err != nil { + hub.RecoverWithContext( + context.WithValue(r.Context(), sentry.RequestContextKey, r), + err, + ) + } +} + +func httpStatusToSentryStatus(status int) sentry.SpanStatus { + // c.f. https://develop.sentry.dev/sdk/event-payloads/span/ + + if status >= 200 && status < 400 { + return sentry.SpanStatusOK + } + + switch status { + case 499: + return sentry.SpanStatusCanceled + case 500: + return sentry.SpanStatusInternalError + case 400: + return sentry.SpanStatusInvalidArgument + case 504: + return sentry.SpanStatusDeadlineExceeded + case 404: + return sentry.SpanStatusNotFound + case 409: + return sentry.SpanStatusAlreadyExists + case 403: + return sentry.SpanStatusPermissionDenied + case 429: + return sentry.SpanStatusResourceExhausted + case 501: + return sentry.SpanStatusUnimplemented + case 503: + return sentry.SpanStatusUnavailable + case 401: + return sentry.SpanStatusUnauthenticated + default: + return sentry.SpanStatusUnknown + } +} diff --git a/backend/server/server.go b/backend/server/server.go index 399ead0..bfc785d 100644 --- a/backend/server/server.go +++ b/backend/server/server.go @@ -50,6 +50,9 @@ func New() (*Server, error) { s.Router.Use(middleware.Logger) } s.Router.Use(middleware.Recoverer) + // add Sentry tracing handler + s.Router.Use(s.sentry) + // add CORS s.Router.Use(cors.Handler(cors.Options{ AllowedOrigins: []string{"https://*", "http://*"}, From fc1f4d03f1ad5b6b403da392f33ad85fd20959d9 Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 03:42:45 +0200 Subject: [PATCH 05/26] i forgot to change the debug setting --- backend/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/main.go b/backend/main.go index 3d9395b..f7f86b9 100644 --- a/backend/main.go +++ b/backend/main.go @@ -28,7 +28,7 @@ func run(c *cli.Context) error { if dsn := os.Getenv("SENTRY_DSN"); dsn != "" { sentry.Init(sentry.ClientOptions{ Dsn: dsn, - Debug: true, + Debug: os.Getenv("DEBUG") == "true", Release: server.Tag, EnableTracing: true, TracesSampleRate: 1.0, From 0e6f3a47f47c91f50acd2a1ddf15e88dcf34073d Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 15:15:43 +0200 Subject: [PATCH 06/26] fix(backend): filter out context.Canceled errors --- backend/server/errors.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/backend/server/errors.go b/backend/server/errors.go index 299ea63..063e773 100644 --- a/backend/server/errors.go +++ b/backend/server/errors.go @@ -1,10 +1,12 @@ package server import ( + "context" "fmt" "net/http" "codeberg.org/pronounscc/pronouns.cc/backend/log" + "emperror.dev/errors" "github.com/getsentry/sentry-go" "github.com/go-chi/chi/v5" "github.com/go-chi/render" @@ -37,9 +39,13 @@ func WrapHandler(hn func(w http.ResponseWriter, r *http.Request) error) http.Han scope.SetTag("path", rctx.RoutePattern()) }) - log.Errorf("error in handler for %v %v: %v", rctx.RouteMethod, rctx.RoutePattern(), err) - - eventID := hub.CaptureException(err) + var eventID *sentry.EventID = nil + if isExpectedError(err) { + log.Infof("expected error in handler for %v %v, ignoring", rctx.RouteMethod, rctx.RoutePattern()) + } else { + log.Errorf("error in handler for %v %v: %v", rctx.RouteMethod, rctx.RoutePattern(), err) + eventID = hub.CaptureException(err) + } apiErr := APIError{ID: eventID, Code: ErrInternalServerError} apiErr.prepare() @@ -49,6 +55,10 @@ func WrapHandler(hn func(w http.ResponseWriter, r *http.Request) error) http.Han } } +func isExpectedError(err error) bool { + return errors.Is(err, context.Canceled) +} + // APIError is an object returned by the API when an error occurs. // It implements the error interface and can be returned by handlers. type APIError struct { From a297ec681e3a96f6f5d96ef081455b38061ddabd Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 15:28:20 +0200 Subject: [PATCH 07/26] fix(backend): tweak traces/profiles sample rate --- backend/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/main.go b/backend/main.go index f7f86b9..a2029f7 100644 --- a/backend/main.go +++ b/backend/main.go @@ -31,8 +31,8 @@ func run(c *cli.Context) error { Debug: os.Getenv("DEBUG") == "true", Release: server.Tag, EnableTracing: true, - TracesSampleRate: 1.0, - ProfilesSampleRate: 1.0, + TracesSampleRate: 0.05, + ProfilesSampleRate: 0.05, }) } From cb8cfb9d2fa225ef00df96ec4b1310a6adf7e679 Mon Sep 17 00:00:00 2001 From: sam Date: Wed, 20 Sep 2023 17:03:12 +0200 Subject: [PATCH 08/26] fix(backend): add environment variable to disable tracing --- backend/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/main.go b/backend/main.go index a2029f7..d9efd98 100644 --- a/backend/main.go +++ b/backend/main.go @@ -30,7 +30,7 @@ func run(c *cli.Context) error { Dsn: dsn, Debug: os.Getenv("DEBUG") == "true", Release: server.Tag, - EnableTracing: true, + EnableTracing: os.Getenv("SENTRY_TRACING") == "true", TracesSampleRate: 0.05, ProfilesSampleRate: 0.05, }) From 65b171696a2c0fd838f209da6c6da084e08685f0 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 13 Oct 2023 23:24:39 +0200 Subject: [PATCH 09/26] add snowflake IDs to docs --- docs/api/endpoints/index.md | 13 +++++++------ docs/api/endpoints/members.md | 26 ++++++++++++++------------ docs/api/endpoints/users.md | 4 +++- docs/api/index.md | 18 +++++++++++------- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/docs/api/endpoints/index.md b/docs/api/endpoints/index.md index 0b14002..556f1c9 100644 --- a/docs/api/endpoints/index.md +++ b/docs/api/endpoints/index.md @@ -45,9 +45,10 @@ A user can set custom word preferences, which can have custom icons and tooltips ## Pride flag -| Field | Type | Description | -| ----------- | ------- | ------------------------------------- | -| id | string | the flag's unique ID | -| hash | string | the flag's [image hash](/api/#images) | -| name | string | the flag's name | -| description | string? | the flag's description or alt text | +| Field | Type | Description | +| ----------- | --------- | ------------------------------------- | +| id | string | the flag's unique ID | +| id_new | snowflake | the flag's unique snowflake ID | +| hash | string | the flag's [image hash](/api/#images) | +| name | string | the flag's name | +| description | string? | the flag's description or alt text | diff --git a/docs/api/endpoints/members.md b/docs/api/endpoints/members.md index 2a41a4c..fb1438d 100644 --- a/docs/api/endpoints/members.md +++ b/docs/api/endpoints/members.md @@ -5,6 +5,7 @@ | Field | Type | Description | | ------------ | ---------------------------------------------------- | --------------------------------------------------------------------------------- | | id | string | the member's unique ID | +| id_new | snowflake | the member's unique snowflake ID | | sid | string | the member's 6-letter short ID | | name | string | the member's name | | display_name | string? | the member's display name or nickname | @@ -23,6 +24,7 @@ | Field | Type | Description | | ------------------ | ---------------------------------------------------- | -------------------------------------- | | id | string | the user's unique ID | +| id_new | snowflake | the user's unique snowflake ID | | name | string | the user's username | | display_name | string? | the user's display name or nickname | | avatar | string? | the user's [avatar hash](/api/#images) | @@ -95,18 +97,18 @@ Returns the updated [member](./members#member-object) on success. #### Request body parameters -| Field | Type | Description | -| ------------------ | -------------------- | --------------------------------------------------------------------------------------------------- | -| name | string | the member's new name. Must be unique per user, and be between 1 and 100 characters. | -| display_name | string | the member's new display name. Must be between 1 and 100 characters | -| bio | string | the member's new bio. Must be between 1 and 1000 characters | -| links | string[] | the member's new profile links. Maximum 25 links, and links must be between 1 and 256 characters | -| names | field_entry[] | the member's new preferred names | -| pronouns | pronoun_entry[] | the member's new preferred pronouns | -| fields | field[] | the member's new profile fields | -| flags | string[] | the member's new flags. This must be an array of [pride flag](./#pride-flag) IDs. | -| avatar | string | the member's new avatar. This must be a PNG, JPEG, or WebP image, encoded in base64 data URI format | -| unlisted | bool | whether or not the member should be hidden from the member list | +| Field | Type | Description | +| ------------ | --------------- | ------------------------------------------------------------------------------------------------------ | +| name | string | the member's new name. Must be unique per user, and be between 1 and 100 characters. | +| display_name | string | the member's new display name. Must be between 1 and 100 characters | +| bio | string | the member's new bio. Must be between 1 and 1000 characters | +| links | string[] | the member's new profile links. Maximum 25 links, and links must be between 1 and 256 characters | +| names | field_entry[] | the member's new preferred names | +| pronouns | pronoun_entry[] | the member's new preferred pronouns | +| fields | field[] | the member's new profile fields | +| flags | string[] | the member's new flags. This must be an array of [pride flag](./#pride-flag) IDs, _not_ snowflake IDs. | +| avatar | string | the member's new avatar. This must be a PNG, JPEG, or WebP image, encoded in base64 data URI format | +| unlisted | bool | whether or not the member should be hidden from the member list | ### Delete member diff --git a/docs/api/endpoints/users.md b/docs/api/endpoints/users.md index 961a0b2..b671f3a 100644 --- a/docs/api/endpoints/users.md +++ b/docs/api/endpoints/users.md @@ -5,6 +5,7 @@ | Field | Type | Description | | ------------------ | ---------------------------------------------------- | --------------------------------------------------------------------------- | | id | string | the user's unique ID | +| id_new | snowflake | the user's unique snowflake ID | | sid | string | the user's 5 letter short ID | | name | string | the user's username | | display_name | string? | the user's display name or nickname | @@ -45,6 +46,7 @@ | Field | Type | Description | | ------------ | ----------------------------------- | ---------------------------------------- | | id | string | the member's unique ID | +| id_new | snowflake | the member's unique snowflake ID | | sid | string | the member's 6-letter short ID | | name | string | the member's name | | display_name | string? | the member's display name or nickname | @@ -89,7 +91,7 @@ Returns the updated [user](./users#user-object) object on success. | names | field_entry[] | the user's new preferred names | | pronouns | pronoun_entry[] | the user's new preferred pronouns | | fields | field[] | the user's new profile fields | -| flags | string[] | the user's new flags. This must be an array of [pride flag](./#pride-flag) IDs. | +| flags | string[] | the user's new flags. This must be an array of [pride flag](./#pride-flag) IDs, _not_ snowflake IDs. | | avatar | string | the user's new avatar. This must be a PNG, JPEG, or WebP image, encoded in base64 data URI format | | timezone | string | the user's new timezone. Must be in IANA timezone database format | | list_private | bool | whether or not the user's member list should be hidden | diff --git a/docs/api/index.md b/docs/api/index.md index 0db8486..51b9eec 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -62,19 +62,23 @@ The "type" column in tables is formatted as follows: ## IDs -::: info -pronouns.cc is [planning a transition](https://codeberg.org/pronounscc/pronouns.cc/issues/89) -to [Snowflake IDs](https://en.wikipedia.org/wiki/Snowflake_ID). -The information below pertains to the current ID format. -::: +### Snowflake IDs -The API uses [xid](https://github.com/rs/xid) for unique IDs. These are always serialized as strings. +For [multiple reasons](https://codeberg.org/pronounscc/pronouns.cc/issues/89), +pronouns.cc is transitioning to using snowflakes for unique IDs. These will become the default in the next API version, +but are already returned as `id_new` in the relevant objects (users, members, and flags). + +### xids + +[xid](https://github.com/rs/xid) is the previous unique ID format. These are always serialized as strings. Although xids have timestamp information embedded in them, this is non-trivial to extract. xids are unique across _all_ resources, they are never shared (for example, a user and a member cannot share the same ID). +### prns.cc IDs + Users and members also have an additional ID type, `sid`. These are randomly generated 5 or 6 letter strings, and are used for the prns.cc URL shortener. -They can be rerolled once per hour. +**These can change at any time**, as short IDs can be rerolled once per hour. ## Images From 97391c51d8f1c8b8a00e6190d1bafd245e762d8f Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 28 Oct 2023 00:58:20 +0200 Subject: [PATCH 10/26] fix: disallow * in member names, it breaks routing --- backend/db/member.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/db/member.go b/backend/db/member.go index f301c89..6eb444c 100644 --- a/backend/db/member.go +++ b/backend/db/member.go @@ -41,12 +41,14 @@ const ( ) // member names must match this regex -var memberNameRegex = regexp.MustCompile("^[^@\\?!#/\\\\[\\]\"\\{\\}'$%&()+<=>^|~`,]{1,100}$") +var memberNameRegex = regexp.MustCompile("^[^@\\?!#/\\\\[\\]\"\\{\\}'$%&()+<=>^|~`,\\*]{1,100}$") // List of member names that cannot be used because they would break routing or be inaccessible due to page conflicts. var invalidMemberNames = []string{ + // these break routing outright ".", "..", + // the user edit page lives at `/@{username}/edit`, so a member named "edit" would be inaccessible "edit", } From 34002e77d9c7275e22297d20a754142172a348d4 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 28 Oct 2023 01:04:20 +0200 Subject: [PATCH 11/26] chore: update go dependencies --- go.mod | 81 +++--- go.sum | 824 ++++++--------------------------------------------------- 2 files changed, 126 insertions(+), 779 deletions(-) diff --git a/go.mod b/go.mod index 9a3c02c..3967e70 100644 --- a/go.mod +++ b/go.mod @@ -9,77 +9,76 @@ require ( github.com/bwmarrin/discordgo v0.27.1 github.com/davidbyttow/govips/v2 v2.13.0 github.com/georgysavva/scany/v2 v2.0.0 - github.com/getsentry/sentry-go v0.24.1 - github.com/go-chi/chi/v5 v5.0.8 + github.com/getsentry/sentry-go v0.25.0 + github.com/go-chi/chi/v5 v5.0.10 github.com/go-chi/cors v1.2.1 - github.com/go-chi/httprate v0.7.1 - github.com/go-chi/render v1.0.2 + github.com/go-chi/httprate v0.7.4 + github.com/go-chi/render v1.0.3 github.com/gobwas/glob v0.2.3 github.com/golang-jwt/jwt/v4 v4.5.0 - github.com/google/uuid v1.3.0 - github.com/jackc/pgx/v5 v5.3.1 + github.com/google/uuid v1.4.0 + github.com/jackc/pgx/v5 v5.4.3 github.com/joho/godotenv v1.5.1 - github.com/mediocregopher/radix/v4 v4.1.2 - github.com/minio/minio-go/v7 v7.0.50 - github.com/prometheus/client_golang v1.15.0 - github.com/rs/xid v1.4.0 - github.com/rubenv/sql-migrate v1.4.0 - github.com/toshi0607/chi-prometheus v0.1.3 - github.com/urfave/cli/v2 v2.25.1 - go.uber.org/zap v1.24.0 - golang.org/x/oauth2 v0.7.0 - google.golang.org/api v0.118.0 + github.com/mediocregopher/radix/v4 v4.1.4 + github.com/minio/minio-go/v7 v7.0.63 + github.com/prometheus/client_golang v1.17.0 + github.com/rs/xid v1.5.0 + github.com/rubenv/sql-migrate v1.5.2 + github.com/toshi0607/chi-prometheus v0.1.4 + github.com/urfave/cli/v2 v2.25.7 + go.uber.org/zap v1.26.0 + golang.org/x/oauth2 v0.13.0 + google.golang.org/api v0.148.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - cloud.google.com/go/compute v1.19.0 // indirect + cloud.google.com/go/compute v1.23.2 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf // indirect github.com/ajg/form v1.5.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/s2a-go v0.1.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/puddle/v2 v2.2.0 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.16.3 // indirect - github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sirupsen/logrus v1.9.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/tilinna/clock v1.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.opencensus.io v0.24.0 // indirect - go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/image v0.6.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd // indirect - google.golang.org/grpc v1.54.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/image v0.13.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/go.sum b/go.sum index 00cfa6f..fb00aa8 100644 --- a/go.sum +++ b/go.sum @@ -1,919 +1,291 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.23.2 h1:nWEMDhgbBkBJjfpVySqU4jgWdc22PLR0o4vEexZHers= +cloud.google.com/go/compute v1.23.2/go.mod h1:JJ0atRC0J/oWYiiVBmsSsrRnh92DhZPG4hFDcR04Rns= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= emperror.dev/errors v0.8.1 h1:UavXZ5cSX/4u9iyvH6aDcuGkVjeexUGJ7Ij7G4VfQT0= emperror.dev/errors v0.8.1/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/a8m/expect v1.0.0/go.mod h1:4IwSCMumY49ScypDnjNbYEjgVeqy1/U2cEs3Lat96eA= github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf h1:+edM69bH/X6JpYPmJYBRLanAMe1V5yRXYU3hHUovGcE= github.com/aarondl/json v0.0.0-20221020222930-8b0db17ef1bf/go.mod h1:FZqLhJSj2tg0ZN48GB1zvj00+ZYcHPqgsC7yzcgCq6k= github.com/aarondl/opt v0.0.0-20230313190023-85d93d668fec h1:2NFk5fe52cHyRcUnXSs4CSEAqm+rL/hr3AdflBE3VPU= github.com/aarondl/opt v0.0.0-20230313190023-85d93d668fec/go.mod h1:l4/5NZtYd/SIohsFhaJQQe+sPOTG22furpZ5FvcYOzk= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidbyttow/govips/v2 v2.13.0 h1:5MK9ZcXZC5GzUR9Ca8fJwOYqMgll/H096ec0PJP59QM= github.com/davidbyttow/govips/v2 v2.13.0/go.mod h1:LPTrwWtNa5n4yl9UC52YBOEGdZcY5hDTP4Ms2QWasTw= -github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/georgysavva/scany/v2 v2.0.0 h1:RGXqxDv4row7/FYoK8MRXAZXqoWF/NM+NP0q50k3DKU= github.com/georgysavva/scany/v2 v2.0.0/go.mod h1:sigOdh+0qb/+aOs3TVhehVT10p8qJL7K/Zhyz8vWo38= -github.com/getsentry/sentry-go v0.24.1 h1:W6/0GyTy8J6ge6lVCc94WB6Gx2ZuLrgopnn9w8Hiwuk= -github.com/getsentry/sentry-go v0.24.1/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= -github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= +github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= +github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= -github.com/go-chi/httprate v0.7.1 h1:d5kXARdms2PREQfU4pHvq44S6hJ1hPu4OXLeBKmCKWs= -github.com/go-chi/httprate v0.7.1/go.mod h1:6GOYBSwnpra4CQfAKXu8sQZg+nZ0M1g9QnyFvxrAB8A= -github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg= -github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= +github.com/go-chi/httprate v0.7.4 h1:a2GIjv8he9LRf3712zxxnRdckQCm7I8y8yQhkJ84V6M= +github.com/go-chi/httprate v0.7.4/go.mod h1:6GOYBSwnpra4CQfAKXu8sQZg+nZ0M1g9QnyFvxrAB8A= +github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= +github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= -github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= -github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= -github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.0 h1:3Qm0liEiCErViKERO2Su5wp+9PfMRiuS6XB5FvpKnYQ= -github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= -github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= -github.com/jackc/puddle/v2 v2.2.0 h1:RdcDk92EJBuBS55nQMMYFXTxwstHug4jkhT5pq8VxPk= -github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= +github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= -github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= -github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= -github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= -github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mediocregopher/radix/v4 v4.1.2 h1:Pj7XnNK5WuzzFy63g98pnccainAePK+aZNQRvxSvj2I= -github.com/mediocregopher/radix/v4 v4.1.2/go.mod h1:ajchozX/6ELmydxWeWM6xCFHVpZ4+67LXHOTOVR0nCE= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mediocregopher/radix/v4 v4.1.4 h1:Uze6DEbEAvL+VHXUEu/EDBTkUk5CLct5h3nVSGpc6Ts= +github.com/mediocregopher/radix/v4 v4.1.4/go.mod h1:ajchozX/6ELmydxWeWM6xCFHVpZ4+67LXHOTOVR0nCE= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= -github.com/minio/minio-go/v7 v7.0.50 h1:4IL4V8m/kI90ZL6GupCARZVrBv8/XrcKcJhaJ3iz68k= -github.com/minio/minio-go/v7 v7.0.50/go.mod h1:IbbodHyjUAguneyucUaahv+VMNs/EOTV9du7A7/Z3HU= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= -github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/minio/minio-go/v7 v7.0.63 h1:GbZ2oCvaUdgT5640WJOpyDhhDxvknAJU2/T3yurwcbQ= +github.com/minio/minio-go/v7 v7.0.63/go.mod h1:Q6X7Qjb7WMhvG65qKf4gUgA5XaiSox74kR1uAEjxRS4= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nelsam/hel/v2 v2.3.2/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= -github.com/nelsam/hel/v2 v2.3.3/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/poy/onpar v0.0.0-20200406201722-06f95a1c68e8/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= -github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= -github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rubenv/sql-migrate v1.4.0 h1:y4ndB3hq5tmjvQ8jcuqhLgeEqoxIjEidN5RaCkKOAAE= -github.com/rubenv/sql-migrate v1.4.0/go.mod h1:lRxHt4vTgRJtpGbulUUYHA9dzfbBJXRt+PwUF/jeNYo= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= +github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= github.com/tilinna/clock v1.1.0 h1:6IQQQCo6KoBxVudv6gwtY8o4eDfhHo8ojA5dP0MfhSs= github.com/tilinna/clock v1.1.0/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/toshi0607/chi-prometheus v0.1.3 h1:KL0+MmVISNyKHsmvlU4fw00NDEUTB9K+OQt4scgD19U= -github.com/toshi0607/chi-prometheus v0.1.3/go.mod h1:2jErPypCR/0jMc4MTnEbjkWmJ3nkh5wmOVO9icayOaM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= -github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/toshi0607/chi-prometheus v0.1.4 h1:5KpqJrmdvMvbfU0JiL9ghOTbe8S9sgHDCCQvXgnyoJo= +github.com/toshi0607/chi-prometheus v0.1.4/go.mod h1:E++tBjqpDsvGWjLYdcFd5rvqJ7HG8wwBux+M6gyIL/Q= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= -golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4= -golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0= +golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg= +golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.118.0 h1:FNfHq9Z2GKULxu7cEhCaB0wWQHg43UpomrrN+24ZRdE= -google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= +google.golang.org/api v0.148.0 h1:HBq4TZlN4/1pNcu0geJZ/Q50vIwIXT532UIMYoo0vOs= +google.golang.org/api v0.148.0/go.mod h1:8/TBgwaKjfqTdacOJrOv2+2Q6fBDU1uHKK06oGSkxzU= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -922,42 +294,18 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From d559d1a03668acf277b1d5d263bf7366543f18b6 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 26 Dec 2023 01:34:50 +0100 Subject: [PATCH 12/26] chore: upgrade sveltekit to 2.0.0, upgrade svelte to 4.0.0 --- frontend/package.json | 27 +- frontend/src/app.d.ts | 6 +- frontend/src/lib/components/ActiveLink.svelte | 2 +- frontend/src/lib/components/ErrorAlert.svelte | 2 +- frontend/src/lib/components/IconButton.svelte | 2 +- .../lib/components/PartialMemberCard.svelte | 2 +- frontend/src/lib/components/StatusIcon.svelte | 2 +- frontend/src/lib/components/Toast.svelte | 2 +- .../lib/components/edit/EditableField.svelte | 2 +- .../lib/components/edit/EditableName.svelte | 2 +- .../components/edit/EditablePronouns.svelte | 2 +- .../src/lib/components/edit/FieldEntry.svelte | 2 +- .../src/lib/components/edit/FlagButton.svelte | 2 +- .../lib/components/edit/MarkdownHelp.svelte | 2 +- frontend/src/routes/+layout.svelte | 2 +- frontend/src/routes/+page.svelte | 2 +- .../src/routes/@[username]/+page.server.ts | 2 +- frontend/src/routes/@[username]/+page.svelte | 2 +- .../src/routes/@[username]/ProfileFlag.svelte | 2 +- .../src/routes/@[username]/ProfileLink.svelte | 2 +- .../routes/@[username]/ReportButton.svelte | 2 +- .../@[username]/[memberName]/+page.server.ts | 4 +- .../@[username]/[memberName]/+page.svelte | 2 +- .../[memberName]/edit/+layout.svelte | 2 +- .../@[username]/[memberName]/edit/+layout.ts | 4 +- .../[memberName]/edit/+page.svelte | 2 +- .../[memberName]/edit/bio/+page.svelte | 2 +- .../[memberName]/edit/fields/+page.svelte | 2 +- .../[memberName]/edit/flags/+page.svelte | 2 +- .../[memberName]/edit/other/+page.svelte | 2 +- .../[memberName]/edit/pronouns/+page.svelte | 2 +- .../routes/@[username]/badges/Admin.svelte | 2 +- .../routes/@[username]/edit/+layout.svelte | 2 +- .../src/routes/@[username]/edit/+layout.ts | 4 +- .../src/routes/@[username]/edit/+page.svelte | 2 +- .../routes/@[username]/edit/bio/+page.svelte | 2 +- .../@[username]/edit/fields/+page.svelte | 2 +- .../@[username]/edit/flags/+page.svelte | 2 +- .../@[username]/edit/other/+page.svelte | 2 +- .../edit/other/CustomPreference.svelte | 2 +- .../@[username]/edit/other/IconPicker.svelte | 2 +- .../@[username]/edit/pronouns/+page.svelte | 2 +- .../src/routes/[username]/+page.server.ts | 4 +- frontend/src/routes/auth/login/+page.svelte | 2 +- .../src/routes/auth/login/CallbackPage.svelte | 2 +- frontend/src/routes/edit/member/[id]/+page.ts | 4 +- frontend/src/routes/edit/profile/+page.ts | 4 +- frontend/src/routes/nav/Navigation.svelte | 2 +- .../routes/pronouns/[...pronouns]/+page.ts | 4 +- frontend/src/routes/reports/+page.svelte | 2 +- frontend/src/routes/reports/ReportCard.svelte | 2 +- frontend/src/routes/settings/+layout.svelte | 2 +- frontend/src/routes/settings/+layout.ts | 2 +- frontend/src/routes/settings/+page.svelte | 2 +- .../src/routes/settings/auth/+page.svelte | 2 +- .../src/routes/settings/export/+page.svelte | 2 +- frontend/src/routes/settings/export/+page.ts | 2 +- .../src/routes/settings/flags/+page.svelte | 2 +- .../src/routes/settings/flags/Flag.svelte | 2 +- .../src/routes/settings/invites/+page.svelte | 2 +- .../src/routes/settings/members/+page.svelte | 2 +- .../src/routes/settings/tokens/+page.svelte | 2 +- .../src/routes/settings/warnings/+page.svelte | 2 +- frontend/svelte.config.js | 2 +- pnpm-lock.yaml | 1645 ++++++++++++++--- 65 files changed, 1441 insertions(+), 375 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index a460457..1628226 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,11 +12,13 @@ "format": "prettier --plugin-search-dir . --write ." }, "devDependencies": { - "@sveltejs/adapter-auto": "^2.0.0", - "@sveltejs/adapter-node": "^1.2.3", - "@sveltejs/kit": "^1.15.0", - "@types/luxon": "^3.2.2", - "@types/markdown-it": "^12.2.3", + "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/adapter-node": "^2.0.0", + "@sveltejs/kit": "^2.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@sveltestrap/sveltestrap": "^6.0.5", + "@types/luxon": "^3.3.7", + "@types/markdown-it": "^13.0.7", "@types/node": "^18.15.11", "@types/sanitize-html": "^2.9.0", "@typescript-eslint/eslint-plugin": "^5.57.1", @@ -25,14 +27,13 @@ "eslint-config-prettier": "^8.8.0", "eslint-plugin-svelte3": "^4.0.0", "prettier": "^2.8.7", - "prettier-plugin-svelte": "^2.10.0", - "svelte": "^3.58.0", - "svelte-check": "^3.1.4", + "prettier-plugin-svelte": "^2.10.1", + "svelte": "^4.0.0", + "svelte-check": "^3.4.3", "svelte-hcaptcha": "^0.1.1", - "sveltestrap": "^5.10.0", "tslib": "^2.5.0", - "typescript": "^4.9.5", - "vite": "^4.2.1", + "typescript": "^5.0.0", + "vite": "^5.0.0", "vite-plugin-markdown": "^2.1.0" }, "type": "module", @@ -41,8 +42,8 @@ "@popperjs/core": "^2.11.7", "@sentry/node": "^7.46.0", "base64-arraybuffer": "^1.0.2", - "bootstrap": "5.3.0-alpha1", - "bootstrap-icons": "^1.10.4", + "bootstrap": "^5.3.2", + "bootstrap-icons": "^1.11.2", "jose": "^4.13.1", "luxon": "^3.3.0", "markdown-it": "^13.0.1", diff --git a/frontend/src/app.d.ts b/frontend/src/app.d.ts index d4759fd..ba59572 100644 --- a/frontend/src/app.d.ts +++ b/frontend/src/app.d.ts @@ -1,15 +1,15 @@ // See https://kit.svelte.dev/docs/types#app -import type { ErrorCode } from "$lib/api/entities"; +import type { APIError, ErrorCode } from "$lib/api/entities"; // for information about these interfaces declare global { namespace App { - interface Error { + type Error = { code: ErrorCode; message?: string | undefined; details?: string | undefined; - } + } | APIError // interface Locals {} // interface PageData {} // interface Platform {} diff --git a/frontend/src/lib/components/ActiveLink.svelte b/frontend/src/lib/components/ActiveLink.svelte index d9bc887..969cfbd 100644 --- a/frontend/src/lib/components/ActiveLink.svelte +++ b/frontend/src/lib/components/ActiveLink.svelte @@ -1,5 +1,5 @@ diff --git a/frontend/src/lib/components/IconButton.svelte b/frontend/src/lib/components/IconButton.svelte index c131a4d..240339a 100644 --- a/frontend/src/lib/components/IconButton.svelte +++ b/frontend/src/lib/components/IconButton.svelte @@ -1,5 +1,5 @@ diff --git a/frontend/src/routes/@[username]/+page.server.ts b/frontend/src/routes/@[username]/+page.server.ts index 447c5e3..1e7b8af 100644 --- a/frontend/src/routes/@[username]/+page.server.ts +++ b/frontend/src/routes/@[username]/+page.server.ts @@ -11,7 +11,7 @@ export const load = async ({ params }) => { return resp; } catch (e) { if ((e as APIError).code === ErrorCode.UserNotFound) { - throw error(404, e as APIError); + error(404, e as APIError); } throw e; diff --git a/frontend/src/routes/@[username]/+page.svelte b/frontend/src/routes/@[username]/+page.svelte index 56542fc..642e715 100644 --- a/frontend/src/routes/@[username]/+page.svelte +++ b/frontend/src/routes/@[username]/+page.svelte @@ -14,7 +14,7 @@ ModalBody, ModalFooter, Tooltip, - } from "sveltestrap"; + } from "@sveltestrap/sveltestrap"; import { DateTime, Duration, FixedOffsetZone, Zone } from "luxon"; import FieldCard from "$lib/components/FieldCard.svelte"; import PronounLink from "$lib/components/PronounLink.svelte"; diff --git a/frontend/src/routes/@[username]/ProfileFlag.svelte b/frontend/src/routes/@[username]/ProfileFlag.svelte index 3ef4c63..6862770 100644 --- a/frontend/src/routes/@[username]/ProfileFlag.svelte +++ b/frontend/src/routes/@[username]/ProfileFlag.svelte @@ -1,6 +1,6 @@ diff --git a/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte b/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte index a77b13a..08a456d 100644 --- a/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte +++ b/frontend/src/routes/@[username]/[memberName]/edit/fields/+page.svelte @@ -1,7 +1,7 @@ diff --git a/frontend/src/routes/@[username]/edit/+layout.svelte b/frontend/src/routes/@[username]/edit/+layout.svelte index 6bcb23b..de6dbf3 100644 --- a/frontend/src/routes/@[username]/edit/+layout.svelte +++ b/frontend/src/routes/@[username]/edit/+layout.svelte @@ -2,7 +2,7 @@ import { setContext } from "svelte"; import { writable } from "svelte/store"; import type { LayoutData } from "./$types"; - import { Button, ButtonGroup, Icon, Nav, NavItem } from "sveltestrap"; + import { Button, ButtonGroup, Icon, Nav, NavItem } from "@sveltestrap/sveltestrap"; import type { MeUser, APIError } from "$lib/api/entities"; import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import { addToast, delToast } from "$lib/toast"; diff --git a/frontend/src/routes/@[username]/edit/+layout.ts b/frontend/src/routes/@[username]/edit/+layout.ts index 2fd9c4c..de77441 100644 --- a/frontend/src/routes/@[username]/edit/+layout.ts +++ b/frontend/src/routes/@[username]/edit/+layout.ts @@ -13,7 +13,7 @@ export const load = async ({ params }) => { const flags = await apiFetchClient("/users/@me/flags"); if (params.username !== user.name) { - throw redirect(303, `/@${user.name}/edit`); + redirect(303, `/@${user.name}/edit`); } return { @@ -22,7 +22,7 @@ export const load = async ({ params }) => { flags, }; } catch (e) { - if ("code" in e) throw error(500, e as APIError); + if ("code" in e) error(500, e as APIError); throw e; } }; diff --git a/frontend/src/routes/@[username]/edit/+page.svelte b/frontend/src/routes/@[username]/edit/+page.svelte index e727633..d5c2aeb 100644 --- a/frontend/src/routes/@[username]/edit/+page.svelte +++ b/frontend/src/routes/@[username]/edit/+page.svelte @@ -3,7 +3,7 @@ import type { Writable } from "svelte/store"; import prettyBytes from "pretty-bytes"; import { encode } from "base64-arraybuffer"; - import { FormGroup, Icon, Input } from "sveltestrap"; + import { FormGroup, Icon, Input } from "@sveltestrap/sveltestrap"; import { userAvatars, type MeUser } from "$lib/api/entities"; import FallbackImage from "$lib/components/FallbackImage.svelte"; import EditableName from "$lib/components/edit/EditableName.svelte"; diff --git a/frontend/src/routes/@[username]/edit/bio/+page.svelte b/frontend/src/routes/@[username]/edit/bio/+page.svelte index 2cbbf38..572fa35 100644 --- a/frontend/src/routes/@[username]/edit/bio/+page.svelte +++ b/frontend/src/routes/@[username]/edit/bio/+page.svelte @@ -4,7 +4,7 @@ import { MAX_DESCRIPTION_LENGTH, type MeUser } from "$lib/api/entities"; import { charCount, renderMarkdown } from "$lib/utils"; import MarkdownHelp from "$lib/components/edit/MarkdownHelp.svelte"; - import { Card, CardBody, CardHeader } from "sveltestrap"; + import { Card, CardBody, CardHeader } from "@sveltestrap/sveltestrap"; const user = getContext>("user"); diff --git a/frontend/src/routes/@[username]/edit/fields/+page.svelte b/frontend/src/routes/@[username]/edit/fields/+page.svelte index f09d89d..9ad8d0a 100644 --- a/frontend/src/routes/@[username]/edit/fields/+page.svelte +++ b/frontend/src/routes/@[username]/edit/fields/+page.svelte @@ -1,7 +1,7 @@ diff --git a/frontend/src/routes/settings/+layout.svelte b/frontend/src/routes/settings/+layout.svelte index fc225ee..1120447 100644 --- a/frontend/src/routes/settings/+layout.svelte +++ b/frontend/src/routes/settings/+layout.svelte @@ -9,7 +9,7 @@ Modal, ModalBody, ModalFooter, - } from "sveltestrap"; + } from "@sveltestrap/sveltestrap"; import { userStore } from "$lib/store"; import { goto } from "$app/navigation"; import { addToast } from "$lib/toast"; diff --git a/frontend/src/routes/settings/+layout.ts b/frontend/src/routes/settings/+layout.ts index 415bf6c..acf0e5e 100644 --- a/frontend/src/routes/settings/+layout.ts +++ b/frontend/src/routes/settings/+layout.ts @@ -40,7 +40,7 @@ export const load = (async ({ parent }) => { }; } catch (e) { if ((e as APIError).code !== ErrorCode.InternalServerError) { - throw redirect(303, "/auth/login"); + redirect(303, "/auth/login"); } throw e; } diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte index 92451e1..58f5650 100644 --- a/frontend/src/routes/settings/+page.svelte +++ b/frontend/src/routes/settings/+page.svelte @@ -23,7 +23,7 @@ ModalFooter, ModalHeader, Table, - } from "sveltestrap"; + } from "@sveltestrap/sveltestrap"; import type { PageData } from "./$types"; import { onMount } from "svelte"; import { DateTime } from "luxon"; diff --git a/frontend/src/routes/settings/auth/+page.svelte b/frontend/src/routes/settings/auth/+page.svelte index 2d03bb5..c55d9bb 100644 --- a/frontend/src/routes/settings/auth/+page.svelte +++ b/frontend/src/routes/settings/auth/+page.svelte @@ -13,7 +13,7 @@ Modal, ModalBody, ModalFooter, - } from "sveltestrap"; + } from "@sveltestrap/sveltestrap"; import type { PageData } from "./$types"; export let data: PageData; diff --git a/frontend/src/routes/settings/export/+page.svelte b/frontend/src/routes/settings/export/+page.svelte index 31f87e7..97733f6 100644 --- a/frontend/src/routes/settings/export/+page.svelte +++ b/frontend/src/routes/settings/export/+page.svelte @@ -1,7 +1,7 @@ + +
+
    + {#each usedDefaultPreferences as pref (pref.id)} +
  • + + {pref.preference.tooltip} +
  • + {/each} +
+ {#if usedCustomPreferences} +
    + {#each usedCustomPreferences as pref (pref.id)} +
  • + + {pref.preference.tooltip} +
  • + {/each} +
+ {/if} +
diff --git a/frontend/src/routes/@[username]/[memberName]/+page.svelte b/frontend/src/routes/@[username]/[memberName]/+page.svelte index 206cbfd..1ecc942 100644 --- a/frontend/src/routes/@[username]/[memberName]/+page.svelte +++ b/frontend/src/routes/@[username]/[memberName]/+page.svelte @@ -22,6 +22,7 @@ import { addToast } from "$lib/toast"; import ProfileFlag from "../ProfileFlag.svelte"; import IconButton from "$lib/components/IconButton.svelte"; + import PreferencesCheatsheet from "../PreferencesCheatsheet.svelte"; export let data: PageData; @@ -154,6 +155,12 @@ {/each} +
From 44b667ff4322051019a90cd4b3d9a484734b87dc Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 30 Dec 2023 02:33:58 +0100 Subject: [PATCH 14/26] add frontend CI --- .woodpecker.yml | 16 ++++++++++++++++ Makefile | 2 +- frontend/svelte.config.js | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 .woodpecker.yml diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..5af005c --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,16 @@ +steps: + frontend: + image: node + directory: frontend + environment: # SvelteKit expects these in the environment during build time. + - PRIVATE_SENTRY_DSN=non_existent_dsn + - PUBLIC_BASE_URL=http://pronouns.localhost + - PUBLIC_MEDIA_URL=http://pronouns.localhost/media + - PUBLIC_SHORT_BASE=http://prns.localhost + - PUBLIC_HCAPTCHA_SITEKEY=non_existent_sitekey + commands: + - corepack enable + - pnpm install + - pnpm check + - pnpm lint + - pnpm build diff --git a/Makefile b/Makefile index 1b15eff..8a7c089 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: generate backend frontend .PHONY: backend backend: - go build -v -o pronouns -ldflags="-buildid= -X codeberg.org/pronounscc/pronouns.cc/backend/server.Revision=`git rev-parse --short HEAD` -X codeberg.org/pronounscc/pronouns.cc/backend/server.Tag=`git describe --tags --long`" . + go build -v -o pronouns -ldflags="-buildid= -X codeberg.org/pronounscc/pronouns.cc/backend/server.Revision=`git rev-parse --short HEAD` -X codeberg.org/pronounscc/pronouns.cc/backend/server.Tag=`git describe --tags --long --always`" . .PHONY: generate generate: diff --git a/frontend/svelte.config.js b/frontend/svelte.config.js index c9182bf..46d780b 100644 --- a/frontend/svelte.config.js +++ b/frontend/svelte.config.js @@ -11,7 +11,7 @@ const config = { kit: { adapter: adapter(), version: { - name: child_process.execSync("git describe --tags --long").toString().trim(), + name: child_process.execSync("git describe --tags --long --always").toString().trim(), }, }, }; From e37b5be376c6446dca5a8a951cf55ed346d93572 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 30 Dec 2023 03:51:01 +0100 Subject: [PATCH 15/26] add backend CI --- .golangci.yml | 2 ++ .woodpecker/.backend.yml | 9 +++++++++ .woodpecker.yml => .woodpecker/.frontend.yml | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .golangci.yml create mode 100644 .woodpecker/.backend.yml rename .woodpecker.yml => .woodpecker/.frontend.yml (97%) diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..29471e1 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,2 @@ +run: + issues-exit-code: 0 # lol diff --git a/.woodpecker/.backend.yml b/.woodpecker/.backend.yml new file mode 100644 index 0000000..71abad3 --- /dev/null +++ b/.woodpecker/.backend.yml @@ -0,0 +1,9 @@ +steps: + check: + image: golang:alpine + commands: + - apk update && apk add curl vips-dev build-base + - make backend + # Install golangci-lint + - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2 + - golangci-lint run diff --git a/.woodpecker.yml b/.woodpecker/.frontend.yml similarity index 97% rename from .woodpecker.yml rename to .woodpecker/.frontend.yml index 5af005c..a10ef11 100644 --- a/.woodpecker.yml +++ b/.woodpecker/.frontend.yml @@ -1,5 +1,5 @@ steps: - frontend: + check: image: node directory: frontend environment: # SvelteKit expects these in the environment during build time. From c13c4e90b669b773360c011ec55d88433b220233 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 30 Dec 2023 04:27:08 +0100 Subject: [PATCH 16/26] don't ignore errors in tx.Rollback() --- .golangci.yml | 2 -- backend/db/export.go | 2 +- backend/db/invites.go | 8 +++++++- backend/db/member.go | 8 +++++++- backend/main.go | 3 ++- backend/routes/v1/auth/discord.go | 8 +++++++- backend/routes/v1/auth/fedi_mastodon.go | 8 +++++++- backend/routes/v1/auth/fedi_misskey.go | 8 +++++++- backend/routes/v1/auth/google.go | 8 +++++++- backend/routes/v1/auth/tokens.go | 9 ++++++++- backend/routes/v1/auth/tumblr.go | 8 +++++++- backend/routes/v1/member/create_member.go | 8 +++++++- backend/routes/v1/member/patch_member.go | 8 +++++++- backend/routes/v1/mod/resolve_report.go | 8 +++++++- backend/routes/v1/user/delete_user.go | 9 ++++++++- backend/routes/v1/user/flags.go | 15 ++++++++++++-- backend/routes/v1/user/patch_user.go | 8 +++++++- backend/server/server.go | 24 +++++++++++------------ scripts/cleandb/main.go | 10 +++++++++- scripts/seeddb/main.go | 9 ++++++++- scripts/snowflakes/main.go | 8 +++++++- 21 files changed, 145 insertions(+), 34 deletions(-) delete mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 29471e1..0000000 --- a/.golangci.yml +++ /dev/null @@ -1,2 +0,0 @@ -run: - issues-exit-code: 0 # lol diff --git a/backend/db/export.go b/backend/db/export.go index 6141aac..5095445 100644 --- a/backend/db/export.go +++ b/backend/db/export.go @@ -79,7 +79,7 @@ func (db *DB) CreateExport(ctx context.Context, userID xid.ID, filename string, return de, errors.Wrap(err, "building query") } - pgxscan.Get(ctx, db, &de, sql, args...) + err = pgxscan.Get(ctx, db, &de, sql, args...) if err != nil { return de, errors.Wrap(err, "executing sql") } diff --git a/backend/db/invites.go b/backend/db/invites.go index d56662e..d13ab0e 100644 --- a/backend/db/invites.go +++ b/backend/db/invites.go @@ -6,6 +6,7 @@ import ( "encoding/base64" "time" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "emperror.dev/errors" "github.com/georgysavva/scany/v2/pgxscan" "github.com/jackc/pgx/v5" @@ -43,7 +44,12 @@ func (db *DB) CreateInvite(ctx context.Context, userID xid.ID) (i Invite, err er if err != nil { return i, errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() var maxInvites, inviteCount int err = tx.QueryRow(ctx, "SELECT max_invites FROM users WHERE id = $1", userID).Scan(&maxInvites) diff --git a/backend/db/member.go b/backend/db/member.go index 6eb444c..a50c431 100644 --- a/backend/db/member.go +++ b/backend/db/member.go @@ -7,6 +7,7 @@ import ( "time" "codeberg.org/pronounscc/pronouns.cc/backend/common" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "emperror.dev/errors" "github.com/Masterminds/squirrel" "github.com/georgysavva/scany/v2/pgxscan" @@ -287,7 +288,12 @@ func (db *DB) RerollMemberSID(ctx context.Context, userID, memberID xid.ID) (new if err != nil { return "", errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() sql, args, err := sq.Update("members"). Set("sid", squirrel.Expr("find_free_member_sid()")). diff --git a/backend/main.go b/backend/main.go index d9efd98..c17679e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -26,7 +26,8 @@ var Command = &cli.Command{ func run(c *cli.Context) error { // initialize sentry if dsn := os.Getenv("SENTRY_DSN"); dsn != "" { - sentry.Init(sentry.ClientOptions{ + // We don't need to check the error here--it's fine if no DSN is set. + _ = sentry.Init(sentry.ClientOptions{ Dsn: dsn, Debug: os.Getenv("DEBUG") == "true", Release: server.Tag, diff --git a/backend/routes/v1/auth/discord.go b/backend/routes/v1/auth/discord.go index 2084b52..b8a72f3 100644 --- a/backend/routes/v1/auth/discord.go +++ b/backend/routes/v1/auth/discord.go @@ -11,6 +11,7 @@ import ( "emperror.dev/errors" "github.com/bwmarrin/discordgo" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" "golang.org/x/oauth2" @@ -291,7 +292,12 @@ func (s *Server) discordSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() du := new(discordgo.User) err = s.DB.GetJSON(ctx, "discord:"+req.Ticket, &du) diff --git a/backend/routes/v1/auth/fedi_mastodon.go b/backend/routes/v1/auth/fedi_mastodon.go index bb07958..f69a2b3 100644 --- a/backend/routes/v1/auth/fedi_mastodon.go +++ b/backend/routes/v1/auth/fedi_mastodon.go @@ -11,6 +11,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" ) @@ -319,7 +320,12 @@ func (s *Server) mastodonSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() mu := new(partialMastodonAccount) err = s.DB.GetJSON(ctx, "mastodon:"+req.Ticket, &mu) diff --git a/backend/routes/v1/auth/fedi_misskey.go b/backend/routes/v1/auth/fedi_misskey.go index ebf6e22..d162f77 100644 --- a/backend/routes/v1/auth/fedi_misskey.go +++ b/backend/routes/v1/auth/fedi_misskey.go @@ -12,6 +12,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" ) @@ -247,7 +248,12 @@ func (s *Server) misskeySignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() mu := new(partialMisskeyAccount) err = s.DB.GetJSON(ctx, "misskey:"+req.Ticket, &mu) diff --git a/backend/routes/v1/auth/google.go b/backend/routes/v1/auth/google.go index 026a6d1..7904889 100644 --- a/backend/routes/v1/auth/google.go +++ b/backend/routes/v1/auth/google.go @@ -10,6 +10,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" "golang.org/x/oauth2" @@ -294,7 +295,12 @@ func (s *Server) googleSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() gu := new(partialGoogleUser) err = s.DB.GetJSON(ctx, "google:"+req.Ticket, &gu) diff --git a/backend/routes/v1/auth/tokens.go b/backend/routes/v1/auth/tokens.go index e48662d..0f8b8b8 100644 --- a/backend/routes/v1/auth/tokens.go +++ b/backend/routes/v1/auth/tokens.go @@ -5,9 +5,11 @@ import ( "time" "codeberg.org/pronounscc/pronouns.cc/backend/db" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -63,7 +65,12 @@ func (s *Server) deleteToken(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() err = s.DB.InvalidateAllTokens(ctx, tx, claims.UserID) if err != nil { diff --git a/backend/routes/v1/auth/tumblr.go b/backend/routes/v1/auth/tumblr.go index 52dcdec..3463c9d 100644 --- a/backend/routes/v1/auth/tumblr.go +++ b/backend/routes/v1/auth/tumblr.go @@ -12,6 +12,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/mediocregopher/radix/v4" "github.com/rs/xid" "golang.org/x/oauth2" @@ -327,7 +328,12 @@ func (s *Server) tumblrSignup(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() tui := new(tumblrUserInfo) err = s.DB.GetJSON(ctx, "tumblr:"+req.Ticket, &tui) diff --git a/backend/routes/v1/member/create_member.go b/backend/routes/v1/member/create_member.go index c94915a..288aafc 100644 --- a/backend/routes/v1/member/create_member.go +++ b/backend/routes/v1/member/create_member.go @@ -11,6 +11,7 @@ import ( "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" ) type CreateMemberRequest struct { @@ -119,7 +120,12 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error if err != nil { return errors.Wrap(err, "starting transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() m, err := s.DB.CreateMember(ctx, tx, claims.UserID, cmr.Name, cmr.DisplayName, cmr.Bio, cmr.Links) if err != nil { diff --git a/backend/routes/v1/member/patch_member.go b/backend/routes/v1/member/patch_member.go index f8cee31..c26cf37 100644 --- a/backend/routes/v1/member/patch_member.go +++ b/backend/routes/v1/member/patch_member.go @@ -13,6 +13,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -246,7 +247,12 @@ func (s *Server) patchMember(w http.ResponseWriter, r *http.Request) error { log.Errorf("creating transaction: %v", err) return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() m, err = s.DB.UpdateMember(ctx, tx, m.ID, req.Name, req.DisplayName, req.Bio, req.Unlisted, req.Links, avatarHash) if err != nil { diff --git a/backend/routes/v1/mod/resolve_report.go b/backend/routes/v1/mod/resolve_report.go index 77e4b8d..c36cb86 100644 --- a/backend/routes/v1/mod/resolve_report.go +++ b/backend/routes/v1/mod/resolve_report.go @@ -10,6 +10,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" ) type resolveReportRequest struct { @@ -43,7 +44,12 @@ func (s *Server) resolveReport(w http.ResponseWriter, r *http.Request) error { log.Errorf("creating transaction: %v", err) return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() report, err := s.DB.Report(ctx, tx, id) if err != nil { diff --git a/backend/routes/v1/user/delete_user.go b/backend/routes/v1/user/delete_user.go index 1523978..1132f05 100644 --- a/backend/routes/v1/user/delete_user.go +++ b/backend/routes/v1/user/delete_user.go @@ -3,9 +3,11 @@ package user import ( "net/http" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "codeberg.org/pronounscc/pronouns.cc/backend/server" "emperror.dev/errors" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" ) func (s *Server) deleteUser(w http.ResponseWriter, r *http.Request) error { @@ -20,7 +22,12 @@ func (s *Server) deleteUser(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() err = s.DB.DeleteUser(ctx, tx, claims.UserID, true, "") if err != nil { diff --git a/backend/routes/v1/user/flags.go b/backend/routes/v1/user/flags.go index b9c3ced..c7b6ad7 100644 --- a/backend/routes/v1/user/flags.go +++ b/backend/routes/v1/user/flags.go @@ -13,6 +13,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/chi/v5" "github.com/go-chi/render" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -80,7 +81,12 @@ func (s *Server) postUserFlag(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "starting transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() flag, err := s.DB.CreateFlag(ctx, tx, claims.UserID, req.Name, req.Description) if err != nil { @@ -192,7 +198,12 @@ func (s *Server) patchUserFlag(w http.ResponseWriter, r *http.Request) error { if err != nil { return errors.Wrap(err, "beginning transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() flag, err = s.DB.EditFlag(ctx, tx, flag.ID, req.Name, req.Description, nil) if err != nil { diff --git a/backend/routes/v1/user/patch_user.go b/backend/routes/v1/user/patch_user.go index ca489ce..6e4f6ab 100644 --- a/backend/routes/v1/user/patch_user.go +++ b/backend/routes/v1/user/patch_user.go @@ -12,6 +12,7 @@ import ( "emperror.dev/errors" "github.com/go-chi/render" "github.com/google/uuid" + "github.com/jackc/pgx/v5" "github.com/rs/xid" ) @@ -221,7 +222,12 @@ func (s *Server) patchUser(w http.ResponseWriter, r *http.Request) error { log.Errorf("creating transaction: %v", err) return errors.Wrap(err, "creating transaction") } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() // update username if req.Username != nil && *req.Username != u.Username { diff --git a/backend/server/server.go b/backend/server/server.go index bfc785d..30cd552 100644 --- a/backend/server/server.go +++ b/backend/server/server.go @@ -100,23 +100,23 @@ func New() (*Server, error) { // set scopes // users - rateLimiter.Scope("GET", "/users/*", 60) - rateLimiter.Scope("PATCH", "/users/@me", 10) + _ = rateLimiter.Scope("GET", "/users/*", 60) + _ = rateLimiter.Scope("PATCH", "/users/@me", 10) // members - rateLimiter.Scope("GET", "/users/*/members", 60) - rateLimiter.Scope("GET", "/users/*/members/*", 60) + _ = rateLimiter.Scope("GET", "/users/*/members", 60) + _ = rateLimiter.Scope("GET", "/users/*/members/*", 60) - rateLimiter.Scope("POST", "/members", 10) - rateLimiter.Scope("GET", "/members/*", 60) - rateLimiter.Scope("PATCH", "/members/*", 20) - rateLimiter.Scope("DELETE", "/members/*", 5) + _ = rateLimiter.Scope("POST", "/members", 10) + _ = rateLimiter.Scope("GET", "/members/*", 60) + _ = rateLimiter.Scope("PATCH", "/members/*", 20) + _ = rateLimiter.Scope("DELETE", "/members/*", 5) // auth - rateLimiter.Scope("*", "/auth/*", 20) - rateLimiter.Scope("*", "/auth/tokens", 10) - rateLimiter.Scope("*", "/auth/invites", 10) - rateLimiter.Scope("POST", "/auth/discord/*", 10) + _ = rateLimiter.Scope("*", "/auth/*", 20) + _ = rateLimiter.Scope("*", "/auth/tokens", 10) + _ = rateLimiter.Scope("*", "/auth/invites", 10) + _ = rateLimiter.Scope("POST", "/auth/discord/*", 10) s.Router.Use(rateLimiter.Handler()) diff --git a/scripts/cleandb/main.go b/scripts/cleandb/main.go index 317951b..9049861 100644 --- a/scripts/cleandb/main.go +++ b/scripts/cleandb/main.go @@ -2,12 +2,15 @@ package cleandb import ( "context" + "errors" "fmt" "os" "time" dbpkg "codeberg.org/pronounscc/pronouns.cc/backend/db" + "codeberg.org/pronounscc/pronouns.cc/backend/log" "github.com/georgysavva/scany/v2/pgxscan" + "github.com/jackc/pgx/v5" "github.com/joho/godotenv" "github.com/rs/xid" "github.com/urfave/cli/v2" @@ -77,7 +80,12 @@ func run(c *cli.Context) error { fmt.Printf("error starting transaction: %v\n", err) return err } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() inactiveUsers, err := db.InactiveUsers(ctx, tx) if err != nil { diff --git a/scripts/seeddb/main.go b/scripts/seeddb/main.go index c2e9f26..bbe20f5 100644 --- a/scripts/seeddb/main.go +++ b/scripts/seeddb/main.go @@ -1,10 +1,12 @@ package seeddb import ( + "errors" "log" "os" "codeberg.org/pronounscc/pronouns.cc/backend/db" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/joho/godotenv" "github.com/urfave/cli/v2" @@ -82,7 +84,12 @@ func run(c *cli.Context) error { log.Println("error beginning transaction:", err) return err } - defer tx.Rollback(ctx) + defer func() { + err := tx.Rollback(ctx) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Println("error rolling back transaction:", err) + } + }() for i, su := range seed.Users { u, err := pg.CreateUser(ctx, tx, su.Username) diff --git a/scripts/snowflakes/main.go b/scripts/snowflakes/main.go index 382035a..e88fe26 100644 --- a/scripts/snowflakes/main.go +++ b/scripts/snowflakes/main.go @@ -1,6 +1,7 @@ package snowflakes import ( + "errors" "os" "time" @@ -39,7 +40,12 @@ func run(c *cli.Context) error { log.Error("creating transaction:", err) return err } - defer tx.Rollback(c.Context) + defer func() { + err := tx.Rollback(c.Context) + if err != nil && !errors.Is(err, pgx.ErrTxClosed) { + log.Error("rolling back transaction:", err) + } + }() var userIDs []xid.ID err = pgxscan.Select(c.Context, conn, &userIDs, "SELECT id FROM users WHERE snowflake_id IS NULL") From 00abe1cb32c3bbbe84e3e29468c7f9354b5c092c Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 30 Dec 2023 04:41:22 +0100 Subject: [PATCH 17/26] fix: let users select the Google account to log in with every time --- backend/routes/v1/auth/routes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/routes/v1/auth/routes.go b/backend/routes/v1/auth/routes.go index 103d43e..2e1a724 100644 --- a/backend/routes/v1/auth/routes.go +++ b/backend/routes/v1/auth/routes.go @@ -185,7 +185,7 @@ func (s *Server) oauthURLs(w http.ResponseWriter, r *http.Request) error { if googleOAuthConfig.ClientID != "" { googleCfg := googleOAuthConfig googleCfg.RedirectURL = req.CallbackDomain + "/auth/login/google" - resp.Google = googleCfg.AuthCodeURL(state) + resp.Google = googleCfg.AuthCodeURL(state) + "&prompt=select_account" } render.JSON(w, r, resp) From ac603ac18eeab598159371d8c46d095a1b3555fc Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 30 Dec 2023 15:13:24 +0100 Subject: [PATCH 18/26] fix(frontend): fix type errors --- frontend/src/app.d.ts | 25 +++---------------- .../src/routes/@[username]/+page.server.ts | 2 +- .../@[username]/[memberName]/+page.server.ts | 4 +-- .../@[username]/[memberName]/edit/+layout.ts | 5 ++-- .../src/routes/@[username]/edit/+layout.ts | 5 ++-- .../src/routes/[username]/+page.server.ts | 2 +- frontend/src/routes/edit/member/[id]/+page.ts | 2 +- frontend/src/routes/edit/profile/+page.ts | 2 +- frontend/src/routes/page/about/+page.svelte | 1 + .../src/routes/page/changelog/+page.svelte | 1 + frontend/src/routes/page/privacy/+page.svelte | 1 + frontend/src/routes/page/terms/+page.svelte | 1 + .../pronouns/[...pronouns]/+page.svelte | 2 +- frontend/src/routes/settings/export/+page.ts | 2 +- frontend/src/svelte-hcaptcha.d.ts | 18 +++++++++++++ 15 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 frontend/src/svelte-hcaptcha.d.ts diff --git a/frontend/src/app.d.ts b/frontend/src/app.d.ts index ba59572..9489da5 100644 --- a/frontend/src/app.d.ts +++ b/frontend/src/app.d.ts @@ -1,38 +1,19 @@ // See https://kit.svelte.dev/docs/types#app -import type { APIError, ErrorCode } from "$lib/api/entities"; +import type { ErrorCode } from "$lib/api/entities"; // for information about these interfaces declare global { namespace App { - type Error = { + interface Error { code: ErrorCode; message?: string | undefined; details?: string | undefined; - } | APIError + } // interface Locals {} // interface PageData {} // interface Platform {} } } -declare module "svelte-hcaptcha" { - import type { SvelteComponent } from "svelte"; - - export interface HCaptchaProps { - sitekey?: string; - apihost?: string; - hl?: string; - reCaptchaCompat?: boolean; - theme?: CaptchaTheme; - size?: string; - } - - declare class HCaptcha extends SvelteComponent { - $$prop_def: HCaptchaProps; - } - - export default HCaptcha; -} - export {}; diff --git a/frontend/src/routes/@[username]/+page.server.ts b/frontend/src/routes/@[username]/+page.server.ts index 1e7b8af..0ae4617 100644 --- a/frontend/src/routes/@[username]/+page.server.ts +++ b/frontend/src/routes/@[username]/+page.server.ts @@ -11,7 +11,7 @@ export const load = async ({ params }) => { return resp; } catch (e) { if ((e as APIError).code === ErrorCode.UserNotFound) { - error(404, e as APIError); + error(404, e as App.Error); } throw e; diff --git a/frontend/src/routes/@[username]/[memberName]/+page.server.ts b/frontend/src/routes/@[username]/[memberName]/+page.server.ts index ad5925d..02aff1b 100644 --- a/frontend/src/routes/@[username]/[memberName]/+page.server.ts +++ b/frontend/src/routes/@[username]/[memberName]/+page.server.ts @@ -14,9 +14,9 @@ export const load = async ({ params }) => { (e as APIError).code === ErrorCode.UserNotFound || (e as APIError).code === ErrorCode.MemberNotFound ) { - error(404, e as APIError); + error(404, e as App.Error); } - error(500, e as APIError); + error(500, e as App.Error); } }; diff --git a/frontend/src/routes/@[username]/[memberName]/edit/+layout.ts b/frontend/src/routes/@[username]/[memberName]/edit/+layout.ts index e6333c0..8493fa6 100644 --- a/frontend/src/routes/@[username]/[memberName]/edit/+layout.ts +++ b/frontend/src/routes/@[username]/[memberName]/edit/+layout.ts @@ -41,8 +41,9 @@ export const load = (async ({ params }) => { pronouns: pronouns.autocomplete, flags, }; - } catch (e) { - if ("code" in e) error(500, e as APIError); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (e: any) { + if ("code" in e) error(500, e as App.Error); throw e; } }) satisfies LayoutLoad; diff --git a/frontend/src/routes/@[username]/edit/+layout.ts b/frontend/src/routes/@[username]/edit/+layout.ts index de77441..23e176d 100644 --- a/frontend/src/routes/@[username]/edit/+layout.ts +++ b/frontend/src/routes/@[username]/edit/+layout.ts @@ -21,8 +21,9 @@ export const load = async ({ params }) => { pronouns: pronouns.autocomplete, flags, }; - } catch (e) { - if ("code" in e) error(500, e as APIError); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (e: any) { + if ("code" in e) error(500, e as App.Error); throw e; } }; diff --git a/frontend/src/routes/[username]/+page.server.ts b/frontend/src/routes/[username]/+page.server.ts index b291ccb..6784dee 100644 --- a/frontend/src/routes/[username]/+page.server.ts +++ b/frontend/src/routes/[username]/+page.server.ts @@ -11,7 +11,7 @@ export const load = async ({ params }) => { redirect(303, `/@${resp.name}`); } catch (e) { if ((e as APIError).code === ErrorCode.UserNotFound) { - error(404, e as APIError); + error(404, e as App.Error); } throw e; diff --git a/frontend/src/routes/edit/member/[id]/+page.ts b/frontend/src/routes/edit/member/[id]/+page.ts index 96a64a2..1d6132c 100644 --- a/frontend/src/routes/edit/member/[id]/+page.ts +++ b/frontend/src/routes/edit/member/[id]/+page.ts @@ -23,7 +23,7 @@ export const load = async ({ params }) => { (e as APIError).code === ErrorCode.InvalidToken || (e as APIError).code === ErrorCode.NotOwnMember ) { - error(403, e as APIError); + error(403, e as App.Error); } throw e; diff --git a/frontend/src/routes/edit/profile/+page.ts b/frontend/src/routes/edit/profile/+page.ts index 71cd278..085adf3 100644 --- a/frontend/src/routes/edit/profile/+page.ts +++ b/frontend/src/routes/edit/profile/+page.ts @@ -14,7 +14,7 @@ export const load = async () => { (e as APIError).code === ErrorCode.Forbidden || (e as APIError).code === ErrorCode.InvalidToken ) { - error(403, e as APIError); + error(403, e as App.Error); } throw e; diff --git a/frontend/src/routes/page/about/+page.svelte b/frontend/src/routes/page/about/+page.svelte index ea19018..82fb6eb 100644 --- a/frontend/src/routes/page/about/+page.svelte +++ b/frontend/src/routes/page/about/+page.svelte @@ -1,4 +1,5 @@ diff --git a/frontend/src/routes/page/changelog/+page.svelte b/frontend/src/routes/page/changelog/+page.svelte index 51cc848..890f472 100644 --- a/frontend/src/routes/page/changelog/+page.svelte +++ b/frontend/src/routes/page/changelog/+page.svelte @@ -1,5 +1,6 @@ diff --git a/frontend/src/routes/page/terms/+page.svelte b/frontend/src/routes/page/terms/+page.svelte index ea126d0..fc3734e 100644 --- a/frontend/src/routes/page/terms/+page.svelte +++ b/frontend/src/routes/page/terms/+page.svelte @@ -1,4 +1,5 @@ diff --git a/frontend/src/routes/pronouns/[...pronouns]/+page.svelte b/frontend/src/routes/pronouns/[...pronouns]/+page.svelte index fd9536f..09a4329 100644 --- a/frontend/src/routes/pronouns/[...pronouns]/+page.svelte +++ b/frontend/src/routes/pronouns/[...pronouns]/+page.svelte @@ -1,6 +1,6 @@ diff --git a/frontend/src/routes/page/changelog/+page.svelte b/frontend/src/routes/page/changelog/+page.svelte index 890f472..bd98e56 100644 --- a/frontend/src/routes/page/changelog/+page.svelte +++ b/frontend/src/routes/page/changelog/+page.svelte @@ -1,5 +1,7 @@ diff --git a/frontend/src/routes/page/terms/+page.svelte b/frontend/src/routes/page/terms/+page.svelte index fc3734e..92044e4 100644 --- a/frontend/src/routes/page/terms/+page.svelte +++ b/frontend/src/routes/page/terms/+page.svelte @@ -1,4 +1,6 @@ diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte index 58f5650..e2c57db 100644 --- a/frontend/src/routes/settings/+page.svelte +++ b/frontend/src/routes/settings/+page.svelte @@ -25,7 +25,6 @@ Table, } from "@sveltestrap/sveltestrap"; import type { PageData } from "./$types"; - import { onMount } from "svelte"; import { DateTime } from "luxon"; export let data: PageData; From 1339550c808218ad92ae99cbd5f82d6b2a72c137 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 30 Dec 2023 15:38:23 +0100 Subject: [PATCH 21/26] fix: don't require a valid sentry dsn for the frontend --- .woodpecker/.frontend.yml | 2 +- frontend/src/hooks.server.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.woodpecker/.frontend.yml b/.woodpecker/.frontend.yml index a10ef11..228ce76 100644 --- a/.woodpecker/.frontend.yml +++ b/.woodpecker/.frontend.yml @@ -3,7 +3,7 @@ steps: image: node directory: frontend environment: # SvelteKit expects these in the environment during build time. - - PRIVATE_SENTRY_DSN=non_existent_dsn + - PRIVATE_SENTRY_DSN= - PUBLIC_BASE_URL=http://pronouns.localhost - PUBLIC_MEDIA_URL=http://pronouns.localhost/media - PUBLIC_SHORT_BASE=http://prns.localhost diff --git a/frontend/src/hooks.server.ts b/frontend/src/hooks.server.ts index e073554..670f914 100644 --- a/frontend/src/hooks.server.ts +++ b/frontend/src/hooks.server.ts @@ -2,7 +2,9 @@ import { PRIVATE_SENTRY_DSN } from "$env/static/private"; import * as Sentry from "@sentry/node"; import type { HandleServerError } from "@sveltejs/kit"; -Sentry.init({ dsn: PRIVATE_SENTRY_DSN }); +if (PRIVATE_SENTRY_DSN) { + Sentry.init({ dsn: PRIVATE_SENTRY_DSN }); +} export const handleError = (({ error, event }) => { console.log(error); From b29a0c86db27cb7f371625a9ae0f08c2d9918a3d Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 31 Dec 2023 15:14:50 +0100 Subject: [PATCH 22/26] only run ci on main [skip ci] --- .woodpecker/.backend.yml | 3 +++ .woodpecker/.frontend.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.woodpecker/.backend.yml b/.woodpecker/.backend.yml index 71abad3..811aa7e 100644 --- a/.woodpecker/.backend.yml +++ b/.woodpecker/.backend.yml @@ -1,3 +1,6 @@ +when: + branch: main + steps: check: image: golang:alpine diff --git a/.woodpecker/.frontend.yml b/.woodpecker/.frontend.yml index 228ce76..abc7e2b 100644 --- a/.woodpecker/.frontend.yml +++ b/.woodpecker/.frontend.yml @@ -1,3 +1,6 @@ +when: + branch: main + steps: check: image: node From 40672d6d4180c37b2f909e935f9364e52c5ad7d1 Mon Sep 17 00:00:00 2001 From: sam Date: Fri, 5 Jan 2024 15:24:42 +0100 Subject: [PATCH 23/26] fix type error in frontend --- frontend/src/routes/@[username]/PreferencesCheatsheet.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/routes/@[username]/PreferencesCheatsheet.svelte b/frontend/src/routes/@[username]/PreferencesCheatsheet.svelte index ac4200a..ebe56f1 100644 --- a/frontend/src/routes/@[username]/PreferencesCheatsheet.svelte +++ b/frontend/src/routes/@[username]/PreferencesCheatsheet.svelte @@ -1,5 +1,5 @@