Skip to content

Add streaming media support for OPDS for Distributors (PP-3590)#3015

Merged
jonathangreen merged 3 commits intomainfrom
feature/opds-distributors-streaming-media
Feb 3, 2026
Merged

Add streaming media support for OPDS for Distributors (PP-3590)#3015
jonathangreen merged 3 commits intomainfrom
feature/opds-distributors-streaming-media

Conversation

@jonathangreen
Copy link
Member

@jonathangreen jonathangreen commented Jan 30, 2026

Description

Add support for streaming media formats (e.g., Biblioboard web reader) in OPDS for Distributors feeds. This allows patrons to access streaming content through viewer URLs with authentication tokens appended.

Note

This implementation is specific to Biblioboard and includes hardcoded knowledge such as appending the token query parameter to the viewer URL. Since Biblioboard is currently the only user of the OPDS for Distributors importer, this is acceptable for now. Future work should migrate the Biblioboard feed to the OPDS 2.x importer, where templated links would allow us to generalize this pattern more cleanly.

Motivation and Context

This enables libraries to provide streaming content (text and audio) to patrons through OPDS for Distributors collections. Streaming content is delivered via web viewer URLs that require an OAuth token for authentication. The token is appended to the URL so patrons can access the content directly in their browser.

How Has This Been Tested?

  • Added unit tests for _streaming_format_data method covering:
    • Non-streaming links returning None
    • Audio medium returning STREAMING_AUDIO_CONTENT_TYPE
    • Book medium returning STREAMING_TEXT_CONTENT_TYPE
    • Default to text when medium is not specified
  • Added unit tests for _append_token_to_url with various URL formats
  • Added integration test for fulfill() with streaming delivery mechanism
  • Added tests for streaming format detection in OPDS 1.x extractor for both text and audio content

Checklist

  • I have updated the documentation accordingly.
  • All new and existing tests passed.

@jonathangreen jonathangreen added the feature New feature label Jan 30, 2026
@codecov
Copy link

codecov bot commented Jan 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.03%. Comparing base (17a2e0b) to head (62e6ec0).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3015      +/-   ##
==========================================
+ Coverage   93.02%   93.03%   +0.01%     
==========================================
  Files         481      482       +1     
  Lines       43563    43588      +25     
  Branches     6055     6058       +3     
==========================================
+ Hits        40525    40553      +28     
+ Misses       1965     1964       -1     
+ Partials     1073     1071       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

open_access = False
media_type = None

for link in links:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing this, I updated to just use the url cached on the resource. This is what we do in other apis, and it simplifies the logic here significantly.

<link rel="self" type="application/atom+xml;type=entry;profile=opds-catalog" href="https://catalog.biblioboard.com/opds/items/04377e87-ab69-41c8-a2a4-812d55dc0952"/>
<link rel="http://opds-spec.org/image/thumbnail" type="image/jpeg" href="https://api.biblioboard.com/media/04377e87-ab69-41c8-a2a4-812d55dc0952/assets/thumbnail.jpg"/>
<link rel="http://opds-spec.org/acquisition" type="text/html" href="https://library.biblioboard.com/viewer/04377e87-ab69-41c8-a2a4-812d55dc0952" title="View on BiblioBoard"/>
<link rel="http://opds-spec.org/acquisition" type="text/html;profile=http://librarysimplified.org/terms/profiles/streaming-media" href="https://library.biblioboard.com/viewer/04377e87-ab69-41c8-a2a4-812d55dc0952" title="View on BiblioBoard"/>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the test data in our feed to match whats in the real feeds.

assert (
pool.delivery_mechanisms[0].rights_status.uri
== RightsStatus.IN_COPYRIGHT
# -- Test the Camelot license pool --
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rewrote these tests a bit, the logic was getting a bit tortured, with the iteration of the pools, since each pool has different properties set. I just unrolled the loops, so that we test each one in sequence, so we can test the differences between them.

Add support for streaming media formats (e.g., Biblioboard web reader)
in OPDS for Distributors feeds. This allows patrons to access streaming
content through viewer URLs with authentication tokens.

Changes:
- Add _streaming_format_data method to detect streaming links by their
  media type profile (text/html;profile=...streaming-media)
- Update fulfill() to return StreamingFulfillment for streaming content,
  appending the OAuth token to the viewer URL
- Add STREAMING_MEDIA_LINK_TYPE constant for consistent exact matching
- Allow STREAMING_DRM in can_fulfill_without_loan check
- Extract STREAMING_MEDIA_PROFILE_URI as a reusable constant
@jonathangreen jonathangreen force-pushed the feature/opds-distributors-streaming-media branch from b7647e7 to 62e6ec0 Compare January 30, 2026 19:19
@jonathangreen jonathangreen marked this pull request as ready for review January 30, 2026 19:24
@jonathangreen jonathangreen requested a review from a team January 30, 2026 19:24
Copy link
Contributor

@dbernstein dbernstein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a minor comment: feel free to ignore or fix as you see fit.

if format_data is None:
# Fall back to bearer token format detection
format_data = self._bearer_token_format_data(link)
if format_data is not None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not else instead of if format_data is not None?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format_data = self._bearer_token_format_data(link) could be None as well, so that if always needs to be evaluated

@jonathangreen jonathangreen merged commit a26ae45 into main Feb 3, 2026
20 of 22 checks passed
@jonathangreen jonathangreen deleted the feature/opds-distributors-streaming-media branch February 3, 2026 16:10
jonathangreen added a commit that referenced this pull request Feb 18, 2026
…PP-3684) (#3055)

## Description

> Note: #3035 needs
to get merged before this can go in.

Adds a startup task that dispatches a forced re-harvest of all OPDS for
Distributors collections on the next deployment.

## Motivation and Context

After streaming media support landed (PR #3015), existing OPDS for
Distributors collections need to be re-imported with the new parsing
logic to pick up the changes.

Resolves PP-3684

## How Has This Been Tested?

The startup task follows the established pattern and delegates to the
existing `import_all` Celery task with `force=True`. The `import_all`
task is already covered by existing tests.

## Checklist

- [x] I have updated the documentation accordingly.
- [x] All new and existing tests passed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants