Changeset 19a9a1e in Klonkt
- Timestamp:
- 08/15/2026 07:43:02 AM (4 weeks ago)
- Branches:
- main
- Children:
- bec9001
- Parents:
- e1da6a1
- Files:
-
- 4 edited
-
src/services/ap-core.js (modified) (3 diffs)
-
src/services/music/index.js (modified) (1 diff)
-
test/ap-collection-paging.test.js (modified) (1 diff)
-
test/ap-library.test.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ap-core.js
re1da6a1 r19a9a1e 265 265 * en zonder `next`. Hem naar de laatste pagina terugbuigen zou opnieuw een 266 266 * antwoord zijn dat over zichzelf liegt. 267 */ 268 export function pagedCollection(id, items, { totalItems, page = false, perPage = PAGINA_GROOTTE, alGesneden = false, extra = {} } = {}) { 267 * 268 * `ongeordend` maakt er de NIET-geordende vorm van: `Collection` met 269 * `CollectionPage` en `items`, in plaats van `OrderedCollection` met 270 * `OrderedCollectionPage` en `orderedItems`. Dat is geen dialect maar de andere 271 * helft van AS2 -- en de bibliotheek hoort daar: een platenkast heeft geen 272 * volgorde die iets betekent, en `Library` is bij Funkwhale expliciet een 273 * `Collection`. Onze outbox is wél geordend (chronologie is daar de inhoud) en 274 * blijft dus zoals hij was. 275 * 276 * De pagina draagt in die vorm ook `first` en `last`. AS2 staat dat toe -- 277 * CollectionPage erft van Collection -- en een lezer die halverwege binnenkomt 278 * kan zo terug naar het begin zonder eerst de wortel op te halen. 279 */ 280 export function pagedCollection(id, items, { totalItems, page = false, perPage = PAGINA_GROOTTE, alGesneden = false, ongeordend = false, extra = {} } = {}) { 269 281 const lijst = items || []; 270 282 const telling = totalItems === undefined ? lijst.length : totalItems; … … 283 295 '@context': AP_CONTEXT, 284 296 id: url(n), 285 type: 'OrderedCollectionPage',297 type: ongeordend ? 'CollectionPage' : 'OrderedCollectionPage', 286 298 partOf: id, 287 299 totalItems: telling, 300 ...(ongeordend ? { first: url(1), last: url(paginas) } : {}), 301 ...(extra.attributedTo ? { attributedTo: extra.attributedTo } : {}), 288 302 ...(n > 1 ? { prev: url(n - 1) } : {}), 289 303 ...(n < paginas ? { next: url(n + 1) } : {}), 290 orderedItems: deel,304 ...(ongeordend ? { items: deel } : { orderedItems: deel }), 291 305 }; 292 306 } … … 294 308 '@context': AP_CONTEXT, 295 309 id, 296 type: 'OrderedCollection',310 type: ongeordend ? 'Collection' : 'OrderedCollection', 297 311 ...extra, 298 312 totalItems: telling, 299 313 first: url(1), 300 314 last: url(paginas), 301 orderedItems: lijst,315 ...(ongeordend ? { items: lijst } : { orderedItems: lijst }), 302 316 }; 303 317 } -
src/services/music/index.js
re1da6a1 r19a9a1e 253 253 return pagedCollection(id, items, { 254 254 page, 255 // Een platenkast is geen tijdlijn: `Collection`, niet `OrderedCollection`. 256 // Funkwhale's LibrarySerializer accepteert ook alleen die twee typen 257 // (as:Collection of fw:Library) en zijn CollectionPageSerializer alleen 258 // `CollectionPage` met `items`. 259 ongeordend: true, 255 260 extra: { 256 261 type: 'Library', 257 262 name: site.title || site.slug, 258 263 attributedTo: actorId(base, site.slug), 264 // WAAROM DIT VELD ER MOET STAAN. Funkwhale's LibrarySerializer noemt 265 // `audience` optioneel, maar zijn create() doet er meteen 266 // `privacy[validated_data["audience"]]` mee -- zonder de sleutel is dat 267 // een KeyError en geeft hun server een 500. Dat is wat open.audio op 15-8 268 // teruggaf toen Robin onze library-URI daar opzocht. 269 // 270 // Het is bovendien gewoon waar: alles hierin is fedi_open, dus openbaar. 271 // Bij hen is dit precies het verschil tussen privacy_level 'everyone' en 272 // 'me' -- oftewel of onze nummers daar afspeelbaar zijn. 273 audience: 'https://www.w3.org/ns/activitystreams#Public', 259 274 // Vereist volgens hun docs. Openbaar, dus de telling is eerlijk en de 260 275 // lijst blijft leeg -- wie ons volgt volgt de ACTOR, niet de bak. -
test/ap-collection-paging.test.js
re1da6a1 r19a9a1e 84 84 assert.notEqual(pagina.body.id, wortel.body.id, `${pad}: pagina deelt zijn id met de collectie`); 85 85 86 // En hij mag niet zelf weer een `first` dragen -- dat is de lus waar 87 // open.audio in liep. 88 assert.equal(pagina.body.first, undefined, `${pad}: de pagina draagt zelf een first`); 86 // Een pagina MAG `first` dragen (AS2: CollectionPage erft van Collection, 87 // en Funkwhale eist het zelfs op library-pagina's). Wat niet mag is een 88 // `next` naar zichzelf: dat is de lus, en die zit in de verwijzing die een 89 // lezer volgt, niet in de aanwezigheid van het veld. 90 assert.notEqual(pagina.body.next, eerste, `${pad}: next wijst naar de pagina zelf`); 91 92 // De items horen bij het type: geordend -> orderedItems, ongeordend -> 93 // items. Een `Collection` met `orderedItems` is voor een strikte lezer leeg. 94 const sleutel = pagina.body.type === 'CollectionPage' ? 'items' : 'orderedItems'; 95 assert.ok(Array.isArray(pagina.body[sleutel]), `${pad}: ${pagina.body.type} zonder ${sleutel}`); 89 96 }); 90 97 } -
test/ap-library.test.js
re1da6a1 r19a9a1e 53 53 // van de bak zijn poort overrulen. 54 54 const lib = AP.buildLibrary(BASE, site, AP.siteOpenTracks('s1')); 55 assert.deepEqual(lib. orderedItems.map((a) => a.name), ['Het open nummer']);55 assert.deepEqual(lib.items.map((a) => a.name), ['Het open nummer']); 56 56 }); 57 57 … … 59 59 // Dit is het veld waar het om begonnen was: het haakje waar een upload aan komt. 60 60 const lib = AP.buildLibrary(BASE, site, AP.siteOpenTracks('s1')); 61 for (const a of lib. orderedItems) assert.equal(a.library, LIB);61 for (const a of lib.items) assert.equal(a.library, LIB); 62 62 // Ook als de track ergens anders vandaan komt -- de losse ophaal, de 63 63 // trackcollectie, de playlist. Anders hangt het er maar op een plek. 64 64 const los = AP.buildTrackAudio(BASE, site, AP.openTrack('s1', 't1'), { standalone: true }); 65 65 assert.equal(los.library, LIB); 66 }); 67 68 // Wat hun serializers WERKELIJK eisen, uit de bron en niet uit de docs. 69 // api/funkwhale_api/federation/serializers.py op develop, gelezen 15-8: 70 // 71 // LibrarySerializer(PaginatedCollectionSerializer) regel 1071 72 // type in [as:Collection, fw:Library] · name · id · first · last · totalItems 73 // audience: ChoiceField(required=False) MAAR create() doet 74 // privacy[validated_data["audience"]] -- ontbreekt de sleutel, dan een 75 // KeyError en dus een 500. Zo gaf open.audio op 15-8 een 500 op onze URL. 76 // en het is de schakel naar privacy_level 'everyone' == afspeelbaar. 77 // 78 // CollectionPageSerializer regel 1157 79 // type == as:CollectionPage (NIET OrderedCollectionPage) · items (NIET 80 // orderedItems) · id · first · last · partOf · totalItems 81 // 82 // Deze test staat er omdat die eisen nergens anders bij ons zijn opgeschreven. 83 // Zonder hem is het volgende dat iemand de bibliotheek 'opruimt' naar de 84 // gewone OrderedCollection-vorm, en dan is hij daar stil weer leeg. 85 test('de bibliotheek voldoet aan Funkwhale LibrarySerializer', () => { 86 const lib = AP.buildLibrary(BASE, site, AP.siteOpenTracks('s1')); 87 assert.equal(lib.audience, 'https://www.w3.org/ns/activitystreams#Public', 88 'zonder audience een KeyError in hun create() -- 500'); 89 assert.ok(Array.isArray(lib.items), 'Collection draagt items, geen orderedItems'); 90 assert.equal(lib.orderedItems, undefined); 91 for (const veld of ['id', 'name', 'first', 'last', 'totalItems', 'attributedTo']) { 92 assert.ok(lib[veld] !== undefined, `${veld} ontbreekt`); 93 } 94 }); 95 96 test('een bibliotheekpagina voldoet aan Funkwhale CollectionPageSerializer', () => { 97 const p = AP.buildLibrary(BASE, site, AP.siteOpenTracks('s1'), { page: 1 }); 98 assert.equal(p.type, 'CollectionPage', 'OrderedCollectionPage wijzen ze af'); 99 assert.ok(Array.isArray(p.items), 'items, niet orderedItems'); 100 assert.equal(p.orderedItems, undefined); 101 assert.equal(p.partOf, LIB); 102 assert.equal(p.id, `${LIB}?page=1`); 103 for (const veld of ['first', 'last', 'totalItems']) { 104 assert.ok(p[veld] !== undefined, `${veld} ontbreekt op de pagina`); 105 } 66 106 }); 67 107
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)