Skip to content

Commit

Permalink
feat(2FA): support added for windscribe (#20)
Browse files Browse the repository at this point in the history
* feat(env): adding pyotp for totp support

* feat(2fa): support added for windscribe login #19

* docs: updated with 2fa information
  • Loading branch information
dhruvinsh committed Aug 26, 2024
1 parent bb46ae1 commit c6f77f8
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 13 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
WS_USERNAME=xxxx
WS_PASSWORD=xxxx
WS_TOTP=xxxxxxxx
WS_DEBUG=False
WS_COOKIE_PATH=/some/mounted/volume/
QBIT_USERNAME=xxxx
Expand Down
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ docker run \
-e WS_DEBUG=False \
-e WS_PASSWORD=password \
-e WS_USERNAME=username \
-e WS_TOPT=totp_token \
-v /path/to/local/data:/cookie \
dhruvinsh/ws-ephemeral:latest
```
Expand All @@ -64,6 +65,7 @@ docker compose up -d
| -------------------- | -------------------------------------------------------------------------------- |
| WS_USERNAME | WS username |
| WS_PASSWORD | WS password |
| WS_TOTP | WS totp token for 2fa |
| WS_DEBUG | Enable Debug logging |
| WS_COOKIE_PATH | Persistent location for the cookie. (v3.x.x only) |
| QBIT_USERNAME | QBIT username |
Expand Down Expand Up @@ -93,14 +95,14 @@ or concerns, please open an issue here.

## Roadmap

- [] Support 2FA
- [] Daemon mode and job mode
- [] Rest API (useful for cron/script job)
- [] Separate port renewal, qbittorrent update and private tracker logic
- [] Random job time for cron job #15
- [] Allow to run custom script (for now Bash script only) #12
- [] Support for deluge
- [] Gluetun support [#2392](https://github.com/qdm12/gluetun/pull/2392)
- [x] Support 2FA, #19
- [ ] Daemon mode and job mode
- [ ] Rest API (useful for cron/script job)
- [ ] Separate port renewal, qbittorrent update and private tracker logic
- [ ] Random job time for cron job #15
- [ ] Allow to run custom script (for now Bash script only) #12
- [ ] Support for deluge
- [ ] Gluetun support [#2392](https://github.com/qdm12/gluetun/pull/2392)

## License

Expand Down
16 changes: 15 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ tqdm = "^4.65.0"
pyyaml = "^6.0"
semver = "^3.0.0"
schedule = "^1.2.0"
pyotp = "^2.9.0"

[tool.poetry.group.dev.dependencies]
tqdm-stubs = ">=0.2.1"
Expand Down
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ idna==3.8 ; python_version >= "3.11" and python_version < "4.0" \
packaging==24.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
pyotp==2.9.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:346b6642e0dbdde3b4ff5a930b664ca82abfa116356ed48cc42c7d6590d36f63 \
--hash=sha256:81c2e5865b8ac55e825b0358e496e1d9387c811e85bb40e71a3b29b288963612
pyyaml==6.0.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
--hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
Expand Down
2 changes: 2 additions & 0 deletions src/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
config module
"""

import os
import sys
from pathlib import Path
Expand Down Expand Up @@ -32,6 +33,7 @@
# WS config
WS_USERNAME: str = os.getenv("WS_USERNAME", "")
WS_PASSWORD: str = os.getenv("WS_PASSWORD", "")
WS_TOTP: str | None = os.getenv("WS_TOTP", None)
WS_COOKIE = Path(os.getenv("WS_COOKIE_PATH", ".")) / "cookie.pkl"

if not all([WS_USERNAME, WS_PASSWORD]):
Expand Down
5 changes: 4 additions & 1 deletion src/run.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Module that run the setup for windscrib's ephemeral port
"""

import logging
import time

Expand Down Expand Up @@ -38,7 +39,9 @@ def main() -> None:
return

logger.info("Running automation...")
with Windscribe(username=config.WS_USERNAME, password=config.WS_PASSWORD) as ws:
with Windscribe(
username=config.WS_USERNAME, password=config.WS_PASSWORD, totp=config.WS_TOTP
) as ws:
port = ws.setup()

if not config.QBIT_FOUND:
Expand Down
13 changes: 10 additions & 3 deletions src/ws/ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from typing import TypedDict, Union

import httpx
import pyotp

import config
from lib.decorators import login_required
Expand All @@ -33,7 +34,7 @@ class Windscribe:
"""

# pylint: disable=redefined-outer-name
def __init__(self, username: str, password: str) -> None:
def __init__(self, username: str, password: str, totp: str | None = None) -> None:
headers = {
"origin": config.BASE_URL,
"referer": config.LOGIN_URL,
Expand All @@ -54,6 +55,7 @@ def __init__(self, username: str, password: str) -> None:
self.csrf: Csrf = self.get_csrf()
self.username = username
self.password = password
self.totp = totp

self.logger = logging.getLogger(self.__class__.__name__)

Expand Down Expand Up @@ -102,16 +104,21 @@ def renew_csrf(self) -> Csrf:

def login(self) -> None:
"""login in to the webpage."""
# NOTE: at the given moment try to resolve totp so that we don't have any delay.
totp = ""
if self.totp is not None:
totp = pyotp.TOTP(self.totp).now()

data = {
"login": 1,
"upgrade": 0,
"csrf_time": self.csrf["csrf_time"],
"csrf_token": self.csrf["csrf_token"],
"username": self.username,
"password": self.password,
"code": "",
"code": totp,
}
self.client.post(config.LOGIN_URL, data=data)
_ = self.client.post(config.LOGIN_URL, data=data)

# save the cookie for the future use.
save_cookie(self.client.cookies)
Expand Down

0 comments on commit c6f77f8

Please sign in to comment.