second one
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
config.py
|
||||
*.pyc
|
||||
**/__pycache__
|
||||
**/.state-save
|
||||
168
bot/app/bot.py
168
bot/app/bot.py
@ -35,22 +35,18 @@ session: Session = None
|
||||
class States(StatesGroup):
|
||||
default = State()
|
||||
newfund_amount = State()
|
||||
close_fund = State()
|
||||
|
||||
|
||||
# Utils
|
||||
|
||||
|
||||
def get_fund_text(fund: Fund):
|
||||
count = len(fund.members)
|
||||
contributors = len(list(filter(lambda m: m.contributed, fund.members)))
|
||||
count = fund.members.count()
|
||||
contributors = fund.members.filter(FundMember.contributed).count()
|
||||
personal_amount = math.ceil(fund.amount / count)
|
||||
return (
|
||||
"🟢 {name}\n\n",
|
||||
"💵 Сумма: {amount}р\n\n",
|
||||
"<b>Каждый скидывает по {personal_amount}</b>\n",
|
||||
"Уже собрано: {collected_amount}\n\n",
|
||||
"👥 Скинули: {contributors}/{count} чел.",
|
||||
).format(
|
||||
return textbook.fund.format(
|
||||
active="🟢" if fund.active else "🔴",
|
||||
name=fund.name,
|
||||
amount=fund.amount,
|
||||
personal_amount=personal_amount,
|
||||
@ -74,7 +70,7 @@ def get_user(tg_user: TgUser) -> User:
|
||||
|
||||
|
||||
def get_group(tg_chat: TgChat) -> Group:
|
||||
if group := session.query(User).filter(User.id == tg_chat.id).first():
|
||||
if group := session.query(Group).filter(Group.id == tg_chat.id).first():
|
||||
return group
|
||||
group = Group(
|
||||
id=tg_chat.id,
|
||||
@ -86,6 +82,7 @@ def get_group(tg_chat: TgChat) -> Group:
|
||||
|
||||
# Bot logic
|
||||
|
||||
|
||||
@bot.message_handler(commands=["start"])
|
||||
async def start(msg: Message):
|
||||
if msg.chat.type == "private":
|
||||
@ -103,7 +100,10 @@ async def start(msg: Message):
|
||||
# session.add(user)
|
||||
# session.commit()
|
||||
user = get_user(msg.from_user)
|
||||
await bot.send_message(chat_id=msg.chat.id, text=textbook.start_private.format(count=len(user.fund_members)))
|
||||
await bot.send_message(
|
||||
chat_id=msg.chat.id,
|
||||
text=textbook.start_private.format(count=user.fund_members.count()),
|
||||
)
|
||||
|
||||
elif msg.chat.type in ("group", "supergroup"):
|
||||
get_group(msg.chat)
|
||||
@ -122,7 +122,7 @@ async def setup(msg: Message):
|
||||
@bot.callback_query_handler(func=lambda c: c.data == "register_group_member")
|
||||
async def register_group_member(call: types.CallbackQuery):
|
||||
new = False
|
||||
user = get_user(call.from_user.id)
|
||||
get_user(call.from_user)
|
||||
if (
|
||||
group_member := session.query(GroupMember)
|
||||
.filter(
|
||||
@ -150,10 +150,11 @@ async def register_group_member(call: types.CallbackQuery):
|
||||
@bot.message_handler(commands=["newfund"])
|
||||
async def newfund(msg: Message):
|
||||
if msg.chat.type in ("group", "supergroup"):
|
||||
if session.query(Group).filter(Group.id == msg.chat.id).first():
|
||||
if group := get_group(msg.chat):
|
||||
if group.group_members.count():
|
||||
if (
|
||||
session.query(Fund)
|
||||
.filter(Fund.group_id == msg.chat.id, Fund.active == True)
|
||||
.filter(Fund.group_id == msg.chat.id, Fund.active)
|
||||
.first()
|
||||
):
|
||||
await bot.send_message(
|
||||
@ -169,14 +170,15 @@ async def newfund(msg: Message):
|
||||
await bot.send_message(
|
||||
chat_id=msg.chat.id,
|
||||
text=textbook.newfund_amount.format(
|
||||
user=user_link(msg.from_user)),
|
||||
user=user_link(msg.from_user)
|
||||
),
|
||||
reply_markup=keyboards.cancel(),
|
||||
parse_mode="html",
|
||||
)
|
||||
else:
|
||||
await bot.send_message(
|
||||
chat_id=msg.chat.id,
|
||||
text=textbook.not_initialized
|
||||
text=textbook.not_set_up,
|
||||
)
|
||||
|
||||
|
||||
@ -187,6 +189,7 @@ async def cancel_newfund_amount(call: types.CallbackQuery):
|
||||
await bot.set_state(
|
||||
user_id=call.from_user.id, chat_id=call.message.chat.id, state=States.default
|
||||
)
|
||||
await bot.delete_message(chat_id=call.message.chat.id, message_id=call.message.id)
|
||||
await bot.answer_callback_query(
|
||||
callback_query_id=call.id,
|
||||
text=textbook.cancel,
|
||||
@ -208,15 +211,13 @@ async def newfund_amount(msg: Message):
|
||||
user_id=msg.from_user.id, chat_id=msg.chat.id, state=States.default
|
||||
)
|
||||
fund = Fund(
|
||||
owner_id=msg.from_user.id, group_id=msg.chat.id, amount=int(
|
||||
msg.text)
|
||||
owner_id=msg.from_user.id, group_id=msg.chat.id, amount=int(msg.text)
|
||||
)
|
||||
session.add(fund)
|
||||
for group_member in session.query(GroupMember).filter(
|
||||
GroupMember.group_id == msg.chat.id
|
||||
):
|
||||
fund_member = FundMember(
|
||||
user_id=group_member.user.id, fund_id=fund.id)
|
||||
fund_member = FundMember(user_id=group_member.user.id, fund_id=fund.id)
|
||||
session.add(fund_member)
|
||||
session.commit()
|
||||
await bot.send_message(
|
||||
@ -228,6 +229,7 @@ async def newfund_amount(msg: Message):
|
||||
chat_id=msg.chat.id,
|
||||
text=get_fund_text(fund),
|
||||
reply_markup=keyboards.fund_markup(),
|
||||
parse_mode="html",
|
||||
)
|
||||
|
||||
else:
|
||||
@ -241,6 +243,132 @@ async def newfund_amount(msg: Message):
|
||||
|
||||
@bot.message_handler(commands=["fund"])
|
||||
async def fund(msg: Message):
|
||||
if msg.chat.type in ("group", "supergroup"):
|
||||
group = get_group(msg.chat)
|
||||
if (
|
||||
fund := session.query(Fund)
|
||||
.filter(Fund.group_id == group.id, Fund.active == True)
|
||||
.first()
|
||||
):
|
||||
await bot.send_message(
|
||||
chat_id=msg.chat.id,
|
||||
text=get_fund_text(fund),
|
||||
reply_markup=keyboards.fund_markup(),
|
||||
parse_mode="html",
|
||||
)
|
||||
else:
|
||||
await bot.send_message(
|
||||
chat_id=msg.chat.id,
|
||||
text=textbook.fund_not_found,
|
||||
)
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=lambda c: c.data == "close_fund")
|
||||
async def close_fund_prompt(call: types.CallbackQuery):
|
||||
if group := get_group(call.message.chat):
|
||||
if fund := group.funds.filter(Fund.active).first():
|
||||
if call.from_user.id == fund.owner_id:
|
||||
await bot.edit_message_text(
|
||||
text=textbook.close_fund_prompt,
|
||||
chat_id=call.message.chat.id,
|
||||
message_id=call.message.id,
|
||||
reply_markup=keyboards.yes_no(),
|
||||
parse_mode="html",
|
||||
)
|
||||
await bot.set_state(
|
||||
user_id=call.from_user.id,
|
||||
chat_id=call.message.chat.id,
|
||||
state=States.close_fund,
|
||||
)
|
||||
else:
|
||||
await bot.answer_callback_query(
|
||||
callback_query_id=call.id,
|
||||
text=textbook.not_owner.format(owner_name=fund.owner.name),
|
||||
)
|
||||
else:
|
||||
await bot.send_message(
|
||||
chat_id=call.message.chat.id,
|
||||
text=textbook.fund_not_found,
|
||||
)
|
||||
|
||||
|
||||
@bot.callback_query_handler(
|
||||
func=lambda c: c.data in ("yes", "no"), state=States.close_fund
|
||||
)
|
||||
async def close_fund(call: types.CallbackQuery):
|
||||
if group := get_group(call.message.chat):
|
||||
if fund := group.funds.filter(Fund.active).first():
|
||||
if call.from_user.id == fund.owner_id:
|
||||
if call.data == "yes":
|
||||
setattr(fund, "active", False)
|
||||
session.commit()
|
||||
await bot.edit_message_text(
|
||||
text=textbook.fund_closed.format(
|
||||
name=fund.name, fund_text=get_fund_text(fund)
|
||||
),
|
||||
chat_id=call.message.chat.id,
|
||||
message_id=call.message.id,
|
||||
parse_mode="html",
|
||||
)
|
||||
elif call.data == "no":
|
||||
await bot.edit_message_text(
|
||||
text=get_fund_text(fund),
|
||||
chat_id=call.message.chat.id,
|
||||
message_id=call.message.id,
|
||||
reply_markup=keyboards.fund_markup(),
|
||||
parse_mode="html",
|
||||
)
|
||||
else:
|
||||
await bot.answer_callback_query(
|
||||
callback_query_id=call.id,
|
||||
text=textbook.not_owner.format(owner_name=fund.owner.name),
|
||||
)
|
||||
else:
|
||||
await bot.send_message(
|
||||
chat_id=call.message.chat.id,
|
||||
text=textbook.fund_not_found,
|
||||
)
|
||||
|
||||
|
||||
@bot.callback_query_handler(func=lambda c: c.data == "contributed")
|
||||
async def contributed(call: types.CallbackQuery):
|
||||
group = get_group(call.message.chat)
|
||||
user = get_user(call.from_user)
|
||||
if fund := group.funds.filter(Fund.active).first():
|
||||
if fund_user := fund.members.filter(
|
||||
FundMember.user_id == call.from_user.id
|
||||
).first():
|
||||
if not fund_user.contributed:
|
||||
setattr(fund_user, "contributed", True)
|
||||
session.commit()
|
||||
await bot.answer_callback_query(
|
||||
callback_query_id=call.id,
|
||||
text=textbook.contributed,
|
||||
)
|
||||
await bot.edit_message_text(
|
||||
text=get_fund_text(fund),
|
||||
chat_id=call.message.chat.id,
|
||||
message_id=call.message.id,
|
||||
reply_markup=keyboards.fund_markup(),
|
||||
parse_mode="html",
|
||||
)
|
||||
else:
|
||||
await bot.answer_callback_query(
|
||||
callback_query_id=call.id,
|
||||
text=textbook.already_contributed,
|
||||
show_alert=True,
|
||||
)
|
||||
|
||||
else:
|
||||
await bot.answer_callback_query(
|
||||
callback_query_id=call.id,
|
||||
text=textbook.not_fund_member,
|
||||
show_alert=True,
|
||||
)
|
||||
else:
|
||||
await bot.answer_callback_query(
|
||||
callback_query_id=call.id, text=textbook.fund_not_found, show_alert=True
|
||||
)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["mystate"])
|
||||
|
||||
@ -16,9 +16,9 @@ class User(Base):
|
||||
name = Column(String(64))
|
||||
username = Column(String(32))
|
||||
|
||||
owns_funds = relationship("Fund", backref="owner")
|
||||
fund_members = relationship("FundMember", backref="user")
|
||||
group_members = relationship("GroupMember", backref="user")
|
||||
owns_funds = relationship("Fund", backref="owner", lazy="dynamic")
|
||||
fund_members = relationship("FundMember", backref="user", lazy="dynamic")
|
||||
group_members = relationship("GroupMember", backref="user", lazy="dynamic")
|
||||
|
||||
|
||||
class Group(Base):
|
||||
@ -26,9 +26,9 @@ class Group(Base):
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
|
||||
funds = relationship("Fund", backref="group")
|
||||
funds = relationship("Fund", backref="group", lazy="dynamic")
|
||||
|
||||
group_members = relationship("GroupMember", backref="group")
|
||||
group_members = relationship("GroupMember", backref="group", lazy="dynamic")
|
||||
|
||||
|
||||
class GroupMember(Base):
|
||||
@ -52,7 +52,7 @@ class Fund(Base):
|
||||
amount = Column(Integer)
|
||||
active = Column(Boolean, default=True)
|
||||
|
||||
members = relationship("FundMember", backref="fund")
|
||||
members = relationship("FundMember", backref="fund", lazy="dynamic")
|
||||
|
||||
|
||||
class FundMember(Base):
|
||||
|
||||
@ -23,6 +23,16 @@ def cancel() -> keyboard:
|
||||
def fund_markup() -> keyboard:
|
||||
return keyboard(
|
||||
keyboard=[
|
||||
[button(text="✅ Я скинул", callback_data="contributed")],
|
||||
[button(text="🏁 Завершить сбор", callback_data="close_fund")],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def yes_no() -> keyboard:
|
||||
return keyboard(
|
||||
keyboard=[
|
||||
[button(text="✅ Да", callback_data="yes")],
|
||||
[button(text="❌ Нет", callback_data="no")],
|
||||
]
|
||||
)
|
||||
|
||||
@ -15,3 +15,15 @@ not_number = 'Вы ввели не число. {user}, напишите сумм
|
||||
fund_created = "Создан новый сбор: {fund}"
|
||||
|
||||
fund_not_found = "На данный момент в этом чате сборов нет! Создать новый - /newfund"
|
||||
|
||||
|
||||
fund = "{active} {name}\n\n💵 Сумма: {amount}р\n\n<b>Каждый скидывает по {personal_amount}р</b>\nУже собрано: {collected_amount}р\n👥 Скинули: {contributors}/{count} чел."
|
||||
|
||||
close_fund_prompt = "Вы уверены? Это завершит <b>активный в данный момент сбор</b>!"
|
||||
fund_closed = 'Сбор "<b>{name}</b>" закрыт! Вот его данные:\n\n{fund_text}'
|
||||
not_owner = "Вы не являетесь создателем этого сбора, обратитесь к {owner_name}, если хотите его закрыть"
|
||||
not_set_up = "В группе меценатов нет ни одного участника! Вы точно прописывали /setup и все желающие участвовать в сборах приняли участие?"
|
||||
not_fund_member = "Вы не являетесь участником этого сбора! Пропишите /setup и попросите создать новый сбор!"
|
||||
|
||||
contributed = "Вы отметились!"
|
||||
already_contributed = "Вы уже отмечались ранее. Не забудьте уведомить создателя сбора, если вы решили отказаться от участия!"
|
||||
|
||||
@ -23,6 +23,8 @@ services:
|
||||
DB_NAME: db
|
||||
HOST: postgres
|
||||
PORT: 5432
|
||||
volumes:
|
||||
- ./.state-save:/app/.state-save/:rw
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
Reference in New Issue
Block a user