Skip to main content

Python client for working with iBroadcast music collections

Project description

iBroadcast Python client

This Python package provides a client for working with iBroadcast music collections via the iBroadcast JSON API.

Setup

Stable version

To install the latest release into your local environment:

pip install ibroadcast

Development version

To install the latest development version from source:

git clone https://github.com/ctrueden/ibroadcast-python
cd ibroadcast-python
pip install -e .

Usage

Authentication

This library uses OAuth 2 for authentication. You will need a client_id from iBroadcast (see Creating an App).

Device Code Flow (recommended for CLI apps)

>>> import ibroadcast
>>> ib = ibroadcast.from_device_code(
...     client_id='your_client_id',
...     scopes=['user.library:read', 'user.library:write', 'user.upload'],
... )
To authorize, visit: https://oauth.ibroadcast.com/device
And enter code: ABCD-1234

Waiting for authorization...

Authorization Code Flow (for apps with a browser redirect)

>>> import ibroadcast
>>> # Step 1: Generate PKCE verifier and challenge
>>> verifier = ibroadcast.generate_code_verifier()
>>> challenge = ibroadcast.generate_code_challenge(verifier)
>>> # Step 2: Build the authorization URL and direct the user to it
>>> url = ibroadcast.build_authorize_url(
...     client_id='your_client_id',
...     state='random_state_string',
...     code_challenge=challenge,
...     scopes=['user.library:read', 'user.library:write'],
...     redirect_uri='https://your-app.com/callback',
... )
>>> # Step 3: After user authorizes, exchange the code
>>> ib = ibroadcast.from_auth_code(
...     client_id='your_client_id',
...     code='authorization_code_from_redirect',
...     redirect_uri='https://your-app.com/callback',
...     code_verifier=verifier,
... )

Using existing tokens

>>> import ibroadcast
>>> ib = ibroadcast.iBroadcast(
...     access_token='your_access_token',
...     refresh_token='your_refresh_token',
...     client_id='your_client_id',
... )

Saving and restoring tokens

>>> # Save tokens for later use
>>> token_dict = ib.token_set.to_dict()
>>> # ... persist token_dict to file ...
>>> # Restore from saved tokens
>>> ib = ibroadcast.from_token_set(token_dict, client_id='your_client_id')

Download library data

After authenticating, download your library data:

>>> ib.refresh()

Query tracks

Track data can be found in ib.tracks.

Here is an example that lists tracks from the year 1984:

>>> from pprint import pprint
>>> tracks_from_1984 = [track for (trackid, track) in ib.tracks.items() if track['year'] == 1984]
>>> pprint(tracks_from_1984)
[{'album_id': 49436760,
  'artist_id': 17407280,
  'artwork_id': 1892638,
  'enid': 0,
  'file': '/128/a8b/567/150924731',
  'genre': 'Pop',
  'length': 205,
  'path': 'music/Artists/Kansas/(1984) The Best of Kansas',
  'plays': 1,
  'rating': 0,
  'replay_gain': '0.5',
  'size': 3572231,
  'title': 'Dust in the Wind',
  'track': 4,
  'trashed': False,
  'type': 'audio/mpeg3',
  'uid': '',
  'uploaded_on': '2020-12-10',
  'uploaded_time': '16:09:59',
  'year': 1984},
 {'album_id': 49438358,
  'artist_id': 17407663,
  'artwork_id': 465315,
  'enid': 0,
  'file': '/128/962/d79/150926596',
  'genre': 'New Wave, Post-Punk, Rock, Funk',
  'length': 307,
  'path': 'music/Artists/Talking Heads/(1984) Stop Making Sense',
  'plays': 1,
  'rating': 0,
  'replay_gain': '0.8',
  'size': 6510922,
  'title': 'Girlfriend Is Better',
  'track': 5,
  'trashed': False,
  'type': 'audio/mpeg3',
  'uid': '',
  'uploaded_on': '2020-12-10',
  'uploaded_time': '16:14:56',
  'year': 1984}]

Query albums

Album data can be found in ib.albums.

Here is an example that lists albums from the year 1984:

>>> albums_from_1984 = [album for (albumid, album) in ib.albums.items() if album['year'] == 1984]
>>> pprint(albums_from_1984)
[{'artist_id': 17407663,
  'disc': 1,
  'name': 'Stop Making Sense',
  'rating': 0,
  'tracks': [189817292],
  'trashed': False,
  'year': 1984},
 {'artist_id': 17407280,
  'disc': 1,
  'name': 'The Best of Kansas',
  'rating': 0,
  'tracks': [189815191],
  'trashed': False,
  'year': 1984}]

Query artists

Artist data can be found in ib.artists.

Here is an example that lists artists with more than 170 tracks:

>>> [artist['name'] for artist in ib.artists.values() if len(artist['tracks']) >= 170]
['Scooter', 'Megadeth', 'Bad Religion', 'Metallica', 'Green Day']

Query playlists

Playlist data can be found in ib.playlists.

Here is an example that lists the names of all playlists:

>>> [playlist['name'] for playlist in ib.playlists.values()]
['Jonathan Hall', 'Army of Hardcore', 'Most Recent Uploads', 'Recently Played', 'Stand Up', 'Roads Untraveled', 'The Storm', 'Thumbs Up']

Here's an example that lists the track names of a particular playlist:

>>> def track2string(ib, track):
...   title = track['title']
...   artistid = track['artist_id']
...   artist = ib.artist(artistid)
...   return f"{artist['name']} - {title}"
...
>>> thumbsup = next(pl for pl in ib.playlists.values() if pl['name'] == 'Thumbs Up')
>>> for trackid in thumbsup['tracks']:
...   track = ib.track(trackid)
...   print(track2string(ib, track))
...
Ozzy Osbourne - I Don't Know
ELLEGARDEN - Mr. Feather
The Dreaming - Become Like You
RMB - Everything (Can't Hide version)
Linkin Park - The Catalyst
Breathe Carolina - Blackout
Lady Gaga - Swine
Adam Lambert - Feeling Good
Virtual Riot - Energy Drink
Jim Yosef - Link
MDK - Hyper Beam
Hybrid - I Know

Query tags

Tag data can be found in ib.tags.

Here is an example that lists all tracks tagged "favorites" from 2010 or later:

>>> favorite_trackids = next(tag['tracks'] for tag in ib.tags.values() if tag['name'] == 'favorites')
>>> for trackid in favorite_trackids:
...   track = ib.track(trackid)
...   year = track['year']
...   if year < 2010: continue
...   print(f"[{year}] {track2string(ib, track)}")
...
[2010] Bad Religion - Only Rain
[2016] Green Day - Still Breathing
[2012] The Offspring - Dirty Magic
[2012] Imagine Dragons - Radioactive
[2013] All Time Low - Fool's Holiday
[2013] Michael Bublé - It's a Beautiful Day
[2010] Kerry Ellis - Defying Gravity
[2010] Glee Cast - Defying Gravity
[2013] Kristen AndersonLopez & Robert Lopez - Let It Go
[2014] The Glitch Mob feat. Aja Volkman - Our Demons
[2012] Great Big Sea - Run Runaway
[2010] Andrew Lippa - Happy / Sad

Available iBroadcast API methods

>>> help(ib)
Help on iBroadcast in module ibroadcast object:

class iBroadcast(builtins.object)
 |  iBroadcast(access_token=None, refresh_token=None, client_id=None,
 |      token_refreshed_callback=None, client='ibroadcast-python',
 |      version='2.0.0', device_name=None, log=None)
 |
 |  Class for making iBroadcast requests.
 |
 |  Class methods:
 |
 |  from_device_code(client_id, scopes, on_device_code=None, **kwargs)
 |      Authenticate via the OAuth 2 Device Code Flow.
 |
 |  from_auth_code(client_id, code, redirect_uri, code_verifier, **kwargs)
 |      Authenticate via the OAuth 2 Authorization Code Flow.
 |
 |  from_token_set(token_set, client_id=None, **kwargs)
 |      Create an instance from a previously saved TokenSet.
 |
 |  Methods defined here:
 |
 |  addtracks(self, playlistid, trackids)
 |      Add tracks to the given playlist.
 |
 |  album(self, albumid)
 |      Get the album object with the given ID.
 |
 |  artist(self, artistid)
 |      Get the artist object with the given ID.
 |
 |  createplaylist(self, name, description='', sharable=False, mood=None)
 |      Create a playlist.
 |
 |  createtag(self, tagname)
 |      Create a tag.
 |
 |  deleteplaylist(self, playlistid)
 |      Delete a playlist.
 |
 |  extensions(self)
 |      Get file extensions for supported audio formats.
 |
 |  get_status(self)
 |      Fetch user status/info from the API.
 |
 |  gettags(self, trackid)
 |      Get the tags for the given track.
 |
 |  istagged(self, tagid, trackid)
 |      Get whether the specified track has the given tag.
 |
 |  isuploaded(self, filepath)
 |      Get whether a given file is already uploaded to the iBroadcast server.
 |
 |  playlist(self, playlistid)
 |      Get the playlist object with the given ID.
 |
 |  refresh(self)
 |      Download library data: albums, artists, tracks, etc.
 |
 |  settracks(self, playlistid, trackids)
 |      Update the given playlist to consist of the specified tracks.
 |
 |  tag(self, tagid)
 |      Get the tag object with the given ID.
 |
 |  tagtracks(self, tagid, trackids, untag=False)
 |      Apply or remove the given tag to the specified tracks.
 |
 |  track(self, trackid)
 |      Get the track object with the given ID.
 |
 |  trash(self, trackids)
 |      Move the given tracks to the trash.
 |
 |  upload(self, filepath, label=None, force=False)
 |      Upload the given file to iBroadcast, if it isn't there already.

Getting help

File an issue in the issue tracker.

Contributing

PRs welcome! ^.~

Testing changes

This project has no unit tests, but there are integration tests. They require a valid OAuth 2 access token or client ID for iBroadcast. All of the integration tests are read-only.

$ IBROADCAST_CLIENT_ID=your_client_id uv run tests/integration.py
INFO:root:iBroadcast integration tests

To authorize, visit: https://oauth.ibroadcast.com/device
And enter code: ABCD-1234

Waiting for authorization...
INFO:root:Downloading library data...
INFO:root:Checked 995 albums totaling 5951 tracks.
.INFO:root:Checked 1790 artists totaling 5951 tracks.
...INFO:root:Downloading MD5 checksums...
INFO:root:Returning list of md5 checksums from server
.INFO:root:Checked 8 playlists totaling 1691 tracks.
.INFO:root:Checked 17 tags totaling 2208 tracks.
INFO:root:Checked 5951 tracks.
..
----------------------------------------------------------------------
Ran 10 tests in 0.567s

OK

Or with an existing access token:

$ IBROADCAST_ACCESS_TOKEN=your_token uv run tests/integration.py

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ibroadcast-2.0.1.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ibroadcast-2.0.1-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

File details

Details for the file ibroadcast-2.0.1.tar.gz.

File metadata

  • Download URL: ibroadcast-2.0.1.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for ibroadcast-2.0.1.tar.gz
Algorithm Hash digest
SHA256 5a2f3de35767086a91415f8d945aeac4ad874b05ed5ea2eddc5c2944ecf5e112
MD5 f63560e45ae90c328bd672509c1d526d
BLAKE2b-256 eab4f6ace80b4364f0e7fd6c5218568d56eb1e92b60e41dbeee2f86b9378b20c

See more details on using hashes here.

File details

Details for the file ibroadcast-2.0.1-py3-none-any.whl.

File metadata

  • Download URL: ibroadcast-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 12.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for ibroadcast-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b4eb150411947b805812ecb42c7ca6ffb6cc95104f6fc66ca5cb23475c27ff9a
MD5 7118abe7e8ea928a947cfc90c67f6f3c
BLAKE2b-256 145c2b184c846b8153dcedd41c689c8477cfed02bb9d243684b9f9fa9808c270

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page