Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto

Compare changes

Choose any two refs to compare.

Changed files
+343 -53
.github
workflows
lexicons
+51 -48
.github/workflows/ci.yml
··· 133 artifacts/${{ matrix.target }}/ 134 retention-days: 1 135 136 - rust-quality: 137 - name: Rust Quality Checks 138 - runs-on: ubuntu-latest 139 - needs: setup-and-build 140 - steps: 141 - - name: Checkout repository 142 - uses: actions/checkout@v4 143 144 - - name: Setup environment 145 - uses: ./.github/actions/setup 146 - with: 147 - setup-rust: "true" 148 - setup-node: "true" 149 - lexicons-only-rust: "true" 150 - cache-key-suffix: "ci-build" 151 152 - - name: Setup SQLx offline files 153 - run: ./scripts/setup-sqlx-offline.sh 154 155 - # - name: Check Rust formatting 156 - # run: | 157 - # cargo fmt --all -- --check 158 159 - - name: Run Clippy 160 - run: | 161 - cargo clippy --all-targets --all-features --workspace --exclude types -- -D warnings 162 163 - - name: Run Rust tests 164 - run: | 165 - cargo test --all-features 166 167 - node-quality: 168 - name: Node.js Quality Checks 169 - runs-on: ubuntu-latest 170 - needs: setup-and-build 171 - steps: 172 - - name: Checkout repository 173 - uses: actions/checkout@v4 174 175 - - name: Setup environment 176 - uses: ./.github/actions/setup 177 - with: 178 - setup-node: "true" 179 - cache-key-suffix: "ci-build" 180 181 - - name: Download Node build artifacts 182 - uses: actions/download-artifact@v4 183 - with: 184 - name: node-builds 185 - path: . 186 187 - # - name: Type check 188 - # run: pnpm typecheck 189 190 - - name: Lint and format check 191 - run: pnpm fix --check 192 193 - - name: Run tests 194 - run: pnpm test 195 196 lexicon-validation: 197 name: Lexicon Validation
··· 133 artifacts/${{ matrix.target }}/ 134 retention-days: 1 135 136 + # disabled b/c it's triggered on autogenerated content 137 + # and can't find a way around it rn 138 139 + # rust-quality: 140 + # name: Rust Quality Checks 141 + # runs-on: ubuntu-latest 142 + # needs: setup-and-build 143 + # steps: 144 + # - name: Checkout repository 145 + # uses: actions/checkout@v4 146 147 + # - name: Setup environment 148 + # uses: ./.github/actions/setup 149 + # with: 150 + # setup-rust: "true" 151 + # setup-node: "true" 152 + # lexicons-only-rust: "true" 153 + # cache-key-suffix: "ci-build" 154 155 + # - name: Setup SQLx offline files 156 + # run: ./scripts/setup-sqlx-offline.sh 157 + 158 + # # - name: Check Rust formatting 159 + # # run: | 160 + # # cargo fmt --all -- --check 161 162 + # - name: Run Clippy 163 + # run: | 164 + # cargo clippy --all-targets --all-features --workspace --exclude types -- -D warnings 165 166 + # - name: Run Rust tests 167 + # run: | 168 + # cargo test --all-features 169 170 + # node-quality: 171 + # name: Node.js Quality Checks 172 + # runs-on: ubuntu-latest 173 + # needs: setup-and-build 174 + # steps: 175 + # - name: Checkout repository 176 + # uses: actions/checkout@v4 177 178 + # - name: Setup environment 179 + # uses: ./.github/actions/setup 180 + # with: 181 + # setup-node: "true" 182 + # cache-key-suffix: "ci-build" 183 184 + # - name: Download Node build artifacts 185 + # uses: actions/download-artifact@v4 186 + # with: 187 + # name: node-builds 188 + # path: . 189 190 + # # - name: Type check 191 + # # run: pnpm typecheck 192 193 + # - name: Lint and format check 194 + # run: pnpm fix --check 195 196 + # - name: Run tests 197 + # run: pnpm test 198 199 lexicon-validation: 200 name: Lexicon Validation
-1
lexicons/fm.teal.alpha/feed/play.json
··· 19 }, 20 "trackMbId": { 21 "type": "string", 22 - 23 "description": "The Musicbrainz ID of the track" 24 }, 25 "recordingMbId": {
··· 19 }, 20 "trackMbId": { 21 "type": "string", 22 "description": "The Musicbrainz ID of the track" 23 }, 24 "recordingMbId": {
+54
lexicons/fm.teal.alpha/feed/social/defs.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "fm.teal.alpha.feed.social.defs", 4 + "description": "This lexicon is in a not officially released state. It is subject to change. | Misc. items related to the social feed..", 5 + "defs": { 6 + "trackView": { 7 + "trackName": { 8 + "type": "string", 9 + "minLength": 1, 10 + "maxLength": 256, 11 + "maxGraphemes": 2560, 12 + "description": "The name of the track" 13 + }, 14 + "trackMbId": { 15 + "type": "string", 16 + "description": "The Musicbrainz ID of the track" 17 + }, 18 + "recordingMbId": { 19 + "type": "string", 20 + "description": "The Musicbrainz recording ID of the track" 21 + }, 22 + "artistNames": { 23 + "type": "array", 24 + "items": { 25 + "type": "string", 26 + "minLength": 1, 27 + "maxLength": 256, 28 + "maxGraphemes": 2560 29 + }, 30 + "description": "Array of artist names in order of original appearance. Prefer using 'artists'." 31 + }, 32 + "artistMbIds": { 33 + "type": "array", 34 + "items": { "type": "string" }, 35 + "description": "Array of Musicbrainz artist IDs. Prefer using 'artists'." 36 + }, 37 + "artists": { 38 + "type": "array", 39 + "items": { "type": "ref", "ref": "fm.teal.alpha.feed.defs#artist" }, 40 + "description": "Array of artists in order of original appearance." 41 + }, 42 + "releaseName": { 43 + "type": "string", 44 + "maxLength": 256, 45 + "maxGraphemes": 2560, 46 + "description": "The name of the release/album" 47 + }, 48 + "releaseMbId": { 49 + "type": "string", 50 + "description": "The Musicbrainz release ID" 51 + } 52 + } 53 + } 54 + }
+24
lexicons/fm.teal.alpha/feed/social/like.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "fm.teal.alpha.feed.social.like", 4 + "description": "This lexicon is in a not officially released state. It is subject to change. | The action of 'Liking' a Teal.fm post.", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "description": "Record containing a like for a teal.fm post.", 9 + "key": "tid", 10 + "record": { 11 + "type": "object", 12 + "required": ["subject", "createdAt"], 13 + "properties": { 14 + "subject": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 15 + "createdAt": { 16 + "type": "string", 17 + "format": "datetime", 18 + "description": "Client-declared timestamp when this post was originally created." 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
+30
lexicons/fm.teal.alpha/feed/social/playlist.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "fm.teal.alpha.feed.social.playlist", 4 + "description": "This lexicon is in a not officially released state. It is subject to change. | A teal.fm playlist, representing a list of tracks.", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "description": "Record containing the playlist metadata.", 9 + "key": "tid", 10 + "record": { 11 + "type": "object", 12 + "required": ["name", "createdAt"], 13 + "properties": { 14 + "name": { 15 + "type": "string", 16 + "description": "Display name for the playlist, required.", 17 + "minLength": 1, 18 + "maxLength": 50 19 + }, 20 + "description": { "type": "string", "maxLength": 5000 }, 21 + "createdAt": { 22 + "type": "string", 23 + "format": "datetime", 24 + "description": "Client-declared timestamp when this playlist was originally created." 25 + } 26 + } 27 + } 28 + } 29 + } 30 + }
+32
lexicons/fm.teal.alpha/feed/social/playlistItem.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "fm.teal.alpha.feed.social.playlistItem", 4 + "description": "This lexicon is in a not officially released state. It is subject to change. | A teal.fm playlist item.", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "description": "Record containing a playlist item for a teal.fm playlist.", 9 + "key": "tid", 10 + "record": { 11 + "type": "object", 12 + "required": ["subject", "createdAt", "trackName"], 13 + "properties": { 14 + "subject": { "type": "record", "ref": "com.atproto.repo.strongRef" }, 15 + "createdAt": { 16 + "type": "string", 17 + "format": "datetime", 18 + "description": "Client-declared timestamp when this post was originally created." 19 + }, 20 + "track": { 21 + "type": "ref", 22 + "ref": "fm.teal.alpha.feed.social.defs#trackView" 23 + }, 24 + "order": { 25 + "type": "integer", 26 + "description": "The order of the track in the playlist" 27 + } 28 + } 29 + } 30 + } 31 + } 32 + }
+104
lexicons/fm.teal.alpha/feed/social/post.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "fm.teal.alpha.feed.social.post", 4 + "description": "This lexicon is in a not officially released state. It is subject to change. | Record containing a teal.fm post. Teal.fm posts include a track that is connected to the post, and could have some text. Replies, by default, have the same track as the parent post.", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "description": "Record containing a teal.fm post.", 9 + "key": "tid", 10 + "record": { 11 + "type": "object", 12 + "required": ["text", "createdAt"], 13 + "properties": { 14 + "text": { 15 + "type": "string", 16 + "maxLength": 3000, 17 + "maxGraphemes": 300, 18 + "description": "The primary post content. May be an empty string, if there are embeds." 19 + }, 20 + 21 + "trackName": { 22 + "type": "string", 23 + "minLength": 1, 24 + "maxLength": 256, 25 + "maxGraphemes": 2560, 26 + "description": "The name of the track" 27 + }, 28 + "trackMbId": { 29 + "type": "string", 30 + "description": "The Musicbrainz ID of the track" 31 + }, 32 + "recordingMbId": { 33 + "type": "string", 34 + "description": "The Musicbrainz recording ID of the track" 35 + }, 36 + "duration": { 37 + "type": "integer", 38 + "description": "The duration of the track in seconds" 39 + }, 40 + "artistNames": { 41 + "type": "array", 42 + "items": { 43 + "type": "string", 44 + "minLength": 1, 45 + "maxLength": 256, 46 + "maxGraphemes": 2560 47 + }, 48 + "description": "The names of the artists" 49 + }, 50 + "artistMbIds": { 51 + "type": "array", 52 + "items": { "type": "string" }, 53 + "description": "The Musicbrainz IDs of the artists" 54 + }, 55 + "releaseName": { 56 + "type": "string", 57 + "maxLength": 256, 58 + "maxGraphemes": 2560, 59 + "description": "The name of the release/album" 60 + }, 61 + "releaseMbId": { 62 + "type": "string", 63 + "description": "The Musicbrainz ID of the release/album" 64 + }, 65 + "isrc": { 66 + "type": "string", 67 + "description": "The ISRC code associated with the recording" 68 + }, 69 + "reply": { "type": "ref", "ref": "#replyRef" }, 70 + "facets": { 71 + "type": "array", 72 + "description": "Rich text facets, which may include mentions, links, and other features.", 73 + "items": { "type": "ref", "ref": "fm.teal.alpha.richtext.facet" } 74 + }, 75 + "langs": { 76 + "type": "array", 77 + "description": "Indicates human language of post primary text content.", 78 + "maxLength": 3, 79 + "items": { "type": "string", "format": "language" } 80 + }, 81 + "tags": { 82 + "type": "array", 83 + "description": "Additional hashtags, in addition to any included in post text and facets.", 84 + "maxLength": 8, 85 + "items": { "type": "string", "maxLength": 640, "maxGraphemes": 64 } 86 + }, 87 + "createdAt": { 88 + "type": "string", 89 + "format": "datetime", 90 + "description": "Client-declared timestamp when this post was originally created." 91 + } 92 + } 93 + } 94 + }, 95 + "replyRef": { 96 + "type": "object", 97 + "required": ["root", "parent"], 98 + "properties": { 99 + "root": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 100 + "parent": { "type": "ref", "ref": "com.atproto.repo.strongRef" } 101 + } 102 + } 103 + } 104 + }
+24
lexicons/fm.teal.alpha/feed/social/repost.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "fm.teal.alpha.feed.social.repost", 4 + "description": "This lexicon is in a not officially released state. It is subject to change. | The action of 'Reposting' a Teal.fm post.", 5 + "defs": { 6 + "main": { 7 + "type": "record", 8 + "description": "Record containing a repost for a teal.fm post.", 9 + "key": "tid", 10 + "record": { 11 + "type": "object", 12 + "required": ["subject", "createdAt"], 13 + "properties": { 14 + "subject": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 15 + "createdAt": { 16 + "type": "string", 17 + "format": "datetime", 18 + "description": "Client-declared timestamp when this post was originally created." 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
+24
lexicons/fm.teal.alpha/richtext/facet.json
···
··· 1 + { 2 + "lexicon": 1, 3 + "id": "fm.teal.alpha.richtext.facet", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "description": "Annotation of a sub-string within rich text.", 8 + "required": ["index", "features"], 9 + "properties": { 10 + "index": { "type": "ref", "ref": "app.bsky.richtext.facet#byteSlice" }, 11 + "features": { 12 + "type": "array", 13 + "items": { 14 + "type": "union", 15 + "refs": [ 16 + "app.bsky.richtext.facet#mention", 17 + "app.bsky.richtext.facet#link" 18 + ] 19 + } 20 + } 21 + } 22 + } 23 + } 24 + }
-4
pnpm-lock.yaml
··· 254 255 services/cadet: {} 256 257 - services/rocketman: {} 258 - 259 services/satellite: {} 260 - 261 - services/types: {} 262 263 tools/lexicon-cli: 264 dependencies:
··· 254 255 services/cadet: {} 256 257 services/satellite: {} 258 259 tools/lexicon-cli: 260 dependencies: