mirror of
https://github.com/Noettore/lagomareGateKeeperBot.git
synced 2025-10-15 03:26:40 +02:00
Refactor and start implementing inline keyboards
This commit is contained in:
114
bot.py
114
bot.py
@@ -1,5 +1,5 @@
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, CommandHandler, MessageHandler, ContextTypes
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from telegram.ext import Application, CommandHandler, MessageHandler, ContextTypes, CallbackQueryHandler
|
||||
from datetime import datetime
|
||||
from config import BotConfig
|
||||
from gates import Gates
|
||||
@@ -23,7 +23,30 @@ async def updateuser(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
users.update_user(user_id, username, fullname)
|
||||
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
await update.message.reply_text("Welcome to GatekeeperBot! Use `/setcredentials` to configure your access")
|
||||
user_id = str(update.effective_user.id)
|
||||
role = users.get_role(user_id)
|
||||
keyboard = []
|
||||
|
||||
if role == Role.GUEST:
|
||||
# Guests: can request access, or open a gate if granted
|
||||
if users.has_grants(user_id):
|
||||
keyboard.append([InlineKeyboardButton("Open Gate", callback_data="open_gate_menu")])
|
||||
keyboard.append([InlineKeyboardButton("Request Access", callback_data="request_access")])
|
||||
elif role == Role.MEMBER:
|
||||
# Members: can open gates and set credentials
|
||||
keyboard.append([InlineKeyboardButton("Open Gate", callback_data="open_gate_menu")])
|
||||
keyboard.append([InlineKeyboardButton("Set Credentials", callback_data="set_credentials")])
|
||||
elif role == Role.ADMIN:
|
||||
# Admins: can open gates, grant access, and set credentials
|
||||
keyboard.append([InlineKeyboardButton("Open Gate", callback_data="open_gate_menu")])
|
||||
keyboard.append([InlineKeyboardButton("Grant Access", callback_data="grant_access")])
|
||||
keyboard.append([InlineKeyboardButton("Set Credentials", callback_data="set_credentials")])
|
||||
|
||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||
await update.message.reply_text(
|
||||
"Welcome to GatekeeperBot! Use the buttons below or commands.",
|
||||
reply_markup=reply_markup
|
||||
)
|
||||
|
||||
async def setcredentials(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
user_id = str(update.effective_user.id)
|
||||
@@ -31,7 +54,7 @@ async def setcredentials(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
if len(args) != 2:
|
||||
return await update.message.reply_text("Usage: `/setcredentials <username> <password>`")
|
||||
role = users.get_role(user_id)
|
||||
if role not in ("admin", "member"):
|
||||
if role not in (Role.ADMIN, Role.MEMBER):
|
||||
return await update.message.reply_text("Only members or admins can set credentials")
|
||||
if users.set_credentials(user_id, Credential(args[0], args[1])):
|
||||
await update.message.reply_text("Credentials saved")
|
||||
@@ -57,7 +80,7 @@ async def opengate(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
return await update.message.reply_text("No valid grantor available.")
|
||||
if not creds:
|
||||
return await update.message.reply_text("No valid grantor credentials available.")
|
||||
#TODO: update guest last_used_at
|
||||
users.update_grant_last_used(user_id, gate)
|
||||
try:
|
||||
await context.bot.send_message(chat_id=grantor, text=f"Guest {user_id} opened {gate_name}")
|
||||
except Exception as e:
|
||||
@@ -69,10 +92,61 @@ async def opengate(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
return await update.message.reply_text(f"Gate {gate_name} opened!")
|
||||
await update.message.reply_text(f"ERROR: Cannot open gate {gate_name}")
|
||||
|
||||
async def open_gate_menu(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
# Show a list of available gates as buttons
|
||||
keyboard = [
|
||||
[InlineKeyboardButton(gate.name, callback_data=f"opengate_{gate_id}")]
|
||||
for gate_id, gate in gates._gates.items()
|
||||
]
|
||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||
if update.callback_query:
|
||||
await update.callback_query.answer()
|
||||
await update.callback_query.edit_message_text(
|
||||
"Select a gate to open:", reply_markup=reply_markup
|
||||
)
|
||||
else:
|
||||
await update.message.reply_text("Select a gate to open:", reply_markup=reply_markup)
|
||||
|
||||
async def handle_gate_open_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
query = update.callback_query
|
||||
user_id = str(query.from_user.id)
|
||||
data = query.data
|
||||
if data.startswith("opengate_"):
|
||||
gate_id = data[len("opengate_") :]
|
||||
gate_name = gates.get_name(gate_id)
|
||||
role = users.get_role(user_id)
|
||||
if role in (Role.ADMIN, Role.MEMBER):
|
||||
creds = users.get_credentials(user_id)
|
||||
if not creds:
|
||||
await query.answer("Please set your credentials with /setcredentials first", show_alert=True)
|
||||
return
|
||||
elif role == Role.GUEST and users.can_open_gate(user_id, gate_id):
|
||||
grantor = users.get_grantor(user_id, gate_id)
|
||||
creds = users.get_credentials(grantor)
|
||||
if not grantor or not creds:
|
||||
await query.answer("No valid grantor credentials available.", show_alert=True)
|
||||
return
|
||||
users.update_grant_last_used(user_id, gate_id)
|
||||
try:
|
||||
await context.bot.send_message(chat_id=grantor, text=f"Guest {user_id} opened {gate_name}")
|
||||
except Exception as e:
|
||||
print(f"Failed to notify {grantor} that guest {user_id} opened {gate_name}: {e}")
|
||||
else:
|
||||
# TODO: guest not working
|
||||
await query.answer("Access denied.", show_alert=True)
|
||||
return
|
||||
|
||||
if gates.open_gate(gate_id, creds):
|
||||
await query.answer(f"Gate {gate_name} opened!", show_alert=True)
|
||||
await query.edit_message_text(f"Gate {gate_name} opened!")
|
||||
else:
|
||||
await query.answer(f"ERROR: Cannot open gate {gate_name}", show_alert=True)
|
||||
await query.edit_message_text(f"ERROR: Cannot open gate {gate_name}")
|
||||
|
||||
async def requestaccess(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
user_id = str(update.effective_user.id)
|
||||
role = users.get_role(user_id)
|
||||
if role not in ("guest"):
|
||||
if role != Role.GUEST:
|
||||
return await update.message.reply_text("Only guests can request access.")
|
||||
if not context.args:
|
||||
return await update.message.reply_text("Usage: `/requestaccess`", parse_mode="Markdown")
|
||||
@@ -86,21 +160,29 @@ async def requestaccess(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
except Exception as e:
|
||||
print(f"Failed to notify {admin_id} that guest {user_id} requested access: {e}")
|
||||
|
||||
async def approve(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
approver_id = str(update.effective_user.id)
|
||||
if users.get_role(approver_id) != "admin":
|
||||
return await update.message.reply_text("Only admins can approve access.")
|
||||
async def handle_main_menu_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
query = update.callback_query
|
||||
data = query.data
|
||||
if data == "open_gate_menu":
|
||||
await open_gate_menu(update, context)
|
||||
elif data == "request_access":
|
||||
await requestaccess(update, context)
|
||||
|
||||
async def grantaccess(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
grantor_id = str(update.effective_user.id)
|
||||
if users.get_role(grantor_id) != Role.ADMIN:
|
||||
return await update.message.reply_text("Only admins can grant access.")
|
||||
try:
|
||||
user_id = context.args[0]
|
||||
gate = context.args[1]
|
||||
expires_at = context.args[2]
|
||||
users.grant_access(user_id, gate, datetime.fromisoformat(expires_at.replace("Z", "+00:00")), grantor_id=approver_id)
|
||||
await update.message.reply_text(f"Access to {gate} granted to user {user_id}.")
|
||||
users.grant_access(user_id, gate, datetime.fromisoformat(expires_at.replace("Z", "+00:00")), grantor_id=grantor_id)
|
||||
await update.message.reply_text(f"Access to {gate} granted to user {user_id} until {expires_at}")
|
||||
try:
|
||||
await context.bot.send_message(chat_id=user_id, text=f"Access granted to gate {gate} up to {expires_at}")
|
||||
except Exception as e:
|
||||
print(f"Failed to notify {user_id} that admin {approver_id} approved access for {gate} up to {expires_at}: {e}")
|
||||
except:
|
||||
print(f"Failed to notify {user_id} that admin {grantor_id} granted access for {gate} up to {expires_at}: {e}")
|
||||
except Exception:
|
||||
await update.message.reply_text("Usage: `/approve <user_id> <gate|all> <expires_at:YYYY-MM-DDTHH:MM:SSZ>`")
|
||||
|
||||
def main():
|
||||
@@ -110,7 +192,9 @@ def main():
|
||||
app.add_handler(CommandHandler("setcredentials", setcredentials))
|
||||
app.add_handler(CommandHandler("opengate", opengate))
|
||||
app.add_handler(CommandHandler("requestaccess", requestaccess))
|
||||
app.add_handler(CommandHandler("approve", approve))
|
||||
app.add_handler(CommandHandler("grantaccess", grantaccess))
|
||||
app.add_handler(CallbackQueryHandler(handle_main_menu_callback, pattern="^(open_gate_menu|request_access)$"))
|
||||
app.add_handler(CallbackQueryHandler(handle_gate_open_callback, pattern="^opengate_"))
|
||||
app.run_polling()
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
Reference in New Issue
Block a user