コード例 #1
0
    def __init__(self, plugin_args):
        self.generic_hooks = self.HookContainer(self.call_plugin_func)
        self.enabled_wiki_hooks = self.HookContainer(self.call_plugin_func)
        self.enabled_wikis = []

        self.wiki_pages_callbacks = {}

        self.plugin_args = plugin_args.copy()

        self.logger = botlog(self.__repr__())
コード例 #2
0
import time
import configparser
from oslo_concurrency.watchdog import watch
from database.db import db_data
from modbot import hook
from modbot.commands import add_inbox_command, add_report_command, execute_inbox_command, execute_report_command

# meh method of getting the callback list after loading, but works for now
from modbot.hook import callbacks, plugins_with_wikis
from modbot.hook import callback_type
from modbot import utils
from modbot.log import botlog
from modbot.moderated_sub import DispatchAll, DispatchSubreddit
from modbot.reddit_wrapper import get_moderated_subs, get_subreddit, start_tick, get_submission, watch_all, get_user

logger = botlog("plugin")

DISPATCH_ANY = 0  # Generic key for dispatching items to all non-bound hooks


class plugin_manager():
    # Dictionary of items that can be passed to plugins
    def __init__(self,
                 bot_inst,
                 master_subreddit,
                 path_list=None,
                 bot_config={},
                 db_params={}):
        """
        Class that manages plugins from a given list of paths.
        :param bot_inst: bot instance
コード例 #3
0
from modbot import hook
from modbot.log import botlog
from modbot.utils import parse_wiki_content

plugin_documentation = """
The plugin sends submissions or modlog items to given discord webhooks.

Configurable parameters are:
- modlog - sends modlog items to the webhook
- submissions - sends new submissions to the webhook

Example configuration:
modlog = http://webhook1
submissions = http://webhook2
"""
logger = botlog("webhook_plugin")

# Store wiki configuration per subreddit
wiki_config = {}

replaces = {"@everyone": "@ everyone", "@here": "@ here"}


class PluginCfg():
    def __init__(self, config):
        if "modlog" in config:
            self.modlog = config["modlog"]

        if "submissions" in config:
            self.submissions = config["submissions"]
コード例 #4
0
import prawcore
from modbot import utils
from modbot.log import botlog
from modbot.storage import dsdict

logger = botlog("wiki_page")
EMPTY_WIKI = ""

RECENT_EDIT_LIMIT = utils.timedata.SEC_IN_MIN * 2

# TODO: merge this class with reddit_wrapper.py/wiki


class WatchedWiki():
    class WikiChange():
        """
        Represents a changed wiki transaction
        """
        def __init__(self, wiki):
            self.author = wiki.author
            self.content = wiki.content
            self.revision_date = wiki.revision_date
            self.recent_edit = False

            # Check if it's a recent edit
            if utils.utcnow() - self.revision_date < RECENT_EDIT_LIMIT:
                self.recent_edit = True

    DOC_BEGIN = "    ###### <Documentation> (do not edit below)\n\n"
    DOC_END = "\n\n    ###### <Documentation> (do not edit above)\n"
コード例 #5
0
ファイル: hook.py プロジェクト: gc-plp/reddit-moderator-bot
import enum
import pathlib
import inspect

from modbot.log import botlog, loglevel

callbacks = []
plugins_with_wikis = []
logger = botlog('hook', file_level=loglevel.INFO)
hook_rights = {}  # Map of non standard hook rights


@enum.unique
class subreddit_type(enum.Enum):
    MASTER_SUBREDDIT = 0  # References the master subreddit


@enum.unique
class callback_type(enum.Enum):
    SUB = 0  # Submission
    COM = 1  # Comment
    PER = 2  # Periodic
    ONL = 3  # On load
    ONS = 4  # On start
    CMD = 5  # message command
    REP = 6  # report command
    MLG = 7  # modlog event


@enum.unique
class permission(enum.IntEnum):
コード例 #6
0
- If the new title is "AAA BBB CC DDD EEE FF", it will be transformed into "AAA BBB DDD EEE"
- Assuming that there is an older submission with the title "EEE DDD BBB", the new submission will be reported because it has 3 common words with the old one
- ignore_users - list of users to ignore

Recommended configuration:
[Setup]
minimum_word_length = 3
minimum_nb_words = 5
min_overlap_percent = 50
ignore_users = ["AutoModerator"]
"""

MAX_AGE = timedata.SEC_IN_DAY * 7  # Maximum age to keep posts
MAX_ACTION_TIME = timedata.SEC_IN_MIN  # Maximum time to wait to take an action

logger = botlog("repost_detector")

# Store wiki configuration per subreddit
wiki_config = {}


class RepostCfg():
    def __init__(self, config):
        self.ignore_users = []
        self.min_overlap_percent = min(
            max(int(config["min_overlap_percent"]), 0), 100)
        self.minimum_nb_words = int(config["minimum_nb_words"])
        self.minimum_word_length = int(config["minimum_word_length"])

        if "ignore_users" in config:
            raw_users = ast.literal_eval(config["ignore_users"])
コード例 #7
0
import os
import json
import collections
import platform
import shutil
from modbot.log import botlog, loglevel
from shutil import copyfile
from oslo_concurrency import lockutils

logger = botlog("storage.log",
                console_level=loglevel.ERROR,
                file_level=loglevel.ERROR)

DS_LOC = "storage_data/"

dsdict_cache = {}


def get_stored_dict(parent, name):
    path = "%s/%s" % (parent, name)

    if path not in dsdict_cache:
        dsdict_cache[path] = dsdict(parent, name)

    return dsdict_cache[path]


class dstype():
    def __init__(self, parent, name):
        if not name.endswith(".json"):
            name = name + ".json"
コード例 #8
0
ファイル: status.py プロジェクト: gc-plp/reddit-moderator-bot
from modbot import hook
from modbot import utils
from modbot.log import botlog

start_date = utils.date()
logger = botlog("audit")

wiki = hook.register_wiki_page(
    wiki_page="bot_startup",
    description="Marks when the bot has started up (always enabled)",
    default_enabled=True,
    subreddits=[hook.subreddit_type.MASTER_SUBREDDIT])


@hook.on_start(wiki=wiki)
def mark_startup(wiki_pages):
    page = wiki_pages["bot_startup"][0]
    page.update_content()

    new_content = page.content.split("\n")
    new_content.insert(
        0,
        "Bot startup: %s; Plugin startup: %s\n" % (start_date, utils.date()))
    logger.info("Bot startup: %s; Plugin startup: %s\n" %
                (start_date, utils.date()))

    # Only upload the last 100 startups
    page.set_content("\n".join(new_content[:100]))
コード例 #9
0
This plugin checks if a link post has been posted with a different title than the original one.
If the difference is larger than a given limit, the post is reported.

Configurable parameters are:
- minimum_overlap_percent - the post title and the article title must overlap at least the given amount, else it's reported (value should be given between 0 and 100)
- domains - list of domains that should be checked
- ignore_users - list of users to ignore

Example configuration:
minimum_overlap_percent = 60
domains = ["google.com", "blabla.co.uk"]
ignore_users = ["AutoModerator"]
"""

MAX_ACTION_TIME = timedata.SEC_IN_MIN  # Maximum time to wait to take an action
logger = botlog("changed_title")

# Store wiki configuration per subreddit
wiki_config = {}


class PluginCfg():
    def __init__(self, config):
        self.domains = []
        self.ignore_users = []
        # Mark that a configuration is valid
        self.valid = False

        if "minimum_overlap_percent" not in config:
            return
コード例 #10
0
ファイル: reddit.py プロジェクト: gc-plp/reddit-moderator-bot
import praw
import prawcore
import time
import requests
import json
from modbot.log import botlog, loglevel
from modbot.utils import utcnow, timedata

praw_credentials = None
praw_user_agent = None
praw_inst = {}  # Dictionary of praw sessions
logger = botlog("redditinput", console_level=loglevel.DEBUG)
audit = botlog("audit", console_level=loglevel.DEBUG)


class Thing():
    """
    Thing class to mock reddit thing
    """

    def __init__(self, id):
        self.id = id


def set_praw_opts(credentials, user_agent):
    """
    Set authentication options
    """
    global praw_credentials
    global praw_user_agent
コード例 #11
0
# Log all exceptions
import sys
import traceback
from modbot.log import botlog

logger = botlog("exception")


def log_exception(type, value, tb):
    trace = traceback.format_list(traceback.extract_tb(tb))
    logger.error(value.args[0] + "\n" + "".join(trace))

    original_hook(type, value, tb)


# Save the original hook and add a custom one
original_hook = sys.excepthook
sys.excepthook = log_exception
コード例 #12
0
import logging
import copy
from modbot import utils
from modbot.log import botlog
from modbot.wiki_page import WatchedWiki
from modbot.hook import callback_type
from modbot.storage import get_stored_dict
from modbot.utils import BotThread, cron_next

logger = botlog("mod_sub")


class DispatchAll():
    class HookContainer():
        def __init__(self, to_call):
            self.callbacks_peri = []
            self.callbacks_subs = []
            self.callbacks_coms = []
            self.callbacks_mlog = []
            self.callbacks_onstart = []
            self.callbacks = []
            self.to_call = to_call
            self.extra_args = {}

        def add_hook(self, func, last_exec=utils.utcnow()):
            # Create an unique copy for this container
            func = copy.copy(func)
            if func.ctype == callback_type.SUB:
                self.callbacks_subs.append(func)

            elif func.ctype == callback_type.COM:
コード例 #13
0
from collections import OrderedDict
from modbot import hook
from modbot.log import botlog
from modbot.utils import parse_wiki_content
from modbot.reddit_wrapper import get_subreddit
from modbot.utils_images import get_picture, gen_fname

plugin_documentation = """
Change sidebar pictures each day.

Configurable parameters are:

Example configuration:

"""
logger = botlog("change_sidebar")

# Store wiki configuration per subreddit
wiki_config = {}

START_MARKER = "[](/begin-pics)"
END_MARKER = "[](/end-pics)"


class PluginCfg():
    def __init__(self, config):
        self.items = OrderedDict()
        for item in config:
            self.items[item] = config[item]

コード例 #14
0
Example configuration:
[some_channel]
id = 123456
message = got a post by some channel
report = reports are optional

[some_other_channel]
id = ABCDEFG
message = blah

[another_channel]
id = ABCDEFG
delete = True
"""

logger = botlog("yt")

# Store wiki configuration per subreddit
wiki_config = {}

# Taken from: https://stackoverflow.com/questions/19377262/regex-for-youtube-url
yt_validator = re.compile(
    r"^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(\S+)?$"
)


class PluginCfg():
    @dataclass
    class YTConfig:
        """Keeps config for a youtube channel."""
        ytid: str
コード例 #15
0
import pathlib

from modbot import hook
from modbot.log import botlog
from modbot.reddit_wrapper import get_moderator_users
from modbot.utils import BotThread
from modbot.storage import get_stored_dict

inbox_cmd_list = {}
report_cmd_list = {}
raw_cmd_list = {}
cmd_prefix = "/"

logger = botlog("commands")


class command():
    def __repr__(self):
        return "%s - %s" % (self.name, self.doc.strip())

    def __init__(self, func, name, documentation, requested_args, path):
        self.func = func
        self.name = name
        self.doc = documentation
        self.requested_args = requested_args
        self.path = path

        self.plugin_name = pathlib.Path(path).name.replace(".py", "")


def add_inbox_command(plugin_func):
コード例 #16
0
plugin_documentation = """
Sends a modmail message when a specific word is detected in a comment or submission anywhere on reddit.
A word must be at least 4 letters long. Shorter expressions will be ignored.

Configurable parameters are:
- word_list - list of words or expressions to trigger messages on
- ignore_users - list of users to ignore

Example configuration:
[Setup]
word_list = ["bla bla", "asdfg", "123456"]
ignore_users = ["yosemitesam", "bugsbunny]
"""

MIN_LEN = 4
logger = botlog("notify_on_word")

# Store wiki configuration per subreddit
wiki_config = {}


class PluginCfg():
    def __init__(self, config):
        word_list = ast.literal_eval(config["word_list"])

        self.word_list = []
        for word in word_list:
            if len(word) <= MIN_LEN:
                continue
            self.word_list.append(word)
コード例 #17
0
import traceback
import time
import base36
import importlib
from modbot.log import botlog, loglevel
from modbot.utils import utcnow, timedata, BotThread, get_utcnow
from modbot.storage import dsdict, get_stored_dict
from modbot.input.rpc_server import create_server

logger = botlog("reddit_wrapper", console_level=loglevel.DEBUG)
audit = botlog("audit", console_level=loglevel.DEBUG)
watch_dict = {}  # maps watched subreddits to threads

posted_things_body = get_stored_dict("all", "posted")

backend = None
all_data = None
subreddit_cache = None
wiki_storages = None
sub_feeder = None
com_feeder = None
bot_signature = None
inbox_thread = None
last_inbox_update = None
report_cmds = None
cache_data = None
modlog_hist = None

last_moderator_subs_check = 0
moderator_subs_list = []