capture-pkg
A modular Python package providing capture capabilities and HyFetch console branding for the x-ray application and standalone Python services. Includes a hardware-bound licensing system with HMAC-SHA256 digital signature verification.
✨ Features
- HyFetch Console Branding: Automatic system fetch console banner with custom
xenogenderpreset andfastfetch/neofetchbackend. - Non-Blocking Auto Configuration: Auto-generates
hyfetch.jsonwhen missing to ensure non-interactive servers (FastAPI/Uvicorn) never hang on setup wizards. - FastAPI / Server Ready: Provides helper functions (
print_banner(),get_info(),process_capture()) ready for API consumption. - CLI Executable: Pre-configured terminal command
capture-pkg. - Hardware-Bound Licensing: HMAC-SHA256 signed license locked to MAC Address and Disk Serial.
- Auto-Update: Automatically checks PyPI for new versions in the background and installs updates without interrupting the server.
🚀 Quick Start
1. Installation from PyPI
pip install capture-pkg
2. Run CLI Command
Execute directly in your terminal to see the HyFetch banner and package status:
capture-pkg
💻 Usage in Python & FastAPI (x-ray)
Import in FastAPI App / Routes
from fastapi import APIRouter
import capture_pkg
router = APIRouter()
# Display HyFetch banner at server startup (Non-blocking)
capture_pkg.print_banner()
@router.get("/api/v1/capture/info")
def get_capture_info():
return capture_pkg.get_info()
@router.post("/api/v1/capture/process")
def trigger_capture(bl_number: str, camera_id: int = 1):
return capture_pkg.process_capture(source_id=bl_number, camera_id=camera_id)
🔐 License Management
Cara Kerja Lisensi
Lisensi di-generate oleh developer/vendor menggunakan generate-license CLI dan kemudian dikirimkan ke server klien. Lisensi dikunci ke hardware spesifik (MAC Address dan/atau Disk Serial) dengan tanda tangan digital HMAC-SHA256.
1. Ambil Hardware Fingerprint Server Klien
Sebelum generate lisensi, minta klien menjalankan perintah ini di server mereka untuk mendapatkan MAC Address dan Disk Serial:
# Jalankan di server klien (x-ray server)
python -c "from capture_pkg.license_verifier import get_hardware_fingerprint; import json; print(json.dumps(get_hardware_fingerprint(), indent=2))"
Contoh output:
{
"mac_address": "A4:BB:6D:12:34:56",
"disk_serial": "WD-WX12345ABCDE",
"platform": "Linux-5.15.0-x86_64"
}
2. Generate Lisensi Klien (di mesin developer/vendor)
Gunakan CLI generate-license setelah capture-pkg ter-install di environment developer:
# Generate lisensi terikat MAC Address dan Disk Serial klien
generate-license \
--client "PT. Pelabuhan Indonesia" \
--mac "A4:BB:6D:12:34:56" \
--disk "WD-WX12345ABCDE" \
--expiry "2027-12-31" \
--output "license_client.json"
# Generate lisensi hanya terikat MAC Address (tanpa cek disk)
generate-license \
--client "PT. Terminal Petikemas Surabaya" \
--mac "A4:BB:6D:12:34:56" \
--expiry "2026-12-31"
# Generate lisensi tanpa binding hardware (berlaku di semua mesin, kurang aman)
generate-license \
--client "Demo License" \
--expiry "2025-06-30"
# Generate lisensi menggunakan hardware mesin developer saat ini
generate-license \
--client "Developer Internal" \
--mac this \
--disk this \
--expiry "2099-12-31" \
--output "license_dev.json"
Contoh output sukses:
===================================================
SUCCESS GENERATING SIGNED CLIENT LICENSE
===================================================
File Path : /home/dev/license_client.json
Issued To : PT. Pelabuhan Indonesia
Bound MAC : A4:BB:6D:12:34:56
Bound Disk : WD-WX12345ABCDE
Expiry Date : 2027-12-31
Anti-Tamper : HMAC-SHA256 Signature Embedded
===================================================
3. Kirim & Pasang Lisensi di Server Klien
Salin file license_client.json ke server klien dan letakkan di salah satu lokasi berikut (dicek berurutan):
| Prioritas | Path |
|---|---|
| 1 | <working directory>/license.lic |
| 2 | <working directory>/license.json |
| 3 | ~/.config/x-ray/license.json |
| 4 | %APPDATA%/x-ray/license.json (Windows only) |
# Contoh: salin ke direktori kerja x-ray
cp license_client.json /opt/x-ray/license.json
4. Verifikasi Lisensi di Server Klien
# Verifikasi manual via Python
python -c "from capture_pkg.license_verifier import verify_license; import json; print(json.dumps(verify_license(), indent=2))"
Contoh output jika valid:
{
"status": "valid",
"license_id": "LIC-20260101120000",
"issued_to": "PT. Pelabuhan Indonesia",
"expiry_date": "2027-12-31",
"signature_verified": true,
"hardware_verified": true
}
⚙️ Environment Variables
Semua variabel berikut dikonfigurasi di .env project x-ray (server klien), bukan di capture_pkg:
| Variabel | Default | Keterangan |
|---|---|---|
APP_ENV |
production |
Set ke development untuk menonaktifkan pengecekan lisensi |
CAPTURE_LICENSE_ENFORCE |
false |
Set ke true untuk memaksa cek lisensi meskipun APP_ENV=development (berguna untuk QA) |
CAPTURE_UPDATE_INTERVAL_DAYS |
7 |
Interval hari pengecekan update otomatis dari PyPI |
CAPTURE_DISABLE_AUTOUPDATE |
false |
Set ke true untuk menonaktifkan auto-update |
Contoh konfigurasi .env x-ray
# Mode Development — lisensi dinonaktifkan
APP_ENV=development
# Mode Production — lisensi aktif (nilai default, tidak perlu diset eksplisit)
APP_ENV=production
# Mode QA — development tapi tetap enforce lisensi
APP_ENV=development
CAPTURE_LICENSE_ENFORCE=true
# Auto-update setiap 30 hari sekali
CAPTURE_UPDATE_INTERVAL_DAYS=30
# Nonaktifkan auto-update (tidak direkomendasikan)
CAPTURE_DISABLE_AUTOUPDATE=true
Tabel Perilaku License Gate
APP_ENV |
CAPTURE_LICENSE_ENFORCE |
Hasil |
|---|---|---|
production (default) |
apa saja | 🔒 ENFORCE — lisensi selalu dicek |
development |
tidak diset / false |
✅ BYPASS — lisensi dilewati |
development |
true |
🔒 ENFORCE — tetap dicek untuk keperluan QA |
🔄 Auto-Update dari PyPI
capture-pkg secara otomatis mengecek versi terbaru di PyPI setiap 7 hari (dapat dikonfigurasi). Proses ini berjalan di background thread sehingga tidak memblokir startup server x-ray.
Alur kerja:
- Saat
import capture_pkg— library cek kapan terakhir kali pengecekan dilakukan - Jika sudah melewati interval → spawn background thread
- Background thread cek PyPI API (
https://pypi.org/pypi/capture-pkg/json) - Jika ada versi baru →
pip install --upgrade capture-pkgdijalankan otomatis - Versi baru aktif setelah x-ray di-restart berikutnya
State file disimpan di: ~/.config/capture-pkg/update_state.json
# Lihat status update terakhir
cat ~/.config/capture-pkg/update_state.json
🛠️ Local Development (Editable Mode)
When developing or modifying capture-pkg locally, install in editable mode:
cd capture_pkg
pip install -e .[dev]
Note: In editable mode (
pip install -e .), any code changes made incapture_pkg/take effect immediately without needing to reinstall!
📦 Package Publishing & Update Workflow
PyPI package releases are immutable. Whenever you update code and want to publish a new release:
1. Configure PyPI Token Credentials
Create a .env file in the project root:
TWINE_USERNAME=__token__
TWINE_PASSWORD=pypi-AgEIcHlwaS5vcmcC...
2. Bump Version Number
Update the version in both pyproject.toml and capture_pkg/__init__.py:
# pyproject.toml
version = "0.4.0"
# capture_pkg/__init__.py
__version__ = "0.4.0"
3. Build Distribution Packages
Clean previous artifacts and build new .whl and .tar.gz archives:
python -m build
4. Upload to PyPI (Manual)
Publish the new version using Twine:
python -m twine upload dist/*
🚀 Mekanisme & Workflow GitLab CI/CD
Project ini dilengkapi dengan pipeline otomatis GitLab CI/CD (.gitlab-ci.yml) untuk memastikan pengujian kualitas kode dan mempublikasikan versi baru secara otomatis ke PyPI tanpa perlu proses build manual di komputer lokal.
🔄 Alur Mekanisme Pipeline (Visual Diagram)
[ Git Push / Tag ]
│
▼
┌───────────┐ Gagal ┌────────────────────────┐
│ Stage 1: ├───────────────►│ ❌ Stop Pipeline │
│ TEST │ │ (Publish Dibatalkan) │
└─────┬─────┘ └────────────────────────┘
│ Lolos (Passed)
▼
┌───────────┐ Bukan Tag ┌────────────────────────┐
│ Is Git ├───────────────►│ ⏹️ Finish │
│ Tag? │ (Normal Push) │ (Hanya menjalankan Test)│
└─────┬─────┘ └────────────────────────┘
│ Ya (Tag format v*.*.*)
▼
┌───────────┐
│ Stage 2: │ ──► Build Wheel (.whl) ──► Upload ke PyPI
│ PUBLISH │ (python -m build) (twine upload via PYPI_API_TOKEN)
└───────────┘
📋 Tahapan Pipeline (Pipeline Stages)
Pipeline dikonfigurasi menjadi 2 tahapan (stages):
-
Stage 1:
test(test:job)- Kapan berjalan: Setiap ada
git pushke branch apapun atau ketika Git Tag di-push. - Tugas: Menginstall dependency pengembangan (
pip install .[dev]) dan menjalankan seluruh unit test (pytest tests/ -v). - Pengamanan: Jika ada test yang gagal (failed), pipeline langsung terhenti. Stage
publishtidak akan pernah berjalan jika pengujian gagal.
- Kapan berjalan: Setiap ada
-
Stage 2:
publish(pypi:publish)- Kapan berjalan: Hanya berjalan secara otomatis jika commit tersebut memiliki Git Tag dengan format versi (misal:
v0.3.2,v1.0.0). - Tugas:
- Melakukan kompilasi/build package distribution archives (
python -m build). - Mengunggah hasil build ke PyPI menggunakan Twine dengan mengonsumsi variable
PYPI_API_TOKEN.
- Melakukan kompilasi/build package distribution archives (
- Kapan berjalan: Hanya berjalan secara otomatis jika commit tersebut memiliki Git Tag dengan format versi (misal:
🔐 1. Setup Prasyarat Token di GitLab
Sebelum rilis otomatis dapat berjalan, daftarkan Token PyPI ke GitLab Repository:
- Buka dashboard PyPI: https://pypi.org/manage/account/token/
- Buat API Token baru dengan scope paket
capture-pkg. - Masuk ke Repository GitLab: Settings > CI/CD > Variables.
- Tambahkan Variable baru:
- Key:
PYPI_API_TOKEN - Value:
pypi-AgEIcHlwa...(Token dari PyPI) - Type: Variable
- Flags: Centang
Protect variabledanMask variable.
- Key:
📦 2. Langkah Rilis Versi Baru
Untuk merilis update ke PyPI, ikuti 3 langkah sederhana ini dari terminal Anda:
# 1. Update angka versi di pyproject.toml dan capture_pkg/__init__.py (misal: 0.3.2)
# 2. Commit perubahan kode tersebut
git add .
git commit -m "chore: release version 0.3.2"
# 3. Buat Git Tag berawalan 'v' lalu push tag tersebut ke remote
git tag v0.3.2
git push origin master --tags
Catatan: Begitu
git push --tagsdieksekusi, GitLab CI/CD akan otomatis mengambil alih, menjalankan pengujian, dan meng-upload versi baru tersebut ke PyPI!
📄 License
Distributed under the MIT License.
Metadata
Release files for capture-pkg 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| capture_pkg-0.3.2.tar.gz | 23.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| capture_pkg-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.7 kB
Release files / capture_pkg-0.3.2.tar.gz
| Download URL | capture_pkg-0.3.2.tar.gz |
|---|---|
| Size | 23.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1fe1755583275f4f315b6329432c8e50aff254dafbc972a044555fe1e5a98c0a
|
|
BLAKE2b-256 checksum How to use checksums |
9777b116441bee18b404296b17441f15c400eab737655e332dd028f0942f2fc5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.20
|
Release files / capture_pkg-0.3.2-py3-none-any.whl
| Download URL | capture_pkg-0.3.2-py3-none-any.whl |
|---|---|
| Size | 20.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
81cc66c393d778c1e4f4050f26daac45862400d18284fbf616c431e2c6e80605
|
|
BLAKE2b-256 checksum How to use checksums |
569d90a410b169343970f81bb89f775e70c46439684d100d6fda698f94fac661
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.20
|