feat(tg-fitness-bot): /feedback command, feedback SQLite table
Users can send /feedback <text> to record feedback. Stored in a new feedback table with user_id, text, created_at. Updated /start help text. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a529416599
commit
3703d87426
2 changed files with 46 additions and 2 deletions
21
bot.py
21
bot.py
|
|
@ -16,7 +16,7 @@ from telegram.ext import (
|
||||||
filters,
|
filters,
|
||||||
)
|
)
|
||||||
|
|
||||||
from db import init_db, save_workout, get_workouts, get_workout_count, get_stats_sql, delete_workout
|
from db import init_db, save_workout, get_workouts, get_workout_count, get_stats_sql, delete_workout, save_feedback
|
||||||
from parser import parse_workout, format_workout
|
from parser import parse_workout, format_workout
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
@ -93,7 +93,8 @@ async def cmd_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
"/history \u2014 view recent workouts\n"
|
"/history \u2014 view recent workouts\n"
|
||||||
"/stats \u2014 quick summary\n"
|
"/stats \u2014 quick summary\n"
|
||||||
"/delete <id> \u2014 delete a workout\n"
|
"/delete <id> \u2014 delete a workout\n"
|
||||||
"/export \u2014 export all data as JSON"
|
"/export \u2014 export all data as JSON\n"
|
||||||
|
"/feedback <text> \u2014 send feedback"
|
||||||
)
|
)
|
||||||
|
|
||||||
if WEBAPP_URL:
|
if WEBAPP_URL:
|
||||||
|
|
@ -197,6 +198,21 @@ async def cmd_export(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def cmd_feedback(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
user_id = update.effective_user.id
|
||||||
|
text = " ".join(context.args) if context.args else ""
|
||||||
|
|
||||||
|
if not text:
|
||||||
|
await update.message.reply_text(
|
||||||
|
"Usage: /feedback <your feedback>",
|
||||||
|
parse_mode=ParseMode.HTML,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
save_feedback(user_id, text)
|
||||||
|
await update.message.reply_text("\U0001f4dd Feedback saved, thanks!")
|
||||||
|
|
||||||
|
|
||||||
# ── Message handler (workout parsing) ───────────────────────────────────────
|
# ── Message handler (workout parsing) ───────────────────────────────────────
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -290,6 +306,7 @@ def main():
|
||||||
app.add_handler(CommandHandler("stats", cmd_stats))
|
app.add_handler(CommandHandler("stats", cmd_stats))
|
||||||
app.add_handler(CommandHandler("delete", cmd_delete))
|
app.add_handler(CommandHandler("delete", cmd_delete))
|
||||||
app.add_handler(CommandHandler("export", cmd_export))
|
app.add_handler(CommandHandler("export", cmd_export))
|
||||||
|
app.add_handler(CommandHandler("feedback", cmd_feedback))
|
||||||
|
|
||||||
# Handle all text messages (including forwarded ones)
|
# Handle all text messages (including forwarded ones)
|
||||||
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
|
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
|
||||||
|
|
|
||||||
27
db.py
27
db.py
|
|
@ -60,6 +60,13 @@ def init_db():
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_workouts_user
|
CREATE INDEX IF NOT EXISTS idx_workouts_user
|
||||||
ON workouts(user_id, timestamp);
|
ON workouts(user_id, timestamp);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS feedback (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
text TEXT NOT NULL,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# Migrations
|
# Migrations
|
||||||
|
|
@ -246,3 +253,23 @@ def export_workouts(user_id: int) -> list[dict]:
|
||||||
""", (user_id,)).fetchall()
|
""", (user_id,)).fetchall()
|
||||||
|
|
||||||
return [dict(r) for r in rows]
|
return [dict(r) for r in rows]
|
||||||
|
|
||||||
|
|
||||||
|
def save_feedback(user_id: int, text: str) -> int:
|
||||||
|
"""Save user feedback. Returns the feedback id."""
|
||||||
|
with get_db() as conn:
|
||||||
|
cur = conn.execute(
|
||||||
|
"INSERT INTO feedback (user_id, text) VALUES (?, ?)",
|
||||||
|
(user_id, text),
|
||||||
|
)
|
||||||
|
return cur.lastrowid
|
||||||
|
|
||||||
|
|
||||||
|
def get_feedback(limit: int = 50) -> list[dict]:
|
||||||
|
"""Get all feedback, newest first."""
|
||||||
|
with get_db() as conn:
|
||||||
|
rows = conn.execute(
|
||||||
|
"SELECT id, user_id, text, created_at FROM feedback ORDER BY created_at DESC LIMIT ?",
|
||||||
|
(limit,),
|
||||||
|
).fetchall()
|
||||||
|
return [dict(r) for r in rows]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue