Example #1
0
 def on_status(self, status):
     if (status.user.screen_name.lower() in self.relevant_users
             and not status.text.startswith("RT ")):
         log.info("On status from tweepy: %s", status.text)
         tweet = status
         ScheduleManager.execute_now(self.dispatch_tweet,
                                     args=[tweet])
Example #2
0
    async def _ban(
        self, user, timeout_in_seconds=0, reason=None, delete_message_days=0
    ):
        delete_message_days = (
            7
            if delete_message_days > 7
            else (0 if delete_message_days < 0 else delete_message_days)
        )

        if not self.guild:
            return
        if not user:
            return
        try:
            ban = await self.guild.fetch_ban(user)
            if ban:
                return
        except:
            pass
        if timeout_in_seconds > 0:
            reason = f"{reason} for {timeout_in_seconds} seconds"
            timeouts = json.loads(self.redis.get("timeouts-discord"))
            timeouts[str(user.id)] = {
                "discord_id": str(user.id),
                "unban_date": str(utils.now() + timedelta(seconds=timeout_in_seconds)),
                "reason": str(reason)
            }
            self.redis.set("timeouts-discord", json.dumps(timeouts))
            ScheduleManager.execute_delayed(delay=timeout_in_seconds, method=self.unban, args=[user.id, "Unbanned by timer"])
        await self.guild.ban(
            user=user, reason=reason, delete_message_days=delete_message_days
        )
Example #3
0
    async def initial_unbans(self):
        try:
            data = json.loads(self.redis.get(f"{self.bot.bot_name}:timeouts-discord"))
            for user in data:
                unban_date = utils.parse_date(data[user]["unban_date"])
                time_now = utils.now()
                resp_timeout = data.get("resp_timeout", "")
                resp_timeout += " after " if resp_timeout else ""
                if unban_date < time_now:
                    ScheduleManager.execute_now(
                        method=self.unban,
                        args=[
                            data[user]["discord_id"],
                            f"Unbanned by timer{resp_timeout}",
                        ],
                    )
                    continue
                ScheduleManager.execute_delayed(
                    delay=(unban_date - time_now).seconds,
                    method=self.unban,
                    args=[data[user]["discord_id"], f"Unbanned by timer{resp_timeout}"],
                )
        except Exception as e:
            log.exception(e)
            self.redis.set(f"{self.bot.bot_name}:timeouts-discord", json.dumps({}))

        with DBManager.create_session_scope() as db_session:
            unnamed_users = db_session.query(User).filter_by(user_name="").all()
            for user in unnamed_users:
                member = self.get_member(int(user.discord_id))
                if not member:
                    db_session.delete(user)
                    continue

                user.user_name = str(member)
Example #4
0
    def __init__(self, config, args):
        self.config = config
        self.args = args
        self.private_loop = asyncio.get_event_loop()
        self.private_loop.set_exception_handler(custom_exception_handler)

        self.discord_token = self.config["main"]["discord_token"]

        ScheduleManager.init(self.private_loop)

        DBManager.init(self.config["main"]["db"])

        ActionParser.bot = self

        # redis
        redis_options = {}
        if "redis" in config:
            redis_options = dict(config.items("redis"))
        RedisManager.init(**redis_options)
        utils.wait_for_redis_data_loaded(RedisManager.get())

        # SQL migrations
        try:
            with DBManager.create_dbapi_connection_scope() as sql_conn:
                sql_migratable = DatabaseMigratable(sql_conn)
                sql_migration = Migration(sql_migratable,
                                          greenbot.migration_revisions.db,
                                          self)
                sql_migration.run()
        except ValueError as error:
            log.error(error)

        HandlerManager.init_handlers()

        self.movienight_api = MovieNightAPI(self, self.config["wsc"],
                                            self.config["wowza_cdn"])

        HandlerManager.add_handler("parse_command_from_message",
                                   self.parse_command_from_message)
        self.bot_name = self.config["main"]["bot_name"]
        self.command_prefix = self.config["discord"]["command_prefix"]
        self.settings = {
            "discord_token": self.discord_token,
            "bot_name": self.bot_name,
            "command_prefix": self.command_prefix,
            "discord_guild_id": self.config["discord"]["discord_guild_id"],
        }

        HandlerManager.add_handler("discord_ready", self.wait_discord_load)

        self.discord_bot = DiscordBotManager(
            bot=self,
            settings=self.settings,
            redis=RedisManager.get(),
            private_loop=self.private_loop,
        )
        self.twitter_manager = TwitterManager(self)
        self.filters = Filters(self, self.discord_bot)
        self.functions = Functions(self, self.filters)
Example #5
0
 def enable(self, settings):
     self.settings = settings
     self.salt = utils.random_string()
     with DBManager.create_session_scope() as db_session:
         current_timeouts = Timeout._active_timeouts(db_session)
         for timeout in current_timeouts:
             if timeout.time_left:
                 ScheduleManager.execute_delayed(
                     timeout.time_left + 1,
                     self.auto_untimeout,
                     args=[timeout.id, self.salt],
                 )
Example #6
0
    def run(self, bot, author, channel, message, args):
        if self.action is None:
            log.warning("This command is not available.")
            return False

        if args["user_level"] < self.level:
            # User does not have a high enough power level to run this command
            return False

        if args["whisper"] and self.can_execute_with_whisper is False:
            # This user cannot execute the command through a whisper
            return False

        cd_modifier = 0.2 if args["user_level"] >= 500 else 1.0

        cur_time = greenbot.utils.now().timestamp()
        time_since_last_run = (cur_time - self.last_run) / cd_modifier

        if (time_since_last_run < self.delay_all
                and args["user_level"] < Command.BYPASS_DELAY_LEVEL):
            log.debug(
                f"Command was run {time_since_last_run:.2f} seconds ago, waiting..."
            )
            return False

        time_since_last_run_user = (cur_time - self.last_run_by_user.get(
            str(author.id), 0)) / cd_modifier

        if (time_since_last_run_user < self.delay_user
                and args["user_level"] < Command.BYPASS_DELAY_LEVEL):
            log.debug(
                f"{author.name}#{author.discriminator} ran command {time_since_last_run_user:.2f} seconds ago, waiting..."
            )
            return False
        with DBManager.create_session_scope() as db_session:
            user = User._create_or_get_by_discord_id(db_session,
                                                     str(author.id),
                                                     str(author))
            if self.cost > 0 and not user.can_afford(self.cost):
                # User does not have enough points to use the command
                return False

            args.update(self.extra_args)
            if self.run_in_thread:
                log.debug(f"Running {self} in a thread")
                ScheduleManager.execute_now(
                    self.run_action,
                    args=[bot, author, channel, message, args])
            else:
                self.run_action(bot, author, channel, message, args)

        return True
Example #7
0
    def __init__(self, bot):
        super().__init__(bot)

        self.twitter_stream = None
        self.listener = None

        if "twitter" not in bot.config or not self.twitter_client:
            return

        try:
            ScheduleManager.execute_every(30, self.check_twitter_connection)
        except:
            log.exception("Twitter authentication failed.")

        log.info("Started Twitter")
Example #8
0
    async def ban(self, user, timeout_in_seconds=0, reason=None, delete_message_days=0):
        delete_message_days = (
            7
            if delete_message_days > 7
            else (0 if delete_message_days < 0 else delete_message_days)
        )

        if not self.guild:
            return False
        if not user:
            return False
        try:
            ban = await self.guild.fetch_ban(user)
            if ban:
                return False
        except:
            return False
        try:
            resp_timeout = utils.seconds_to_resp(timeout_in_seconds)
            reason += (
                f" for {resp_timeout}!" if timeout_in_seconds > 0 else " Permanently!"
            )
            await self.guild.ban(
                user=user, reason=reason, delete_message_days=delete_message_days
            )
            if timeout_in_seconds > 0:
                timeouts = json.loads(
                    self.redis.get(f"{self.bot.bot_name}:timeouts-discord")
                )
                timeouts[str(user.id)] = {
                    "discord_id": str(user.id),
                    "unban_date": str(
                        utils.now() + timedelta(seconds=timeout_in_seconds)
                    ),
                    "resp_timeout": resp_timeout,
                    "reason": str(reason),
                }
                self.redis.set(
                    f"{self.bot.bot_name}:timeouts-discord", json.dumps(timeouts)
                )
                ScheduleManager.execute_delayed(
                    delay=timeout_in_seconds,
                    method=self.unban,
                    args=[user.id, f"Unbanned by timer after {resp_timeout}"],
                )
        except:
            return False
        return True
Example #9
0
def run_functions(
    functions, bot, extra, author, channel, args, num_urlfetch_subs, private_message
):
    for func in functions:
        final_args = get_argument_substitutions_array(
            get_substitutions_array(func.arguments, bot, extra), extra
        )
        resp, embed = func.cb(final_args, extra)
        if num_urlfetch_subs == 0:

            return (
                bot.private_message(author, resp, embed)
                if private_message
                else bot.say(channel, resp, embed)
            )

        return ScheduleManager.execute_now(
            urlfetch_msg,
            args=[],
            kwargs={
                "args": [author if private_message else channel],
                "kwargs": {},
                "method": bot.private_message if private_message else bot.say,
                "bot": bot,
                "extra": extra,
                "message": resp,
                "embed": embed,
                "num_urlfetch_subs": num_urlfetch_subs,
            },
        )
Example #10
0
 def initial_unbans(self):
     try:
         data = json.loads(self.redis.get("timeouts-discord"))
         for user in data:
             unban_date = data[user]["unban_date"]
             if ":" in unban_date[-5:]:
                 unban_date = f"{unban_date[:-5]}{unban_date[-5:-3]}{unban_date[-2:]}"
             unban_date = datetime.strptime(unban_date, "%Y-%m-%d %H:%M:%S.%f%z")
             time_now = utils.now()
             if unban_date < time_now:
                 ScheduleManager.execute_now(method=self.unban, args=[data[user]["discord_id"], "Unbanned by timer"])
                 continue
             ScheduleManager.execute_delayed(delay=(unban_date - time_now).seconds, method=self.unban, args=[data[user]["discord_id"], "Unbanned by timer"])
     except Exception as e:
         log.exception(e)
         self.redis.set("timeouts-discord", json.dumps({}))
Example #11
0
    def __init__(self, bot, wsc_config, wowza_cdn_config):
        self.bot = bot
        self.wsc_api_key = wsc_config.get("wsc_api_key", None)
        self.wsc_access_key = wsc_config.get("wsc_access_key", None)
        self.wsc_host = wsc_config.get("wsc_host", None)
        self.wsc_version = wsc_config.get("wsc_version", None)

        self.wowza_cdn_expiration_time = wowza_cdn_config.get("wowza_cdn_expiration_time", None)
        self.wowza_cdn_live_stream_id = wowza_cdn_config.get("wowza_cdn_live_stream_id", None)
        self.wowza_cdn_trusted_shared_secret = wowza_cdn_config.get("wowza_cdn_trusted_shared_secret")

        self.ull_stream_running = False
        self.cdn_stream_running = False
        self.ull_playback_key = ""
        self.cdn_playback_key = ""

        if self.wsc_api_key\
            and self.wsc_access_key\
            and self.wsc_host\
            and self.wsc_version\
            and self.wowza_cdn_expiration_time\
            and self.wowza_cdn_live_stream_id\
            and self.wowza_cdn_trusted_shared_secret:
            self.schedule_job = ScheduleManager.execute_every(interval=30, method=self.stream_check)
            self.active = True
        else:
            self.active = False
Example #12
0
    def run(self, bot, author, channel, message, args):
        extra = self.get_extra_data(author, channel, message, args)
        resp, embed = self.get_response(bot, extra)
        if self.functions:
            run_functions(
                self.functions,
                bot,
                extra,
                author,
                channel,
                args,
                self.num_urlfetch_subs,
                True,
            )

        if not resp and embed:
            return False

        if self.num_urlfetch_subs == 0:
            return bot.private_message(author, resp, embed)

        return ScheduleManager.execute_now(
            urlfetch_msg,
            args=[],
            kwargs={
                "args": [author],
                "kwargs": {},
                "method": bot.private_message,
                "bot": bot,
                "extra": extra,
                "message": resp,
                "embed": embed,
                "num_urlfetch_subs": self.num_urlfetch_subs,
            },
        )
Example #13
0
 def enable(self, bot):
     if not bot:
         return
     try:
         reminders_list = json.loads(self.redis.get("remind-me-reminders"))
         """
         { 
             user_id: {
                 "message_id": message_id,
                 "message": message,
                 "date_of_reminder": date_of_reminder,
             },
         }
         """
     except:
         self.redis.set("remind-me-reminders", json.dumps({}))
         reminders_list = {}
     new_reminders_list = {}
     for user in reminders_list:
         user_reminders = reminders_list[user]
         new_user_reminders = []
         for reminder in user_reminders:
             salt = random_string()
             date_of_reminder = reminder["date_of_reminder"]
             if ":" in date_of_reminder[-5:]:
                 date_of_reminder = f"{date_of_reminder[:-5]}{date_of_reminder[-5:-3]}{date_of_reminder[-2:]}"
             date_of_reminder = datetime.strptime(date_of_reminder, "%Y-%m-%d %H:%M:%S.%f%z")
             if date_of_reminder < utils.now():
                 continue
             new_user_reminders.append(reminder)
             self.reminder_tasks[salt] = ScheduleManager.execute_delayed((date_of_reminder-utils.now()).seconds, self.execute_reminder, args=[salt, reminder])
Example #14
0
 def enable(self, bot):
     if not bot:
         return
     try:
         reminders_list = json.loads(
             self.redis.get(f"{self.bot.bot_name}:remind-me-reminders"))
         """
         { 
             user_id: [
                 {
                     "message_id": message_id,
                     "channel_id": channel_id,
                     "salt": salt,
                     "message": message,
                     "date_of_reminder": date_of_reminder,
                     "date_reminder_set": date_reminder_set
                 },
             ],
         }
         """
     except:
         self.redis.set(f"{self.bot.bot_name}:remind-me-reminders",
                        json.dumps({}))
         reminders_list = {}
     new_reminders_list = {}
     for user_id in reminders_list:
         user_reminders = reminders_list[user_id]
         new_user_reminders = []
         for reminder in user_reminders:
             salt = reminder["salt"]
             date_of_reminder = utils.parse_date(
                 reminder["date_of_reminder"])
             if date_of_reminder < utils.now():
                 continue
             new_user_reminders.append(reminder)
             self.reminder_tasks[salt] = ScheduleManager.execute_delayed(
                 (date_of_reminder - utils.now()).total_seconds(),
                 self.execute_reminder,
                 args=[salt, user_id, reminder],
             )
         new_reminders_list[user_id] = new_user_reminders
     self.redis.set(f"{self.bot.bot_name}:remind-me-reminders",
                    json.dumps(new_reminders_list))
Example #15
0
 async def create_reminder(self, bot, author, channel, message, args):
     command_args = message.split(" ") if message else []
     try:
         reminders_list = json.loads(
             self.redis.get(f"{self.bot.bot_name}:remind-me-reminders"))
         """
         { 
             user_id: [
                 {
                     "message_id": message_id,
                     "channel_id": channel_id,
                     "message": message,
                     "date_of_reminder": date_of_reminder,
                     "date_reminder_set": date_reminder_set
                 },
             ],
         }
         """
     except:
         self.redis.set(f"{self.bot.bot_name}:remind-me-reminders",
                        json.dumps({}))
         reminders_list = {}
     user_reminders = (reminders_list[str(author.id)]
                       if str(author.id) in reminders_list else [])
     if len(user_reminders) >= int(self.settings["max_reminders_per_user"]):
         await self.bot.say(
             channel,
             f"{author.mention} you already have {len(user_reminders)} reminders!",
         )
         return False
     if len(command_args) == 0:
         await self.bot.say(channel, embed=self.help)
         return False
     time_delta = utils.parse_timedelta(command_args[0])
     if not time_delta:
         await self.bot.say(
             channel, f"{author.mention} invalid time: {command_args[0]}")
         return False
     await self.bot.say(
         channel,
         f"{author.mention} ill remind you that in {utils.seconds_to_resp(time_delta.total_seconds())}",
     )
     bot_message = await self.bot.say(
         channel,
         f"If anyone else wants to be reminded click the {self.settings['emoji']}",
     )
     salt = utils.random_string()
     await bot_message.add_reaction(self.settings["emoji"])
     reminder = {
         "message_id": bot_message.id,
         "channel_id": bot_message.channel.id,
         "salt": salt,
         "message": " ".join(command_args[1:]),
         "date_of_reminder": str(utils.now() + time_delta),
         "date_reminder_set": str(utils.now()),
     }
     user_reminders.append(reminder)
     reminders_list[str(author.id)] = user_reminders
     self.redis.set(f"{self.bot.bot_name}:remind-me-reminders",
                    json.dumps(reminders_list))
     self.reminder_tasks[salt] = ScheduleManager.execute_delayed(
         time_delta.total_seconds(),
         self.execute_reminder,
         args=[salt, author.id, reminder],
     )
Example #16
0
def init(args):
    import subprocess
    import sys

    from flask import request
    from flask import session
    from flask_scrypt import generate_random_salt

    import greenbot.utils
    import greenbot.web.common
    import greenbot.web.routes

    from greenbot.managers.db import DBManager
    from greenbot.managers.redis import RedisManager
    from greenbot.managers.schedule import ScheduleManager
    from greenbot.models.module import ModuleManager
    from greenbot.models.sock import SocketClientManager
    from greenbot.utils import load_config
    from greenbot.web.models import errors
    from greenbot.bothelper import BotHelper

    ScheduleManager.init()

    config = load_config(args.config)

    redis_options = {}
    if "redis" in config:
        redis_options = dict(config["redis"])

    RedisManager.init(**redis_options)

    if "web" not in config:
        log.error("Missing [web] section in config.ini")
        sys.exit(1)

    if "secret_key" not in config["web"]:
        salt = generate_random_salt()
        config.set("web", "secret_key", salt.decode("utf-8"))

        with open(args.config, "w") as configfile:
            config.write(configfile)

    bot_name = config["main"]["bot_name"]
    BotHelper.set_bot_name(bot_name)
    SocketClientManager.init(bot_name)

    app.bot_modules = config["web"].get("modules", "").split()
    app.bot_commands_list = []
    app.bot_config = config
    app.secret_key = config["web"]["secret_key"]
    app.config["DISCORD_CLIENT_ID"] = app.bot_config["discord"]["client_id"]
    app.config["DISCORD_CLIENT_SECRET"] = app.bot_config["discord"][
        "client_secret"]
    app.config["DISCORD_REDIRECT_URI"] = app.bot_config["discord"][
        "redirect_uri"]
    app.bot_dev = ("flags" in config and "dev" in config["flags"]
                   and config["flags"]["dev"] == "1")

    DBManager.init(config["main"]["db"])

    app.module_manager = ModuleManager(None).load()

    greenbot.web.routes.admin.init(app)
    greenbot.web.routes.api.init(app)
    greenbot.web.routes.base.init(app)

    greenbot.web.common.filters.init(app)
    greenbot.web.common.assets.init(app)
    greenbot.web.common.menu.init(app)

    errors.init(app, config)

    last_commit = None
    if app.bot_dev:
        try:
            last_commit = (subprocess.check_output(
                ["git", "log", "-1", "--format=%cd"]).decode("utf8").strip())
        except:
            log.exception(
                "Failed to get last_commit, will not show last commit")

    default_variables = {
        "last_commit": last_commit,
        "version": "v1.0",
        "bot": {
            "name": config["main"]["bot_name"]
        },
        "site": {
            "domain": config["web"]["domain"]
        },
        "modules": app.bot_modules,
        "request": request,
        "session": session,
        "google_analytics": config["web"].get("google_analytics", None),
    }

    @app.context_processor
    def current_time():
        current_time = {}
        current_time["current_time"] = greenbot.utils.now()
        return current_time

    @app.context_processor
    def inject_default_variables():
        return default_variables
Example #17
0
 def execute_every(self, period, function, *args, **kwargs):
     ScheduleManager.execute_every(period,
                                   lambda: function(*args, **kwargs))
Example #18
0
 def execute_delayed(self, delay, function, *args, **kwargs):
     ScheduleManager.execute_delayed(delay,
                                     lambda: function(*args, **kwargs))
Example #19
0
    async def timeout_user(self, db_session, member, banner, until,
                           ban_reason):
        if not self.settings["enabled"]:
            return False, "Module is not enabled"
        current_timeout = Timeout._is_timedout(db_session, str(member.id))
        new_timeout = None
        if current_timeout is not None:
            if current_timeout.check_lengths(until):
                current_timeout.active = False
                new_timeout = Timeout._create(db_session, str(member.id),
                                              str(banner.id), until,
                                              ban_reason)
                db_session.commit()
                current_timeout.unban(
                    db_session,
                    None,
                    f"Timeout overwritten by Timeout #{new_timeout.id}",
                )
                db_session.commit()
            else:
                return (
                    False,
                    f"{member} is currently timedout by Timeout #{current_timeout.id}",
                )
        if not new_timeout:
            new_timeout = Timeout._create(db_session, str(member.id),
                                          str(banner.id), until, ban_reason)
            db_session.commit()
        await self.apply_timeout(member, new_timeout)

        if self.settings["log_timeout"]:
            embed = discord.Embed(
                title="Member has been timedout",
                timestamp=new_timeout.created_at,
                colour=member.colour,
            )
            embed.set_author(
                name=f"{member} ({member.id})- Timeout Removed",
                icon_url=str(member.avatar_url),
            )
            embed.add_field(
                name="Banned on",
                value=str(
                    new_timeout.created_at.strftime("%b %d %Y %H:%M:%S %Z")),
                inline=False,
            )
            if new_timeout.issued_by_id:
                issued_by = self.bot.filters.get_member(
                    [int(new_timeout.issued_by_id)], None, {})[0]
                embed.add_field(
                    name="Banned by",
                    value=issued_by.mention
                    if issued_by else f"{new_timeout.issued_by_id}",
                    inline=False,
                )
            if new_timeout.ban_reason:
                embed.add_field(name="Ban Reason",
                                value=str(new_timeout.ban_reason),
                                inline=False)
            await HandlerManager.trigger("aml_custom_log", embed=embed)
        if new_timeout.time_left:
            ScheduleManager.execute_delayed(
                new_timeout.time_left + 5,
                self.auto_untimeout,
                args=[new_timeout.id, self.salt],
            )
        return True, None
Example #20
0
    def load_commands(self, **options):
        if not self.bot:
            return

        ScheduleManager.execute_now(self.update_manager)
Example #21
0
 def enable(self, bot):
     if not bot:
         return
     self.process_messages_job = ScheduleManager.execute_every(
         3600, self.process_messages)  # Checks every hour