summaryrefslogtreecommitdiffstats
path: root/restaurants.py
blob: d501b9b99e282f82fbf943dce5ac9b9d641f8b64 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import sqlite3
import random
import os

DB_PATH = os.path.join(os.path.dirname(__file__), "restaurants.db")

SEED_DATA = [
]


def _get_conn() -> sqlite3.Connection:
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    return conn


def init_db():
    with _get_conn() as conn:
        conn.execute("""
            CREATE TABLE IF NOT EXISTS restaurants (
                id       INTEGER PRIMARY KEY AUTOINCREMENT,
                name     TEXT NOT NULL UNIQUE COLLATE NOCASE,
                note     TEXT NOT NULL DEFAULT '',
                added_by TEXT NOT NULL DEFAULT 'unknown'
            )
        """)
        conn.commit()

        row = conn.execute("SELECT COUNT(*) AS cnt FROM restaurants").fetchone()
        if row["cnt"] == 0:
            conn.executemany(
                "INSERT OR IGNORE INTO restaurants (name, note, added_by) VALUES (?, ?, ?)",
                SEED_DATA,
            )
            conn.commit()


def _format_restaurant(row: sqlite3.Row) -> str:
    return f"{row['name']}\n- {row['note']}\nAdded by {row['added_by']}"


def add_restaurant(name: str, note: str, added_by: str) -> str:
    name = name.strip()
    note = note.strip()
    if not name:
        return "❌ Restaurant name cannot be empty."
    with _get_conn() as conn:
        existing = conn.execute(
            "SELECT id FROM restaurants WHERE name = ?", (name,)
        ).fetchone()
        if existing:
            return f"❌ **{name}** is already in the list."
        conn.execute(
            "INSERT INTO restaurants (name, note, added_by) VALUES (?, ?, ?)",
            (name, note, added_by),
        )
        conn.commit()
    return f"✅ Added **{name}** to the restaurant list!"


def remove_restaurant(name: str) -> str:
    name = name.strip()
    if not name:
        return "❌ Please provide a restaurant name to remove."
    with _get_conn() as conn:
        existing = conn.execute(
            "SELECT id, name FROM restaurants WHERE name = ?", (name,)
        ).fetchone()
        if not existing:
            return f"❌ No restaurant named **{name}** found. Names are case-insensitive."
        actual_name = existing["name"]
        conn.execute("DELETE FROM restaurants WHERE id = ?", (existing["id"],))
        conn.commit()
    return f"🗑️ Removed **{actual_name}** from the restaurant list."




def find_restaurant(keyword: str = "") -> str:
    keyword = keyword.strip().lower()
    with _get_conn() as conn:
        if keyword:
            rows = conn.execute(
                "SELECT name, note, added_by FROM restaurants WHERE LOWER(note) LIKE ?",
                (f"%{keyword}%",),
            ).fetchall()
        else:
            rows = conn.execute(
                "SELECT name, note, added_by FROM restaurants"
            ).fetchall()

    if not rows:
        if keyword:
            return f"🔍 No restaurants found with **{keyword}** in their notes."
        return "No restaurants in the list yet. Use !addrestaurant to add one!"

    pick = random.choice(rows)
    label = f'🎲 Random pick (keyword: "{keyword}"):' if keyword else "🎲 Random pick:"
    return f"{label}\n\n{_format_restaurant(pick)}"



HELP_TEXT = (
    "🍽️ Restaurant bot commands:\n"
    "  !addrestaurant <name> | <note>  — add a new restaurant (names must be unique)\n"
    "  !removerestaurant <name>        — remove a restaurant by name\n"
    "  !findrestaurant [keyword]       — get a random restaurant (optionally filtered by keyword in note)"
)


async def handle_restaurant_command(bot_api, room_id: str, sender: str, body: str):
    """
    Returns True if the message was handled as a restaurant command, False otherwise.
    Call this from your on_message_event listener.
    """
    stripped = body.strip()
    lower = stripped.lower()

    # Passive trigger: any message containing "where to eat"
    if "where to eat" in lower and not lower.startswith("!"):
        reply = find_restaurant()
        await bot_api.send_text_message(room_id, reply)
        return True

    if not lower.startswith("!"):
        return False

    # !addrestaurant <name> | <note>
    if lower.startswith("!addrestaurant"):
        rest = stripped[len("!addrestaurant"):].strip()
        if not rest:
            await bot_api.send_text_message(
                room_id,
                "Usage: !addrestaurant <name> | <note>\nExample: !addrestaurant Sushi Place | great omakase | 📍 Downtown",
            )
            return True
        if "|" in rest:
            name, _, note = rest.partition("|")
        else:
            name = rest
            note = ""
        # Derive a friendly display name from the Matrix sender ID (@user:server -> user)
        added_by = sender.lstrip("@").split(":")[0]
        reply = add_restaurant(name, note, added_by)
        await bot_api.send_text_message(room_id, reply)
        return True

    # !removerestaurant <name>
    if lower.startswith("!removerestaurant"):
        name = stripped[len("!removerestaurant"):].strip()
        if not name:
            await bot_api.send_text_message(
                room_id,
                "Usage: !removerestaurant <name>\nExample: !removerestaurant MCDONALDS",
            )
            return True
        reply = remove_restaurant(name)
        await bot_api.send_text_message(room_id, reply)
        return True

    # !findrestaurant [keyword]
    if lower.startswith("!findrestaurant"):
        keyword = stripped[len("!findrestaurant"):].strip()
        reply = find_restaurant(keyword)
        await bot_api.send_text_message(room_id, reply)
        return True

    # !restaurants (help alias)
    if lower.startswith("!restaurants"):
        await bot_api.send_text_message(room_id, HELP_TEXT)
        return True

    return False
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage