minimal working functionality
This commit is contained in:
		| @@ -380,17 +380,18 @@ def video_receive_frame(toxav, friend_number, width, height, y, u, v, ystride, u | |||||||
|  |  | ||||||
|  |  | ||||||
| def group_invite(tox, friend_number, gc_type, data, length,  user_data): | def group_invite(tox, friend_number, gc_type, data, length,  user_data): | ||||||
|     invoke_in_main_thread(Profile.get_instance().group_invite, friend_number, gc_type, data[:length]) |     invoke_in_main_thread(Profile.get_instance().group_invite, friend_number, gc_type, | ||||||
|  |                           bytes(data[:length])) | ||||||
|  |  | ||||||
|  |  | ||||||
| def group_message(tox, group_number, peer_number, message, length, user_data): | def group_message(tox, group_number, peer_number, message, length, user_data): | ||||||
|     invoke_in_main_thread(Profile.get_instance().new_gc_message, group_number, |     invoke_in_main_thread(Profile.get_instance().new_gc_message, group_number, | ||||||
|                           peer_number, TOX_MESSAGE_TYPE['NORMAL'], message[:length]) |                           peer_number, TOX_MESSAGE_TYPE['NORMAL'], str(message, 'utf-8')) | ||||||
|  |  | ||||||
|  |  | ||||||
| def group_action(tox, group_number, peer_number, message, length, user_data): | def group_action(tox, group_number, peer_number, message, length, user_data): | ||||||
|     invoke_in_main_thread(Profile.get_instance().new_gc_message, group_number, |     invoke_in_main_thread(Profile.get_instance().new_gc_message, group_number, | ||||||
|                           peer_number, TOX_MESSAGE_TYPE['ACTION'], message[:length]) |                           peer_number, TOX_MESSAGE_TYPE['ACTION'], str(message, 'utf-8')) | ||||||
|  |  | ||||||
|  |  | ||||||
| def group_title(tox, group_number, peer_number, title, length, user_data): | def group_title(tox, group_number, peer_number, title, length, user_data): | ||||||
|   | |||||||
| @@ -1,4 +1,7 @@ | |||||||
| import contact | import contact | ||||||
|  | import util | ||||||
|  | from PyQt5 import QtGui, QtCore | ||||||
|  | import toxcore_enums_and_consts as cnst | ||||||
|  |  | ||||||
|  |  | ||||||
| class GroupChat(contact.Contact): | class GroupChat(contact.Contact): | ||||||
| @@ -6,6 +9,7 @@ class GroupChat(contact.Contact): | |||||||
|     def __init__(self, name, status_message, widget, tox, group_number): |     def __init__(self, name, status_message, widget, tox, group_number): | ||||||
|         super().__init__(None, group_number, name, status_message, widget, None) |         super().__init__(None, group_number, name, status_message, widget, None) | ||||||
|         self._tox = tox |         self._tox = tox | ||||||
|  |         self._status = cnst.TOX_USER_STATUS['NONE'] | ||||||
|  |  | ||||||
|     def set_name(self, name): |     def set_name(self, name): | ||||||
|         self._tox.group_set_title(self._number, name) |         self._tox.group_set_title(self._number, name) | ||||||
| @@ -16,3 +20,14 @@ class GroupChat(contact.Contact): | |||||||
|  |  | ||||||
|     def new_title(self, title): |     def new_title(self, title): | ||||||
|         super().set_name(title) |         super().set_name(title) | ||||||
|  |  | ||||||
|  |     def load_avatar(self): | ||||||
|  |         path = util.curr_directory() + '/images/group.png' | ||||||
|  |         width = self._widget.avatar_label.width() | ||||||
|  |         pixmap = QtGui.QPixmap(path) | ||||||
|  |         self._widget.avatar_label.setPixmap(pixmap.scaled(width, width, QtCore.Qt.KeepAspectRatio, | ||||||
|  |                                                           QtCore.Qt.SmoothTransformation)) | ||||||
|  |         self._widget.avatar_label.repaint() | ||||||
|  |  | ||||||
|  |     def remove_invalid_unsent_files(self): | ||||||
|  |         pass | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								toxygen/images/group.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								toxygen/images/group.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.0 KiB | 
| @@ -41,6 +41,7 @@ class MainWindow(QtWidgets.QMainWindow, Singleton): | |||||||
|         self.menuAbout.setObjectName("menuAbout") |         self.menuAbout.setObjectName("menuAbout") | ||||||
|  |  | ||||||
|         self.actionAdd_friend = QtWidgets.QAction(window) |         self.actionAdd_friend = QtWidgets.QAction(window) | ||||||
|  |         self.actionAdd_gc = QtWidgets.QAction(window) | ||||||
|         self.actionAdd_friend.setObjectName("actionAdd_friend") |         self.actionAdd_friend.setObjectName("actionAdd_friend") | ||||||
|         self.actionprofilesettings = QtWidgets.QAction(window) |         self.actionprofilesettings = QtWidgets.QAction(window) | ||||||
|         self.actionprofilesettings.setObjectName("actionprofilesettings") |         self.actionprofilesettings.setObjectName("actionprofilesettings") | ||||||
| @@ -64,6 +65,7 @@ class MainWindow(QtWidgets.QMainWindow, Singleton): | |||||||
|         self.reloadPlugins = QtWidgets.QAction(window) |         self.reloadPlugins = QtWidgets.QAction(window) | ||||||
|         self.lockApp = QtWidgets.QAction(window) |         self.lockApp = QtWidgets.QAction(window) | ||||||
|         self.menuProfile.addAction(self.actionAdd_friend) |         self.menuProfile.addAction(self.actionAdd_friend) | ||||||
|  |         self.menuProfile.addAction(self.actionAdd_gc) | ||||||
|         self.menuProfile.addAction(self.actionSettings) |         self.menuProfile.addAction(self.actionSettings) | ||||||
|         self.menuProfile.addAction(self.lockApp) |         self.menuProfile.addAction(self.lockApp) | ||||||
|         self.menuSettings.addAction(self.actionPrivacy_settings) |         self.menuSettings.addAction(self.actionPrivacy_settings) | ||||||
| @@ -86,6 +88,7 @@ class MainWindow(QtWidgets.QMainWindow, Singleton): | |||||||
|         self.actionAbout_program.triggered.connect(self.about_program) |         self.actionAbout_program.triggered.connect(self.about_program) | ||||||
|         self.actionNetwork.triggered.connect(self.network_settings) |         self.actionNetwork.triggered.connect(self.network_settings) | ||||||
|         self.actionAdd_friend.triggered.connect(self.add_contact) |         self.actionAdd_friend.triggered.connect(self.add_contact) | ||||||
|  |         self.actionAdd_gc.triggered.connect(self.create_gc) | ||||||
|         self.actionSettings.triggered.connect(self.profile_settings) |         self.actionSettings.triggered.connect(self.profile_settings) | ||||||
|         self.actionPrivacy_settings.triggered.connect(self.privacy_settings) |         self.actionPrivacy_settings.triggered.connect(self.privacy_settings) | ||||||
|         self.actionInterface_settings.triggered.connect(self.interface_settings) |         self.actionInterface_settings.triggered.connect(self.interface_settings) | ||||||
| @@ -115,6 +118,7 @@ class MainWindow(QtWidgets.QMainWindow, Singleton): | |||||||
|         self.menuSettings.setTitle(QtWidgets.QApplication.translate("MainWindow", "Settings")) |         self.menuSettings.setTitle(QtWidgets.QApplication.translate("MainWindow", "Settings")) | ||||||
|         self.menuAbout.setTitle(QtWidgets.QApplication.translate("MainWindow", "About")) |         self.menuAbout.setTitle(QtWidgets.QApplication.translate("MainWindow", "About")) | ||||||
|         self.actionAdd_friend.setText(QtWidgets.QApplication.translate("MainWindow", "Add contact")) |         self.actionAdd_friend.setText(QtWidgets.QApplication.translate("MainWindow", "Add contact")) | ||||||
|  |         self.actionAdd_gc.setText(QtWidgets.QApplication.translate("MainWindow", "Create group chat")) | ||||||
|         self.actionprofilesettings.setText(QtWidgets.QApplication.translate("MainWindow", "Profile")) |         self.actionprofilesettings.setText(QtWidgets.QApplication.translate("MainWindow", "Profile")) | ||||||
|         self.actionPrivacy_settings.setText(QtWidgets.QApplication.translate("MainWindow", "Privacy")) |         self.actionPrivacy_settings.setText(QtWidgets.QApplication.translate("MainWindow", "Privacy")) | ||||||
|         self.actionInterface_settings.setText(QtWidgets.QApplication.translate("MainWindow", "Interface")) |         self.actionInterface_settings.setText(QtWidgets.QApplication.translate("MainWindow", "Interface")) | ||||||
| @@ -431,6 +435,9 @@ class MainWindow(QtWidgets.QMainWindow, Singleton): | |||||||
|         self.a_c = AddContact(link or '') |         self.a_c = AddContact(link or '') | ||||||
|         self.a_c.show() |         self.a_c.show() | ||||||
|  |  | ||||||
|  |     def create_gc(self): | ||||||
|  |         self.profile.create_group_chat() | ||||||
|  |  | ||||||
|     def profile_settings(self, *args): |     def profile_settings(self, *args): | ||||||
|         self.p_s = ProfileSettings() |         self.p_s = ProfileSettings() | ||||||
|         self.p_s.show() |         self.p_s.show() | ||||||
|   | |||||||
| @@ -252,12 +252,15 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|                                 print('Incoming not started transfer - no info found') |                                 print('Incoming not started transfer - no info found') | ||||||
|                     elif message.get_type() == MESSAGE_TYPE['INLINE']:  # inline |                     elif message.get_type() == MESSAGE_TYPE['INLINE']:  # inline | ||||||
|                         self.create_inline_item(message.get_data()) |                         self.create_inline_item(message.get_data()) | ||||||
|                     else:  # info message |                     elif message.get_type() < 5:  # info message | ||||||
|                         data = message.get_data() |                         data = message.get_data() | ||||||
|                         self.create_message_item(data[0], |                         self.create_message_item(data[0], | ||||||
|                                                  data[2], |                                                  data[2], | ||||||
|                                                  '', |                                                  '', | ||||||
|                                                  data[3]) |                                                  data[3]) | ||||||
|  |                     else: | ||||||
|  |                         data = message.get_data() | ||||||
|  |                         self.create_gc_message_item(data[0], data[2], data[1], data[4], data[3]) | ||||||
|                 self._messages.scrollToBottom() |                 self._messages.scrollToBottom() | ||||||
|                 self._load_history = True |                 self._load_history = True | ||||||
|                 if value in self._call: |                 if value in self._call: | ||||||
| @@ -271,7 +274,10 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|  |  | ||||||
|             self._screen.account_name.setText(friend.name) |             self._screen.account_name.setText(friend.name) | ||||||
|             self._screen.account_status.setText(friend.status_message) |             self._screen.account_status.setText(friend.status_message) | ||||||
|             avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(friend.tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) |             if friend.tox_id is None: | ||||||
|  |                 avatar_path = curr_directory() + '/images/group.png' | ||||||
|  |             else: | ||||||
|  |                 avatar_path = (ProfileHelper.get_path() + 'avatars/{}.png').format(friend.tox_id[:TOX_PUBLIC_KEY_SIZE * 2]) | ||||||
|             if not os.path.isfile(avatar_path):  # load default image |             if not os.path.isfile(avatar_path):  # load default image | ||||||
|                 avatar_path = curr_directory() + '/images/avatar.png' |                 avatar_path = curr_directory() + '/images/avatar.png' | ||||||
|             os.chdir(os.path.dirname(avatar_path)) |             os.chdir(os.path.dirname(avatar_path)) | ||||||
| @@ -466,6 +472,9 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|         :param text: message text |         :param text: message text | ||||||
|         :param friend_num: num of friend |         :param friend_num: num of friend | ||||||
|         """ |         """ | ||||||
|  |         if not self.is_active_a_friend(): | ||||||
|  |             self.send_gc_message(text) | ||||||
|  |             return | ||||||
|         if friend_num is None: |         if friend_num is None: | ||||||
|             friend_num = self.get_active_number() |             friend_num = self.get_active_number() | ||||||
|         if text.startswith('/plugin '): |         if text.startswith('/plugin '): | ||||||
| @@ -481,8 +490,8 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|             friend.inc_receipts() |             friend.inc_receipts() | ||||||
|             if friend.status is not None: |             if friend.status is not None: | ||||||
|                 self.split_and_send(friend.number, message_type, text.encode('utf-8')) |                 self.split_and_send(friend.number, message_type, text.encode('utf-8')) | ||||||
|             if friend.number == self.get_active_number(): |             t = time.time() | ||||||
|                 t = time.time() |             if friend.number == self.get_active_number() and self.is_active_a_friend(): | ||||||
|                 self.create_message_item(text, t, MESSAGE_OWNER['NOT_SENT'], message_type) |                 self.create_message_item(text, t, MESSAGE_OWNER['NOT_SENT'], message_type) | ||||||
|                 self._screen.messageEdit.clear() |                 self._screen.messageEdit.clear() | ||||||
|                 self._messages.scrollToBottom() |                 self._messages.scrollToBottom() | ||||||
| @@ -505,7 +514,7 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|         s = Settings.get_instance() |         s = Settings.get_instance() | ||||||
|         if hasattr(self, '_history'): |         if hasattr(self, '_history'): | ||||||
|             if s['save_history']: |             if s['save_history']: | ||||||
|                 for friend in self._contacts: |                 for friend in filter(lambda x: type(x) is Friend, self._contacts): | ||||||
|                     if not self._history.friend_exists_in_db(friend.tox_id): |                     if not self._history.friend_exists_in_db(friend.tox_id): | ||||||
|                         self._history.add_friend_to_db(friend.tox_id) |                         self._history.add_friend_to_db(friend.tox_id) | ||||||
|                     if not s['save_unsent_only']: |                     if not s['save_unsent_only']: | ||||||
| @@ -645,7 +654,7 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|             else: |             else: | ||||||
|                 pixmap = self.get_pixmap() |                 pixmap = self.get_pixmap() | ||||||
|         return self._factory.message_item(text, time, name, True, |         return self._factory.message_item(text, time, name, True, | ||||||
|                                           message_type, append, pixmap) |                                           message_type - 5, append, pixmap) | ||||||
|  |  | ||||||
|     def create_file_transfer_item(self, tm, append=True): |     def create_file_transfer_item(self, tm, append=True): | ||||||
|         data = list(tm.get_data()) |         data = list(tm.get_data()) | ||||||
| @@ -1289,7 +1298,7 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|  |  | ||||||
|     def add_gc(self, number): |     def add_gc(self, number): | ||||||
|         widget = self.create_friend_item() |         widget = self.create_friend_item() | ||||||
|         gc = GroupChat('', '', widget, self._tox, number) |         gc = GroupChat('Group chat #' + str(number), '', widget, self._tox, number) | ||||||
|         self._contacts.append(gc) |         self._contacts.append(gc) | ||||||
|  |  | ||||||
|     def create_group_chat(self): |     def create_group_chat(self): | ||||||
| @@ -1299,7 +1308,8 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|     def group_invite(self, friend_number, gc_type, data): |     def group_invite(self, friend_number, gc_type, data): | ||||||
|         text = QtWidgets.QApplication.translate('MainWindow', 'User {} invites you to group chat. Accept?') |         text = QtWidgets.QApplication.translate('MainWindow', 'User {} invites you to group chat. Accept?') | ||||||
|         title = QtWidgets.QApplication.translate('MainWindow', 'Group chat invite') |         title = QtWidgets.QApplication.translate('MainWindow', 'Group chat invite') | ||||||
|         reply = QtWidgets.QMessageBox.question(None, title, text, QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No) |         friend = self.get_friend_by_number(friend_number) | ||||||
|  |         reply = QtWidgets.QMessageBox.question(None, title, text.format(friend.name), QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No) | ||||||
|         if reply == QtWidgets.QMessageBox.Yes:  # accepted |         if reply == QtWidgets.QMessageBox.Yes:  # accepted | ||||||
|             if gc_type == TOX_GROUPCHAT_TYPE['TEXT']: |             if gc_type == TOX_GROUPCHAT_TYPE['TEXT']: | ||||||
|                 number = self._tox.join_groupchat(friend_number, data) |                 number = self._tox.join_groupchat(friend_number, data) | ||||||
| @@ -1309,12 +1319,13 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|  |  | ||||||
|     def new_gc_message(self, group_number, peer_number, message_type, message): |     def new_gc_message(self, group_number, peer_number, message_type, message): | ||||||
|         name = self._tox.group_peername(group_number, peer_number) |         name = self._tox.group_peername(group_number, peer_number) | ||||||
|  |         message_type += 5 | ||||||
|         if group_number == self.get_active_number() and not self.is_active_a_friend():  # add message to list |         if group_number == self.get_active_number() and not self.is_active_a_friend():  # add message to list | ||||||
|             t = time.time() |             t = time.time() | ||||||
|             self.create_gc_message_item(message, t, MESSAGE_OWNER['FRIEND'], name, message_type) |             self.create_gc_message_item(message, t, MESSAGE_OWNER['FRIEND'], name, message_type) | ||||||
|             self._messages.scrollToBottom() |             self._messages.scrollToBottom() | ||||||
|             self.get_curr_friend().append_message( |             self.get_curr_friend().append_message( | ||||||
|                 GroupChatMessage(message, MESSAGE_OWNER['FRIEND'], t, message_type. name)) |                 GroupChatMessage(message, MESSAGE_OWNER['FRIEND'], t, message_type, name)) | ||||||
|         else: |         else: | ||||||
|             gc = self.get_group_by_number(group_number) |             gc = self.get_group_by_number(group_number) | ||||||
|             gc.inc_messages() |             gc.inc_messages() | ||||||
| @@ -1328,7 +1339,19 @@ class Profile(basecontact.BaseContact, Singleton): | |||||||
|         gc.new_title(title) |         gc.new_title(title) | ||||||
|  |  | ||||||
|     def update_gc(self, group_number): |     def update_gc(self, group_number): | ||||||
|         pass |         count = self._tox.group_number_peers(group_number) | ||||||
|  |         gc = self.get_group_by_number(group_number) | ||||||
|  |         text = QtWidgets.QApplication.translate('MainWindow', '{} users in chat') | ||||||
|  |         gc.status_message = text.format(str(count)).encode('utf-8') | ||||||
|  |  | ||||||
|  |     def send_gc_message(self, text): | ||||||
|  |         group_number = self.get_active_number() | ||||||
|  |         if text.startswith('/me '): | ||||||
|  |             text = text[4:] | ||||||
|  |             self._tox.group_action_send(group_number, text.encode('utf-8')) | ||||||
|  |         else: | ||||||
|  |             self._tox.group_message_send(group_number, text.encode('utf-8')) | ||||||
|  |         self._screen.messageEdit.clear() | ||||||
|  |  | ||||||
|  |  | ||||||
| def tox_factory(data=None, settings=None): | def tox_factory(data=None, settings=None): | ||||||
|   | |||||||
| @@ -90,6 +90,11 @@ class Tox: | |||||||
|             self.file_recv_chunk_cb = None |             self.file_recv_chunk_cb = None | ||||||
|             self.friend_lossy_packet_cb = None |             self.friend_lossy_packet_cb = None | ||||||
|             self.friend_lossless_packet_cb = None |             self.friend_lossless_packet_cb = None | ||||||
|  |             self.group_namelist_change_cb = None | ||||||
|  |             self.group_title_cb = None | ||||||
|  |             self.group_action_cb = None | ||||||
|  |             self.group_message_cb = None | ||||||
|  |             self.group_invite_cb = None | ||||||
|  |  | ||||||
|             self.AV = ToxAV(self._tox_pointer) |             self.AV = ToxAV(self._tox_pointer) | ||||||
|  |  | ||||||
| @@ -1521,7 +1526,7 @@ class Tox: | |||||||
|         buffer = create_string_buffer(TOX_MAX_NAME_LENGTH) |         buffer = create_string_buffer(TOX_MAX_NAME_LENGTH) | ||||||
|         result = Tox.libtoxcore.tox_group_peername(self._tox_pointer, c_int(groupnumber), c_int(peernumber), |         result = Tox.libtoxcore.tox_group_peername(self._tox_pointer, c_int(groupnumber), c_int(peernumber), | ||||||
|                                                    buffer, None) |                                                    buffer, None) | ||||||
|         return buffer[:] |         return str(buffer[:result], 'utf-8') | ||||||
|  |  | ||||||
|     def invite_friend(self, friendnumber, groupnumber): |     def invite_friend(self, friendnumber, groupnumber): | ||||||
|         result = Tox.libtoxcore.tox_invite_friend(self._tox_pointer, c_int(friendnumber), |         result = Tox.libtoxcore.tox_invite_friend(self._tox_pointer, c_int(friendnumber), | ||||||
| @@ -1554,24 +1559,30 @@ class Tox: | |||||||
|         result = Tox.libtoxcore.tox_group_get_title(self._tox_pointer, |         result = Tox.libtoxcore.tox_group_get_title(self._tox_pointer, | ||||||
|                                                     c_int(groupnumber), buffer, |                                                     c_int(groupnumber), buffer, | ||||||
|                                                     c_uint32(TOX_MAX_NAME_LENGTH), None) |                                                     c_uint32(TOX_MAX_NAME_LENGTH), None) | ||||||
|         return buffer[:] |         return str(buffer[:result], 'utf-8') | ||||||
|  |  | ||||||
|     def group_number_peers(self, groupnumber): |     def group_number_peers(self, groupnumber): | ||||||
|         result = Tox.libtoxcore.tox_group_number_peers(self._tox_pointer, c_int(groupnumber), None) |         result = Tox.libtoxcore.tox_group_number_peers(self._tox_pointer, c_int(groupnumber), None) | ||||||
|         return result |         return result | ||||||
|  |  | ||||||
|     # def group_get_names(self): |     def group_get_names(self, groupnumber): | ||||||
|     #     result = Tox.libtoxcore.tox_group_get_names(self._tox_pointer, c_int(groupnumber), |         peers_count = self.group_number_peers(groupnumber) | ||||||
|     #                                                 c_char_p(names), None, c_uint16(length), error) |         arr = (c_char_p * peers_count)() | ||||||
|     #     return result |         for i in range(peers_count): | ||||||
|  |             arr[i] = create_string_buffer(TOX_MAX_NAME_LENGTH) | ||||||
|  |         result = Tox.libtoxcore.tox_group_get_names(self._tox_pointer, c_int(groupnumber), | ||||||
|  |                                                     arr, None, c_uint16(peers_count), None) | ||||||
|  |         arr = map(lambda x: str(x, 'utf-8'), arr) | ||||||
|  |         return list(arr) | ||||||
|  |  | ||||||
|     def add_av_groupchat(self): |     def add_av_groupchat(self): | ||||||
|         result = Tox.libtoxcore.tox_add_av_groupchat(self._tox_pointer, None, None, None) |         result = self.AV.libtoxav.tox_add_av_groupchat(self._tox_pointer, None, None, None) | ||||||
|         return result |         return result | ||||||
|  |  | ||||||
|     def join_av_groupchat(self, friendnumber, data): |     def join_av_groupchat(self, friendnumber, data): | ||||||
|         result = Tox.libtoxcore.tox_join_av_groupchat(self._tox_pointer, c_int(friendnumber), |         result = self.AV.libtoxav.tox_join_av_groupchat(self._tox_pointer, c_int(friendnumber), | ||||||
|                                                       c_char_p(data), c_uint16(len(data)), None, None, None) |                                                         c_char_p(data), c_uint16(len(data)), | ||||||
|  |                                                         None, None, None) | ||||||
|         return result |         return result | ||||||
|  |  | ||||||
|     def callback_group_invite(self, callback, user_data=None): |     def callback_group_invite(self, callback, user_data=None): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user