# mullvad-api

A complete api for [mullvad.net](https://mullvad.net)

# Installation

    pip install mullvad-neo-api

# Usage

## CLI

```
usage: python -m mullvadapi [-h] [-p PASSWORD] [-w TIME] [-W TIME] [-r NUM] [--retry-delay TIME] [--retry-all-errors] [-m TIMEOUT] [-k] [-L] [--max-redirs NUM] [-A UA]
                            [-x PROXY] [-H HEADER] [-b COOKIE] [-B BROWSER]
                            {create-account,status,devices,instances,version,create-device,revoke-device,receipt,create-config} ...

Tool for interacting with mullvad.net

If password is not passed through arguments, it'll be read from $MULLVAD_PASSWORD environment variable.

General:
  -h, --help            Show this help message and exit
  -p, --password PASSWORD
                        Specify password for authentication

subcommands:
  {create-account,status,devices,instances,version,create-device,revoke-device,receipt,create-config}
    create-account      create account
    status              Get status
    devices             Get devices
    instances           Get instances
    version             Get version
    create-device       create new device
    revoke-device       remove device
    receipt             Get receipt
    create-config       create wireguird config

Request settings:
  -w, --wait TIME       Set waiting time for each request
  -W, --wait-random TIME
                        Set random waiting time for each request to be from 0 to TIME
  -r, --retry NUM       Set number of retries for failed request to NUM
  --retry-delay TIME    Set interval between each retry
  --retry-all-errors    Retry no matter the error
  -m, --timeout TIMEOUT
                        Set request timeout, if in TIME format it'll be set for the whole request. If in TIME,TIME format first TIME will specify connection timeout, the
                        second read timeout. If set to '-' timeout is disabled
  -k, --insecure        Ignore ssl errors
  -L, --location        Allow for redirections, can be dangerous if credentials are passed in headers
  --max-redirs NUM      Set the maximum number of redirections to follow
  -A, --user-agent UA   Sets custom user agent
  -x, --proxy PROXY     Use the specified proxy, can be used multiple times. If set to URL it'll be used for all protocols, if in PROTOCOL URL format it'll be set only for
                        given protocol, if in URL URL format it'll be set only for given path. If first character is '@' then proxies are read from file
  -H, --header HEADER   Set curl style header, can be used multiple times e.g. -H 'User: Admin' -H 'Pass: 12345', if first character is '@' then headers are read from file
                        e.g. -H @file
  -b, --cookie COOKIE   Set curl style cookie, can be used multiple times e.g. -b 'auth=8f82ab' -b 'PHPSESSID=qw3r8an829', without '=' character argument is read as a file
  -B, --browser BROWSER
                        Get cookies from specified browser e.g. -B firefox
```

Password for login can be specified either by options or in `MULLVAD_PASSWORD` environment variable.

```bash
mullvadapi -p 1234567890123456 status

export MULLVAD_PASSWORD='1234567890123456'
mullvadapi status
```

Additional options for requests also can be specified before the subcommand

```bash
mullvadapi --wait 0.1 -header 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0' status
```

### create-account

```bash
mullvadapi create-account
```

Creates new account and prints it's password

### status

```bash
mullvadapi status
```

Prints general status of the account in json

### instances

```bash
mullvadapi instances
```

Prints a list of all server instances available in json

### devices

```bash
mullvadapi devices
```

Prints info about currently registered devices in json

### version

```bash
mullvadapi version
```

Prints version string of mullvad

### create-device

```bash
mullvadapi create-device <PUBKEY>
```

Registers new device with specified wireguard `public key` and prints info about it in json

### revoke-device

```bash
mullvadapi revoke-device <UUID>
```

Removes device by it's `uuid`

### receipt

```bash
mullvadapi receipt <SOURCE> <TOKEN>
```

Prints info about receipt in json by it's `token`, `source` can be `swish`, `paypal`, `card` or `other`.

### create-config

```bash
mullvadapi create-config <INSTANCE> <DEVICE>
```

Prints wireguard config file by extracting info from `instance` and `device` info passed as json, extracted from output of `instances` and `devices` subcommands.

## Library

### Code

```python
from mullvadapi import Api, Error, RequestError, AuthorizationError, FailedError

password='1234567890123456'
try:
    api = Api(password)
except AuthorizationError:
    print(f"Invalid password - {password}")
    exit(1)
except RequestError as e:
    print("request error - {}".format(repr(e)))
    exit(1)

if len(api.status()['me']['expiry']) == 0:
    print("No time left on the account")
    exit(1)

try:
    devices = api.devices()
    instances = api.instances()
except Error as e:
    print(repr(e))

device = None
if len(devices) == 0:
    wireguard_pubkey="rWiQxq5lAWD8v/bws9ITSAvThyZW8cR2x+Ins9ZvvRo="
    device = api.create_device(wireguard_pubkey)
else:
    device = devices[0]

#creates wireguard config
print(api.create_config(instances[0],device))
```

### Api

`Api` class provides methods for interacting with mullvad.net, at it's initialization password can be passed which will be passed to `login` method, it also accepts parameters for [treerequests](https://github.com/TUVIMEN/treerequests) session.

#### login(self, password: str)

Log in to account

#### logout(self)

Log out from account

#### receipt(self, source: str, token: str) -> dict

Get receipt on transaction, `source` can be `swish`, `paypal`, `card` or `other`.

#### status_raw(self) -> dict

Get status of user

#### status(self) -> dict

Get status of user in format easier to use

#### devices_raw(self) -> dict:

List devices of user

#### devices(self) -> dict:

List devices of user in format easier to use

#### create_device(self, key: str) -> dict

Create a new device with wireguard public `key`.

On error raises `FailedError`, otherwise format similar to `devices` method is returned about the newly created device.

#### revoke_device(self, uuid: str) -> bool

Remove device with `uuid`.

Returns `True` on success and False on failure.

#### version(self) -> str

Get version string

#### create_account(self) -> str

Create new account and return password.

`FailedError` is raised on failure

#### create_config(self, instance: dict, device: dict) -> str

Creates wireguard configuration from `instance` and `device` which should bee derived from `instances` and `devices` methods

#### instances(self) -> List[dict]

Gets full list of available server instances

### Exceptions

All exceptions raised by this library are derived from `Error`.

`RequestError` is raised for errors when handling requests.

`AuthenticationError` is raised by calling methods needing authentication without being logged in.

`FailedError` is raised by `create_device` and `create_user` methods on failure.
