Monorepo for Tangled
at master 99 lines 2.8 kB view raw
1package searchquery 2 3import ( 4 "context" 5 "log/slog" 6 "strings" 7) 8 9// IdentResolver converts a handle/identifier string to a DID string. 10type IdentResolver func(ctx context.Context, ident string) (string, error) 11 12// ResolveAuthor extracts the "author" tag from the query and resolves 13// both the positive and negated values to DIDs using the provided resolver. 14// Returns empty string / nil on missing tags or resolution failure. 15func ResolveAuthor(ctx context.Context, q *Query, resolve IdentResolver, log *slog.Logger) (authorDid string, negatedAuthorDids []string) { 16 if authorHandle := q.Get("author"); authorHandle != nil { 17 did, err := resolve(ctx, *authorHandle) 18 if err != nil { 19 log.Debug("failed to resolve author handle", "handle", *authorHandle, "err", err) 20 } else { 21 authorDid = did 22 } 23 } 24 25 for _, handle := range q.GetAllNegated("author") { 26 did, err := resolve(ctx, handle) 27 if err != nil { 28 log.Debug("failed to resolve negated author handle", "handle", handle, "err", err) 29 continue 30 } 31 negatedAuthorDids = append(negatedAuthorDids, did) 32 } 33 34 return authorDid, negatedAuthorDids 35} 36 37// TextFilters holds the keyword and phrase filters extracted from a query. 38type TextFilters struct { 39 Keywords []string 40 NegatedKeywords []string 41 Phrases []string 42 NegatedPhrases []string 43} 44 45// ExtractTextFilters extracts keyword and quoted-phrase items from the query, 46// separated into positive and negated slices. 47func ExtractTextFilters(q *Query) TextFilters { 48 var tf TextFilters 49 for _, item := range q.Items() { 50 switch item.Kind { 51 case KindKeyword: 52 if item.Negated { 53 tf.NegatedKeywords = append(tf.NegatedKeywords, item.Value) 54 } else { 55 tf.Keywords = append(tf.Keywords, item.Value) 56 } 57 case KindQuoted: 58 if item.Negated { 59 tf.NegatedPhrases = append(tf.NegatedPhrases, item.Value) 60 } else { 61 tf.Phrases = append(tf.Phrases, item.Value) 62 } 63 } 64 } 65 return tf 66} 67 68// ResolveDIDLabelValues resolves handle values to DIDs for dynamic label 69// tags whose name appears in didLabels. Tags not in didLabels are returned 70// unchanged. On resolution failure the original value is kept. 71func ResolveDIDLabelValues( 72 ctx context.Context, 73 tags []string, 74 didLabels map[string]bool, 75 resolve IdentResolver, 76 log *slog.Logger, 77) []string { 78 resolved := make([]string, 0, len(tags)) 79 for _, tag := range tags { 80 idx := strings.Index(tag, ":") 81 if idx < 0 { 82 resolved = append(resolved, tag) 83 continue 84 } 85 name, val := tag[:idx], tag[idx+1:] 86 if didLabels[name] { 87 did, err := resolve(ctx, val) 88 if err != nil { 89 log.Debug("failed to resolve DID label value", "label", name, "value", val, "err", err) 90 resolved = append(resolved, tag) 91 continue 92 } 93 resolved = append(resolved, name+":"+did) 94 } else { 95 resolved = append(resolved, tag) 96 } 97 } 98 return resolved 99}