Exemplo n.º 1
0
def toggle_safety(bot: SopelWrapper, trigger: Trigger):
    """Set safety setting for channel."""
    if not trigger.admin and bot.channels[trigger.sender].privileges[
            trigger.nick] < plugin.OP:
        bot.reply('Only channel operators can change safety settings')
        return

    new_mode = None
    if trigger.group(2):
        new_mode = trigger.group(2).lower()

    if not new_mode or (new_mode != "default"
                        and new_mode not in SAFETY_MODES):
        bot.reply(
            "Current mode: {}. Available modes: {}, or default ({})".format(
                bot.db.get_channel_value(
                    trigger.sender,
                    "safety",
                    "default",
                ),
                ", ".join(SAFETY_MODES),
                bot.settings.safety.default_mode,
            ))
        return

    if new_mode == "default":
        bot.db.delete_channel_value(trigger.sender, "safety")
    else:
        bot.db.set_channel_value(trigger.sender, "safety", new_mode)
    bot.say('Safety is now set to "%s" for this channel' % new_mode)
Exemplo n.º 2
0
def url_handler(bot: SopelWrapper, trigger: Trigger):
    """Checks for malicious URLs."""
    mode = bot.db.get_channel_value(
        trigger.sender,
        "safety",
        bot.settings.safety.default_mode,
    )
    if mode == "off":
        return
    local_only = "local" in mode or bot.settings.safety.vt_api_key is None
    strict = "strict" in mode

    for url in tools.web.search_urls(trigger):
        safe_url = safeify_url(url)

        positives = 0  # Number of engines saying it's malicious
        total = 0  # Number of total engines

        try:
            hostname = urlparse(url).hostname.lower()
        except ValueError:
            pass  # Invalid address
        else:
            if any(regex.search(hostname) for regex in known_good):
                continue  # explicitly trusted

            if hostname in bot.memory[SAFETY_CACHE_LOCAL_KEY]:
                LOGGER.debug("[local] domain in blocklist: %r", hostname)
                positives += 1
                total += 1

        result = virustotal_lookup(bot, url, local_only=local_only)
        if result:
            positives += result["positives"]
            total += result["total"]

        if positives >= 1:
            # Possibly malicious URL detected!
            LOGGER.info(
                "Possibly malicious link (%s/%s) posted in %s by %s: %r",
                positives,
                total,
                trigger.sender,
                trigger.nick,
                safe_url,
            )
            bot.say(
                "{} {} of {} engine{} flagged a link {} posted as malicious".
                format(
                    bold(color("WARNING:", colors.RED)),
                    positives,
                    total,
                    "" if total == 1 else "s",
                    bold(trigger.nick),
                ))
            if strict:
                bot.kick(trigger.nick, trigger.sender,
                         "Posted a malicious link")
Exemplo n.º 3
0
def title_auto(bot: SopelWrapper, trigger: Trigger):
    """
    Automatically show titles for URLs. For shortened URLs/redirects, find
    where the URL redirects to and show the title for that (or call a function
    from another plugin to give more information).
    """
    # Enabled or disabled by feature flag
    if not bot.settings.url.enable_auto_title:
        return

    # Avoid fetching links from another command
    if re.match(bot.config.core.prefix + r'\S+', trigger):
        return

    unchecked_urls = web.search_urls(
        trigger, exclusion_char=bot.config.url.exclusion_char, clean=True)

    urls = []
    safety_cache = bot.memory.get("safety_cache", {})
    safety_cache_local = bot.memory.get("safety_cache_local", {})
    for url in unchecked_urls:
        # Avoid fetching known malicious links
        if url in safety_cache and safety_cache[url]["positives"] > 0:
            continue
        if urlparse(url).hostname.lower() in safety_cache_local:
            continue
        urls.append(url)

    for url, title, domain, tinyurl, dispatched in process_urls(
            bot, trigger, urls):
        if not dispatched:
            message = '%s | %s' % (title, domain)
            if tinyurl:
                message += ' ( %s )' % tinyurl
            # Guard against responding to other instances of this bot.
            if message != trigger:
                bot.say(message)
        bot.memory["last_seen_url"][trigger.sender] = url