/botly/reaction.py (4c0e2c300bd93452fc1419c8d09cb167fa98b36d) (4834 bytes) (mode 100644) (type blob)

#!/usr/bin/env python
"""Contains the ReactionBase class and load_reactions function."""

import asyncio
from importlib import import_module
from os import listdir
from os.path import isfile, join

from botly.trigger import Trigger


class ReactionBase:
    """Subclass this class in a reaction module to create a new Reaction.
    
    When sublcassed, it should pass the event name hook through the constructor
    and should redefine these two methods:
    def prepare_trigger(self, trigger)
    async def react(self)

    The first method is called when the object is created. It should defines
    the trigger's conditions.

    The second one is called when an event triggers this reaction. Place the
    actions there.
    """

    def __init__(self, eventName):
        """When subclassed, pass the event name to the mother class."""
        self.eventName = eventName
        self.bot = False
        self.knowledge = False
        trigger = Trigger(eventName)
        # Call the function that should have been subclassed
        self.prepare_trigger(trigger)
        self.trigger = trigger

    def prepare_trigger(self, trigger):
        """Allows the trigger to be personalized. Meant to be subclassed.

        This method should be redefined in the subclass.
        It should prepare the given trigger by defining its conditions.
        It does not require to return anything
        """
        raise NotImplementedError

    async def react(self):
        """Method to be subclassed. Called when conditions were met."""
        raise NotImplementedError

    def print(self, message):
        """Helper for console printing. Will prepend current Reaction name."""
        self.bot.print('[Reaction][{0}] {1}'.format(self.moduleName, message))

    def is_mentioned(self):
        """Returns whether or not our bot was mentioned in the message."""
        assert self.bot, 'Botly instance not passed to this object'
        if self.message:
            return self.bot.me.mentioned_in(self.message)
    
    async def reply(self, message):
        """Coroutine that replies in current chan with given message."""
        if self.channel:
            await self.bot.say(self.channel, message)

    async def send_to_chan(self, channel, message):
        """Coroutine that send message to given channel."""
        await self.bot.say(channel, message)

    def set_instance_info(self, bot):
        """Saves botly instance. Only meant to becalled upon module import."""
        self.bot = bot
        self.knowledge = bot.knowledge

    def set_module_name(self, name):
        """Saves the name of this Reaction. Called upon module import."""
        self.moduleName = name

    def prepare_react(self, **eventInfo):
        """Only meant to be called from Botly. Do not call elsewhere."""
        self.message = False
        self.messageAfter = False
        self.author = False
        self.channel = False
        self.user = False
        self.when = False
        self.before = False
        self.after = False

        if 'message' in self.eventName:
            self.message = eventInfo['message']
            self.author = eventInfo['message'].author
            self.channel = eventInfo['message'].channel
            if 'on_message_edit' == self.eventName:
                self.messageAfter = eventInfo['after']
        elif 'on_typing' == self.eventName:
            self.channel = eventInfo['channel']
            self.user = eventInfo['user']
            self.when = eventInfo['when']
        elif 'on_member_update' == self.eventName:
            self.before = eventInfo['before']
            self.after = eventInfo['after']
        elif 'reaction' in self.eventName:
            self.reaction = eventInfo['reaction']
            self.user = eventInfo['user']


def load_reactions(bot, reactionsParent):
    """Function that loads reactions from given parent module directory."""
    # Convert module path to drive path.
    dpath = './' + reactionsParent.replace('.', '/')

    # Retreive every python script in the reaction module directory
    files = [f for f in listdir(dpath)
             if isfile(join(dpath,f))
                and f.endswith('.py')]

    # Build the list of reactions
    reactions = []            
    for file in files:
        # Module name does not include '.py' so remove that part
        module = file[:-3]
        _reaction = import_module(reactionsParent + '.' + module)
        reaction = _reaction.Reaction()
        reactions.append(reaction)
        assert len(reaction.eventName), \
            'Loaded a reaction linked to no event.'
        # Inject instance info in reaction object
        reaction.set_instance_info(bot)
        reaction.set_module_name(module)
    bot.print('Loaded ' + str(len(reactions)) + ' reactions from drive.')
    return reactions




Mode Type Size Ref File
100644 blob 896 ac3944627b46e5914bc225d541cab61e13102ad4 README.md
040000 tree - 7fe31426b83442fe984fbceaebdfe52b5027603f botly
100644 blob 172 3f148ab99d152565c46e51fd45e51030417f7faa example.py
040000 tree - 397dee229020cc10f79921f6d7253dcd4a117273 examplebot
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/detche/Botly

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/detche/Botly

Clone this repository using git:
git clone git://git.rocketgit.com/user/detche/Botly

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main