gh-space-shooter 0.0.5__tar.gz → 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/.github/workflows/publish.yml +2 -2
  2. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/.github/workflows/test.yml +3 -3
  3. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/.gitignore +2 -1
  4. gh_space_shooter-1.0.1/.python-version +1 -0
  5. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/CLAUDE.md +4 -1
  6. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/PKG-INFO +6 -2
  7. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/README.md +4 -0
  8. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/action.yml +1 -1
  9. gh_space_shooter-1.0.1/app/README.md +53 -0
  10. gh_space_shooter-1.0.1/app/public/android-chrome-192x192.png +0 -0
  11. gh_space_shooter-1.0.1/app/public/android-chrome-512x512.png +0 -0
  12. gh_space_shooter-1.0.1/app/public/apple-touch-icon.png +0 -0
  13. gh_space_shooter-1.0.1/app/public/favicon-16x16.png +0 -0
  14. gh_space_shooter-1.0.1/app/public/favicon-32x32.png +0 -0
  15. gh_space_shooter-1.0.1/app/public/favicon.ico +0 -0
  16. gh_space_shooter-1.0.1/app/public/og-image.gif +0 -0
  17. gh_space_shooter-1.0.1/app/public/site.webmanifest +1 -0
  18. gh_space_shooter-1.0.1/app/pyproject.toml +19 -0
  19. gh_space_shooter-1.0.1/app/src/main.py +78 -0
  20. gh_space_shooter-1.0.1/app/src/templates/index.html +564 -0
  21. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/pyproject.toml +9 -3
  22. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/github_client.py +1 -1
  23. gh_space_shooter-1.0.1/src/gh_space_shooter/py.typed +0 -0
  24. gh_space_shooter-1.0.1/uv.lock +1093 -0
  25. gh_space_shooter-0.0.5/.python-version +0 -1
  26. gh_space_shooter-0.0.5/uv.lock +0 -305
  27. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/.github/dependabot.yml +0 -0
  28. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/LICENSE +0 -0
  29. /gh_space_shooter-0.0.5/src/gh_space_shooter/py.typed → /gh_space_shooter-1.0.1/app/src/__init__.py +0 -0
  30. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/example.gif +0 -0
  31. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/__init__.py +0 -0
  32. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/cli.py +0 -0
  33. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/console_printer.py +0 -0
  34. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/constants.py +0 -0
  35. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/__init__.py +0 -0
  36. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/animator.py +0 -0
  37. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/drawables/__init__.py +0 -0
  38. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/drawables/bullet.py +0 -0
  39. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/drawables/drawable.py +0 -0
  40. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/drawables/enemy.py +0 -0
  41. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/drawables/explosion.py +0 -0
  42. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/drawables/ship.py +0 -0
  43. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/drawables/starfield.py +0 -0
  44. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/game_state.py +0 -0
  45. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/render_context.py +0 -0
  46. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/renderer.py +0 -0
  47. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/strategies/__init__.py +0 -0
  48. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/strategies/base_strategy.py +0 -0
  49. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/strategies/column_strategy.py +0 -0
  50. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/strategies/random_strategy.py +0 -0
  51. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/src/gh_space_shooter/game/strategies/row_strategy.py +0 -0
  52. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/tests/conftest.py +0 -0
  53. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/tests/test_bullet_collision.py +0 -0
  54. {gh_space_shooter-0.0.5 → gh_space_shooter-1.0.1}/tests/test_strategies.py +0 -0
@@ -14,7 +14,7 @@ on:
14
14
  - patch
15
15
 
16
16
  env:
17
- PYTHON_LATEST: 3.13
17
+ PYTHON_LATEST: 3.12
18
18
 
19
19
  jobs:
20
20
  build:
@@ -22,7 +22,7 @@ jobs:
22
22
  runs-on: ubuntu-latest
23
23
 
24
24
  steps:
25
- - uses: actions/checkout@v4
25
+ - uses: actions/checkout@v6
26
26
 
27
27
  - name: Install uv
28
28
  uses: astral-sh/setup-uv@v7
@@ -7,7 +7,7 @@ on:
7
7
  types: [opened, synchronize, reopened]
8
8
 
9
9
  env:
10
- PYTHON_LATEST: 3.13
10
+ PYTHON_LATEST: 3.12
11
11
 
12
12
  jobs:
13
13
  test:
@@ -15,11 +15,11 @@ jobs:
15
15
  runs-on: ubuntu-latest
16
16
  strategy:
17
17
  matrix:
18
- python-version: ["3.13"]
18
+ python-version: ["3.12"]
19
19
 
20
20
  steps:
21
21
  - name: Checkout code
22
- uses: actions/checkout@v4
22
+ uses: actions/checkout@v6
23
23
 
24
24
  - name: Install uv
25
25
  uses: astral-sh/setup-uv@v7
@@ -19,4 +19,5 @@ wheels/
19
19
  .env.*
20
20
 
21
21
  # Test output
22
- my-contributions.json
22
+ my-contributions.json
23
+ .vercel
@@ -0,0 +1 @@
1
+ 3.12
@@ -22,6 +22,9 @@ uv run pytest tests/test_strategies.py -v
22
22
 
23
23
  # Run a specific test
24
24
  uv run pytest tests/test_strategies.py::test_column_strategy -v
25
+
26
+ # Run the web app (from app/ directory)
27
+ uv run --project gh-space-shooter-app uvicorn main:app
25
28
  ```
26
29
 
27
30
  ## Environment Setup
@@ -36,7 +39,7 @@ export GH_TOKEN=your_token_here
36
39
 
37
40
  **Current main usage**: GitHub Action that automatically updates a game GIF in user repositories daily (see `.github/workflows/` for the action definition).
38
41
 
39
- **Planned**: Wrap this into a Python webapp for on-demand GIF generation.
42
+ **Web App**: A FastAPI-based web application is available in the `app/` directory for on-demand GIF generation. See `app/README.md` for details.
40
43
 
41
44
  ## Architecture Overview
42
45
 
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gh-space-shooter
3
- Version: 0.0.5
3
+ Version: 1.0.1
4
4
  Summary: A CLI tool that visualizes GitHub contribution graphs as gamified GIFs
5
5
  Author-email: zane <czl970721@gmail.com>
6
6
  License-File: LICENSE
7
- Requires-Python: >=3.13
7
+ Requires-Python: >=3.12
8
8
  Requires-Dist: httpx>=0.27.0
9
9
  Requires-Dist: pillow>=10.1.0
10
10
  Requires-Dist: python-dotenv>=1.0.0
@@ -22,6 +22,10 @@ Transform your GitHub contribution graph into an epic space shooter game!
22
22
 
23
23
  ## Usage
24
24
 
25
+ ### Onetime Generation
26
+
27
+ A [web interface](https://gh-space-shooter.kiyo-n-zane.com) is available for on-demand GIF generation without installing anything locally.
28
+
25
29
  ### GitHub Action
26
30
 
27
31
  Automatically update your game GIF daily using GitHub Actions! Add this workflow to your repository at `.github/workflows/update-game.yml`:
@@ -6,6 +6,10 @@ Transform your GitHub contribution graph into an epic space shooter game!
6
6
 
7
7
  ## Usage
8
8
 
9
+ ### Onetime Generation
10
+
11
+ A [web interface](https://gh-space-shooter.kiyo-n-zane.com) is available for on-demand GIF generation without installing anything locally.
12
+
9
13
  ### GitHub Action
10
14
 
11
15
  Automatically update your game GIF daily using GitHub Actions! Add this workflow to your repository at `.github/workflows/update-game.yml`:
@@ -42,7 +42,7 @@ runs:
42
42
  - name: Set up Python
43
43
  uses: actions/setup-python@v5
44
44
  with:
45
- python-version: '3.13'
45
+ python-version: '3.12'
46
46
 
47
47
  - name: Install gh-space-shooter
48
48
  shell: bash
@@ -0,0 +1,53 @@
1
+ # gh-space-shooter Web App
2
+
3
+ A FastAPI web application that provides on-demand GitHub Space Shooter GIF generation through a browser interface.
4
+
5
+ ## Features
6
+
7
+ - Web UI for generating GIFs without CLI installation
8
+ - Select GitHub username and animation strategy (random, column, row)
9
+ - Download generated GIFs directly
10
+ - Share functionality for supported browsers
11
+
12
+ ## Setup
13
+
14
+ 1. Install dependencies:
15
+ ```bash
16
+ cd app
17
+ uv sync
18
+ ```
19
+
20
+ 2. Set up environment:
21
+ ```bash
22
+ export GH_TOKEN=your_github_token
23
+ # Or create a .env file with GH_TOKEN=your_token
24
+ ```
25
+
26
+ ## Running Locally
27
+
28
+ ```bash
29
+ uv run --project gh-space-shooter-app uvicorn main:app
30
+ ```
31
+
32
+ The app will be available at `http://localhost:8000`.
33
+
34
+ ## API Endpoints
35
+
36
+ - `GET /` - Web UI for generating GIFs
37
+ - `GET /api/generate?username=<username>&strategy=<strategy>` - Generate and return a GIF
38
+ - `username` (required): GitHub username
39
+ - `strategy` (optional): Animation strategy - `random`, `column`, or `row` (default: `random`)
40
+
41
+ ## Project Structure
42
+
43
+ ```
44
+ app/
45
+ ├── src/
46
+ │ ├── main.py # FastAPI application
47
+ │ └── templates/
48
+ │ └── index.html # Web UI template
49
+ ├── public/
50
+ │ └── favicon.ico
51
+ ├── pyproject.toml
52
+ └── README.md
53
+ ```
@@ -0,0 +1 @@
1
+ {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
@@ -0,0 +1,19 @@
1
+ [project]
2
+ name = "gh-space-shooter-app"
3
+ version = "0.1.0"
4
+ description = "Web app wrapper for gh-space-shooter GIF generation"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "gh-space-shooter",
9
+ "fastapi[standard]",
10
+ "uvicorn[standard]",
11
+ "jinja2",
12
+ ]
13
+
14
+ [build-system]
15
+ requires = ["setuptools"]
16
+ build-backend = "setuptools.build_meta"
17
+
18
+ [project.scripts]
19
+ app = "main:app"
@@ -0,0 +1,78 @@
1
+ """FastAPI web app for gh-space-shooter GIF generation."""
2
+
3
+ import os
4
+ from io import BytesIO
5
+ from pathlib import Path
6
+
7
+ from dotenv import load_dotenv
8
+ from fastapi import FastAPI, HTTPException, Query
9
+ from fastapi.requests import Request
10
+ from fastapi.responses import HTMLResponse, Response
11
+ # from fastapi.staticfiles import StaticFiles
12
+ from fastapi.templating import Jinja2Templates
13
+
14
+ from gh_space_shooter.game import Animator, ColumnStrategy, RandomStrategy, RowStrategy, BaseStrategy
15
+ from gh_space_shooter.github_client import GitHubAPIError, GitHubClient
16
+
17
+ load_dotenv()
18
+
19
+ app = FastAPI(title="GitHub Space Shooter")
20
+
21
+ templates = Jinja2Templates(directory=Path(__file__).parent / "templates")
22
+ # app.mount("/public", StaticFiles(directory=Path(__file__).parent / "public"), name="public")
23
+
24
+
25
+ STRATEGY_MAP: dict[str, type[BaseStrategy]] = {
26
+ "column": ColumnStrategy,
27
+ "row": RowStrategy,
28
+ "random": RandomStrategy,
29
+ }
30
+
31
+
32
+ def generate_gif(username: str, strategy: str, token: str) -> BytesIO:
33
+ """Generate a space shooter GIF for a GitHub user."""
34
+ with GitHubClient(token) as client:
35
+ data = client.get_contribution_graph(username)
36
+
37
+ strategy_class: type[BaseStrategy] = STRATEGY_MAP.get(strategy, RandomStrategy)
38
+ strat = strategy_class()
39
+
40
+ animator = Animator(data, strat, fps=25, watermark=True)
41
+ return animator.generate_gif(maxFrame=250)
42
+
43
+ @app.get("/", response_class=HTMLResponse)
44
+ async def index(request: Request):
45
+ """Serve the main page."""
46
+ return templates.TemplateResponse(request, "index.html")
47
+
48
+
49
+ @app.get("/api/generate")
50
+ async def generate(
51
+ username: str = Query(..., min_length=1, description="GitHub username"),
52
+ strategy: str = Query("random", description="Animation strategy"),
53
+ ):
54
+ """Generate and return a space shooter GIF."""
55
+ token = os.getenv("GH_TOKEN")
56
+ if not token:
57
+ raise HTTPException(status_code=500, detail="GitHub token not configured")
58
+
59
+ if strategy not in STRATEGY_MAP:
60
+ raise HTTPException(
61
+ status_code=400,
62
+ detail=f"Invalid strategy. Choose from: {', '.join(STRATEGY_MAP.keys())}",
63
+ )
64
+
65
+ try:
66
+ gif_buffer = generate_gif(username, strategy, token)
67
+ return Response(
68
+ content=gif_buffer.getvalue(),
69
+ media_type="image/gif",
70
+ headers={
71
+ "Response-Type": "blob",
72
+ "Content-Disposition": f"inline; filename={username}-space-shooter.gif"
73
+ },
74
+ )
75
+ except GitHubAPIError as e:
76
+ raise HTTPException(status_code=400, detail=str(e))
77
+ except Exception as e:
78
+ raise HTTPException(status_code=500, detail=f"Failed to generate GIF: {e}")