Browse Source

If a user is a member of a chat, but not a member of the corresponding community, suggest it

master
Lev 2 years ago
parent
commit
cb89542809
  1. 16
      bot.py
  2. 7
      main.py
  3. 10
      templates.txt
  4. 17
      user.py
  5. 32
      views.py

16
bot.py

@ -205,6 +205,21 @@ class Bot(telebot.TeleBot):
self.poll_user_for_community(user, community) self.poll_user_for_community(user, community)
self.save_community(community) self.save_community(community)
def run_suggestions(self):
for user in self.iter_users():
found_communities = False
try:
for community in self.iter_communities():
if user.check_chat(community.chat_id, self):
self.send_template(user.user_id, 'community_suggest', community=community)
found_communities = True
except KeyboardInterrupt as e:
raise e
except Exception:
print(f'An exception occured in suggestions: {traceback.format_exc()}')
if found_communities:
self.save_user(user)
def send_meeting_info_in_community(self, community: Community): def send_meeting_info_in_community(self, community: Community):
for meeting in community.scheduled_meetings: for meeting in community.scheduled_meetings:
person_1, person_2 = self.get_chat(meeting[0]), self.get_chat(meeting[1]) person_1, person_2 = self.get_chat(meeting[0]), self.get_chat(meeting[1])
@ -240,6 +255,7 @@ class Bot(telebot.TeleBot):
raise e raise e
except Exception: except Exception:
print(f'An exception occurred while iterating through communities: {traceback.format_exc()}') print(f'An exception occurred while iterating through communities: {traceback.format_exc()}')
Thread(target=self.run_suggestions).start()
time.sleep(60) time.sleep(60)
def register_next_step_handler(self, message, callback, *args, **kwargs): def register_next_step_handler(self, message, callback, *args, **kwargs):

7
main.py

@ -2,12 +2,13 @@ from bot import Bot
from views import views from views import views
from threading import Thread from threading import Thread
import traceback import traceback
import os
config = { config = {
'mongo': __import__('os').getenv('DB'), 'mongo': os.getenv('DB'),
'name': 'ranteabot', 'name': 'ranteabot' if not os.getenv('DEBUG') else 'flazhokbot',
'token': __import__('os').getenv('TOKEN'), 'token': os.getenv('TOKEN'),
'template_files': ['templates.txt'], 'template_files': ['templates.txt'],
'main_keyboard': {'en': [[' About']], 'ru': [[' О боте']]} 'main_keyboard': {'en': [[' About']], 'ru': [[' О боте']]}
} }

10
templates.txt

@ -81,6 +81,16 @@ You have already requested a meeting in the community <b>{{ community.name }}</b
//| ru |// //| ru |//
Вы уже запрашивали встречу в сообществе <b>{{ community.name }}</b> недавно. Вы сможете запросить еще одну встречу через несколько дней. Вы уже запрашивали встречу в сообществе <b>{{ community.name }}</b> недавно. Вы сможете запросить еще одну встречу через несколько дней.
||<| community_suggest |>||
//| en |//
You are a member of the chat {{ community.name }}. Do you want to add this community in the bot and participate in meetings?
>>| Yes :-: community_add_{{ community.chat_id }} |<<
>>| No :-: dismiss |<<
//| ru |//
Вы являетесь участником чата {{ community.name }}. Хотите добавить его как сообщество в бота и присоединиться к встречам?
>>| Да :-: community_add_{{ community.chat_id }} |<<
>>| Нет :-: dismiss |<<
||<| canceled |>|| ||<| canceled |>||
//| en |// //| en |//
Canceled Canceled

17
user.py

@ -3,6 +3,7 @@ from dataclasses import dataclass, field, asdict
import typing import typing
import time import time
from community import Community from community import Community
from telebot.types import ChatMember
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from bot import Bot from bot import Bot
@ -15,6 +16,20 @@ class User:
locale: str = '' locale: str = ''
start_timestamp: int = field(default_factory=lambda: int(time.time())) start_timestamp: int = field(default_factory=lambda: int(time.time()))
last_action_timestamp: int = field(default_factory=lambda: int(time.time())) last_action_timestamp: int = field(default_factory=lambda: int(time.time()))
# Store the chats which were checked
# (so that we send a message for communities
# where the user is a member of the chat but not a member of the RT community)
checked_chats: typing.List[int] = field(default_factory=list)
def check_chat(self, chat_id: int, bot: Bot) -> bool:
"""
Check if the user should be notified of this chat
"""
if chat_id in self.checked_chats:
return False
self.checked_chats.append(chat_id)
chat_member_info: ChatMember = bot.get_chat_member(chat_id, self.user_id)
return chat_member_info.is_member or chat_member_info.status in ['creator', 'administrator', 'admin', 'member']
def dict(self) -> dict: def dict(self) -> dict:
data = asdict(self) data = asdict(self)
@ -25,7 +40,7 @@ class User:
def from_dict(cls, data: dict) -> User: def from_dict(cls, data: dict) -> User:
data = getattr(data, '__dict__', data) data = getattr(data, '__dict__', data)
data_ = {key: data[key] for key in data.keys() if data_ = {key: data[key] for key in data.keys() if
key in ['user_id', 'chat_id', 'locale', 'start_timestamp', 'last_action_timestamp']} key in ['user_id', 'chat_id', 'locale', 'start_timestamp', 'last_action_timestamp', 'checked_chats']}
self = cls(**data_) self = cls(**data_)
return self return self

32
views.py

@ -1,4 +1,5 @@
from datetime import date from datetime import date
from telebot.types import CallbackQuery, Message
from bot import Bot from bot import Bot
from community import Community from community import Community
@ -6,7 +7,7 @@ from community import Community
def views(bot: Bot): def views(bot: Bot):
@bot.handle_commands(['/start']) @bot.handle_commands(['/start'])
def handle_start(msg, user, args): def handle_start(msg: Message, user, args):
if msg.chat.type in 'supergroup': if msg.chat.type in 'supergroup':
bot.reply_with_template(msg, 'welcome', community=Community.by_id(msg.chat.id, bot)) bot.reply_with_template(msg, 'welcome', community=Community.by_id(msg.chat.id, bot))
return return
@ -20,6 +21,7 @@ def views(bot: Bot):
bot.poll_user_for_community(user, community) bot.poll_user_for_community(user, community)
else: else:
bot.reply_with_template(msg, 'err_not_a_member', community=community) bot.reply_with_template(msg, 'err_not_a_member', community=community)
bot.save_community(community)
bot.reply_with_template(msg, 'info', start=True) bot.reply_with_template(msg, 'info', start=True)
@bot.handle_commands(['/help', ' About', ' О боте']) @bot.handle_commands(['/help', ' About', ' О боте'])
@ -27,7 +29,7 @@ def views(bot: Bot):
bot.reply_with_template(msg, 'info', start=False) bot.reply_with_template(msg, 'info', start=False)
@bot.handle_commands(['/request', '📝 Request a meeting', '📝 Запросить встречу']) @bot.handle_commands(['/request', '📝 Request a meeting', '📝 Запросить встречу'])
def request_meeting(msg, user, _args): def request_meeting(msg: Message, user, _args):
if msg.chat.type != 'private': if msg.chat.type != 'private':
bot.reply_with_template(msg, 'err_not_private') bot.reply_with_template(msg, 'err_not_private')
return return
@ -35,7 +37,7 @@ def views(bot: Bot):
bot.reply_with_template(msg, 'request_meeting', comm_list=comm_ids_and_names) bot.reply_with_template(msg, 'request_meeting', comm_list=comm_ids_and_names)
@bot.handle_commands(['/join']) @bot.handle_commands(['/join'])
def join_community(msg, user, args): def join_community(msg: Message, user, args):
# check if it really is a community # check if it really is a community
if msg.chat.type == 'private': if msg.chat.type == 'private':
bot.reply_with_template(msg, 'err_not_community') bot.reply_with_template(msg, 'err_not_community')
@ -45,15 +47,31 @@ def views(bot: Bot):
bot.reply_with_template(msg, 'welcome', community=community, join=True) bot.reply_with_template(msg, 'welcome', community=community, join=True)
@bot.handle_callback('request_meeting') @bot.handle_callback('request_meeting')
def request_meeting_callback(msg, user, args): def request_meeting_callback(query: CallbackQuery, user, args):
community = Community.by_id(int(args), bot) community = Community.by_id(int(args), bot)
if community.can_user_request_a_meeting(user.user_id): if community.can_user_request_a_meeting(user.user_id):
community.polled[user.user_id] = date.today() community.polled[user.user_id] = date.today()
community.pool.append(user.user_id) community.pool.append(user.user_id)
bot.reply_with_template(msg, 'request_meeting_success', community=community) bot.reply_with_template(query, 'request_meeting_success', community=community)
else: else:
bot.reply_with_template(msg, 'request_meeting_failure', community=community) bot.reply_with_template(query, 'request_meeting_failure', community=community)
bot.answer_callback_query(msg.id) bot.answer_callback_query(query.id)
@bot.handle_callback('dismiss')
def dismiss_callback(query: CallbackQuery, user, _args):
bot.answer_callback_query(query.id, {'en': 'Ok, fine', 'ru': 'ладно'}.get(user.locale, 'Ok'))
bot.delete_message(query.message.chat.id, query.message.message_id)
@bot.handle_callback('community_add')
def community_add_callback(query: CallbackQuery, user, args):
community = Community.by_id(int(args), bot)
if user.user_id in community.members:
bot.reply_with_template(query, 'community_added', community=community, already_member=True)
elif community.add_member(user.user_id, bot):
bot.reply_with_template(query, 'community_added', community=community, already_member=False)
bot.poll_user_for_community(user, community)
bot.answer_callback_query(query.id)
bot.save_community(community)
@bot.handle_commands(['/send_all']) @bot.handle_commands(['/send_all'])
def send_spam(msg, user, _args): def send_spam(msg, user, _args):

Loading…
Cancel
Save