Expansion of tonie.json with API data from your own Tonie account
📌 Goal The local file tonie.json currently contains only limited information about Tonie figures. I suggest automatically expanding or replacing this file by obtaining missing data directly from your own Tonie account.
🔍 Background
All of your Tonies are listed with an image, title, and description at https://my.tonies.com/content-tonies. This data is provided via a GraphQL API: API endpoint: https://api.prod.tcs.toys/v2/graphql The JSON there contains:
- Title
- Description
- Cover image
Tag ID (e.g. E0040350178864AE), which can be linked to the local tonie.json and the tag ID.
🔐 Authentication
Login is easy to implement with Python (session + token). Once logged in, you can retrieve the content and process it locally. Implementation ideaPython script for authentication and data retrieval Linking API data with local tag IDs Extension or regeneration of tonie.json Optional: Integration as a CLI tool or web module in TeddyCloud Advantages Automatic addition of missing contentUniform display of all Tonies No more manual maintenance of JSON files
❓Open questions
Where and how should the script be integrated into TeddyCloud? (e.g., as a module, hook, admin tool) How do we handle authentication and token storage? What do you think of the idea? I welcome feedback and am happy to contribute an initial prototype.
What is the advantage regards the current automatic data scraping implemented? Data is fetched from tonies also?
It connects the figurine and the content without the way over the audio-id. Using this, the quality of the tonies-json could be enhanced and automatically crowdsourced.
As a first step the tonies.custom.json could be used for that purpose. But it would be nicer to generate YAMLs as https://github.com/toniebox-reverse-engineering/tonies-json does and then generate the JSON itself out of it (I have a python script doing that).
I would see, as a first step, a Python based prototype would be interesting. How it could be integrated is another step to be solved. Especially the UX Part. If there is any API missing within teddyCloud let me know.
There will be several edge cases to be checked: Creative Tonies, Tonies with Tunes Content from the shop, Custom content, those combined cheap book Tonies.
@SciLor I think that's great. Would you share your script with me so I don't have to rewrite it myself?
This is the raw Version. You'll need to fix it manually, as the Config is missing. You may delete the YamlStruct entirely out of the script. I may make a repo with it public someday. But this should work for you. Feel free to contact me via Telegram
import os
import yaml
import json
import subprocess
import argparse
from article_yaml_helpers import YamlStruct
from tonies_json_config import Config
def main():
parser = argparse.ArgumentParser(description="Export YAML files to JSON")
parser.add_argument(
"--simulate", "-s",
action="store_true",
help="Run in simulate mode (no output files are written)"
)
args = parser.parse_args()
yaml_dir = Config.yaml_dir
tonies_file = Config.export_tonies_file
toniesV2_file = Config.export_toniesV2_file
tonies_json = []
toniesV2_json = []
for filename in sorted(os.listdir(yaml_dir)):
if filename.endswith('.yaml'):
yaml_path = f"{yaml_dir}{filename}"
with open(yaml_path, 'r') as yaml_file:
base = yaml.safe_load(yaml_file)
toniesV2_base = {
"article": str(base["article"]),
"data": []
}
no = 0
for item in base["data"]:
audio_ids = []
hashes = []
for id in item["ids"]:
audio_ids.append(str(id["audio-id"]))
hashes.append(id["hash"].upper())
tonies_element = {
"no": str(no),
"model": str(base["article"]),
"audio_id": audio_ids,
"hash": hashes,
"title": f'{item["series"]} - {item["episode"]}',
"series": item["series"],
"episodes": item["episode"],
"tracks": item["track-desc"],
"release": str(item["release"]),
"language": item["language"],
"category": item["category"],
"pic": item["image"]
}
no += 1
tonies_json.append(tonies_element)
toniesV2_element = {
"series": item["series"],
"episode": item["episode"],
"release": item["release"],
"language": item["language"],
"category": item["category"],
"runtime": item["runtime"],
"age": item["age"],
"origin": item["origin"],
"image": item["image"],
"sample": item["sample"],
"web": item["web"],
"shop-id": item["shop-id"],
"track-desc": item["track-desc"],
"ids": item["ids"]
}
toniesV2_base["data"].append(toniesV2_element)
toniesV2_json.append(toniesV2_base)
if args.simulate:
print(f"[SIMULATE] Would export {len(tonies_json)} v1 elements to {tonies_file}")
print(f"[SIMULATE] Would export {len(toniesV2_json)} v2 elements to {toniesV2_file}")
else:
with open(tonies_file, "w", encoding="utf-8") as json_file:
json.dump(tonies_json, json_file, ensure_ascii=False)
print(f"Exported {len(tonies_json)} v1 elements")
with open(toniesV2_file, "w", encoding="utf-8") as json_file:
json.dump(toniesV2_json, json_file, ensure_ascii=False)
print(f"Exported {len(toniesV2_json)} v2 elements")
if __name__ == "__main__":
main()
@SciLor Thanks, I saw that you implemented a bug fix in the method for updating the JSON. Can't we implement a method there directly that calls your script so that we don't need to make any changes to the UX?
I meant with the UX Part: How the user can enter his credentials and how we can ask the user to provide the data to fill the tonies-json (globally) with that data in the future...
Thanks, I saw that you implemented a bug fix in the method for updating the JSON
Sorry I don't understand that.
I think that’s a good part for the web Ui of tc.
Credentials can be stored locally in a semi safe way, and then we can fetch the data using the tonies account of the user. The so fetched data can be send to a to be defined api endpoint which sorts the data and filter bullshit requests.
It could be fully automated so the enduser has no chance to break the data. Kind of Ui: enter tonies credentials (so even without storing the credentials), fetch data from tonies and submit data to the to be tonies.json api.
It could be added as a menu entry in community —> contribution or directly on the home section. Contribute your toniemetadata from tonies. ( no auth codes).
Could be a page with credential input fields (allow user to store them locally)
A button fetch data, then a list with all fetched data (so he sees what data will be submitted) where user can select the entries he want to submit (all preselected) and a submit to tonies.json button.
ok. pure frontend is not possible as they do not use graphql for authentication. they are using an other service instead which can not be called from frontend (XCORS)... too bad...
so we can just use the frontend to get the user credentials, pass them to backend, backend does the magic (maybe for now just returns the authorization bearer token) and then we can proceed in frontend (select what we want to submit) and send the selected data to the tonies.json api