Plain is headed towards 1.0! Subscribe for development updates →

 1import getpass
 2import random
 3import string
 4
 5import click
 6
 7from plain.cli import register_cli
 8
 9from .client import TunnelClient
10
11
12@register_cli("tunnel")
13@click.command()
14@click.argument("destination")
15@click.option(
16    "--subdomain",
17    help="The subdomain to use for the tunnel.",
18    envvar="PLAIN_TUNNEL_SUBDOMAIN",
19)
20@click.option(
21    "--tunnel-host", envvar="PLAIN_TUNNEL_HOST", hidden=True, default="plaintunnel.com"
22)
23@click.option("--debug", "log_level", flag_value="DEBUG", help="Enable debug logging.")
24@click.option(
25    "--quiet", "log_level", flag_value="WARNING", help="Only log warnings and errors."
26)
27def cli(destination, subdomain, tunnel_host, log_level):
28    if not destination.startswith("http://") and not destination.startswith("https://"):
29        destination = f"https://{destination}"
30
31    # Strip trailing slashes from the destination URL (maybe even enforce no path at all?)
32    destination = destination.rstrip("/")
33
34    if not log_level:
35        log_level = "INFO"
36
37    if not subdomain:
38        # Generate a subdomain using the system username + 7 random characters
39        random_chars = "".join(random.choices(string.ascii_lowercase, k=7))
40        subdomain = f"{getpass.getuser()}-{random_chars}"
41
42    tunnel = TunnelClient(
43        destination_url=destination,
44        subdomain=subdomain,
45        tunnel_host=tunnel_host,
46        log_level=log_level,
47    )
48    click.secho(f"Tunneling {tunnel.tunnel_http_url} -> {destination}", bold=True)
49    tunnel.run()