Skip to content

Commit 9419361

Browse files
committed
feat: banning users
Merge pull request #103 from d-Rickyy-b/dev
2 parents 05e8daa + 7566647 commit 9419361

File tree

10 files changed

+175
-33
lines changed

10 files changed

+175
-33
lines changed

blackjackbot/__init__.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
# -*- coding: utf-8 -*-
2+
from telegram import Update
23
from telegram.ext import CommandHandler, CallbackQueryHandler, MessageHandler, Filters
3-
from blackjackbot.errors import error_handler
44

55
from blackjackbot.commands import game, admin, settings, util
6+
from blackjackbot.errors import error_handler
7+
from util import BannedUserHandler, banned_user_callback
8+
9+
# Banned users
10+
banned_user_handler = BannedUserHandler(callback=banned_user_callback, type=Update)
611

712
# User commands
813
start_command_handler = CommandHandler("start", game.start_cmd)
@@ -17,6 +22,9 @@
1722
users_command_handler = CommandHandler("users", admin.users_cmd)
1823
answer_command_handler = CommandHandler("answer", admin.answer_comment_cmd, Filters.reply)
1924
kill_command_handler = CommandHandler("kill", admin.kill_game_cmd, Filters.text)
25+
ban_command_handler = CommandHandler("ban", admin.ban_user_cmd, pass_args=True)
26+
unban_command_handler = CommandHandler("unban", admin.unban_user_cmd, pass_args=True)
27+
bans_command_handler = CommandHandler("bans", admin.bans_cmd)
2028

2129
# Callback handlers
2230
hit_callback_handler = CallbackQueryHandler(game.hit_callback, pattern=r"^hit_[0-9]{7}$")
@@ -26,8 +34,11 @@
2634
newgame_callback_handler = CallbackQueryHandler(game.newgame_callback, pattern=r"^newgame$")
2735
language_callback_handler = CallbackQueryHandler(settings.language_callback, pattern=r"^lang_([a-z]{2}(?:-[a-z]{2})?)$")
2836

29-
handlers = [start_command_handler, stop_command_handler, join_callback_handler, hit_callback_handler, stand_callback_handler, start_callback_handler,
30-
language_command_handler, stats_command_handler, newgame_callback_handler, reload_lang_command_handler, language_callback_handler,
31-
users_command_handler, comment_command_handler, comment_text_command_handler, answer_command_handler]
37+
handlers = [banned_user_handler,
38+
start_command_handler, stop_command_handler, join_callback_handler, hit_callback_handler,
39+
stand_callback_handler, start_callback_handler, language_command_handler, stats_command_handler,
40+
newgame_callback_handler, reload_lang_command_handler, language_callback_handler, users_command_handler,
41+
comment_command_handler, comment_text_command_handler, answer_command_handler, ban_command_handler,
42+
unban_command_handler, bans_command_handler]
3243

3344
__all__ = ['handlers', 'error_handler']
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from .functions import notify_admins
3-
from .commands import answer_comment_cmd, reload_languages_cmd, users_cmd, kill_game_cmd
3+
from .commands import answer_comment_cmd, reload_languages_cmd, users_cmd, kill_game_cmd, ban_user_cmd, \
4+
unban_user_cmd, bans_cmd
45

5-
__all__ = ["answer_comment_cmd", "reload_languages_cmd", "users_cmd", "notify_admins", "kill_game_cmd"]
6+
__all__ = ["answer_comment_cmd", "reload_languages_cmd", "users_cmd", "notify_admins", "kill_game_cmd", "ban_user_cmd",
7+
"unban_user_cmd", "bans_cmd"]

blackjackbot/commands/admin/commands.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import logging
44
import re
55

6+
from telegram import ParseMode
7+
68
from blackjackbot.commands.admin import notify_admins
79
from blackjackbot.commands.util.decorators import admin_method
810
from blackjackbot.errors import NoActiveGameException
@@ -13,6 +15,53 @@
1315
logger = logging.getLogger(__name__)
1416

1517

18+
@admin_method
19+
def ban_user_cmd(update, context):
20+
"""Bans a user from using the bot"""
21+
usage_message = r"Please provide a valid userid\. Usage: `/ban <userid>`"
22+
# Try to get user_id from command
23+
if len(context.args) != 1:
24+
update.effective_message.reply_text(usage_message, parse_mode=ParseMode.MARKDOWN_V2)
25+
return
26+
27+
match = re.search(r"^\d+$", context.args[0])
28+
if not match:
29+
logger.error(f"The user_id did not match. Args: {context.args}")
30+
update.effective_message.reply_text(usage_message, parse_mode=ParseMode.MARKDOWN_V2)
31+
return
32+
user_id = match.group(0)
33+
34+
db = Database()
35+
db.ban_user(user_id=user_id)
36+
37+
logger.info(f"Admin '{update.effective_user.id}' banned user '{user_id}'!")
38+
notify_admins(f"Admin '{update.effective_user.id}' banned user '{user_id}'!", context)
39+
40+
41+
@admin_method
42+
def unban_user_cmd(update, context):
43+
"""Unbans a user from using the bot"""
44+
usage_message = r"Please provide a valid userid\. Usage: `/unban <userid>`"
45+
46+
# Try to get user_id from command
47+
if len(context.args) != 1:
48+
update.message.reply_text(usage_message, parse_mode=ParseMode.MARKDOWN_V2)
49+
return
50+
51+
match = re.search(r"^\d+$", context.args[0])
52+
if not match:
53+
logger.error(f"The user_id did not match. Args: {context.args}")
54+
update.effective_message.reply_text(usage_message, parse_mode=ParseMode.MARKDOWN_V2)
55+
return
56+
user_id = match.group(0)
57+
58+
db = Database()
59+
db.unban_user(user_id=user_id)
60+
61+
logger.info(f"Admin '{update.effective_user.id}' unbanned user '{user_id}'!")
62+
notify_admins(f"Admin '{update.effective_user.id}' unbanned user '{user_id}'!", context)
63+
64+
1665
@admin_method
1766
def kill_game_cmd(update, context):
1867
"""Kills the game for a certain chat/group"""
@@ -103,3 +152,14 @@ def users_cmd(update, context):
103152
text = "Last 24 hours: {}".format(len(players))
104153

105154
update.message.reply_text(text=text)
155+
156+
157+
@admin_method
158+
def bans_cmd(update, context):
159+
"""Returns the amount of players in the last 24 hours"""
160+
db = Database()
161+
banned_users = db.get_banned_users()
162+
163+
text = f"Banned user count: {len(banned_users)}"
164+
165+
update.message.reply_text(text=text)

blackjackbot/commands/game/commands.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# -*- coding: utf-8 -*-
22

3+
from telegram.parsemode import ParseMode
4+
35
import blackjack.errors as errors
46
from blackjack.game import BlackJackGame
57
from blackjackbot.commands.util import html_mention, get_game_keyboard, get_join_keyboard, get_start_keyboard, remove_inline_keyboard
@@ -156,21 +158,21 @@ def hit_callback(update, context):
156158
game.draw_card()
157159
player_cards = get_cards_string(player, lang_id)
158160
text = translator("your_cards_are").format(user_mention, player.cardvalue, player_cards)
159-
update.effective_message.edit_text(text=text, parse_mode="HTML", reply_markup=get_game_keyboard(game.id, lang_id))
161+
update.effective_message.edit_text(text=text, parse_mode=ParseMode.HTML, reply_markup=get_game_keyboard(game.id, lang_id))
160162
except errors.PlayerBustedException:
161163
player_cards = get_cards_string(player, lang_id)
162164
text = (translator("your_cards_are") + "\n\n" + translator("you_busted")).format(user_mention, player.cardvalue, player_cards)
163-
update.effective_message.edit_text(text=text, parse_mode="HTML", reply_markup=None)
165+
update.effective_message.edit_text(text=text, parse_mode=ParseMode.HTML, reply_markup=None)
164166
next_player(update, context)
165167
except errors.PlayerGot21Exception:
166168
player_cards = get_cards_string(player, lang_id)
167169
if player.has_blackjack():
168170
text = (translator("your_cards_are") + "\n\n" + translator("got_blackjack")).format(user_mention, player.cardvalue, player_cards)
169-
update.effective_message.edit_text(text=text, parse_mode="HTML", reply_markup=None)
171+
update.effective_message.edit_text(text=text, parse_mode=ParseMode.HTML, reply_markup=None)
170172
next_player(update, context)
171173
elif player.cardvalue == 21:
172174
text = (translator("your_cards_are") + "\n\n" + translator("got_21")).format(user_mention, player.cardvalue, player_cards)
173-
update.effective_message.edit_text(text=text, parse_mode="HTML", reply_markup=None)
175+
update.effective_message.edit_text(text=text, parse_mode=ParseMode.HTML, reply_markup=None)
174176
next_player(update, context)
175177

176178

blackjackbot/commands/game/functions.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
import logging
33

4-
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
4+
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode
55

66
from blackjack.errors import NoPlayersLeftException
77
from blackjack.game import BlackJackGame
@@ -45,15 +45,15 @@ def players_turn(update, context):
4545
# We need reply_text here, because we must send a new message (this is the first message for the player)!
4646
if player.has_blackjack():
4747
text = (translator("your_cards_are") + "\n\n" + translator("got_blackjack")).format(user_mention, player.cardvalue, player_cards)
48-
update.effective_message.reply_text(text=text, parse_mode="HTML", reply_markup=None)
48+
update.effective_message.reply_text(text=text, parse_mode=ParseMode.HTML, reply_markup=None)
4949
next_player(update, context)
5050
elif player.cardvalue == 21:
5151
text = (translator("your_cards_are") + "\n\n" + translator("got_21")).format(user_mention, player.cardvalue, player_cards)
52-
update.effective_message.reply_text(text=text, parse_mode="HTML", reply_markup=None)
52+
update.effective_message.reply_text(text=text, parse_mode=ParseMode.HTML, reply_markup=None)
5353
next_player(update, context)
5454
else:
5555
text = translator("your_cards_are").format(user_mention, player.cardvalue, player_cards)
56-
update.effective_message.reply_text(text=text, parse_mode="HTML", reply_markup=get_game_keyboard(game.id, lang_id))
56+
update.effective_message.reply_text(text=text, parse_mode=ParseMode.HTML, reply_markup=get_game_keyboard(game.id, lang_id))
5757

5858

5959
@needs_active_game
@@ -76,7 +76,7 @@ def next_player(update, context):
7676
# TODO merge messages
7777
update.effective_message.reply_text(translator("dealers_cards_are").format(game.dealer.cardvalue,
7878
get_cards_string(game.dealer, lang_id)),
79-
parse_mode="HTML")
79+
parse_mode=ParseMode.HTML)
8080
evaluation_string = generate_evaluation_string(game, lang_id)
8181

8282
newgame_button = InlineKeyboardButton(text=translator("inline_keyboard_newgame"), callback_data="newgame")

blackjackbot/commands/util/commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
from telegram import ForceReply
3+
from telegram import ForceReply, ParseMode
44

55
from blackjackbot.commands.admin.functions import notify_admins
66
from blackjackbot.lang import translate
@@ -10,7 +10,7 @@
1010

1111

1212
def stats_cmd(update, context):
13-
update.message.reply_text(get_user_stats(update.effective_user.id), parse_mode="HTML")
13+
update.message.reply_text(get_user_stats(update.effective_user.id), parse_mode=ParseMode.HTML)
1414

1515

1616
def comment_cmd(update, context):

database/database.py

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
import sqlite3
55
from time import time
6+
67
from util import Cache
78

89

@@ -11,29 +12,35 @@ class Database(object):
1112

1213
_instance = None
1314
_initialized = False
15+
_banned_users = set()
1416

1517
def __new__(cls):
1618
if not Database._instance:
1719
Database._instance = super(Database, cls).__new__(cls)
1820
return Database._instance
1921

2022
def __init__(self):
21-
if not self._initialized:
22-
database_path = os.path.join(self.dir_path, "users.db")
23-
self.logger = logging.getLogger(__name__)
23+
if self._initialized:
24+
return
25+
26+
database_path = os.path.join(self.dir_path, "users.db")
27+
self.logger = logging.getLogger(__name__)
28+
29+
if not os.path.exists(database_path):
30+
self.logger.debug("File '{}' does not exist! Trying to create one.".format(database_path))
31+
try:
32+
self.create_database(database_path)
33+
except Exception:
34+
self.logger.error("An error has occurred while creating the database!")
2435

25-
if not os.path.exists(database_path):
26-
self.logger.debug("File '{}' does not exist! Trying to create one.".format(database_path))
27-
try:
28-
self.create_database(database_path)
29-
except Exception:
30-
self.logger.error("An error has occurred while creating the database!")
36+
self.connection = sqlite3.connect(database_path)
37+
self.connection.row_factory = sqlite3.Row
38+
self.connection.text_factory = lambda x: str(x, 'utf-8', "ignore")
39+
self.cursor = self.connection.cursor()
3140

32-
self.connection = sqlite3.connect(database_path)
33-
self.connection.text_factory = lambda x: str(x, 'utf-8', "ignore")
34-
self.cursor = self.connection.cursor()
41+
self.load_banned_users()
3542

36-
self._initialized = True
43+
self._initialized = True
3744

3845
@staticmethod
3946
def create_database(database_path):
@@ -63,6 +70,7 @@ def create_database(database_path):
6370
"'games_won' INTEGER DEFAULT 0,"
6471
"'games_tie' INTEGER DEFAULT 0,"
6572
"'last_played' INTEGER DEFAULT 0,"
73+
"'banned' INTEGER DEFAULT 0,"
6674
"PRIMARY KEY('user_id'));")
6775

6876
cursor.execute("CREATE TABLE IF NOT EXISTS 'chats'"
@@ -72,15 +80,49 @@ def create_database(database_path):
7280
connection.commit()
7381
connection.close()
7482

83+
def load_banned_users(self):
84+
"""Loads all banned users from the database into a list"""
85+
self.cursor.execute("SELECT user_id FROM users WHERE banned=1;")
86+
result = self.cursor.fetchall()
87+
88+
if not result:
89+
return
90+
91+
for row in result:
92+
print(int(row["user_id"]))
93+
self._banned_users.add(int(row["user_id"]))
94+
95+
def get_banned_users(self):
96+
"""Returns a list of all banned user_ids"""
97+
return self._banned_users
98+
7599
def get_user(self, user_id):
76-
self.cursor.execute("SELECT user_id, first_name, last_name, username, games_played, games_won, games_tie, last_played"
100+
self.cursor.execute("SELECT user_id, first_name, last_name, username, games_played, games_won, games_tie, last_played, banned"
77101
" FROM users WHERE user_id=?;", [str(user_id)])
78102

79103
result = self.cursor.fetchone()
80104
if not result or len(result) == 0:
81105
return None
82106
return result
83107

108+
def is_user_banned(self, user_id):
109+
"""Checks if a user was banned by the admin of the bot from using it"""
110+
# user = self.get_user(user_id)
111+
# return user is not None and user[8] == 1
112+
return int(user_id) in self._banned_users
113+
114+
def ban_user(self, user_id):
115+
"""Bans a user from using a the bot"""
116+
self.cursor.execute("UPDATE users SET banned=1 WHERE user_id=?;", [str(user_id)])
117+
self.connection.commit()
118+
self._banned_users.add(int(user_id))
119+
120+
def unban_user(self, user_id):
121+
"""Unbans a user from using a the bot"""
122+
self.cursor.execute("UPDATE users SET banned=0 WHERE user_id=?;", [str(user_id)])
123+
self.connection.commit()
124+
self._banned_users.remove(int(user_id))
125+
84126
def get_recent_players(self):
85127
one_day_in_secs = 60 * 60 * 24
86128
current_time = int(time())
@@ -141,7 +183,7 @@ def add_user(self, user_id, lang_id, first_name, last_name, username):
141183

142184
def _add_user(self, user_id, lang_id, first_name, last_name, username):
143185
try:
144-
self.cursor.execute("INSERT INTO users VALUES (?, ?, ?, ?, 0, 0, 0, 0);", [str(user_id), first_name, last_name, username])
186+
self.cursor.execute("INSERT INTO users VALUES (?, ?, ?, ?, 0, 0, 0, 0, 0);", [str(user_id), first_name, last_name, username])
145187
self.cursor.execute("INSERT INTO chats VALUES (?, ?);", [str(user_id), lang_id])
146188
self.connection.commit()
147189
except sqlite3.IntegrityError:

util/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# -*- coding: utf-8 -*-
2+
from .bannedusercallback import banned_user_callback
3+
from .banneduserhandler import BannedUserHandler
24
from .cache import Cache
35

4-
__all__ = ['Cache']
6+
__all__ = ["Cache", "BannedUserHandler", "banned_user_callback"]

util/bannedusercallback.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# -*- coding: utf-8 -*-
2+
3+
def banned_user_callback(update, context):
4+
"""Gets called by the dispatcher when it's found that the user sending the update was banned from using the bot"""
5+
banned_text = "You have been banned from using this bot!"
6+
7+
if update.callback_query:
8+
update.callback_query.answer(banned_text)
9+
else:
10+
update.effective_message.reply_text(banned_text)

util/banneduserhandler.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: utf-8 -*-
2+
from telegram.ext import TypeHandler
3+
4+
import database
5+
6+
7+
class BannedUserHandler(TypeHandler):
8+
9+
def check_update(self, update):
10+
db = database.Database()
11+
if db.is_user_banned(update.effective_user.id):
12+
return True
13+
return False

0 commit comments

Comments
 (0)