lexicon devex tutorial

first pass at implementation

+24
.gitignore
··· 1 + *.o 2 + *.a 3 + *.pyc 4 + \#*\# 5 + *~ 6 + *.swp 7 + .* 8 + *.tmp 9 + *.old 10 + *.profile 11 + *.bkp 12 + *.bak 13 + [Tt]humbs.db 14 + *.DS_Store 15 + build/ 16 + _build/ 17 + src/build/ 18 + *.log 19 + 20 + atwork-cli 21 + .env 22 + 23 + # Don't ignore this file itself 24 + !.gitignore
+14
communitylexicon/locationhthree.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: community.lexicon.location.hthree 4 + 5 + package communitylexicon 6 + 7 + // A physical location in the form of a H3 encoded location. 8 + type LocationHthree struct { 9 + LexiconTypeID string `json:"$type,omitempty" cborgen:"$type,const=community.lexicon.location.hthree,omitempty"` 10 + // name: The name of the location. 11 + Name *string `json:"name,omitempty" cborgen:"name,omitempty"` 12 + // value: The h3 encoded location. 13 + Value string `json:"value" cborgen:"value"` 14 + }
+40
go.mod
··· 1 + module tangled.org/bnewbold.net/atwork-cli 2 + 3 + go 1.25.4 4 + 5 + require ( 6 + github.com/bluesky-social/indigo v0.0.0-20251125184450-35c1e15d2e5f 7 + github.com/joho/godotenv v1.5.1 8 + github.com/urfave/cli/v3 v3.4.1 9 + ) 10 + 11 + require ( 12 + github.com/beorn7/perks v1.0.1 // indirect 13 + github.com/cespare/xxhash/v2 v2.2.0 // indirect 14 + github.com/earthboundkid/versioninfo/v2 v2.24.1 // indirect 15 + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect 16 + github.com/ipfs/go-cid v0.4.1 // indirect 17 + github.com/klauspost/cpuid/v2 v2.2.7 // indirect 18 + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect 19 + github.com/minio/sha256-simd v1.0.1 // indirect 20 + github.com/mr-tron/base58 v1.2.0 // indirect 21 + github.com/multiformats/go-base32 v0.1.0 // indirect 22 + github.com/multiformats/go-base36 v0.2.0 // indirect 23 + github.com/multiformats/go-multibase v0.2.0 // indirect 24 + github.com/multiformats/go-multihash v0.2.3 // indirect 25 + github.com/multiformats/go-varint v0.0.7 // indirect 26 + github.com/prometheus/client_golang v1.17.0 // indirect 27 + github.com/prometheus/client_model v0.5.0 // indirect 28 + github.com/prometheus/common v0.45.0 // indirect 29 + github.com/prometheus/procfs v0.12.0 // indirect 30 + github.com/spaolacci/murmur3 v1.1.0 // indirect 31 + github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e // indirect 32 + gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect 33 + gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect 34 + golang.org/x/crypto v0.21.0 // indirect 35 + golang.org/x/sys v0.22.0 // indirect 36 + golang.org/x/time v0.3.0 // indirect 37 + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect 38 + google.golang.org/protobuf v1.33.0 // indirect 39 + lukechampine.com/blake3 v1.2.1 // indirect 40 + )
+73
go.sum
··· 1 + github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 + github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 + github.com/bluesky-social/indigo v0.0.0-20251125184450-35c1e15d2e5f h1:DNWIa5AsHDenBFyycb0CRxwSr+5GUN61nbbpKEpP4pc= 4 + github.com/bluesky-social/indigo v0.0.0-20251125184450-35c1e15d2e5f/go.mod h1:GuGAU33qKulpZCZNPcUeIQ4RW6KzNvOy7s8MSUXbAng= 5 + github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= 6 + github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 7 + github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 + github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg= 10 + github.com/earthboundkid/versioninfo/v2 v2.24.1/go.mod h1:VcWEooDEuyUJnMfbdTh0uFN4cfEIg+kHMuWB2CDCLjw= 11 + github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 12 + github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 13 + github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= 14 + github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= 15 + github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= 16 + github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= 17 + github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 18 + github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 19 + github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= 20 + github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 21 + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= 22 + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 23 + github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= 24 + github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= 25 + github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= 26 + github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 27 + github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= 28 + github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 29 + github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= 30 + github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= 31 + github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= 32 + github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= 33 + github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= 34 + github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= 35 + github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= 36 + github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= 37 + github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 38 + github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 39 + github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= 40 + github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= 41 + github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= 42 + github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= 43 + github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= 44 + github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 45 + github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= 46 + github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 47 + github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 48 + github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 49 + github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 50 + github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 51 + github.com/urfave/cli/v3 v3.4.1 h1:1M9UOCy5bLmGnuu1yn3t3CB4rG79Rtoxuv1sPhnm6qM= 52 + github.com/urfave/cli/v3 v3.4.1/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= 53 + github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e h1:28X54ciEwwUxyHn9yrZfl5ojgF4CBNLWX7LR0rvBkf4= 54 + github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so= 55 + gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA= 56 + gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= 57 + gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= 58 + gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= 59 + golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= 60 + golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= 61 + golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 62 + golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= 63 + golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 64 + golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= 65 + golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 66 + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= 67 + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 68 + google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 69 + google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 70 + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 71 + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 72 + lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= 73 + lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
+89
lexicons/app/bsky/richtext/facet.json
··· 1 + { 2 + "defs": { 3 + "byteSlice": { 4 + "description": "Specifies the sub-string range a facet feature applies to. Start index is inclusive, end index is exclusive. Indices are zero-indexed, counting bytes of the UTF-8 encoded text. NOTE: some languages, like Javascript, use UTF-16 or Unicode codepoints for string slice indexing; in these languages, convert to byte arrays before working with facets.", 5 + "properties": { 6 + "byteEnd": { 7 + "minimum": 0, 8 + "type": "integer" 9 + }, 10 + "byteStart": { 11 + "minimum": 0, 12 + "type": "integer" 13 + } 14 + }, 15 + "required": [ 16 + "byteStart", 17 + "byteEnd" 18 + ], 19 + "type": "object" 20 + }, 21 + "link": { 22 + "description": "Facet feature for a URL. The text URL may have been simplified or truncated, but the facet reference should be a complete URL.", 23 + "properties": { 24 + "uri": { 25 + "format": "uri", 26 + "type": "string" 27 + } 28 + }, 29 + "required": [ 30 + "uri" 31 + ], 32 + "type": "object" 33 + }, 34 + "main": { 35 + "description": "Annotation of a sub-string within rich text.", 36 + "properties": { 37 + "features": { 38 + "items": { 39 + "refs": [ 40 + "#mention", 41 + "#link", 42 + "#tag" 43 + ], 44 + "type": "union" 45 + }, 46 + "type": "array" 47 + }, 48 + "index": { 49 + "ref": "#byteSlice", 50 + "type": "ref" 51 + } 52 + }, 53 + "required": [ 54 + "index", 55 + "features" 56 + ], 57 + "type": "object" 58 + }, 59 + "mention": { 60 + "description": "Facet feature for mention of another account. The text is usually a handle, including a '@' prefix, but the facet reference is a DID.", 61 + "properties": { 62 + "did": { 63 + "format": "did", 64 + "type": "string" 65 + } 66 + }, 67 + "required": [ 68 + "did" 69 + ], 70 + "type": "object" 71 + }, 72 + "tag": { 73 + "description": "Facet feature for a hashtag. The text usually includes a '#' prefix, but the facet reference should not (except in the case of 'double hash tags').", 74 + "properties": { 75 + "tag": { 76 + "maxGraphemes": 64, 77 + "maxLength": 640, 78 + "type": "string" 79 + } 80 + }, 81 + "required": [ 82 + "tag" 83 + ], 84 + "type": "object" 85 + } 86 + }, 87 + "id": "app.bsky.richtext.facet", 88 + "lexicon": 1 89 + }
+24
lexicons/com/atproto/repo/strongRef.json
··· 1 + { 2 + "defs": { 3 + "main": { 4 + "properties": { 5 + "cid": { 6 + "format": "cid", 7 + "type": "string" 8 + }, 9 + "uri": { 10 + "format": "at-uri", 11 + "type": "string" 12 + } 13 + }, 14 + "required": [ 15 + "uri", 16 + "cid" 17 + ], 18 + "type": "object" 19 + } 20 + }, 21 + "description": "A URI with a content-hash fingerprint.", 22 + "id": "com.atproto.repo.strongRef", 23 + "lexicon": 1 24 + }
+23
lexicons/community/lexicon/location/hthree.json
··· 1 + { 2 + "defs": { 3 + "main": { 4 + "description": "A physical location in the form of a H3 encoded location.", 5 + "properties": { 6 + "name": { 7 + "description": "The name of the location.", 8 + "type": "string" 9 + }, 10 + "value": { 11 + "description": "The h3 encoded location.", 12 + "type": "string" 13 + } 14 + }, 15 + "required": [ 16 + "value" 17 + ], 18 + "type": "object" 19 + } 20 + }, 21 + "id": "community.lexicon.location.hthree", 22 + "lexicon": 1 23 + }
+53
lexicons/place/atwork/endorsement.json
··· 1 + { 2 + "defs": { 3 + "main": { 4 + "description": "A cryptographically-verified professional endorsement between two identities.", 5 + "key": "tid", 6 + "record": { 7 + "properties": { 8 + "createdAt": { 9 + "description": "Timestamp when the endorsement was created.", 10 + "format": "datetime", 11 + "type": "string" 12 + }, 13 + "giver": { 14 + "description": "The DID of the identity giving the endorsement.", 15 + "format": "did", 16 + "type": "string" 17 + }, 18 + "receiver": { 19 + "description": "The DID of the identity receiving the endorsement.", 20 + "format": "did", 21 + "type": "string" 22 + }, 23 + "signatures": { 24 + "description": "Verified signatures from endorsement proofs (strong references).", 25 + "items": { 26 + "refs": [ 27 + "com.atproto.repo.strongRef" 28 + ], 29 + "type": "union" 30 + }, 31 + "type": "array" 32 + }, 33 + "text": { 34 + "description": "The endorsement text content.", 35 + "maxGraphemes": 1000, 36 + "maxLength": 1000, 37 + "type": "string" 38 + } 39 + }, 40 + "required": [ 41 + "giver", 42 + "receiver", 43 + "text", 44 + "createdAt" 45 + ], 46 + "type": "object" 47 + }, 48 + "type": "record" 49 + } 50 + }, 51 + "id": "place.atwork.endorsement", 52 + "lexicon": 1 53 + }
+24
lexicons/place/atwork/endorsementProof.json
··· 1 + { 2 + "defs": { 3 + "main": { 4 + "description": "A cryptographic proof record that validates an endorsement by containing the CID of the endorsement content.", 5 + "key": "tid", 6 + "record": { 7 + "properties": { 8 + "cid": { 9 + "description": "The CID (Content Identifier) of the endorsement content that this proof validates. The endorsement's signatures array references this proof record.", 10 + "format": "cid", 11 + "type": "string" 12 + } 13 + }, 14 + "required": [ 15 + "cid" 16 + ], 17 + "type": "object" 18 + }, 19 + "type": "record" 20 + } 21 + }, 22 + "id": "place.atwork.endorsementProof", 23 + "lexicon": 1 24 + }
+69
lexicons/place/atwork/getListing.json
··· 1 + { 2 + "defs": { 3 + "main": { 4 + "description": "Get a single job listing by repo (DID) and record key", 5 + "errors": [ 6 + { 7 + "description": "The requested listing does not exist", 8 + "name": "ListingNotFound" 9 + }, 10 + { 11 + "description": "Failed to parse the listing data", 12 + "name": "ListingParseFailed" 13 + }, 14 + { 15 + "description": "Failed to fetch the listing from storage", 16 + "name": "ListingFetchFailed" 17 + } 18 + ], 19 + "output": { 20 + "encoding": "application/json", 21 + "schema": { 22 + "properties": { 23 + "cid": { 24 + "description": "CID of the listing record", 25 + "format": "cid", 26 + "type": "string" 27 + }, 28 + "uri": { 29 + "description": "AT-URI of the listing", 30 + "format": "at-uri", 31 + "type": "string" 32 + }, 33 + "value": { 34 + "description": "The job listing record", 35 + "ref": "place.atwork.listing", 36 + "type": "ref" 37 + } 38 + }, 39 + "required": [ 40 + "uri", 41 + "value" 42 + ], 43 + "type": "object" 44 + } 45 + }, 46 + "parameters": { 47 + "properties": { 48 + "repo": { 49 + "description": "The DID of the repo (repository owner)", 50 + "format": "at-identifier", 51 + "type": "string" 52 + }, 53 + "rkey": { 54 + "description": "The record key (TID)", 55 + "type": "string" 56 + } 57 + }, 58 + "required": [ 59 + "repo", 60 + "rkey" 61 + ], 62 + "type": "params" 63 + }, 64 + "type": "query" 65 + } 66 + }, 67 + "id": "place.atwork.getListing", 68 + "lexicon": 1 69 + }
+66
lexicons/place/atwork/getListings.json
··· 1 + { 2 + "defs": { 3 + "listingRecord": { 4 + "description": "A job listing record with metadata for strong references", 5 + "properties": { 6 + "cid": { 7 + "description": "CID of the listing record", 8 + "format": "cid", 9 + "type": "string" 10 + }, 11 + "uri": { 12 + "description": "AT-URI of the listing (at://did/place.atwork.listing/rkey)", 13 + "format": "at-uri", 14 + "type": "string" 15 + }, 16 + "value": { 17 + "description": "The full job listing record", 18 + "ref": "place.atwork.listing", 19 + "type": "ref" 20 + } 21 + }, 22 + "required": [ 23 + "uri", 24 + "cid" 25 + ], 26 + "type": "object" 27 + }, 28 + "main": { 29 + "description": "Get job listings, optionally filtered by tag or identity", 30 + "output": { 31 + "encoding": "application/json", 32 + "schema": { 33 + "properties": { 34 + "listings": { 35 + "items": { 36 + "ref": "#listingRecord", 37 + "type": "ref" 38 + }, 39 + "type": "array" 40 + } 41 + }, 42 + "required": [ 43 + "listings" 44 + ], 45 + "type": "object" 46 + } 47 + }, 48 + "parameters": { 49 + "properties": { 50 + "identity": { 51 + "description": "Filter listings by creator DID (e.g., did:plc:abc123)", 52 + "type": "string" 53 + }, 54 + "tag": { 55 + "description": "Filter listings by hashtag", 56 + "type": "string" 57 + } 58 + }, 59 + "type": "params" 60 + }, 61 + "type": "query" 62 + } 63 + }, 64 + "id": "place.atwork.getListings", 65 + "lexicon": 1 66 + }
+75
lexicons/place/atwork/listing.json
··· 1 + { 2 + "defs": { 3 + "main": { 4 + "description": "A job listing", 5 + "key": "tid", 6 + "record": { 7 + "properties": { 8 + "applyLink": { 9 + "description": "URL where applicants can apply for the job.", 10 + "format": "uri", 11 + "type": "string" 12 + }, 13 + "banner": { 14 + "accept": [ 15 + "image/png", 16 + "image/jpeg" 17 + ], 18 + "description": "Larger horizontal image to display behind job listing view.", 19 + "maxSize": 1000000, 20 + "type": "blob" 21 + }, 22 + "description": { 23 + "description": "The description of the job listing.", 24 + "maxGraphemes": 10000, 25 + "maxLength": 10000, 26 + "type": "string" 27 + }, 28 + "facets": { 29 + "description": "Annotations of text (mentions, URLs, hashtags, etc).", 30 + "items": { 31 + "ref": "app.bsky.richtext.facet", 32 + "type": "ref" 33 + }, 34 + "type": "array" 35 + }, 36 + "locations": { 37 + "description": "Locations that are relevant to the job listing.", 38 + "items": { 39 + "refs": [ 40 + "community.lexicon.location.hthree" 41 + ], 42 + "type": "union" 43 + }, 44 + "type": "array" 45 + }, 46 + "notAfter": { 47 + "description": "Client-declared timestamp when the job listing expires.", 48 + "format": "datetime", 49 + "type": "string" 50 + }, 51 + "notBefore": { 52 + "description": "Client-declared timestamp when the job listing becomes visible.", 53 + "format": "datetime", 54 + "type": "string" 55 + }, 56 + "title": { 57 + "description": "The title of the job listing.", 58 + "maxLength": 200, 59 + "type": "string" 60 + } 61 + }, 62 + "required": [ 63 + "title", 64 + "notBefore", 65 + "notAfter", 66 + "description" 67 + ], 68 + "type": "object" 69 + }, 70 + "type": "record" 71 + } 72 + }, 73 + "id": "place.atwork.listing", 74 + "lexicon": 1 75 + }
+87
lexicons/place/atwork/profile.json
··· 1 + { 2 + "defs": { 3 + "forhire": { 4 + "description": "Indicates the identity is available for hire", 5 + "type": "token" 6 + }, 7 + "hiring": { 8 + "description": "Indicates the identity is actively hiring", 9 + "type": "token" 10 + }, 11 + "main": { 12 + "description": "A user profile for AT://Work.Place", 13 + "key": "literal:self", 14 + "record": { 15 + "properties": { 16 + "avatar": { 17 + "accept": [ 18 + "image/png", 19 + "image/jpeg" 20 + ], 21 + "description": "Small image to be displayed next to job listings from account. AKA, 'profile picture'", 22 + "maxSize": 1000000, 23 + "type": "blob" 24 + }, 25 + "banner": { 26 + "accept": [ 27 + "image/png", 28 + "image/jpeg" 29 + ], 30 + "description": "Larger horizontal image to display behind profile view.", 31 + "maxSize": 1000000, 32 + "type": "blob" 33 + }, 34 + "description": { 35 + "description": "A free text description of the identity.", 36 + "maxGraphemes": 2000, 37 + "maxLength": 2000, 38 + "type": "string" 39 + }, 40 + "displayName": { 41 + "description": "The display name of the identity.", 42 + "maxGraphemes": 200, 43 + "maxLength": 200, 44 + "type": "string" 45 + }, 46 + "facets": { 47 + "description": "Annotations of text (mentions, URLs, hashtags, etc) in the description.", 48 + "items": { 49 + "ref": "app.bsky.richtext.facet", 50 + "type": "ref" 51 + }, 52 + "type": "array" 53 + }, 54 + "profile_host": { 55 + "description": "The service used for profile links", 56 + "knownValues": [ 57 + "bsky.app", 58 + "blacksky.community" 59 + ], 60 + "type": "string" 61 + }, 62 + "resume": { 63 + "accept": [ 64 + "application/pdf", 65 + "text/plain" 66 + ], 67 + "description": "The identity's resume.", 68 + "maxSize": 4000000, 69 + "type": "blob" 70 + }, 71 + "status": { 72 + "description": "The current status of the identity.", 73 + "knownValues": [ 74 + "place.atwork.profile#hiring", 75 + "place.atwork.profile#forhire" 76 + ], 77 + "type": "string" 78 + } 79 + }, 80 + "type": "object" 81 + }, 82 + "type": "record" 83 + } 84 + }, 85 + "id": "place.atwork.profile", 86 + "lexicon": 1 87 + }
+71
lexicons/place/atwork/searchListings.json
··· 1 + { 2 + "defs": { 3 + "listingRecord": { 4 + "description": "A job listing record with metadata for strong references", 5 + "properties": { 6 + "cid": { 7 + "description": "CID of the listing record", 8 + "format": "cid", 9 + "type": "string" 10 + }, 11 + "uri": { 12 + "description": "AT-URI of the listing (at://did/place.atwork.listing/rkey)", 13 + "format": "at-uri", 14 + "type": "string" 15 + }, 16 + "value": { 17 + "description": "The full job listing record", 18 + "ref": "place.atwork.listing", 19 + "type": "ref" 20 + } 21 + }, 22 + "required": [ 23 + "uri", 24 + "cid" 25 + ], 26 + "type": "object" 27 + }, 28 + "main": { 29 + "description": "Search job listings using full-text query", 30 + "errors": [ 31 + { 32 + "description": "Failed to search listings", 33 + "name": "SearchFailed" 34 + } 35 + ], 36 + "output": { 37 + "encoding": "application/json", 38 + "schema": { 39 + "properties": { 40 + "listings": { 41 + "items": { 42 + "ref": "#listingRecord", 43 + "type": "ref" 44 + }, 45 + "type": "array" 46 + } 47 + }, 48 + "required": [ 49 + "listings" 50 + ], 51 + "type": "object" 52 + } 53 + }, 54 + "parameters": { 55 + "properties": { 56 + "query": { 57 + "description": "Search query string for full-text search", 58 + "type": "string" 59 + } 60 + }, 61 + "required": [ 62 + "query" 63 + ], 64 + "type": "params" 65 + }, 66 + "type": "query" 67 + } 68 + }, 69 + "id": "place.atwork.searchListings", 70 + "lexicon": 1 71 + }
+233
main.go
··· 1 + package main 2 + 3 + import ( 4 + "context" 5 + "encoding/json" 6 + "fmt" 7 + "net/http" 8 + "os" 9 + 10 + _ "github.com/joho/godotenv/autoload" 11 + 12 + "tangled.org/bnewbold.net/atwork-cli/placeatwork" 13 + 14 + "github.com/bluesky-social/indigo/api/agnostic" 15 + comatproto "github.com/bluesky-social/indigo/api/atproto" 16 + appbsky "github.com/bluesky-social/indigo/api/bsky" 17 + "github.com/bluesky-social/indigo/atproto/atclient" 18 + "github.com/bluesky-social/indigo/atproto/identity" 19 + "github.com/bluesky-social/indigo/atproto/syntax" 20 + "github.com/urfave/cli/v3" 21 + ) 22 + 23 + func main() { 24 + app := cli.Command{ 25 + Name: "atwork-cli", 26 + Usage: "example CLI project for at://work lexicons", 27 + Commands: []*cli.Command{ 28 + &cli.Command{ 29 + Name: "search", 30 + Usage: "queries public API for listings", 31 + ArgsUsage: "<query>", 32 + Flags: []cli.Flag{ 33 + &cli.StringFlag{ 34 + Name: "host", 35 + Value: "https://atwork.place", 36 + }, 37 + }, 38 + Action: runSearch, 39 + }, 40 + &cli.Command{ 41 + Name: "import-bsky-profile", 42 + Usage: "creates a new atwork profile using Bluesky profile data", 43 + Flags: []cli.Flag{ 44 + &cli.StringFlag{ 45 + Name: "username", 46 + Sources: cli.EnvVars("ATP_USERNAME"), 47 + }, 48 + &cli.StringFlag{ 49 + Name: "password", 50 + Sources: cli.EnvVars("ATP_PASSWORD"), 51 + }, 52 + }, 53 + Action: runImportProfile, 54 + }, 55 + &cli.Command{ 56 + Name: "upload-resume", 57 + Usage: "uploads resume PDF and adds to atwork profile", 58 + ArgsUsage: "<pdf-path>", 59 + Flags: []cli.Flag{ 60 + &cli.StringFlag{ 61 + Name: "username", 62 + Sources: cli.EnvVars("ATP_USERNAME"), 63 + }, 64 + &cli.StringFlag{ 65 + Name: "password", 66 + Sources: cli.EnvVars("ATP_PASSWORD"), 67 + }, 68 + }, 69 + Action: runUploadResume, 70 + }, 71 + }, 72 + } 73 + 74 + if err := app.Run(context.Background(), os.Args); err != nil { 75 + fmt.Fprintf(os.Stderr, "error: %v\n", err) 76 + os.Exit(1) 77 + } 78 + } 79 + 80 + func runSearch(ctx context.Context, cmd *cli.Command) error { 81 + if !cmd.Args().Present() { 82 + return fmt.Errorf("requires a search query") 83 + } 84 + searchQuery := cmd.Args().First() 85 + 86 + c := atclient.NewAPIClient(cmd.String("host")) 87 + 88 + resp, err := placeatwork.SearchListings(ctx, c, searchQuery) 89 + if err != nil { 90 + return err 91 + } 92 + 93 + for _, hit := range resp.Listings { 94 + if hit.Value == nil { 95 + continue 96 + } 97 + listing := *hit.Value 98 + aturi, err := syntax.ParseATURI(hit.Uri) 99 + if err != nil { 100 + continue 101 + } 102 + fmt.Printf("%s: %s\n", aturi.Authority(), listing.Title) 103 + if listing.ApplyLink != nil { 104 + fmt.Printf("\tApply: %s\n", *listing.ApplyLink) 105 + } 106 + } 107 + 108 + return nil 109 + } 110 + 111 + func runImportProfile(ctx context.Context, cmd *cli.Command) error { 112 + 113 + if !cmd.IsSet("username") || !cmd.IsSet("password") { 114 + return fmt.Errorf("authentication required (username and password)") 115 + } 116 + 117 + username, err := syntax.ParseAtIdentifier(cmd.String("username")) 118 + if err != nil { 119 + return fmt.Errorf("invalid username: %w", err) 120 + } 121 + dir := identity.DefaultDirectory() 122 + 123 + c, err := atclient.LoginWithPassword(ctx, dir, *username, cmd.String("password"), "", nil) 124 + if err != nil { 125 + return err 126 + } 127 + 128 + // fetch existing bsky profile 129 + resp, err := agnostic.RepoGetRecord(ctx, c, "", "app.bsky.actor.profile", c.AccountDID.String(), "self") 130 + if err != nil { 131 + return fmt.Errorf("failed fetching bsky profile record: %s", err) 132 + } 133 + 134 + var bskyProfile appbsky.ActorProfile 135 + if err := json.Unmarshal(*resp.Value, &bskyProfile); err != nil { 136 + return err 137 + } 138 + 139 + // create new atwork profile record 140 + atworkProfile := placeatwork.Profile{ 141 + LexiconTypeID: "place.atwork.profile", 142 + Avatar: bskyProfile.Avatar, 143 + Banner: bskyProfile.Banner, 144 + Description: bskyProfile.Description, 145 + DisplayName: bskyProfile.DisplayName, 146 + } 147 + 148 + // create profile record (fails if one already exists) 149 + if err := c.Post(ctx, syntax.NSID("com.atproto.repo.createRecord"), map[string]any{ 150 + "repo": c.AccountDID, 151 + "collection": atworkProfile.LexiconTypeID, 152 + "rkey": "self", 153 + "record": atworkProfile, 154 + }, nil); err != nil { 155 + return err 156 + } 157 + 158 + return nil 159 + } 160 + 161 + func runUploadResume(ctx context.Context, cmd *cli.Command) error { 162 + 163 + if !cmd.Args().Present() { 164 + return fmt.Errorf("requires resume PDF path as argument") 165 + } 166 + resumePath := cmd.Args().First() 167 + 168 + if !cmd.IsSet("username") || !cmd.IsSet("password") { 169 + return fmt.Errorf("authentication required (username and password)") 170 + } 171 + 172 + username, err := syntax.ParseAtIdentifier(cmd.String("username")) 173 + if err != nil { 174 + return fmt.Errorf("invalid username: %w", err) 175 + } 176 + dir := identity.DefaultDirectory() 177 + 178 + c, err := atclient.LoginWithPassword(ctx, dir, *username, cmd.String("password"), "", nil) 179 + if err != nil { 180 + return err 181 + } 182 + 183 + // fetch existing at://work profile 184 + getResp, err := agnostic.RepoGetRecord(ctx, c, "", "place.atwork.profile", c.AccountDID.String(), "self") 185 + if err != nil { 186 + return fmt.Errorf("failed fetching profile record: %s", err) 187 + } 188 + 189 + var atworkProfile placeatwork.Profile 190 + if err := json.Unmarshal(*getResp.Value, &atworkProfile); err != nil { 191 + return err 192 + } 193 + 194 + // upload resume PDF as blob 195 + resumeFile, err := os.Open(resumePath) 196 + if err != nil { 197 + return err 198 + } 199 + defer resumeFile.Close() 200 + 201 + // update record 202 + req := atclient.NewAPIRequest(http.MethodPost, syntax.NSID("com.atproto.repo.uploadBlob"), resumeFile) 203 + req.Headers.Set("Accept", "application/json") 204 + req.Headers.Set("Content-Type", "application/pdf") 205 + 206 + resp, err := c.Do(ctx, req) 207 + if err != nil { 208 + return err 209 + } 210 + defer resp.Body.Close() 211 + 212 + if !(resp.StatusCode >= 200 && resp.StatusCode < 300) { 213 + return fmt.Errorf("blob upload failed") 214 + } 215 + 216 + var blobResp comatproto.RepoUploadBlob_Output 217 + if err := json.NewDecoder(resp.Body).Decode(&blobResp); err != nil { 218 + return fmt.Errorf("failed decoding JSON response body: %w", err) 219 + } 220 + 221 + // update profile with blob ref 222 + atworkProfile.Resume = blobResp.Blob 223 + if err := c.Post(ctx, syntax.NSID("com.atproto.repo.putRecord"), map[string]any{ 224 + "repo": c.AccountDID, 225 + "collection": atworkProfile.LexiconTypeID, 226 + "rkey": "self", 227 + "record": atworkProfile, 228 + }, nil); err != nil { 229 + return err 230 + } 231 + 232 + return nil 233 + }
+55
placeatwork/endorsement.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: place.atwork.endorsement 4 + 5 + package placeatwork 6 + 7 + import ( 8 + "encoding/json" 9 + "fmt" 10 + 11 + comatproto "github.com/bluesky-social/indigo/api/atproto" 12 + lexutil "github.com/bluesky-social/indigo/lex/util" 13 + ) 14 + 15 + // A cryptographically-verified professional endorsement between two identities. 16 + type Endorsement struct { 17 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.atwork.endorsement"` 18 + // createdAt: Timestamp when the endorsement was created. 19 + CreatedAt string `json:"createdAt" cborgen:"createdAt"` 20 + // giver: The DID of the identity giving the endorsement. 21 + Giver string `json:"giver" cborgen:"giver"` 22 + // receiver: The DID of the identity receiving the endorsement. 23 + Receiver string `json:"receiver" cborgen:"receiver"` 24 + // signatures: Verified signatures from endorsement proofs (strong references). 25 + Signatures []Endorsement_Signatures_Elem `json:"signatures,omitempty" cborgen:"signatures,omitempty"` 26 + // text: The endorsement text content. 27 + Text string `json:"text" cborgen:"text"` 28 + } 29 + 30 + type Endorsement_Signatures_Elem struct { 31 + RepoStrongRef *comatproto.RepoStrongRef 32 + } 33 + 34 + func (t *Endorsement_Signatures_Elem) MarshalJSON() ([]byte, error) { 35 + if t.RepoStrongRef != nil { 36 + t.RepoStrongRef.LexiconTypeID = "com.atproto.repo.strongRef" 37 + return json.Marshal(t.RepoStrongRef) 38 + } 39 + return nil, fmt.Errorf("can not marshal empty union as JSON") 40 + } 41 + 42 + func (t *Endorsement_Signatures_Elem) UnmarshalJSON(b []byte) error { 43 + typ, err := lexutil.TypeExtract(b) 44 + if err != nil { 45 + return err 46 + } 47 + 48 + switch typ { 49 + case "com.atproto.repo.strongRef": 50 + t.RepoStrongRef = new(comatproto.RepoStrongRef) 51 + return json.Unmarshal(b, t.RepoStrongRef) 52 + default: 53 + return nil 54 + } 55 + }
+12
placeatwork/endorsementProof.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: place.atwork.endorsementProof 4 + 5 + package placeatwork 6 + 7 + // A cryptographic proof record that validates an endorsement by containing the CID of the endorsement content. 8 + type EndorsementProof struct { 9 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.atwork.endorsementProof"` 10 + // cid: The CID (Content Identifier) of the endorsement content that this proof validates. The endorsement's signatures array references this proof record. 11 + Cid string `json:"cid" cborgen:"cid"` 12 + }
+40
placeatwork/getListing.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: place.atwork.getListing 4 + 5 + package placeatwork 6 + 7 + import ( 8 + "context" 9 + 10 + lexutil "github.com/bluesky-social/indigo/lex/util" 11 + ) 12 + 13 + // GetListing_Output is the output of a place.atwork.getListing call. 14 + type GetListing_Output struct { 15 + // cid: CID of the listing record 16 + Cid *string `json:"cid,omitempty" cborgen:"cid,omitempty"` 17 + // uri: AT-URI of the listing 18 + Uri string `json:"uri" cborgen:"uri"` 19 + // value: The job listing record 20 + Value Listing `json:"value" cborgen:"value"` 21 + } 22 + 23 + // GetListing calls the XRPC method "place.atwork.getListing". 24 + // 25 + // # Get a single job listing by repo (DID) and record key 26 + // 27 + // repo: The DID of the repo (repository owner) 28 + // rkey: The record key (TID) 29 + func GetListing(ctx context.Context, c lexutil.LexClient, repo string, rkey string) (*GetListing_Output, error) { 30 + var out GetListing_Output 31 + 32 + params := map[string]interface{}{} 33 + params["repo"] = repo 34 + params["rkey"] = rkey 35 + 36 + if err := c.LexDo(ctx, lexutil.Query, "", "place.atwork.getListing", params, nil, &out); err != nil { 37 + return nil, err 38 + } 39 + return &out, nil 40 + }
+52
placeatwork/getListings.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: place.atwork.getListings 4 + 5 + package placeatwork 6 + 7 + import ( 8 + "context" 9 + 10 + lexutil "github.com/bluesky-social/indigo/lex/util" 11 + ) 12 + 13 + // GetListings_Output is the output of a place.atwork.getListings call. 14 + type GetListings_Output struct { 15 + Listings []GetListings_ListingRecord `json:"listings" cborgen:"listings"` 16 + } 17 + 18 + // GetListings calls the XRPC method "place.atwork.getListings". 19 + // 20 + // # Get job listings, optionally filtered by tag or identity 21 + // 22 + // identity: Filter listings by creator DID (e.g., did:plc:abc123) 23 + // tag: Filter listings by hashtag 24 + func GetListings(ctx context.Context, c lexutil.LexClient, identity string, tag string) (*GetListings_Output, error) { 25 + var out GetListings_Output 26 + 27 + params := map[string]interface{}{} 28 + if identity != "" { 29 + params["identity"] = identity 30 + } 31 + if tag != "" { 32 + params["tag"] = tag 33 + } 34 + 35 + if err := c.LexDo(ctx, lexutil.Query, "", "place.atwork.getListings", params, nil, &out); err != nil { 36 + return nil, err 37 + } 38 + return &out, nil 39 + } 40 + 41 + // GetListings_ListingRecord is a "listingRecord" in the place.atwork.getListings schema. 42 + // 43 + // A job listing record with metadata for strong references 44 + type GetListings_ListingRecord struct { 45 + LexiconTypeID string `json:"$type,omitempty" cborgen:"$type,const=place.atwork.getListings#listingRecord,omitempty"` 46 + // cid: CID of the listing record 47 + Cid string `json:"cid" cborgen:"cid"` 48 + // uri: AT-URI of the listing (at://did/place.atwork.listing/rkey) 49 + Uri string `json:"uri" cborgen:"uri"` 50 + // value: The full job listing record 51 + Value *Listing `json:"value,omitempty" cborgen:"value,omitempty"` 52 + }
+62
placeatwork/listing.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: place.atwork.listing 4 + 5 + package placeatwork 6 + 7 + import ( 8 + "encoding/json" 9 + "fmt" 10 + 11 + appbsky "github.com/bluesky-social/indigo/api/bsky" 12 + lexutil "github.com/bluesky-social/indigo/lex/util" 13 + "tangled.org/bnewbold.net/atwork-cli/communitylexicon" 14 + ) 15 + 16 + // A job listing 17 + type Listing struct { 18 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.atwork.listing"` 19 + // applyLink: URL where applicants can apply for the job. 20 + ApplyLink *string `json:"applyLink,omitempty" cborgen:"applyLink,omitempty"` 21 + // banner: Larger horizontal image to display behind job listing view. 22 + Banner *lexutil.LexBlob `json:"banner,omitempty" cborgen:"banner,omitempty"` 23 + // description: The description of the job listing. 24 + Description string `json:"description" cborgen:"description"` 25 + // facets: Annotations of text (mentions, URLs, hashtags, etc). 26 + Facets []appbsky.RichtextFacet `json:"facets,omitempty" cborgen:"facets,omitempty"` 27 + // locations: Locations that are relevant to the job listing. 28 + Locations []Listing_Locations_Elem `json:"locations,omitempty" cborgen:"locations,omitempty"` 29 + // notAfter: Client-declared timestamp when the job listing expires. 30 + NotAfter string `json:"notAfter" cborgen:"notAfter"` 31 + // notBefore: Client-declared timestamp when the job listing becomes visible. 32 + NotBefore string `json:"notBefore" cborgen:"notBefore"` 33 + // title: The title of the job listing. 34 + Title string `json:"title" cborgen:"title"` 35 + } 36 + 37 + type Listing_Locations_Elem struct { 38 + LocationHthree *communitylexicon.LocationHthree 39 + } 40 + 41 + func (t *Listing_Locations_Elem) MarshalJSON() ([]byte, error) { 42 + if t.LocationHthree != nil { 43 + t.LocationHthree.LexiconTypeID = "community.lexicon.location.hthree" 44 + return json.Marshal(t.LocationHthree) 45 + } 46 + return nil, fmt.Errorf("can not marshal empty union as JSON") 47 + } 48 + 49 + func (t *Listing_Locations_Elem) UnmarshalJSON(b []byte) error { 50 + typ, err := lexutil.TypeExtract(b) 51 + if err != nil { 52 + return err 53 + } 54 + 55 + switch typ { 56 + case "community.lexicon.location.hthree": 57 + t.LocationHthree = new(communitylexicon.LocationHthree) 58 + return json.Unmarshal(b, t.LocationHthree) 59 + default: 60 + return nil 61 + } 62 + }
+31
placeatwork/profile.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: place.atwork.profile 4 + 5 + package placeatwork 6 + 7 + import ( 8 + appbsky "github.com/bluesky-social/indigo/api/bsky" 9 + lexutil "github.com/bluesky-social/indigo/lex/util" 10 + ) 11 + 12 + // A user profile for AT://Work.Place 13 + type Profile struct { 14 + LexiconTypeID string `json:"$type" cborgen:"$type,const=place.atwork.profile"` 15 + // avatar: Small image to be displayed next to job listings from account. AKA, 'profile picture' 16 + Avatar *lexutil.LexBlob `json:"avatar,omitempty" cborgen:"avatar,omitempty"` 17 + // banner: Larger horizontal image to display behind profile view. 18 + Banner *lexutil.LexBlob `json:"banner,omitempty" cborgen:"banner,omitempty"` 19 + // description: A free text description of the identity. 20 + Description *string `json:"description,omitempty" cborgen:"description,omitempty"` 21 + // displayName: The display name of the identity. 22 + DisplayName *string `json:"displayName,omitempty" cborgen:"displayName,omitempty"` 23 + // facets: Annotations of text (mentions, URLs, hashtags, etc) in the description. 24 + Facets []appbsky.RichtextFacet `json:"facets,omitempty" cborgen:"facets,omitempty"` 25 + // profile_host: The service used for profile links 26 + Profile_host *string `json:"profile_host,omitempty" cborgen:"profile_host,omitempty"` 27 + // resume: The identity's resume. 28 + Resume *lexutil.LexBlob `json:"resume,omitempty" cborgen:"resume,omitempty"` 29 + // status: The current status of the identity. 30 + Status *string `json:"status,omitempty" cborgen:"status,omitempty"` 31 + }
+46
placeatwork/searchListings.go
··· 1 + // Code generated by indigo lexgen tool. DO NOT EDIT MANUALLY. 2 + 3 + // Lexicon schema: place.atwork.searchListings 4 + 5 + package placeatwork 6 + 7 + import ( 8 + "context" 9 + 10 + lexutil "github.com/bluesky-social/indigo/lex/util" 11 + ) 12 + 13 + // SearchListings_Output is the output of a place.atwork.searchListings call. 14 + type SearchListings_Output struct { 15 + Listings []SearchListings_ListingRecord `json:"listings" cborgen:"listings"` 16 + } 17 + 18 + // SearchListings calls the XRPC method "place.atwork.searchListings". 19 + // 20 + // # Search job listings using full-text query 21 + // 22 + // query: Search query string for full-text search 23 + func SearchListings(ctx context.Context, c lexutil.LexClient, query string) (*SearchListings_Output, error) { 24 + var out SearchListings_Output 25 + 26 + params := map[string]interface{}{} 27 + params["query"] = query 28 + 29 + if err := c.LexDo(ctx, lexutil.Query, "", "place.atwork.searchListings", params, nil, &out); err != nil { 30 + return nil, err 31 + } 32 + return &out, nil 33 + } 34 + 35 + // SearchListings_ListingRecord is a "listingRecord" in the place.atwork.searchListings schema. 36 + // 37 + // A job listing record with metadata for strong references 38 + type SearchListings_ListingRecord struct { 39 + LexiconTypeID string `json:"$type,omitempty" cborgen:"$type,const=place.atwork.searchListings#listingRecord,omitempty"` 40 + // cid: CID of the listing record 41 + Cid string `json:"cid" cborgen:"cid"` 42 + // uri: AT-URI of the listing (at://did/place.atwork.listing/rkey) 43 + Uri string `json:"uri" cborgen:"uri"` 44 + // value: The full job listing record 45 + Value *Listing `json:"value,omitempty" cborgen:"value,omitempty"` 46 + }