go scratch code for atproto

DNS checking feature

+131
+130
cmd/glot/dns.go
··· 1 + package main 2 + 3 + import ( 4 + "context" 5 + "encoding/json" 6 + "fmt" 7 + "io/fs" 8 + "os" 9 + "path" 10 + "path/filepath" 11 + "sort" 12 + 13 + "github.com/bluesky-social/indigo/atproto/identity" 14 + "github.com/bluesky-social/indigo/atproto/syntax" 15 + 16 + "github.com/urfave/cli/v3" 17 + ) 18 + 19 + var cmdCheckDNS = &cli.Command{ 20 + Name: "check-dns", 21 + Usage: "checks for any schemas missing DNS NSID resolution", 22 + ArgsUsage: `<file-or-dir>*`, 23 + Flags: []cli.Flag{ 24 + &cli.StringFlag{ 25 + Name: "lexicons-dir", 26 + Value: "./lexicons/", 27 + Usage: "base directory for project Lexicon files", 28 + Sources: cli.EnvVars("LEXICONS_DIR"), 29 + }, 30 + &cli.StringFlag{ 31 + Name: "did", 32 + Usage: "lexicon publication DID for example text", 33 + Value: "did:web:lex.example.com", 34 + }, 35 + }, 36 + Action: runCheckDNS, 37 + } 38 + 39 + /* 40 + - enumerate all local groups 41 + - resolve and record any missing 42 + - print DNS configuration instructions 43 + */ 44 + func runCheckDNS(ctx context.Context, cmd *cli.Command) error { 45 + 46 + paths := cmd.Args().Slice() 47 + if !cmd.Args().Present() { 48 + paths = []string{cmd.String("lexicons-dir")} 49 + _, err := os.Stat(paths[0]) 50 + if err != nil { 51 + return fmt.Errorf("no path arguments specified and default lexicon directory not found\n%w", err) 52 + } 53 + } 54 + 55 + // collect all NSID/path mappings 56 + localSchemas := map[syntax.NSID]json.RawMessage{} 57 + 58 + for _, p := range paths { 59 + finfo, err := os.Stat(p) 60 + if err != nil { 61 + return fmt.Errorf("failed loading %s: %w", p, err) 62 + } 63 + if finfo.IsDir() { 64 + if err := filepath.WalkDir(p, func(fp string, d fs.DirEntry, err error) error { 65 + if d.IsDir() || path.Ext(fp) != ".json" { 66 + return nil 67 + } 68 + nsid, rec, err := loadSchemaPath(fp) 69 + if err != nil { 70 + return err 71 + } 72 + localSchemas[nsid] = *rec 73 + return nil 74 + }); err != nil { 75 + return err 76 + } 77 + continue 78 + } 79 + nsid, rec, err := loadSchemaPath(p) 80 + if err != nil { 81 + return err 82 + } 83 + localSchemas[nsid] = *rec 84 + } 85 + 86 + localGroups := map[string]bool{} 87 + for k := range localSchemas { 88 + g := nsidGroup(k) 89 + localGroups[g] = true 90 + } 91 + 92 + dir := identity.BaseDirectory{} 93 + missingGroups := []string{} 94 + for g := range localGroups { 95 + _, err := dir.ResolveNSID(ctx, syntax.NSID(g+"name")) 96 + if err != nil { 97 + missingGroups = append(missingGroups, g) 98 + } 99 + } 100 + 101 + if len(missingGroups) == 0 { 102 + fmt.Println("all lexicon schema NSIDs resolved successfully") 103 + return nil 104 + } 105 + sort.Strings(missingGroups) 106 + 107 + fmt.Println("Some lexicon NSIDs did not resolve via DNS:") 108 + fmt.Println("") 109 + for _, g := range missingGroups { 110 + fmt.Printf(" %s*\n", g) 111 + } 112 + fmt.Println("") 113 + fmt.Println("To make these resolve, add DNS TXT entries like:") 114 + fmt.Println("") 115 + for _, g := range missingGroups { 116 + nsid, err := syntax.ParseNSID(g + "name") 117 + if err != nil { 118 + return err 119 + } 120 + fmt.Printf(" _lexicon.%s\tTXT\t\"did=%s\"\n", nsid.Authority(), cmd.String("did")) 121 + } 122 + if !cmd.IsSet("did") { 123 + fmt.Println("") 124 + fmt.Println("(substituting your account DID for the example value)") 125 + } 126 + fmt.Println("") 127 + fmt.Println("Note that DNS management interfaces commonly require only the sub-domain parts of a name, not the full registered domain.") 128 + 129 + return nil 130 + }
+1
cmd/glot/main.go
··· 37 37 cmdNew, 38 38 cmdPublish, 39 39 cmdUnpublish, 40 + cmdCheckDNS, 40 41 } 41 42 return app.Run(context.Background(), args) 42 43 }