Browse Source

User polling and matching functions

master
Lev 2 years ago
parent
commit
907adc6fd0
  1. 28
      bot.py
  2. 34
      community.py
  3. 10
      templates.txt

28
bot.py

@ -1,3 +1,5 @@
import datetime
import telebot import telebot
import pymongo import pymongo
from functools import wraps from functools import wraps
@ -66,7 +68,8 @@ class Bot(telebot.TeleBot):
as_reply: bool = False, locale_overwrite: typing.Optional[str] = None, **kwargs): as_reply: bool = False, locale_overwrite: typing.Optional[str] = None, **kwargs):
if isinstance(msg, telebot.types.CallbackQuery): if isinstance(msg, telebot.types.CallbackQuery):
msg = msg.message msg = msg.message
text, keyboard = self.render_message_for_user(self.get_user_by_msg(msg), template, user = self.get_user_by_msg(msg)
text, keyboard = self.render_message_for_user(user, template,
tg_user=msg.from_user, locale_overwrite=locale_overwrite, tg_user=msg.from_user, locale_overwrite=locale_overwrite,
**kwargs) **kwargs)
if as_reply: if as_reply:
@ -74,6 +77,14 @@ class Bot(telebot.TeleBot):
else: else:
self.send_message(msg.chat.id, text, reply_markup=keyboard, parse_mode='HTML') self.send_message(msg.chat.id, text, reply_markup=keyboard, parse_mode='HTML')
def send_template(self, user_id: int, template: str, locale_overwrite: typing.Optional[str] = None, **kwargs):
user = User.by_id(user_id, self)
tg_user = self.get_chat(user_id)
text, keyboard = self.render_message_for_user(user, template,
tg_user=tg_user, locale_overwrite=locale_overwrite,
**kwargs)
self.send_message(user_id, text, reply_markup=keyboard, parse_mode='HTML')
def get_user_from_db(self, request: dict) -> typing.Optional[User]: def get_user_from_db(self, request: dict) -> typing.Optional[User]:
data = self.db.users.find_one(request) data = self.db.users.find_one(request)
if data is None: if data is None:
@ -175,6 +186,21 @@ class Bot(telebot.TeleBot):
for user_data in self.db.users.find(): for user_data in self.db.users.find():
yield User.from_dict(user_data) yield User.from_dict(user_data)
def iter_communities(self) -> typing.Iterable[Community]:
for community_data in self.db.communities.find():
yield Community.from_dict(community_data)
def poll_users_in_community(self, community: Community):
for user_id in community.users_to_poll():
user = User.by_id(user_id, self)
if user is None:
continue
def_answer = community.default_answers.get(user_id, True)
self.send_template(user_id, 'poll_user', community=community, def_answer=def_answer)
community.pool += [user_id] * def_answer
community.polled[user_id] = datetime.date.today()
self.save_community(community)
def register_next_step_handler(self, message, callback, *args, **kwargs): def register_next_step_handler(self, message, callback, *args, **kwargs):
if isinstance(message, telebot.types.CallbackQuery): if isinstance(message, telebot.types.CallbackQuery):
message = message.message message = message.message

34
community.py

@ -1,7 +1,8 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass, field, asdict from dataclasses import dataclass, field, asdict
import typing import typing
from datetime import date import random
from datetime import date, timedelta
from telebot.types import ChatMember, Chat from telebot.types import ChatMember, Chat
import time import time
from threading import Thread from threading import Thread
@ -15,10 +16,12 @@ class Community:
chat_id: int # Telegram chat id chat_id: int # Telegram chat id
name: str = '' name: str = ''
members: typing.List[int] = field(default_factory=list) members: typing.List[int] = field(default_factory=list)
pool: typing.List[typing.Tuple[int, int]] = field(default_factory=list) # (user_id, number_of_copies) pool: typing.List[int] = field(default_factory=list) # [user_id]
polled: typing.Dict[int, date] = field(default_factory=dict) # Days since the user was asked
scheduled_meetings: typing.List[typing.Tuple[int, int, date]] = field( scheduled_meetings: typing.List[typing.Tuple[int, int, date]] = field(
default_factory=list) # (user_id_1, user_id_2, meeting date) default_factory=list) # (user_id_1, user_id_2, meeting date)
archived_meetings: typing.List[typing.Tuple[int, int, date]] = field(default_factory=list) archived_meetings: typing.List[typing.Tuple[int, int, date]] = field(default_factory=list)
default_answers: typing.Dict[int, bool] = field(default_factory=dict) # Last answers
start_timestamp: int = field(default_factory=lambda: int(time.time())) start_timestamp: int = field(default_factory=lambda: int(time.time()))
def dict(self) -> dict: def dict(self) -> dict:
@ -29,8 +32,8 @@ class Community:
def from_dict(cls, data: dict) -> Community: def from_dict(cls, data: dict) -> Community:
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 ['chat_id', 'name', 'members', 'pool', 'scheduled_meetings', 'archived_meetings', key in ['chat_id', 'name', 'members', 'pool', 'polled', 'scheduled_meetings',
'start_timestamp']} 'archived_meetings', 'start_timestamp', 'default_answers']}
self = cls(**data_) self = cls(**data_)
return self return self
@ -55,3 +58,26 @@ class Community:
bot.save_community(self) bot.save_community(self)
return True return True
return False return False
def users_to_poll(self) -> typing.List[int]:
return [
user_id for user_id in self.members
if user_id not in self.polled or self.polled[user_id] <= date.today() - timedelta(days=7)
]
def add_answer(self, user_id: int, answer: bool, bot: Bot):
if user_id not in self.users_to_poll():
return
self.pool.remove(user_id)
self.pool += [user_id] * answer
self.default_answers[user_id] = bool(answer)
bot.save_community(self)
def schedule_meetings(self):
random.shuffle(self.pool) # It's called RandomTea for a reason
today = date.today()
while len(self.pool) > 1:
user_id_1 = self.pool.pop()
while (user_id_2 := self.pool.pop()) == user_id_1:
continue
self.scheduled_meetings.append((user_id_1, user_id_2, today))

10
templates.txt

@ -35,6 +35,16 @@ You have joined the community, congrats!
//| ru |// //| ru |//
Вы присоединились к сообществу, хорошего дня! Вы присоединились к сообществу, хорошего дня!
||<| poll_user |>||
//| en |//
Do you want to have any meetings this week{% if community.name %} in the community <b>{{ community.name }}</b>{% endif %}?
>>| {{ "✅" * bool(def_answer) }} Yes :-: meetings_{{ community.chat_id }}_1 |<<
>>| {{ "✅" * (not def_answer) }} No :-: meetings_{{ community.chat_id }}_0 |<<
//| ru |//
Хотите ли вы сходить на встречи на этой неделе{% if community.name %} в сообществе <b>{{ community.name }}</b>{% endif %}?
>>| {{ "✅" * bool(def_answer) }} Да :-: meetings_{{ community.chat_id }}_1 |<<
>>| {{ "✅" * (not def_answer) }} Нет :-: meetings_{{ community.chat_id }}_0 |<<
||<| canceled |>|| ||<| canceled |>||
//| en |// //| en |//
Canceled Canceled

Loading…
Cancel
Save