Chats parses a search query for chats. Supported query parameters: - title: case-insensitive title substring match via ILIKE (bare terms are rejected; use title: for title filtering) - archived: boolean (default: false, excludes archived chats unless explicitly set) - has_unread: nullable bo
(query string)
| 560 | // - repo: string (case-insensitive substring match against git remote origin or URL) |
| 561 | // - pr_title: string (case-insensitive PR title substring match) |
| 562 | func Chats(query string) (database.GetChatsParams, []codersdk.ValidationError) { |
| 563 | filter := database.GetChatsParams{ |
| 564 | // Default to hiding archived chats. |
| 565 | Archived: sql.NullBool{Bool: false, Valid: true}, |
| 566 | } |
| 567 | |
| 568 | if query == "" { |
| 569 | return filter, nil |
| 570 | } |
| 571 | |
| 572 | // Lowercase the keys so they match regardless of how the caller |
| 573 | // types them, but preserve value casing because some filters |
| 574 | // (e.g. diff_url) may include URL path segments where case is |
| 575 | // meaningful. |
| 576 | values, errors := searchTerms(query, func(term string, _ url.Values) error { |
| 577 | return xerrors.Errorf("unsupported search term: %q", term) |
| 578 | }) |
| 579 | if len(errors) > 0 { |
| 580 | return filter, errors |
| 581 | } |
| 582 | |
| 583 | parser := httpapi.NewQueryParamParser() |
| 584 | filter.Archived = parser.NullableBoolean(values, filter.Archived, "archived") |
| 585 | filter.HasUnread = parser.NullableBoolean(values, filter.HasUnread, "has_unread") |
| 586 | filter.PullRequestStatuses = httpapi.ParseCustomList(parser, values, nil, "pr_status", func(v string) (string, error) { |
| 587 | normalizedPRStatus := strings.ToLower(strings.TrimSpace(v)) |
| 588 | switch normalizedPRStatus { |
| 589 | case "draft", "open", "merged", "closed": |
| 590 | return normalizedPRStatus, nil |
| 591 | default: |
| 592 | return "", xerrors.Errorf("%q is not a valid value", v) |
| 593 | } |
| 594 | }) |
| 595 | if diffURL := parser.String(values, "", "diff_url"); diffURL != "" { |
| 596 | if err := validateDiffURL(diffURL); err != nil { |
| 597 | parser.Errors = append(parser.Errors, codersdk.ValidationError{ |
| 598 | Field: "diff_url", |
| 599 | Detail: err.Error(), |
| 600 | }) |
| 601 | } else { |
| 602 | filter.DiffURL = sql.NullString{String: diffURL, Valid: true} |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | filter.TitleQuery = parser.String(values, "", "title") |
| 607 | filter.PrTitleQuery = parser.String(values, "", "pr_title") |
| 608 | filter.RepoQuery = parser.String(values, "", "repo") |
| 609 | |
| 610 | // pr: requires a positive integer. |
| 611 | if prStr := parser.String(values, "", "pr"); prStr != "" { |
| 612 | n, err := strconv.ParseInt(prStr, 10, 32) |
| 613 | if err != nil || n <= 0 { |
| 614 | parser.Errors = append(parser.Errors, codersdk.ValidationError{ |
| 615 | Field: "pr", |
| 616 | Detail: fmt.Sprintf("%q is not a valid positive integer", prStr), |
| 617 | }) |
| 618 | } else { |
| 619 | filter.PrNumber = int32(n) |