Skip to content

Commit efd6601

Browse files
konardclaude
andcommitted
Implement censored words rating system for issue #13
- Add CENSORED_WORDS list in config.py with Russian and English profanity - Add censored_words_rating property to user data model - Implement process_censored_words_rating() method with logic: * +1 for clean messages (no censored words) * -1 for each censored word found - Add 'рейтинг'/'rating' command to display user's censored words rating - Process all messages (commands and regular messages) for rating - Add comprehensive tests for the new functionality - Use regex word boundaries to avoid partial matches 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent f05dc4f commit efd6601

File tree

6 files changed

+112
-0
lines changed

6 files changed

+112
-0
lines changed

python/__main__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def __init__(
5252
(patterns.REMOVE_GITHUB_PROFILE,
5353
lambda: self.commands.change_github_profile(False)),
5454
(patterns.KARMA, self.commands.karma_message),
55+
(patterns.CENSORED_WORDS_RATING, self.commands.censored_words_rating_message),
5556
(patterns.TOP, self.commands.top),
5657
(patterns.PEOPLE, self.commands.top),
5758
(patterns.BOTTOM,

python/config.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,13 @@
155155

156156
DEFAULT_PROGRAMMING_LANGUAGES_PATTERN_STRING = "|".join(DEFAULT_PROGRAMMING_LANGUAGES)
157157
GITHUB_COPILOT_LANGUAGES_PATTERN_STRING = "|".join([i for i in GITHUB_COPILOT_LANGUAGES.keys()])
158+
159+
# Censored words for rating system
160+
CENSORED_WORDS = [
161+
"блядь", "бляд", "сука", "хуй", "пизда", "ебать", "ебаный", "хуйня", "сраный",
162+
"говно", "дерьмо", "дебил", "идиот", "урод", "тупой", "долбоеб", "мудак",
163+
"ублюдок", "гнида", "сволочь", "падла", "засранец", "говнюк", "пидор",
164+
# English words
165+
"fuck", "fucking", "shit", "bitch", "asshole", "damn", "crap", "bastard",
166+
"stupid", "idiot", "moron", "dickhead", "motherfucker", "bullshit"
167+
]

python/modules/commands.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,26 @@ def karma_message(self) -> NoReturn:
119119
self.vk_instance.send_msg(
120120
CommandsBuilder.build_karma(self.user, self.data_service, is_self),
121121
self.peer_id)
122+
123+
def censored_words_rating_message(self) -> NoReturn:
124+
"""Shows user's censored words rating."""
125+
is_self = self.user.uid == self.from_id
126+
rating = self.user.censored_words_rating
127+
user_name = self.vk_instance.get_user_name(self.user.uid, "gen")
128+
129+
if is_self:
130+
message = f"Ваш рейтинг использования цензурных слов: {rating}"
131+
else:
132+
message = f"Рейтинг использования цензурных слов у {user_name}: {rating}"
133+
134+
if rating > 0:
135+
message += "\n✅ Превосходно! Вы общаетесь культурно."
136+
elif rating == 0:
137+
message += "\n⚖️ Нейтральный рейтинг."
138+
else:
139+
message += "\n❌ Рекомендуется следить за речью."
140+
141+
self.vk_instance.send_msg(message, self.peer_id)
122142

123143
def top(
124144
self,
@@ -308,6 +328,36 @@ def apply_user_karma(
308328
user.karma = new_karma
309329
return (user.uid, user.name, initial_karma, new_karma)
310330

331+
def process_censored_words_rating(self) -> NoReturn:
332+
"""Process message for censored words and update rating."""
333+
if not self.current_user or self.from_id < 0:
334+
return
335+
336+
# Convert message to lowercase for case-insensitive matching
337+
message_lower = self.msg.lower()
338+
339+
# Count censored words in the message
340+
censored_count = 0
341+
for word in config.CENSORED_WORDS:
342+
# Simple word boundary check to avoid partial matches
343+
import re
344+
pattern = r'\b' + re.escape(word.lower()) + r'\b'
345+
censored_count += len(re.findall(pattern, message_lower))
346+
347+
# Calculate rating change: +1 for clean message, -1 for each censored word
348+
if censored_count == 0:
349+
rating_change = 1 # +1 for clean message
350+
else:
351+
rating_change = -censored_count # -1 for each censored word
352+
353+
# Update user's censored words rating
354+
current_rating = self.current_user.censored_words_rating
355+
new_rating = current_rating + rating_change
356+
self.current_user.censored_words_rating = new_rating
357+
358+
# Save the updated user
359+
self.data_service.save_user(self.current_user)
360+
311361
def what_is(self) -> NoReturn:
312362
"""Search on wikipedia and sends if available"""
313363
question = self.matched.groups()
@@ -435,4 +485,9 @@ def process(
435485
self.match_command(cmd)
436486
if self.matched:
437487
action()
488+
# Process censored words rating for all messages including commands
489+
self.process_censored_words_rating()
438490
return
491+
492+
# Process censored words rating for non-command messages
493+
self.process_censored_words_rating()

python/modules/data_service.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def __init__(self, db_name: str = "users"):
1919
self.base.addPattern("supporters", [])
2020
self.base.addPattern("opponents", [])
2121
self.base.addPattern("karma", 0)
22+
self.base.addPattern("censored_words_rating", 0)
2223

2324
def get_or_create_user(
2425
self,

python/patterns.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
KARMA = recompile(
1919
r'\A\s*(карма|karma)\s*\Z', IGNORECASE)
2020

21+
CENSORED_WORDS_RATING = recompile(
22+
r'\A\s*(рейтинг|rating|цензура|censored)\s*\Z', IGNORECASE)
23+
2124
APPLY_KARMA = recompile(
2225
r'\A(\[id(?<selectedUserId>\d+)\|@\w+\])?\s*(?P<operator>\+|\-)(?P<amount>[0-9]*)\s*\Z')
2326

python/tests.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,48 @@ def test_apply_karma_change(
222222
self.commands.apply_karma_change('-', 6)
223223
self.commands.karma_message()
224224

225+
@ordered
226+
def test_censored_words_rating_clean_message(
227+
self
228+
) -> NoReturn:
229+
"""Test rating for clean message (+1)"""
230+
self.commands.msg = "Hello, this is a clean message"
231+
self.commands.current_user = db.get_user(1)
232+
initial_rating = self.commands.current_user.censored_words_rating
233+
234+
self.commands.process_censored_words_rating()
235+
236+
# Should get +1 for clean message
237+
assert self.commands.current_user.censored_words_rating == initial_rating + 1
238+
239+
@ordered
240+
def test_censored_words_rating_with_censored_words(
241+
self
242+
) -> NoReturn:
243+
"""Test rating for message with censored words (-1 per word)"""
244+
self.commands.msg = "This is stupid shit"
245+
self.commands.current_user = db.get_user(2)
246+
initial_rating = self.commands.current_user.censored_words_rating
247+
248+
self.commands.process_censored_words_rating()
249+
250+
# Should get -2 for two censored words (stupid, shit)
251+
assert self.commands.current_user.censored_words_rating == initial_rating - 2
252+
253+
@ordered
254+
def test_censored_words_rating_message_display(
255+
self
256+
) -> NoReturn:
257+
"""Test censored words rating message display"""
258+
self.commands.user = db.get_user(1)
259+
self.commands.from_id = 1
260+
self.commands.censored_words_rating_message()
261+
262+
# Test for another user
263+
self.commands.user = db.get_user(2)
264+
self.commands.from_id = 1
265+
self.commands.censored_words_rating_message()
266+
225267

226268
if __name__ == '__main__':
227269
db = BetterBotBaseDataService("test_db")

0 commit comments

Comments
 (0)