-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #47 from kiwix/protonvpn-wireguard-config-downloader
Protonvpn wireguard config downloader
- Loading branch information
Showing
11 changed files
with
610 additions
and
0 deletions.
There are no files selected for viewing
40 changes: 40 additions & 0 deletions
40
.github/workflows/protonvpn-wireguard-config-downloader-QA.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
name: ProtonVPN Wireguard Config Downloader QA | ||
|
||
on: | ||
pull_request: | ||
push: | ||
paths: | ||
- 'protonvpn-wireguard-config-downloader/**' | ||
branches: | ||
- main | ||
|
||
jobs: | ||
|
||
check-qa: | ||
runs-on: ubuntu-24.04 | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version-file: protonvpn-wireguard-config-downloader/pyproject.toml | ||
architecture: x64 | ||
|
||
- name: Install dependencies (and project) | ||
working-directory: protonvpn-wireguard-config-downloader | ||
run: | | ||
pip install -U pip | ||
pip install -e .[lint,scripts,test,check] | ||
- name: Check black formatting | ||
working-directory: protonvpn-wireguard-config-downloader | ||
run: inv lint-black | ||
|
||
- name: Check ruff | ||
working-directory: protonvpn-wireguard-config-downloader | ||
run: inv lint-ruff | ||
|
||
- name: Check pyright | ||
working-directory: protonvpn-wireguard-config-downloader | ||
run: inv check-pyright |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
FROM python:3.11-slim-bookworm | ||
LABEL org.opencontainers.image.source=https://github.com/kiwix/mirrors-qa | ||
|
||
# We need gnupg2 for python-gnupg used in Proton libraries to work properly. | ||
RUN apt-get update && apt-get install -y gnupg2 | ||
|
||
COPY src /src/src | ||
|
||
COPY pyproject.toml README.md /src/ | ||
|
||
RUN pip install --no-cache-dir /src \ | ||
&& rm -rf /src | ||
|
||
RUN mkdir /data | ||
|
||
CMD ["protonvpn-wireguard-configs", "--help"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# ProtonVPN Wireguard Configuration Downloader | ||
|
||
A tool to automatically download wireguard configuration files for all available VPN servers from ProtonVPN. | ||
|
||
**NOTE** | ||
This script is intended to be used in Linux environments only. | ||
|
||
## Environment Variables | ||
|
||
- `USERNAME`: username for connnecting to ProtonVPN account | ||
- `PASSWORD` | ||
- `WORKDIR`: location to store configuration files. (default: /data) | ||
- `WIREGUARD_PORT`: Port of the wireguard configuration files (default: 51820).This allows to choose the wireguard port for the configuration files rather than leaving it to the ProtonVPN library which often defaults to the first available port in the session object. | ||
|
||
## Usage | ||
- Build the image | ||
```sh | ||
docker build -t protonvpn-wireguard-config-downloader . | ||
``` | ||
- Download the configuration files | ||
```sh | ||
docker run --rm -e USERNAME=abcd@efg -e PASSWORD=pa55word -v ./proton:/data protonvpn-wireguard-config-downloader protonvpn-wireguard-configs | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
[build-system] | ||
requires = ["hatchling", "hatch-openzim"] | ||
build-backend = "hatchling.build" | ||
|
||
[project] | ||
name = "protonvpn_wireguard_config_downloader" | ||
requires-python = ">=3.11,<3.13" | ||
description = "ProtonVPN Wireguard Configuration Files Downloader" | ||
readme = "README.md" | ||
authors = [ | ||
{ name = "Kiwix", email = "[email protected]" }, | ||
] | ||
keywords = ["protonvpn", "wireguard"] | ||
dependencies = [ | ||
"proton-core @ https://github.com/ProtonVPN/python-proton-core/archive/refs/tags/v0.2.0.zip", | ||
"proton-vpn-logger @ https://github.com/ProtonVPN/python-proton-vpn-logger/archive/refs/tags/v0.2.1.zip", | ||
"proton-vpn-api-core @ https://github.com/ProtonVPN/python-proton-vpn-api-core/archive/refs/tags/v0.32.2.zip", | ||
"distro==1.9.0" | ||
] | ||
license = {text = "GPL-3.0-or-later"} | ||
classifiers = [ | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: 3.12", | ||
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", | ||
] | ||
|
||
dynamic = ["version"] | ||
|
||
[project.urls] | ||
Homepage = "https://github.com/kiwix/mirrors-qa/protonvpn-wireguard-config-downloader" | ||
|
||
[project.optional-dependencies] | ||
scripts = [ | ||
"invoke==2.2.0", | ||
] | ||
lint = [ | ||
"black==24.4.2", | ||
"ruff==0.5.1", | ||
] | ||
check = [ | ||
"pyright==1.1.370", | ||
] | ||
test = [ | ||
"pytest==8.2.2", | ||
"coverage==7.5.4", | ||
] | ||
dev = [ | ||
"pre-commit==3.7.1", | ||
"debugpy==1.8.2", | ||
"protonvpn_wireguard_config_downloader[scripts]", | ||
"protonvpn_wireguard_config_downloader[lint]", | ||
"protonvpn_wireguard_config_downloader[test]", | ||
"protonvpn_wireguard_config_downloader[check]", | ||
] | ||
|
||
[project.scripts] | ||
protonvpn-wireguard-configs = "protonvpn_wireguard_config_downloader.entrypoint:main" | ||
|
||
[tool.hatch.version] | ||
path = "src/protonvpn_wireguard_config_downloader/__about__.py" | ||
|
||
[tool.hatch.build] | ||
exclude = [ | ||
"/.github", | ||
] | ||
|
||
[tool.hatch.metadata] | ||
allow-direct-references = true | ||
|
||
[tool.hatch.build.targets.wheel] | ||
packages = ["src/protonvpn_wireguard_config_downloader"] | ||
|
||
[tool.hatch.envs.default] | ||
features = ["dev"] | ||
|
||
[tool.hatch.envs.test] | ||
features = ["scripts", "test"] | ||
|
||
|
||
[tool.hatch.envs.test.scripts] | ||
run = "inv test --args '{args}'" | ||
run-cov = "inv test-cov --args '{args}'" | ||
report-cov = "inv report-cov" | ||
coverage = "inv coverage --args '{args}'" | ||
html = "inv coverage --html --args '{args}'" | ||
|
||
[tool.hatch.envs.lint] | ||
template = "lint" | ||
skip-install = false | ||
features = ["scripts", "lint"] | ||
|
||
[tool.hatch.envs.lint.scripts] | ||
black = "inv lint-black --args '{args}'" | ||
ruff = "inv lint-ruff --args '{args}'" | ||
all = "inv lintall --args '{args}'" | ||
fix-black = "inv fix-black --args '{args}'" | ||
fix-ruff = "inv fix-ruff --args '{args}'" | ||
fixall = "inv fixall --args '{args}'" | ||
|
||
[tool.hatch.envs.check] | ||
features = ["scripts", "check"] | ||
|
||
[tool.hatch.envs.check.scripts] | ||
pyright = "inv check-pyright --args '{args}'" | ||
all = "inv checkall --args '{args}'" | ||
|
||
[tool.black] | ||
line-length = 88 | ||
target-version = ['py310'] | ||
|
||
[tool.ruff] | ||
target-version = "py311" | ||
line-length = 88 | ||
src = ["src"] | ||
|
||
[tool.ruff.lint] | ||
select = [ | ||
"A", # flake8-builtins | ||
# "ANN", # flake8-annotations | ||
"ARG", # flake8-unused-arguments | ||
# "ASYNC", # flake8-async | ||
"B", # flake8-bugbear | ||
# "BLE", # flake8-blind-except | ||
"C4", # flake8-comprehensions | ||
"C90", # mccabe | ||
# "COM", # flake8-commas | ||
# "D", # pydocstyle | ||
# "DJ", # flake8-django | ||
"DTZ", # flake8-datetimez | ||
"E", # pycodestyle (default) | ||
"EM", # flake8-errmsg | ||
# "ERA", # eradicate | ||
# "EXE", # flake8-executable | ||
"F", # Pyflakes (default) | ||
# "FA", # flake8-future-annotations | ||
"FBT", # flake8-boolean-trap | ||
# "FLY", # flynt | ||
# "G", # flake8-logging-format | ||
"I", # isort | ||
"ICN", # flake8-import-conventions | ||
# "INP", # flake8-no-pep420 | ||
# "INT", # flake8-gettext | ||
"ISC", # flake8-implicit-str-concat | ||
"N", # pep8-naming | ||
# "NPY", # NumPy-specific rules | ||
# "PD", # pandas-vet | ||
# "PGH", # pygrep-hooks | ||
# "PIE", # flake8-pie | ||
# "PL", # Pylint | ||
"PLC", # Pylint: Convention | ||
"PLE", # Pylint: Error | ||
"PLR", # Pylint: Refactor | ||
"PLW", # Pylint: Warning | ||
# "PT", # flake8-pytest-style | ||
# "PTH", # flake8-use-pathlib | ||
# "PYI", # flake8-pyi | ||
"Q", # flake8-quotes | ||
# "RET", # flake8-return | ||
# "RSE", # flake8-raise | ||
"RUF", # Ruff-specific rules | ||
"S", # flake8-bandit | ||
# "SIM", # flake8-simplify | ||
# "SLF", # flake8-self | ||
"T10", # flake8-debugger | ||
"T20", # flake8-print | ||
# "TCH", # flake8-type-checking | ||
# "TD", # flake8-todos | ||
"TID", # flake8-tidy-imports | ||
# "TRY", # tryceratops | ||
"UP", # pyupgrade | ||
"W", # pycodestyle | ||
"YTT", # flake8-2020 | ||
] | ||
ignore = [ | ||
# Allow non-abstract empty methods in abstract base classes | ||
"B027", | ||
# Remove flake8-errmsg since we consider they bloat the code and provide limited value | ||
"EM", | ||
# Allow boolean positional values in function calls, like `dict.get(... True)` | ||
"FBT003", | ||
# Ignore checks for possible passwords | ||
"S105", "S106", "S107", | ||
# Ignore warnings on subprocess.run / popen | ||
"S603", | ||
# Ignore complexity | ||
"C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915", | ||
] | ||
unfixable = [ | ||
# Don't touch unused imports | ||
"F401", | ||
] | ||
|
||
[tool.ruff.lint.isort] | ||
known-first-party = ["protonvpn_wireguard_config_downloader"] | ||
|
||
[tool.ruff.lint.flake8-bugbear] | ||
# add exceptions to B008 for fastapi. | ||
extend-immutable-calls = ["fastapi.Depends", "fastapi.Query"] | ||
|
||
[tool.ruff.lint.flake8-tidy-imports] | ||
ban-relative-imports = "all" | ||
|
||
[tool.ruff.lint.per-file-ignores] | ||
# Tests can use magic values, assertions, and relative imports | ||
"tests/**/*" = ["PLR2004", "S101", "TID252"] | ||
|
||
[tool.pytest.ini_options] | ||
minversion = "7.3" | ||
testpaths = ["tests"] | ||
pythonpath = [".", "src"] | ||
|
||
[tool.coverage.paths] | ||
protonvpn_wireguard_config_downloader = ["src/protonvpn_wireguard_config_downloader"] | ||
tests = ["tests"] | ||
|
||
[tool.coverage.run] | ||
source_pkgs = ["protonvpn_wireguard_config_downloader"] | ||
branch = true | ||
parallel = true | ||
omit = [ | ||
"src/protonvpn_wireguard_config_downloader/__about__.py", | ||
] | ||
|
||
[tool.coverage.report] | ||
exclude_lines = [ | ||
"no cov", | ||
"if __name__ == .__main__.:", | ||
"if TYPE_CHECKING:", | ||
] | ||
|
||
[tool.pyright] | ||
include = ["src", "tests", "tasks.py"] | ||
exclude = [".env/**", ".venv/**"] | ||
extraPaths = ["src"] | ||
pythonVersion = "3.11" | ||
typeCheckingMode="strict" | ||
disableBytesTypePromotions = true |
1 change: 1 addition & 0 deletions
1
protonvpn-wireguard-config-downloader/src/protonvpn_wireguard_config_downloader/__about__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
__version__ = "1.0.0" |
11 changes: 11 additions & 0 deletions
11
protonvpn-wireguard-config-downloader/src/protonvpn_wireguard_config_downloader/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import logging | ||
|
||
from protonvpn_wireguard_config_downloader.settings import Settings | ||
|
||
logger = logging.getLogger("task") | ||
|
||
if not logger.hasHandlers(): | ||
logger.setLevel(logging.DEBUG if Settings.DEBUG else logging.INFO) | ||
handler = logging.StreamHandler() | ||
handler.setFormatter(logging.Formatter("[%(asctime)s: %(levelname)s] %(message)s")) | ||
logger.addHandler(handler) |
54 changes: 54 additions & 0 deletions
54
...onvpn-wireguard-config-downloader/src/protonvpn_wireguard_config_downloader/entrypoint.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import argparse | ||
import asyncio | ||
import logging | ||
from pathlib import Path | ||
|
||
from protonvpn_wireguard_config_downloader import logger | ||
from protonvpn_wireguard_config_downloader.__about__ import __version__ | ||
from protonvpn_wireguard_config_downloader.protonvpn import ( | ||
login, | ||
logout, | ||
save_vpn_server_wireguard_config, | ||
vpn_servers, | ||
) | ||
from protonvpn_wireguard_config_downloader.settings import Settings | ||
|
||
|
||
async def download_vpn_wireguard_configs( | ||
username: str, password: str, wireguard_port: int, work_dir: Path | ||
) -> None: | ||
"""Download Wireguard configuration files for all VPN servers.""" | ||
session = await login(username, password) | ||
try: | ||
logger.debug("Fetching available VPN servers for client...") | ||
for vpn_server in vpn_servers(session, wireguard_port): | ||
save_vpn_server_wireguard_config(session, vpn_server, work_dir) | ||
finally: | ||
logger.debug("Logging out...") | ||
await logout(session) | ||
logger.info("Successfully logged out client.") | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
"-v", "--verbose", help="Show verbose output", action="store_true" | ||
) | ||
parser.add_argument( | ||
"--version", | ||
help="Show version and exit.", | ||
action="version", | ||
version="%(prog)s " + __version__, | ||
) | ||
args = parser.parse_args() | ||
if args.verbose: | ||
logger.setLevel(logging.DEBUG) | ||
|
||
asyncio.run( | ||
download_vpn_wireguard_configs( | ||
Settings.USERNAME, | ||
Settings.PASSWORD, | ||
Settings.WIREGUARD_PORT, | ||
Settings.WORKDIR, | ||
) | ||
) |
Oops, something went wrong.