diff --git a/build-all.sh b/build-all.sh index d091e9238..832391bfc 100755 --- a/build-all.sh +++ b/build-all.sh @@ -137,15 +137,7 @@ rm -f $GOPATH/bin/init-db # Build chatbot release echo "Building python code..." -pushd ./py_grpc > /dev/null - -# Generate version file from git tags -python3 version.py - -# Generate tinode-grpc package -python3 setup.py -q sdist bdist_wheel - -popd > /dev/null +./build-py-grpc.py # Release chatbot echo "Packaging chatbot.py..." diff --git a/chatbot/python/README.md b/chatbot/python/README.md index 6c64c85dc..8723a8070 100644 --- a/chatbot/python/README.md +++ b/chatbot/python/README.md @@ -1,6 +1,6 @@ -# Tinode Chatbot Example +# Tinode Chatbot -This is a rudimentary chatbot for Tinode using [gRPC API](../../pbx/). It's written in Python as a demonstration +This is a simple chatbot for Tinode using [gRPC API](../../pbx/). It's written in Python as a demonstration that the API is language-independent. The chat bot subscribes to events stream using Plugin API and logs in as a regular user. The event stream API is used to listen for creation of new accounts. When a new account is created, the bot initiates a p2p topic with the new user. Then it listens for messages sent to the topic and responds to each with a random quote from `quotes.txt` file. diff --git a/pbx/README.md b/pbx/README.md index 4449fd8bd..43d4e42a9 100644 --- a/pbx/README.md +++ b/pbx/README.md @@ -1,21 +1,23 @@ # Protocol Buffer and gRPC definitions -Definitions for [gRPC](https://grpc.io/) client and plugins. +Definitions for Tinode [gRPC](https://grpc.io/) client and plugins. -gRPC clients must implement rpc service `Node`, plugins `Plugin`. +Tinode gRPC clients must implement rpc service `Node`, Tinode plugins `Plugin`. -Generated `Go` and `Python` code is included. For a sample `Python` implementation of a command line client see [tn-cli](../tn-cli/). +Generated `Go` and `Python` code is included. For a sample `Python` implementation of a command line client see [tn-cli](../tn-cli/). For a partial plugin implementation see [chatbot](../chatbot/). -If you want to make changes, you have to install protobuffers tool chain and gRPC. To generate `Go` bindings add the following comment to your code and run `go generate` (your actual path to `/pbx` may be different): +If you want to make changes, you have to install protobuffers tool chain and gRPC: +``` +$ python -m pip install grpcio grpcio-tools googleapis-common-protos +``` +To generate `Go` bindings add the following comment to your code and run `go generate` (your actual path to `/pbx` may be different): ``` //go:generate protoc --proto_path=../pbx --go_out=plugins=grpc:../pbx ../pbx/model.proto ``` To generate `Python` bindings: - ``` python -m grpc_tools.protoc -I../pbx --python_out=. --grpc_python_out=. ../pbx/model.proto ``` - diff --git a/pbx/generate-python.sh b/pbx/generate-python.sh index f24e19ec1..8d28f06e5 100755 --- a/pbx/generate-python.sh +++ b/pbx/generate-python.sh @@ -1,4 +1,6 @@ #!/bin/bash -# This generates +# This generates python gRPC bindings for Tinode. python -m grpc_tools.protoc -I../pbx --python_out=../py_grpc/tinode_grpc --grpc_python_out=../py_grpc/tinode_grpc ../pbx/model.proto +# Bindings are incompatible with Python packaging system. This is a fix. +python py_fix.py diff --git a/py_grpc/tinode_grpc/model_pb2.py b/py_grpc/tinode_grpc/model_pb2.py index 73e2be380..907bfc5a4 100644 --- a/py_grpc/tinode_grpc/model_pb2.py +++ b/py_grpc/tinode_grpc/model_pb2.py @@ -20,9 +20,40 @@ name='model.proto', package='pbx', syntax='proto3', - serialized_pb=_b('\n\x0bmodel.proto\x12\x03pbx\"\x08\n\x06Unused\",\n\x0e\x44\x65\x66\x61ultAcsMode\x12\x0c\n\x04\x61uth\x18\x01 \x01(\t\x12\x0c\n\x04\x61non\x18\x02 \x01(\t\")\n\nAccessMode\x12\x0c\n\x04want\x18\x01 \x01(\t\x12\r\n\x05given\x18\x02 \x01(\t\"\'\n\x06SetSub\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x0c\n\x04mode\x18\x02 \x01(\t\"T\n\x07SetDesc\x12(\n\x0b\x64\x65\x66\x61ult_acs\x18\x01 \x01(\x0b\x32\x13.pbx.DefaultAcsMode\x12\x0e\n\x06public\x18\x02 \x01(\x0c\x12\x0f\n\x07private\x18\x03 \x01(\x0c\"u\n\x07GetOpts\x12\x19\n\x11if_modified_since\x18\x01 \x01(\x03\x12\x0c\n\x04user\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x10\n\x08since_id\x18\x04 \x01(\x05\x12\x11\n\tbefore_id\x18\x05 \x01(\x05\x12\r\n\x05limit\x18\x06 \x01(\x05\"k\n\x08GetQuery\x12\x0c\n\x04what\x18\x01 \x01(\t\x12\x1a\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x0c.pbx.GetOpts\x12\x19\n\x03sub\x18\x03 \x01(\x0b\x32\x0c.pbx.GetOpts\x12\x1a\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32\x0c.pbx.GetOpts\"N\n\x08SetQuery\x12\x1a\n\x04\x64\x65sc\x18\x01 \x01(\x0b\x32\x0c.pbx.SetDesc\x12\x18\n\x03sub\x18\x02 \x01(\x0b\x32\x0b.pbx.SetSub\x12\x0c\n\x04tags\x18\x03 \x03(\t\"#\n\x08SeqRange\x12\x0b\n\x03low\x18\x01 \x01(\x05\x12\n\n\x02hi\x18\x02 \x01(\x05\"M\n\nCredential\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12\x10\n\x08response\x18\x03 \x01(\t\x12\x0e\n\x06params\x18\x04 \x01(\x0c\"X\n\x08\x43lientHi\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nuser_agent\x18\x02 \x01(\t\x12\x0b\n\x03ver\x18\x03 \x01(\t\x12\x11\n\tdevice_id\x18\x04 \x01(\t\x12\x0c\n\x04lang\x18\x05 \x01(\t\"\xa0\x01\n\tClientAcc\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12\x0e\n\x06scheme\x18\x03 \x01(\t\x12\x0e\n\x06secret\x18\x04 \x01(\x0c\x12\r\n\x05login\x18\x05 \x01(\x08\x12\x0c\n\x04tags\x18\x06 \x03(\t\x12\x1a\n\x04\x64\x65sc\x18\x07 \x01(\x0b\x32\x0c.pbx.SetDesc\x12\x1d\n\x04\x63red\x18\x08 \x03(\x0b\x32\x0f.pbx.Credential\"X\n\x0b\x43lientLogin\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06scheme\x18\x02 \x01(\t\x12\x0e\n\x06secret\x18\x03 \x01(\x0c\x12\x1d\n\x04\x63red\x18\x04 \x03(\x0b\x32\x0f.pbx.Credential\"j\n\tClientSub\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12 \n\tset_query\x18\x03 \x01(\x0b\x32\r.pbx.SetQuery\x12 \n\tget_query\x18\x04 \x01(\x0b\x32\r.pbx.GetQuery\"7\n\x0b\x43lientLeave\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\r\n\x05unsub\x18\x03 \x01(\x08\"\x9d\x01\n\tClientPub\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0f\n\x07no_echo\x18\x03 \x01(\x08\x12&\n\x04head\x18\x04 \x03(\x0b\x32\x18.pbx.ClientPub.HeadEntry\x12\x0f\n\x07\x63ontent\x18\x05 \x01(\x0c\x1a+\n\tHeadEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"D\n\tClientGet\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x1c\n\x05query\x18\x03 \x01(\x0b\x32\r.pbx.GetQuery\"D\n\tClientSet\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x1c\n\x05query\x18\x03 \x01(\x0b\x32\r.pbx.SetQuery\"\xad\x01\n\tClientDel\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12!\n\x04what\x18\x03 \x01(\x0e\x32\x13.pbx.ClientDel.What\x12\x1e\n\x07\x64\x65l_seq\x18\x04 \x03(\x0b\x32\r.pbx.SeqRange\x12\x0f\n\x07user_id\x18\x05 \x01(\t\x12\x0c\n\x04hard\x18\x06 \x01(\x08\"#\n\x04What\x12\x07\n\x03MSG\x10\x00\x12\t\n\x05TOPIC\x10\x01\x12\x07\n\x03SUB\x10\x02\"H\n\nClientNote\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x1b\n\x04what\x18\x02 \x01(\x0e\x32\r.pbx.InfoNote\x12\x0e\n\x06seq_id\x18\x03 \x01(\x05\"\xd4\x02\n\tClientMsg\x12\x1b\n\x02hi\x18\x01 \x01(\x0b\x32\r.pbx.ClientHiH\x00\x12\x1d\n\x03\x61\x63\x63\x18\x02 \x01(\x0b\x32\x0e.pbx.ClientAccH\x00\x12!\n\x05login\x18\x03 \x01(\x0b\x32\x10.pbx.ClientLoginH\x00\x12\x1d\n\x03sub\x18\x04 \x01(\x0b\x32\x0e.pbx.ClientSubH\x00\x12!\n\x05leave\x18\x05 \x01(\x0b\x32\x10.pbx.ClientLeaveH\x00\x12\x1d\n\x03pub\x18\x06 \x01(\x0b\x32\x0e.pbx.ClientPubH\x00\x12\x1d\n\x03get\x18\x07 \x01(\x0b\x32\x0e.pbx.ClientGetH\x00\x12\x1d\n\x03set\x18\x08 \x01(\x0b\x32\x0e.pbx.ClientSetH\x00\x12\x1d\n\x03\x64\x65l\x18\t \x01(\x0b\x32\x0e.pbx.ClientDelH\x00\x12\x1f\n\x04note\x18\n \x01(\x0b\x32\x0f.pbx.ClientNoteH\x00\x42\t\n\x07Message\"\xed\x01\n\tTopicDesc\x12\x12\n\ncreated_at\x18\x01 \x01(\x03\x12\x12\n\nupdated_at\x18\x02 \x01(\x03\x12\x12\n\ntouched_at\x18\x03 \x01(\x03\x12#\n\x06\x64\x65\x66\x61\x63s\x18\x04 \x01(\x0b\x32\x13.pbx.DefaultAcsMode\x12\x1c\n\x03\x61\x63s\x18\x05 \x01(\x0b\x32\x0f.pbx.AccessMode\x12\x0e\n\x06seq_id\x18\x06 \x01(\x05\x12\x0f\n\x07read_id\x18\x07 \x01(\x05\x12\x0f\n\x07recv_id\x18\x08 \x01(\x05\x12\x0e\n\x06\x64\x65l_id\x18\t \x01(\x05\x12\x0e\n\x06public\x18\n \x01(\x0c\x12\x0f\n\x07private\x18\x0b \x01(\x0c\"\xad\x02\n\x08TopicSub\x12\x12\n\nupdated_at\x18\x01 \x01(\x03\x12\x12\n\ndeleted_at\x18\x02 \x01(\x03\x12\x0e\n\x06online\x18\x03 \x01(\x08\x12\x1c\n\x03\x61\x63s\x18\x04 \x01(\x0b\x32\x0f.pbx.AccessMode\x12\x0f\n\x07read_id\x18\x05 \x01(\x05\x12\x0f\n\x07recv_id\x18\x06 \x01(\x05\x12\x0e\n\x06public\x18\x07 \x01(\x0c\x12\x0f\n\x07private\x18\x08 \x01(\x0c\x12\x0f\n\x07user_id\x18\t \x01(\t\x12\r\n\x05topic\x18\n \x01(\t\x12\x12\n\ntouched_at\x18\x0b \x01(\x03\x12\x0e\n\x06seq_id\x18\x0c \x01(\x05\x12\x0e\n\x06\x64\x65l_id\x18\r \x01(\x05\x12\x16\n\x0elast_seen_time\x18\x0e \x01(\x03\x12\x1c\n\x14last_seen_user_agent\x18\x0f \x01(\t\";\n\tDelValues\x12\x0e\n\x06\x64\x65l_id\x18\x01 \x01(\x05\x12\x1e\n\x07\x64\x65l_seq\x18\x02 \x03(\x0b\x32\r.pbx.SeqRange\"\x9f\x01\n\nServerCtrl\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0c\n\x04\x63ode\x18\x03 \x01(\x05\x12\x0c\n\x04text\x18\x04 \x01(\t\x12+\n\x06params\x18\x05 \x03(\x0b\x32\x1b.pbx.ServerCtrl.ParamsEntry\x1a-\n\x0bParamsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xbc\x01\n\nServerData\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x14\n\x0c\x66rom_user_id\x18\x02 \x01(\t\x12\x12\n\ndeleted_at\x18\x03 \x01(\x03\x12\x0e\n\x06seq_id\x18\x04 \x01(\x05\x12\'\n\x04head\x18\x05 \x03(\x0b\x32\x19.pbx.ServerData.HeadEntry\x12\x0f\n\x07\x63ontent\x18\x06 \x01(\x0c\x1a+\n\tHeadEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xda\x02\n\nServerPres\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x0b\n\x03src\x18\x02 \x01(\t\x12\"\n\x04what\x18\x03 \x01(\x0e\x32\x14.pbx.ServerPres.What\x12\x12\n\nuser_agent\x18\x04 \x01(\t\x12\x0e\n\x06seq_id\x18\x05 \x01(\x05\x12\x0e\n\x06\x64\x65l_id\x18\x06 \x01(\x05\x12\x1e\n\x07\x64\x65l_seq\x18\x07 \x03(\x0b\x32\r.pbx.SeqRange\x12\x16\n\x0etarget_user_id\x18\x08 \x01(\t\x12\x15\n\ractor_user_id\x18\t \x01(\t\x12\x1c\n\x03\x61\x63s\x18\n \x01(\x0b\x32\x0f.pbx.AccessMode\"k\n\x04What\x12\x06\n\x02ON\x10\x00\x12\x07\n\x03OFF\x10\x01\x12\x06\n\x02UA\x10\x03\x12\x07\n\x03UPD\x10\x04\x12\x08\n\x04GONE\x10\x05\x12\x07\n\x03\x41\x43S\x10\x06\x12\x08\n\x04TERM\x10\x07\x12\x07\n\x03MSG\x10\x08\x12\x08\n\x04READ\x10\t\x12\x08\n\x04RECV\x10\n\x12\x07\n\x03\x44\x45L\x10\x0b\"~\n\nServerMeta\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x1c\n\x04\x64\x65sc\x18\x03 \x01(\x0b\x32\x0e.pbx.TopicDesc\x12\x1a\n\x03sub\x18\x04 \x03(\x0b\x32\r.pbx.TopicSub\x12\x1b\n\x03\x64\x65l\x18\x05 \x01(\x0b\x32\x0e.pbx.DelValues\"^\n\nServerInfo\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x14\n\x0c\x66rom_user_id\x18\x02 \x01(\t\x12\x1b\n\x04what\x18\x03 \x01(\x0e\x32\r.pbx.InfoNote\x12\x0e\n\x06seq_id\x18\x04 \x01(\x05\"\xbb\x01\n\tServerMsg\x12\x1f\n\x04\x63trl\x18\x01 \x01(\x0b\x32\x0f.pbx.ServerCtrlH\x00\x12\x1f\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x0f.pbx.ServerDataH\x00\x12\x1f\n\x04pres\x18\x03 \x01(\x0b\x32\x0f.pbx.ServerPresH\x00\x12\x1f\n\x04meta\x18\x04 \x01(\x0b\x32\x0f.pbx.ServerMetaH\x00\x12\x1f\n\x04info\x18\x05 \x01(\x0b\x32\x0f.pbx.ServerInfoH\x00\x42\t\n\x07Message\"j\n\nServerResp\x12\x1d\n\x06status\x18\x01 \x01(\x0e\x32\r.pbx.RespCode\x12\x1e\n\x06srvmsg\x18\x02 \x01(\x0b\x32\x0e.pbx.ServerMsg\x12\x1d\n\x05\x63lmsg\x18\x03 \x01(\x0b\x32\x0e.pbx.ClientMsg\"\xdd\x01\n\x07Session\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12*\n\nauth_level\x18\x03 \x01(\x0e\x32\x16.pbx.Session.AuthLevel\x12\x13\n\x0bremote_addr\x18\x04 \x01(\t\x12\x12\n\nuser_agent\x18\x05 \x01(\t\x12\x11\n\tdevice_id\x18\x06 \x01(\t\x12\x10\n\x08language\x18\x07 \x01(\t\"3\n\tAuthLevel\x12\x08\n\x04NONE\x10\x00\x12\x08\n\x04\x41NON\x10\n\x12\x08\n\x04\x41UTH\x10\x14\x12\x08\n\x04ROOT\x10\x1e\"D\n\tClientReq\x12\x1b\n\x03msg\x18\x01 \x01(\x0b\x32\x0e.pbx.ClientMsg\x12\x1a\n\x04sess\x18\x02 \x01(\x0b\x32\x0c.pbx.Session\"-\n\x0bSearchQuery\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t\"Z\n\x0bSearchFound\x12\x1d\n\x06status\x18\x01 \x01(\x0e\x32\r.pbx.RespCode\x12\r\n\x05query\x18\x02 \x01(\t\x12\x1d\n\x06result\x18\x03 \x03(\x0b\x32\r.pbx.TopicSub\"S\n\nTopicEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x1c\n\x04\x64\x65sc\x18\x03 \x01(\x0b\x32\x0e.pbx.TopicDesc\"\x82\x01\n\x0c\x41\x63\x63ountEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12(\n\x0b\x64\x65\x66\x61ult_acs\x18\x03 \x01(\x0b\x32\x13.pbx.DefaultAcsMode\x12\x0e\n\x06public\x18\x04 \x01(\x0c\x12\x0c\n\x04tags\x18\x08 \x03(\t\"\xb0\x01\n\x11SubscriptionEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0f\n\x07user_id\x18\x03 \x01(\t\x12\x0e\n\x06\x64\x65l_id\x18\x04 \x01(\x05\x12\x0f\n\x07read_id\x18\x05 \x01(\x05\x12\x0f\n\x07recv_id\x18\x06 \x01(\x05\x12\x1d\n\x04mode\x18\x07 \x01(\x0b\x32\x0f.pbx.AccessMode\x12\x0f\n\x07private\x18\x08 \x01(\x0c\"G\n\x0cMessageEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\x1c\n\x03msg\x18\x02 \x01(\x0b\x32\x0f.pbx.ServerData*&\n\x08InfoNote\x12\x08\n\x04READ\x10\x00\x12\x08\n\x04RECV\x10\x01\x12\x06\n\x02KP\x10\x02*<\n\x08RespCode\x12\x0c\n\x08\x43ONTINUE\x10\x00\x12\x08\n\x04\x44ROP\x10\x01\x12\x0b\n\x07RESPOND\x10\x02\x12\x0b\n\x07REPLACE\x10\x03**\n\x04\x43rud\x12\n\n\x06\x43REATE\x10\x00\x12\n\n\x06UPDATE\x10\x01\x12\n\n\x06\x44\x45LETE\x10\x02\x32;\n\x04Node\x12\x33\n\x0bMessageLoop\x12\x0e.pbx.ClientMsg\x1a\x0e.pbx.ServerMsg\"\x00(\x01\x30\x01\x32\x9f\x02\n\x06Plugin\x12-\n\x08\x46ireHose\x12\x0e.pbx.ClientReq\x1a\x0f.pbx.ServerResp\"\x00\x12,\n\x04\x46ind\x12\x10.pbx.SearchQuery\x1a\x10.pbx.SearchFound\"\x00\x12+\n\x07\x41\x63\x63ount\x12\x11.pbx.AccountEvent\x1a\x0b.pbx.Unused\"\x00\x12\'\n\x05Topic\x12\x0f.pbx.TopicEvent\x1a\x0b.pbx.Unused\"\x00\x12\x35\n\x0cSubscription\x12\x16.pbx.SubscriptionEvent\x1a\x0b.pbx.Unused\"\x00\x12+\n\x07Message\x12\x11.pbx.MessageEvent\x1a\x0b.pbx.Unused\"\x00\x62\x06proto3') + serialized_pb=_b('\n\x0bmodel.proto\x12\x03pbx\"\x08\n\x06Unused\",\n\x0e\x44\x65\x66\x61ultAcsMode\x12\x0c\n\x04\x61uth\x18\x01 \x01(\t\x12\x0c\n\x04\x61non\x18\x02 \x01(\t\")\n\nAccessMode\x12\x0c\n\x04want\x18\x01 \x01(\t\x12\r\n\x05given\x18\x02 \x01(\t\"\'\n\x06SetSub\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x0c\n\x04mode\x18\x02 \x01(\t\"T\n\x07SetDesc\x12(\n\x0b\x64\x65\x66\x61ult_acs\x18\x01 \x01(\x0b\x32\x13.pbx.DefaultAcsMode\x12\x0e\n\x06public\x18\x02 \x01(\x0c\x12\x0f\n\x07private\x18\x03 \x01(\x0c\"u\n\x07GetOpts\x12\x19\n\x11if_modified_since\x18\x01 \x01(\x03\x12\x0c\n\x04user\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x10\n\x08since_id\x18\x04 \x01(\x05\x12\x11\n\tbefore_id\x18\x05 \x01(\x05\x12\r\n\x05limit\x18\x06 \x01(\x05\"k\n\x08GetQuery\x12\x0c\n\x04what\x18\x01 \x01(\t\x12\x1a\n\x04\x64\x65sc\x18\x02 \x01(\x0b\x32\x0c.pbx.GetOpts\x12\x19\n\x03sub\x18\x03 \x01(\x0b\x32\x0c.pbx.GetOpts\x12\x1a\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32\x0c.pbx.GetOpts\"N\n\x08SetQuery\x12\x1a\n\x04\x64\x65sc\x18\x01 \x01(\x0b\x32\x0c.pbx.SetDesc\x12\x18\n\x03sub\x18\x02 \x01(\x0b\x32\x0b.pbx.SetSub\x12\x0c\n\x04tags\x18\x03 \x03(\t\"#\n\x08SeqRange\x12\x0b\n\x03low\x18\x01 \x01(\x05\x12\n\n\x02hi\x18\x02 \x01(\x05\"M\n\nCredential\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12\x10\n\x08response\x18\x03 \x01(\t\x12\x0e\n\x06params\x18\x04 \x01(\x0c\"X\n\x08\x43lientHi\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nuser_agent\x18\x02 \x01(\t\x12\x0b\n\x03ver\x18\x03 \x01(\t\x12\x11\n\tdevice_id\x18\x04 \x01(\t\x12\x0c\n\x04lang\x18\x05 \x01(\t\"\xa0\x01\n\tClientAcc\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12\x0e\n\x06scheme\x18\x03 \x01(\t\x12\x0e\n\x06secret\x18\x04 \x01(\x0c\x12\r\n\x05login\x18\x05 \x01(\x08\x12\x0c\n\x04tags\x18\x06 \x03(\t\x12\x1a\n\x04\x64\x65sc\x18\x07 \x01(\x0b\x32\x0c.pbx.SetDesc\x12\x1d\n\x04\x63red\x18\x08 \x03(\x0b\x32\x0f.pbx.Credential\"X\n\x0b\x43lientLogin\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0e\n\x06scheme\x18\x02 \x01(\t\x12\x0e\n\x06secret\x18\x03 \x01(\x0c\x12\x1d\n\x04\x63red\x18\x04 \x03(\x0b\x32\x0f.pbx.Credential\"j\n\tClientSub\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12 \n\tset_query\x18\x03 \x01(\x0b\x32\r.pbx.SetQuery\x12 \n\tget_query\x18\x04 \x01(\x0b\x32\r.pbx.GetQuery\"7\n\x0b\x43lientLeave\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\r\n\x05unsub\x18\x03 \x01(\x08\"\x9d\x01\n\tClientPub\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0f\n\x07no_echo\x18\x03 \x01(\x08\x12&\n\x04head\x18\x04 \x03(\x0b\x32\x18.pbx.ClientPub.HeadEntry\x12\x0f\n\x07\x63ontent\x18\x05 \x01(\x0c\x1a+\n\tHeadEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"D\n\tClientGet\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x1c\n\x05query\x18\x03 \x01(\x0b\x32\r.pbx.GetQuery\"D\n\tClientSet\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x1c\n\x05query\x18\x03 \x01(\x0b\x32\r.pbx.SetQuery\"\xad\x01\n\tClientDel\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12!\n\x04what\x18\x03 \x01(\x0e\x32\x13.pbx.ClientDel.What\x12\x1e\n\x07\x64\x65l_seq\x18\x04 \x03(\x0b\x32\r.pbx.SeqRange\x12\x0f\n\x07user_id\x18\x05 \x01(\t\x12\x0c\n\x04hard\x18\x06 \x01(\x08\"#\n\x04What\x12\x07\n\x03MSG\x10\x00\x12\t\n\x05TOPIC\x10\x01\x12\x07\n\x03SUB\x10\x02\"H\n\nClientNote\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x1b\n\x04what\x18\x02 \x01(\x0e\x32\r.pbx.InfoNote\x12\x0e\n\x06seq_id\x18\x03 \x01(\x05\"\x8e\x03\n\tClientMsg\x12\x1b\n\x02hi\x18\x01 \x01(\x0b\x32\r.pbx.ClientHiH\x00\x12\x1d\n\x03\x61\x63\x63\x18\x02 \x01(\x0b\x32\x0e.pbx.ClientAccH\x00\x12!\n\x05login\x18\x03 \x01(\x0b\x32\x10.pbx.ClientLoginH\x00\x12\x1d\n\x03sub\x18\x04 \x01(\x0b\x32\x0e.pbx.ClientSubH\x00\x12!\n\x05leave\x18\x05 \x01(\x0b\x32\x10.pbx.ClientLeaveH\x00\x12\x1d\n\x03pub\x18\x06 \x01(\x0b\x32\x0e.pbx.ClientPubH\x00\x12\x1d\n\x03get\x18\x07 \x01(\x0b\x32\x0e.pbx.ClientGetH\x00\x12\x1d\n\x03set\x18\x08 \x01(\x0b\x32\x0e.pbx.ClientSetH\x00\x12\x1d\n\x03\x64\x65l\x18\t \x01(\x0b\x32\x0e.pbx.ClientDelH\x00\x12\x1f\n\x04note\x18\n \x01(\x0b\x32\x0f.pbx.ClientNoteH\x00\x12\x14\n\x0con_behalf_of\x18\x0b \x01(\t\x12\"\n\nauth_level\x18\x0c \x01(\x0e\x32\x0e.pbx.AuthLevelB\t\n\x07Message\"\xed\x01\n\tTopicDesc\x12\x12\n\ncreated_at\x18\x01 \x01(\x03\x12\x12\n\nupdated_at\x18\x02 \x01(\x03\x12\x12\n\ntouched_at\x18\x03 \x01(\x03\x12#\n\x06\x64\x65\x66\x61\x63s\x18\x04 \x01(\x0b\x32\x13.pbx.DefaultAcsMode\x12\x1c\n\x03\x61\x63s\x18\x05 \x01(\x0b\x32\x0f.pbx.AccessMode\x12\x0e\n\x06seq_id\x18\x06 \x01(\x05\x12\x0f\n\x07read_id\x18\x07 \x01(\x05\x12\x0f\n\x07recv_id\x18\x08 \x01(\x05\x12\x0e\n\x06\x64\x65l_id\x18\t \x01(\x05\x12\x0e\n\x06public\x18\n \x01(\x0c\x12\x0f\n\x07private\x18\x0b \x01(\x0c\"\xad\x02\n\x08TopicSub\x12\x12\n\nupdated_at\x18\x01 \x01(\x03\x12\x12\n\ndeleted_at\x18\x02 \x01(\x03\x12\x0e\n\x06online\x18\x03 \x01(\x08\x12\x1c\n\x03\x61\x63s\x18\x04 \x01(\x0b\x32\x0f.pbx.AccessMode\x12\x0f\n\x07read_id\x18\x05 \x01(\x05\x12\x0f\n\x07recv_id\x18\x06 \x01(\x05\x12\x0e\n\x06public\x18\x07 \x01(\x0c\x12\x0f\n\x07private\x18\x08 \x01(\x0c\x12\x0f\n\x07user_id\x18\t \x01(\t\x12\r\n\x05topic\x18\n \x01(\t\x12\x12\n\ntouched_at\x18\x0b \x01(\x03\x12\x0e\n\x06seq_id\x18\x0c \x01(\x05\x12\x0e\n\x06\x64\x65l_id\x18\r \x01(\x05\x12\x16\n\x0elast_seen_time\x18\x0e \x01(\x03\x12\x1c\n\x14last_seen_user_agent\x18\x0f \x01(\t\";\n\tDelValues\x12\x0e\n\x06\x64\x65l_id\x18\x01 \x01(\x05\x12\x1e\n\x07\x64\x65l_seq\x18\x02 \x03(\x0b\x32\r.pbx.SeqRange\"\x9f\x01\n\nServerCtrl\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0c\n\x04\x63ode\x18\x03 \x01(\x05\x12\x0c\n\x04text\x18\x04 \x01(\t\x12+\n\x06params\x18\x05 \x03(\x0b\x32\x1b.pbx.ServerCtrl.ParamsEntry\x1a-\n\x0bParamsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xbc\x01\n\nServerData\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x14\n\x0c\x66rom_user_id\x18\x02 \x01(\t\x12\x12\n\ndeleted_at\x18\x03 \x01(\x03\x12\x0e\n\x06seq_id\x18\x04 \x01(\x05\x12\'\n\x04head\x18\x05 \x03(\x0b\x32\x19.pbx.ServerData.HeadEntry\x12\x0f\n\x07\x63ontent\x18\x06 \x01(\x0c\x1a+\n\tHeadEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"\xda\x02\n\nServerPres\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x0b\n\x03src\x18\x02 \x01(\t\x12\"\n\x04what\x18\x03 \x01(\x0e\x32\x14.pbx.ServerPres.What\x12\x12\n\nuser_agent\x18\x04 \x01(\t\x12\x0e\n\x06seq_id\x18\x05 \x01(\x05\x12\x0e\n\x06\x64\x65l_id\x18\x06 \x01(\x05\x12\x1e\n\x07\x64\x65l_seq\x18\x07 \x03(\x0b\x32\r.pbx.SeqRange\x12\x16\n\x0etarget_user_id\x18\x08 \x01(\t\x12\x15\n\ractor_user_id\x18\t \x01(\t\x12\x1c\n\x03\x61\x63s\x18\n \x01(\x0b\x32\x0f.pbx.AccessMode\"k\n\x04What\x12\x06\n\x02ON\x10\x00\x12\x07\n\x03OFF\x10\x01\x12\x06\n\x02UA\x10\x03\x12\x07\n\x03UPD\x10\x04\x12\x08\n\x04GONE\x10\x05\x12\x07\n\x03\x41\x43S\x10\x06\x12\x08\n\x04TERM\x10\x07\x12\x07\n\x03MSG\x10\x08\x12\x08\n\x04READ\x10\t\x12\x08\n\x04RECV\x10\n\x12\x07\n\x03\x44\x45L\x10\x0b\"~\n\nServerMeta\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x1c\n\x04\x64\x65sc\x18\x03 \x01(\x0b\x32\x0e.pbx.TopicDesc\x12\x1a\n\x03sub\x18\x04 \x03(\x0b\x32\r.pbx.TopicSub\x12\x1b\n\x03\x64\x65l\x18\x05 \x01(\x0b\x32\x0e.pbx.DelValues\"^\n\nServerInfo\x12\r\n\x05topic\x18\x01 \x01(\t\x12\x14\n\x0c\x66rom_user_id\x18\x02 \x01(\t\x12\x1b\n\x04what\x18\x03 \x01(\x0e\x32\r.pbx.InfoNote\x12\x0e\n\x06seq_id\x18\x04 \x01(\x05\"\xca\x01\n\tServerMsg\x12\x1f\n\x04\x63trl\x18\x01 \x01(\x0b\x32\x0f.pbx.ServerCtrlH\x00\x12\x1f\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x0f.pbx.ServerDataH\x00\x12\x1f\n\x04pres\x18\x03 \x01(\x0b\x32\x0f.pbx.ServerPresH\x00\x12\x1f\n\x04meta\x18\x04 \x01(\x0b\x32\x0f.pbx.ServerMetaH\x00\x12\x1f\n\x04info\x18\x05 \x01(\x0b\x32\x0f.pbx.ServerInfoH\x00\x12\r\n\x05topic\x18\x06 \x01(\tB\t\n\x07Message\"j\n\nServerResp\x12\x1d\n\x06status\x18\x01 \x01(\x0e\x32\r.pbx.RespCode\x12\x1e\n\x06srvmsg\x18\x02 \x01(\x0b\x32\x0e.pbx.ServerMsg\x12\x1d\n\x05\x63lmsg\x18\x03 \x01(\x0b\x32\x0e.pbx.ClientMsg\"\xa0\x01\n\x07Session\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12\"\n\nauth_level\x18\x03 \x01(\x0e\x32\x0e.pbx.AuthLevel\x12\x13\n\x0bremote_addr\x18\x04 \x01(\t\x12\x12\n\nuser_agent\x18\x05 \x01(\t\x12\x11\n\tdevice_id\x18\x06 \x01(\t\x12\x10\n\x08language\x18\x07 \x01(\t\"D\n\tClientReq\x12\x1b\n\x03msg\x18\x01 \x01(\x0b\x32\x0e.pbx.ClientMsg\x12\x1a\n\x04sess\x18\x02 \x01(\x0b\x32\x0c.pbx.Session\"-\n\x0bSearchQuery\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\r\n\x05query\x18\x02 \x01(\t\"Z\n\x0bSearchFound\x12\x1d\n\x06status\x18\x01 \x01(\x0e\x32\r.pbx.RespCode\x12\r\n\x05query\x18\x02 \x01(\t\x12\x1d\n\x06result\x18\x03 \x03(\x0b\x32\r.pbx.TopicSub\"S\n\nTopicEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x1c\n\x04\x64\x65sc\x18\x03 \x01(\x0b\x32\x0e.pbx.TopicDesc\"\x82\x01\n\x0c\x41\x63\x63ountEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12(\n\x0b\x64\x65\x66\x61ult_acs\x18\x03 \x01(\x0b\x32\x13.pbx.DefaultAcsMode\x12\x0e\n\x06public\x18\x04 \x01(\x0c\x12\x0c\n\x04tags\x18\x08 \x03(\t\"\xb0\x01\n\x11SubscriptionEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\r\n\x05topic\x18\x02 \x01(\t\x12\x0f\n\x07user_id\x18\x03 \x01(\t\x12\x0e\n\x06\x64\x65l_id\x18\x04 \x01(\x05\x12\x0f\n\x07read_id\x18\x05 \x01(\x05\x12\x0f\n\x07recv_id\x18\x06 \x01(\x05\x12\x1d\n\x04mode\x18\x07 \x01(\x0b\x32\x0f.pbx.AccessMode\x12\x0f\n\x07private\x18\x08 \x01(\x0c\"G\n\x0cMessageEvent\x12\x19\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\t.pbx.Crud\x12\x1c\n\x03msg\x18\x02 \x01(\x0b\x32\x0f.pbx.ServerData*3\n\tAuthLevel\x12\x08\n\x04NONE\x10\x00\x12\x08\n\x04\x41NON\x10\n\x12\x08\n\x04\x41UTH\x10\x14\x12\x08\n\x04ROOT\x10\x1e*&\n\x08InfoNote\x12\x08\n\x04READ\x10\x00\x12\x08\n\x04RECV\x10\x01\x12\x06\n\x02KP\x10\x02*<\n\x08RespCode\x12\x0c\n\x08\x43ONTINUE\x10\x00\x12\x08\n\x04\x44ROP\x10\x01\x12\x0b\n\x07RESPOND\x10\x02\x12\x0b\n\x07REPLACE\x10\x03**\n\x04\x43rud\x12\n\n\x06\x43REATE\x10\x00\x12\n\n\x06UPDATE\x10\x01\x12\n\n\x06\x44\x45LETE\x10\x02\x32;\n\x04Node\x12\x33\n\x0bMessageLoop\x12\x0e.pbx.ClientMsg\x1a\x0e.pbx.ServerMsg\"\x00(\x01\x30\x01\x32\x9f\x02\n\x06Plugin\x12-\n\x08\x46ireHose\x12\x0e.pbx.ClientReq\x1a\x0f.pbx.ServerResp\"\x00\x12,\n\x04\x46ind\x12\x10.pbx.SearchQuery\x1a\x10.pbx.SearchFound\"\x00\x12+\n\x07\x41\x63\x63ount\x12\x11.pbx.AccountEvent\x1a\x0b.pbx.Unused\"\x00\x12\'\n\x05Topic\x12\x0f.pbx.TopicEvent\x1a\x0b.pbx.Unused\"\x00\x12\x35\n\x0cSubscription\x12\x16.pbx.SubscriptionEvent\x1a\x0b.pbx.Unused\"\x00\x12+\n\x07Message\x12\x11.pbx.MessageEvent\x1a\x0b.pbx.Unused\"\x00\x62\x06proto3') ) +_AUTHLEVEL = _descriptor.EnumDescriptor( + name='AuthLevel', + full_name='pbx.AuthLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NONE', index=0, number=0, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ANON', index=1, number=10, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='AUTH', index=2, number=20, + options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ROOT', index=3, number=30, + options=None, + type=None), + ], + containing_type=None, + options=None, + serialized_start=4815, + serialized_end=4866, +) +_sym_db.RegisterEnumDescriptor(_AUTHLEVEL) + +AuthLevel = enum_type_wrapper.EnumTypeWrapper(_AUTHLEVEL) _INFONOTE = _descriptor.EnumDescriptor( name='InfoNote', full_name='pbx.InfoNote', @@ -44,8 +75,8 @@ ], containing_type=None, options=None, - serialized_start=4803, - serialized_end=4841, + serialized_start=4868, + serialized_end=4906, ) _sym_db.RegisterEnumDescriptor(_INFONOTE) @@ -75,8 +106,8 @@ ], containing_type=None, options=None, - serialized_start=4843, - serialized_end=4903, + serialized_start=4908, + serialized_end=4968, ) _sym_db.RegisterEnumDescriptor(_RESPCODE) @@ -102,12 +133,16 @@ ], containing_type=None, options=None, - serialized_start=4905, - serialized_end=4947, + serialized_start=4970, + serialized_end=5012, ) _sym_db.RegisterEnumDescriptor(_CRUD) Crud = enum_type_wrapper.EnumTypeWrapper(_CRUD) +NONE = 0 +ANON = 10 +AUTH = 20 +ROOT = 30 READ = 0 RECV = 1 KP = 2 @@ -199,41 +234,11 @@ ], containing_type=None, options=None, - serialized_start=3269, - serialized_end=3376, + serialized_start=3327, + serialized_end=3434, ) _sym_db.RegisterEnumDescriptor(_SERVERPRES_WHAT) -_SESSION_AUTHLEVEL = _descriptor.EnumDescriptor( - name='AuthLevel', - full_name='pbx.Session.AuthLevel', - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name='NONE', index=0, number=0, - options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='ANON', index=1, number=10, - options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='AUTH', index=2, number=20, - options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='ROOT', index=3, number=30, - options=None, - type=None), - ], - containing_type=None, - options=None, - serialized_start=4071, - serialized_end=4122, -) -_sym_db.RegisterEnumDescriptor(_SESSION_AUTHLEVEL) - _UNUSED = _descriptor.Descriptor( name='Unused', @@ -1334,6 +1339,20 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='on_behalf_of', full_name='pbx.ClientMsg.on_behalf_of', index=10, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='auth_level', full_name='pbx.ClientMsg.auth_level', index=11, + number=12, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -1350,7 +1369,7 @@ index=0, containing_type=None, fields=[]), ], serialized_start=1729, - serialized_end=2069, + serialized_end=2127, ) @@ -1450,8 +1469,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2072, - serialized_end=2309, + serialized_start=2130, + serialized_end=2367, ) @@ -1579,8 +1598,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2312, - serialized_end=2613, + serialized_start=2370, + serialized_end=2671, ) @@ -1617,8 +1636,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2615, - serialized_end=2674, + serialized_start=2673, + serialized_end=2732, ) @@ -1655,8 +1674,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2791, - serialized_end=2836, + serialized_start=2849, + serialized_end=2894, ) _SERVERCTRL = _descriptor.Descriptor( @@ -1713,8 +1732,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2677, - serialized_end=2836, + serialized_start=2735, + serialized_end=2894, ) @@ -1816,8 +1835,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2839, - serialized_end=3027, + serialized_start=2897, + serialized_end=3085, ) @@ -1911,8 +1930,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3030, - serialized_end=3376, + serialized_start=3088, + serialized_end=3434, ) @@ -1970,8 +1989,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3378, - serialized_end=3504, + serialized_start=3436, + serialized_end=3562, ) @@ -2022,8 +2041,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3506, - serialized_end=3600, + serialized_start=3564, + serialized_end=3658, ) @@ -2069,6 +2088,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='topic', full_name='pbx.ServerMsg.topic', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -2084,8 +2110,8 @@ name='Message', full_name='pbx.ServerMsg.Message', index=0, containing_type=None, fields=[]), ], - serialized_start=3603, - serialized_end=3790, + serialized_start=3661, + serialized_end=3863, ) @@ -2129,8 +2155,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3792, - serialized_end=3898, + serialized_start=3865, + serialized_end=3971, ) @@ -2195,7 +2221,6 @@ ], nested_types=[], enum_types=[ - _SESSION_AUTHLEVEL, ], options=None, is_extendable=False, @@ -2203,8 +2228,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3901, - serialized_end=4122, + serialized_start=3974, + serialized_end=4134, ) @@ -2241,8 +2266,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4124, - serialized_end=4192, + serialized_start=4136, + serialized_end=4204, ) @@ -2279,8 +2304,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4194, - serialized_end=4239, + serialized_start=4206, + serialized_end=4251, ) @@ -2324,8 +2349,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4241, - serialized_end=4331, + serialized_start=4253, + serialized_end=4343, ) @@ -2369,8 +2394,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4333, - serialized_end=4416, + serialized_start=4345, + serialized_end=4428, ) @@ -2428,8 +2453,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4419, - serialized_end=4549, + serialized_start=4431, + serialized_end=4561, ) @@ -2508,8 +2533,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4552, - serialized_end=4728, + serialized_start=4564, + serialized_end=4740, ) @@ -2546,8 +2571,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4730, - serialized_end=4801, + serialized_start=4742, + serialized_end=4813, ) _SETDESC.fields_by_name['default_acs'].message_type = _DEFAULTACSMODE @@ -2579,6 +2604,7 @@ _CLIENTMSG.fields_by_name['set'].message_type = _CLIENTSET _CLIENTMSG.fields_by_name['del'].message_type = _CLIENTDEL _CLIENTMSG.fields_by_name['note'].message_type = _CLIENTNOTE +_CLIENTMSG.fields_by_name['auth_level'].enum_type = _AUTHLEVEL _CLIENTMSG.oneofs_by_name['Message'].fields.append( _CLIENTMSG.fields_by_name['hi']) _CLIENTMSG.fields_by_name['hi'].containing_oneof = _CLIENTMSG.oneofs_by_name['Message'] @@ -2648,8 +2674,7 @@ _SERVERRESP.fields_by_name['status'].enum_type = _RESPCODE _SERVERRESP.fields_by_name['srvmsg'].message_type = _SERVERMSG _SERVERRESP.fields_by_name['clmsg'].message_type = _CLIENTMSG -_SESSION.fields_by_name['auth_level'].enum_type = _SESSION_AUTHLEVEL -_SESSION_AUTHLEVEL.containing_type = _SESSION +_SESSION.fields_by_name['auth_level'].enum_type = _AUTHLEVEL _CLIENTREQ.fields_by_name['msg'].message_type = _CLIENTMSG _CLIENTREQ.fields_by_name['sess'].message_type = _SESSION _SEARCHFOUND.fields_by_name['status'].enum_type = _RESPCODE @@ -2701,6 +2726,7 @@ DESCRIPTOR.message_types_by_name['AccountEvent'] = _ACCOUNTEVENT DESCRIPTOR.message_types_by_name['SubscriptionEvent'] = _SUBSCRIPTIONEVENT DESCRIPTOR.message_types_by_name['MessageEvent'] = _MESSAGEEVENT +DESCRIPTOR.enum_types_by_name['AuthLevel'] = _AUTHLEVEL DESCRIPTOR.enum_types_by_name['InfoNote'] = _INFONOTE DESCRIPTOR.enum_types_by_name['RespCode'] = _RESPCODE DESCRIPTOR.enum_types_by_name['Crud'] = _CRUD @@ -3017,8 +3043,8 @@ file=DESCRIPTOR, index=0, options=None, - serialized_start=4949, - serialized_end=5008, + serialized_start=5014, + serialized_end=5073, methods=[ _descriptor.MethodDescriptor( name='MessageLoop', @@ -3041,8 +3067,8 @@ file=DESCRIPTOR, index=1, options=None, - serialized_start=5011, - serialized_end=5298, + serialized_start=5076, + serialized_end=5363, methods=[ _descriptor.MethodDescriptor( name='FireHose', diff --git a/server/topic.go b/server/topic.go index 5b6de29f7..0f08fdb56 100644 --- a/server/topic.go +++ b/server/topic.go @@ -623,9 +623,10 @@ func (t *Topic) run(hub *Hub) { func (t *Topic) handleSubscription(h *Hub, sreg *sessionJoin) error { asUid := types.ParseUserId(sreg.pkt.from) + msgsub := sreg.pkt.Sub getWhat := 0 - if sreg.pkt.Get != nil { - getWhat = parseMsgClientMeta(sreg.pkt.Get.What) + if msgsub.Get != nil { + getWhat = parseMsgClientMeta(msgsub.Get.What) } if err := t.subCommonReply(h, sreg, (getWhat&constMsgMetaDesc != 0)); err != nil { @@ -705,7 +706,7 @@ func (t *Topic) handleSubscription(h *Hub, sreg *sessionJoin) error { if getWhat&constMsgMetaSub != 0 { // Send get.sub response as a separate {meta} packet - if err := t.replyGetSub(sreg.sess, asUid, sreg.pkt.id, sreg.pkt.Get.Sub); err != nil { + if err := t.replyGetSub(sreg.sess, asUid, sreg.pkt.id, msgsub.Get.Sub); err != nil { log.Printf("topic[%s] handleSubscription Get.Sub failed: %v", t.name, err) } } @@ -719,14 +720,14 @@ func (t *Topic) handleSubscription(h *Hub, sreg *sessionJoin) error { if getWhat&constMsgMetaData != 0 { // Send get.data response as {data} packets - if err := t.replyGetData(sreg.sess, asUid, sreg.pkt.id, sreg.pkt.Get.Data); err != nil { + if err := t.replyGetData(sreg.sess, asUid, sreg.pkt.id, msgsub.Get.Data); err != nil { log.Printf("topic[%s] handleSubscription Get.Data failed: %v", t.name, err) } } if getWhat&constMsgMetaDel != 0 { // Send get.del response as a separate {meta} packet - if err := t.replyGetDel(sreg.sess, asUid, sreg.pkt.id, sreg.pkt.Get.Del); err != nil { + if err := t.replyGetDel(sreg.sess, asUid, sreg.pkt.id, msgsub.Get.Del); err != nil { log.Printf("topic[%s] handleSubscription Get.Del failed: %v", t.name, err) } } diff --git a/tn-cli/README.md b/tn-cli/README.md index 0d76a8431..f2be5da68 100644 --- a/tn-cli/README.md +++ b/tn-cli/README.md @@ -25,3 +25,7 @@ The client takes optional parameters: * `--login-cookie` direct the client to read the token from the cookie file generated during an earlier login. If multiple `login-XYZ` are provided, `login-cookie` is considered first, then `login-token` then `login-basic`. Authentication with token (and cookie) is much faster than with the username-password pair. + +## Crash on shutdown + +Python 3 sometimes crashes on shutdown with a message `Fatal Python error: PyImport_GetModuleDict: no module dictionary!`. That happens because it's buggy: https://bugs.python.org/issue26153 diff --git a/tn-cli/tn-cli.py b/tn-cli/tn-cli.py index e747bdefb..15334bc78 100644 --- a/tn-cli/tn-cli.py +++ b/tn-cli/tn-cli.py @@ -35,9 +35,14 @@ # Saved topic: default topic name to make keyboard input easier SavedTopic = None -# IO queues for asynchronous input/output +# IO queues and thread for asynchronous input/output input_queue = queue.Queue() output_queue = queue.Queue() +input_thread = None + +# Default values for user and topic +default_user = None +default_topic = None # Pack user's name and avatar into a vcard represented as json. def make_vcard(fn, photofile): @@ -77,7 +82,9 @@ def stdout(*args): text = "" for a in args: text = text + str(a) + " " - output_queue.put(text) + text = text.strip(" ") + if text != "": + output_queue.put(text) def stdoutln(*args): args = args + ("\n",) @@ -114,7 +121,7 @@ def accMsg(id, user, scheme, secret, uname, password, do_login, fn, photo, priva return pb.ClientMsg(acc=pb.ClientAcc(id=str(id), user_id=user, scheme=scheme, secret=secret, login=do_login, tags=tags.split(",") if tags else None, desc=pb.SetDesc(default_acs=pb.DefaultAcsMode(auth=auth, anon=anon), - public=public, private=private, cred=parse_cred(cred)))) + public=public, private=private, cred=parse_cred(cred))), on_behalf_of=default_user) def loginMsg(id, scheme, secret, cred, uname, password): if secret == None and uname != None: @@ -129,6 +136,8 @@ def loginMsg(id, scheme, secret, cred, uname, password): secret=secret, cred=parse_cred(cred))) def subMsg(id, topic, fn, photo, private, auth, anon, mode, tags, get_query): + if not topic: + topic = default_topic if get_query: get_query = pb.GetQuery(what=get_query.split(",").join(" ")) public = encode_to_bytes(make_vcard(fn, photo)) @@ -137,9 +146,23 @@ def subMsg(id, topic, fn, photo, private, auth, anon, mode, tags, get_query): set_query=pb.SetQuery( desc=pb.SetDesc(public=public, private=private, default_acs=pb.DefaultAcsMode(auth=auth, anon=anon)), sub=pb.SetSub(mode=mode), - tags=tags.split(",") if tags else None), get_query=get_query)) + tags=tags.split(",") if tags else None), get_query=get_query), on_behalf_of=default_user) + +def leaveMsg(id, topic, unsub): + if not topic: + topic = default_topic + return pb.ClientMsg(leave=pb.ClientLeave(id=str(id), topic=topic, unsub=unsub), on_behalf_of=default_user) + +def pubMsg(id, topic, content): + if not topic: + topic = default_topic + return pb.ClientMsg(pub=pb.ClientPub(id=str(id), topic=topic, no_echo=True, + content=encode_to_bytes(content)), on_behalf_of=default_user) def getMsg(id, topic, desc, sub, tags, data): + if not topic: + topic = default_topic + what = [] if desc: what.append("desc") @@ -150,9 +173,13 @@ def getMsg(id, topic, desc, sub, tags, data): if data: what.append("data") return pb.ClientMsg(get=pb.ClientGet(id=str(id), topic=topic, - query=pb.GetQuery(what=" ".join(what)))) + query=pb.GetQuery(what=" ".join(what))), on_behalf_of=default_user) + def setMsg(id, topic, user, fn, photo, public, private, auth, anon, mode, tags): + if not topic: + topic = default_topic + if public == None: public = encode_to_bytes(make_vcard(fn, photo)) else: @@ -163,13 +190,17 @@ def setMsg(id, topic, user, fn, photo, public, private, auth, anon, mode, tags): desc=pb.SetDesc(default_acs=pb.DefaultAcsMode(auth=auth, anon=anon), public=public, private=private), sub=pb.SetSub(user_id=user, mode=mode), - tags=tags))) + tags=tags)), on_behalf_of=default_user) + def delMsg(id, topic, what, param, hard): if topic == None and param != None: topic = param param = None + if not topic: + topic = default_topic + stdoutln(id, topic, what, param, hard) enum_what = None before = None @@ -190,7 +221,7 @@ def delMsg(id, topic, what, param, hard): enum_what = pb.ClientDel.TOPIC # Field named 'del' conflicts with the keyword 'del. This is a work around. - msg = pb.ClientMsg() + msg = pb.ClientMsg(on_behalf_of=default_user) xdel = getattr(msg, 'del') """ setattr(msg, 'del', pb.ClientDel(id=str(id), topic=topic, what=enum_what, hard=hard, @@ -208,6 +239,9 @@ def delMsg(id, topic, what, param, hard): return msg def noteMsg(id, topic, what, seq): + if not topic: + topic = default_topic + enum_what = None if what == 'kp': enum_what = pb.KP @@ -218,7 +252,7 @@ def noteMsg(id, topic, what, seq): elif what == 'recv': enum_what = pb.READ seq = int(seq) - return pb.ClientMsg(note=pb.ClientNote(topic=topic, what=enum_what, seq_id=seq)) + return pb.ClientMsg(note=pb.ClientNote(topic=topic, what=enum_what, seq_id=seq), on_behalf_of=default_user) def parse_cmd(cmd): """Parses command line input into a dictionary""" @@ -227,7 +261,11 @@ def parse_cmd(cmd): return None parser = None - if parts[0] == "acc": + if parts[0] == ".use": + parser = argparse.ArgumentParser(prog=parts[0], description='Set default user or topic') + parser.add_argument('--user', default="unchanged", help='ID of the default user') + parser.add_argument('--topic', default="unchanged", help='Name of default topic') + elif parts[0] == "acc": parser = argparse.ArgumentParser(prog=parts[0], description='Create or alter an account') parser.add_argument('--user', default='new', help='ID of the account to update') parser.add_argument('--scheme', default='basic', help='authentication scheme, default=basic') @@ -312,6 +350,7 @@ def parse_cmd(cmd): else: print("Unrecognized:", parts[0]) print("Possible commands:") + print("\t.use\t- set default user or topic") print("\tacc\t- create account") print("\tlogin\t- authenticate") print("\tsub\t- subscribe to topic") @@ -340,7 +379,17 @@ def serialize_cmd(string, id): return None # Process dictionary - if cmd.cmd == "acc": + if cmd.cmd == ".use": + if cmd.user != "unchanged": + global default_user + default_user = cmd.user + stdoutln("Default user is '" + default_user + "'") + if cmd.topic != "unchanged": + global default_topic + default_topic = cmd.topic + stdoutln("Default topic is '" + default_topic + "'") + return None + elif cmd.cmd == "acc": return accMsg(id, cmd.user, cmd.scheme, cmd.secret, cmd.uname, cmd.password, cmd.do_login, cmd.fn, cmd.photo, cmd.private, cmd.auth, cmd.anon, cmd.tags, cmd.cred) elif cmd.cmd == "login": @@ -349,10 +398,9 @@ def serialize_cmd(string, id): return subMsg(id, cmd.topic, cmd.fn, cmd.photo, cmd.private, cmd.auth, cmd.anon, cmd.mode, cmd.tags, cmd.get_query) elif cmd.cmd == "leave": - return pb.ClientMsg(leave=pb.ClientLeave(id=str(id), topic=cmd.topic)) + return leaveMsg(id, cmd.topic, cmd.unsub) elif cmd.cmd == "pub": - return pb.ClientMsg(pub=pb.ClientPub(id=str(id), topic=cmd.topic, no_echo=True, - content=encode_to_bytes(cmd.content))) + return pubMsg(id, cmd.topic, cmd.content) elif cmd.cmd == "get": return getMsg(id, cmd.topic, cmd.desc, cmd.sub, cmd.tags, cmd.data) elif cmd.cmd == "set": @@ -369,21 +417,22 @@ def serialize_cmd(string, id): def gen_message(schema, secret): """Client message generator: reads user input as string, converts to pb.ClientMsg, and yields""" + global input_thread random.seed() id = random.randint(10000,60000) + # Asynchronous input-output + input_thread = threading.Thread(target=stdin, args=(input_queue,)) + input_thread.daemon = True + input_thread.start() + yield hiMsg(id) if schema != None: id += 1 yield loginMsg(id, schema, secret, None, None, None) - # Asynchronous input-output - input_thread = threading.Thread(target=stdin, args=(input_queue,)) - input_thread.daemon = True - input_thread.start() - print_prompt = True while True: @@ -410,11 +459,12 @@ def gen_message(schema, secret): time.sleep(0.1) def run(addr, schema, secret): - channel = grpc.insecure_channel(addr) - stub = pbx.NodeStub(channel) - # Call the server - stream = stub.MessageLoop(gen_message(schema, secret)) try: + channel = grpc.insecure_channel(addr) + stub = pbx.NodeStub(channel) + # Call the server + stream = stub.MessageLoop(gen_message(schema, secret)) + # Read server responses for msg in stream: if msg.HasField("ctrl"): @@ -424,29 +474,34 @@ def run(addr, schema, secret): del onCompletion[msg.ctrl.id] if msg.ctrl.code >= 200 and msg.ctrl.code < 400: func(msg.ctrl.params) - stdoutln(str(msg.ctrl.code) + " " + msg.ctrl.text) + stdoutln("\r" + str(msg.ctrl.code) + " " + msg.ctrl.text) elif msg.HasField("data"): - stdoutln("\nFrom: " + msg.data.from_user_id + ":\n") - stdoutln(json.loads(msg.data.content) + "\n") + stdoutln("\rFrom: " + msg.data.from_user_id + ":\n") + stdoutln(json.loads(msg.data.content)) elif msg.HasField("pres"): pass + elif msg.HasField("info"): + user = getattr(msg.info, 'from') + stdoutln("\rMessage #" + str(msg.info.seq) + " " + msg.info.what + + " by " + user + "; topic=" + msg.info.topic + "(" + msg.topic + ")") else: - stdoutln("Message type not handled", msg) + stdoutln("\rMessage type not handled", msg) except grpc._channel._Rendezvous as err: - stdoutln(err) + print(err) + channel.close() + if input_thread != None: + input_thread.join(0.3) def read_cookie(): try: cookie = open('.tn-cli-cookie', 'r') params = json.load(cookie) cookie.close() - if params.get("token") == None: - return None - return params + return params.get("token") except Exception as err: - stdoutln("Missing or invalid cookie file '.tn-cli-cookie'", err) + println("Missing or invalid cookie file '.tn-cli-cookie'", err) return None def save_cookie(params): @@ -461,7 +516,7 @@ def save_cookie(params): stdoutln("Authenticated as", nice.get('user')) try: - cookie = open('.tn-cookie', 'w') + cookie = open('.tn-cli-cookie', 'w') json.dump(nice, cookie) cookie.close() except Exception as err: @@ -496,20 +551,21 @@ def print_server_params(params): """Use token to login""" schema = 'token' secret = args.login_token.encode('acsii') - stdoutln("Logging in with token", args.login_token) + print("Logging in with token", args.login_token) elif args.login_basic: """Use username:password""" schema = 'basic' secret = args.login_basic.encode('utf-8') - stdoutln("Logging in with login:password", args.login_basic) + print("Logging in with login:password", args.login_basic) else: """Try reading the cookie file""" try: - schema, secret = read_auth_cookie(args.login_cookie) - stdoutln("Logging in with cookie file", args.login_cookie) + schema = 'token' + secret = read_cookie() + print("Logging in with cookie file") except Exception as err: - stdoutln("Failed to read authentication cookie", err) + print("Failed to read authentication cookie", err) run(args.host, schema, secret)