Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,58 @@ start server:
python cmd_chat.py serve 0.0.0.0 3000 --password mysecret
```

start server and join as host:

```bash
python cmd_chat.py serve 0.0.0.0 3000 --password mysecret --join alice
```

connect:

```bash
python cmd_chat.py connect SERVER_IP 3000 username mysecret
```

### ngrok (internet access)

expose your server over the internet without port forwarding using [ngrok](https://ngrok.com):

```bash
python cmd_chat.py serve 0.0.0.0 3000 --password mysecret --ngrok
```

with a free ngrok account (removes session limits):

```bash
python cmd_chat.py serve 0.0.0.0 3000 --password mysecret --ngrok --ngrok-token YOUR_TOKEN
```

on startup a panel is printed with the public address and ready-to-run connect command, e.g.:

```
╭─────────────── Public Access ────────────────╮
│ ngrok tunnel active (HTTPS) │
│ │
│ Address: https://abc1-2a04.ngrok-free.app:443│
│ │
│ Connect: python cmd_chat.py connect │
│ abc1-2a04.ngrok-free.app 443 <username> │
│ mysecret │
╰──────────────────────────────────────────────╯
```

remote participants connect via the ngrok address (TLS encrypted end-to-end):

```bash
python cmd_chat.py connect abc1-2a04.ngrok-free.app 443 username mysecret
```

to host and chat simultaneously over ngrok:

```bash
python cmd_chat.py serve 0.0.0.0 3000 --password mysecret --ngrok --join alice
```

![Example](example.gif)

## features
Expand Down
10 changes: 9 additions & 1 deletion cmd_chat.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
from cmd_chat import main
import sys
import os

_venv_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "venv")
_venv_python = os.path.join(_venv_dir, "bin", "python3")

if os.path.exists(_venv_python) and os.path.realpath(sys.prefix) != os.path.realpath(_venv_dir):
os.execv(_venv_python, [_venv_python] + sys.argv)

if __name__ == "__main__":
from cmd_chat import main
main()
48 changes: 40 additions & 8 deletions cmd_chat/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import argparse
from cmd_chat.server.server import run_server
from cmd_chat.client.client import Client
import getpass


def _prompt(label: str, secret: bool = False) -> str:
while True:
value = (getpass.getpass(label) if secret else input(label)).strip()
if value:
return value


def main():
Expand All @@ -10,24 +16,50 @@ def main():
serve_p = subparsers.add_parser("serve", help="Run server")
serve_p.add_argument("ip_address")
serve_p.add_argument("port")
serve_p.add_argument("--password", "-p", required=True)
serve_p.add_argument("--password", "-p", default=None)
serve_p.add_argument("--join", "-j", nargs="?", const=True, default=False, metavar="USERNAME",
help="Join chat as host (prompts for username if not given)")
serve_p.add_argument("--ngrok", action="store_true", help="Expose server via ngrok tunnel")
serve_p.add_argument("--ngrok-token", metavar="TOKEN", help="ngrok authtoken")

connect_p = subparsers.add_parser("connect", help="Connect to server")
connect_p.add_argument("ip_address")
connect_p.add_argument("port")
connect_p.add_argument("username")
connect_p.add_argument("password")
connect_p.add_argument("username", nargs="?", default=None)
connect_p.add_argument("password", nargs="?", default=None)

args = parser.parse_args()

if args.command == "serve":
run_server(host=args.ip_address, port=int(args.port), password=args.password)
password = args.password or _prompt("Password: ", secret=True)

if args.join is True:
join_as = _prompt("Your username: ")
elif args.join:
join_as = args.join
else:
join_as = None

from cmd_chat.server.server import run_server
run_server(
host=args.ip_address,
port=int(args.port),
password=password,
join_as=join_as,
ngrok=args.ngrok,
ngrok_token=args.ngrok_token,
)

elif args.command == "connect":
username = args.username or _prompt("Username: ")
password = args.password or _prompt("Password: ", secret=True)

from cmd_chat.client.client import Client
Client(
server=args.ip_address,
port=int(args.port),
username=args.username,
password=args.password,
username=username,
password=password,
).run()


Expand Down
Loading