Exemple #1
0
class Homepage(SimpleResponseCommand):

    condition = IsCommand(["homepage", "home"])
    help = "`homepage`: link to Meowbot homepage"

    def get_message_args(self, context: CommandContext):
        return {"text": url_for("main.index", _external=True)}
Exemple #2
0
class Dog(SimpleResponseCommand):

    condition = IsCommand(["dog"])
    private = True

    def get_message_args(self, context: CommandContext):
        return {"text": "no", "icon_emoji": f"{Emoji.MONKACAT}"}
Exemple #3
0
class Fail(SimpleResponseCommand):

    private = True
    condition = And(IsCommand(["fail"]), IsUser([get_admin_user_id()]))

    def get_message_args(self, context: CommandContext):
        raise Exception()
Exemple #4
0
class AddCat(SimpleResponseCommand):

    condition = IsCommand(["addcat", "addacat", "registercat"])
    help = "`addcat [name] [photo_url]`: add a cat to the database"

    def get_message_args(self, context: CommandContext):
        if len(context.args) != 2:
            return {
                "text": "Expected 2 args (name, url). "
                f"Got {len(context.args)}",
                "thread_ts": context.event.ts,
            }
        name, url = context.args
        # TODO: figure out why URLs are wrapped in <>.
        url = url[1:-1]
        if not validators.url(url):
            return {
                "text": f"`{url}` is not a valid URL",
                "thread_ts": context.event.ts,
            }
        row = Cat(name=name.lower(), url=url)
        meowbot.db.session.add(row)
        meowbot.db.session.commit()
        return {
            "attachments": [{
                "text": f"Registered {name}!",
                "image_url": url
            }],
            "thread_ts": context.event.ts,
        }
Exemple #5
0
class Ping(SimpleResponseCommand):

    condition = IsCommand(["ping"])
    help = "`ping`: see if meowbot is awake"

    def get_message_args(self, context: CommandContext):
        return {"text": "pong!", "icon_emoji": f"{Emoji.PING_PONG}"}
Exemple #6
0
class RemoveCat(SimpleResponseCommand):

    condition = IsCommand(["removecat"])
    help = "`removecat [name] [number]`: delete a photo from the database"

    def get_message_args(self, context: CommandContext):
        if len(context.args) != 2:
            return context.api.chat_post_message({
                "text":
                "Expected 2 args (name, number). "
                f"Got {len(context.args)}"
            })
        name, number = context.args
        if not number.isnumeric():
            return {
                "text": f"Second argument must be a number. Got `{number}`"
            }
        offset = int(number)
        if offset <= 0:
            return {"text": f"Number must be > 0. Got `{offset}`"}
        row = (Cat.query.filter_by(name=name.lower()).order_by(
            Cat.id).limit(1).offset(offset - 1).one_or_none())
        if row is None:
            return {"text": "No matching rows"}
        meowbot.db.session.delete(row)
        meowbot.db.session.commit()
        return {"text": "Successfully removed!"}
Exemple #7
0
class Meow(SimpleResponseCommand):

    condition = IsCommand(["meow"])
    help = "`meow`: meow!"

    def get_message_args(self, context: CommandContext):
        return {"text": f"Meow! {Emoji.CATKOOL}"}
Exemple #8
0
class Hmm(SimpleResponseCommand):

    condition = IsCommand(["hmm", "think", "thinking"])
    help = ("`hmm`: thinking...", )

    def get_message_args(self, context: CommandContext):
        return {"text": str(random.choice(list(Emoji.thinking())))}
Exemple #9
0
class AdoptCat(SimpleResponseCommand):

    condition = IsCommand(["adoptcat"])
    help = "`adoptcat [zipcode]`: get cat adoption info"

    def get_message_args(self, context: CommandContext):
        if len(context.args) == 1:
            (zip_code, ) = context.args
            if not zip_code.isnumeric():
                return {"text": f"Zip code must be a number. Got `{zip_code}`"}
        elif len(context.args) > 1:
            return {"text": "Usage: `adoptcat [zipcode]`"}
        else:
            zip_code = get_default_zip_code()

        api_key = get_petfinder_api_key()
        petfinder_url = "http://api.petfinder.com/pet.find"
        r = requests.get(
            petfinder_url,
            params={
                "key": api_key,
                "output": "basic",
                "animal": "cat",
                "count": "25",
                "location": zip_code,
                "format": "json",
            },
        )
        data = r.json()

        def pet_info(pet):
            url = ("https://www.petfinder.com/cat/"
                   "{short_name}-{pet_id}/state/city/shelter-{shelter_id}/"
                   ).format(
                       short_name=pet["name"]["$t"].split(" ", 1)[0].lower(),
                       pet_id=pet["id"]["$t"],
                       shelter_id=pet["shelterId"]["$t"],
                   )
            photos = [
                photo["$t"] for photo in pet.get("media", {}).get(
                    "photos", {}).get("photo", []) if photo["@size"] == "pn"
            ]
            name = pet["name"]["$t"]
            sex = pet["sex"]["$t"]
            age = pet["age"]["$t"]
            return {
                "basic_info": f"{name} sex: {sex} age: {age} {url}",
                "photo": None if len(photos) == 0 else photos[0],
            }

        pets = random.sample(
            [pet_info(pet) for pet in data["petfinder"]["pets"]["pet"]], k=5)
        return {
            "attachments": [{
                "text": pet["basic_info"],
                "image_url": pet["photo"]
            } for pet in pets],
            "thread_ts":
            context.event.ts,
        }
Exemple #10
0
class GitHub(SimpleResponseCommand):

    condition = IsCommand(["github", "git", "source"])
    help = "`github`: GitHub page for Meowbot"

    def get_message_args(self, context: CommandContext):
        return {"text": "https://github.com/pbhuss/meowbot"}
Exemple #11
0
class TV(SimpleResponseCommand):

    condition = IsCommand(["tv", "television", "meowtv", "meowbottv"])
    help = "`tv`: watch Meowbot TV"

    def get_message_args(self, context: CommandContext):
        return {"text": url_for("main.tv")}
Exemple #12
0
class RefreshTV(SimpleResponseCommand):

    condition = IsCommand(["refreshtv", "refresh"])
    help = "`refreshtv`: refresh Meowbot TV"

    def get_message_args(self, context: CommandContext):
        get_redis().incr("tvid")
        return {"text": "Refreshed tv!"}
Exemple #13
0
class Debug(SimpleResponseCommand):

    private = True
    condition = And(IsCommand(["debug"]), IsUser([get_admin_user_id()]))

    def get_message_args(self, context: CommandContext):
        context._data["token"] = "REMOVED"
        return {"text": pformat(context._data)}
Exemple #14
0
class Shrug(SimpleResponseCommand):

    condition = IsCommand(["shrug"])
    help = "`shrug`: shrug"
    private = True

    def get_message_args(self, context: CommandContext):
        return {"text": rf"¯\_{Emoji.CAT}_/¯"}
Exemple #15
0
class Rainbow(SimpleResponseCommand):
    condition = IsCommand(["rainbow"])
    help = "`rainbow [text]`: make rainbow text"

    def get_message_args(self, context: CommandContext):
        text = " ".join(context.args)

        return {"text": coloring(text, itertools.cycle(ALL_TEXT_COLORS))}
Exemple #16
0
class Poop(SimpleResponseCommand):

    condition = IsCommand(["poop"])
    help = "`poop`: meowbot poops"
    private = True

    def get_message_args(self, context: CommandContext):
        return {"icon_emoji": f"{Emoji.SMIRK_CAT}", "text": f"{Emoji.POOP}"}
Exemple #17
0
class Christmas(SimpleResponseCommand):
    condition = IsCommand(["christmas"])
    help = "`christmas [text]`: make Christmas text"

    def get_message_args(self, context: CommandContext):
        text = " ".join(context.args)

        return {"text": coloring(text, christmas_color())}
Exemple #18
0
class Color(SimpleResponseCommand):

    condition = IsCommand(["color", "colour"])
    help = "`color [text]`: add some color"

    def get_message_args(self, context: CommandContext):
        text = " ".join(context.args)

        return {"text": coloring(text, random_color())}
Exemple #19
0
class ListCats(SimpleResponseCommand):

    condition = IsCommand(["listcats"])
    help = "`listcats`: see all cats available for the `cat` command"

    def get_message_args(self, context: CommandContext):
        rows = meowbot.db.session.query(Cat.name).distinct()
        names = ", ".join(row.name for row in rows)
        return {"text": f"Cats in database: {names}"}
Exemple #20
0
class CatCommand(SimpleResponseCommand):

    condition = IsCommand(["cat", "getcat"])
    help = "`cat [name] [number]`: gives one cat"

    def get_message_args(self, context: CommandContext):
        if len(context.args) in (1, 2):
            name = context.args[0]
            num_photos = Cat.query.filter_by(name=name.lower()).count()
            if num_photos == 0:
                return {"text": f"No cats named {name} registered"}
            if len(context.args) == 2:
                number = context.args[1]
                if not number.isnumeric():
                    return {
                        "text":
                        "Second argument must be a number. "
                        f"Got `{number}`"
                    }
                number = int(number)
                if 1 <= number <= num_photos:
                    offset = number - 1
                else:
                    offset = random.randint(0, num_photos - 1)
            else:
                offset = random.randint(0, num_photos - 1)
            row = (Cat.query.filter_by(name=name.lower()).order_by(
                Cat.id).limit(1).offset(offset).one())
            self.image_url = row.url
            self.alt_text = name
        else:
            self.image_url = requests.head(
                "https://api.thecatapi.com/v1/images/search?"
                "format=src&mime_types=image/gif",
                headers={
                    "x-api-key": get_cat_api_key()
                },
            ).headers["Location"]
            self.alt_text = "cat gif"
        return {
            "blocks": [{
                "type": "image",
                "image_url": self.image_url,
                "alt_text": self.alt_text,
            }]
        }

    def post_run(self, context):
        for response in self.responses:
            if not response.ok:
                context.api.chat_post_message({
                    "channel":
                    context.event.channel,
                    "text": ("Image could not be retrieved by Slack: "
                             f"{self.image_url}"),
                })
        super().post_run(context)
Exemple #21
0
class Fact(SimpleResponseCommand):

    condition = IsCommand(["fact", "catfact", "catfacts", "facts"])
    help = "`fact`: get a cat fact"
    private = True

    def get_message_args(self, context: CommandContext):
        return {
            "text": requests.get("https://catfact.ninja/fact").json()["fact"]
        }
Exemple #22
0
class Lacroix(SimpleResponseCommand):

    condition = IsCommand(["lacroix"])
    help = "`lacroix`: meowbot recommends a flavor"

    def get_message_args(self, context: CommandContext):
        flavor = random.choice(list(Emoji.lacroix()))
        flavor_name = flavor.name.split("_")[0].capitalize()
        user = quote_user_id(context.event.user)
        return {"text": f"{user}: I recommend {flavor} {flavor_name} La Croix"}
Exemple #23
0
class Magic8(SimpleResponseCommand):

    condition = IsCommand(["magic8", "8ball"])
    help = "`magic8 [question]`: tells your fortune"

    def get_message_args(self, context: CommandContext):
        text = "{} asked:\n>{}\n{}".format(
            quote_user_id(context.event.user),
            " ".join(context.args),
            random.choice(magic_eight_ball_options),
        )
        return {"text": text, "icon_emoji": f"{Emoji.EIGHT_BALL}"}
Exemple #24
0
class EnableTV(SimpleResponseCommand):

    condition = And(IsCommand(["enabletv"]), IsUser([get_admin_user_id()]))
    help = "`enable`: this restores Meowbot TV"
    private = True

    def get_message_args(self, context: CommandContext):
        redis = get_redis()
        redis.delete("killtv")
        return {
            "text": "Meowbot TV has been enabled",
        }
Exemple #25
0
class XKCD(SimpleResponseCommand):

    condition = IsCommand(["xkcd"])
    help = "`xkcd [num]`: get today's xkcd, or a particular number"

    def get_message_args(self, context: CommandContext):
        if context.args:
            if len(context.args) != 1:
                return {"text": f"Usage: {self.get_help(context)}"}

            (num, ) = context.args
            if not num.isnumeric():
                return {"text": f"Argument must be a number (got `{num}`)"}

            url = f"http://xkcd.com/{num}/info.0.json"
        else:
            url = "http://xkcd.com/info.0.json"

        resp = requests.get(url)
        if resp.status_code == 404:
            return {"text": "Comic not found"}
        data = resp.json()

        date = datetime.date(int(data["year"]), int(data["month"]),
                             int(data["day"])).strftime("%b %d, %Y")

        return {
            "blocks": [
                {
                    "type": "image",
                    "image_url": data["img"],
                    "title": {
                        "type": "plain_text",
                        "text": data["safe_title"]
                    },
                    "alt_text": data["alt"],
                },
                {
                    "type":
                    "context",
                    "elements": [
                        {
                            "type": "mrkdwn",
                            "text": f'#{data["num"]}'
                        },
                        {
                            "type": "mrkdwn",
                            "text": date
                        },
                    ],
                },
            ]
        }
Exemple #26
0
class Concerts(SimpleResponseCommand):

    condition = IsCommand(["concerts", "concert"])
    help = "`concerts`: upcoming concerts at Yerba Buena Gardens Festival"

    def get_message_args(self, context: CommandContext):
        redis = get_redis()
        key = "concertcal"
        ical_data = redis.get(key)
        if ical_data is None:
            ical_data = requests.get(
                "https://ybgfestival.org/events/?ical=1&tribe_display=list"
            ).content
            redis.set(key, ical_data)
            # Expire at midnight PST
            redis.expireat(
                key,
                (arrow.utcnow().to("US/Pacific") + timedelta(days=1)).replace(
                    hour=0, minute=0).timestamp,
            )

        cal = ics.Calendar(ical_data.decode("utf-8"))
        events = cal.timeline.start_after(arrow.utcnow() - timedelta(hours=3))
        colors = ["#7aff33", "#33a2ff"]
        return {
            "text":
            "Upcoming concerts at <https://ybgfestival.org/|"
            "Yerba Buena Gardens Festival>:",
            "attachments": [{
                "title":
                event.name,
                "title_link":
                event.url,
                "text":
                event.description,
                "color":
                color,
                "fields": [
                    {
                        "title":
                        "When",
                        "value":
                        "{} - {}".format(
                            event.begin.strftime("%a %b %d, %I:%M"),
                            event.end.strftime("%I:%M %p"),
                        ),
                        "short":
                        False,
                    },
                ],
            } for event, color in zip(events, colors)],
        }
Exemple #27
0
class Shakespeare(SimpleResponseCommand):

    condition = IsCommand(["shakespeare"])
    help = "`shakespeare`: generates a Shakespearean insult"

    def get_message_args(self, context: CommandContext):
        return {
            "text":
            "{}thou {} {} {}".format(
                " ".join(context.args) + " " if len(context.args) > 0 else "",
                random.choice(shakespeare_insult_start),
                random.choice(shakespeare_insult_middle),
                random.choice(shakespeare_insult_end),
            )
        }
Exemple #28
0
class Nyan(SimpleResponseCommand):

    condition = IsCommand(["nyan"])
    help = "`nyan`: nyan"

    def get_message_args(self, context: CommandContext):
        return {
            "blocks": [{
                "type":
                "image",
                "image_url":
                ("https://media.giphy.com/media/sIIhZliB2McAo/giphy.gif"),
                "alt_text":
                "nyan cat",
            }]
        }
Exemple #29
0
class SetLocation(BaseCommand):

    condition = IsCommand(["setlocation"])
    help = "`setlocation [location]`: set your default location for `weather`"

    def run(self, context: CommandContext):
        location = " ".join(context.args)
        redis = get_redis()
        redis.hset("user_location", context.event.user, location)
        context.api.chat_post_ephemeral(
            {
                "channel": context.event.channel,
                "user": context.event.user,
                "text": f"Set default location to {location}",
            }
        )
Exemple #30
0
class Redis(SimpleResponseCommand):

    private = True
    condition = And(IsCommand(["redis"]), IsUser([get_admin_user_id()]))

    def get_message_args(self, context: CommandContext):
        if len(context.args) == 0:
            return {"text": "must specify at least one argument"}
        redis = get_redis()
        func_name, *func_args = context.args
        func = getattr(redis, func_name, None)
        if func is None:
            return {"text": f"invalid func_name: {func_name}"}
        arg_names = ", ".join(func_args)
        ret = func(*func_args)
        return {"text": f"Ran `{func_name}({arg_names})`\nReturned `{ret}`"}