From e92d36a2405e9bb7d016f340bd48703b6f94bfc9 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 14 Sep 2015 19:55:53 +0200 Subject: [PATCH 01/22] Regenerate protocol buffers --- Spectrum2/protocol_pb2.py | 612 +++++++++++++++++++++----------------- 1 file changed, 347 insertions(+), 265 deletions(-) diff --git a/Spectrum2/protocol_pb2.py b/Spectrum2/protocol_pb2.py index e01bd27..638435c 100644 --- a/Spectrum2/protocol_pb2.py +++ b/Spectrum2/protocol_pb2.py @@ -1,88 +1,99 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! +# source: protocol.proto -from google.protobuf import descriptor -from google.protobuf import message -from google.protobuf import reflection +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) +_sym_db = _symbol_database.Default() -DESCRIPTOR = descriptor.FileDescriptor( + + + +DESCRIPTOR = _descriptor.FileDescriptor( name='protocol.proto', package='pbnetwork', - serialized_pb='\n\x0eprotocol.proto\x12\tpbnetwork\"\x19\n\tConnected\x12\x0c\n\x04user\x18\x01 \x02(\t\"<\n\x0c\x44isconnected\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\r\n\x05\x65rror\x18\x02 \x02(\x05\x12\x0f\n\x07message\x18\x03 \x01(\t\"P\n\x05Login\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\x12\x10\n\x08password\x18\x03 \x02(\t\x12\x13\n\x0b\x65xtraFields\x18\x04 \x03(\t\"*\n\x06Logout\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\"\xab\x01\n\x05\x42uddy\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\r\n\x05\x61lias\x18\x03 \x01(\t\x12\r\n\x05group\x18\x04 \x03(\t\x12%\n\x06status\x18\x05 \x01(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x10\n\x08iconHash\x18\x07 \x01(\t\x12\x0f\n\x07\x62locked\x18\x08 \x01(\x08\"\xa9\x01\n\x13\x43onversationMessage\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x0f\n\x07message\x18\x03 \x02(\t\x12\x10\n\x08nickname\x18\x04 \x01(\t\x12\r\n\x05xhtml\x18\x05 \x01(\t\x12\x11\n\ttimestamp\x18\x06 \x01(\t\x12\x10\n\x08headline\x18\x07 \x01(\x08\x12\n\n\x02id\x18\x08 \x01(\t\x12\n\n\x02pm\x18\t \x01(\x08\"J\n\x04Room\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x10\n\x08nickname\x18\x02 \x02(\t\x12\x0c\n\x04room\x18\x03 \x02(\t\x12\x10\n\x08password\x18\x04 \x01(\t\"&\n\x08RoomList\x12\x0c\n\x04room\x18\x01 \x03(\t\x12\x0c\n\x04name\x18\x02 \x03(\t\"\x9c\x01\n\x0bParticipant\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x0c\n\x04room\x18\x02 \x02(\t\x12\x10\n\x08nickname\x18\x03 \x02(\t\x12\x0c\n\x04\x66lag\x18\x04 \x02(\x05\x12%\n\x06status\x18\x05 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x0f\n\x07newname\x18\x07 \x01(\t\"k\n\x05VCard\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\n\n\x02id\x18\x03 \x02(\x05\x12\x10\n\x08\x66ullname\x18\x04 \x01(\t\x12\x10\n\x08nickname\x18\x05 \x01(\t\x12\r\n\x05photo\x18\x06 \x01(\x0c\"X\n\x06Status\x12\x10\n\x08userName\x18\x01 \x02(\t\x12%\n\x06status\x18\x03 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x04 \x01(\t\"B\n\x05Stats\x12\x0b\n\x03res\x18\x01 \x02(\x05\x12\x10\n\x08init_res\x18\x02 \x02(\x05\x12\x0e\n\x06shared\x18\x03 \x02(\x05\x12\n\n\x02id\x18\x04 \x02(\t\"Y\n\x04\x46ile\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x10\n\x08\x66ileName\x18\x03 \x02(\t\x12\x0c\n\x04size\x18\x04 \x02(\x05\x12\x0c\n\x04\x66tID\x18\x05 \x01(\x05\".\n\x10\x46ileTransferData\x12\x0c\n\x04\x66tID\x18\x01 \x02(\x05\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c\"\x1f\n\rBackendConfig\x12\x0e\n\x06\x63onfig\x18\x01 \x02(\t\"\x9a\x06\n\x0eWrapperMessage\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.pbnetwork.WrapperMessage.Type\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"\xc8\x05\n\x04Type\x12\x12\n\x0eTYPE_CONNECTED\x10\x01\x12\x15\n\x11TYPE_DISCONNECTED\x10\x02\x12\x0e\n\nTYPE_LOGIN\x10\x03\x12\x0f\n\x0bTYPE_LOGOUT\x10\x04\x12\x16\n\x12TYPE_BUDDY_CHANGED\x10\x06\x12\x16\n\x12TYPE_BUDDY_REMOVED\x10\x07\x12\x15\n\x11TYPE_CONV_MESSAGE\x10\x08\x12\r\n\tTYPE_PING\x10\t\x12\r\n\tTYPE_PONG\x10\n\x12\x12\n\x0eTYPE_JOIN_ROOM\x10\x0b\x12\x13\n\x0fTYPE_LEAVE_ROOM\x10\x0c\x12\x1c\n\x18TYPE_PARTICIPANT_CHANGED\x10\r\x12\x1e\n\x1aTYPE_ROOM_NICKNAME_CHANGED\x10\x0e\x12\x1d\n\x19TYPE_ROOM_SUBJECT_CHANGED\x10\x0f\x12\x0e\n\nTYPE_VCARD\x10\x10\x12\x17\n\x13TYPE_STATUS_CHANGED\x10\x11\x12\x15\n\x11TYPE_BUDDY_TYPING\x10\x12\x12\x1d\n\x19TYPE_BUDDY_STOPPED_TYPING\x10\x13\x12\x14\n\x10TYPE_BUDDY_TYPED\x10\x14\x12\x15\n\x11TYPE_AUTH_REQUEST\x10\x15\x12\x12\n\x0eTYPE_ATTENTION\x10\x16\x12\x0e\n\nTYPE_STATS\x10\x17\x12\x11\n\rTYPE_FT_START\x10\x18\x12\x12\n\x0eTYPE_FT_FINISH\x10\x19\x12\x10\n\x0cTYPE_FT_DATA\x10\x1a\x12\x11\n\rTYPE_FT_PAUSE\x10\x1b\x12\x14\n\x10TYPE_FT_CONTINUE\x10\x1c\x12\r\n\tTYPE_EXIT\x10\x1d\x12\x17\n\x13TYPE_BACKEND_CONFIG\x10\x1e\x12\x0e\n\nTYPE_QUERY\x10\x1f\x12\x12\n\x0eTYPE_ROOM_LIST\x10 \x12\x19\n\x15TYPE_CONV_MESSAGE_ACK\x10!\x12\x10\n\x0cTYPE_RAW_XML\x10\"*\xb3\x05\n\x0f\x43onnectionError\x12\"\n\x1e\x43ONNECTION_ERROR_NETWORK_ERROR\x10\x00\x12%\n!CONNECTION_ERROR_INVALID_USERNAME\x10\x01\x12*\n&CONNECTION_ERROR_AUTHENTICATION_FAILED\x10\x02\x12.\n*CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE\x10\x03\x12#\n\x1f\x43ONNECTION_ERROR_NO_SSL_SUPPORT\x10\x04\x12%\n!CONNECTION_ERROR_ENCRYPTION_ERROR\x10\x05\x12 \n\x1c\x43ONNECTION_ERROR_NAME_IN_USE\x10\x06\x12%\n!CONNECTION_ERROR_INVALID_SETTINGS\x10\x07\x12&\n\"CONNECTION_ERROR_CERT_NOT_PROVIDED\x10\x08\x12#\n\x1f\x43ONNECTION_ERROR_CERT_UNTRUSTED\x10\t\x12!\n\x1d\x43ONNECTION_ERROR_CERT_EXPIRED\x10\n\x12\'\n#CONNECTION_ERROR_CERT_NOT_ACTIVATED\x10\x0b\x12+\n\'CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH\x10\x0c\x12.\n*CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH\x10\r\x12%\n!CONNECTION_ERROR_CERT_SELF_SIGNED\x10\x0e\x12%\n!CONNECTION_ERROR_CERT_OTHER_ERROR\x10\x0f\x12 \n\x1c\x43ONNECTION_ERROR_OTHER_ERROR\x10\x10*\x86\x01\n\nStatusType\x12\x11\n\rSTATUS_ONLINE\x10\x00\x12\x0f\n\x0bSTATUS_AWAY\x10\x01\x12\x0e\n\nSTATUS_FFC\x10\x02\x12\r\n\tSTATUS_XA\x10\x03\x12\x0e\n\nSTATUS_DND\x10\x04\x12\x0f\n\x0bSTATUS_NONE\x10\x05\x12\x14\n\x10STATUS_INVISIBLE\x10\x06*\x88\x02\n\x0fParticipantFlag\x12\x19\n\x15PARTICIPANT_FLAG_NONE\x10\x00\x12\x1e\n\x1aPARTICIPANT_FLAG_MODERATOR\x10\x01\x12\x1d\n\x19PARTICIPANT_FLAG_CONFLICT\x10\x02\x12\x1b\n\x17PARTICIPANT_FLAG_BANNED\x10\x04\x12#\n\x1fPARTICIPANT_FLAG_NOT_AUTHORIZED\x10\x08\x12\x17\n\x13PARTICIPANT_FLAG_ME\x10\x10\x12\x1b\n\x17PARTICIPANT_FLAG_KICKED\x10 \x12#\n\x1fPARTICIPANT_FLAG_ROOM_NOT_FOUND\x10@') + serialized_pb=_b('\n\x0eprotocol.proto\x12\tpbnetwork\"\x19\n\tConnected\x12\x0c\n\x04user\x18\x01 \x02(\t\"<\n\x0c\x44isconnected\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\r\n\x05\x65rror\x18\x02 \x02(\x05\x12\x0f\n\x07message\x18\x03 \x01(\t\"P\n\x05Login\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\x12\x10\n\x08password\x18\x03 \x02(\t\x12\x13\n\x0b\x65xtraFields\x18\x04 \x03(\t\"*\n\x06Logout\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\"\xab\x01\n\x05\x42uddy\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\r\n\x05\x61lias\x18\x03 \x01(\t\x12\r\n\x05group\x18\x04 \x03(\t\x12%\n\x06status\x18\x05 \x01(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x10\n\x08iconHash\x18\x07 \x01(\t\x12\x0f\n\x07\x62locked\x18\x08 \x01(\x08\"\xa9\x01\n\x13\x43onversationMessage\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x0f\n\x07message\x18\x03 \x02(\t\x12\x10\n\x08nickname\x18\x04 \x01(\t\x12\r\n\x05xhtml\x18\x05 \x01(\t\x12\x11\n\ttimestamp\x18\x06 \x01(\t\x12\x10\n\x08headline\x18\x07 \x01(\x08\x12\n\n\x02id\x18\x08 \x01(\t\x12\n\n\x02pm\x18\t \x01(\x08\"J\n\x04Room\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x10\n\x08nickname\x18\x02 \x02(\t\x12\x0c\n\x04room\x18\x03 \x02(\t\x12\x10\n\x08password\x18\x04 \x01(\t\"&\n\x08RoomList\x12\x0c\n\x04room\x18\x01 \x03(\t\x12\x0c\n\x04name\x18\x02 \x03(\t\"\x9c\x01\n\x0bParticipant\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x0c\n\x04room\x18\x02 \x02(\t\x12\x10\n\x08nickname\x18\x03 \x02(\t\x12\x0c\n\x04\x66lag\x18\x04 \x02(\x05\x12%\n\x06status\x18\x05 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x0f\n\x07newname\x18\x07 \x01(\t\"k\n\x05VCard\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\n\n\x02id\x18\x03 \x02(\x05\x12\x10\n\x08\x66ullname\x18\x04 \x01(\t\x12\x10\n\x08nickname\x18\x05 \x01(\t\x12\r\n\x05photo\x18\x06 \x01(\x0c\"X\n\x06Status\x12\x10\n\x08userName\x18\x01 \x02(\t\x12%\n\x06status\x18\x03 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x04 \x01(\t\"B\n\x05Stats\x12\x0b\n\x03res\x18\x01 \x02(\x05\x12\x10\n\x08init_res\x18\x02 \x02(\x05\x12\x0e\n\x06shared\x18\x03 \x02(\x05\x12\n\n\x02id\x18\x04 \x02(\t\"Y\n\x04\x46ile\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x10\n\x08\x66ileName\x18\x03 \x02(\t\x12\x0c\n\x04size\x18\x04 \x02(\x05\x12\x0c\n\x04\x66tID\x18\x05 \x01(\x05\".\n\x10\x46ileTransferData\x12\x0c\n\x04\x66tID\x18\x01 \x02(\x05\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c\"\x1f\n\rBackendConfig\x12\x0e\n\x06\x63onfig\x18\x01 \x02(\t\"\x9a\x06\n\x0eWrapperMessage\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.pbnetwork.WrapperMessage.Type\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"\xc8\x05\n\x04Type\x12\x12\n\x0eTYPE_CONNECTED\x10\x01\x12\x15\n\x11TYPE_DISCONNECTED\x10\x02\x12\x0e\n\nTYPE_LOGIN\x10\x03\x12\x0f\n\x0bTYPE_LOGOUT\x10\x04\x12\x16\n\x12TYPE_BUDDY_CHANGED\x10\x06\x12\x16\n\x12TYPE_BUDDY_REMOVED\x10\x07\x12\x15\n\x11TYPE_CONV_MESSAGE\x10\x08\x12\r\n\tTYPE_PING\x10\t\x12\r\n\tTYPE_PONG\x10\n\x12\x12\n\x0eTYPE_JOIN_ROOM\x10\x0b\x12\x13\n\x0fTYPE_LEAVE_ROOM\x10\x0c\x12\x1c\n\x18TYPE_PARTICIPANT_CHANGED\x10\r\x12\x1e\n\x1aTYPE_ROOM_NICKNAME_CHANGED\x10\x0e\x12\x1d\n\x19TYPE_ROOM_SUBJECT_CHANGED\x10\x0f\x12\x0e\n\nTYPE_VCARD\x10\x10\x12\x17\n\x13TYPE_STATUS_CHANGED\x10\x11\x12\x15\n\x11TYPE_BUDDY_TYPING\x10\x12\x12\x1d\n\x19TYPE_BUDDY_STOPPED_TYPING\x10\x13\x12\x14\n\x10TYPE_BUDDY_TYPED\x10\x14\x12\x15\n\x11TYPE_AUTH_REQUEST\x10\x15\x12\x12\n\x0eTYPE_ATTENTION\x10\x16\x12\x0e\n\nTYPE_STATS\x10\x17\x12\x11\n\rTYPE_FT_START\x10\x18\x12\x12\n\x0eTYPE_FT_FINISH\x10\x19\x12\x10\n\x0cTYPE_FT_DATA\x10\x1a\x12\x11\n\rTYPE_FT_PAUSE\x10\x1b\x12\x14\n\x10TYPE_FT_CONTINUE\x10\x1c\x12\r\n\tTYPE_EXIT\x10\x1d\x12\x17\n\x13TYPE_BACKEND_CONFIG\x10\x1e\x12\x0e\n\nTYPE_QUERY\x10\x1f\x12\x12\n\x0eTYPE_ROOM_LIST\x10 \x12\x19\n\x15TYPE_CONV_MESSAGE_ACK\x10!\x12\x10\n\x0cTYPE_RAW_XML\x10\"*\xb3\x05\n\x0f\x43onnectionError\x12\"\n\x1e\x43ONNECTION_ERROR_NETWORK_ERROR\x10\x00\x12%\n!CONNECTION_ERROR_INVALID_USERNAME\x10\x01\x12*\n&CONNECTION_ERROR_AUTHENTICATION_FAILED\x10\x02\x12.\n*CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE\x10\x03\x12#\n\x1f\x43ONNECTION_ERROR_NO_SSL_SUPPORT\x10\x04\x12%\n!CONNECTION_ERROR_ENCRYPTION_ERROR\x10\x05\x12 \n\x1c\x43ONNECTION_ERROR_NAME_IN_USE\x10\x06\x12%\n!CONNECTION_ERROR_INVALID_SETTINGS\x10\x07\x12&\n\"CONNECTION_ERROR_CERT_NOT_PROVIDED\x10\x08\x12#\n\x1f\x43ONNECTION_ERROR_CERT_UNTRUSTED\x10\t\x12!\n\x1d\x43ONNECTION_ERROR_CERT_EXPIRED\x10\n\x12\'\n#CONNECTION_ERROR_CERT_NOT_ACTIVATED\x10\x0b\x12+\n\'CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH\x10\x0c\x12.\n*CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH\x10\r\x12%\n!CONNECTION_ERROR_CERT_SELF_SIGNED\x10\x0e\x12%\n!CONNECTION_ERROR_CERT_OTHER_ERROR\x10\x0f\x12 \n\x1c\x43ONNECTION_ERROR_OTHER_ERROR\x10\x10*\x86\x01\n\nStatusType\x12\x11\n\rSTATUS_ONLINE\x10\x00\x12\x0f\n\x0bSTATUS_AWAY\x10\x01\x12\x0e\n\nSTATUS_FFC\x10\x02\x12\r\n\tSTATUS_XA\x10\x03\x12\x0e\n\nSTATUS_DND\x10\x04\x12\x0f\n\x0bSTATUS_NONE\x10\x05\x12\x14\n\x10STATUS_INVISIBLE\x10\x06*\x88\x02\n\x0fParticipantFlag\x12\x19\n\x15PARTICIPANT_FLAG_NONE\x10\x00\x12\x1e\n\x1aPARTICIPANT_FLAG_MODERATOR\x10\x01\x12\x1d\n\x19PARTICIPANT_FLAG_CONFLICT\x10\x02\x12\x1b\n\x17PARTICIPANT_FLAG_BANNED\x10\x04\x12#\n\x1fPARTICIPANT_FLAG_NOT_AUTHORIZED\x10\x08\x12\x17\n\x13PARTICIPANT_FLAG_ME\x10\x10\x12\x1b\n\x17PARTICIPANT_FLAG_KICKED\x10 \x12#\n\x1fPARTICIPANT_FLAG_ROOM_NOT_FOUND\x10@') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) -_CONNECTIONERROR = descriptor.EnumDescriptor( +_CONNECTIONERROR = _descriptor.EnumDescriptor( name='ConnectionError', full_name='pbnetwork.ConnectionError', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_NETWORK_ERROR', index=0, number=0, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_INVALID_USERNAME', index=1, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_AUTHENTICATION_FAILED', index=2, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE', index=3, number=3, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_NO_SSL_SUPPORT', index=4, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_ENCRYPTION_ERROR', index=5, number=5, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_NAME_IN_USE', index=6, number=6, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_INVALID_SETTINGS', index=7, number=7, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_NOT_PROVIDED', index=8, number=8, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_UNTRUSTED', index=9, number=9, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_EXPIRED', index=10, number=10, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_NOT_ACTIVATED', index=11, number=11, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH', index=12, number=12, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH', index=13, number=13, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_SELF_SIGNED', index=14, number=14, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_OTHER_ERROR', index=15, number=15, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_OTHER_ERROR', index=16, number=16, options=None, type=None), @@ -92,39 +103,40 @@ _CONNECTIONERROR = descriptor.EnumDescriptor( serialized_start=2102, serialized_end=2793, ) +_sym_db.RegisterEnumDescriptor(_CONNECTIONERROR) - -_STATUSTYPE = descriptor.EnumDescriptor( +ConnectionError = enum_type_wrapper.EnumTypeWrapper(_CONNECTIONERROR) +_STATUSTYPE = _descriptor.EnumDescriptor( name='StatusType', full_name='pbnetwork.StatusType', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_ONLINE', index=0, number=0, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_AWAY', index=1, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_FFC', index=2, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_XA', index=3, number=3, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_DND', index=4, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_NONE', index=5, number=5, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_INVISIBLE', index=6, number=6, options=None, type=None), @@ -134,43 +146,44 @@ _STATUSTYPE = descriptor.EnumDescriptor( serialized_start=2796, serialized_end=2930, ) +_sym_db.RegisterEnumDescriptor(_STATUSTYPE) - -_PARTICIPANTFLAG = descriptor.EnumDescriptor( +StatusType = enum_type_wrapper.EnumTypeWrapper(_STATUSTYPE) +_PARTICIPANTFLAG = _descriptor.EnumDescriptor( name='ParticipantFlag', full_name='pbnetwork.ParticipantFlag', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_NONE', index=0, number=0, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_MODERATOR', index=1, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_CONFLICT', index=2, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_BANNED', index=3, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_NOT_AUTHORIZED', index=4, number=8, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_ME', index=5, number=16, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_KICKED', index=6, number=32, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_ROOM_NOT_FOUND', index=7, number=64, options=None, type=None), @@ -180,8 +193,9 @@ _PARTICIPANTFLAG = descriptor.EnumDescriptor( serialized_start=2933, serialized_end=3197, ) +_sym_db.RegisterEnumDescriptor(_PARTICIPANTFLAG) - +ParticipantFlag = enum_type_wrapper.EnumTypeWrapper(_PARTICIPANTFLAG) CONNECTION_ERROR_NETWORK_ERROR = 0 CONNECTION_ERROR_INVALID_USERNAME = 1 CONNECTION_ERROR_AUTHENTICATION_FAILED = 2 @@ -216,141 +230,141 @@ PARTICIPANT_FLAG_KICKED = 32 PARTICIPANT_FLAG_ROOM_NOT_FOUND = 64 -_WRAPPERMESSAGE_TYPE = descriptor.EnumDescriptor( +_WRAPPERMESSAGE_TYPE = _descriptor.EnumDescriptor( name='Type', full_name='pbnetwork.WrapperMessage.Type', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_CONNECTED', index=0, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_DISCONNECTED', index=1, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_LOGIN', index=2, number=3, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_LOGOUT', index=3, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_CHANGED', index=4, number=6, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_REMOVED', index=5, number=7, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_CONV_MESSAGE', index=6, number=8, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_PING', index=7, number=9, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_PONG', index=8, number=10, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_JOIN_ROOM', index=9, number=11, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_LEAVE_ROOM', index=10, number=12, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_PARTICIPANT_CHANGED', index=11, number=13, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ROOM_NICKNAME_CHANGED', index=12, number=14, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ROOM_SUBJECT_CHANGED', index=13, number=15, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_VCARD', index=14, number=16, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_STATUS_CHANGED', index=15, number=17, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_TYPING', index=16, number=18, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_STOPPED_TYPING', index=17, number=19, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_TYPED', index=18, number=20, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_AUTH_REQUEST', index=19, number=21, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ATTENTION', index=20, number=22, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_STATS', index=21, number=23, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_START', index=22, number=24, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_FINISH', index=23, number=25, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_DATA', index=24, number=26, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_PAUSE', index=25, number=27, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_CONTINUE', index=26, number=28, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_EXIT', index=27, number=29, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BACKEND_CONFIG', index=28, number=30, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_QUERY', index=29, number=31, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ROOM_LIST', index=30, number=32, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_CONV_MESSAGE_ACK', index=31, number=33, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_RAW_XML', index=32, number=34, options=None, type=None), @@ -360,19 +374,20 @@ _WRAPPERMESSAGE_TYPE = descriptor.EnumDescriptor( serialized_start=1387, serialized_end=2099, ) +_sym_db.RegisterEnumDescriptor(_WRAPPERMESSAGE_TYPE) -_CONNECTED = descriptor.Descriptor( +_CONNECTED = _descriptor.Descriptor( name='Connected', full_name='pbnetwork.Connected', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Connected.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -385,36 +400,38 @@ _CONNECTED = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=29, serialized_end=54, ) -_DISCONNECTED = descriptor.Descriptor( +_DISCONNECTED = _descriptor.Descriptor( name='Disconnected', full_name='pbnetwork.Disconnected', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Disconnected.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='error', full_name='pbnetwork.Disconnected.error', index=1, number=2, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='message', full_name='pbnetwork.Disconnected.message', index=2, number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -427,40 +444,42 @@ _DISCONNECTED = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=56, serialized_end=116, ) -_LOGIN = descriptor.Descriptor( +_LOGIN = _descriptor.Descriptor( name='Login', full_name='pbnetwork.Login', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Login.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='legacyName', full_name='pbnetwork.Login.legacyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='password', full_name='pbnetwork.Login.password', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='extraFields', full_name='pbnetwork.Login.extraFields', index=3, number=4, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], @@ -476,29 +495,31 @@ _LOGIN = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=118, serialized_end=198, ) -_LOGOUT = descriptor.Descriptor( +_LOGOUT = _descriptor.Descriptor( name='Logout', full_name='pbnetwork.Logout', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Logout.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='legacyName', full_name='pbnetwork.Logout.legacyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -511,68 +532,70 @@ _LOGOUT = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=200, serialized_end=242, ) -_BUDDY = descriptor.Descriptor( +_BUDDY = _descriptor.Descriptor( name='Buddy', full_name='pbnetwork.Buddy', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Buddy.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.Buddy.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='alias', full_name='pbnetwork.Buddy.alias', index=2, number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='group', full_name='pbnetwork.Buddy.group', index=3, number=4, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='status', full_name='pbnetwork.Buddy.status', index=4, number=5, 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='statusMessage', full_name='pbnetwork.Buddy.statusMessage', index=5, number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='iconHash', full_name='pbnetwork.Buddy.iconHash', index=6, number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='blocked', full_name='pbnetwork.Buddy.blocked', index=7, number=8, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, @@ -588,75 +611,77 @@ _BUDDY = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=245, serialized_end=416, ) -_CONVERSATIONMESSAGE = descriptor.Descriptor( +_CONVERSATIONMESSAGE = _descriptor.Descriptor( name='ConversationMessage', full_name='pbnetwork.ConversationMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.ConversationMessage.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.ConversationMessage.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='message', full_name='pbnetwork.ConversationMessage.message', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.ConversationMessage.nickname', index=3, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='xhtml', full_name='pbnetwork.ConversationMessage.xhtml', index=4, number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='timestamp', full_name='pbnetwork.ConversationMessage.timestamp', index=5, number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='headline', full_name='pbnetwork.ConversationMessage.headline', index=6, number=7, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='id', full_name='pbnetwork.ConversationMessage.id', index=7, number=8, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='pm', full_name='pbnetwork.ConversationMessage.pm', index=8, number=9, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, @@ -672,43 +697,45 @@ _CONVERSATIONMESSAGE = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=419, serialized_end=588, ) -_ROOM = descriptor.Descriptor( +_ROOM = _descriptor.Descriptor( name='Room', full_name='pbnetwork.Room', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Room.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.Room.nickname', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='room', full_name='pbnetwork.Room.room', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='password', full_name='pbnetwork.Room.password', index=3, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -721,26 +748,28 @@ _ROOM = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=590, serialized_end=664, ) -_ROOMLIST = descriptor.Descriptor( +_ROOMLIST = _descriptor.Descriptor( name='RoomList', full_name='pbnetwork.RoomList', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='room', full_name='pbnetwork.RoomList.room', index=0, number=1, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='name', full_name='pbnetwork.RoomList.name', index=1, number=2, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], @@ -756,64 +785,66 @@ _ROOMLIST = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=666, serialized_end=704, ) -_PARTICIPANT = descriptor.Descriptor( +_PARTICIPANT = _descriptor.Descriptor( name='Participant', full_name='pbnetwork.Participant', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Participant.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='room', full_name='pbnetwork.Participant.room', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.Participant.nickname', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='flag', full_name='pbnetwork.Participant.flag', index=3, number=4, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='status', full_name='pbnetwork.Participant.status', index=4, number=5, type=14, cpp_type=8, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='statusMessage', full_name='pbnetwork.Participant.statusMessage', index=5, number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='newname', full_name='pbnetwork.Participant.newname', index=6, number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -826,57 +857,59 @@ _PARTICIPANT = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=707, serialized_end=863, ) -_VCARD = descriptor.Descriptor( +_VCARD = _descriptor.Descriptor( name='VCard', full_name='pbnetwork.VCard', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.VCard.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.VCard.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='id', full_name='pbnetwork.VCard.id', index=2, number=3, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='fullname', full_name='pbnetwork.VCard.fullname', index=3, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.VCard.nickname', index=4, number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='photo', full_name='pbnetwork.VCard.photo', index=5, number=6, type=12, cpp_type=9, label=1, - has_default_value=False, default_value="", + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -889,36 +922,38 @@ _VCARD = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=865, serialized_end=972, ) -_STATUS = descriptor.Descriptor( +_STATUS = _descriptor.Descriptor( name='Status', full_name='pbnetwork.Status', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Status.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='status', full_name='pbnetwork.Status.status', index=1, number=3, type=14, cpp_type=8, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='statusMessage', full_name='pbnetwork.Status.statusMessage', index=2, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -931,43 +966,45 @@ _STATUS = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=974, serialized_end=1062, ) -_STATS = descriptor.Descriptor( +_STATS = _descriptor.Descriptor( name='Stats', full_name='pbnetwork.Stats', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='res', full_name='pbnetwork.Stats.res', index=0, number=1, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='init_res', full_name='pbnetwork.Stats.init_res', index=1, number=2, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='shared', full_name='pbnetwork.Stats.shared', index=2, number=3, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='id', full_name='pbnetwork.Stats.id', index=3, number=4, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -980,47 +1017,49 @@ _STATS = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1064, serialized_end=1130, ) -_FILE = descriptor.Descriptor( +_FILE = _descriptor.Descriptor( name='File', full_name='pbnetwork.File', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.File.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.File.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='fileName', full_name='pbnetwork.File.fileName', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='size', full_name='pbnetwork.File.size', index=3, number=4, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='ftID', full_name='pbnetwork.File.ftID', index=4, number=5, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, @@ -1036,29 +1075,31 @@ _FILE = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1132, serialized_end=1221, ) -_FILETRANSFERDATA = descriptor.Descriptor( +_FILETRANSFERDATA = _descriptor.Descriptor( name='FileTransferData', full_name='pbnetwork.FileTransferData', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='ftID', full_name='pbnetwork.FileTransferData.ftID', index=0, number=1, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='data', full_name='pbnetwork.FileTransferData.data', index=1, number=2, type=12, cpp_type=9, label=2, - has_default_value=False, default_value="", + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -1071,22 +1112,24 @@ _FILETRANSFERDATA = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1223, serialized_end=1269, ) -_BACKENDCONFIG = descriptor.Descriptor( +_BACKENDCONFIG = _descriptor.Descriptor( name='BackendConfig', full_name='pbnetwork.BackendConfig', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='config', full_name='pbnetwork.BackendConfig.config', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -1099,29 +1142,31 @@ _BACKENDCONFIG = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1271, serialized_end=1302, ) -_WRAPPERMESSAGE = descriptor.Descriptor( +_WRAPPERMESSAGE = _descriptor.Descriptor( name='WrapperMessage', full_name='pbnetwork.WrapperMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='type', full_name='pbnetwork.WrapperMessage.type', index=0, number=1, type=14, cpp_type=8, label=2, has_default_value=False, default_value=1, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='payload', full_name='pbnetwork.WrapperMessage.payload', index=1, number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value="", + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -1135,111 +1180,148 @@ _WRAPPERMESSAGE = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1305, serialized_end=2099, ) - _BUDDY.fields_by_name['status'].enum_type = _STATUSTYPE _PARTICIPANT.fields_by_name['status'].enum_type = _STATUSTYPE _STATUS.fields_by_name['status'].enum_type = _STATUSTYPE _WRAPPERMESSAGE.fields_by_name['type'].enum_type = _WRAPPERMESSAGE_TYPE -_WRAPPERMESSAGE_TYPE.containing_type = _WRAPPERMESSAGE; +_WRAPPERMESSAGE_TYPE.containing_type = _WRAPPERMESSAGE +DESCRIPTOR.message_types_by_name['Connected'] = _CONNECTED +DESCRIPTOR.message_types_by_name['Disconnected'] = _DISCONNECTED +DESCRIPTOR.message_types_by_name['Login'] = _LOGIN +DESCRIPTOR.message_types_by_name['Logout'] = _LOGOUT +DESCRIPTOR.message_types_by_name['Buddy'] = _BUDDY +DESCRIPTOR.message_types_by_name['ConversationMessage'] = _CONVERSATIONMESSAGE +DESCRIPTOR.message_types_by_name['Room'] = _ROOM +DESCRIPTOR.message_types_by_name['RoomList'] = _ROOMLIST +DESCRIPTOR.message_types_by_name['Participant'] = _PARTICIPANT +DESCRIPTOR.message_types_by_name['VCard'] = _VCARD +DESCRIPTOR.message_types_by_name['Status'] = _STATUS +DESCRIPTOR.message_types_by_name['Stats'] = _STATS +DESCRIPTOR.message_types_by_name['File'] = _FILE +DESCRIPTOR.message_types_by_name['FileTransferData'] = _FILETRANSFERDATA +DESCRIPTOR.message_types_by_name['BackendConfig'] = _BACKENDCONFIG +DESCRIPTOR.message_types_by_name['WrapperMessage'] = _WRAPPERMESSAGE +DESCRIPTOR.enum_types_by_name['ConnectionError'] = _CONNECTIONERROR +DESCRIPTOR.enum_types_by_name['StatusType'] = _STATUSTYPE +DESCRIPTOR.enum_types_by_name['ParticipantFlag'] = _PARTICIPANTFLAG -class Connected(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _CONNECTED - +Connected = _reflection.GeneratedProtocolMessageType('Connected', (_message.Message,), dict( + DESCRIPTOR = _CONNECTED, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Connected) + )) +_sym_db.RegisterMessage(Connected) -class Disconnected(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _DISCONNECTED - +Disconnected = _reflection.GeneratedProtocolMessageType('Disconnected', (_message.Message,), dict( + DESCRIPTOR = _DISCONNECTED, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Disconnected) + )) +_sym_db.RegisterMessage(Disconnected) -class Login(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _LOGIN - +Login = _reflection.GeneratedProtocolMessageType('Login', (_message.Message,), dict( + DESCRIPTOR = _LOGIN, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Login) + )) +_sym_db.RegisterMessage(Login) -class Logout(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _LOGOUT - +Logout = _reflection.GeneratedProtocolMessageType('Logout', (_message.Message,), dict( + DESCRIPTOR = _LOGOUT, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Logout) + )) +_sym_db.RegisterMessage(Logout) -class Buddy(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _BUDDY - +Buddy = _reflection.GeneratedProtocolMessageType('Buddy', (_message.Message,), dict( + DESCRIPTOR = _BUDDY, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Buddy) + )) +_sym_db.RegisterMessage(Buddy) -class ConversationMessage(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _CONVERSATIONMESSAGE - +ConversationMessage = _reflection.GeneratedProtocolMessageType('ConversationMessage', (_message.Message,), dict( + DESCRIPTOR = _CONVERSATIONMESSAGE, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.ConversationMessage) + )) +_sym_db.RegisterMessage(ConversationMessage) -class Room(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _ROOM - +Room = _reflection.GeneratedProtocolMessageType('Room', (_message.Message,), dict( + DESCRIPTOR = _ROOM, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Room) + )) +_sym_db.RegisterMessage(Room) -class RoomList(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _ROOMLIST - +RoomList = _reflection.GeneratedProtocolMessageType('RoomList', (_message.Message,), dict( + DESCRIPTOR = _ROOMLIST, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.RoomList) + )) +_sym_db.RegisterMessage(RoomList) -class Participant(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _PARTICIPANT - +Participant = _reflection.GeneratedProtocolMessageType('Participant', (_message.Message,), dict( + DESCRIPTOR = _PARTICIPANT, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Participant) + )) +_sym_db.RegisterMessage(Participant) -class VCard(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _VCARD - +VCard = _reflection.GeneratedProtocolMessageType('VCard', (_message.Message,), dict( + DESCRIPTOR = _VCARD, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.VCard) + )) +_sym_db.RegisterMessage(VCard) -class Status(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _STATUS - +Status = _reflection.GeneratedProtocolMessageType('Status', (_message.Message,), dict( + DESCRIPTOR = _STATUS, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Status) + )) +_sym_db.RegisterMessage(Status) -class Stats(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _STATS - +Stats = _reflection.GeneratedProtocolMessageType('Stats', (_message.Message,), dict( + DESCRIPTOR = _STATS, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Stats) + )) +_sym_db.RegisterMessage(Stats) -class File(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _FILE - +File = _reflection.GeneratedProtocolMessageType('File', (_message.Message,), dict( + DESCRIPTOR = _FILE, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.File) + )) +_sym_db.RegisterMessage(File) -class FileTransferData(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _FILETRANSFERDATA - +FileTransferData = _reflection.GeneratedProtocolMessageType('FileTransferData', (_message.Message,), dict( + DESCRIPTOR = _FILETRANSFERDATA, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.FileTransferData) + )) +_sym_db.RegisterMessage(FileTransferData) -class BackendConfig(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _BACKENDCONFIG - +BackendConfig = _reflection.GeneratedProtocolMessageType('BackendConfig', (_message.Message,), dict( + DESCRIPTOR = _BACKENDCONFIG, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.BackendConfig) + )) +_sym_db.RegisterMessage(BackendConfig) -class WrapperMessage(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _WRAPPERMESSAGE - +WrapperMessage = _reflection.GeneratedProtocolMessageType('WrapperMessage', (_message.Message,), dict( + DESCRIPTOR = _WRAPPERMESSAGE, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.WrapperMessage) + )) +_sym_db.RegisterMessage(WrapperMessage) + # @@protoc_insertion_point(module_scope) From 6c12956dd663be4ad072594bf062f84abe56eefe Mon Sep 17 00:00:00 2001 From: moyamo Date: Tue, 15 Sep 2015 21:29:26 +0200 Subject: [PATCH 02/22] Attempt to fix groupchats --- Spectrum2/backend.py | 3 +- session.py | 266 ++++++++++++++++++++++++++----------------- yowsupwrapper.py | 48 +++++++- 3 files changed, 211 insertions(+), 106 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index a027adc..afbdec8 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -25,7 +25,7 @@ class SpectrumBackend: self.m_data = "" self.m_init_res = 0 - def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""): + def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = "", pm = True): m = protocol_pb2.ConversationMessage() m.userName = user m.buddyName = legacyName @@ -33,6 +33,7 @@ class SpectrumBackend: m.nickname = nickname m.xhtml = xhtml m.timestamp = str(timestamp) + m.pm = pm message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE) self.send(message) diff --git a/session.py b/session.py index b86fa97..b59544a 100644 --- a/session.py +++ b/session.py @@ -47,8 +47,6 @@ class Session(YowsupApp): self.backend = backend self.user = user self.legacyName = legacyName - self.buddies = BuddyList(self.legacyName, self.db) - self.bot = Bot(self) self.status = protocol_pb2.STATUS_NONE self.statusMessage = '' @@ -56,36 +54,36 @@ class Session(YowsupApp): self.groups = {} self.presenceRequested = [] self.offlineQueue = [] + self.msgIDs = { } self.groupOfflineQueue = { } + self.shouldBeConnected = False self.timer = None self.password = None self.initialized = False - self.loggedin = False + self.synced = False + self.buddies = BuddyList(self.legacyName, self.db) self.bot = Bot(self) def __del__(self): # handleLogoutRequest self.logout() - def call(self, method, **kwargs): - self.logger.debug("%s(%s)", method, - ", ".join(str(k) + ': ' + str(v) for k, v in kwargs.items())) - ##self.stack.broadcastEvent(YowLayerEvent(method, **kwargs)) - def logout(self): - self.loggedin = False + self.logger.info("%s logged out", self.user) super(Session, self).logout() def login(self, password): - self.loggedin = True + self.logger.info("%s attempting login", self.user) self.password = password + self.shouldBeConncted = True super(Session, self).login(self.legacyName, self.password) def updateRoomList(self): rooms = [] for room, group in self.groups.iteritems(): rooms.append([room, group.subject]) + self.logger.debug("Got rooms: %s", rooms) self.backend.handleRoomList(rooms) @@ -95,6 +93,11 @@ class Session(YowsupApp): old = self.buddies.keys() self.buddies.load() new = self.buddies.keys() + contacts = new + + if self.synced == False: + self.sendSync(contacts, delta = False, interactive = True) + self.synced = True add = set(new) - set(old) remove = set(old) - set(new) @@ -103,27 +106,28 @@ class Session(YowsupApp): self.logger.debug("Roster add: %s", str(list(add))) for number in remove: - self.backend.handleBuddyChanged(self.user, number, "", [], protocol_pb2.STATUS_NONE) + self.backend.handleBuddyChanged(self.user, number, "", [], + protocol_pb2.STATUS_NONE) self.backend.handleBuddyRemoved(self.user, number) self.unsubscribePresence(number) for number in add: buddy = self.buddies[number] self.subscribePresence(number) - self.backend.handleBuddyChanged(self.user, number, buddy.nick, buddy.groups, protocol_pb2.STATUS_NONE, iconHash = buddy.image_hash if buddy.image_hash is not None else "") + self.backend.handleBuddyChanged(self.user, number, buddy.nick, + buddy.groups, protocol_pb2.STATUS_NONE, + iconHash = buddy.image_hash if buddy.image_hash is not None else "") + #self.requestLastSeen(number, self._lastSeen) - self.logger.debug('Requesting groups list') - self.requestGroupsList(self._updateGroups) - + def _updateGroups(self, response, request): self.logger.debug('Received groups list %s', response) - # This XMPP client is not receiving this for some reason. groups = response.getGroups() for group in groups: room = group.getId() - owner = group.getOwner() - subjectOwner = group.getSubjectOwner() - subject = group.getSubject() + owner = group.getOwner().split('@')[0] + subjectOwner = group.getSubjectOwner().split('@')[0] + subject = utils.softToUni(group.getSubject()) if room in self.groups: oroom = self.groups[room] @@ -132,22 +136,61 @@ class Session(YowsupApp): oroom.subject = subject else: self.groups[room] = Group(room, owner, subject, subjectOwner) - # A crude implemtation of groups that act like buddies + self.joinRoom(room, self.user.split("@")[0]) - self.backend.handleBuddyChanged(self.user, room, subject, [], protocol_pb2.STATUS_NONE) - # This XMPP client is not receiving this for some reason. -# self.updateRoomList() -# for group in groups: -# room = group.getId() -# subjectOwner = group.getSubjectOwner() -# subject = group.getSubject() -# self.backend.handleSubject(self.user, room, subject, subjectOwner) -# for participant in group.getParticipants(): -# buddy = participant.split('@')[0] -# self.logger.debug("Added %s to room %s", buddy, room) -# self.backend.handleParticipantChanged(self.user, buddy, room, -# protocol_pb2.PARTICIPANT_FLAG_NONE, protocol_pb2.STATUS_ONLINE) + self._addParticipantsToRoom(room, group.getParticipants()) + if room in self.groupOfflineQueue: + while self.groupOfflineQueue[room]: + msg = self.groupOfflineQueue[room].pop(0) + self.backend.handleMessage(self.user, room, msg[1], + msg[0], "", msg[2]) + self.logger.debug("Send queued group message to: %s %s %s", + msg[0],msg[1], msg[2]) + self.updateRoomList() + + def joinRoom(self, room, nick): + if room in self.groups: + self.logger.info("Joining room: %s room=%s, nick=%s", + self.legacyName, room, nick) + + group = self.groups[room] + group.nick = nick + try: + ownerNick = self.buddies[group.subjectOwner].nick + except KeyError: + ownerNick = group.subjectOwner + + self.backend.handleSubject(self.user, room, group.subject, + ownerNick) + self.backend.handleRoomNicknameChanged(self.user, room, + group.subject) + else: + self.logger.warn("Room doesn't exist: %s", room) + + def _addParticipantsToRoom(self, room, participants): + group = self.groups[room] + + for jid, _type in participants.iteritems(): + buddy = jid.split("@")[0] + buddyFull = buddy + self.logger.info("Added %s to room %s", buddy, room) + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + buddyFull = buddy + if _type == 'admin': + flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR + else: + flags = protocol_pb2.PARTICIPANT_FLAG_NONE + if buddy == self.legacyName: + nick = group.nick + flags = protocol_pb2.PARTICIPANT_FLAG_ME + buddyFull = self.user + + self.backend.handleParticipantChanged(self.user, buddyFull, + room, flags, protocol_pb2.STATUS_ONLINE, buddy, nick) def _lastSeen(self, number, seconds): @@ -163,23 +206,29 @@ class Session(YowsupApp): self.logger.info("Auth success: %s", self.user) self.backend.handleConnected(self.user) - self.backend.handleBuddyChanged(self.user, "bot", self.bot.name, ["Admin"], protocol_pb2.STATUS_ONLINE) - self.initialized = True + self.backend.handleBuddyChanged(self.user, "bot", self.bot.name, + ["Admin"], protocol_pb2.STATUS_ONLINE) + if self.initialized == False: + self.sendOfflineMessages() + self.bot.call("welcome") + self.initialized = True self.sendPresence(True) - self.updateRoster() + self.logger.debug('Requesting groups list') + self.requestGroupsList(self._updateGroups) + # Called by superclass def onAuthFailed(self, reason): self.logger.info("Auth failed: %s (%s)", self.user, reason) self.backend.handleDisconnected(self.user, 0, reason) self.password = None + self.shouldBeConnected = False # Called by superclass def onDisconnect(self): self.logger.debug('Disconnected') self.backend.handleDisconnected(self.user, 0, 'Disconnected for unknown reasons') - self.loggedin = False # Called by superclass def onReceipt(self, _id, _from, timestamp, type, participant, offline, items): @@ -198,8 +247,9 @@ class Session(YowsupApp): ) # Called by superclass - def onTextMessage(self, _id, _from, to, notify, timestamp, participant, offline, retry, body): - self.logger.debug('received TextMessage' + + def onTextMessage(self, _id, _from, to, notify, timestamp, participant, + offline, retry, body): + self.logger.debug('received TextMessage' + ' '.join(map(str, [ _id, _from, to, notify, timestamp, participant, offline, retry, body @@ -210,10 +260,10 @@ class Session(YowsupApp): self.sendReceipt(_id, _from, None, participant) self.logger.info("Message received from %s to %s: %s (at ts=%s)", buddy, self.legacyName, messageContent, timestamp) - if participant is not None: + if participant is not None: # Group message partname = participant.split('@')[0] - message = partname + ': ' + messageContent - self.sendMessageToXMPP(buddy, message, timestamp) + self.sendGroupMessageToXMPP(buddy, partname, messageContent, + timestamp) else: self.sendMessageToXMPP(buddy, messageContent, timestamp) # isBroadcast always returns false, I'm not sure how to get a broadcast @@ -229,7 +279,7 @@ class Session(YowsupApp): buddy = image._from.split('@')[0] message = image.url + ' ' + image.caption self.sendMessageToXMPP(buddy, message, image.timestamp) - self.sendReceipt(image._id, image._from, None, image.participant) + self.sendReceipt(image._id, image._from, None, image.participant) # Called by superclass def onAudio(self, audio): @@ -237,7 +287,7 @@ class Session(YowsupApp): buddy = audio._from.split('@')[0] message = audio.url self.sendMessageToXMPP(buddy, message, audio.timestamp) - self.sendReceipt(audio._id, audio._from, None, audio.participant) + self.sendReceipt(audio._id, audio._from, None, audio.participant) # Called by superclass def onVideo(self, video): @@ -245,21 +295,35 @@ class Session(YowsupApp): buddy = video._from.split('@')[0] message = video.url self.sendMessageToXMPP(buddy, message, video.timestamp) - self.sendReceipt(video._id, video._from, None, video.participant) + self.sendReceipt(video._id, video._from, None, video.participant) + + def onLocation(self, location): + buddy = location._from.split('@')[0] + latitude = location.getLatitude() + longitude = location.getLongitude() + url = location.getLocationUrl() + + self.logger.debug("Location received from %s: %s, %s", + buddy, latitude, longitude) + + self.sendMessageToXMPP(buddy, url, location.timestamp) + self.sendMessageToXMPP(buddy, 'geo:' + latitude + ',' + longitude, + location.timestamp) + # Called by superclass def onVCard(self, _id, _from, name, card_data, to, notify, timestamp, participant): - self.logger.debug('received VCard' + + self.logger.debug('received VCard' + ' '.join(map(str, [ _id, _from, name, card_data, to, notify, timestamp, participant ])) ) buddy = _from.split("@")[0] self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)") - self.sendMessageToXMPP(buddy, card_data) +# self.sendMessageToXMPP(buddy, card_data) self.transferFile(buddy, str(name), card_data) self.sendReceipt(_id, _from, None, participant) - + def transferFile(self, buddy, name, data): # Not working self.logger.debug('transfering file %s', name) @@ -270,17 +334,21 @@ class Session(YowsupApp): # Called by superclass def onContactTyping(self, buddy): self.logger.info("Started typing: %s", buddy) - self.sendPresence(True) - self.backend.handleBuddyTyping(self.user, buddy) + if buddy != 'bot': + self.sendPresence(True) + self.backend.handleBuddyTyping(self.user, buddy) - if self.timer != None: - self.timer.cancel() + if self.timer != None: + self.timer.cancel() # Called by superclass def onContactPaused(self, buddy): self.logger.info("Paused typing: %s", buddy) - self.backend.handleBuddyTyped(self.user, buddy) - self.timer = Timer(3, self.backend.handleBuddyStoppedTyping, (self.user, buddy)).start() + if buddy != 'bot': + self.backend.handleBuddyTyped(self.user, buddy) + self.timer = Timer(3, self.backend.handleBuddyStoppedTyping, + (self.user, buddy)).start() + def onPresenceReceived(self, _type, name, jid, lastseen): self.logger.info("Presence received: %s %s %s %s", _type, name, jid, lastseen) buddy = jid.split("@")[0] @@ -302,7 +370,8 @@ class Session(YowsupApp): try: buddy = self.buddies[buddy] self.logger.info("Is available: %s", buddy) - self.backend.handleBuddyChanged(self.user, buddy.number.number, buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + self.backend.handleBuddyChanged(self.user, buddy.number.number, + buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) except KeyError: self.logger.error("Buddy not found: %s", buddy) @@ -310,7 +379,8 @@ class Session(YowsupApp): try: buddy = self.buddies[buddy] self.logger.info("Is unavailable: %s", buddy) - self.backend.handleBuddyChanged(self.user, buddy.number.number, buddy.nick, buddy.groups, protocol_pb2.STATUS_XA) + self.backend.handleBuddyChanged(self.user, buddy.number.number, + buddy.nick, buddy.groups, protocol_pb2.STATUS_XA) except KeyError: self.logger.error("Buddy not found: %s", buddy) @@ -330,20 +400,33 @@ class Session(YowsupApp): self.sendTyping(buddy, False) def sendMessageToWA(self, sender, message): - self.logger.info("Message sent from %s to %s: %s", self.legacyName, sender, message) + self.logger.info("Message sent from %s to %s: %s", + self.legacyName, sender, message) + message = message.encode("utf-8") if sender == "bot": self.bot.parse(message) elif "-" in sender: # group msg - if "/" in sender: - room, buddy = sender.split("/") - self.sendTextMessage(buddy + '@s.whatsapp.net', message) + if "/" in sender: # directed at single user + room, nick = sender.split("/") + for buddy, buddy3 in self.buddies.iteritems(): + self.logger.info("Group buddy=%s nick=%s", buddy, + buddy3.nick) + if buddy3.nick == nick: + nick = buddy + self.sendTextMessage(nick + '@s.whatsapp.net', message) else: room = sender -# group = self.groups[room] - -# self.backend.handleMessage(self.user, room, message, group.nick) + try: + group = self.groups[room] + self.logger.info("Group Message from %s to %s Groups: %s", + group.nick , group , self.groups) + self.backend.handleMessage( + self.user, room, message.decode('utf-8'), group.nick + ) + except KeyError: + self.logger.error('Group not found: %s', room) self.sendTextMessage(room + '@g.us', message) else: # private msg @@ -368,26 +451,37 @@ class Session(YowsupApp): "", timestamp) def sendGroupMessageToXMPP(self, room, buddy, messageContent, timestamp = ""): + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + if timestamp: timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp)) if self.initialized == False: - self.logger.debug("Group message queued from %s to %s: %s", buddy, room, messageContent) + self.logger.debug("Group message queued from %s to %s: %s", + buddy, room, messageContent) if room not in self.groupOfflineQueue: self.groupOfflineQueue[room] = [ ] - self.groupOfflineQueue[room].append((buddy, messageContent, timestamp)) + self.groupOfflineQueue[room].append( + (buddy, messageContent, timestamp) + ) else: - self.logger.debug("Group message sent from %s to %s: %s", buddy, room, messageContent) - self.backend.handleMessage(self.user, room, messageContent, buddy, "", timestamp) + self.logger.debug("Group message sent from %s to %s: %s", buddy, + room, messageContent) + self.backend.handleMessage(self.user, room, messageContent, nick, + "", timestamp, False) def changeStatus(self, status): if status != self.status: self.logger.info("Status changed: %s", status) self.status = status - if status == protocol_pb2.STATUS_ONLINE or status == protocol_pb2.STATUS_FFC: + if status == protocol_pb2.STATUS_ONLINE \ + or status == protocol_pb2.STATUS_FFC: self.sendPresence(True) else: self.sendPresence(False) @@ -421,21 +515,8 @@ class Session(YowsupApp): self.buddies.remove(buddy) self.updateRoster() - def joinRoom(self, room, nick): - if room in self.groups: - group = self.groups[room] - self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick) - - group.nick = nick - - self.call("group_getParticipants", (room + "@g.us",)) - self.backend.handleSubject(self.user, room, group.subject, group.subjectOwner) - else: - self.logger.warn("Room doesn't exist: %s", room) - def requestVCard(self, buddy, ID): - def onSuccess(response, request): self.logger.debug('Sending VCard (%s) with image id %s', ID, response.pictureId) @@ -458,32 +539,11 @@ class Session(YowsupApp): if receiptRequested: self.call("message_ack", (jid, messageId)) - def onGroupGotParticipants(self, gjid, jids): - room = gjid.split("@")[0] - group = self.groups[room] - - for jid in jids: - buddy = jid.split("@")[0] - self.logger.info("Added %s to room %s", buddy, room) - - if buddy == group.owner: - flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR - else: - flags = protocol_pb2.PARTICIPANT_FLAG_NONE - - self.backend.handleParticipantChanged(self.user, buddy, room, flags, protocol_pb2.STATUS_ONLINE) # TODO check status - - if room in self.groupOfflineQueue: - while self.groupOfflineQueue[room]: - msg = self.groupOfflineQueue[room].pop(0) - self.backend.handleMessage(self.user, room, msg[1], msg[0], "", msg[2]) - self.logger.debug("Send queued group message to: %s %s %s", msg[0],msg[1], msg[2]) - def onGroupMessageReceived(self, messageId, gjid, jid, messageContent, timestamp, receiptRequested, pushName): buddy = jid.split("@")[0] room = gjid.split("@")[0] - self.logger.info("Group message received in %s from %s: %s", room, buddy, messageContent) + self.logger.info("Group message received in %s from %s: %s", room, buddy, messageContent) self.sendGroupMessageToXMPP(room, buddy, utils.softToUni(messageContent), timestamp) if receiptRequested: self.call("message_ack", (gjid, messageId)) diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 8058b10..2a8349b 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -30,6 +30,7 @@ from yowsup.layers.protocol_calls import YowCallsProtocolLayer from yowsup.layers.protocol_acks.protocolentities import * from yowsup.layers.protocol_chatstate.protocolentities import * +from yowsup.layers.protocol_contacts.protocolentities import * from yowsup.layers.protocol_groups.protocolentities import * from yowsup.layers.protocol_media.protocolentities import * from yowsup.layers.protocol_messages.protocolentities import * @@ -197,6 +198,26 @@ class YowsupApp(object): ) self.sendEntity(state) + def sendSync(self, contacts, delta = False, interactive = True): + """ + You need to sync new contacts before you interact with + them, failure to do so could result in a temporary ban. + + Args: + - contacts: ([str]) a list of phone numbers of the + contacts you wish to sync + - delta: (bool; default: False) If true only send new + contacts to sync, if false you should send your full + contact list. + - interactive: (bool; default: True) Set to false if you are + sure this is the first time registering + """ + # TODO: Implement callbacks + mode = GetSyncIqProtocolEntity.MODE_DELTA if delta else GetSyncIqProtocolEntity.MODE_FULL + context = GetSyncIqProtocolEntity.CONTEXT_INTERACTIVE if interactive else GetSyncIqProtocolEntity.CONTEXT_REGISTRATION + iq = GetSyncIqProtocolEntity(contacts, mode, context) + self.sendIq(iq) + def requestLastSeen(self, phoneNumber, success = None, failure = None): """ Requests when user was last seen. @@ -219,8 +240,8 @@ class YowsupApp(object): Requests profile picture of whatsapp user Args: - phoneNumber: (str) the phone number of the user - - success: (func) called when request is successfully processed. - - failure: (func) called when request has failed + - onSuccess: (func) called when request is successfully processed. + - onFailure: (func) called when request has failed """ iq = GetPictureIqProtocolEntity(phoneNumber + '@s.whatsapp.net') self.sendIq(iq, onSuccess = onSuccess, onError = onFailure) @@ -229,6 +250,18 @@ class YowsupApp(object): iq = ListGroupsIqProtocolEntity() self.sendIq(iq, onSuccess = onSuccess, onError = onFailure) + def requestGroupInfo(self, group, onSuccess = None, onFailure = None): + """ + Request info on a specific group (includes participants, subject, owner etc.) + + Args: + - group: (str) the group id in the form of xxxxxxxxx-xxxxxxxx + - onSuccess: (func) called when request is successfully processed. + - onFailure: (func) called when request is has failed + """ + iq = InfoGroupsIqProtocolEntity(group + '@g.us') + self.sendIq(iq, onSuccess = onSuccess, onError = onFailure) + def onAuthSuccess(self, status, kind, creation, expiration, props, nonce, t): """ Called when login is successful. @@ -361,6 +394,15 @@ class YowsupApp(object): - entity: VideoDownloadableMediaMessageProtocolEntity """ pass + + def onLocation(self, entity): + """ + Called when location message is received + + Args: + - entity: LocationMediaMessageProtocolEntity + """ + pass def onVCard(self, _id, _from, name, card_data, to, notify, timestamp, participant): """ @@ -508,6 +550,8 @@ class YowsupAppLayer(YowInterfaceLayer): entity.timestamp, entity.participant ) + elif isinstance(entity, LocationMediaMessageProtocolEntity): + self.caller.onLocation(entity) @ProtocolEntityCallback('presence') def onPresenceReceived(self, presence): From 7f1c9cd0dbc837773b51cb2b643161ecb5982f40 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 21 Sep 2015 20:30:11 +0200 Subject: [PATCH 03/22] Shorten the name of groupchats to overcome truncation bug The names of groupchats are truncated internally to 22 characters. This causes many problems with groupchats, since spectrum incorrectly identifies the chat by the long name. To overcome this the phoneNumber-unixTime is converted to hexadecimal, to shorten the groupchat below 22 characters --- Spectrum2/backend.py | 3 +- buddy.py | 4 +-- session.py | 77 +++++++++++++++++++++++++++++++------------- whatsappbackend.py | 2 ++ 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index afbdec8..a027adc 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -25,7 +25,7 @@ class SpectrumBackend: self.m_data = "" self.m_init_res = 0 - def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = "", pm = True): + def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""): m = protocol_pb2.ConversationMessage() m.userName = user m.buddyName = legacyName @@ -33,7 +33,6 @@ class SpectrumBackend: m.nickname = nickname m.xhtml = xhtml m.timestamp = str(timestamp) - m.pm = pm message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE) self.send(message) diff --git a/buddy.py b/buddy.py index 1ab9944..e07ec46 100644 --- a/buddy.py +++ b/buddy.py @@ -23,7 +23,6 @@ __status__ = "Prototype" """ from Spectrum2 import protocol_pb2 -from Yowsup.Contacts.contacts import WAContactsSyncRequest import logging @@ -61,7 +60,8 @@ class Buddy(): def update(self, nick, groups, image_hash): self.nick = nick self.groups = groups - self.image_hash = image_hash + if image_hash is not None: + self.image_hash = image_hash groups = u",".join(groups).encode("latin-1") cur = self.db.cursor() diff --git a/session.py b/session.py index b59544a..d65361f 100644 --- a/session.py +++ b/session.py @@ -79,10 +79,18 @@ class Session(YowsupApp): self.shouldBeConncted = True super(Session, self).login(self.legacyName, self.password) + def _shortenGroupId(self, gid): + # FIXME: will have problems if number begins with 0 + return '-'.join(hex(int(s))[2:] for s in gid.split('-')) + + def _lengthenGroupId(self, gid): + # FIXME: will have problems if number begins with 0 + return '-'.join(str(int(s, 16)) for s in gid.split('-')) + def updateRoomList(self): rooms = [] for room, group in self.groups.iteritems(): - rooms.append([room, group.subject]) + rooms.append([self._shortenGroupId(room), group.subject]) self.logger.debug("Got rooms: %s", rooms) self.backend.handleRoomList(rooms) @@ -136,7 +144,7 @@ class Session(YowsupApp): oroom.subject = subject else: self.groups[room] = Group(room, owner, subject, subjectOwner) - self.joinRoom(room, self.user.split("@")[0]) + self.joinRoom(self._shortenGroupId(room), self.user.split("@")[0]) self._addParticipantsToRoom(room, group.getParticipants()) @@ -150,6 +158,7 @@ class Session(YowsupApp): self.updateRoomList() def joinRoom(self, room, nick): + room = self._lengthenGroupId(room) if room in self.groups: self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick) @@ -165,11 +174,38 @@ class Session(YowsupApp): ownerNick) self.backend.handleRoomNicknameChanged(self.user, room, group.subject) + self._refreshParticipants(room) else: self.logger.warn("Room doesn't exist: %s", room) + def _refreshParticipants(self, room): + group = self.groups[room] + for jid in group.participants: + buddy = jid.split("@")[0] + self.logger.info("Added %s to room %s", buddy, room) + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + if nick == "": + nick = buddy + + buddyFull = buddy + if buddy == group.owner: + flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR + else: + flags = protocol_pb2.PARTICIPANT_FLAG_NONE + if buddy == self.legacyName: + nick = group.nick + flags = flags | protocol_pb2.PARTICIPANT_FLAG_ME + buddyFull = self.user + self.backend.handleParticipantChanged( + self.user, buddyFull, self._shortenGroupId(room), flags, + protocol_pb2.STATUS_ONLINE, buddy, nick) + def _addParticipantsToRoom(self, room, participants): group = self.groups[room] + group.participants = participants for jid, _type in participants.iteritems(): buddy = jid.split("@")[0] @@ -190,7 +226,7 @@ class Session(YowsupApp): buddyFull = self.user self.backend.handleParticipantChanged(self.user, buddyFull, - room, flags, protocol_pb2.STATUS_ONLINE, buddy, nick) + self._shortenGroupId(room), flags, protocol_pb2.STATUS_ONLINE, buddy, nick) def _lastSeen(self, number, seconds): @@ -224,7 +260,7 @@ class Session(YowsupApp): self.backend.handleDisconnected(self.user, 0, reason) self.password = None self.shouldBeConnected = False - + # Called by superclass def onDisconnect(self): self.logger.debug('Disconnected') @@ -236,9 +272,12 @@ class Session(YowsupApp): ' '.join(map(str, [_id, _from, timestamp, type, participant, offline, items])) ) - buddy = self.buddies[_from.split('@')[0]] - self.backend.handleBuddyChanged(self.user, buddy.number.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + try: + buddy = self.buddies[_from.split('@')[0]] + self.backend.handleBuddyChanged(self.user, buddy.number.number, + buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + except KeyError: + pass # Called by superclass def onAck(self, _id, _class, _from, timestamp): @@ -427,7 +466,7 @@ class Session(YowsupApp): ) except KeyError: self.logger.error('Group not found: %s', room) - self.sendTextMessage(room + '@g.us', message) + self.sendTextMessage(self._lengthenGroupId(room) + '@g.us', message) else: # private msg buddy = sender @@ -451,10 +490,13 @@ class Session(YowsupApp): "", timestamp) def sendGroupMessageToXMPP(self, room, buddy, messageContent, timestamp = ""): + self._refreshParticipants(room) try: nick = self.buddies[buddy].nick except KeyError: nick = buddy + if nick == "": + nick = buddy if timestamp: timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp)) @@ -470,10 +512,10 @@ class Session(YowsupApp): (buddy, messageContent, timestamp) ) else: - self.logger.debug("Group message sent from %s to %s: %s", buddy, - room, messageContent) - self.backend.handleMessage(self.user, room, messageContent, nick, - "", timestamp, False) + self.logger.debug("Group message sent from %s (%s) to %s: %s", + buddy, nick, room, messageContent) + self.backend.handleMessage(self.user, self._shortenGroupId(room), + messageContent, nick, "", timestamp) def changeStatus(self, status): if status != self.status: @@ -504,7 +546,7 @@ class Session(YowsupApp): self.backend.handleMessage(self.user, msg[0], msg[1], "", "", msg[2]) # also for adding a new buddy - def updateBuddy(self, buddy, nick, groups, image_hash =""): + def updateBuddy(self, buddy, nick, groups, image_hash = None): if buddy != "bot": self.buddies.update(buddy, nick, groups, image_hash) self.updateRoster() @@ -539,15 +581,6 @@ class Session(YowsupApp): if receiptRequested: self.call("message_ack", (jid, messageId)) - def onGroupMessageReceived(self, messageId, gjid, jid, messageContent, timestamp, receiptRequested, pushName): - buddy = jid.split("@")[0] - room = gjid.split("@")[0] - - self.logger.info("Group message received in %s from %s: %s", room, buddy, messageContent) - - self.sendGroupMessageToXMPP(room, buddy, utils.softToUni(messageContent), timestamp) - if receiptRequested: self.call("message_ack", (gjid, messageId)) - def onGroupSubjectReceived(self, messageId, gjid, jid, subject, timestamp, receiptRequested): room = gjid.split("@")[0] buddy = jid.split("@")[0] diff --git a/whatsappbackend.py b/whatsappbackend.py index b7b9827..b973f76 100644 --- a/whatsappbackend.py +++ b/whatsappbackend.py @@ -67,6 +67,7 @@ class WhatsAppBackend(SpectrumBackend): # # TODO Proper fix, this work around drops all duplicate messages even # intentional ones. + # IDEA there is an ID field in ConvMessage. If it is extracted it will work usersMessage = self.lastMessage[user] if buddy not in usersMessage or usersMessage[buddy] != message: self.sessions[user].sendMessageToWA(buddy, message) @@ -105,6 +106,7 @@ class WhatsAppBackend(SpectrumBackend): self.logger.debug("handleVCardRequest(user=%s, buddy=%s, ID=%s)", user, buddy, ID) self.sessions[user].requestVCard(buddy, ID) + # TODO def handleBuddyBlockToggled(self, user, buddy, blocked): pass From f4e85f7689ae95fc9881e6c84166b699ffad9ee9 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 21 Sep 2015 21:45:18 +0200 Subject: [PATCH 04/22] Try to prevent transwhat from crashing on malformed protobuf --- Spectrum2/backend.py | 11 ++++++++++- session.py | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index a027adc..342f0e4 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -4,6 +4,7 @@ import struct import sys import os +import logging import google.protobuf def WRAP(MESSAGE, TYPE): @@ -24,6 +25,7 @@ class SpectrumBackend: self.m_pingReceived = False self.m_data = "" self.m_init_res = 0 + self.logger = logging.getLogger(self.__class__.__name__) def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""): m = protocol_pb2.ConversationMessage() @@ -349,8 +351,15 @@ class SpectrumBackend: wrapper = protocol_pb2.WrapperMessage() - if (wrapper.ParseFromString(self.m_data[4:]) == False): + try: + parseFromString = wrapper.ParseFromString(self.m_data[4:]) + except: + parseFromString = True + self.logger.error("Parse from String exception") + + if parseFromString == False: self.m_data = self.m_data[expected_size+4:] + self.logger.error("Parse from String exception") return self.m_data = self.m_data[4+expected_size:] diff --git a/session.py b/session.py index d65361f..bdd9144 100644 --- a/session.py +++ b/session.py @@ -458,7 +458,7 @@ class Session(YowsupApp): else: room = sender try: - group = self.groups[room] + group = self.groups[self._lengthenGroupId(room)] self.logger.info("Group Message from %s to %s Groups: %s", group.nick , group , self.groups) self.backend.handleMessage( From f1a6b109f70e7d422307853de1f3daa83654b1f7 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 14 Sep 2015 19:55:53 +0200 Subject: [PATCH 05/22] Regenerate protocol buffers --- Spectrum2/protocol_pb2.py | 612 +++++++++++++++++++++----------------- 1 file changed, 347 insertions(+), 265 deletions(-) diff --git a/Spectrum2/protocol_pb2.py b/Spectrum2/protocol_pb2.py index e01bd27..638435c 100644 --- a/Spectrum2/protocol_pb2.py +++ b/Spectrum2/protocol_pb2.py @@ -1,88 +1,99 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! +# source: protocol.proto -from google.protobuf import descriptor -from google.protobuf import message -from google.protobuf import reflection +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) +_sym_db = _symbol_database.Default() -DESCRIPTOR = descriptor.FileDescriptor( + + + +DESCRIPTOR = _descriptor.FileDescriptor( name='protocol.proto', package='pbnetwork', - serialized_pb='\n\x0eprotocol.proto\x12\tpbnetwork\"\x19\n\tConnected\x12\x0c\n\x04user\x18\x01 \x02(\t\"<\n\x0c\x44isconnected\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\r\n\x05\x65rror\x18\x02 \x02(\x05\x12\x0f\n\x07message\x18\x03 \x01(\t\"P\n\x05Login\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\x12\x10\n\x08password\x18\x03 \x02(\t\x12\x13\n\x0b\x65xtraFields\x18\x04 \x03(\t\"*\n\x06Logout\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\"\xab\x01\n\x05\x42uddy\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\r\n\x05\x61lias\x18\x03 \x01(\t\x12\r\n\x05group\x18\x04 \x03(\t\x12%\n\x06status\x18\x05 \x01(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x10\n\x08iconHash\x18\x07 \x01(\t\x12\x0f\n\x07\x62locked\x18\x08 \x01(\x08\"\xa9\x01\n\x13\x43onversationMessage\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x0f\n\x07message\x18\x03 \x02(\t\x12\x10\n\x08nickname\x18\x04 \x01(\t\x12\r\n\x05xhtml\x18\x05 \x01(\t\x12\x11\n\ttimestamp\x18\x06 \x01(\t\x12\x10\n\x08headline\x18\x07 \x01(\x08\x12\n\n\x02id\x18\x08 \x01(\t\x12\n\n\x02pm\x18\t \x01(\x08\"J\n\x04Room\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x10\n\x08nickname\x18\x02 \x02(\t\x12\x0c\n\x04room\x18\x03 \x02(\t\x12\x10\n\x08password\x18\x04 \x01(\t\"&\n\x08RoomList\x12\x0c\n\x04room\x18\x01 \x03(\t\x12\x0c\n\x04name\x18\x02 \x03(\t\"\x9c\x01\n\x0bParticipant\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x0c\n\x04room\x18\x02 \x02(\t\x12\x10\n\x08nickname\x18\x03 \x02(\t\x12\x0c\n\x04\x66lag\x18\x04 \x02(\x05\x12%\n\x06status\x18\x05 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x0f\n\x07newname\x18\x07 \x01(\t\"k\n\x05VCard\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\n\n\x02id\x18\x03 \x02(\x05\x12\x10\n\x08\x66ullname\x18\x04 \x01(\t\x12\x10\n\x08nickname\x18\x05 \x01(\t\x12\r\n\x05photo\x18\x06 \x01(\x0c\"X\n\x06Status\x12\x10\n\x08userName\x18\x01 \x02(\t\x12%\n\x06status\x18\x03 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x04 \x01(\t\"B\n\x05Stats\x12\x0b\n\x03res\x18\x01 \x02(\x05\x12\x10\n\x08init_res\x18\x02 \x02(\x05\x12\x0e\n\x06shared\x18\x03 \x02(\x05\x12\n\n\x02id\x18\x04 \x02(\t\"Y\n\x04\x46ile\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x10\n\x08\x66ileName\x18\x03 \x02(\t\x12\x0c\n\x04size\x18\x04 \x02(\x05\x12\x0c\n\x04\x66tID\x18\x05 \x01(\x05\".\n\x10\x46ileTransferData\x12\x0c\n\x04\x66tID\x18\x01 \x02(\x05\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c\"\x1f\n\rBackendConfig\x12\x0e\n\x06\x63onfig\x18\x01 \x02(\t\"\x9a\x06\n\x0eWrapperMessage\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.pbnetwork.WrapperMessage.Type\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"\xc8\x05\n\x04Type\x12\x12\n\x0eTYPE_CONNECTED\x10\x01\x12\x15\n\x11TYPE_DISCONNECTED\x10\x02\x12\x0e\n\nTYPE_LOGIN\x10\x03\x12\x0f\n\x0bTYPE_LOGOUT\x10\x04\x12\x16\n\x12TYPE_BUDDY_CHANGED\x10\x06\x12\x16\n\x12TYPE_BUDDY_REMOVED\x10\x07\x12\x15\n\x11TYPE_CONV_MESSAGE\x10\x08\x12\r\n\tTYPE_PING\x10\t\x12\r\n\tTYPE_PONG\x10\n\x12\x12\n\x0eTYPE_JOIN_ROOM\x10\x0b\x12\x13\n\x0fTYPE_LEAVE_ROOM\x10\x0c\x12\x1c\n\x18TYPE_PARTICIPANT_CHANGED\x10\r\x12\x1e\n\x1aTYPE_ROOM_NICKNAME_CHANGED\x10\x0e\x12\x1d\n\x19TYPE_ROOM_SUBJECT_CHANGED\x10\x0f\x12\x0e\n\nTYPE_VCARD\x10\x10\x12\x17\n\x13TYPE_STATUS_CHANGED\x10\x11\x12\x15\n\x11TYPE_BUDDY_TYPING\x10\x12\x12\x1d\n\x19TYPE_BUDDY_STOPPED_TYPING\x10\x13\x12\x14\n\x10TYPE_BUDDY_TYPED\x10\x14\x12\x15\n\x11TYPE_AUTH_REQUEST\x10\x15\x12\x12\n\x0eTYPE_ATTENTION\x10\x16\x12\x0e\n\nTYPE_STATS\x10\x17\x12\x11\n\rTYPE_FT_START\x10\x18\x12\x12\n\x0eTYPE_FT_FINISH\x10\x19\x12\x10\n\x0cTYPE_FT_DATA\x10\x1a\x12\x11\n\rTYPE_FT_PAUSE\x10\x1b\x12\x14\n\x10TYPE_FT_CONTINUE\x10\x1c\x12\r\n\tTYPE_EXIT\x10\x1d\x12\x17\n\x13TYPE_BACKEND_CONFIG\x10\x1e\x12\x0e\n\nTYPE_QUERY\x10\x1f\x12\x12\n\x0eTYPE_ROOM_LIST\x10 \x12\x19\n\x15TYPE_CONV_MESSAGE_ACK\x10!\x12\x10\n\x0cTYPE_RAW_XML\x10\"*\xb3\x05\n\x0f\x43onnectionError\x12\"\n\x1e\x43ONNECTION_ERROR_NETWORK_ERROR\x10\x00\x12%\n!CONNECTION_ERROR_INVALID_USERNAME\x10\x01\x12*\n&CONNECTION_ERROR_AUTHENTICATION_FAILED\x10\x02\x12.\n*CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE\x10\x03\x12#\n\x1f\x43ONNECTION_ERROR_NO_SSL_SUPPORT\x10\x04\x12%\n!CONNECTION_ERROR_ENCRYPTION_ERROR\x10\x05\x12 \n\x1c\x43ONNECTION_ERROR_NAME_IN_USE\x10\x06\x12%\n!CONNECTION_ERROR_INVALID_SETTINGS\x10\x07\x12&\n\"CONNECTION_ERROR_CERT_NOT_PROVIDED\x10\x08\x12#\n\x1f\x43ONNECTION_ERROR_CERT_UNTRUSTED\x10\t\x12!\n\x1d\x43ONNECTION_ERROR_CERT_EXPIRED\x10\n\x12\'\n#CONNECTION_ERROR_CERT_NOT_ACTIVATED\x10\x0b\x12+\n\'CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH\x10\x0c\x12.\n*CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH\x10\r\x12%\n!CONNECTION_ERROR_CERT_SELF_SIGNED\x10\x0e\x12%\n!CONNECTION_ERROR_CERT_OTHER_ERROR\x10\x0f\x12 \n\x1c\x43ONNECTION_ERROR_OTHER_ERROR\x10\x10*\x86\x01\n\nStatusType\x12\x11\n\rSTATUS_ONLINE\x10\x00\x12\x0f\n\x0bSTATUS_AWAY\x10\x01\x12\x0e\n\nSTATUS_FFC\x10\x02\x12\r\n\tSTATUS_XA\x10\x03\x12\x0e\n\nSTATUS_DND\x10\x04\x12\x0f\n\x0bSTATUS_NONE\x10\x05\x12\x14\n\x10STATUS_INVISIBLE\x10\x06*\x88\x02\n\x0fParticipantFlag\x12\x19\n\x15PARTICIPANT_FLAG_NONE\x10\x00\x12\x1e\n\x1aPARTICIPANT_FLAG_MODERATOR\x10\x01\x12\x1d\n\x19PARTICIPANT_FLAG_CONFLICT\x10\x02\x12\x1b\n\x17PARTICIPANT_FLAG_BANNED\x10\x04\x12#\n\x1fPARTICIPANT_FLAG_NOT_AUTHORIZED\x10\x08\x12\x17\n\x13PARTICIPANT_FLAG_ME\x10\x10\x12\x1b\n\x17PARTICIPANT_FLAG_KICKED\x10 \x12#\n\x1fPARTICIPANT_FLAG_ROOM_NOT_FOUND\x10@') + serialized_pb=_b('\n\x0eprotocol.proto\x12\tpbnetwork\"\x19\n\tConnected\x12\x0c\n\x04user\x18\x01 \x02(\t\"<\n\x0c\x44isconnected\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\r\n\x05\x65rror\x18\x02 \x02(\x05\x12\x0f\n\x07message\x18\x03 \x01(\t\"P\n\x05Login\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\x12\x10\n\x08password\x18\x03 \x02(\t\x12\x13\n\x0b\x65xtraFields\x18\x04 \x03(\t\"*\n\x06Logout\x12\x0c\n\x04user\x18\x01 \x02(\t\x12\x12\n\nlegacyName\x18\x02 \x02(\t\"\xab\x01\n\x05\x42uddy\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\r\n\x05\x61lias\x18\x03 \x01(\t\x12\r\n\x05group\x18\x04 \x03(\t\x12%\n\x06status\x18\x05 \x01(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x10\n\x08iconHash\x18\x07 \x01(\t\x12\x0f\n\x07\x62locked\x18\x08 \x01(\x08\"\xa9\x01\n\x13\x43onversationMessage\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x0f\n\x07message\x18\x03 \x02(\t\x12\x10\n\x08nickname\x18\x04 \x01(\t\x12\r\n\x05xhtml\x18\x05 \x01(\t\x12\x11\n\ttimestamp\x18\x06 \x01(\t\x12\x10\n\x08headline\x18\x07 \x01(\x08\x12\n\n\x02id\x18\x08 \x01(\t\x12\n\n\x02pm\x18\t \x01(\x08\"J\n\x04Room\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x10\n\x08nickname\x18\x02 \x02(\t\x12\x0c\n\x04room\x18\x03 \x02(\t\x12\x10\n\x08password\x18\x04 \x01(\t\"&\n\x08RoomList\x12\x0c\n\x04room\x18\x01 \x03(\t\x12\x0c\n\x04name\x18\x02 \x03(\t\"\x9c\x01\n\x0bParticipant\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x0c\n\x04room\x18\x02 \x02(\t\x12\x10\n\x08nickname\x18\x03 \x02(\t\x12\x0c\n\x04\x66lag\x18\x04 \x02(\x05\x12%\n\x06status\x18\x05 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x06 \x01(\t\x12\x0f\n\x07newname\x18\x07 \x01(\t\"k\n\x05VCard\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\n\n\x02id\x18\x03 \x02(\x05\x12\x10\n\x08\x66ullname\x18\x04 \x01(\t\x12\x10\n\x08nickname\x18\x05 \x01(\t\x12\r\n\x05photo\x18\x06 \x01(\x0c\"X\n\x06Status\x12\x10\n\x08userName\x18\x01 \x02(\t\x12%\n\x06status\x18\x03 \x02(\x0e\x32\x15.pbnetwork.StatusType\x12\x15\n\rstatusMessage\x18\x04 \x01(\t\"B\n\x05Stats\x12\x0b\n\x03res\x18\x01 \x02(\x05\x12\x10\n\x08init_res\x18\x02 \x02(\x05\x12\x0e\n\x06shared\x18\x03 \x02(\x05\x12\n\n\x02id\x18\x04 \x02(\t\"Y\n\x04\x46ile\x12\x10\n\x08userName\x18\x01 \x02(\t\x12\x11\n\tbuddyName\x18\x02 \x02(\t\x12\x10\n\x08\x66ileName\x18\x03 \x02(\t\x12\x0c\n\x04size\x18\x04 \x02(\x05\x12\x0c\n\x04\x66tID\x18\x05 \x01(\x05\".\n\x10\x46ileTransferData\x12\x0c\n\x04\x66tID\x18\x01 \x02(\x05\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c\"\x1f\n\rBackendConfig\x12\x0e\n\x06\x63onfig\x18\x01 \x02(\t\"\x9a\x06\n\x0eWrapperMessage\x12,\n\x04type\x18\x01 \x02(\x0e\x32\x1e.pbnetwork.WrapperMessage.Type\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\"\xc8\x05\n\x04Type\x12\x12\n\x0eTYPE_CONNECTED\x10\x01\x12\x15\n\x11TYPE_DISCONNECTED\x10\x02\x12\x0e\n\nTYPE_LOGIN\x10\x03\x12\x0f\n\x0bTYPE_LOGOUT\x10\x04\x12\x16\n\x12TYPE_BUDDY_CHANGED\x10\x06\x12\x16\n\x12TYPE_BUDDY_REMOVED\x10\x07\x12\x15\n\x11TYPE_CONV_MESSAGE\x10\x08\x12\r\n\tTYPE_PING\x10\t\x12\r\n\tTYPE_PONG\x10\n\x12\x12\n\x0eTYPE_JOIN_ROOM\x10\x0b\x12\x13\n\x0fTYPE_LEAVE_ROOM\x10\x0c\x12\x1c\n\x18TYPE_PARTICIPANT_CHANGED\x10\r\x12\x1e\n\x1aTYPE_ROOM_NICKNAME_CHANGED\x10\x0e\x12\x1d\n\x19TYPE_ROOM_SUBJECT_CHANGED\x10\x0f\x12\x0e\n\nTYPE_VCARD\x10\x10\x12\x17\n\x13TYPE_STATUS_CHANGED\x10\x11\x12\x15\n\x11TYPE_BUDDY_TYPING\x10\x12\x12\x1d\n\x19TYPE_BUDDY_STOPPED_TYPING\x10\x13\x12\x14\n\x10TYPE_BUDDY_TYPED\x10\x14\x12\x15\n\x11TYPE_AUTH_REQUEST\x10\x15\x12\x12\n\x0eTYPE_ATTENTION\x10\x16\x12\x0e\n\nTYPE_STATS\x10\x17\x12\x11\n\rTYPE_FT_START\x10\x18\x12\x12\n\x0eTYPE_FT_FINISH\x10\x19\x12\x10\n\x0cTYPE_FT_DATA\x10\x1a\x12\x11\n\rTYPE_FT_PAUSE\x10\x1b\x12\x14\n\x10TYPE_FT_CONTINUE\x10\x1c\x12\r\n\tTYPE_EXIT\x10\x1d\x12\x17\n\x13TYPE_BACKEND_CONFIG\x10\x1e\x12\x0e\n\nTYPE_QUERY\x10\x1f\x12\x12\n\x0eTYPE_ROOM_LIST\x10 \x12\x19\n\x15TYPE_CONV_MESSAGE_ACK\x10!\x12\x10\n\x0cTYPE_RAW_XML\x10\"*\xb3\x05\n\x0f\x43onnectionError\x12\"\n\x1e\x43ONNECTION_ERROR_NETWORK_ERROR\x10\x00\x12%\n!CONNECTION_ERROR_INVALID_USERNAME\x10\x01\x12*\n&CONNECTION_ERROR_AUTHENTICATION_FAILED\x10\x02\x12.\n*CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE\x10\x03\x12#\n\x1f\x43ONNECTION_ERROR_NO_SSL_SUPPORT\x10\x04\x12%\n!CONNECTION_ERROR_ENCRYPTION_ERROR\x10\x05\x12 \n\x1c\x43ONNECTION_ERROR_NAME_IN_USE\x10\x06\x12%\n!CONNECTION_ERROR_INVALID_SETTINGS\x10\x07\x12&\n\"CONNECTION_ERROR_CERT_NOT_PROVIDED\x10\x08\x12#\n\x1f\x43ONNECTION_ERROR_CERT_UNTRUSTED\x10\t\x12!\n\x1d\x43ONNECTION_ERROR_CERT_EXPIRED\x10\n\x12\'\n#CONNECTION_ERROR_CERT_NOT_ACTIVATED\x10\x0b\x12+\n\'CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH\x10\x0c\x12.\n*CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH\x10\r\x12%\n!CONNECTION_ERROR_CERT_SELF_SIGNED\x10\x0e\x12%\n!CONNECTION_ERROR_CERT_OTHER_ERROR\x10\x0f\x12 \n\x1c\x43ONNECTION_ERROR_OTHER_ERROR\x10\x10*\x86\x01\n\nStatusType\x12\x11\n\rSTATUS_ONLINE\x10\x00\x12\x0f\n\x0bSTATUS_AWAY\x10\x01\x12\x0e\n\nSTATUS_FFC\x10\x02\x12\r\n\tSTATUS_XA\x10\x03\x12\x0e\n\nSTATUS_DND\x10\x04\x12\x0f\n\x0bSTATUS_NONE\x10\x05\x12\x14\n\x10STATUS_INVISIBLE\x10\x06*\x88\x02\n\x0fParticipantFlag\x12\x19\n\x15PARTICIPANT_FLAG_NONE\x10\x00\x12\x1e\n\x1aPARTICIPANT_FLAG_MODERATOR\x10\x01\x12\x1d\n\x19PARTICIPANT_FLAG_CONFLICT\x10\x02\x12\x1b\n\x17PARTICIPANT_FLAG_BANNED\x10\x04\x12#\n\x1fPARTICIPANT_FLAG_NOT_AUTHORIZED\x10\x08\x12\x17\n\x13PARTICIPANT_FLAG_ME\x10\x10\x12\x1b\n\x17PARTICIPANT_FLAG_KICKED\x10 \x12#\n\x1fPARTICIPANT_FLAG_ROOM_NOT_FOUND\x10@') +) +_sym_db.RegisterFileDescriptor(DESCRIPTOR) -_CONNECTIONERROR = descriptor.EnumDescriptor( +_CONNECTIONERROR = _descriptor.EnumDescriptor( name='ConnectionError', full_name='pbnetwork.ConnectionError', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_NETWORK_ERROR', index=0, number=0, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_INVALID_USERNAME', index=1, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_AUTHENTICATION_FAILED', index=2, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE', index=3, number=3, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_NO_SSL_SUPPORT', index=4, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_ENCRYPTION_ERROR', index=5, number=5, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_NAME_IN_USE', index=6, number=6, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_INVALID_SETTINGS', index=7, number=7, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_NOT_PROVIDED', index=8, number=8, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_UNTRUSTED', index=9, number=9, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_EXPIRED', index=10, number=10, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_NOT_ACTIVATED', index=11, number=11, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH', index=12, number=12, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH', index=13, number=13, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_SELF_SIGNED', index=14, number=14, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_CERT_OTHER_ERROR', index=15, number=15, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CONNECTION_ERROR_OTHER_ERROR', index=16, number=16, options=None, type=None), @@ -92,39 +103,40 @@ _CONNECTIONERROR = descriptor.EnumDescriptor( serialized_start=2102, serialized_end=2793, ) +_sym_db.RegisterEnumDescriptor(_CONNECTIONERROR) - -_STATUSTYPE = descriptor.EnumDescriptor( +ConnectionError = enum_type_wrapper.EnumTypeWrapper(_CONNECTIONERROR) +_STATUSTYPE = _descriptor.EnumDescriptor( name='StatusType', full_name='pbnetwork.StatusType', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_ONLINE', index=0, number=0, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_AWAY', index=1, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_FFC', index=2, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_XA', index=3, number=3, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_DND', index=4, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_NONE', index=5, number=5, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='STATUS_INVISIBLE', index=6, number=6, options=None, type=None), @@ -134,43 +146,44 @@ _STATUSTYPE = descriptor.EnumDescriptor( serialized_start=2796, serialized_end=2930, ) +_sym_db.RegisterEnumDescriptor(_STATUSTYPE) - -_PARTICIPANTFLAG = descriptor.EnumDescriptor( +StatusType = enum_type_wrapper.EnumTypeWrapper(_STATUSTYPE) +_PARTICIPANTFLAG = _descriptor.EnumDescriptor( name='ParticipantFlag', full_name='pbnetwork.ParticipantFlag', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_NONE', index=0, number=0, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_MODERATOR', index=1, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_CONFLICT', index=2, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_BANNED', index=3, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_NOT_AUTHORIZED', index=4, number=8, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_ME', index=5, number=16, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_KICKED', index=6, number=32, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='PARTICIPANT_FLAG_ROOM_NOT_FOUND', index=7, number=64, options=None, type=None), @@ -180,8 +193,9 @@ _PARTICIPANTFLAG = descriptor.EnumDescriptor( serialized_start=2933, serialized_end=3197, ) +_sym_db.RegisterEnumDescriptor(_PARTICIPANTFLAG) - +ParticipantFlag = enum_type_wrapper.EnumTypeWrapper(_PARTICIPANTFLAG) CONNECTION_ERROR_NETWORK_ERROR = 0 CONNECTION_ERROR_INVALID_USERNAME = 1 CONNECTION_ERROR_AUTHENTICATION_FAILED = 2 @@ -216,141 +230,141 @@ PARTICIPANT_FLAG_KICKED = 32 PARTICIPANT_FLAG_ROOM_NOT_FOUND = 64 -_WRAPPERMESSAGE_TYPE = descriptor.EnumDescriptor( +_WRAPPERMESSAGE_TYPE = _descriptor.EnumDescriptor( name='Type', full_name='pbnetwork.WrapperMessage.Type', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_CONNECTED', index=0, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_DISCONNECTED', index=1, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_LOGIN', index=2, number=3, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_LOGOUT', index=3, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_CHANGED', index=4, number=6, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_REMOVED', index=5, number=7, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_CONV_MESSAGE', index=6, number=8, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_PING', index=7, number=9, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_PONG', index=8, number=10, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_JOIN_ROOM', index=9, number=11, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_LEAVE_ROOM', index=10, number=12, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_PARTICIPANT_CHANGED', index=11, number=13, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ROOM_NICKNAME_CHANGED', index=12, number=14, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ROOM_SUBJECT_CHANGED', index=13, number=15, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_VCARD', index=14, number=16, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_STATUS_CHANGED', index=15, number=17, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_TYPING', index=16, number=18, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_STOPPED_TYPING', index=17, number=19, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BUDDY_TYPED', index=18, number=20, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_AUTH_REQUEST', index=19, number=21, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ATTENTION', index=20, number=22, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_STATS', index=21, number=23, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_START', index=22, number=24, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_FINISH', index=23, number=25, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_DATA', index=24, number=26, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_PAUSE', index=25, number=27, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_FT_CONTINUE', index=26, number=28, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_EXIT', index=27, number=29, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_BACKEND_CONFIG', index=28, number=30, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_QUERY', index=29, number=31, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_ROOM_LIST', index=30, number=32, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_CONV_MESSAGE_ACK', index=31, number=33, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='TYPE_RAW_XML', index=32, number=34, options=None, type=None), @@ -360,19 +374,20 @@ _WRAPPERMESSAGE_TYPE = descriptor.EnumDescriptor( serialized_start=1387, serialized_end=2099, ) +_sym_db.RegisterEnumDescriptor(_WRAPPERMESSAGE_TYPE) -_CONNECTED = descriptor.Descriptor( +_CONNECTED = _descriptor.Descriptor( name='Connected', full_name='pbnetwork.Connected', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Connected.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -385,36 +400,38 @@ _CONNECTED = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=29, serialized_end=54, ) -_DISCONNECTED = descriptor.Descriptor( +_DISCONNECTED = _descriptor.Descriptor( name='Disconnected', full_name='pbnetwork.Disconnected', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Disconnected.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='error', full_name='pbnetwork.Disconnected.error', index=1, number=2, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='message', full_name='pbnetwork.Disconnected.message', index=2, number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -427,40 +444,42 @@ _DISCONNECTED = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=56, serialized_end=116, ) -_LOGIN = descriptor.Descriptor( +_LOGIN = _descriptor.Descriptor( name='Login', full_name='pbnetwork.Login', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Login.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='legacyName', full_name='pbnetwork.Login.legacyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='password', full_name='pbnetwork.Login.password', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='extraFields', full_name='pbnetwork.Login.extraFields', index=3, number=4, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], @@ -476,29 +495,31 @@ _LOGIN = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=118, serialized_end=198, ) -_LOGOUT = descriptor.Descriptor( +_LOGOUT = _descriptor.Descriptor( name='Logout', full_name='pbnetwork.Logout', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='user', full_name='pbnetwork.Logout.user', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='legacyName', full_name='pbnetwork.Logout.legacyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -511,68 +532,70 @@ _LOGOUT = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=200, serialized_end=242, ) -_BUDDY = descriptor.Descriptor( +_BUDDY = _descriptor.Descriptor( name='Buddy', full_name='pbnetwork.Buddy', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Buddy.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.Buddy.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='alias', full_name='pbnetwork.Buddy.alias', index=2, number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='group', full_name='pbnetwork.Buddy.group', index=3, number=4, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='status', full_name='pbnetwork.Buddy.status', index=4, number=5, 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='statusMessage', full_name='pbnetwork.Buddy.statusMessage', index=5, number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='iconHash', full_name='pbnetwork.Buddy.iconHash', index=6, number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='blocked', full_name='pbnetwork.Buddy.blocked', index=7, number=8, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, @@ -588,75 +611,77 @@ _BUDDY = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=245, serialized_end=416, ) -_CONVERSATIONMESSAGE = descriptor.Descriptor( +_CONVERSATIONMESSAGE = _descriptor.Descriptor( name='ConversationMessage', full_name='pbnetwork.ConversationMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.ConversationMessage.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.ConversationMessage.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='message', full_name='pbnetwork.ConversationMessage.message', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.ConversationMessage.nickname', index=3, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='xhtml', full_name='pbnetwork.ConversationMessage.xhtml', index=4, number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='timestamp', full_name='pbnetwork.ConversationMessage.timestamp', index=5, number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='headline', full_name='pbnetwork.ConversationMessage.headline', index=6, number=7, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='id', full_name='pbnetwork.ConversationMessage.id', index=7, number=8, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='pm', full_name='pbnetwork.ConversationMessage.pm', index=8, number=9, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, @@ -672,43 +697,45 @@ _CONVERSATIONMESSAGE = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=419, serialized_end=588, ) -_ROOM = descriptor.Descriptor( +_ROOM = _descriptor.Descriptor( name='Room', full_name='pbnetwork.Room', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Room.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.Room.nickname', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='room', full_name='pbnetwork.Room.room', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='password', full_name='pbnetwork.Room.password', index=3, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -721,26 +748,28 @@ _ROOM = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=590, serialized_end=664, ) -_ROOMLIST = descriptor.Descriptor( +_ROOMLIST = _descriptor.Descriptor( name='RoomList', full_name='pbnetwork.RoomList', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='room', full_name='pbnetwork.RoomList.room', index=0, number=1, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='name', full_name='pbnetwork.RoomList.name', index=1, number=2, type=9, cpp_type=9, label=3, has_default_value=False, default_value=[], @@ -756,64 +785,66 @@ _ROOMLIST = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=666, serialized_end=704, ) -_PARTICIPANT = descriptor.Descriptor( +_PARTICIPANT = _descriptor.Descriptor( name='Participant', full_name='pbnetwork.Participant', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Participant.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='room', full_name='pbnetwork.Participant.room', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.Participant.nickname', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='flag', full_name='pbnetwork.Participant.flag', index=3, number=4, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='status', full_name='pbnetwork.Participant.status', index=4, number=5, type=14, cpp_type=8, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='statusMessage', full_name='pbnetwork.Participant.statusMessage', index=5, number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='newname', full_name='pbnetwork.Participant.newname', index=6, number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -826,57 +857,59 @@ _PARTICIPANT = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=707, serialized_end=863, ) -_VCARD = descriptor.Descriptor( +_VCARD = _descriptor.Descriptor( name='VCard', full_name='pbnetwork.VCard', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.VCard.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.VCard.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='id', full_name='pbnetwork.VCard.id', index=2, number=3, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='fullname', full_name='pbnetwork.VCard.fullname', index=3, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='nickname', full_name='pbnetwork.VCard.nickname', index=4, number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='photo', full_name='pbnetwork.VCard.photo', index=5, number=6, type=12, cpp_type=9, label=1, - has_default_value=False, default_value="", + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -889,36 +922,38 @@ _VCARD = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=865, serialized_end=972, ) -_STATUS = descriptor.Descriptor( +_STATUS = _descriptor.Descriptor( name='Status', full_name='pbnetwork.Status', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.Status.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='status', full_name='pbnetwork.Status.status', index=1, number=3, type=14, cpp_type=8, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='statusMessage', full_name='pbnetwork.Status.statusMessage', index=2, number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -931,43 +966,45 @@ _STATUS = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=974, serialized_end=1062, ) -_STATS = descriptor.Descriptor( +_STATS = _descriptor.Descriptor( name='Stats', full_name='pbnetwork.Stats', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='res', full_name='pbnetwork.Stats.res', index=0, number=1, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='init_res', full_name='pbnetwork.Stats.init_res', index=1, number=2, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='shared', full_name='pbnetwork.Stats.shared', index=2, number=3, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='id', full_name='pbnetwork.Stats.id', index=3, number=4, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -980,47 +1017,49 @@ _STATS = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1064, serialized_end=1130, ) -_FILE = descriptor.Descriptor( +_FILE = _descriptor.Descriptor( name='File', full_name='pbnetwork.File', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='userName', full_name='pbnetwork.File.userName', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='buddyName', full_name='pbnetwork.File.buddyName', index=1, number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='fileName', full_name='pbnetwork.File.fileName', index=2, number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='size', full_name='pbnetwork.File.size', index=3, number=4, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='ftID', full_name='pbnetwork.File.ftID', index=4, number=5, type=5, cpp_type=1, label=1, has_default_value=False, default_value=0, @@ -1036,29 +1075,31 @@ _FILE = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1132, serialized_end=1221, ) -_FILETRANSFERDATA = descriptor.Descriptor( +_FILETRANSFERDATA = _descriptor.Descriptor( name='FileTransferData', full_name='pbnetwork.FileTransferData', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='ftID', full_name='pbnetwork.FileTransferData.ftID', index=0, number=1, type=5, cpp_type=1, label=2, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='data', full_name='pbnetwork.FileTransferData.data', index=1, number=2, type=12, cpp_type=9, label=2, - has_default_value=False, default_value="", + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -1071,22 +1112,24 @@ _FILETRANSFERDATA = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1223, serialized_end=1269, ) -_BACKENDCONFIG = descriptor.Descriptor( +_BACKENDCONFIG = _descriptor.Descriptor( name='BackendConfig', full_name='pbnetwork.BackendConfig', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='config', full_name='pbnetwork.BackendConfig.config', index=0, number=1, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), + 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), @@ -1099,29 +1142,31 @@ _BACKENDCONFIG = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1271, serialized_end=1302, ) -_WRAPPERMESSAGE = descriptor.Descriptor( +_WRAPPERMESSAGE = _descriptor.Descriptor( name='WrapperMessage', full_name='pbnetwork.WrapperMessage', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='type', full_name='pbnetwork.WrapperMessage.type', index=0, number=1, type=14, cpp_type=8, label=2, has_default_value=False, default_value=1, message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='payload', full_name='pbnetwork.WrapperMessage.payload', index=1, number=2, type=12, cpp_type=9, label=1, - has_default_value=False, default_value="", + has_default_value=False, default_value=_b(""), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None), @@ -1135,111 +1180,148 @@ _WRAPPERMESSAGE = descriptor.Descriptor( options=None, is_extendable=False, extension_ranges=[], + oneofs=[ + ], serialized_start=1305, serialized_end=2099, ) - _BUDDY.fields_by_name['status'].enum_type = _STATUSTYPE _PARTICIPANT.fields_by_name['status'].enum_type = _STATUSTYPE _STATUS.fields_by_name['status'].enum_type = _STATUSTYPE _WRAPPERMESSAGE.fields_by_name['type'].enum_type = _WRAPPERMESSAGE_TYPE -_WRAPPERMESSAGE_TYPE.containing_type = _WRAPPERMESSAGE; +_WRAPPERMESSAGE_TYPE.containing_type = _WRAPPERMESSAGE +DESCRIPTOR.message_types_by_name['Connected'] = _CONNECTED +DESCRIPTOR.message_types_by_name['Disconnected'] = _DISCONNECTED +DESCRIPTOR.message_types_by_name['Login'] = _LOGIN +DESCRIPTOR.message_types_by_name['Logout'] = _LOGOUT +DESCRIPTOR.message_types_by_name['Buddy'] = _BUDDY +DESCRIPTOR.message_types_by_name['ConversationMessage'] = _CONVERSATIONMESSAGE +DESCRIPTOR.message_types_by_name['Room'] = _ROOM +DESCRIPTOR.message_types_by_name['RoomList'] = _ROOMLIST +DESCRIPTOR.message_types_by_name['Participant'] = _PARTICIPANT +DESCRIPTOR.message_types_by_name['VCard'] = _VCARD +DESCRIPTOR.message_types_by_name['Status'] = _STATUS +DESCRIPTOR.message_types_by_name['Stats'] = _STATS +DESCRIPTOR.message_types_by_name['File'] = _FILE +DESCRIPTOR.message_types_by_name['FileTransferData'] = _FILETRANSFERDATA +DESCRIPTOR.message_types_by_name['BackendConfig'] = _BACKENDCONFIG +DESCRIPTOR.message_types_by_name['WrapperMessage'] = _WRAPPERMESSAGE +DESCRIPTOR.enum_types_by_name['ConnectionError'] = _CONNECTIONERROR +DESCRIPTOR.enum_types_by_name['StatusType'] = _STATUSTYPE +DESCRIPTOR.enum_types_by_name['ParticipantFlag'] = _PARTICIPANTFLAG -class Connected(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _CONNECTED - +Connected = _reflection.GeneratedProtocolMessageType('Connected', (_message.Message,), dict( + DESCRIPTOR = _CONNECTED, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Connected) + )) +_sym_db.RegisterMessage(Connected) -class Disconnected(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _DISCONNECTED - +Disconnected = _reflection.GeneratedProtocolMessageType('Disconnected', (_message.Message,), dict( + DESCRIPTOR = _DISCONNECTED, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Disconnected) + )) +_sym_db.RegisterMessage(Disconnected) -class Login(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _LOGIN - +Login = _reflection.GeneratedProtocolMessageType('Login', (_message.Message,), dict( + DESCRIPTOR = _LOGIN, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Login) + )) +_sym_db.RegisterMessage(Login) -class Logout(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _LOGOUT - +Logout = _reflection.GeneratedProtocolMessageType('Logout', (_message.Message,), dict( + DESCRIPTOR = _LOGOUT, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Logout) + )) +_sym_db.RegisterMessage(Logout) -class Buddy(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _BUDDY - +Buddy = _reflection.GeneratedProtocolMessageType('Buddy', (_message.Message,), dict( + DESCRIPTOR = _BUDDY, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Buddy) + )) +_sym_db.RegisterMessage(Buddy) -class ConversationMessage(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _CONVERSATIONMESSAGE - +ConversationMessage = _reflection.GeneratedProtocolMessageType('ConversationMessage', (_message.Message,), dict( + DESCRIPTOR = _CONVERSATIONMESSAGE, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.ConversationMessage) + )) +_sym_db.RegisterMessage(ConversationMessage) -class Room(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _ROOM - +Room = _reflection.GeneratedProtocolMessageType('Room', (_message.Message,), dict( + DESCRIPTOR = _ROOM, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Room) + )) +_sym_db.RegisterMessage(Room) -class RoomList(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _ROOMLIST - +RoomList = _reflection.GeneratedProtocolMessageType('RoomList', (_message.Message,), dict( + DESCRIPTOR = _ROOMLIST, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.RoomList) + )) +_sym_db.RegisterMessage(RoomList) -class Participant(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _PARTICIPANT - +Participant = _reflection.GeneratedProtocolMessageType('Participant', (_message.Message,), dict( + DESCRIPTOR = _PARTICIPANT, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Participant) + )) +_sym_db.RegisterMessage(Participant) -class VCard(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _VCARD - +VCard = _reflection.GeneratedProtocolMessageType('VCard', (_message.Message,), dict( + DESCRIPTOR = _VCARD, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.VCard) + )) +_sym_db.RegisterMessage(VCard) -class Status(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _STATUS - +Status = _reflection.GeneratedProtocolMessageType('Status', (_message.Message,), dict( + DESCRIPTOR = _STATUS, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Status) + )) +_sym_db.RegisterMessage(Status) -class Stats(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _STATS - +Stats = _reflection.GeneratedProtocolMessageType('Stats', (_message.Message,), dict( + DESCRIPTOR = _STATS, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.Stats) + )) +_sym_db.RegisterMessage(Stats) -class File(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _FILE - +File = _reflection.GeneratedProtocolMessageType('File', (_message.Message,), dict( + DESCRIPTOR = _FILE, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.File) + )) +_sym_db.RegisterMessage(File) -class FileTransferData(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _FILETRANSFERDATA - +FileTransferData = _reflection.GeneratedProtocolMessageType('FileTransferData', (_message.Message,), dict( + DESCRIPTOR = _FILETRANSFERDATA, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.FileTransferData) + )) +_sym_db.RegisterMessage(FileTransferData) -class BackendConfig(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _BACKENDCONFIG - +BackendConfig = _reflection.GeneratedProtocolMessageType('BackendConfig', (_message.Message,), dict( + DESCRIPTOR = _BACKENDCONFIG, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.BackendConfig) + )) +_sym_db.RegisterMessage(BackendConfig) -class WrapperMessage(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType - DESCRIPTOR = _WRAPPERMESSAGE - +WrapperMessage = _reflection.GeneratedProtocolMessageType('WrapperMessage', (_message.Message,), dict( + DESCRIPTOR = _WRAPPERMESSAGE, + __module__ = 'protocol_pb2' # @@protoc_insertion_point(class_scope:pbnetwork.WrapperMessage) + )) +_sym_db.RegisterMessage(WrapperMessage) + # @@protoc_insertion_point(module_scope) From ecfa2d7f858a900463aaefae973eb55ba991aadb Mon Sep 17 00:00:00 2001 From: moyamo Date: Tue, 15 Sep 2015 21:29:26 +0200 Subject: [PATCH 06/22] Attempt to fix groupchats --- Spectrum2/backend.py | 3 +- session.py | 266 ++++++++++++++++++++++++++----------------- yowsupwrapper.py | 48 +++++++- 3 files changed, 211 insertions(+), 106 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index a59567a..2ecc968 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -27,7 +27,7 @@ class SpectrumBackend: self.m_init_res = 0 self.logger = logging.getLogger(self.__class__.__name__) - def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""): + def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = "", pm = True): m = protocol_pb2.ConversationMessage() m.userName = user m.buddyName = legacyName @@ -35,6 +35,7 @@ class SpectrumBackend: m.nickname = nickname m.xhtml = xhtml m.timestamp = str(timestamp) + m.pm = pm message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE) self.send(message) diff --git a/session.py b/session.py index b86fa97..b59544a 100644 --- a/session.py +++ b/session.py @@ -47,8 +47,6 @@ class Session(YowsupApp): self.backend = backend self.user = user self.legacyName = legacyName - self.buddies = BuddyList(self.legacyName, self.db) - self.bot = Bot(self) self.status = protocol_pb2.STATUS_NONE self.statusMessage = '' @@ -56,36 +54,36 @@ class Session(YowsupApp): self.groups = {} self.presenceRequested = [] self.offlineQueue = [] + self.msgIDs = { } self.groupOfflineQueue = { } + self.shouldBeConnected = False self.timer = None self.password = None self.initialized = False - self.loggedin = False + self.synced = False + self.buddies = BuddyList(self.legacyName, self.db) self.bot = Bot(self) def __del__(self): # handleLogoutRequest self.logout() - def call(self, method, **kwargs): - self.logger.debug("%s(%s)", method, - ", ".join(str(k) + ': ' + str(v) for k, v in kwargs.items())) - ##self.stack.broadcastEvent(YowLayerEvent(method, **kwargs)) - def logout(self): - self.loggedin = False + self.logger.info("%s logged out", self.user) super(Session, self).logout() def login(self, password): - self.loggedin = True + self.logger.info("%s attempting login", self.user) self.password = password + self.shouldBeConncted = True super(Session, self).login(self.legacyName, self.password) def updateRoomList(self): rooms = [] for room, group in self.groups.iteritems(): rooms.append([room, group.subject]) + self.logger.debug("Got rooms: %s", rooms) self.backend.handleRoomList(rooms) @@ -95,6 +93,11 @@ class Session(YowsupApp): old = self.buddies.keys() self.buddies.load() new = self.buddies.keys() + contacts = new + + if self.synced == False: + self.sendSync(contacts, delta = False, interactive = True) + self.synced = True add = set(new) - set(old) remove = set(old) - set(new) @@ -103,27 +106,28 @@ class Session(YowsupApp): self.logger.debug("Roster add: %s", str(list(add))) for number in remove: - self.backend.handleBuddyChanged(self.user, number, "", [], protocol_pb2.STATUS_NONE) + self.backend.handleBuddyChanged(self.user, number, "", [], + protocol_pb2.STATUS_NONE) self.backend.handleBuddyRemoved(self.user, number) self.unsubscribePresence(number) for number in add: buddy = self.buddies[number] self.subscribePresence(number) - self.backend.handleBuddyChanged(self.user, number, buddy.nick, buddy.groups, protocol_pb2.STATUS_NONE, iconHash = buddy.image_hash if buddy.image_hash is not None else "") + self.backend.handleBuddyChanged(self.user, number, buddy.nick, + buddy.groups, protocol_pb2.STATUS_NONE, + iconHash = buddy.image_hash if buddy.image_hash is not None else "") + #self.requestLastSeen(number, self._lastSeen) - self.logger.debug('Requesting groups list') - self.requestGroupsList(self._updateGroups) - + def _updateGroups(self, response, request): self.logger.debug('Received groups list %s', response) - # This XMPP client is not receiving this for some reason. groups = response.getGroups() for group in groups: room = group.getId() - owner = group.getOwner() - subjectOwner = group.getSubjectOwner() - subject = group.getSubject() + owner = group.getOwner().split('@')[0] + subjectOwner = group.getSubjectOwner().split('@')[0] + subject = utils.softToUni(group.getSubject()) if room in self.groups: oroom = self.groups[room] @@ -132,22 +136,61 @@ class Session(YowsupApp): oroom.subject = subject else: self.groups[room] = Group(room, owner, subject, subjectOwner) - # A crude implemtation of groups that act like buddies + self.joinRoom(room, self.user.split("@")[0]) - self.backend.handleBuddyChanged(self.user, room, subject, [], protocol_pb2.STATUS_NONE) - # This XMPP client is not receiving this for some reason. -# self.updateRoomList() -# for group in groups: -# room = group.getId() -# subjectOwner = group.getSubjectOwner() -# subject = group.getSubject() -# self.backend.handleSubject(self.user, room, subject, subjectOwner) -# for participant in group.getParticipants(): -# buddy = participant.split('@')[0] -# self.logger.debug("Added %s to room %s", buddy, room) -# self.backend.handleParticipantChanged(self.user, buddy, room, -# protocol_pb2.PARTICIPANT_FLAG_NONE, protocol_pb2.STATUS_ONLINE) + self._addParticipantsToRoom(room, group.getParticipants()) + if room in self.groupOfflineQueue: + while self.groupOfflineQueue[room]: + msg = self.groupOfflineQueue[room].pop(0) + self.backend.handleMessage(self.user, room, msg[1], + msg[0], "", msg[2]) + self.logger.debug("Send queued group message to: %s %s %s", + msg[0],msg[1], msg[2]) + self.updateRoomList() + + def joinRoom(self, room, nick): + if room in self.groups: + self.logger.info("Joining room: %s room=%s, nick=%s", + self.legacyName, room, nick) + + group = self.groups[room] + group.nick = nick + try: + ownerNick = self.buddies[group.subjectOwner].nick + except KeyError: + ownerNick = group.subjectOwner + + self.backend.handleSubject(self.user, room, group.subject, + ownerNick) + self.backend.handleRoomNicknameChanged(self.user, room, + group.subject) + else: + self.logger.warn("Room doesn't exist: %s", room) + + def _addParticipantsToRoom(self, room, participants): + group = self.groups[room] + + for jid, _type in participants.iteritems(): + buddy = jid.split("@")[0] + buddyFull = buddy + self.logger.info("Added %s to room %s", buddy, room) + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + buddyFull = buddy + if _type == 'admin': + flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR + else: + flags = protocol_pb2.PARTICIPANT_FLAG_NONE + if buddy == self.legacyName: + nick = group.nick + flags = protocol_pb2.PARTICIPANT_FLAG_ME + buddyFull = self.user + + self.backend.handleParticipantChanged(self.user, buddyFull, + room, flags, protocol_pb2.STATUS_ONLINE, buddy, nick) def _lastSeen(self, number, seconds): @@ -163,23 +206,29 @@ class Session(YowsupApp): self.logger.info("Auth success: %s", self.user) self.backend.handleConnected(self.user) - self.backend.handleBuddyChanged(self.user, "bot", self.bot.name, ["Admin"], protocol_pb2.STATUS_ONLINE) - self.initialized = True + self.backend.handleBuddyChanged(self.user, "bot", self.bot.name, + ["Admin"], protocol_pb2.STATUS_ONLINE) + if self.initialized == False: + self.sendOfflineMessages() + self.bot.call("welcome") + self.initialized = True self.sendPresence(True) - self.updateRoster() + self.logger.debug('Requesting groups list') + self.requestGroupsList(self._updateGroups) + # Called by superclass def onAuthFailed(self, reason): self.logger.info("Auth failed: %s (%s)", self.user, reason) self.backend.handleDisconnected(self.user, 0, reason) self.password = None + self.shouldBeConnected = False # Called by superclass def onDisconnect(self): self.logger.debug('Disconnected') self.backend.handleDisconnected(self.user, 0, 'Disconnected for unknown reasons') - self.loggedin = False # Called by superclass def onReceipt(self, _id, _from, timestamp, type, participant, offline, items): @@ -198,8 +247,9 @@ class Session(YowsupApp): ) # Called by superclass - def onTextMessage(self, _id, _from, to, notify, timestamp, participant, offline, retry, body): - self.logger.debug('received TextMessage' + + def onTextMessage(self, _id, _from, to, notify, timestamp, participant, + offline, retry, body): + self.logger.debug('received TextMessage' + ' '.join(map(str, [ _id, _from, to, notify, timestamp, participant, offline, retry, body @@ -210,10 +260,10 @@ class Session(YowsupApp): self.sendReceipt(_id, _from, None, participant) self.logger.info("Message received from %s to %s: %s (at ts=%s)", buddy, self.legacyName, messageContent, timestamp) - if participant is not None: + if participant is not None: # Group message partname = participant.split('@')[0] - message = partname + ': ' + messageContent - self.sendMessageToXMPP(buddy, message, timestamp) + self.sendGroupMessageToXMPP(buddy, partname, messageContent, + timestamp) else: self.sendMessageToXMPP(buddy, messageContent, timestamp) # isBroadcast always returns false, I'm not sure how to get a broadcast @@ -229,7 +279,7 @@ class Session(YowsupApp): buddy = image._from.split('@')[0] message = image.url + ' ' + image.caption self.sendMessageToXMPP(buddy, message, image.timestamp) - self.sendReceipt(image._id, image._from, None, image.participant) + self.sendReceipt(image._id, image._from, None, image.participant) # Called by superclass def onAudio(self, audio): @@ -237,7 +287,7 @@ class Session(YowsupApp): buddy = audio._from.split('@')[0] message = audio.url self.sendMessageToXMPP(buddy, message, audio.timestamp) - self.sendReceipt(audio._id, audio._from, None, audio.participant) + self.sendReceipt(audio._id, audio._from, None, audio.participant) # Called by superclass def onVideo(self, video): @@ -245,21 +295,35 @@ class Session(YowsupApp): buddy = video._from.split('@')[0] message = video.url self.sendMessageToXMPP(buddy, message, video.timestamp) - self.sendReceipt(video._id, video._from, None, video.participant) + self.sendReceipt(video._id, video._from, None, video.participant) + + def onLocation(self, location): + buddy = location._from.split('@')[0] + latitude = location.getLatitude() + longitude = location.getLongitude() + url = location.getLocationUrl() + + self.logger.debug("Location received from %s: %s, %s", + buddy, latitude, longitude) + + self.sendMessageToXMPP(buddy, url, location.timestamp) + self.sendMessageToXMPP(buddy, 'geo:' + latitude + ',' + longitude, + location.timestamp) + # Called by superclass def onVCard(self, _id, _from, name, card_data, to, notify, timestamp, participant): - self.logger.debug('received VCard' + + self.logger.debug('received VCard' + ' '.join(map(str, [ _id, _from, name, card_data, to, notify, timestamp, participant ])) ) buddy = _from.split("@")[0] self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)") - self.sendMessageToXMPP(buddy, card_data) +# self.sendMessageToXMPP(buddy, card_data) self.transferFile(buddy, str(name), card_data) self.sendReceipt(_id, _from, None, participant) - + def transferFile(self, buddy, name, data): # Not working self.logger.debug('transfering file %s', name) @@ -270,17 +334,21 @@ class Session(YowsupApp): # Called by superclass def onContactTyping(self, buddy): self.logger.info("Started typing: %s", buddy) - self.sendPresence(True) - self.backend.handleBuddyTyping(self.user, buddy) + if buddy != 'bot': + self.sendPresence(True) + self.backend.handleBuddyTyping(self.user, buddy) - if self.timer != None: - self.timer.cancel() + if self.timer != None: + self.timer.cancel() # Called by superclass def onContactPaused(self, buddy): self.logger.info("Paused typing: %s", buddy) - self.backend.handleBuddyTyped(self.user, buddy) - self.timer = Timer(3, self.backend.handleBuddyStoppedTyping, (self.user, buddy)).start() + if buddy != 'bot': + self.backend.handleBuddyTyped(self.user, buddy) + self.timer = Timer(3, self.backend.handleBuddyStoppedTyping, + (self.user, buddy)).start() + def onPresenceReceived(self, _type, name, jid, lastseen): self.logger.info("Presence received: %s %s %s %s", _type, name, jid, lastseen) buddy = jid.split("@")[0] @@ -302,7 +370,8 @@ class Session(YowsupApp): try: buddy = self.buddies[buddy] self.logger.info("Is available: %s", buddy) - self.backend.handleBuddyChanged(self.user, buddy.number.number, buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + self.backend.handleBuddyChanged(self.user, buddy.number.number, + buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) except KeyError: self.logger.error("Buddy not found: %s", buddy) @@ -310,7 +379,8 @@ class Session(YowsupApp): try: buddy = self.buddies[buddy] self.logger.info("Is unavailable: %s", buddy) - self.backend.handleBuddyChanged(self.user, buddy.number.number, buddy.nick, buddy.groups, protocol_pb2.STATUS_XA) + self.backend.handleBuddyChanged(self.user, buddy.number.number, + buddy.nick, buddy.groups, protocol_pb2.STATUS_XA) except KeyError: self.logger.error("Buddy not found: %s", buddy) @@ -330,20 +400,33 @@ class Session(YowsupApp): self.sendTyping(buddy, False) def sendMessageToWA(self, sender, message): - self.logger.info("Message sent from %s to %s: %s", self.legacyName, sender, message) + self.logger.info("Message sent from %s to %s: %s", + self.legacyName, sender, message) + message = message.encode("utf-8") if sender == "bot": self.bot.parse(message) elif "-" in sender: # group msg - if "/" in sender: - room, buddy = sender.split("/") - self.sendTextMessage(buddy + '@s.whatsapp.net', message) + if "/" in sender: # directed at single user + room, nick = sender.split("/") + for buddy, buddy3 in self.buddies.iteritems(): + self.logger.info("Group buddy=%s nick=%s", buddy, + buddy3.nick) + if buddy3.nick == nick: + nick = buddy + self.sendTextMessage(nick + '@s.whatsapp.net', message) else: room = sender -# group = self.groups[room] - -# self.backend.handleMessage(self.user, room, message, group.nick) + try: + group = self.groups[room] + self.logger.info("Group Message from %s to %s Groups: %s", + group.nick , group , self.groups) + self.backend.handleMessage( + self.user, room, message.decode('utf-8'), group.nick + ) + except KeyError: + self.logger.error('Group not found: %s', room) self.sendTextMessage(room + '@g.us', message) else: # private msg @@ -368,26 +451,37 @@ class Session(YowsupApp): "", timestamp) def sendGroupMessageToXMPP(self, room, buddy, messageContent, timestamp = ""): + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + if timestamp: timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp)) if self.initialized == False: - self.logger.debug("Group message queued from %s to %s: %s", buddy, room, messageContent) + self.logger.debug("Group message queued from %s to %s: %s", + buddy, room, messageContent) if room not in self.groupOfflineQueue: self.groupOfflineQueue[room] = [ ] - self.groupOfflineQueue[room].append((buddy, messageContent, timestamp)) + self.groupOfflineQueue[room].append( + (buddy, messageContent, timestamp) + ) else: - self.logger.debug("Group message sent from %s to %s: %s", buddy, room, messageContent) - self.backend.handleMessage(self.user, room, messageContent, buddy, "", timestamp) + self.logger.debug("Group message sent from %s to %s: %s", buddy, + room, messageContent) + self.backend.handleMessage(self.user, room, messageContent, nick, + "", timestamp, False) def changeStatus(self, status): if status != self.status: self.logger.info("Status changed: %s", status) self.status = status - if status == protocol_pb2.STATUS_ONLINE or status == protocol_pb2.STATUS_FFC: + if status == protocol_pb2.STATUS_ONLINE \ + or status == protocol_pb2.STATUS_FFC: self.sendPresence(True) else: self.sendPresence(False) @@ -421,21 +515,8 @@ class Session(YowsupApp): self.buddies.remove(buddy) self.updateRoster() - def joinRoom(self, room, nick): - if room in self.groups: - group = self.groups[room] - self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick) - - group.nick = nick - - self.call("group_getParticipants", (room + "@g.us",)) - self.backend.handleSubject(self.user, room, group.subject, group.subjectOwner) - else: - self.logger.warn("Room doesn't exist: %s", room) - def requestVCard(self, buddy, ID): - def onSuccess(response, request): self.logger.debug('Sending VCard (%s) with image id %s', ID, response.pictureId) @@ -458,32 +539,11 @@ class Session(YowsupApp): if receiptRequested: self.call("message_ack", (jid, messageId)) - def onGroupGotParticipants(self, gjid, jids): - room = gjid.split("@")[0] - group = self.groups[room] - - for jid in jids: - buddy = jid.split("@")[0] - self.logger.info("Added %s to room %s", buddy, room) - - if buddy == group.owner: - flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR - else: - flags = protocol_pb2.PARTICIPANT_FLAG_NONE - - self.backend.handleParticipantChanged(self.user, buddy, room, flags, protocol_pb2.STATUS_ONLINE) # TODO check status - - if room in self.groupOfflineQueue: - while self.groupOfflineQueue[room]: - msg = self.groupOfflineQueue[room].pop(0) - self.backend.handleMessage(self.user, room, msg[1], msg[0], "", msg[2]) - self.logger.debug("Send queued group message to: %s %s %s", msg[0],msg[1], msg[2]) - def onGroupMessageReceived(self, messageId, gjid, jid, messageContent, timestamp, receiptRequested, pushName): buddy = jid.split("@")[0] room = gjid.split("@")[0] - self.logger.info("Group message received in %s from %s: %s", room, buddy, messageContent) + self.logger.info("Group message received in %s from %s: %s", room, buddy, messageContent) self.sendGroupMessageToXMPP(room, buddy, utils.softToUni(messageContent), timestamp) if receiptRequested: self.call("message_ack", (gjid, messageId)) diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 8058b10..2a8349b 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -30,6 +30,7 @@ from yowsup.layers.protocol_calls import YowCallsProtocolLayer from yowsup.layers.protocol_acks.protocolentities import * from yowsup.layers.protocol_chatstate.protocolentities import * +from yowsup.layers.protocol_contacts.protocolentities import * from yowsup.layers.protocol_groups.protocolentities import * from yowsup.layers.protocol_media.protocolentities import * from yowsup.layers.protocol_messages.protocolentities import * @@ -197,6 +198,26 @@ class YowsupApp(object): ) self.sendEntity(state) + def sendSync(self, contacts, delta = False, interactive = True): + """ + You need to sync new contacts before you interact with + them, failure to do so could result in a temporary ban. + + Args: + - contacts: ([str]) a list of phone numbers of the + contacts you wish to sync + - delta: (bool; default: False) If true only send new + contacts to sync, if false you should send your full + contact list. + - interactive: (bool; default: True) Set to false if you are + sure this is the first time registering + """ + # TODO: Implement callbacks + mode = GetSyncIqProtocolEntity.MODE_DELTA if delta else GetSyncIqProtocolEntity.MODE_FULL + context = GetSyncIqProtocolEntity.CONTEXT_INTERACTIVE if interactive else GetSyncIqProtocolEntity.CONTEXT_REGISTRATION + iq = GetSyncIqProtocolEntity(contacts, mode, context) + self.sendIq(iq) + def requestLastSeen(self, phoneNumber, success = None, failure = None): """ Requests when user was last seen. @@ -219,8 +240,8 @@ class YowsupApp(object): Requests profile picture of whatsapp user Args: - phoneNumber: (str) the phone number of the user - - success: (func) called when request is successfully processed. - - failure: (func) called when request has failed + - onSuccess: (func) called when request is successfully processed. + - onFailure: (func) called when request has failed """ iq = GetPictureIqProtocolEntity(phoneNumber + '@s.whatsapp.net') self.sendIq(iq, onSuccess = onSuccess, onError = onFailure) @@ -229,6 +250,18 @@ class YowsupApp(object): iq = ListGroupsIqProtocolEntity() self.sendIq(iq, onSuccess = onSuccess, onError = onFailure) + def requestGroupInfo(self, group, onSuccess = None, onFailure = None): + """ + Request info on a specific group (includes participants, subject, owner etc.) + + Args: + - group: (str) the group id in the form of xxxxxxxxx-xxxxxxxx + - onSuccess: (func) called when request is successfully processed. + - onFailure: (func) called when request is has failed + """ + iq = InfoGroupsIqProtocolEntity(group + '@g.us') + self.sendIq(iq, onSuccess = onSuccess, onError = onFailure) + def onAuthSuccess(self, status, kind, creation, expiration, props, nonce, t): """ Called when login is successful. @@ -361,6 +394,15 @@ class YowsupApp(object): - entity: VideoDownloadableMediaMessageProtocolEntity """ pass + + def onLocation(self, entity): + """ + Called when location message is received + + Args: + - entity: LocationMediaMessageProtocolEntity + """ + pass def onVCard(self, _id, _from, name, card_data, to, notify, timestamp, participant): """ @@ -508,6 +550,8 @@ class YowsupAppLayer(YowInterfaceLayer): entity.timestamp, entity.participant ) + elif isinstance(entity, LocationMediaMessageProtocolEntity): + self.caller.onLocation(entity) @ProtocolEntityCallback('presence') def onPresenceReceived(self, presence): From 29d92b456ed270c5eb80606e7cabba3d3526f57c Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 21 Sep 2015 20:30:11 +0200 Subject: [PATCH 07/22] Shorten the name of groupchats to overcome truncation bug The names of groupchats are truncated internally to 22 characters. This causes many problems with groupchats, since spectrum incorrectly identifies the chat by the long name. To overcome this the phoneNumber-unixTime is converted to hexadecimal, to shorten the groupchat below 22 characters --- Spectrum2/backend.py | 3 +- buddy.py | 4 +-- session.py | 77 +++++++++++++++++++++++++++++++------------- whatsappbackend.py | 2 ++ 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index 2ecc968..a59567a 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -27,7 +27,7 @@ class SpectrumBackend: self.m_init_res = 0 self.logger = logging.getLogger(self.__class__.__name__) - def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = "", pm = True): + def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""): m = protocol_pb2.ConversationMessage() m.userName = user m.buddyName = legacyName @@ -35,7 +35,6 @@ class SpectrumBackend: m.nickname = nickname m.xhtml = xhtml m.timestamp = str(timestamp) - m.pm = pm message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE) self.send(message) diff --git a/buddy.py b/buddy.py index 1ab9944..e07ec46 100644 --- a/buddy.py +++ b/buddy.py @@ -23,7 +23,6 @@ __status__ = "Prototype" """ from Spectrum2 import protocol_pb2 -from Yowsup.Contacts.contacts import WAContactsSyncRequest import logging @@ -61,7 +60,8 @@ class Buddy(): def update(self, nick, groups, image_hash): self.nick = nick self.groups = groups - self.image_hash = image_hash + if image_hash is not None: + self.image_hash = image_hash groups = u",".join(groups).encode("latin-1") cur = self.db.cursor() diff --git a/session.py b/session.py index b59544a..d65361f 100644 --- a/session.py +++ b/session.py @@ -79,10 +79,18 @@ class Session(YowsupApp): self.shouldBeConncted = True super(Session, self).login(self.legacyName, self.password) + def _shortenGroupId(self, gid): + # FIXME: will have problems if number begins with 0 + return '-'.join(hex(int(s))[2:] for s in gid.split('-')) + + def _lengthenGroupId(self, gid): + # FIXME: will have problems if number begins with 0 + return '-'.join(str(int(s, 16)) for s in gid.split('-')) + def updateRoomList(self): rooms = [] for room, group in self.groups.iteritems(): - rooms.append([room, group.subject]) + rooms.append([self._shortenGroupId(room), group.subject]) self.logger.debug("Got rooms: %s", rooms) self.backend.handleRoomList(rooms) @@ -136,7 +144,7 @@ class Session(YowsupApp): oroom.subject = subject else: self.groups[room] = Group(room, owner, subject, subjectOwner) - self.joinRoom(room, self.user.split("@")[0]) + self.joinRoom(self._shortenGroupId(room), self.user.split("@")[0]) self._addParticipantsToRoom(room, group.getParticipants()) @@ -150,6 +158,7 @@ class Session(YowsupApp): self.updateRoomList() def joinRoom(self, room, nick): + room = self._lengthenGroupId(room) if room in self.groups: self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick) @@ -165,11 +174,38 @@ class Session(YowsupApp): ownerNick) self.backend.handleRoomNicknameChanged(self.user, room, group.subject) + self._refreshParticipants(room) else: self.logger.warn("Room doesn't exist: %s", room) + def _refreshParticipants(self, room): + group = self.groups[room] + for jid in group.participants: + buddy = jid.split("@")[0] + self.logger.info("Added %s to room %s", buddy, room) + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + if nick == "": + nick = buddy + + buddyFull = buddy + if buddy == group.owner: + flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR + else: + flags = protocol_pb2.PARTICIPANT_FLAG_NONE + if buddy == self.legacyName: + nick = group.nick + flags = flags | protocol_pb2.PARTICIPANT_FLAG_ME + buddyFull = self.user + self.backend.handleParticipantChanged( + self.user, buddyFull, self._shortenGroupId(room), flags, + protocol_pb2.STATUS_ONLINE, buddy, nick) + def _addParticipantsToRoom(self, room, participants): group = self.groups[room] + group.participants = participants for jid, _type in participants.iteritems(): buddy = jid.split("@")[0] @@ -190,7 +226,7 @@ class Session(YowsupApp): buddyFull = self.user self.backend.handleParticipantChanged(self.user, buddyFull, - room, flags, protocol_pb2.STATUS_ONLINE, buddy, nick) + self._shortenGroupId(room), flags, protocol_pb2.STATUS_ONLINE, buddy, nick) def _lastSeen(self, number, seconds): @@ -224,7 +260,7 @@ class Session(YowsupApp): self.backend.handleDisconnected(self.user, 0, reason) self.password = None self.shouldBeConnected = False - + # Called by superclass def onDisconnect(self): self.logger.debug('Disconnected') @@ -236,9 +272,12 @@ class Session(YowsupApp): ' '.join(map(str, [_id, _from, timestamp, type, participant, offline, items])) ) - buddy = self.buddies[_from.split('@')[0]] - self.backend.handleBuddyChanged(self.user, buddy.number.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + try: + buddy = self.buddies[_from.split('@')[0]] + self.backend.handleBuddyChanged(self.user, buddy.number.number, + buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + except KeyError: + pass # Called by superclass def onAck(self, _id, _class, _from, timestamp): @@ -427,7 +466,7 @@ class Session(YowsupApp): ) except KeyError: self.logger.error('Group not found: %s', room) - self.sendTextMessage(room + '@g.us', message) + self.sendTextMessage(self._lengthenGroupId(room) + '@g.us', message) else: # private msg buddy = sender @@ -451,10 +490,13 @@ class Session(YowsupApp): "", timestamp) def sendGroupMessageToXMPP(self, room, buddy, messageContent, timestamp = ""): + self._refreshParticipants(room) try: nick = self.buddies[buddy].nick except KeyError: nick = buddy + if nick == "": + nick = buddy if timestamp: timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime(timestamp)) @@ -470,10 +512,10 @@ class Session(YowsupApp): (buddy, messageContent, timestamp) ) else: - self.logger.debug("Group message sent from %s to %s: %s", buddy, - room, messageContent) - self.backend.handleMessage(self.user, room, messageContent, nick, - "", timestamp, False) + self.logger.debug("Group message sent from %s (%s) to %s: %s", + buddy, nick, room, messageContent) + self.backend.handleMessage(self.user, self._shortenGroupId(room), + messageContent, nick, "", timestamp) def changeStatus(self, status): if status != self.status: @@ -504,7 +546,7 @@ class Session(YowsupApp): self.backend.handleMessage(self.user, msg[0], msg[1], "", "", msg[2]) # also for adding a new buddy - def updateBuddy(self, buddy, nick, groups, image_hash =""): + def updateBuddy(self, buddy, nick, groups, image_hash = None): if buddy != "bot": self.buddies.update(buddy, nick, groups, image_hash) self.updateRoster() @@ -539,15 +581,6 @@ class Session(YowsupApp): if receiptRequested: self.call("message_ack", (jid, messageId)) - def onGroupMessageReceived(self, messageId, gjid, jid, messageContent, timestamp, receiptRequested, pushName): - buddy = jid.split("@")[0] - room = gjid.split("@")[0] - - self.logger.info("Group message received in %s from %s: %s", room, buddy, messageContent) - - self.sendGroupMessageToXMPP(room, buddy, utils.softToUni(messageContent), timestamp) - if receiptRequested: self.call("message_ack", (gjid, messageId)) - def onGroupSubjectReceived(self, messageId, gjid, jid, subject, timestamp, receiptRequested): room = gjid.split("@")[0] buddy = jid.split("@")[0] diff --git a/whatsappbackend.py b/whatsappbackend.py index b7b9827..b973f76 100644 --- a/whatsappbackend.py +++ b/whatsappbackend.py @@ -67,6 +67,7 @@ class WhatsAppBackend(SpectrumBackend): # # TODO Proper fix, this work around drops all duplicate messages even # intentional ones. + # IDEA there is an ID field in ConvMessage. If it is extracted it will work usersMessage = self.lastMessage[user] if buddy not in usersMessage or usersMessage[buddy] != message: self.sessions[user].sendMessageToWA(buddy, message) @@ -105,6 +106,7 @@ class WhatsAppBackend(SpectrumBackend): self.logger.debug("handleVCardRequest(user=%s, buddy=%s, ID=%s)", user, buddy, ID) self.sessions[user].requestVCard(buddy, ID) + # TODO def handleBuddyBlockToggled(self, user, buddy, blocked): pass From a5877bc1a9e698cad6a96c078a565e1bb8201078 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 21 Sep 2015 21:45:18 +0200 Subject: [PATCH 08/22] Try to prevent transwhat from crashing on malformed protobuf --- Spectrum2/backend.py | 1 - session.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index a59567a..a4bdd50 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -4,7 +4,6 @@ import struct import sys import os import logging - import google.protobuf def WRAP(MESSAGE, TYPE): diff --git a/session.py b/session.py index d65361f..bdd9144 100644 --- a/session.py +++ b/session.py @@ -458,7 +458,7 @@ class Session(YowsupApp): else: room = sender try: - group = self.groups[room] + group = self.groups[self._lengthenGroupId(room)] self.logger.info("Group Message from %s to %s Groups: %s", group.nick , group , self.groups) self.backend.handleMessage( From 744efd154ff80131ba3d5a80c17f362e9dc5398e Mon Sep 17 00:00:00 2001 From: moyamo Date: Tue, 22 Sep 2015 16:14:25 +0200 Subject: [PATCH 09/22] Use notify as buddies nickname when sending groupchats. --- session.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/session.py b/session.py index bdd9144..7193be3 100644 --- a/session.py +++ b/session.py @@ -54,7 +54,6 @@ class Session(YowsupApp): self.groups = {} self.presenceRequested = [] self.offlineQueue = [] - self.msgIDs = { } self.groupOfflineQueue = { } self.shouldBeConnected = False @@ -170,10 +169,12 @@ class Session(YowsupApp): except KeyError: ownerNick = group.subjectOwner - self.backend.handleSubject(self.user, room, group.subject, + self.backend.handleSubject(self.user, self._shortenGroupId(room), + group.subject, ownerNick) - self.backend.handleRoomNicknameChanged(self.user, room, - group.subject) + self.backend.handleRoomNicknameChanged( + self.user, self._shortenGroupId(room), group.subject + ) self._refreshParticipants(room) else: self.logger.warn("Room doesn't exist: %s", room) @@ -225,8 +226,10 @@ class Session(YowsupApp): flags = protocol_pb2.PARTICIPANT_FLAG_ME buddyFull = self.user - self.backend.handleParticipantChanged(self.user, buddyFull, - self._shortenGroupId(room), flags, protocol_pb2.STATUS_ONLINE, buddy, nick) + self.backend.handleParticipantChanged( + self.user, buddyFull, self._shortenGroupId(room), flags, + protocol_pb2.STATUS_ONLINE, buddy, nick + ) def _lastSeen(self, number, seconds): @@ -296,11 +299,22 @@ class Session(YowsupApp): ) buddy = _from.split('@')[0] messageContent = utils.softToUni(body) - self.sendReceipt(_id, _from, None, participant) + self.sendReceipt(_id, _from, None, participant) self.logger.info("Message received from %s to %s: %s (at ts=%s)", buddy, self.legacyName, messageContent, timestamp) if participant is not None: # Group message partname = participant.split('@')[0] + try: + part = self.buddies[partname] + if part.nick == "": + part.nick = notify + self.backend.handleParticipantChanged( + self.user, partname, buddy, + protocol_pb2.PARTICIPANT_FLAG_NONE, + protocol_pb2.STATUS_NONE, "", part.nick + ) # TODO + except KeyError: + self.updateBuddy(partname, notify, []) self.sendGroupMessageToXMPP(buddy, partname, messageContent, timestamp) else: From 1c0ae79ec2b5308595b15cefde137ea0024375f2 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 26 Oct 2015 18:47:17 +0200 Subject: [PATCH 10/22] Fix join room, inform user of all groups, and new participants In the previous implementation join_room was called on all groups immediately after the user was authenticated. When a user joined a group, join_room will be called again. This was incorrect behaviour and confused spectrum. There was no truncation error, thus _shortenGroupId and _lengthenGroupId have edited to be a no-op (and should be removed in the next commit). The correct behavoiur is to only call join_room in whatsappbackend.py:handleRoomJoined, however the user may do this before the groups have been loaded, in which case those requests must be added to a queue. The bot informs the user of all the groups the user has joined and when the user is added to a new group. --- session.py | 100 +++++++++++++++++++++++++-------------------- transwhat.py | 2 +- whatsappbackend.py | 3 +- yowsupwrapper.py | 37 ++++++++++++----- 4 files changed, 85 insertions(+), 57 deletions(-) diff --git a/session.py b/session.py index 7193be3..a8a4bbd 100644 --- a/session.py +++ b/session.py @@ -52,6 +52,8 @@ class Session(YowsupApp): self.statusMessage = '' self.groups = {} + self.gotGroupList = False + self.joinRoomQueue = [] self.presenceRequested = [] self.offlineQueue = [] self.groupOfflineQueue = { } @@ -79,20 +81,27 @@ class Session(YowsupApp): super(Session, self).login(self.legacyName, self.password) def _shortenGroupId(self, gid): - # FIXME: will have problems if number begins with 0 - return '-'.join(hex(int(s))[2:] for s in gid.split('-')) - + # FIXME: might have problems if number begins with 0 + return gid +# return '-'.join(hex(int(s))[2:] for s in gid.split('-')) + def _lengthenGroupId(self, gid): - # FIXME: will have problems if number begins with 0 - return '-'.join(str(int(s, 16)) for s in gid.split('-')) + return gid + # FIXME: might have problems if number begins with 0 +# return '-'.join(str(int(s, 16)) for s in gid.split('-')) def updateRoomList(self): rooms = [] + text = [] for room, group in self.groups.iteritems(): rooms.append([self._shortenGroupId(room), group.subject]) + text.append(self._shortenGroupId(room) + '@' + self.backend.spectrum_jid + ' :' + group.subject) self.logger.debug("Got rooms: %s", rooms) self.backend.handleRoomList(rooms) + message = "Note, you are a participant of the following groups:\n" +\ + '\n'.join(text) + '\nIf you do not join them you will lose messages' + self.bot.send(message) def updateRoster(self): self.logger.debug("Update roster") @@ -143,9 +152,10 @@ class Session(YowsupApp): oroom.subject = subject else: self.groups[room] = Group(room, owner, subject, subjectOwner) - self.joinRoom(self._shortenGroupId(room), self.user.split("@")[0]) +# self.joinRoom(self._shortenGroupId(room), self.user.split("@")[0]) + self.groups[room].participants = group.getParticipants().keys() - self._addParticipantsToRoom(room, group.getParticipants()) + #self._addParticipantsToRoom(room, group.getParticipants()) if room in self.groupOfflineQueue: while self.groupOfflineQueue[room]: @@ -154,9 +164,16 @@ class Session(YowsupApp): msg[0], "", msg[2]) self.logger.debug("Send queued group message to: %s %s %s", msg[0],msg[1], msg[2]) + self.gotGroupList = True + for room, nick in self.joinRoomQueue: + self.joinRoom(room, nick) + self.joinRoomQueue = [] self.updateRoomList() def joinRoom(self, room, nick): + if not self.gotGroupList: + self.joinRoomQueue.append((room, nick)) + return room = self._lengthenGroupId(room) if room in self.groups: self.logger.info("Joining room: %s room=%s, nick=%s", @@ -169,13 +186,14 @@ class Session(YowsupApp): except KeyError: ownerNick = group.subjectOwner + self._refreshParticipants(room) self.backend.handleSubject(self.user, self._shortenGroupId(room), - group.subject, - ownerNick) + group.subject) + self.logger.debug("Room subject: room=%s, subject=%s", + room, group.subject) self.backend.handleRoomNicknameChanged( self.user, self._shortenGroupId(room), group.subject ) - self._refreshParticipants(room) else: self.logger.warn("Room doesn't exist: %s", room) @@ -191,7 +209,6 @@ class Session(YowsupApp): if nick == "": nick = buddy - buddyFull = buddy if buddy == group.owner: flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR else: @@ -199,38 +216,9 @@ class Session(YowsupApp): if buddy == self.legacyName: nick = group.nick flags = flags | protocol_pb2.PARTICIPANT_FLAG_ME - buddyFull = self.user self.backend.handleParticipantChanged( - self.user, buddyFull, self._shortenGroupId(room), flags, - protocol_pb2.STATUS_ONLINE, buddy, nick) - - def _addParticipantsToRoom(self, room, participants): - group = self.groups[room] - group.participants = participants - - for jid, _type in participants.iteritems(): - buddy = jid.split("@")[0] - buddyFull = buddy - self.logger.info("Added %s to room %s", buddy, room) - try: - nick = self.buddies[buddy].nick - except KeyError: - nick = buddy - buddyFull = buddy - if _type == 'admin': - flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR - else: - flags = protocol_pb2.PARTICIPANT_FLAG_NONE - if buddy == self.legacyName: - nick = group.nick - flags = protocol_pb2.PARTICIPANT_FLAG_ME - buddyFull = self.user - - self.backend.handleParticipantChanged( - self.user, buddyFull, self._shortenGroupId(room), flags, - protocol_pb2.STATUS_ONLINE, buddy, nick - ) - + self.user, nick, self._shortenGroupId(room), flags, + protocol_pb2.STATUS_ONLINE, buddy) def _lastSeen(self, number, seconds): self.logger.debug("Last seen %s at %s seconds" % (number, str(seconds))) @@ -309,9 +297,9 @@ class Session(YowsupApp): if part.nick == "": part.nick = notify self.backend.handleParticipantChanged( - self.user, partname, buddy, + self.user, partname, self._shortenGroupId(buddy), protocol_pb2.PARTICIPANT_FLAG_NONE, - protocol_pb2.STATUS_NONE, "", part.nick + protocol_pb2.STATUS_ONLINE, "", part.nick ) # TODO except KeyError: self.updateBuddy(partname, notify, []) @@ -402,6 +390,28 @@ class Session(YowsupApp): self.timer = Timer(3, self.backend.handleBuddyStoppedTyping, (self.user, buddy)).start() + # Called by superclass + def onAddedToGroup(self, group): + self.logger.debug("Added to group: %s", group) + room = group.getGroupId() + owner = group.getCreatorJid(full = False) + subjectOwner = group.getSubjectOwnerJid(full = False) + subject = utils.softToUni(group.getSubject()) + + self.groups[room] = Group(room, owner, subject, subjectOwner) + self.groups[room].participants = group.getParticipants().keys() +# self.joinRoom(self._shortenGroupId(room), self.user.split("@")[0]) + + #self._addParticipantsToRoom(room, group.getParticipants()) + self.bot.send("You have been added to group: %s@%s (%s)" + % (self._shortenGroupId(room), subject, self.backend.spectrum_jid)) + + def onParticipantsAddedToGroup(self, group): + self.logger.debug("Participants added to group: %s", group) + room = group.getGroupId().split('@')[0] + self.groups[room].participants.extend(group.getParticipants()) + self._refreshParticipants(room) + def onPresenceReceived(self, _type, name, jid, lastseen): self.logger.info("Presence received: %s %s %s %s", _type, name, jid, lastseen) buddy = jid.split("@")[0] @@ -504,7 +514,7 @@ class Session(YowsupApp): "", timestamp) def sendGroupMessageToXMPP(self, room, buddy, messageContent, timestamp = ""): - self._refreshParticipants(room) + # self._refreshParticipants(room) try: nick = self.buddies[buddy].nick except KeyError: diff --git a/transwhat.py b/transwhat.py index 84abc31..5875dc4 100755 --- a/transwhat.py +++ b/transwhat.py @@ -78,7 +78,7 @@ def connectionClosed(): db = MySQLdb.connect(DB_HOST, DB_USER, DB_PASS, DB_TABLE) io = IOChannel(args.host, args.port, handleTransportData, connectionClosed) -plugin = WhatsAppBackend(io, db) +plugin = WhatsAppBackend(io, db, args.j) while True: try: diff --git a/whatsappbackend.py b/whatsappbackend.py index b973f76..c645330 100644 --- a/whatsappbackend.py +++ b/whatsappbackend.py @@ -30,12 +30,13 @@ from session import Session import logging class WhatsAppBackend(SpectrumBackend): - def __init__(self, io, db): + def __init__(self, io, db, spectrum_jid): SpectrumBackend.__init__(self) self.logger = logging.getLogger(self.__class__.__name__) self.io = io self.db = db self.sessions = { } + self.spectrum_jid = spectrum_jid # Used to prevent duplicate messages self.lastMessage = {} diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 2a8349b..7ed3d4a 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -1,3 +1,5 @@ +import logging + from yowsup import env from yowsup.stacks import YowStack from yowsup.common import YowConstants @@ -67,6 +69,7 @@ class YowsupApp(object): YowStanzaRegulator, YowNetworkLayer ) + self.logger = logging.getLogger(self.__class__.__name__) self.stack = YowStack(layers) self.stack.broadcastEvent( YowLayerEvent(YowsupAppLayer.EVENT_START, caller = self) @@ -108,7 +111,7 @@ class YowsupApp(object): Logout from whatsapp """ self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_DISCONNECT)) - + def sendReceipt(self, _id, _from, read, participant): """ Send a receipt (delivered: double-tick, read: blue-ticks) @@ -168,7 +171,7 @@ class YowsupApp(object): jid = phone_number + '@s.whatsapp.net' entity = UnsubscribePresenceProtocolEntity(jid) self.sendEntity(entity) - + def setStatus(self, statusText): """ Send status to whatsapp @@ -313,7 +316,7 @@ class YowsupApp(object): - timestamp """ pass - + def onPresenceReceived(self, _type, name, _from, last): """ Called when presence (e.g. available, unavailable) is received @@ -331,7 +334,7 @@ class YowsupApp(object): """ Called when disconnected from whatsapp """ - + def onContactTyping(self, number): """ Called when contact starts to type @@ -366,7 +369,7 @@ class YowsupApp(object): - body: The content of the message """ pass - + def onImage(self, entity): """ Called when image message is received @@ -384,7 +387,7 @@ class YowsupApp(object): - entity: AudioDownloadableMediaMessageProtocolEntity """ pass - + def onVideo(self, entity): """ @@ -403,7 +406,7 @@ class YowsupApp(object): - entity: LocationMediaMessageProtocolEntity """ pass - + def onVCard(self, _id, _from, name, card_data, to, notify, timestamp, participant): """ Called when VCard message is received @@ -420,12 +423,20 @@ class YowsupApp(object): """ pass + def onAddedToGroup(self, entity): + """Called when the user has been added to a new group""" + pass + + def onParticipantsAddedToGroup(self, entity): + """Called when participants have been added to a group""" + pass + def sendEntity(self, entity): """Sends an entity down the stack (as if YowsupAppLayer called toLower)""" self.stack.broadcastEvent(YowLayerEvent(YowsupAppLayer.TO_LOWER_EVENT, entity = entity )) - + def sendIq(self, iq, onSuccess = None, onError = None): self.stack.broadcastEvent( YowLayerEvent( @@ -450,6 +461,7 @@ class YowsupAppLayer(YowInterfaceLayer): # return True otherwise if layerEvent.getName() == YowsupAppLayer.EVENT_START: self.caller = layerEvent.getArg('caller') + self.logger = logging.getLogger(self.__class__.__name__) return True elif layerEvent.getName() == YowNetworkLayer.EVENT_STATE_DISCONNECTED: self.caller.onDisconnect() @@ -514,8 +526,13 @@ class YowsupAppLayer(YowInterfaceLayer): """ Sends ack automatically """ + self.logger.debug("Received notification: %s", entity) self.toLower(entity.ack()) - + if isinstance(entity, CreateGroupsNotificationProtocolEntity): + self.caller.onAddedToGroup(entity) + elif isinstance(entity, AddGroupsNotificationProtocolEntity): + self.caller.onParticipantsAddedToGroup(entity) + @ProtocolEntityCallback('message') def onMessageReceived(self, entity): if entity.getType() == MessageProtocolEntity.MESSAGE_TYPE_TEXT: @@ -560,7 +577,7 @@ class YowsupAppLayer(YowInterfaceLayer): _from = presence.getFrom() last = presence.getLast() self.caller.onPresenceReceived(_type, name, _from, last) - + @ProtocolEntityCallback('chatstate') def onChatstate(self, chatstate): number = chatstate._from.split('@')[0] From dbb66e03815bcf36afc6da1fc73125f11635b066 Mon Sep 17 00:00:00 2001 From: moyamo Date: Thu, 5 Nov 2015 17:57:16 +0200 Subject: [PATCH 11/22] Prevent no caption in an image from crashing transwhat --- Spectrum2/backend.py | 2 +- session.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index a4bdd50..c09ed33 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -7,7 +7,7 @@ import logging import google.protobuf def WRAP(MESSAGE, TYPE): - wrap = protocol_pb2.WrapperMessage() + wrap = protocol_pb2.WrapperMessage() wrap.type = TYPE wrap.payload = MESSAGE return wrap.SerializeToString() diff --git a/session.py b/session.py index a8a4bbd..d03eaaa 100644 --- a/session.py +++ b/session.py @@ -318,6 +318,8 @@ class Session(YowsupApp): def onImage(self, image): self.logger.debug('Received image message %s', str(image)) buddy = image._from.split('@')[0] + if image.caption is None: + image.caption = '' message = image.url + ' ' + image.caption self.sendMessageToXMPP(buddy, message, image.timestamp) self.sendReceipt(image._id, image._from, None, image.participant) From 98b9487c7f0ff932af7c04131643f1d321f481d2 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 9 Nov 2015 23:09:12 +0100 Subject: [PATCH 12/22] send imgaes, locations, ... fix presence --- Spectrum2/backend.py | 65 ++++++++-- bot.py | 84 ++++++++++++- buddy.py | 22 +++- session.py | 285 +++++++++++++++++++++++++++++++++++++------ whatsappbackend.py | 7 +- yowsupwrapper.py | 61 +++++++++ 6 files changed, 470 insertions(+), 54 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index 342f0e4..ec04767 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -3,7 +3,6 @@ import socket import struct import sys import os - import logging import google.protobuf @@ -20,13 +19,13 @@ class SpectrumBackend: @param host: Host where Spectrum2 NetworkPluginServer runs. @param port: Port. """ - def __init__(self): self.m_pingReceived = False self.m_data = "" self.m_init_res = 0 self.logger = logging.getLogger(self.__class__.__name__) + def handleMessage(self, user, legacyName, msg, nickname = "", xhtml = "", timestamp = ""): m = protocol_pb2.ConversationMessage() m.userName = user @@ -39,6 +38,17 @@ class SpectrumBackend: message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE) self.send(message) + def handleMessageAck(self, user, legacyName, ID): + m = protocol_pb2.ConversationMessage() + m.userName = user + m.buddyName = legacyName + m.message = "" + m.id = ID + + message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE_ACK) + self.send(message) + + def handleAttention(self, user, buddyName, msg): m = protocol_pb2.ConversationMessage() m.userName = user @@ -206,7 +216,7 @@ class SpectrumBackend: def handleFTData(self, ftID, data): d = protocol_pb2.FileTransferData() - d.ftID = ftID + d.ftid = ftID d.data = data message = WRAP(d.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_FT_DATA); @@ -242,10 +252,20 @@ class SpectrumBackend: def handleConvMessagePayload(self, data): payload = protocol_pb2.ConversationMessage() + self.logger.error("handleConvMessagePayload") if (payload.ParseFromString(data) == False): #TODO: ERROR return - self.handleMessageSendRequest(payload.userName, payload.buddyName, payload.message, payload.xhtml) + self.handleMessageSendRequest(payload.userName, payload.buddyName, payload.message, payload.xhtml, payload.id) + + def handleConvMessageAckPayload(self, data): + payload = protocol_pb2.ConversationMessage() + if (payload.ParseFromString(data) == False): + #TODO: ERROR + return + self.handleMessageAckRequest(payload.userName, payload.buddyName, payload.id) + + def handleAttentionPayload(self, data): payload = protocol_pb2.ConversationMessage() @@ -345,24 +365,30 @@ class SpectrumBackend: if (len(self.m_data) >= 4): expected_size = struct.unpack('!I', self.m_data[0:4])[0] if (len(self.m_data) - 4 < expected_size): + self.logger.error("Expected Data Size Error") return else: + self.logger.error("Data too small") return wrapper = protocol_pb2.WrapperMessage() - try: - parseFromString = wrapper.ParseFromString(self.m_data[4:]) - except: - parseFromString = True - self.logger.error("Parse from String exception") + try: + parseFromString = wrapper.ParseFromString(self.m_data[4:]) + except: + parseFromString = True + self.logger.error("Parse from String exception") - if parseFromString == False: + + if (parseFromString == False): self.m_data = self.m_data[expected_size+4:] - self.logger.error("Parse from String exception") + self.logger.error("Parse from String error") return + self.m_data = self.m_data[4+expected_size:] + #self.logger.error("Data Type: %s",wrapper.type) + if wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGIN: self.handleLoginPayload(wrapper.payload) @@ -402,6 +428,8 @@ class SpectrumBackend: self.handleFTContinuePayload(wrapper.payload) elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_EXIT: self.handleExitRequest() + elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE_ACK: + self.handleConvMessageAckPayload(wrapper.payload) elif wrapper.type == protocol_pb2.WrapperMessage.TYPE_RAW_XML: self.handleRawXmlRequest(wrapper.payload) @@ -474,17 +502,30 @@ class SpectrumBackend: raise NotImplementedError, "Implement me" - def handleMessageSendRequest(self, user, legacyName, message, xhtml = ""): + def handleMessageSendRequest(self, user, legacyName, message, xhtml = "", ID = 0): """ Called when XMPP user sends message to legacy network. @param user: XMPP JID of user for which this event occurs. @param legacyName: Legacy network name of buddy or room. @param message: Plain text message. @param xhtml: XHTML message. + @param ID: message ID """ raise NotImplementedError, "Implement me" + def handleMessageAckRequest(self, user, legacyName, ID = 0): + """ + Called when XMPP user sends message to legacy network. + @param user: XMPP JID of user for which this event occurs. + @param legacyName: Legacy network name of buddy or room. + @param ID: message ID + """ + + # raise NotImplementedError, "Implement me" + pass + + def handleVCardRequest(self, user, legacyName, ID): """ Called when XMPP user requests VCard of buddy. @param user: XMPP JID of user for which this event occurs. diff --git a/bot.py b/bot.py index aa9bd35..469dd78 100644 --- a/bot.py +++ b/bot.py @@ -31,20 +31,26 @@ import os import utils from constants import * +#from googleclient import GoogleClient -from Yowsup.Contacts.contacts import WAContactsSyncRequest +#from Yowsup.Contacts.contacts import WAContactsSyncRequest class Bot(): def __init__(self, session, name = "Bot"): self.session = session self.name = name + #self.google = GoogleClient() + self.commands = { + "import": self._import, "help": self._help, "prune": self._prune, "welcome": self._welcome, "fortune": self._fortune, - "sync": self._sync + "sync": self._sync, + "groups": self._groups, + "getgroups": self._getgroups } def parse(self, message): @@ -75,6 +81,41 @@ class Bot(): def send(self, message): self.session.backend.handleMessage(self.session.user, self.name, message) + def __do_import(self, token): + # Google + google = self.google.getContacts(token) + self.send("%d buddies imported from google" % len(google)) + + result = { } + for number, name in google.iteritems(): + number = re.sub("[^0-9]", "", number) + number = number if number[0] == "0" else "+" + number + + result[number] = { 'nick': name, 'state': 0 } + + # WhatsApp + user = self.session.legacyName + password = self.session.password + sync = WAContactsSyncRequest(user, password, result.keys()) + whatsapp = sync.send()['c'] + + for w in whatsapp: + result[w['p']]['state'] = w['w'] + result[w['p']]['number'] = w['n'] + + self.send("%d buddies are using whatsapp" % len(filter(lambda w: w['w'], whatsapp))) + + for r in result.values(): + if r['nick']: + self.session.buddies.add( + number = r['number'], + nick = r['nick'], + groups = [u'Google'], + state = r['state'] + ) + + self.send("%d buddies imported" % len(whatsapp)) + def __get_token(self, filename, timeout = 30): file = open(filename, 'r') file.seek(-1, 2) # look at the end @@ -96,6 +137,25 @@ class Bot(): file.close() # commands + def _import(self, token = None): + if not token: + token_url = self.google.getTokenUrl("http://whatsapp.0l.de/auth.py") + auth_url = "http://whatsapp.0l.de/auth.py?number=%s&auth_url=%s" % (self.session.legacyName, urllib.quote(token_url)) + short_url = utils.shorten(auth_url) + self.send("please visit this url to auth: %s" % short_url) + + self.send("waiting for authorization...") + token = self.__get_token(TOKEN_FILE) + if token: + self.send("got token: %s" % token) + self.__do_import(token) + self.session.updateRoster() + else: + self.send("timeout! please use \"\\import [token]\"") + else: + self.__do_import(token) + self.session.updateRoster() + def _sync(self): user = self.session.legacyName password = self.session.password @@ -112,15 +172,18 @@ class Bot(): self.send("""following bot commands are available: \\help show this message \\prune clear your buddylist +\\import [token] import buddies from Google \\sync sync your imported contacts with WhatsApp \\fortune [database] give me a quote +\\groups print all attended groups +\\getgroups get current groups from WA following user commands are available: \\lastseen request last online timestamp from buddy""") def _fortune(self, database = '', prefix=''): - if os.path.exists("/usr/share/games/fortunes/%s" % database): - fortune = os.popen('/usr/games/fortune %s' % database).read() + if os.path.exists("/usr/share/fortune/%s" % database): + fortune = os.popen('/usr/bin/fortune %s' % database).read() self.send(prefix + fortune[:-1]) else: self.send("invalid database") @@ -134,3 +197,16 @@ following user commands are available: self.session.buddies.prune() self.session.updateRoster() self.send("buddy list cleared") + def _groups(self): + for group in self.session.groups: + buddy = self.session.groups[group].owner + try: + nick = self.session.buddies[buddy].nick + except KeyError: + nick = buddy + + self.send(self.session.groups[group].id + "@transwhat.xmpp.ewg.2y.net " + self.session.groups[group].subject + " Owner: " + nick ) + def _getgroups(self): + #self.session.call("group_getGroups", ("participating",)) + self.session.requestGroupsList(self.session._updateGroups) + diff --git a/buddy.py b/buddy.py index e07ec46..8bb09e3 100644 --- a/buddy.py +++ b/buddy.py @@ -25,6 +25,8 @@ __status__ = "Prototype" from Spectrum2 import protocol_pb2 import logging +import threading + class Number(): @@ -56,6 +58,8 @@ class Buddy(): self.number = number self.groups = groups self.image_hash = image_hash + self.statusMsg = "" + def update(self, nick, groups, image_hash): self.nick = nick @@ -65,7 +69,7 @@ class Buddy(): groups = u",".join(groups).encode("latin-1") cur = self.db.cursor() - cur.execute("UPDATE buddies SET nick = %s, groups = %s, image_hash = %s WHERE owner_id = %s AND buddy_id = %s", (self.nick, groups, image_hash, self.owner.id, self.number.id)) + cur.execute("UPDATE buddies SET nick = %s, groups = %s, image_hash = %s WHERE owner_id = %s AND buddy_id = %s", (self.nick, groups, self.image_hash, self.owner.id, self.number.id)) self.db.commit() def delete(self): @@ -91,9 +95,12 @@ class BuddyList(dict): def __init__(self, owner, db): self.db = db self.owner = Number(owner, 1, db) + self.lock = threading.Lock() + def load(self): self.clear() + self.lock.acquire() cur = self.db.cursor() cur.execute("""SELECT @@ -114,13 +121,17 @@ class BuddyList(dict): for i in range(cur.rowcount): id, number, nick, groups, state, image_hash = cur.fetchone() self[number] = Buddy(self.owner, Number(number, state, self.db), nick.decode('latin1'), groups.split(","), image_hash, id, self.db) + self.lock.release() + def update(self, number, nick, groups, image_hash): + self.lock.acquire() if number in self: buddy = self[number] buddy.update(nick, groups, image_hash) else: buddy = self.add(number, nick, groups, 1, image_hash) + self.lock.release() return buddy @@ -130,17 +141,24 @@ class BuddyList(dict): def remove(self, number): try: buddy = self[number] + self.lock.acquire() buddy.delete() + self.lock.release() return buddy except KeyError: return None def prune(self): + self.lock.acquire() + cur = self.db.cursor() cur.execute("DELETE FROM buddies WHERE owner_id = %s", self.owner.id) self.db.commit() + self.lock.release() + def sync(self, user, password): + self.lock.acquire() cur = self.db.cursor() cur.execute("""SELECT n.number AS number, @@ -165,5 +183,5 @@ class BuddyList(dict): cur.execute("UPDATE numbers SET state = %s WHERE number = %s", (number['w'], number['n'])) self.db.commit() using += number['w'] - + self.lock.release() return using diff --git a/session.py b/session.py index bdd9144..d5022ae 100644 --- a/session.py +++ b/session.py @@ -27,6 +27,15 @@ import logging import urllib import time +from PIL import Image +import MySQLdb +import sys +import os + +from yowsup.common.tools import TimeTools +from yowsup.layers.protocol_media.mediauploader import MediaUploader +from yowsup.layers.protocol_media.mediadownloader import MediaDownloader + from Spectrum2 import protocol_pb2 from buddy import BuddyList @@ -36,6 +45,16 @@ from bot import Bot from constants import * from yowsupwrapper import YowsupApp + +class MsgIDs: + def __init__(self, xmppId, waId): + self.xmppId = xmppId + self.waId = waId + self.cnt = 0 + + + + class Session(YowsupApp): def __init__(self, backend, user, legacyName, extra, db): @@ -43,7 +62,9 @@ class Session(YowsupApp): self.logger = logging.getLogger(self.__class__.__name__) self.logger.info("Created: %s", legacyName) - self.db = db + #self.db = db + self.db = MySQLdb.connect(DB_HOST, DB_USER, DB_PASS, DB_TABLE) + self.backend = backend self.user = user self.legacyName = legacyName @@ -61,11 +82,18 @@ class Session(YowsupApp): self.timer = None self.password = None self.initialized = False + self.lastMsgId = None self.synced = False self.buddies = BuddyList(self.legacyName, self.db) self.bot = Bot(self) + self.imgMsgId = None + self.imgPath = "" + self.imgBuddy = None + self.imgType = "" + + def __del__(self): # handleLogoutRequest self.logout() @@ -81,11 +109,13 @@ class Session(YowsupApp): def _shortenGroupId(self, gid): # FIXME: will have problems if number begins with 0 - return '-'.join(hex(int(s))[2:] for s in gid.split('-')) - + #return '-'.join(hex(int(s))[2:] for s in gid.split('-')) + return gid + def _lengthenGroupId(self, gid): # FIXME: will have problems if number begins with 0 - return '-'.join(str(int(s, 16)) for s in gid.split('-')) + #return '-'.join(str(int(s, 16)) for s in gid.split('-')) + return gid def updateRoomList(self): rooms = [] @@ -144,7 +174,7 @@ class Session(YowsupApp): oroom.subject = subject else: self.groups[room] = Group(room, owner, subject, subjectOwner) - self.joinRoom(self._shortenGroupId(room), self.user.split("@")[0]) + #self.joinRoom(self._shortenGroupId(room), self.user.split("@")[0]) self._addParticipantsToRoom(room, group.getParticipants()) @@ -159,6 +189,10 @@ class Session(YowsupApp): def joinRoom(self, room, nick): room = self._lengthenGroupId(room) + if room not in self.groups: + time.sleep(5) + + if room in self.groups: self.logger.info("Joining room: %s room=%s, nick=%s", self.legacyName, room, nick) @@ -206,6 +240,7 @@ class Session(YowsupApp): def _addParticipantsToRoom(self, room, participants): group = self.groups[room] group.participants = participants + group.nick = self.user.split("@")[0] for jid, _type in participants.iteritems(): buddy = jid.split("@")[0] @@ -220,10 +255,10 @@ class Session(YowsupApp): flags = protocol_pb2.PARTICIPANT_FLAG_MODERATOR else: flags = protocol_pb2.PARTICIPANT_FLAG_NONE - if buddy == self.legacyName: - nick = group.nick - flags = protocol_pb2.PARTICIPANT_FLAG_ME - buddyFull = self.user + if buddy == self.legacyName: + nick = group.nick + flags = flags | protocol_pb2.PARTICIPANT_FLAG_ME + buddyFull = self.user self.backend.handleParticipantChanged(self.user, buddyFull, self._shortenGroupId(room), flags, protocol_pb2.STATUS_ONLINE, buddy, nick) @@ -246,7 +281,7 @@ class Session(YowsupApp): ["Admin"], protocol_pb2.STATUS_ONLINE) if self.initialized == False: self.sendOfflineMessages() - self.bot.call("welcome") + #self.bot.call("welcome") self.initialized = True self.sendPresence(True) self.updateRoster() @@ -274,8 +309,13 @@ class Session(YowsupApp): ) try: buddy = self.buddies[_from.split('@')[0]] - self.backend.handleBuddyChanged(self.user, buddy.number.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + #self.backend.handleBuddyChanged(self.user, buddy.number.number, + # buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + self.backend.handleMessageAck(self.user, buddy.number.number, self.msgIDs[_id].xmppId) + self.msgIDs[_id].cnt = self.msgIDs[_id].cnt +1 + if self.msgIDs[_id].cnt == 2: + del self.msgIDs[_id] + except KeyError: pass @@ -316,24 +356,43 @@ class Session(YowsupApp): def onImage(self, image): self.logger.debug('Received image message %s', str(image)) buddy = image._from.split('@')[0] + participant = image.participant message = image.url + ' ' + image.caption - self.sendMessageToXMPP(buddy, message, image.timestamp) + if participant is not None: # Group message + partname = participant.split('@')[0] + self.sendGroupMessageToXMPP(buddy, partname, message, image.timestamp) + else: + + self.sendMessageToXMPP(buddy, message, image.timestamp) self.sendReceipt(image._id, image._from, None, image.participant) # Called by superclass def onAudio(self, audio): self.logger.debug('Received audio message %s', str(audio)) buddy = audio._from.split('@')[0] + participant = audio.participant message = audio.url - self.sendMessageToXMPP(buddy, message, audio.timestamp) + if participant is not None: # Group message + partname = participant.split('@')[0] + self.sendGroupMessageToXMPP(buddy, partname, message, audio.timestamp) + else: + + self.sendMessageToXMPP(buddy, message, audio.timestamp) self.sendReceipt(audio._id, audio._from, None, audio.participant) # Called by superclass def onVideo(self, video): self.logger.debug('Received video message %s', str(video)) buddy = video._from.split('@')[0] + participant = video.participant + message = video.url - self.sendMessageToXMPP(buddy, message, video.timestamp) + if participant is not None: # Group message + partname = participant.split('@')[0] + self.sendGroupMessageToXMPP(buddy, partname, message, video.timestamp) + else: + + self.sendMessageToXMPP(buddy, message, video.timestamp) self.sendReceipt(video._id, video._from, None, video.participant) def onLocation(self, location): @@ -341,13 +400,22 @@ class Session(YowsupApp): latitude = location.getLatitude() longitude = location.getLongitude() url = location.getLocationUrl() + participant = location.participant self.logger.debug("Location received from %s: %s, %s", buddy, latitude, longitude) - self.sendMessageToXMPP(buddy, url, location.timestamp) - self.sendMessageToXMPP(buddy, 'geo:' + latitude + ',' + longitude, + if participant is not None: # Group message + partname = participant.split('@')[0] + self.sendGroupMessageToXMPP(buddy, partname, url, location.timestamp) + self.sendGroupMessageToXMPP(buddy, partname, 'geo:' + latitude + ',' + longitude, + location.timestamp) + else: + + self.sendMessageToXMPP(buddy, url, location.timestamp) + self.sendMessageToXMPP(buddy, 'geo:' + latitude + ',' + longitude, location.timestamp) + self.sendReceipt(location._id, location._from, None, location.participant) # Called by superclass @@ -358,9 +426,14 @@ class Session(YowsupApp): ])) ) buddy = _from.split("@")[0] - self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)") + if participant is not None: # Group message + partname = participant.split('@')[0] + self.sendGroupMessageToXMPP(buddy, partname, "Received VCard (not implemented yet)", timestamp) + else: + + self.sendMessageToXMPP(buddy, "Received VCard (not implemented yet)") # self.sendMessageToXMPP(buddy, card_data) - self.transferFile(buddy, str(name), card_data) + #self.transferFile(buddy, str(name), card_data) self.sendReceipt(_id, _from, None, participant) def transferFile(self, buddy, name, data): @@ -393,6 +466,15 @@ class Session(YowsupApp): buddy = jid.split("@")[0] # seems to be causing an error # self.logger.info("Lastseen: %s %s", buddy, utils.ago(lastseen)) + if lastseen != None and lastseen != "deny": + #lastseen = int(TimeTools.utcTimestamp()) - int(lastseen) + try: + + lastseen=time.time() - int(lastseen) + except ValueError: + lastseen = -1 + else: + lastseen = -1 if buddy in self.presenceRequested: timestamp = time.localtime(time.time() - lastseen) @@ -400,26 +482,27 @@ class Session(YowsupApp): self.sendMessageToXMPP(buddy, "%s (%s)" % (timestring, utils.ago(lastseen))) self.presenceRequested.remove(buddy) - if lastseen < 60: + if (lastseen < 60) and (lastseen >= 0): self.onPresenceAvailable(buddy) else: - self.onPresenceUnavailable(buddy) + self.onPresenceUnavailable(buddy, lastseen) def onPresenceAvailable(self, buddy): try: buddy = self.buddies[buddy] self.logger.info("Is available: %s", buddy) self.backend.handleBuddyChanged(self.user, buddy.number.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE) + buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE, buddy.statusMsg, buddy.image_hash) except KeyError: self.logger.error("Buddy not found: %s", buddy) - def onPresenceUnavailable(self, buddy): + def onPresenceUnavailable(self, buddy, lastseen): try: buddy = self.buddies[buddy] self.logger.info("Is unavailable: %s", buddy) + statusmsg = buddy.statusMsg + "\n Last seen: " + utils.ago(lastseen) self.backend.handleBuddyChanged(self.user, buddy.number.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_XA) + buddy.nick, buddy.groups, protocol_pb2.STATUS_AWAY, statusmsg, buddy.image_hash) except KeyError: self.logger.error("Buddy not found: %s", buddy) @@ -438,7 +521,7 @@ class Session(YowsupApp): self.logger.info("Stopped typing: %s to %s", self.legacyName, buddy) self.sendTyping(buddy, False) - def sendMessageToWA(self, sender, message): + def sendMessageToWA(self, sender, message, ID): self.logger.info("Message sent from %s to %s: %s", self.legacyName, sender, message) @@ -466,14 +549,83 @@ class Session(YowsupApp): ) except KeyError: self.logger.error('Group not found: %s', room) - self.sendTextMessage(self._lengthenGroupId(room) + '@g.us', message) + + if (".jpg" in message) or (".webp" in message): + if (".jpg" in message): + self.imgType = "jpg" + if (".webp" in message): + self.imgType = "webp" + self.imgMsgId = ID + self.imgBuddy = room + "@g.us" + downloader = MediaDownloader(self.onDlsuccess, self.onDlerror) + downloader.download(message) + #self.imgMsgId = ID + #self.imgBuddy = room + "@g.us" + elif "geo:" in message: + self._sendLocation(room + "@g.us", message, ID) + + else: + + self.sendTextMessage(self._lengthenGroupId(room) + '@g.us', message) else: # private msg buddy = sender # if message == "\\lastseen": # self.call("presence_request", buddy = (buddy + "@s.whatsapp.net",)) # else: - self.sendTextMessage(sender + '@s.whatsapp.net', message) + if message == "\\lastseen": + self.presenceRequested.append(buddy) + #self.call("presence_request", (buddy + "@s.whatsapp.net",)) + self._requestLastSeen(buddy) + elif message == "\\gpp": + self.logger.info("Get Profile Picture! ") + self.sendMessageToXMPP(buddy, "Fetching Profile Picture") + #self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",)) + self.requestVCard(buddy) + else: + if (".jpg" in message) or (".webp" in message): + #waId = self.call("message_imageSend", (buddy + "@s.whatsapp.net", message, None, 0, None)) + #waId = self.call("message_send", (buddy + "@s.whatsapp.net", message)) + if (".jpg" in message): + self.imgType = "jpg" + if (".webp" in message): + self.imgType = "webp" + self.imgMsgId = ID + self.imgBuddy = buddy + "@s.whatsapp.net" + + downloader = MediaDownloader(self.onDlsuccess, self.onDlerror) + downloader.download(message) + #self.imgMsgId = ID + #self.imgBuddy = buddy + "@s.whatsapp.net" + elif "geo:" in message: + self._sendLocation(buddy + "@s.whatsapp.net", message, ID) + else: + waId = self.sendTextMessage(sender + '@s.whatsapp.net', message) + self.msgIDs[waId] = MsgIDs( ID, waId) + + self.logger.info("WA Message send to %s with ID %s", buddy, waId) + #self.sendTextMessage(sender + '@s.whatsapp.net', message) + + def _requestLastSeen(self, buddy): + + def onSuccess(buddy, lastseen): + timestamp = time.localtime(time.time()-(lastseen/60)) + timestring = time.strftime("%a, %d %b %Y %H:%M:%S", timestamp) + self.sendMessageToXMPP(buddy, "%s (%s) %s" % (timestring, utils.ago(lastseen),str(lastseen))) + def onError(errorIqEntity, originalIqEntity): + self.sendMessageToXMPP(errorIqEntity.getFrom(), "LastSeen Error") + + self.requestLastSeen(buddy, onSuccess, onError) + + def _sendLocation(self, buddy, message, ID): + #with open('/opt/transwhat/map.jpg', 'rb') as imageFile: + # raw = base64.b64encode(imageFile.read()) + latitude,longitude = message.split(':')[1].split(',') + waId = self.sendLocation(buddy, float(latitude), float(longitude)) + self.msgIDs[waId] = MsgIDs( ID, waId) + self.logger.info("WA Location Message send to %s with ID %s", buddy, waId) + + def sendMessageToXMPP(self, buddy, messageContent, timestamp = "", nickname = ""): if timestamp: @@ -534,10 +686,10 @@ class Session(YowsupApp): self.setStatus(statusMessage.encode('utf-8')) self.logger.info("Status message changed: %s", statusMessage) - if self.initialized == False: - self.sendOfflineMessages() - self.bot.call("welcome") - self.initialized = True + #if self.initialized == False: + # self.sendOfflineMessages() + # self.bot.call("welcome") + # self.initialized = True def sendOfflineMessages(self): # Flush Queues @@ -549,7 +701,8 @@ class Session(YowsupApp): def updateBuddy(self, buddy, nick, groups, image_hash = None): if buddy != "bot": self.buddies.update(buddy, nick, groups, image_hash) - self.updateRoster() + if self.initialized == True: + self.updateRoster() def removeBuddy(self, buddy): if buddy != "bot": @@ -558,13 +711,14 @@ class Session(YowsupApp): self.updateRoster() - def requestVCard(self, buddy, ID): + def requestVCard(self, buddy, ID=None): def onSuccess(response, request): self.logger.debug('Sending VCard (%s) with image id %s', ID, response.pictureId) image_hash = utils.sha1hash(response.pictureData) self.logger.debug('Image hash is %s', image_hash) - self.backend.handleVCard(self.user, ID, buddy, "", "", response.pictureData) + if ID != None: + self.backend.handleVCard(self.user, ID, buddy, "", "", response.pictureData) obuddy = self.buddies[buddy] self.updateBuddy(buddy, obuddy.nick, obuddy.groups, image_hash) @@ -605,3 +759,66 @@ class Session(YowsupApp): def onGroupPictureUpdated(self, jid, author, timestamp, messageId, pictureId, receiptRequested): # TODO if receiptRequested: self.call("notification_ack", (jid, messageId)) + + + + def onDlsuccess(self, path): + self.logger.info("Success: Image downloaded to %s", path) + os.rename(path, path+"."+self.imgType) + if self.imgType != "jpg": + im = Image.open(path+"."+self.imgType) + im.save(path+".jpg") + self.imgPath = path+".jpg" + statinfo = os.stat(self.imgPath) + name=os.path.basename(self.imgPath) + self.logger.info("Buddy %s",self.imgBuddy) + self.image_send(self.imgBuddy, self.imgPath) + + #self.logger.info("Sending picture %s of size %s with name %s",self.imgPath, statinfo.st_size, name) + #mtype = "image" + + #sha1 = hashlib.sha256() + #fp = open(self.imgPath, 'rb') + #try: + # sha1.update(fp.read()) + # hsh = base64.b64encode(sha1.digest()) + # self.call("media_requestUpload", (hsh, mtype, os.path.getsize(self.imgPath))) + #finally: + # fp.close() + + + def onDlerror(self): + self.logger.info("Download Error") + + + def _doSendImage(self, filePath, url, to, ip = None, caption = None): + waId = self.doSendImage(filePath, url, to, ip, caption) + self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) + + def _doSendAudio(self, filePath, url, to, ip = None, caption = None): + waId = self.doSendAudio(filePath, url, to, ip, caption) + self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) + + + + + def createThumb(self, size=100, raw=False): + img = Image.open(self.imgPath) + width, height = img.size + img_thumbnail = self.imgPath + '_thumbnail' + + if width > height: + nheight = float(height) / width * size + nwidth = size + else: + nwidth = float(width) / height * size + nheight = size + + img.thumbnail((nwidth, nheight), Image.ANTIALIAS) + img.save(img_thumbnail, 'JPEG') + + with open(img_thumbnail, 'rb') as imageFile: + raw = base64.b64encode(imageFile.read()) + + return raw + diff --git a/whatsappbackend.py b/whatsappbackend.py index b973f76..ae3a6b9 100644 --- a/whatsappbackend.py +++ b/whatsappbackend.py @@ -58,7 +58,7 @@ class WhatsAppBackend(SpectrumBackend): self.sessions[user].logout() del self.sessions[user] - def handleMessageSendRequest(self, user, buddy, message, xhtml = ""): + def handleMessageSendRequest(self, user, buddy, message, xhtml = "", ID = 0): self.logger.debug("handleMessageSendRequest(user=%s, buddy=%s, message=%s, xhtml = %s)", user, buddy, message, xhtml) # For some reason spectrum occasionally sends to identical messages to # a buddy, one to the bare jid and one to /bot. This causes duplicate @@ -70,7 +70,7 @@ class WhatsAppBackend(SpectrumBackend): # IDEA there is an ID field in ConvMessage. If it is extracted it will work usersMessage = self.lastMessage[user] if buddy not in usersMessage or usersMessage[buddy] != message: - self.sessions[user].sendMessageToWA(buddy, message) + self.sessions[user].sendMessageToWA(buddy, message, ID) usersMessage[buddy] = message def handleJoinRoomRequest(self, user, room, nickname, pasword): @@ -136,6 +136,9 @@ class WhatsAppBackend(SpectrumBackend): def handleRawXmlRequest(self, xml): pass + def handleMessageAckRequest(self, user, legacyName, ID = 0): + self.logger.info("Meassage ACK request for %s !!",leagcyName) + def sendData(self, data): self.io.sendData(data) diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 2a8349b..6369279 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -37,9 +37,12 @@ from yowsup.layers.protocol_messages.protocolentities import * from yowsup.layers.protocol_presence.protocolentities import * from yowsup.layers.protocol_profiles.protocolentities import * from yowsup.layers.protocol_receipts.protocolentities import * +from yowsup.layers.protocol_media.mediauploader import MediaUploader from functools import partial +#from session import MsgIDs + class YowsupApp(object): def __init__(self): env.CURRENT_ENV = env.S40YowsupEnv() @@ -132,6 +135,64 @@ class YowsupApp(object): """ messageEntity = TextMessageProtocolEntity(message, to = to) self.sendEntity(messageEntity) + return messageEntity.getId() + + def sendLocation(self, to, latitude, longitude): + messageEntity = LocationMediaMessageProtocolEntity(latitude,longitude, None, None, "raw", to = to) + self.sendEntity(messageEntity) + return messageEntity.getId() + + def image_send(self, jid, path, caption = None): + entity = RequestUploadIqProtocolEntity(RequestUploadIqProtocolEntity.MEDIA_TYPE_IMAGE, filePath=path) + successFn = lambda successEntity, originalEntity: self.onRequestUploadResult(jid, path, successEntity, originalEntity, caption) + errorFn = lambda errorEntity, originalEntity: self.onRequestUploadError(jid, path, errorEntity, originalEntity) + + self.sendIq(entity, successFn, errorFn) + + def onRequestUploadResult(self, jid, filePath, resultRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity, caption = None): + + if requestUploadIqProtocolEntity.mediaType == RequestUploadIqProtocolEntity.MEDIA_TYPE_AUDIO: + doSendFn = self._doSendAudio + else: + doSendFn = self._doSendImage + + if resultRequestUploadIqProtocolEntity.isDuplicate(): + doSendFn(filePath, resultRequestUploadIqProtocolEntity.getUrl(), jid, + resultRequestUploadIqProtocolEntity.getIp(), caption) + else: + successFn = lambda filePath, jid, url: doSendFn(filePath, url, jid, resultRequestUploadIqProtocolEntity.getIp(), caption) + mediaUploader = MediaUploader(jid, self.legacyName, filePath, + resultRequestUploadIqProtocolEntity.getUrl(), + resultRequestUploadIqProtocolEntity.getResumeOffset(), + successFn, self.onUploadError, self.onUploadProgress, async=False) + mediaUploader.start() + + def onRequestUploadError(self, jid, path, errorRequestUploadIqProtocolEntity, requestUploadIqProtocolEntity): + self.logger.error("Request upload for file %s for %s failed" % (path, jid)) + + def onUploadError(self, filePath, jid, url): + #logger.error("Upload file %s to %s for %s failed!" % (filePath, url, jid)) + self.logger.error("Upload Error!") + + def onUploadProgress(self, filePath, jid, url, progress): + #sys.stdout.write("%s => %s, %d%% \r" % (os.path.basename(filePath), jid, progress)) + #sys.stdout.flush() + pass + + def doSendImage(self, filePath, url, to, ip = None, caption = None): + entity = ImageDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to, caption = caption) + self.sendEntity(entity) + #self.msgIDs[entity.getId()] = MsgIDs(self.imgMsgId, entity.getId()) + return entity.getId() + + + def doSendAudio(self, filePath, url, to, ip = None, caption = None): + entity = AudioDownloadableMediaMessageProtocolEntity.fromFilePath(filePath, url, ip, to) + self.sendEntity(entity) + #self.msgIDs[entity.getId()] = MsgIDs(self.imgMsgId, entity.getId()) + return entity.getId() + + def sendPresence(self, available): """ From bcd5e7e54161109f2affa8df107ca39101f9dec2 Mon Sep 17 00:00:00 2001 From: DaZZZl Date: Tue, 10 Nov 2015 14:00:38 +0100 Subject: [PATCH 13/22] do not send messages on every login --- bot.py | 2 +- session.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bot.py b/bot.py index 469dd78..85d4ae7 100644 --- a/bot.py +++ b/bot.py @@ -205,7 +205,7 @@ following user commands are available: except KeyError: nick = buddy - self.send(self.session.groups[group].id + "@transwhat.xmpp.ewg.2y.net " + self.session.groups[group].subject + " Owner: " + nick ) + self.send(self.session.groups[group].id + self.session.backend.spectrum_jid + " " + self.session.groups[group].subject + " Owner: " + nick ) def _getgroups(self): #self.session.call("group_getGroups", ("participating",)) self.session.requestGroupsList(self.session._updateGroups) diff --git a/session.py b/session.py index c80072f..204c614 100644 --- a/session.py +++ b/session.py @@ -130,7 +130,7 @@ class Session(YowsupApp): self.backend.handleRoomList(rooms) message = "Note, you are a participant of the following groups:\n" +\ '\n'.join(text) + '\nIf you do not join them you will lose messages' - self.bot.send(message) + #self.bot.send(message) def updateRoster(self): self.logger.debug("Update roster") @@ -267,7 +267,6 @@ class Session(YowsupApp): if self.initialized == False: self.sendOfflineMessages() #self.bot.call("welcome") - self.bot.call("welcome") self.initialized = True self.sendPresence(True) self.updateRoster() @@ -414,8 +413,7 @@ class Session(YowsupApp): self.sendMessageToXMPP(buddy, url, location.timestamp) self.sendMessageToXMPP(buddy, 'geo:' + latitude + ',' + longitude, location.timestamp) - self.sendReceipt(location._id, location._from, None, location.participant) - location.timestamp) + self.sendReceipt(location._id, location._from, None, location.participant, location.timestamp) # Called by superclass From f269bf5be7f5cd3f1506ea5420e5e81407e6b308 Mon Sep 17 00:00:00 2001 From: DaZZZl Date: Tue, 10 Nov 2015 17:04:20 +0100 Subject: [PATCH 14/22] fix presence --- bot.py | 4 +-- buddy.py | 2 ++ session.py | 87 +++++++++++++++++++++++++----------------------------- 3 files changed, 45 insertions(+), 48 deletions(-) diff --git a/bot.py b/bot.py index 85d4ae7..16d0e1d 100644 --- a/bot.py +++ b/bot.py @@ -72,7 +72,7 @@ class Bot(): spec = inspect.getargspec(func) maxs = len(spec.args) - 1 reqs = maxs - len(spec.defaults or []) - if reqs > len(args) > maxs: + if (reqs > len(args)) or (len(args) > maxs): raise TypeError() thread = threading.Thread(target=func, args=tuple(args)) @@ -205,7 +205,7 @@ following user commands are available: except KeyError: nick = buddy - self.send(self.session.groups[group].id + self.session.backend.spectrum_jid + " " + self.session.groups[group].subject + " Owner: " + nick ) + self.send(self.session.groups[group].id + "@" + self.session.backend.spectrum_jid + " " + self.session.groups[group].subject + " Owner: " + nick ) def _getgroups(self): #self.session.call("group_getGroups", ("participating",)) self.session.requestGroupsList(self.session._updateGroups) diff --git a/buddy.py b/buddy.py index 8bb09e3..83c4739 100644 --- a/buddy.py +++ b/buddy.py @@ -59,6 +59,8 @@ class Buddy(): self.groups = groups self.image_hash = image_hash self.statusMsg = "" + self.lastseen = 0 + self.presence = 0 def update(self, nick, groups, image_hash): diff --git a/session.py b/session.py index 204c614..7f14441 100644 --- a/session.py +++ b/session.py @@ -484,47 +484,41 @@ class Session(YowsupApp): def onPresenceReceived(self, _type, name, jid, lastseen): self.logger.info("Presence received: %s %s %s %s", _type, name, jid, lastseen) buddy = jid.split("@")[0] -# seems to be causing an error -# self.logger.info("Lastseen: %s %s", buddy, utils.ago(lastseen)) - if lastseen != None and lastseen != "deny": - #lastseen = int(TimeTools.utcTimestamp()) - int(lastseen) - try: + try: + buddy = self.buddies[buddy] + except KeyError: + self.logger.error("Buddy not found: %s", buddy) + return - lastseen=time.time() - int(lastseen) - except ValueError: - lastseen = -1 - else: - lastseen = -1 + if (lastseen == str(buddy.lastseen)) and (_type == buddy.presence): + return + + if ((lastseen != "deny") and (lastseen != None) and (lastseen != "none")): + buddy.lastseen = int(lastseen) + if (_type == None): + buddy.lastseen = time.time() - if buddy in self.presenceRequested: - timestamp = time.localtime(time.time() - lastseen) - timestring = time.strftime("%a, %d %b %Y %H:%M:%S", timestamp) - self.sendMessageToXMPP(buddy, "%s (%s)" % (timestring, utils.ago(lastseen))) - self.presenceRequested.remove(buddy) + buddy.presence = _type - if (lastseen < 60) and (lastseen >= 0): - self.onPresenceAvailable(buddy) + timestamp = time.localtime(buddy.lastseen) + statusmsg = buddy.statusMsg + time.strftime("\n Last seen: %a, %d %b %Y %H:%M:%S", timestamp) + + if _type == "unavailable": + self.onPresenceUnavailable(buddy, statusmsg) else: - self.onPresenceUnavailable(buddy, lastseen) + self.onPresenceAvailable(buddy, statusmsg) - def onPresenceAvailable(self, buddy): - try: - buddy = self.buddies[buddy] - self.logger.info("Is available: %s", buddy) - self.backend.handleBuddyChanged(self.user, buddy.number.number, - buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE, buddy.statusMsg, buddy.image_hash) - except KeyError: - self.logger.error("Buddy not found: %s", buddy) - def onPresenceUnavailable(self, buddy, lastseen): - try: - buddy = self.buddies[buddy] - self.logger.info("Is unavailable: %s", buddy) - statusmsg = buddy.statusMsg + "\n Last seen: " + utils.ago(lastseen) - self.backend.handleBuddyChanged(self.user, buddy.number.number, + + def onPresenceAvailable(self, buddy, statusmsg): + self.logger.info("Is available: %s", buddy) + self.backend.handleBuddyChanged(self.user, buddy.number.number, + buddy.nick, buddy.groups, protocol_pb2.STATUS_ONLINE, statusmsg, buddy.image_hash) + + def onPresenceUnavailable(self, buddy, statusmsg): + self.logger.info("Is unavailable: %s", buddy) + self.backend.handleBuddyChanged(self.user, buddy.number.number, buddy.nick, buddy.groups, protocol_pb2.STATUS_AWAY, statusmsg, buddy.image_hash) - except KeyError: - self.logger.error("Buddy not found: %s", buddy) # spectrum RequestMethods def sendTypingStarted(self, buddy): @@ -557,7 +551,8 @@ class Session(YowsupApp): buddy3.nick) if buddy3.nick == nick: nick = buddy - self.sendTextMessage(nick + '@s.whatsapp.net', message) + waId = self.sendTextMessage(nick + '@s.whatsapp.net', message) + self.msgIDs[waId] = MsgIDs( ID, waId) else: room = sender try: @@ -570,10 +565,10 @@ class Session(YowsupApp): except KeyError: self.logger.error('Group not found: %s', room) - if (".jpg" in message) or (".webp" in message): - if (".jpg" in message): + if (".jpg" in message.lower()) or (".webp" in message.lower()): + if (".jpg" in message.lower()): self.imgType = "jpg" - if (".webp" in message): + if (".webp" in message.lower()): self.imgType = "webp" self.imgMsgId = ID self.imgBuddy = room + "@g.us" @@ -582,7 +577,7 @@ class Session(YowsupApp): downloader.download(message) #self.imgMsgId = ID #self.imgBuddy = room + "@g.us" - elif "geo:" in message: + elif "geo:" in message.lower(): self._sendLocation(room + "@g.us", message, ID) else: @@ -593,22 +588,22 @@ class Session(YowsupApp): # if message == "\\lastseen": # self.call("presence_request", buddy = (buddy + "@s.whatsapp.net",)) # else: - if message == "\\lastseen": + if message.split(" ").pop(0) == "\\lastseen": self.presenceRequested.append(buddy) #self.call("presence_request", (buddy + "@s.whatsapp.net",)) self._requestLastSeen(buddy) - elif message == "\\gpp": + elif message.split(" ").pop(0) == "\\gpp": self.logger.info("Get Profile Picture! ") self.sendMessageToXMPP(buddy, "Fetching Profile Picture") #self.call("contact_getProfilePicture", (buddy + "@s.whatsapp.net",)) self.requestVCard(buddy) else: - if (".jpg" in message) or (".webp" in message): + if (".jpg" in message.lower()) or (".webp" in message.lower()): #waId = self.call("message_imageSend", (buddy + "@s.whatsapp.net", message, None, 0, None)) #waId = self.call("message_send", (buddy + "@s.whatsapp.net", message)) - if (".jpg" in message): + if (".jpg" in message.lower()): self.imgType = "jpg" - if (".webp" in message): + if (".webp" in message.lower()): self.imgType = "webp" self.imgMsgId = ID self.imgBuddy = buddy + "@s.whatsapp.net" @@ -617,7 +612,7 @@ class Session(YowsupApp): downloader.download(message) #self.imgMsgId = ID #self.imgBuddy = buddy + "@s.whatsapp.net" - elif "geo:" in message: + elif "geo:" in message.lower(): self._sendLocation(buddy + "@s.whatsapp.net", message, ID) else: waId = self.sendTextMessage(sender + '@s.whatsapp.net', message) @@ -629,7 +624,7 @@ class Session(YowsupApp): def _requestLastSeen(self, buddy): def onSuccess(buddy, lastseen): - timestamp = time.localtime(time.time()-(lastseen/60)) + timestamp = time.localtime(time.localtime()-lastseen) timestring = time.strftime("%a, %d %b %Y %H:%M:%S", timestamp) self.sendMessageToXMPP(buddy, "%s (%s) %s" % (timestring, utils.ago(lastseen),str(lastseen))) def onError(errorIqEntity, originalIqEntity): From cb041395db92d1d6fcf36744ff8a939e12284fae Mon Sep 17 00:00:00 2001 From: moyamo Date: Tue, 10 Nov 2015 20:39:25 +0200 Subject: [PATCH 15/22] Prevent a None image_hash from causing a TypeError --- buddy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buddy.py b/buddy.py index 83c4739..a393a2c 100644 --- a/buddy.py +++ b/buddy.py @@ -57,7 +57,7 @@ class Buddy(): self.owner = owner self.number = number self.groups = groups - self.image_hash = image_hash + self.image_hash = image_hash if image_hash is not None else "" self.statusMsg = "" self.lastseen = 0 self.presence = 0 From a95b88e7c864be4a51ee6ceb1bc060caf7f47bee Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 23 Nov 2015 14:57:39 +0200 Subject: [PATCH 16/22] Remove duplicate MediaProtocolLayer Prevents user from receiving duplicate media messages. --- yowsupwrapper.py | 1 - 1 file changed, 1 deletion(-) diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 978da3f..add9b93 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -61,7 +61,6 @@ class YowsupApp(object): YowContactsIqProtocolLayer, YowChatstateProtocolLayer, YowCallsProtocolLayer, - YowMediaProtocolLayer, YowPrivacyProtocolLayer, YowProfilesProtocolLayer, YowGroupsProtocolLayer, From 03d4a98fc70d64dfc6ca306b99cad4daae595536 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 23 Nov 2015 15:34:37 +0200 Subject: [PATCH 17/22] Change error messages is backend.py to debug messages --- Spectrum2/backend.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Spectrum2/backend.py b/Spectrum2/backend.py index 05b498f..92cd03d 100644 --- a/Spectrum2/backend.py +++ b/Spectrum2/backend.py @@ -38,14 +38,14 @@ class SpectrumBackend: self.send(message) def handleMessageAck(self, user, legacyName, ID): - m = protocol_pb2.ConversationMessage() - m.userName = user - m.buddyName = legacyName - m.message = "" - m.id = ID + m = protocol_pb2.ConversationMessage() + m.userName = user + m.buddyName = legacyName + m.message = "" + m.id = ID - message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE_ACK) - self.send(message) + message = WRAP(m.SerializeToString(), protocol_pb2.WrapperMessage.TYPE_CONV_MESSAGE_ACK) + self.send(message) def handleAttention(self, user, buddyName, msg): @@ -364,10 +364,10 @@ class SpectrumBackend: if (len(self.m_data) >= 4): expected_size = struct.unpack('!I', self.m_data[0:4])[0] if (len(self.m_data) - 4 < expected_size): - self.logger.error("Expected Data Size Error") + self.logger.debug("Data packet incomplete") return else: - self.logger.error("Data too small") + self.logger.debug("Data packet incomplete") return packet = self.m_data[4:4+expected_size] @@ -376,17 +376,15 @@ class SpectrumBackend: parseFromString = wrapper.ParseFromString(packet) except: self.m_data = self.m_data[expected_size+4:] - self.logger.error("Parse from String exception") + self.logger.error("Parse from String exception. Skipping packet.") return if parseFromString == False: self.m_data = self.m_data[expected_size+4:] - self.logger.error("Parse from String failed") + self.logger.error("Parse from String failed. Skipping packet.") return self.m_data = self.m_data[4+expected_size:] - #self.logger.error("Data Type: %s",wrapper.type) - if wrapper.type == protocol_pb2.WrapperMessage.TYPE_LOGIN: self.handleLoginPayload(wrapper.payload) From 1cec0a4e3004397f453c7eac2e6f39881fe15688 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 23 Nov 2015 16:06:50 +0200 Subject: [PATCH 18/22] Add fortune paths for Debian based systems --- bot.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bot.py b/bot.py index 16d0e1d..0515f5b 100644 --- a/bot.py +++ b/bot.py @@ -185,6 +185,9 @@ following user commands are available: if os.path.exists("/usr/share/fortune/%s" % database): fortune = os.popen('/usr/bin/fortune %s' % database).read() self.send(prefix + fortune[:-1]) + elif os.path.exists("/usr/share/games/fortunes/%s" % database): + fortune = os.popen('/usr/games/fortune %s' % database).read() + self.send(prefix + fortune[:-1]) else: self.send("invalid database") From 8e08efabc94d80c2aafac64fd0b8398ad58d0086 Mon Sep 17 00:00:00 2001 From: moyamo Date: Mon, 23 Nov 2015 17:06:14 +0200 Subject: [PATCH 19/22] Notify user when a group message is sent to a group they have not yet joined Before messages sent to groups the user had not joined were lost. Now the message is sent via the bot to the user. The bot suggests that the user join the group and also relays the contents of the message. --- group.py | 1 + session.py | 32 +++++++++++++++++++++++++++----- whatsappbackend.py | 7 ++++--- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/group.py b/group.py index f5c703e..ca403a9 100644 --- a/group.py +++ b/group.py @@ -29,6 +29,7 @@ class Group(): self.subject = subject self.subjectOwner = subjectOwner self.owner = owner + self.joined = False self.nick = "me" self.participants = { } diff --git a/session.py b/session.py index 7f14441..7f54f71 100644 --- a/session.py +++ b/session.py @@ -91,9 +91,9 @@ class Session(YowsupApp): self.bot = Bot(self) self.imgMsgId = None - self.imgPath = "" - self.imgBuddy = None - self.imgType = "" + self.imgPath = "" + self.imgBuddy = None + self.imgType = "" def __del__(self): # handleLogoutRequest @@ -223,9 +223,18 @@ class Session(YowsupApp): self.backend.handleRoomNicknameChanged( self.user, self._shortenGroupId(room), group.subject ) + group.joined = True else: self.logger.warn("Room doesn't exist: %s", room) + def leaveRoom(self, room): + if room in self.groups: + self.logger.info("Leaving room: %s room=%s", self.legacyName, room) + group = self.groups[room] + group.joined = False + else: + self.logger.warn("Room doesn't exist: %s. Unable to leave.", room) + def _refreshParticipants(self, room): group = self.groups[room] for jid in group.participants: @@ -681,8 +690,21 @@ class Session(YowsupApp): else: self.logger.debug("Group message sent from %s (%s) to %s: %s", buddy, nick, room, messageContent) - self.backend.handleMessage(self.user, self._shortenGroupId(room), - messageContent, nick, "", timestamp) + try: + group = self.groups[room] + if group.joined: + self.backend.handleMessage(self.user,room, messageContent, + nick, "", timestamp) + else: + self.bot.send("You have received a message in group: %s@%s" + % (room, self.backend.spectrum_jid)) + self.bot.send("Join the group in order to reply") + self.bot.send("%s: %s" % (nick, messageContent)) + except KeyError: + self.logger.warn("Group is not in group list") + self.backend.handleMessage(self.user, self._shortenGroupId(room), + messageContent, nick, "", timestamp) + def changeStatus(self, status): if status != self.status: diff --git a/whatsappbackend.py b/whatsappbackend.py index 0de395d..06fbe9b 100644 --- a/whatsappbackend.py +++ b/whatsappbackend.py @@ -78,6 +78,10 @@ class WhatsAppBackend(SpectrumBackend): self.logger.debug("handleJoinRoomRequest(user=%s, room=%s, nickname=%s)", user, room, nickname) self.sessions[user].joinRoom(room, nickname) + def handleLeaveRoomRequest(self, user, room): + self.logger.debug("handleLeaveRoomRequest(user=%s, room=%s)", user, room) + self.sessions[user].leaveRoom(room) + def handleStatusChangeRequest(self, user, status, statusMessage): self.logger.debug("handleStatusChangeRequest(user=%s, status=%d, statusMessage=%s)", user, status, statusMessage) self.sessions[user].changeStatusMessage(statusMessage) @@ -112,9 +116,6 @@ class WhatsAppBackend(SpectrumBackend): def handleBuddyBlockToggled(self, user, buddy, blocked): pass - def handleLeaveRoomRequest(self, user, room): - pass - def handleVCardUpdatedRequest(self, user, photo, nickname): pass From bd74021ca61b4b73c864a500f100ca5f44014522 Mon Sep 17 00:00:00 2001 From: moyamo Date: Fri, 27 Nov 2015 22:01:16 +0200 Subject: [PATCH 20/22] Typing \leave in a MUC will leave the group chat --- bot.py | 5 ++++- session.py | 46 +++++++++++++++++++++++++++++++++++++--------- yowsupwrapper.py | 11 +++++++++++ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/bot.py b/bot.py index 0515f5b..f6a39ba 100644 --- a/bot.py +++ b/bot.py @@ -179,7 +179,10 @@ class Bot(): \\getgroups get current groups from WA following user commands are available: -\\lastseen request last online timestamp from buddy""") +\\lastseen request last online timestamp from buddy + +following group commands are available +\\leave permanently leave group chat""") def _fortune(self, database = '', prefix=''): if os.path.exists("/usr/share/fortune/%s" % database): diff --git a/session.py b/session.py index 7f54f71..78e9985 100644 --- a/session.py +++ b/session.py @@ -564,15 +564,19 @@ class Session(YowsupApp): self.msgIDs[waId] = MsgIDs( ID, waId) else: room = sender - try: - group = self.groups[self._lengthenGroupId(room)] - self.logger.info("Group Message from %s to %s Groups: %s", - group.nick , group , self.groups) - self.backend.handleMessage( - self.user, room, message.decode('utf-8'), group.nick - ) - except KeyError: - self.logger.error('Group not found: %s', room) + if message[0] == '\\' and message[:1] != '\\\\': + self.logger.debug("Executing command %s in %s", message, room) + self.executeCommand(message, room) + else: + try: + group = self.groups[self._lengthenGroupId(room)] + self.logger.debug("Group Message from %s to %s Groups: %s", + group.nick , group , self.groups) + self.backend.handleMessage( + self.user, room, message.decode('utf-8'), group.nick + ) + except KeyError: + self.logger.error('Group not found: %s', room) if (".jpg" in message.lower()) or (".webp" in message.lower()): if (".jpg" in message.lower()): @@ -629,6 +633,30 @@ class Session(YowsupApp): self.logger.info("WA Message send to %s with ID %s", buddy, waId) #self.sendTextMessage(sender + '@s.whatsapp.net', message) + + def executeCommand(self, command, room): + if command == '\\leave': + self.logger.debug("Leaving room %s", room) + # Leave group on whatsapp side + self.leaveGroup(room) + # Delete Room on spectrum side + group = self.groups[room] + for jid in group.participants: + buddy = jid.split("@")[0] + self.logger.info("Added %s to room %s", buddy, room) + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + if nick == "": + nick = buddy + if buddy == self.legacyName: + nick = group.nick + flags = protocol_pb2.PARTICIPANT_FLAG_ROOM_NOT_FOUND + self.backend.handleParticipantChanged( + self.user, nick, self._shortenGroupId(room), flags, + protocol_pb2.STATUS_NONE, buddy) + del self.groups[room] def _requestLastSeen(self, buddy): diff --git a/yowsupwrapper.py b/yowsupwrapper.py index add9b93..4de5be9 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -232,6 +232,16 @@ class YowsupApp(object): entity = UnsubscribePresenceProtocolEntity(jid) self.sendEntity(entity) + def leaveGroup(self, group): + """ + Permanently leave a WhatsApp group + + Args: + - group: (str) the group id (e.g. 27831788123-144024456) + """ + entity = LeaveGroupsIqProtocolEntity([group + '@g.us']) + self.sendEntity(entity) + def setStatus(self, statusText): """ Send status to whatsapp @@ -595,6 +605,7 @@ class YowsupAppLayer(YowInterfaceLayer): @ProtocolEntityCallback('message') def onMessageReceived(self, entity): + self.logger.debug("Received Message: %s", entity) if entity.getType() == MessageProtocolEntity.MESSAGE_TYPE_TEXT: self.caller.onTextMessage( entity._id, From b34643a756ff73035ecbfc2a7423d1e3dae0d7bc Mon Sep 17 00:00:00 2001 From: moyamo Date: Sun, 29 Nov 2015 16:32:33 +0200 Subject: [PATCH 21/22] Handle a user leaving a group chat. --- group.py | 2 +- session.py | 23 ++++++++++++++++++++++- yowsupwrapper.py | 16 +++++++++++++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/group.py b/group.py index ca403a9..c612473 100644 --- a/group.py +++ b/group.py @@ -32,4 +32,4 @@ class Group(): self.joined = False self.nick = "me" - self.participants = { } + self.participants = [] diff --git a/session.py b/session.py index 78e9985..399e861 100644 --- a/session.py +++ b/session.py @@ -484,12 +484,34 @@ class Session(YowsupApp): self.bot.send("You have been added to group: %s@%s (%s)" % (self._shortenGroupId(room), subject, self.backend.spectrum_jid)) + # Called by superclass def onParticipantsAddedToGroup(self, group): self.logger.debug("Participants added to group: %s", group) room = group.getGroupId().split('@')[0] self.groups[room].participants.extend(group.getParticipants()) self._refreshParticipants(room) + # Called by superclass + def onParticipantsRemovedFromGroup(self, room, participants): + self.logger.debug("Participants removed from group: %s, %s", + room, participants) + group = self.groups[room] + for jid in participants: + group.participants.remove(jid) + buddy = jid.split("@")[0] + try: + nick = self.buddies[buddy].nick + except KeyError: + nick = buddy + if nick == "": + nick = buddy + if buddy == self.legacyName: + nick = group.nick + flags = protocol_pb2.PARTICIPANT_FLAG_NONE + self.backend.handleParticipantChanged( + self.user, nick, self._shortenGroupId(room), flags, + protocol_pb2.STATUS_NONE, buddy) + def onPresenceReceived(self, _type, name, jid, lastseen): self.logger.info("Presence received: %s %s %s %s", _type, name, jid, lastseen) buddy = jid.split("@")[0] @@ -643,7 +665,6 @@ class Session(YowsupApp): group = self.groups[room] for jid in group.participants: buddy = jid.split("@")[0] - self.logger.info("Added %s to room %s", buddy, room) try: nick = self.buddies[buddy].nick except KeyError: diff --git a/yowsupwrapper.py b/yowsupwrapper.py index 4de5be9..ef1928b 100644 --- a/yowsupwrapper.py +++ b/yowsupwrapper.py @@ -501,6 +501,15 @@ class YowsupApp(object): """Called when participants have been added to a group""" pass + def onParticipantsRemovedFromGroup(self, group, participants): + """Called when participants have been removed from a group + + Args: + - group: (str) id of the group (e.g. 27831788123-144024456) + - participants: (list) jids of participants that are removed + """ + pass + def sendEntity(self, entity): """Sends an entity down the stack (as if YowsupAppLayer called toLower)""" self.stack.broadcastEvent(YowLayerEvent(YowsupAppLayer.TO_LOWER_EVENT, @@ -596,12 +605,17 @@ class YowsupAppLayer(YowInterfaceLayer): """ Sends ack automatically """ - self.logger.debug("Received notification: %s", entity) + self.logger.debug("Received notification (%s): %s", type(entity), entity) self.toLower(entity.ack()) if isinstance(entity, CreateGroupsNotificationProtocolEntity): self.caller.onAddedToGroup(entity) elif isinstance(entity, AddGroupsNotificationProtocolEntity): self.caller.onParticipantsAddedToGroup(entity) + elif isinstance(entity, RemoveGroupsNotificationProtocolEntity): + self.caller.onParticipantsRemovedFromGroup( + entity.getGroupId().split('@')[0], + entity.getParticipants().keys() + ) @ProtocolEntityCallback('message') def onMessageReceived(self, entity): From e111b0fcffa13553682d17e52d4f9c7ac5c08f4e Mon Sep 17 00:00:00 2001 From: moyamo Date: Sun, 29 Nov 2015 17:06:50 +0200 Subject: [PATCH 22/22] If an image download fails, just send the link. --- session.py | 128 ++++++++++++++++++++++++++++------------------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/session.py b/session.py index 399e861..9060673 100644 --- a/session.py +++ b/session.py @@ -571,6 +571,11 @@ class Session(YowsupApp): self.legacyName, sender, message) message = message.encode("utf-8") + # FIXME: Fragile, should pass this in to onDlerror + self.dlerror_message = message + self.dlerror_sender = sender + self.dlerror_ID = ID + # End Fragile if sender == "bot": self.bot.parse(message) @@ -608,6 +613,7 @@ class Session(YowsupApp): self.imgMsgId = ID self.imgBuddy = room + "@g.us" + downloader = MediaDownloader(self.onDlsuccess, self.onDlerror) downloader.download(message) #self.imgMsgId = ID @@ -811,6 +817,68 @@ class Session(YowsupApp): self.logger.debug('Requesting profile picture of %s', buddy) self.requestProfilePicture(buddy, onSuccess = onSuccess) + def onDlsuccess(self, path): + self.logger.info("Success: Image downloaded to %s", path) + os.rename(path, path+"."+self.imgType) + if self.imgType != "jpg": + im = Image.open(path+"."+self.imgType) + im.save(path+".jpg") + self.imgPath = path+".jpg" + statinfo = os.stat(self.imgPath) + name=os.path.basename(self.imgPath) + self.logger.info("Buddy %s",self.imgBuddy) + self.image_send(self.imgBuddy, self.imgPath) + + #self.logger.info("Sending picture %s of size %s with name %s",self.imgPath, statinfo.st_size, name) + #mtype = "image" + + #sha1 = hashlib.sha256() + #fp = open(self.imgPath, 'rb') + #try: + # sha1.update(fp.read()) + # hsh = base64.b64encode(sha1.digest()) + # self.call("media_requestUpload", (hsh, mtype, os.path.getsize(self.imgPath))) + #finally: + # fp.close() + + + def onDlerror(self): + self.logger.info("Download Error. Sending message as is.") + waId = self.sendTextMessage(self.dlerror_sender + '@s.whatsapp.net', self.dlerror_message) + self.msgIDs[waId] = MsgIDs(self.dlerror_ID, waId) + + + def _doSendImage(self, filePath, url, to, ip = None, caption = None): + waId = self.doSendImage(filePath, url, to, ip, caption) + self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) + + def _doSendAudio(self, filePath, url, to, ip = None, caption = None): + waId = self.doSendAudio(filePath, url, to, ip, caption) + self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) + + + + + def createThumb(self, size=100, raw=False): + img = Image.open(self.imgPath) + width, height = img.size + img_thumbnail = self.imgPath + '_thumbnail' + + if width > height: + nheight = float(height) / width * size + nwidth = size + else: + nwidth = float(width) / height * size + nheight = size + + img.thumbnail((nwidth, nheight), Image.ANTIALIAS) + img.save(img_thumbnail, 'JPEG') + + with open(img_thumbnail, 'rb') as imageFile: + raw = base64.b64encode(imageFile.read()) + + return raw + # Not used def onLocationReceived(self, messageId, jid, name, preview, latitude, longitude, receiptRequested, isBroadcast): buddy = jid.split("@")[0] @@ -848,63 +916,3 @@ class Session(YowsupApp): - def onDlsuccess(self, path): - self.logger.info("Success: Image downloaded to %s", path) - os.rename(path, path+"."+self.imgType) - if self.imgType != "jpg": - im = Image.open(path+"."+self.imgType) - im.save(path+".jpg") - self.imgPath = path+".jpg" - statinfo = os.stat(self.imgPath) - name=os.path.basename(self.imgPath) - self.logger.info("Buddy %s",self.imgBuddy) - self.image_send(self.imgBuddy, self.imgPath) - - #self.logger.info("Sending picture %s of size %s with name %s",self.imgPath, statinfo.st_size, name) - #mtype = "image" - - #sha1 = hashlib.sha256() - #fp = open(self.imgPath, 'rb') - #try: - # sha1.update(fp.read()) - # hsh = base64.b64encode(sha1.digest()) - # self.call("media_requestUpload", (hsh, mtype, os.path.getsize(self.imgPath))) - #finally: - # fp.close() - - - def onDlerror(self): - self.logger.info("Download Error") - - - def _doSendImage(self, filePath, url, to, ip = None, caption = None): - waId = self.doSendImage(filePath, url, to, ip, caption) - self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) - - def _doSendAudio(self, filePath, url, to, ip = None, caption = None): - waId = self.doSendAudio(filePath, url, to, ip, caption) - self.msgIDs[waId] = MsgIDs(self.imgMsgId, waId) - - - - - def createThumb(self, size=100, raw=False): - img = Image.open(self.imgPath) - width, height = img.size - img_thumbnail = self.imgPath + '_thumbnail' - - if width > height: - nheight = float(height) / width * size - nwidth = size - else: - nwidth = float(width) / height * size - nheight = size - - img.thumbnail((nwidth, nheight), Image.ANTIALIAS) - img.save(img_thumbnail, 'JPEG') - - with open(img_thumbnail, 'rb') as imageFile: - raw = base64.b64encode(imageFile.read()) - - return raw -