mirror of
https://github.com/tinode/chat.git
synced 2026-05-07 20:12:42 +00:00
117 lines
4.6 KiB
Python
117 lines
4.6 KiB
Python
#!/usr/bin/env python
|
|
# coding=utf-8
|
|
|
|
"""Python implementation of Tinode command line client using gRPC."""
|
|
|
|
from __future__ import print_function
|
|
|
|
import argparse
|
|
import os
|
|
import platform
|
|
import sys
|
|
|
|
try:
|
|
from importlib.metadata import version
|
|
except ImportError:
|
|
# Fallback for Python < 3.8
|
|
from importlib_metadata import version
|
|
|
|
import tn_globals
|
|
from tn_globals import printout
|
|
from client import run, read_cookie
|
|
from commands import set_macros_module
|
|
|
|
APP_NAME = "tn-cli"
|
|
APP_VERSION = "3.1.0" # format: 1.9.0b1
|
|
LIB_VERSION = version("tinode_grpc")
|
|
GRPC_VERSION = version("grpcio")
|
|
|
|
# This is needed for gRPC SSL to work correctly.
|
|
os.environ["GRPC_SSL_CIPHER_SUITES"] = "HIGH+ECDSA"
|
|
|
|
|
|
# Setup crash handler: close input reader otherwise a crash
|
|
# makes terminal session unusable.
|
|
def exception_hook(type, value, traceBack):
|
|
if tn_globals.InputThread != None:
|
|
tn_globals.InputThread.join(0.3)
|
|
sys.excepthook = exception_hook
|
|
|
|
|
|
# Enable the following variables for debugging.
|
|
# os.environ["GRPC_TRACE"] = "all"
|
|
# os.environ["GRPC_VERBOSITY"] = "INFO"
|
|
|
|
|
|
if __name__ == '__main__':
|
|
"""Parse command-line arguments. Extract host name and authentication scheme, if one is provided"""
|
|
version_str = APP_VERSION + "/" + LIB_VERSION + "; gRPC/" + GRPC_VERSION + "; Python " + platform.python_version()
|
|
purpose = "Tinode command line client. Version " + version_str + "."
|
|
|
|
parser = argparse.ArgumentParser(description=purpose)
|
|
parser.add_argument('--host', default='localhost:16060', help='address of Tinode gRPC server')
|
|
parser.add_argument('--web-host', default='localhost:6060', help='address of Tinode web server (for file uploads)')
|
|
parser.add_argument('--ssl', action='store_true', help='connect to server over secure connection')
|
|
parser.add_argument('--ssl-host', help='SSL host name to use instead of default (useful for connecting to localhost)')
|
|
parser.add_argument('--login-basic', help='login using basic authentication username:password')
|
|
parser.add_argument('--login-token', help='login using token authentication')
|
|
parser.add_argument('--login-cookie', action='store_true', help='read token from cookie file and use it for authentication')
|
|
parser.add_argument('--no-login', action='store_true', help='do not login even if cookie file is present; default in non-interactive (scripted) mode')
|
|
parser.add_argument('--no-cookie', action='store_true', help='do not save login cookie; default in non-interactive (scripted) mode')
|
|
parser.add_argument('--api-key', default='AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K', help='API key for file uploads')
|
|
parser.add_argument('--load-macros', default='./macros.py', help='path to macro module to load')
|
|
parser.add_argument('--version', action='store_true', help='print version')
|
|
parser.add_argument('--verbose', action='store_true', help='log full JSON representation of all messages')
|
|
parser.add_argument('--background', action='store_const', const=True, help='start interactive sessionin background (non-intractive is always in background)')
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.version:
|
|
printout(version_str)
|
|
exit()
|
|
|
|
if args.verbose:
|
|
tn_globals.Verbose = True
|
|
|
|
printout(purpose)
|
|
printout("Secure server" if args.ssl else "Server", "at '"+args.host+"'",
|
|
"SNI="+args.ssl_host if args.ssl_host else "")
|
|
|
|
schema = None
|
|
secret = None
|
|
|
|
if not args.no_login:
|
|
if args.login_token:
|
|
"""Use token to login"""
|
|
schema = 'token'
|
|
secret = args.login_token.encode('ascii')
|
|
printout("Logging in with token", args.login_token)
|
|
|
|
elif args.login_basic:
|
|
"""Use username:password"""
|
|
schema = 'basic'
|
|
secret = args.login_basic
|
|
printout("Logging in with login:password", args.login_basic)
|
|
|
|
elif tn_globals.IsInteractive:
|
|
"""Interactive mode only: try reading the cookie file"""
|
|
printout("Logging in with cookie file")
|
|
schema = 'token'
|
|
secret = read_cookie()
|
|
if not secret:
|
|
schema = None
|
|
|
|
# Attempt to load the macro file if available.
|
|
macros = None
|
|
if args.load_macros:
|
|
import importlib
|
|
macros = importlib.import_module('macros', args.load_macros) if args.load_macros else None
|
|
set_macros_module(macros)
|
|
|
|
# Check if background session is specified explicitly. If not set it to
|
|
# True for non-interactive sessions.
|
|
if args.background is None and not tn_globals.IsInteractive:
|
|
args.background = True
|
|
|
|
sys.exit(run(args, schema, secret))
|