aboutsummaryrefslogtreecommitdiffstats
path: root/contessa/commands.py
blob: ac5be722ad40897b6141b6ddc10ad25606a46b65 (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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
"""
Sopel plugin: contessa - recipe bot

Egyptian, Middle Eastern and Western recipes.

  !breakfast [list]  - random breakfast dish or list all
  !lunch     [list]  - random lunch dish or list all
  !dinner    [list]  - random dinner dish or list all
  !snack     [list]  - random snack or list all
  !recipe <name>     - full recipe (up to 3 lines)

  !join / !part / !chans / !help  - owner commands
"""

import json
import os
import random

from sopel import plugin
from sopel.config.types import FilenameAttribute, StaticSection


class ContessaSection(StaticSection):
    recipes_path = FilenameAttribute("recipes_path", relative=False,
                                     default="/var/contessa/recipes.json")


def setup(bot):
    bot.config.define_section("contessa", ContessaSection, validate=False)
    try:
        path = bot.config.contessa.recipes_path
    except Exception:
        path = "/var/contessa/recipes.json"

    try:
        with open(path) as f:
            bot.memory["ct_recipes"] = json.load(f)
    except Exception:
        bot.memory["ct_recipes"] = {"breakfast": [], "lunch": [], "dinner": [], "snack": []}


def _is_owner(bot, trigger):
    return trigger.nick == bot.settings.core.owner


def _fmt_random(category, dish):
    return (
        f"{category.capitalize()} suggestion: "
        f"{dish['name']} | {dish['description']}. "
        f"Type !recipe {dish['name'].lower()} for the full recipe."
    )


def _fmt_list(category, dishes):
    names = ", ".join(d["name"] for d in dishes)
    return f"{category.capitalize()} dishes ({len(dishes)}): {names}"


def _fmt_recipe(dish):
    line1 = f"{dish['name']} | {dish['description']}"
    line2 = "Ingredients: " + ", ".join(dish["ingredients"])
    steps = " ".join(
        f"{i+1}. {s.rstrip('.')}." for i, s in enumerate(dish["steps"])
    )
    line3 = steps
    return line1, line2, line3


def _all_dishes(bot):
    recipes = bot.memory.get("ct_recipes", {})
    for category, dishes in recipes.items():
        for dish in dishes:
            yield category, dish


def _find_dish(bot, query):
    q = query.strip().lower()
    for _, dish in _all_dishes(bot):
        if dish["name"].lower() == q:
            return dish
    for _, dish in _all_dishes(bot):
        if q in dish["name"].lower():
            return dish
    return None


def _meal_cmd(bot, trigger, category):
    arg     = (trigger.group(2) or "").strip().lower()
    recipes = bot.memory.get("ct_recipes", {})
    dishes  = recipes.get(category, [])

    if not dishes:
        bot.say(f"no {category} recipes loaded", trigger.sender)
        return

    if arg == "list":
        bot.say(_fmt_list(category, dishes), trigger.sender)
        return

    dish = random.choice(dishes)
    bot.say(_fmt_random(category, dish), trigger.sender)


@plugin.command("breakfast")
@plugin.require_chanmsg
def cmd_breakfast(bot, trigger):
    _meal_cmd(bot, trigger, "breakfast")


@plugin.command("lunch")
@plugin.require_chanmsg
def cmd_lunch(bot, trigger):
    _meal_cmd(bot, trigger, "lunch")


@plugin.command("dinner")
@plugin.require_chanmsg
def cmd_dinner(bot, trigger):
    _meal_cmd(bot, trigger, "dinner")


@plugin.command("snack")
@plugin.require_chanmsg
def cmd_snack(bot, trigger):
    _meal_cmd(bot, trigger, "snack")


@plugin.command("recipe")
@plugin.require_chanmsg
def cmd_recipe(bot, trigger):
    query = (trigger.group(2) or "").strip()
    if not query:
        bot.say("usage: !recipe <dish name>", trigger.sender)
        return

    dish = _find_dish(bot, query)
    if not dish:
        bot.say(f"no recipe found for '{query}'", trigger.sender)
        return

    line1, line2, line3 = _fmt_recipe(dish)
    bot.say(line1, trigger.sender)
    bot.say(line2, trigger.sender)
    bot.say(line3, trigger.sender)


@plugin.command("join")
def cmd_join(bot, trigger):
    if not _is_owner(bot, trigger):
        return
    channel = (trigger.group(2) or "").strip()
    if not channel.startswith("#"):
        bot.say("usage: !join #channel", trigger.nick)
        return
    bot.join(channel)


@plugin.command("part")
def cmd_part(bot, trigger):
    if not _is_owner(bot, trigger):
        return
    channel = (trigger.group(2) or "").strip() or str(trigger.sender)
    bot.part(channel)


@plugin.command("chans")
def cmd_chans(bot, trigger):
    if not _is_owner(bot, trigger):
        return
    chans = sorted(str(c) for c in bot.channels)
    bot.say(("in: " + " ".join(chans)) if chans else "not in any channels", trigger.nick)


@plugin.command("help")
def cmd_help(bot, trigger):
    lines = [
        "!breakfast [list]  - random breakfast dish or list all",
        "!lunch     [list]  - random lunch dish or list all",
        "!dinner    [list]  - random dinner dish or list all",
        "!snack     [list]  - random snack or list all",
        "!recipe <name>     - full recipe (3 lines)",
    ]
    if _is_owner(bot, trigger):
        lines += [
            "!join #channel     - join a channel",
            "!part [#channel]   - leave a channel",
            "!chans             - list channels",
        ]
    lines.append("!help              - this message")
    for line in lines:
        bot.say(line, trigger.nick)