The ToniesLoader plugin provides cached access to the Tonies JSON database from the Team RevvoX toniebox-reverse-engineering project. It automatically downloads, caches, and provides a query API for both V1 and V2 tonies.json formats.
- Automatic Downloads: Fetches latest tonies.json and toniesV2.json from GitHub
- Smart Caching: 24-hour cache with automatic refresh using
context.download_and_cache() - Fallback Data: Bundled JSON files as fallback using
context.get_resource_path() - Thread-Safe: Safe for concurrent access
- Query API: Search methods for both V1 and V2 formats
- Service-Based: Registered as shared service accessible by all plugins
- Launch TonieToolbox GUI:
tonietoolbox --gui - Open Tools → Plugin Manager
- Go to Discover tab
- Search for "Tonies Loader"
- Click Install
cd ~/.tonietoolbox/plugins/
git clone https://github.com/TonieToolbox/plugin_tonies_loader.git tonies_loaderAfter installation, enable the plugin in the Plugin Manager or via config.json.
# In your plugin's initialize() method:
tonies_service = context.get_service('tonies_loader')
if tonies_service:
# Query by audio ID
tonie = tonies_service.get_v1_by_audio_id(1490952835)
print(f"Found: {tonie.get('series')} - {tonie.get('episodes')}")
# Search by series
tonies = tonies_service.get_v1_by_series("Bibi", partial=True)
print(f"Found {len(tonies)} Bibi tonies")
# Get by hash
tonie = tonies_service.get_v1_by_hash("43B590E78F561BD167A75D698B19C07323F766D6")get_v1_by_audio_id(audio_id: int)- Find tonie by audio IDget_v1_by_hash(hash_value: str)- Find tonie by hash (case-insensitive)get_v1_by_model(model: str)- Find tonies by model numberget_v1_by_series(series: str, partial: bool = True)- Find tonies by series nameget_v1_by_category(category: str)- Find tonies by categoryget_v1_by_episodes(episodes: str, partial: bool = True)- Find tonies by episode nameget_all_v1_tonies()- Get all V1 toniesget_v1_categories()- Get list of all V1 categories
get_v2_by_audio_id(audio_id: int)- Find article by audio IDget_v2_by_hash(hash_value: str)- Find article by hash (case-insensitive)get_v2_by_model(model: str)- Find articles by article/model numberget_v2_by_series(series: str, partial: bool = True)- Find articles by series nameget_v2_by_category(category: str)- Find articles by categoryget_v2_by_episodes(episode: str, partial: bool = True)- Find articles by episode nameget_all_v2_tonies()- Get all V2 articlesget_v2_categories()- Get list of all V2 categories
Default: ~/.tonietoolbox/cache/tonies_loader/
Cache files:
tonies_v1.json- Cached V1 datatonies_v2.json- Cached V2 data
Cache timestamps are stored in file metadata (modification time).
- Duration: 24 hours (configurable via
cache_ttlsetting) - Refresh: Automatic when cache expires (if
auto_updateis enabled) - Fallback Order:
- Download from GitHub
- Use stale cache if download fails
- Use bundled data if no cache exists
To force a cache refresh, delete the cached files:
rm ~/.tonietoolbox/cache/tonies_loader/*.jsonNext time the plugin loads, it will download fresh data from GitHub.
- V1: https://raw.githubusercontent.com/toniebox-reverse-engineering/tonies-json/release/tonies.json
- V2: https://raw.githubusercontent.com/toniebox-reverse-engineering/tonies-json/release/toniesV2.json
Bundled fallback data is included in the plugin directory.
tonies_service = context.get_service('tonies_loader')
tonie = tonies_service.get_v1_by_audio_id(1490952835)
if tonie:
print(f"Series: {tonie.get('series')}")
print(f"Episode: {tonie.get('episodes')}")
print(f"Model: {tonie.get('model')}")
print(f"Language: {tonie.get('language')}")
print(f"Category: {tonie.get('category')}")tonies_service = context.get_service('tonies_loader')
# Partial match (case-insensitive)
bibi_tonies = tonies_service.get_v1_by_series("Bibi", partial=True)
for tonie in bibi_tonies[:5]: # First 5 results
print(f"{tonie.get('model')}: {tonie.get('series')} - {tonie.get('episodes')}")tonies_service = context.get_service('tonies_loader')
# Read audio_id from TAF file
audio_id = extract_audio_id_from_taf(taf_path)
# Look up in database
tonie_v1 = tonies_service.get_v1_by_audio_id(audio_id)
tonie_v2 = tonies_service.get_v2_by_audio_id(audio_id)
if tonie_v1:
print(f"✅ Valid Tonie: {tonie_v1.get('series')}")
else:
print("❌ Unknown Tonie audio ID")tonies_service = context.get_service('tonies_loader')
categories = tonies_service.get_v1_categories()
print(f"Available categories: {', '.join(categories)}")
# Get all tonies in a category
audiobooks = tonies_service.get_v1_by_category("Audiobook")
print(f"Found {len(audiobooks)} audiobooks")Current database size (as of bundled data):
- V1 tonies: 6,135 entries
- V2 articles: 6,128 entries
The plugin registers itself as a shared service during initialization:
context.register_service('tonies_loader', service_instance)This makes it accessible from any plugin via:
service = context.get_service('tonies_loader')All query methods are thread-safe. Downloads use a lock to prevent concurrent download attempts.
The plugin can be configured via ~/.tonietoolbox/config.json:
{
"plugins": {
"com.tonietoolbox.tonies_loader": {
"cache_ttl": 86400,
"auto_update": true
}
}
}| Option | Type | Default | Description |
|---|---|---|---|
cache_ttl |
integer | 86400 |
Cache time-to-live in seconds (24 hours) |
auto_update |
boolean | true |
Automatically download updated tonies.json on startup if cache is stale |
Disable automatic updates:
{
"plugins": {
"com.tonietoolbox.tonies_loader": {
"auto_update": false
}
}
}Set cache to 7 days:
{
"plugins": {
"com.tonietoolbox.tonies_loader": {
"cache_ttl": 604800
}
}
}Disable the plugin:
{
"plugins": {
"disabled_plugins": ["com.tonietoolbox.tonies_loader"]
}
}- Data source: toniebox-reverse-engineering/tonies-json
For issues or questions about the plugin, please open an issue on the TonieToolbox repository.