mirror of
https://github.com/PR0M3TH3AN/VoxVera.git
synced 2025-09-08 06:58:42 +00:00
Add docs and CI/CD workflows
This commit is contained in:
3
.flake8
Normal file
3
.flake8
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[flake8]
|
||||||
|
max-line-length = 120
|
||||||
|
ignore = E501,E741,E401,E402
|
23
.github/workflows/ci.yml
vendored
Normal file
23
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install flake8 pytest InquirerPy rich
|
||||||
|
- name: Lint
|
||||||
|
run: flake8 voxvera tests
|
||||||
|
- name: Test
|
||||||
|
run: pytest
|
44
.github/workflows/release.yml
vendored
Normal file
44
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
|
- name: Install build tools
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install build pyinstaller
|
||||||
|
- name: Build wheel
|
||||||
|
run: python -m build --wheel --sdist
|
||||||
|
- name: Build binary
|
||||||
|
run: pyinstaller --onefile -n voxvera voxvera/cli.py
|
||||||
|
- name: Build Docker image
|
||||||
|
run: docker build -t ghcr.io/${{ github.repository_owner }}/voxvera:${{ github.ref_name }} .
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Push Docker image
|
||||||
|
run: docker push ghcr.io/${{ github.repository_owner }}/voxvera:${{ github.ref_name }}
|
||||||
|
- name: Publish to PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||||
|
- name: Upload release assets
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
dist/*.whl
|
||||||
|
dist/*.tar.gz
|
||||||
|
dist/voxvera
|
51
README.md
51
README.md
@@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
VoxVera provides scripts and templates for producing printable flyers with QR codes. These flyers link to content hosted through Tor and can also include a Nostr page. The project automates building the HTML, generating the QR codes, and copying all assets into a directory under `host/` so they can be served statically.
|
VoxVera provides scripts and templates for producing printable flyers with QR codes. These flyers link to content hosted through Tor and can also include a Nostr page. The project automates building the HTML, generating the QR codes, and copying all assets into a directory under `host/` so they can be served statically.
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/PR0M3TH3AN/VoxVera.git
|
||||||
|
cd VoxVera
|
||||||
|
./install.sh # use install.ps1 on Windows
|
||||||
|
voxvera quickstart
|
||||||
|
```
|
||||||
|
|
||||||
|
See [docs/usage.md](docs/usage.md) for detailed usage instructions.
|
||||||
|
|
||||||
## Quick Install
|
## Quick Install
|
||||||
|
|
||||||
Run the installer to set up all dependencies and the `voxvera` CLI in one step.
|
Run the installer to set up all dependencies and the `voxvera` CLI in one step.
|
||||||
@@ -103,45 +114,7 @@ The script updates the chosen config file, regenerates QR codes, obfuscates `ind
|
|||||||
|
|
||||||
Additional documentation is available in the `src/` directory; see [src/README.md](src/README.md) for more details on the obfuscation scripts and additional usage notes.
|
Additional documentation is available in the `src/` directory; see [src/README.md](src/README.md) for more details on the obfuscation scripts and additional usage notes.
|
||||||
|
|
||||||
## Step-by-Step
|
Additional documentation, including step-by-step instructions and hosting guides, lives under the [docs](docs/) directory.
|
||||||
1. Edit `src/index-master.html` or `src/nostr-master.html` if you need custom content.
|
|
||||||
2. Run `voxvera init` and follow the prompts, or use `voxvera init --from-pdf path/to/form.pdf`.
|
|
||||||
3. Host the generated `host/<subdomain>` directory.
|
|
||||||
The `index.html` file fetches `config.json`, so the flyer must be served via a
|
|
||||||
local or remote web server rather than opened directly from disk. For a quick
|
|
||||||
test you can run `python3 -m http.server` inside the folder and then visit the
|
|
||||||
provided address.
|
|
||||||
|
|
||||||
## Batch Import
|
|
||||||
Place configuration files in an `imports/` directory at the project root. Run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
voxvera import
|
|
||||||
```
|
|
||||||
|
|
||||||
Each JSON file is copied to `src/config.json` and processed with
|
|
||||||
`voxvera build`. Existing folders under `host/` with the
|
|
||||||
same subdomain are removed before new files are written.
|
|
||||||
|
|
||||||
## Hosting with OnionShare
|
|
||||||
The folder under `host/<subdomain>` contains everything needed to serve the
|
|
||||||
flyer. Use the CLI to publish it over Tor:
|
|
||||||
The script now resolves the configuration and host paths internally, so it can
|
|
||||||
be invoked from any directory:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
voxvera serve
|
|
||||||
```
|
|
||||||
|
|
||||||
The script launches `onionshare-cli` in persistent website mode, waits for the
|
|
||||||
generated onion URL, patches `config.json`, regenerates the QR codes and
|
|
||||||
obfuscated HTML, and then copies the updated files back into the `host`
|
|
||||||
directory. The onion address is printed when ready. Keep OnionShare running to
|
|
||||||
continue hosting.
|
|
||||||
|
|
||||||
`index.html` fetches `config.json` dynamically, so the flyer should be viewed
|
|
||||||
through a local or remote web server. For quick testing, run
|
|
||||||
`python3 -m http.server` in the folder and open the provided address instead of
|
|
||||||
loading the file directly.
|
|
||||||
|
|
||||||
This project is licensed under the [MIT License](./LICENSE).
|
This project is licensed under the [MIT License](./LICENSE).
|
||||||
|
17
docs/troubleshooting.md
Normal file
17
docs/troubleshooting.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Troubleshooting
|
||||||
|
|
||||||
|
This page collects common issues encountered when hosting or accessing flyers.
|
||||||
|
|
||||||
|
## Tor connectivity
|
||||||
|
- Ensure Tor is allowed through your firewall. On systems using `ufw` you may need to run `sudo ufw allow tor`.
|
||||||
|
- Some networks block Tor entirely. If you cannot reach onion services, try connecting over a different network or use a Tor bridge.
|
||||||
|
|
||||||
|
## Firewall rules
|
||||||
|
- If `voxvera serve` fails to start OnionShare, verify that outbound connections on ports 9001 and 80 are permitted.
|
||||||
|
- Corporate or university firewalls can block the hidden service ports required by Tor.
|
||||||
|
|
||||||
|
## SELinux
|
||||||
|
- On SELinux-enabled distributions you may see `permission denied` errors when OnionShare writes to the `host` directory.
|
||||||
|
- Run `sudo chcon -Rt svirt_sandbox_file_t host` or disable SELinux enforcement for the folder.
|
||||||
|
|
||||||
|
If problems persist, consult the OnionShare and Tor documentation for more advanced configuration tips.
|
24
docs/usage.md
Normal file
24
docs/usage.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Detailed Usage
|
||||||
|
|
||||||
|
This guide covers common CLI workflows. See `docs/docker.md` for Docker instructions and `docs/templates.md` for available flyer templates.
|
||||||
|
|
||||||
|
## Step-by-Step
|
||||||
|
1. Edit `src/index-master.html` or `src/nostr-master.html` if you need custom content.
|
||||||
|
2. Run `voxvera init` and follow the prompts, or use `voxvera init --from-pdf path/to/form.pdf`.
|
||||||
|
3. Host the generated `host/<subdomain>` directory. The `index.html` file fetches `config.json`, so the flyer must be served via a local or remote web server rather than opened directly from disk. For a quick test you can run `python3 -m http.server` inside the folder and then visit the provided address.
|
||||||
|
|
||||||
|
## Batch Import
|
||||||
|
Place configuration files in an `imports/` directory at the project root and run:
|
||||||
|
```bash
|
||||||
|
voxvera import
|
||||||
|
```
|
||||||
|
Each JSON file is copied to `src/config.json` and processed with `voxvera build`. Existing folders under `host/` with the same subdomain are removed before new files are written.
|
||||||
|
|
||||||
|
## Hosting with OnionShare
|
||||||
|
Use the CLI to publish the flyer over Tor:
|
||||||
|
```bash
|
||||||
|
voxvera serve
|
||||||
|
```
|
||||||
|
The script launches `onionshare-cli` in persistent website mode, waits for the generated onion URL, patches `config.json`, regenerates the QR codes and obfuscated HTML, and then copies the updated files back into the `host` directory. Keep OnionShare running to continue hosting.
|
||||||
|
|
||||||
|
`index.html` fetches `config.json` dynamically, so the flyer should be viewed through a local or remote web server. For quick testing, run `python3 -m http.server` in the folder and open the provided address instead of loading the file directly.
|
18
pyproject.toml
Normal file
18
pyproject.toml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=42", "wheel"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "voxvera"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "VoxVera CLI utilities"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = [{name = "VoxVera"}]
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = [
|
||||||
|
"InquirerPy",
|
||||||
|
"rich",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
voxvera = "voxvera.cli:main"
|
13
tests/test_cli.py
Normal file
13
tests/test_cli.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
import os, sys
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
|
||||||
|
from voxvera.cli import main
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def test_help(capsys):
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
main(["-h"])
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert "usage:" in captured.out
|
@@ -164,7 +164,8 @@ def serve(config_path: str):
|
|||||||
logfile = os.path.join(dir_path, 'onionshare.log')
|
logfile = os.path.join(dir_path, 'onionshare.log')
|
||||||
proc = subprocess.Popen(['onionshare-cli', '--website', '--public', '--persistent', f'{dir_path}/.onionshare-session', dir_path], stdout=open(logfile, 'w'), stderr=subprocess.STDOUT)
|
proc = subprocess.Popen(['onionshare-cli', '--website', '--public', '--persistent', f'{dir_path}/.onionshare-session', dir_path], stdout=open(logfile, 'w'), stderr=subprocess.STDOUT)
|
||||||
try:
|
try:
|
||||||
import time, re as _re
|
import time
|
||||||
|
import re as _re
|
||||||
onion_url = None
|
onion_url = None
|
||||||
while onion_url is None:
|
while onion_url is None:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
Reference in New Issue
Block a user