Skip to content

Commit 6a72ff7

Browse files
docs(readme): add item count badges
1 parent 556f4ca commit 6a72ff7

File tree

3 files changed

+88
-5
lines changed

3 files changed

+88
-5
lines changed

README.md

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,56 @@
1-
# GameDB
1+
<div align="center">
2+
<h1 align="center">GameDB</h1>
3+
<h4 align="center">Jekyll static site with IGDB data</h4>
4+
</div>
25

3-
[![GitHub Workflow Status (DB)](https://img.shields.io/github/actions/workflow/status/lizardbyte/gamedb/update-db.yml.svg?branch=master&label=update%20db&logo=github&style=for-the-badge)](https://github.com/LizardByte/GameDB/actions/workflows/update-db.yml?query=branch%3Amaster)
4-
[![Codecov](https://img.shields.io/codecov/c/gh/LizardByte/GameDB.svg?token=AG91ICECDX&style=for-the-badge&logo=codecov&label=codecov)](https://app.codecov.io/gh/LizardByte/GameDB)
6+
<div align="center">
7+
<a href="https://github.com/LizardByte/GameDB/actions/workflows/ci-tests.yml?query=branch%3Amaster"><img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/gamedb/ci-tests.yml.svg?branch=master&label=CI&logo=github&style=for-the-badge" alt="CI"></a>
8+
<a href="https://github.com/LizardByte/GameDB/actions/workflows/update-db.yml?query=branch%3Amaster"><img src="https://img.shields.io/github/actions/workflow/status/lizardbyte/gamedb/update-db.yml.svg?branch=master&label=update%20db&logo=github&style=for-the-badge" alt="Update DB"></a>
9+
<a href="https://app.codecov.io/gh/LizardByte/GameDB"><img src="https://img.shields.io/codecov/c/gh/LizardByte/GameDB.svg?token=AG91ICECDX&style=for-the-badge&logo=codecov&label=codecov" alt="Codecov"></a>
10+
</div>
511

6-
This repository clones IGDB to gh-pages to be consumed by LizardByte projects, such as LizardByte/Sunshine.
12+
---
713

8-
Information from YouTube API is also added to the database for videos.
14+
<div align="center">
15+
<a href="https://app.lizardbyte.dev/GameDB/characters/all.json"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapp.lizardbyte.dev%2FGameDB%2Fstats.json&query=%24.characters&label=characters&style=for-the-badge&color=blue" alt="Characters"></a>
16+
<a href="https://app.lizardbyte.dev/GameDB/collections/all.json"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapp.lizardbyte.dev%2FGameDB%2Fstats.json&query=%24.collections&label=collections&style=for-the-badge&color=blue" alt="Collections"></a>
17+
<a href="https://app.lizardbyte.dev/GameDB/franchises/all.json"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapp.lizardbyte.dev%2FGameDB%2Fstats.json&query=%24.franchises&label=franchises&style=for-the-badge&color=blue" alt="Franchises"></a>
18+
<a href="https://app.lizardbyte.dev/GameDB/games"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapp.lizardbyte.dev%2FGameDB%2Fstats.json&query=%24.games&label=games&style=for-the-badge&color=blue" alt="Games"></a>
19+
<a href="https://app.lizardbyte.dev/GameDB/platforms/all.json"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapp.lizardbyte.dev%2FGameDB%2Fstats.json&query=%24.platforms&label=platforms&style=for-the-badge&color=blue" alt="Platforms"></a>
20+
<a href="https://app.lizardbyte.dev/GameDB/videos"><img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapp.lizardbyte.dev%2FGameDB%2Fstats.json&query=%24.videos&label=videos&style=for-the-badge&color=blue" alt="Videos"></a>
21+
</div>
22+
23+
## Overview
24+
25+
GameDB is a database of games, platforms, characters, collections, franchises, and videos sourced from
26+
[IGDB](https://www.igdb.com) and published as a static JSON API via
27+
[GitHub Pages](https://lizardbyte.github.io/GameDB). Video metadata is enriched with data from the YouTube API.
28+
29+
The data is intended to be consumed by [LizardByte](https://app.lizardbyte.dev) projects such as
30+
[Sunshine](https://github.com/LizardByte/Sunshine).
31+
32+
## Data
33+
34+
The database is updated automatically on a schedule via the [update-db](.github/workflows/update-db.yml) workflow.
35+
The generated JSON files are published to the `gh-pages` branch and served at
36+
`https://app.lizardbyte.dev/GameDB/`.
37+
38+
| Endpoint | Description | URL |
39+
|-------------|-------------------------------------------------------|-----------------------------------------------------------|
40+
| Buckets | Game name search index, split by first two characters | `https://app.lizardbyte.dev/GameDB/buckets/<bucket>.json` |
41+
| Characters | Individual character details and all characters | `https://app.lizardbyte.dev/GameDB/characters/<id>.json` |
42+
| Collections | Individual collection details and all collections | `https://app.lizardbyte.dev/GameDB/collections/<id>.json` |
43+
| Franchises | Individual franchise details and all franchises | `https://app.lizardbyte.dev/GameDB/franchises/<id>.json` |
44+
| Games | Individual game details (no aggregate `all.json`) | `https://app.lizardbyte.dev/GameDB/games/<id>.json` |
45+
| Platforms | Individual platform details and all platforms | `https://app.lizardbyte.dev/GameDB/platforms/<id>.json` |
46+
| Videos | Individual YouTube video metadata | `https://app.lizardbyte.dev/GameDB/videos/<id>.json` |
47+
| Stats | Total item counts per category | `https://app.lizardbyte.dev/GameDB/stats.json` |
48+
49+
`all.json` files (e.g. `characters/all.json`) contain a summary of every item in that category as a single
50+
dictionary keyed by ID.
51+
52+
Buckets are used as a lightweight search index for game names. Each bucket file is named after the first two
53+
alphanumeric characters of the game name (lowercased), e.g. `ha.json` for games starting with "Ha" such as
54+
*Halo*. Games whose names contain a space as the second character are put into a bucket named after the first
55+
character. Games whose names do not start with two alphanumeric characters are grouped into `@.json`. Each bucket
56+
contains a dictionary of `{ id: { name } }` entries, keeping individual files small for fast lookups.

src/update_db.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,20 @@ def _enrich_game_videos(full_dict: dict) -> None:
451451
video['thumb'] = video_thumbs[0][1]['url']
452452

453453

454+
def _write_stats(full_dict: dict) -> None:
455+
"""
456+
Write a ``stats.json`` file to the output directory containing item counts per category.
457+
458+
Parameters
459+
----------
460+
full_dict : dict
461+
The combined data dictionary keyed by endpoint name.
462+
"""
463+
stats = {endpoint: len(items) for endpoint, items in full_dict.items()}
464+
file_path = os.path.join(args.out_dir, 'stats')
465+
write_json_files(file_path=file_path, data=stats)
466+
467+
454468
def get_data():
455469
"""
456470
Get data from IGDB and YouTube.
@@ -614,6 +628,8 @@ def get_data():
614628

615629
_enrich_game_videos(full_dict=full_dict)
616630

631+
_write_stats(full_dict=full_dict)
632+
617633
for endpoint, endpoint_dict in full_dict.items():
618634
print(f'writing individual files for {endpoint}')
619635
for item_id, data in endpoint_dict.items():

tests/unit/test_update_db.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,23 @@ def test_get_youtube(tmp_path):
445445
assert 'yt_key_123' in called_url
446446

447447

448+
def test_write_stats(tmp_path):
449+
udb.args = _make_args(tmp_path)
450+
full_dict = {
451+
'characters': {1: {}, 2: {}, 3: {}},
452+
'games': {10: {}, 20: {}},
453+
'videos': {'abc': {}, 'def': {}},
454+
}
455+
456+
with patch('src.update_db.write_json_files') as mock_write:
457+
udb._write_stats(full_dict=full_dict)
458+
459+
mock_write.assert_called_once()
460+
call_kwargs = mock_write.call_args[1]
461+
assert 'stats' in call_kwargs['file_path']
462+
assert call_kwargs['data'] == {'characters': 3, 'games': 2, 'videos': 2}
463+
464+
448465
def test_get_platform_cross_reference(tmp_path):
449466
udb.args = _make_args(tmp_path)
450467

@@ -474,6 +491,7 @@ def test_get_data_orchestration(tmp_path):
474491
patch('src.update_db._resolve_video_groups', return_value=[['vid1']]) as m_vgroups, \
475492
patch('src.update_db._fetch_youtube_metadata') as m_yt, \
476493
patch('src.update_db._enrich_game_videos') as m_enrich, \
494+
patch('src.update_db._write_stats') as m_stats, \
477495
patch('src.update_db.write_json_files') as m_write:
478496
udb.get_data()
479497

@@ -484,6 +502,7 @@ def test_get_data_orchestration(tmp_path):
484502
m_vgroups.assert_called_once()
485503
m_yt.assert_called_once()
486504
m_enrich.assert_called_once()
505+
m_stats.assert_called_once()
487506
assert m_write.call_count >= 2 # bucket files + individual files
488507

489508

0 commit comments

Comments
 (0)