diff --git a/toxygen/contacts/contact_menu.py b/toxygen/contacts/contact_menu.py
index 63d0d36..7330b35 100644
--- a/toxygen/contacts/contact_menu.py
+++ b/toxygen/contacts/contact_menu.py
@@ -187,6 +187,9 @@ class GroupMenuGenerator(BaseContactMenuGenerator):
.with_optional_action(util_ui.tr('Set topic'),
lambda: groups_service.set_group_topic(self._contact),
self._contact.is_self_moderator_or_founder())
+ .with_optional_action(util_ui.tr('Bans list'),
+ lambda: groups_service.show_bans_list(self._contact),
+ self._contact.is_self_moderator_or_founder())
.with_action(util_ui.tr('Reconnect to group'),
lambda: groups_service.reconnect_to_group(self._contact.number))
.with_optional_action(util_ui.tr('Disconnect from group'),
diff --git a/toxygen/contacts/group_chat.py b/toxygen/contacts/group_chat.py
index e89b561..f173695 100644
--- a/toxygen/contacts/group_chat.py
+++ b/toxygen/contacts/group_chat.py
@@ -4,6 +4,7 @@ import utils.util as util
from groups.group_peer import GroupChatPeer
from wrapper import toxcore_enums_and_consts as constants
from common.tox_save import ToxSave
+from groups.group_ban import GroupBan
class GroupChat(contact.Contact, ToxSave):
@@ -102,6 +103,19 @@ class GroupChat(contact.Contact, ToxSave):
peers = property(get_peers)
+ def get_bans(self):
+ ban_ids = self._tox.group_ban_get_list(self._number)
+ bans = []
+ for ban_id in ban_ids:
+ ban = GroupBan(ban_id,
+ self._tox.group_ban_get_target(self._number, ban_id),
+ self._tox.group_ban_get_time_set(self._number, ban_id))
+ bans.append(ban)
+
+ return bans
+
+ bans = property(get_bans)
+
# -----------------------------------------------------------------------------------------------------------------
# Private methods
# -----------------------------------------------------------------------------------------------------------------
diff --git a/toxygen/groups/group_ban.py b/toxygen/groups/group_ban.py
new file mode 100644
index 0000000..89ecc7e
--- /dev/null
+++ b/toxygen/groups/group_ban.py
@@ -0,0 +1,23 @@
+
+
+class GroupBan:
+
+ def __init__(self, ban_id, ban_target, ban_time):
+ self._ban_id = ban_id
+ self._ban_target = ban_target
+ self._ban_time = ban_time
+
+ def get_ban_id(self):
+ return self._ban_id
+
+ ban_id = property(get_ban_id)
+
+ def get_ban_target(self):
+ return self._ban_target
+
+ ban_target = property(get_ban_target)
+
+ def get_ban_time(self):
+ return self._ban_time
+
+ ban_time = property(get_ban_time)
diff --git a/toxygen/groups/groups_service.py b/toxygen/groups/groups_service.py
index 4cf1368..19b53cf 100644
--- a/toxygen/groups/groups_service.py
+++ b/toxygen/groups/groups_service.py
@@ -15,7 +15,7 @@ class GroupsService(tox_save.ToxSave):
self._peers_list_widget = main_screen.peers_list
self._widgets_factory_provider = widgets_factory_provider
self._group_invites = []
- self._peer_screen = self._management_screen = None
+ self._screen = None
def set_tox(self, tox):
super().set_tox(tox)
@@ -114,8 +114,8 @@ class GroupsService(tox_save.ToxSave):
def show_group_management_screen(self, group):
widgets_factory = self._get_widgets_factory()
- self._management_screen = widgets_factory.create_group_management_screen(group)
- self._management_screen.show()
+ self._screen = widgets_factory.create_group_management_screen(group)
+ self._screen.show()
def set_group_password(self, group, password):
if group.password == password:
@@ -151,10 +151,10 @@ class GroupsService(tox_save.ToxSave):
group = self._get_group_by_public_key(chat_id)
self_peer = group.get_self_peer()
if self_peer.id != peer_id:
- self._peer_screen = widgets_factory.create_peer_screen_window(group, peer_id)
+ self._screen = widgets_factory.create_peer_screen_window(group, peer_id)
else:
- self._peer_screen = widgets_factory.create_self_peer_screen_window(group)
- self._peer_screen.show()
+ self._screen = widgets_factory.create_self_peer_screen_window(group)
+ self._screen.show()
# -----------------------------------------------------------------------------------------------------------------
# Peers actions
@@ -177,6 +177,26 @@ class GroupsService(tox_save.ToxSave):
self_peer.status = status
self.generate_peers_list()
+ # -----------------------------------------------------------------------------------------------------------------
+ # Bans support
+ # -----------------------------------------------------------------------------------------------------------------
+
+ def show_bans_list(self, group):
+ widgets_factory = self._get_widgets_factory()
+ self._screen = widgets_factory.create_groups_bans_screen(group)
+ self._screen.show()
+
+ def ban_peer(self, group, peer_id, ban_type):
+ self._tox.group_mod_ban_peer(group.number, peer_id, ban_type)
+ group.remove_peer(peer_id)
+
+ def kick_peer(self, group, peer_id):
+ self._tox.group_mod_remove_peer(group.number, peer_id)
+ group.remove_peer(peer_id)
+
+ def cancel_ban(self, group_number, ban_id):
+ self._tox.group_mod_remove_ban(group_number, ban_id)
+
# -----------------------------------------------------------------------------------------------------------------
# Private methods
# -----------------------------------------------------------------------------------------------------------------
diff --git a/toxygen/ui/group_bans_widgets.py b/toxygen/ui/group_bans_widgets.py
new file mode 100644
index 0000000..45a5f2b
--- /dev/null
+++ b/toxygen/ui/group_bans_widgets.py
@@ -0,0 +1,62 @@
+from ui.widgets import CenteredWidget
+from PyQt5 import uic, QtWidgets, QtCore
+import utils.util as util
+import utils.ui as util_ui
+
+
+class GroupBanItem(QtWidgets.QWidget):
+
+ def __init__(self, ban, cancel_ban, parent=None):
+ super().__init__(parent)
+ self._ban = ban
+ self._cancel_ban = cancel_ban
+
+ def _update_ui(self):
+ self._retranslate_ui()
+
+ self.banTargetLabel.setText(self._ban.target)
+ ban_time = self._ban.ban_time
+ self.banTimeLabel.setText(util.unix_time_to_long_str(ban_time))
+
+ self.cancelPushButton.clicked.connect(self._cancel_ban)
+
+ def _retranslate_ui(self):
+ self.cancelPushButton.setText(util_ui.tr('Cancel ban'))
+
+ def _cancel_ban(self):
+ self._cancel_ban(self._ban.ban_id)
+
+
+class GroupBansScreen(CenteredWidget):
+
+ def __init__(self, groups_service, group):
+ super().__init__()
+ self._groups_service = groups_service
+ self._group = group
+
+ uic.loadUi(util.get_views_path('bans_list_screen'), self)
+ self._update_ui()
+
+ def _update_ui(self):
+ self._retranslate_ui()
+
+ self._refresh_bans_list()
+
+ def _retranslate_ui(self):
+ self.setWindowTitle(util_ui.tr('Bans list for group "{}"').format(self._group.name))
+
+ def _refresh_bans_list(self):
+ self.bansListWidget.clear()
+ for ban in self._group.bans:
+ self._create_ban_item(ban)
+
+ def _create_ban_item(self, ban):
+ item = GroupBanItem(ban, self._on_ban_cancelled, self.bansListWidget)
+ elem = QtWidgets.QListWidgetItem()
+ elem.setSizeHint(QtCore.QSize(item.width(), item.height()))
+ self.bansListWidget.addItem(elem)
+ self.bansListWidget.setItemWidget(elem, item)
+
+ def _on_ban_cancelled(self, ban_id):
+ self._groups_service.cancel_ban(self._group.number, ban_id)
+ self._refresh_bans_list()
diff --git a/toxygen/ui/peer_screen.py b/toxygen/ui/peer_screen.py
index 651d998..687c818 100644
--- a/toxygen/ui/peer_screen.py
+++ b/toxygen/ui/peer_screen.py
@@ -1,8 +1,9 @@
from ui.widgets import CenteredWidget
-from PyQt5 import QtCore, QtWidgets, uic
+from PyQt5 import uic
import utils.util as util
import utils.ui as util_ui
from ui.contact_items import *
+import wrapper.toxcore_enums_and_consts as consts
class PeerScreen(CenteredWidget):
@@ -35,9 +36,12 @@ class PeerScreen(CenteredWidget):
self.sendPrivateMessagePushButton.clicked.connect(self._send_private_message)
self.copyPublicKeyPushButton.clicked.connect(self._copy_public_key)
self.roleNameLabel.setText(self._get_role_name())
- can_change_role = self._can_change_role()
- self.rolesComboBox.setVisible(can_change_role)
- self.roleNameLabel.setVisible(not can_change_role)
+ can_change_role_or_ban = self._can_change_role_or_ban()
+ self.rolesComboBox.setVisible(can_change_role_or_ban)
+ self.roleNameLabel.setVisible(not can_change_role_or_ban)
+ self.banGroupBox.setEnabled(can_change_role_or_ban)
+ self.banPushButton.clicked.connect(self._ban_peer)
+ self.kickPushButton.clicked.connect(self._kick_peer)
self._retranslate_ui()
@@ -49,7 +53,12 @@ class PeerScreen(CenteredWidget):
self.roleLabel.setText(util_ui.tr('Role:'))
self.copyPublicKeyPushButton.setText(util_ui.tr('Copy public key'))
self.sendPrivateMessagePushButton.setText(util_ui.tr('Send private message'))
- self.banGroupBox.setTitle(util_ui.tr('Moderation'))
+ self.banPushButton.setText(util_ui.tr('Ban peer'))
+ self.kickPushButton.setText(util_ui.tr('Kick peer'))
+ self.banGroupBox.setTitle(util_ui.tr('Ban peer'))
+ self.ipBanRadioButton.setText(util_ui.tr('IP'))
+ self.nickBanRadioButton.setText(util_ui.tr('Nickname'))
+ self.pkBanRadioButton.setText(util_ui.tr('Public key'))
self.rolesComboBox.clear()
index = self._group.get_self_peer().role
@@ -58,7 +67,7 @@ class PeerScreen(CenteredWidget):
self.rolesComboBox.addItem(role)
self.rolesComboBox.setCurrentIndex(self._peer.role - index - 1)
- def _can_change_role(self):
+ def _can_change_role_or_ban(self):
self_peer = self._group.get_self_peer()
if self_peer.role > TOX_GROUP_ROLE['MODERATOR']:
return False
@@ -85,3 +94,17 @@ class PeerScreen(CenteredWidget):
def _copy_public_key(self):
clipboard = QtWidgets.QApplication.clipboard()
clipboard.setText(self._peer.public_key)
+
+ def _ban_peer(self):
+ ban_type = self._get_ban_type()
+ self._groups_service.ban_peer(self._group, self._peer.id, ban_type)
+
+ def _kick_peer(self):
+ self._groups_service.kick_peer(self._group, self._peer.id)
+
+ def _get_ban_type(self):
+ if self.ipBanRadioButton.isChecked():
+ return consts.TOX_GROUP_BAN_TYPE['IP_PORT']
+ elif self.nickRadioButton.isCHecked():
+ return consts.TOX_GROUP_BAN_TYPE['NICK']
+ return consts.TOX_GROUP_BAN_TYPE['PUBLIC_KEY']
diff --git a/toxygen/ui/views/bans_list_screen.ui b/toxygen/ui/views/bans_list_screen.ui
new file mode 100644
index 0000000..16339d8
--- /dev/null
+++ b/toxygen/ui/views/bans_list_screen.ui
@@ -0,0 +1,29 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 500
+ 375
+
+
+
+ Form
+
+
+
+
+ 0
+ 0
+ 500
+ 375
+
+
+
+
+
+
+
diff --git a/toxygen/ui/views/gc_ban_item.ui b/toxygen/ui/views/gc_ban_item.ui
new file mode 100644
index 0000000..20e1e16
--- /dev/null
+++ b/toxygen/ui/views/gc_ban_item.ui
@@ -0,0 +1,58 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 500
+ 100
+
+
+
+ Form
+
+
+
+
+ 320
+ 30
+ 161
+ 41
+
+
+
+ PushButton
+
+
+
+
+
+ 20
+ 20
+ 200
+ 20
+
+
+
+ TextLabel
+
+
+
+
+
+ 20
+ 50
+ 200
+ 20
+
+
+
+ TextLabel
+
+
+
+
+
+
diff --git a/toxygen/ui/views/peer_screen.ui b/toxygen/ui/views/peer_screen.ui
index f6b13b3..a66ec11 100644
--- a/toxygen/ui/views/peer_screen.ui
+++ b/toxygen/ui/views/peer_screen.ui
@@ -76,6 +76,74 @@
GroupBox
+
+
+
+ 380
+ 50
+ 101
+ 41
+
+
+
+ PushButton
+
+
+
+
+
+ 40
+ 40
+ 251
+ 23
+
+
+
+ RadioButton
+
+
+ true
+
+
+
+
+
+ 40
+ 80
+ 251
+ 23
+
+
+
+ RadioButton
+
+
+
+
+
+ 40
+ 120
+ 251
+ 23
+
+
+
+ RadioButton
+
+
+
+
+
+ 380
+ 100
+ 101
+ 41
+
+
+
+ PushButton
+
+
diff --git a/toxygen/ui/widgets_factory.py b/toxygen/ui/widgets_factory.py
index e394684..b146088 100644
--- a/toxygen/ui/widgets_factory.py
+++ b/toxygen/ui/widgets_factory.py
@@ -5,6 +5,7 @@ from ui.peer_screen import *
from ui.self_peer_screen import *
from ui.group_invites_widgets import *
from ui.group_management_screen import *
+from ui.group_bans_widgets import *
class WidgetsFactory:
@@ -86,3 +87,6 @@ class WidgetsFactory:
def create_group_management_screen(self, group):
return GroupManagementScreen(self._groups_service, group)
+
+ def create_groups_bans_screen(self, group):
+ return GroupBansScreen(self._groups_service, group)
diff --git a/toxygen/utils/util.py b/toxygen/utils/util.py
index 0f718ef..3c6910e 100644
--- a/toxygen/utils/util.py
+++ b/toxygen/utils/util.py
@@ -4,6 +4,7 @@ import shutil
import sys
import re
import platform
+import datetime
def cached(func):
@@ -21,10 +22,10 @@ def cached(func):
def log(data):
try:
- with open(curr_directory() + '/logs.log', 'a') as fl:
+ with open(join_path(curr_directory(), 'logs.log'), 'a') as fl:
fl.write(str(data) + '\n')
- except:
- pass
+ except Exception as ex:
+ print(ex)
def curr_directory(current_file=None):
@@ -144,6 +145,12 @@ def time_offset():
return result
+def unix_time_to_long_str(unix_time):
+ date_time = datetime.datetime.utcfromtimestamp(unix_time)
+
+ return date_time.strftime('%Y-%m-%d %H:%M:%S')
+
+
@cached
def is_64_bit():
return sys.maxsize > 2 ** 32
diff --git a/toxygen/wrapper/tox.py b/toxygen/wrapper/tox.py
index 0e3310d..a2abf6a 100644
--- a/toxygen/wrapper/tox.py
+++ b/toxygen/wrapper/tox.py
@@ -2468,9 +2468,11 @@ class Tox:
"""
error = c_int()
- result = Tox.libtoxcore.tox_group_ban_get_list(self._tox_pointer, group_number, POINTER(c_uint32)(
- create_string_buffer(sizeof(c_uint32) * self.group_ban_get_list_size(group_number)), byref(error)))
- return result
+ bans_list_size = self.group_ban_get_list_size(group_number)
+ bans_list = create_string_buffer(sizeof(c_uint32) * bans_list_size)
+ bans_list = POINTER(c_uint32)(bans_list)
+ result = Tox.libtoxcore.tox_group_ban_get_list(self._tox_pointer, group_number, bans_list, byref(error))
+ return bans_list[:bans_list_size]
def group_ban_get_target_size(self, group_number, ban_id):
"""
diff --git a/toxygen/wrapper/toxcore_enums_and_consts.py b/toxygen/wrapper/toxcore_enums_and_consts.py
index 7c6478c..1e134f9 100644
--- a/toxygen/wrapper/toxcore_enums_and_consts.py
+++ b/toxygen/wrapper/toxcore_enums_and_consts.py
@@ -914,11 +914,11 @@ TOX_ERR_GROUP_BAN_QUERY = {
TOX_GROUP_BAN_TYPE = {
- 'TOX_GROUP_BAN_TYPE_IP_PORT': 0,
+ 'IP_PORT': 0,
- 'TOX_GROUP_BAN_TYPE_PUBLIC_KEY': 1,
+ 'PUBLIC_KEY': 1,
- 'TOX_GROUP_BAN_TYPE_NICK': 2
+ 'NICK': 2
}