Exemple #1
0
def commit_info(bot, trigger, match=None):
    match = match or trigger
    URL = 'https://api.github.com/repos/%s/commits/%s' % (match.group(1),
                                                          match.group(2))

    try:
        raw = fetch_api_endpoint(bot, URL)
    except HTTPError:
        bot.say('[Github] API returned an error.')
        return NOLIMIT
    data = json.loads(raw)
    try:
        if len(data['commit']['message'].split('\n')) > 1:
            body = data['commit']['message'].split('\n')[0] + '...'
        else:
            body = data['commit']['message'].split('\n')[0]
    except (KeyError):
        bot.say(
            '[Github] API says this is an invalid commit. Please report this if you know it\'s a correct link!'
        )
        return NOLIMIT

    if body.strip() == '':
        body = 'No commit message provided.'

    response = [
        bold('[Github]'), ' [',
        match.group(1), '] ', data['author']['login'], ': ', body,
        bold(' | '),
        str(data['stats']['total']), ' changes in ',
        str(len(data['files'])), ' files'
    ]
    bot.say(''.join(response))
Exemple #2
0
def issue_info(bot, trigger, match=None):
    match = match or trigger
    URL = 'https://api.github.com/repos/%s/issues/%s' % (match.group(1),
                                                         match.group(2))

    try:
        raw = fetch_api_endpoint(bot, URL)
    except HTTPError:
        bot.say('[Github] API returned an error.')
        return NOLIMIT
    data = json.loads(raw)
    try:
        if len(data['body'].split('\n')) > 1:
            body = data['body'].split('\n')[0] + '...'
        else:
            body = data['body'].split('\n')[0]
    except (KeyError):
        bot.say(
            '[Github] API says this is an invalid issue. Please report this if you know it\'s a correct link!'
        )
        return NOLIMIT

    if body.strip() == '':
        body = 'No description provided.'

    response = [
        bold('[Github]'), ' [',
        match.group(1), ' #',
        str(data['number']), '] ', data['user']['login'], ': ', data['title'],
        bold(' | '), body
    ]
    bot.say(''.join(response))
Exemple #3
0
def issue_info(bot, trigger, match=None):
    match = match or trigger
    URL = 'https://api.github.com/repos/%s/issues/%s' % (match.group(1), match.group(2))

    try:
        raw = web.get(URL)
    except HTTPError:
        bot.say('The GitHub API returned an error.')
        return NOLIMIT
    data = json.loads(raw)
    try:
        if len(data['body'].split('\n')) > 1:
            body = data['body'].split('\n')[0] + '...'
        else:
            body = data['body'].split('\n')[0]
    except (KeyError):
        bot.say('The API says this is an invalid issue. Please report this if you know it\'s a correct link!')
        return NOLIMIT
    response = [
        bold('[Github]'),
        ' [', 
        match.group(1), 
        ' #', 
        str(data['number']),
        '] ',
        data['user']['login'],
        ': ',
        data['title'],
        bold(' | '),
        body
    ]
    bot.say(''.join(response))
Exemple #4
0
def default_mask(trigger):
    welcome = formatting.color('Benvenuto su:', formatting.colors.PURPLE)
    chan = formatting.color(trigger.sender, formatting.colors.TEAL)
    topic_ = formatting.bold('Topic:')
    topic_ = formatting.color('| ' + topic_, formatting.colors.PURPLE)
    arg = formatting.color('{}', formatting.colors.GREEN)
    return '{} {} {} {}'.format(welcome, chan, topic_, arg)
Exemple #5
0
def default_mask(trigger):
    welcome = formatting.color('Welcome to:', formatting.colors.PURPLE)
    chan = formatting.color(trigger.sender, formatting.colors.TEAL)
    topic_ = formatting.bold('Topic:')
    topic_ = formatting.color('| ' + topic_, formatting.colors.PURPLE)
    arg = formatting.color('{}', formatting.colors.GREEN)
    return '{} {} {} {}'.format(welcome, chan, topic_, arg)
def fmt_response(bot, trigger, URL, from_regex=False):
    data = get_data(bot, trigger, URL)

    if not data:
        return

    response = [bold("[Github]"), " ", str(data["full_name"])]

    if data["description"] != None:
        response.append(" - " + str(data["description"]))

    if not data["language"].strip() == "":
        response.extend([" | ", data["language"].strip()])

    response.extend(
        [
            " | Last Push: ",
            str(data["pushed_at"]),
            " | Stargazers: ",
            str(data["stargazers_count"]),
            " | Watchers: ",
            str(data["watchers_count"]),
            " | Forks: ",
            str(data["forks_count"]),
            " | Network: ",
            str(data["network_count"]),
            " | Open Issues: ",
            str(data["open_issues"]),
        ]
    )

    if not from_regex:
        response.extend([" | ", data["html_url"]])

    bot.say("".join(response))
Exemple #7
0
def fmt_response(bot, trigger, URL, from_regex=False):
    data = get_data(bot, trigger, URL)

    if not data:
        return

    response = [bold('[Github]'), ' ', str(data['full_name'])]

    if data['description'] != None:
        response.append(' - ' + str(data['description']))

    if not data['language'].strip() == '':
        response.extend([' | ', data['language'].strip()])

    response.extend([
        ' | Last Push: ',
        str(data['pushed_at']), ' | Stargazers: ',
        str(data['stargazers_count']), ' | Watchers: ',
        str(data['watchers_count']), ' | Forks: ',
        str(data['forks_count']), ' | Network: ',
        str(data['network_count']), ' | Open Issues: ',
        str(data['open_issues'])
    ])

    if not from_regex:
        response.extend([' | ', data['html_url']])

    bot.say(''.join(response))
def issue_info(bot, trigger, match=None):
    match = match or trigger
    URL = 'https://api.github.com/repos/%s/issues/%s' % (match.group(1), match.group(2))
    if (match.group(3)):
        URL = 'https://api.github.com/repos/%s/issues/comments/%s' % (match.group(1), match.group(3))

    try:
        raw = fetch_api_endpoint(bot, URL)
    except HTTPError:
        bot.say('[Github] API returned an error.')
        return NOLIMIT
    data = json.loads(raw)
    try:
        if len(data['body'].split('\n')) > 1 and len(data['body'].split('\n')[0]) > 180:
            body = data['body'].split('\n')[0] + '...'
        elif len(data['body'].split('\n')) > 2 and len(data['body'].split('\n')[0]) <= 180:
            body = ' '.join(data['body'].split('\n')[:2]) + '...'
        else:
            body = data['body'].split('\n')[0]
    except (KeyError):
        bot.say('[Github] API says this is an invalid issue. Please report this if you know it\'s a correct link!')
        return NOLIMIT

    if body.strip() == '':
        body = 'No description provided.'

    response = [
        bold('[Github]'),
        ' [',
        match.group(1),
        ' #',
        match.group(2),
        '] ',
        data['user']['login'],
        ': '
    ]

    if ('title' in data):
        response.append(data['title'])
        response.append(bold(' | '))
    response.append(body)

    bot.say(''.join(response))
def error(bot, msg):
    print("{}: {}".format(str(datetime.datetime.now()), msg))

    if "initialized" in bot.memory:
        if "last_error_msg" not in bot.memory["ff"] or bot.memory["ff"]["last_error_msg"] != msg:
            bot.memory["ff"]["last_error_msg"] = msg
            bot.msg(
                bot.config.freifunk.change_announce_target,
                formatting.color("{}: {}".format(formatting.bold("[ERROR]"), msg), formatting.colors.RED),
            )
Exemple #10
0
def rpost_info(bot, trigger, match=None):
    r = praw.Reddit(user_agent=USER_AGENT)
    match = match or trigger
    s = r.get_submission(url=match.group(1))

    message = ('[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | '
               '{comments} comments | Posted by {author} | '
               'Created at {created}')

    if s.is_self:
        link = '(self.{})'.format(s.subreddit.display_name)
    else:
        link = '({}) to r/{}'.format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(' [NSFW]', colors.RED))
        sfw = bot.db.get_channel_value(trigger.sender, 'sfw')
        if sfw:
            link = '(link hidden)'
            bot.write([
                'KICK', trigger.sender, trigger.nick,
                'Linking to NSFW content in a SFW channel.'
            ])
    else:
        nsfw = ''

    if s.author:
        author = s.author.name
    else:
        author = '[deleted]'

    tz = time.get_timezone(bot.db, bot.config, None, trigger.nick,
                           trigger.sender)
    time_created = dt.datetime.utcfromtimestamp(s.created_utc)
    created = time.format_time(bot.db, bot.config, tz, trigger.nick,
                               trigger.sender, time_created)

    if s.score > 0:
        point_color = colors.GREEN
    else:
        point_color = colors.RED

    percent = color(unicode(s.upvote_ratio * 100) + '%', point_color)

    h = HTMLParser.HTMLParser()
    message = message.format(title=h.unescape(s.title),
                             link=link,
                             nsfw=nsfw,
                             points=s.score,
                             percent=percent,
                             comments=s.num_comments,
                             author=author,
                             created=created)

    bot.say(message)
def rpost_info(bot, trigger, match=None):
    r = praw.Reddit(user_agent=USER_AGENT)
    match = match or trigger
    s = r.get_submission(url=match.group(1))

    message = (
        "[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | "
        "{comments} comments | Posted by {author} | "
        "Created at {created}"
    )

    if s.is_self:
        link = "(self.{})".format(s.subreddit.display_name)
    else:
        link = "({}) to r/{}".format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(" [NSFW]", colors.RED))
        sfw = bot.db.get_channel_value(trigger.sender, "sfw")
        if sfw:
            link = "(link hidden)"
            bot.write(["KICK", trigger.sender, trigger.nick, "Linking to NSFW content in a SFW channel."])
    else:
        nsfw = ""

    if s.author:
        author = s.author.name
    else:
        author = "[deleted]"

    tz = time.get_timezone(bot.db, bot.config, None, trigger.nick, trigger.sender)
    time_created = dt.datetime.utcfromtimestamp(s.created_utc)
    created = time.format_time(bot.db, bot.config, tz, trigger.nick, trigger.sender, time_created)

    if s.score > 0:
        point_color = colors.GREEN
    else:
        point_color = colors.RED

    percent = color(unicode(s.upvote_ratio * 100) + "%", point_color)

    h = HTMLParser.HTMLParser()
    message = message.format(
        title=h.unescape(s.title),
        link=link,
        nsfw=nsfw,
        points=s.score,
        percent=percent,
        comments=s.num_comments,
        author=author,
        created=created,
    )

    bot.say(message)
def rpost_info(bot, trigger, match=None):
    r = praw.Reddit(user_agent=USER_AGENT)
    match = match or trigger
    s = r.get_submission(url=match.group(1))

    if (comment_regex.match(match.group(0))):
        return rcomment_info(bot, trigger, s)

    message = ('[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | '
               '{comments} comments | Posted by {author} | '
               'Created at {created}')

    if s.is_self:
        link = '(self.{})'.format(s.subreddit.display_name)
    else:
        link = '({}) to /r/{}'.format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(' [NSFW]', colors.RED))
        sfw = bot.db.get_channel_value(trigger.sender, 'sfw')
        if sfw:
            link = '(link hidden)'
            bot.write(['KICK', trigger.sender, trigger.nick,
                       'Linking to NSFW content in a SFW channel.'])
    else:
        nsfw = ''

    if s.author:
        author = s.author.name
    else:
        author = '[deleted]'

    tz = time.get_timezone(bot.db, bot.config, None, trigger.nick,
                           trigger.sender)
    time_created = dt.datetime.utcfromtimestamp(s.created_utc)
    created = time.format_time(bot.db, bot.config, tz, trigger.nick,
                               trigger.sender, time_created)

    if s.score > 0:
        point_color = colors.GREEN
    else:
        point_color = colors.RED

    percent = color(unicode(s.upvote_ratio * 100) + '%', point_color)

    h = HTMLParser.HTMLParser()
    message = message.format(
        title=h.unescape(s.title), link=link, nsfw=nsfw, points=s.score, percent=percent,
        comments=s.num_comments, author=author, created=created)

    bot.say(message)
def commit_info(bot, trigger, match=None):
    match = match or trigger
    URL = 'https://api.github.com/repos/%s/commits/%s' % (match.group(1), match.group(2))

    try:
        raw = fetch_api_endpoint(bot, URL)
    except HTTPError:
        bot.say('[Github] API returned an error.')
        return NOLIMIT
    data = json.loads(raw)
    try:
        if len(data['commit']['message'].split('\n')) > 1:
            body = data['commit']['message'].split('\n')[0] + '...'
        else:
            body = data['commit']['message'].split('\n')[0]
    except (KeyError):
        bot.say('[Github] API says this is an invalid commit. Please report this if you know it\'s a correct link!')
        return NOLIMIT

    if body.strip() == '':
        body = 'No commit message provided.'

    response = [
        bold('[Github]'),
        ' [',
        match.group(1),
        '] ',
        data['author']['login'],
        ': ',
        body,
        bold(' | '),
        str(data['stats']['total']),
        ' changes in ',
        str(len(data['files'])),
        ' files'
    ]
    bot.say(''.join(response))
def commit_info(bot, trigger, match=None):
    match = match or trigger
    URL = "https://api.github.com/repos/%s/commits/%s" % (match.group(1), match.group(2))

    try:
        raw = fetch_api_endpoint(bot, URL)
    except HTTPError:
        bot.say("[Github] API returned an error.")
        return NOLIMIT
    data = json.loads(raw)
    try:
        if len(data["commit"]["message"].split("\n")) > 1:
            body = data["commit"]["message"].split("\n")[0] + "..."
        else:
            body = data["commit"]["message"].split("\n")[0]
    except (KeyError):
        bot.say("[Github] API says this is an invalid commit. Please report this if you know it's a correct link!")
        return NOLIMIT

    if body.strip() == "":
        body = "No commit message provided."

    response = [
        bold("[Github]"),
        " [",
        match.group(1),
        "] ",
        data["author"]["login"],
        ": ",
        body,
        bold(" | "),
        str(data["stats"]["total"]),
        " changes in ",
        str(len(data["files"])),
        " files",
    ]
    bot.say("".join(response))
def issue_info(bot, trigger, match=None):
    match = match or trigger
    URL = "https://api.github.com/repos/%s/issues/%s" % (match.group(1), match.group(2))

    try:
        raw = fetch_api_endpoint(bot, URL)
    except HTTPError:
        bot.say("[Github] API returned an error.")
        return NOLIMIT
    data = json.loads(raw)
    try:
        if len(data["body"].split("\n")) > 1:
            body = data["body"].split("\n")[0] + "..."
        else:
            body = data["body"].split("\n")[0]
    except (KeyError):
        bot.say("[Github] API says this is an invalid issue. Please report this if you know it's a correct link!")
        return NOLIMIT

    if body.strip() == "":
        body = "No description provided."

    response = [
        bold("[Github]"),
        " [",
        match.group(1),
        " #",
        str(data["number"]),
        "] ",
        data["user"]["login"],
        ": ",
        data["title"],
        bold(" | "),
        body,
    ]
    bot.say("".join(response))
def rcomment_info(bot, trigger, s):
    message = ('[REDDIT] Comment on {link}{nsfw} | {created} | {points} points | '
               '{author}: {message}')

    if (s.comments[0] == None):
        return

    c = s.comments[0]
    
    if s.is_self:
        link = '(self.{})'.format(s.subreddit.display_name)
    else:
        link = '({}) to /r/{}'.format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(' [NSFW]', colors.RED))
        sfw = bot.db.get_channel_value(trigger.sender, 'sfw')
        if sfw:
            link = '(link hidden)'
            bot.write(['KICK', trigger.sender, trigger.nick,
                       'Linking to NSFW content in a SFW channel.'])
    else:
        nsfw = ''

    if c.author:
        author = c.author.name
    else:
        author = '[deleted]'

    tz = time.get_timezone(bot.db, bot.config, None, trigger.nick,
                           trigger.sender)
    time_created = dt.datetime.utcfromtimestamp(c.created_utc)
    created = time.format_time(bot.db, bot.config, tz, trigger.nick,
                               trigger.sender, time_created)

    h = HTMLParser.HTMLParser()
    message = message.format(
        title=h.unescape(s.title), link=s.short_link, nsfw=nsfw, points=c.score,
        author=author, created=created, message=c)

    bot.say(message)
Exemple #17
0
def rpost_info(bot, trigger, match=None):
    r = praw.Reddit(user_agent=USER_AGENT)
    match = match or trigger
    s = r.get_submission(url=match.group(1))

    message = ('[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | '
               '{comments} comments | Posted by {author}')

    if s.is_self:
        link = '(self.{})'.format(s.subreddit.display_name)
    else:
        link = '({}) to r/{}'.format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(' [NSFW]', colors.RED))
        #TODO implement per-channel settings db, and make this able to kick
    else:
        nsfw = ''

    if s.author:
        author = s.author.name
    else:
        author = '[deleted]'
    #TODO add creation time with s.created

    if s.score > 0:
        point_color = colors.GREEN
    else:
        point_color = colors.RED

    percent = color(unicode(s.upvote_ratio * 100) + '%', point_color)

    message = message.format(title=s.title,
                             link=link,
                             nsfw=nsfw,
                             points=s.score,
                             percent=percent,
                             comments=s.num_comments,
                             author=author)
    bot.say(message)
def fmt_response(bot, trigger, URL, from_regex=False):
    data = get_data(bot, trigger, URL)

    if not data:
        return

    response = [
        bold('[Github]'),
        ' ',
        str(data['full_name'])
    ]

    if data['description'] != None:
        response.append(' - ' + str(data['description']))

    if not data['language'].strip() == '':
        response.extend([' | ', data['language'].strip()])

    response.extend([
        ' | Last Push: ',
        str(data['pushed_at']),
        ' | Stargazers: ',
        str(data['stargazers_count']),
        ' | Watchers: ',
        str(data['watchers_count']),
        ' | Forks: ',
        str(data['forks_count']),
        ' | Network: ',
        str(data['network_count']),
        ' | Open Issues: ',
        str(data['open_issues'])
    ])

    if not from_regex:
        response.extend([' | ', data['html_url']])

    bot.say(''.join(response))
Exemple #19
0
def rpost_info(bot, trigger, match=None):
    r = praw.Reddit(user_agent=USER_AGENT)
    match = match or trigger
    s = r.get_submission(url=match.group(1))

    message = (
        "[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | " "{comments} comments | Posted by {author}"
    )

    if s.is_self:
        link = "(self.{})".format(s.subreddit.display_name)
    else:
        link = "({}) to r/{}".format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(" [NSFW]", colors.RED))
        # TODO implement per-channel settings db, and make this able to kick
    else:
        nsfw = ""

    if s.author:
        author = s.author.name
    else:
        author = "[deleted]"
    # TODO add creation time with s.created

    if s.score > 0:
        point_color = colors.GREEN
    else:
        point_color = colors.RED

    percent = color(unicode(s.upvote_ratio * 100) + "%", point_color)

    message = message.format(
        title=s.title, link=link, nsfw=nsfw, points=s.score, percent=percent, comments=s.num_comments, author=author
    )
    bot.say(message)
Exemple #20
0
def rpost_info(bot, trigger, match=None):
    r = praw.Reddit(user_agent=USER_AGENT)
    match = match or trigger
    s = r.get_submission(url=match.group(1))

    message = ('[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | '
               '{comments} comments | Posted by {author} {ago}')

    if s.is_self:
        link = '(self.{})'.format(s.subreddit.display_name)
    else:
        link = '({}) to r/{}'.format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(' [NSFW]', colors.RED))
        #TODO implement per-channel settings db, and make this able to kick
    else:
        nsfw = ''

    if s.author:
        author = s.author.name
    else:
        author = '[deleted]'

    if s.score > 0:
        point_color = colors.GREEN
    else:
        point_color = colors.RED

    percent = color(unicode(s.upvote_ratio * 100) + '%', point_color)

    posted_ago = human(datetime.datetime.utcnow() - datetime.datetime.utcfromtimestamp(int(s.created_utc)))

    message = message.format(
        title=s.title, link=link, nsfw=nsfw, points=s.score, percent=percent,
        comments=s.num_comments, author=author, ago=posted_ago)
    bot.say(message)
Exemple #21
0
def rpost_info(bot, trigger, match=None):
    r = praw.Reddit(user_agent='Willie IRC bot - see dft.ba/-williesource for more')
    match = match or trigger
    s = r.get_submission(url=match.group(1))

    message = ('[REDDIT] {title} {link}{nsfw} | {points} points ({percent}) | '
               '{comments} comments | Posted by {author}')

    if s.is_self:
        link = '(self.{})'.format(s.subreddit.display_name)
    else:
        link = '({}) to r/{}'.format(s.url, s.subreddit.display_name)

    if s.over_18:
        nsfw = bold(color(' [NSFW]', colors.RED))
        #TODO implement per-channel settings db, and make this able to kick
    else:
        nsfw = ''

    if s.author:
        author = s.author.name
    else:
        author = '[deleted]'
    #TODO add creation time with s.created

    if s.score > 0:
        point_color = colors.GREEN
    else:
        point_color = colors.RED

    percent = color(unicode(s.upvote_ratio * 100) + '%', point_color)

    message = message.format(
        title=s.title, link=link, nsfw=nsfw, points=s.score, percent=percent,
        comments=s.num_comments, author=author)
    bot.say(message)
Exemple #22
0
def url_handler(bot, trigger):
    """ Check for malicious URLs """
    check = True  # Enable URL checking
    strict = False  # Strict mode: kick on malicious URL
    positives = 0  # Number of engines saying it's malicious
    total = 0  # Number of total engines
    use_vt = True  # Use VirusTotal
    if bot.config.has_section('safety'):
        check = bot.config.safety.enabled_by_default
        if check is None:
            # If not set, assume default
            check = True
        else:
            check = bool(check)
    # DB overrides config:
    setting = bot.db.get_channel_value(trigger.sender, 'safety')
    if setting is not None:
        if setting == 'off':
            return  # Not checking
        elif setting in ['on', 'strict', 'local', 'local strict']:
            check = True
        if setting == 'strict' or setting == 'local strict':
            strict = True
        if setting == 'local' or setting == 'local strict':
            use_vt = False

    if not check:
        return  # Not overriden by DB, configured default off

    netloc = urlparse(trigger).netloc
    if any(regex.search(netloc) for regex in known_good):
        return  # Whitelisted

    apikey = bot.config.safety.vt_api_key
    try:
        if apikey is not None and use_vt:
            payload = {
                'resource': unicode(trigger),
                'apikey': apikey,
                'scan': '1'
            }

            if trigger not in bot.memory['safety_cache']:
                result = web.post(vt_base_api_url + 'report', payload)
                if sys.version_info.major > 2:
                    result = result.decode('utf-8')
                result = json.loads(result)
                age = time.time()
                data = {
                    'positives': result['positives'],
                    'total': result['total'],
                    'age': age
                }
                bot.memory['safety_cache'][trigger] = data
                if len(bot.memory['safety_cache']) > 1024:
                    _clean_cache(bot)
            else:
                print('using cache')
                result = bot.memory['safety_cache'][trigger]
            positives = result['positives']
            total = result['total']
    except Exception as e:
        LOGGER.debug('Error from checking URL with VT.', exc_info=True)
        pass  # Ignoring exceptions with VT so MalwareDomains will always work

    if unicode(netloc).lower() in malware_domains:
        # malwaredomains is more trustworthy than some VT engines
        # therefor it gets a weight of 10 engines when calculating confidence
        positives += 10
        total += 10

    if positives > 1:
        # Possibly malicious URL detected!
        confidence = '{}%'.format(round((positives / total) * 100))
        msg = 'link posted by %s is possibliy malicious ' % bold(trigger.nick)
        msg += '(confidence %s - %s/%s)' % (confidence, positives, total)
        bot.say('[' + bold(color('WARNING', 'red')) + '] ' + msg)
        if strict:
            bot.write([
                'KICK', trigger.sender, trigger.nick, 'Posted a malicious link'
            ])
def findandreplace(bot, trigger):
    # Don't bother in PM
    if trigger.is_privmsg:
        return

    # Correcting other person vs self.
    rIdentifier = Identifier(trigger.group(1) or trigger.nick)

    search_dict = bot.memory['find_lines']
    # only do something if there is conversation to work with
    if trigger.sender not in search_dict:
        return
    if Identifier(rIdentifier) not in search_dict[trigger.sender]:
        return

    rest = [trigger.group(2), trigger.group(3)]
    find = rest[0].replace('\\\\', '\\')
    replace = rest[1]
    me = False  # /me command
    flags = (trigger.group(4) or '')

    # If g flag is given, replace all. Otherwise, replace once.
    if 'g' in flags:
        count = -1
    else:
        count = 1

    # repl is a lambda function which performs the substitution. i flag turns
    # off case sensitivity. re.U turns on unicode replacement.
    reflags = 0
    if 'i' in flags:
        reflags = re.U | re.I

    # Look back through the user's lines in the channel until you find a line
    # where the replacement works
    try:
        find = re.compile(find, reflags)
    except re.error as e:
        bot.reply(u'That ain\'t valid regex! (%s)' % (e.message))
        return
    for line in reversed(search_dict[trigger.sender][rIdentifier]):
        if line.startswith("\x01ACTION"):
            me = True  # /me command
            line = line[8:]
        else:
            me = False
        new_phrase = find.sub(replace, line, count == 1)
        if new_phrase != line:  # we are done
            break

    if not new_phrase or new_phrase == line:
        return  # Didn't find anything

    # Save the new "edited" message.
    action = (me and '\x01ACTION ') or ''  # If /me message, prepend \x01ACTION
    templist = search_dict[trigger.sender][rIdentifier]
    templist.append(action + new_phrase)
    search_dict[trigger.sender][rIdentifier] = templist
    bot.memory['find_lines'] = search_dict

    # output
    if not me:
        new_phrase = '%s to say: %s' % (bold('meant'), new_phrase)
    if trigger.group(1):
        phrase = '%s thinks %s %s' % (trigger.nick, rIdentifier, new_phrase)
    else:
        phrase = '%s %s' % (trigger.nick, new_phrase)

    bot.say(phrase)
Exemple #24
0
def findandreplace(bot, trigger):
    # Don't bother in PM
    if trigger.is_privmsg:
        return

    # Correcting other person vs self.
    rIdentifier = Identifier(trigger.group(1) or trigger.nick)

    search_dict = bot.memory['find_lines']
    # only do something if there is conversation to work with
    if trigger.sender not in search_dict:
        return
    if Identifier(rIdentifier) not in search_dict[trigger.sender]:
        return

    rest = [trigger.group(2), trigger.group(3)]
    find = rest[0].replace('\\\\', '\\')
    replace = rest[1]
    me = False  # /me command
    flags = (trigger.group(4) or '')

    # If g flag is given, replace all. Otherwise, replace once.
    if 'g' in flags:
        count = -1
    else:
        count = 1

    # repl is a lambda function which performs the substitution. i flag turns
    # off case sensitivity. re.U turns on unicode replacement.
    reflags = 0
    if 'i' in flags:
        reflags = re.U | re.I

    # Look back through the user's lines in the channel until you find a line
    # where the replacement works
    try:
        find = re.compile(find, reflags)
    except re.error as e:
        bot.reply(u'That ain\'t valid regex! (%s)' % (e.message))
        return
    for line in reversed(search_dict[trigger.sender][rIdentifier]):
        if line.startswith("\x01ACTION"):
            me = True  # /me command
            line = line[8:]
        else:
            me = False
        new_phrase = find.sub(replace, line, count == 1)
        if new_phrase != line:  # we are done
            break

    if not new_phrase or new_phrase == line:
        return  # Didn't find anything

    # Save the new "edited" message.
    action = (me and '\x01ACTION ') or ''  # If /me message, prepend \x01ACTION
    templist = search_dict[trigger.sender][rIdentifier]
    templist.append(action + new_phrase)
    search_dict[trigger.sender][rIdentifier] = templist
    bot.memory['find_lines'] = search_dict

    # output
    if not me:
        new_phrase = '%s to say: %s' % (bold('meant'), new_phrase)
    if trigger.group(1):
        phrase = '%s thinks %s %s' % (trigger.nick, rIdentifier, new_phrase)
    else:
        phrase = '%s %s' % (trigger.nick, new_phrase)

    bot.say(phrase)
def fetch(bot, initial=False):
    global session_maker_instance

    headers = {"User-Agent": "ff-irc-bot"}

    if "alfred_last_modified" in bot.memory["ff"]:
        headers["If-Modified-Since"] = bot.memory["ff"]["alfred_last_modified"]

    try:
        result = requests.get(bot.config.freifunk.alfred_uri, headers=headers)
    except Exception as e:
        print("Problems requesting alfred.json: {}".format(str(e)))
        return

    if result.status_code == 304:
        # no update since last fetch
        return

    if result.status_code != 200:
        # err, we have a problem!
        print("Unable to get alfred.json! Status code: {:d}".format(result.status_code))
        return

    try:
        mapdata = json.loads(result.text)
    except ValueError as e:
        # err, we have a problem!
        print("Unable to parse JSON! Error: {}".format(str(e)))
        return

        # No problems? Everything fine? Update last modified timestamp!
    bot.memory["ff"]["alfred_last_modified"] = result.headers["Last-Modified"]

    session = session_maker_instance()

    with session.no_autoflush:
        # Set all Nodes offline. Only nodes present in alfred.json are online.
        for node in session.query(Node).filter(Node.source == "alfred.json"):
            node.online = False
            node.clientcount = 0

        for key, data in mapdata.items():
            data["mac"] = key
            data["online"] = True
            data["source"] = "alfred.json"
            session.merge(Node(data))

        if not initial:
            for node in filter(lambda item: type(item) is Node, session.new):
                bot.msg(bot.config.freifunk.channel, "Neuer Knoten: {:s}".format(str(node)))
                node.firstseen = datetime.datetime.now()

            for node in filter(lambda item: type(item) is Node, session.dirty):
                attrs = inspect(node).attrs
                location_updated = False

                for attr in attrs:
                    if (
                        attr.key not in (["lastseen", "firstseen"] + bot.config.freifunk.get_list("change_no_announce"))
                        and attr.history.has_changes()
                    ):
                        if attr.key == "online":
                            bot.msg(
                                bot.config.freifunk.change_announce_target,
                                "Knoten {:s} ist nun {:s}".format(
                                    formatting.bold(str(node.name)),
                                    formatting.color("online", formatting.colors.GREEN)
                                    if attr.value
                                    else formatting.color("offline", formatting.colors.RED),
                                ),
                            )
                        elif attr.key == "lat" or attr.key == "lon":
                            if not location_updated:
                                location_updated = True

                                if attrs.lat.history.has_changes():
                                    old_lat = attrs.lat.history.deleted[0]
                                else:
                                    old_lat = attrs.lat.value

                                if attrs.lon.history.has_changes():
                                    old_lon = attrs.lon.history.deleted[0]
                                else:
                                    old_lon = attrs.lon.value

                                if old_lat and old_lon and attrs.lat.value and attrs.lon.value:
                                    bot.msg(
                                        bot.config.freifunk.change_announce_target,
                                        "Knoten {:s} änderte seine Position um {:.0f} Meter: {:s}".format(
                                            formatting.bold(str(node.name)),
                                            calc_distance(old_lat, old_lon, attrs.lat.value, attrs.lon.value),
                                            bot.config.freifunk.map_uri.format(
                                                lat=attrs.lat.value, lon=attrs.lon.value
                                            ),
                                        ),
                                    )
                                elif attrs.lat.value and attrs.lon.value:
                                    bot.msg(
                                        bot.config.freifunk.change_announce_target,
                                        "Knoten {:s} hat nun eine Position: {:s}".format(
                                            formatting.bold(str(node.name)),
                                            bot.config.freifunk.map_uri.format(
                                                lat=attrs.lat.value, lon=attrs.lon.value
                                            ),
                                        ),
                                    )
                                else:
                                    bot.msg(
                                        bot.config.freifunk.change_announce_target,
                                        "Knoten {:s} hat keine Position mehr".format(formatting.bold(str(node.name))),
                                    )

                        else:
                            bot.msg(
                                bot.config.freifunk.change_announce_target,
                                "Knoten {:s} änderte {:s} von {:s} zu {:s}".format(
                                    formatting.bold(str(node.name)),
                                    str(attr.key),
                                    str(attr.history.deleted[0]),
                                    str(attr.value),
                                ),
                            )
        try:
            session.commit()

            if not initial:
                check_highscores(bot)
        except:
            session.rollback()
            raise
        finally:
            session.close()
def get_prefix():
    prefix = color('[', 'grey') + 'deviant' + bold('art') + color(']', 'grey')
    return prefix
def fetch(bot, initial=False):
    global session_maker_instance

    headers = {"User-Agent": "ff-irc-bot"}

    if "nodes_last_modified" in bot.memory["ff"]:
        headers["If-Modified-Since"] = bot.memory["ff"]["nodes_last_modified"]

    try:
        result = requests.get(bot.config.freifunk.nodes_uri, headers=headers, timeout=5)
    except requests.exceptions.ConnectTimeout:
        error(bot, "Problems requesting nodes.json: Timeout")
        return
    except requests.exceptions.ConnectionError:
        error(bot, "Problems requesting nodes.json: ConnectionError")
        return
    except Exception as e:
        error(bot, "Problems requesting nodes.json: {}".format(type(e)))
        return

    if result.status_code == 304:
        # no update since last fetch
        return

    if result.status_code != 200:
        # err, we have a problem!
        error(bot, "Unable to get nodes.json! Status code: {:d}".format(result.status_code))
        return

    try:
        mapdata = json.loads(result.text)
    except ValueError as e:
        # err, we have a problem!
        error(bot, "Unable to parse JSON! {}".format(str(e)))
        return

    # No problems? Everything fine? Update last modified timestamp!
    bot.memory["ff"]["nodes_last_modified"] = result.headers["Last-Modified"]

    # .. and clear last error
    if "last_error_msg" in bot.memory["ff"] and bot.memory["ff"]["last_error_msg"]:
        bot.memory["ff"]["last_error_msg"] = None
        bot.msg(
            bot.config.freifunk.change_announce_target,
            formatting.color("Everything back to normal!", formatting.colors.GREEN),
        )

    session = session_maker_instance()

    with session.no_autoflush:
        # Set all Nodes offline. Only nodes present in nodes.json and with online True are online.
        for node in session.query(Node).filter(Node.source == "nodes.json"):
            node.online = False
            node.clientcount = 0

        for key, data in mapdata["nodes"].items():
            data["node_id"] = key
            data["source"] = "nodes.json"

            node = Node(data)

            if not (node.site_code and node.site_code == "ffka"):
                continue

            session.merge(node)

        nodes_new = filter(lambda item: type(item) is Node, session.new)
        nodes_changed = filter(lambda item: type(item) is Node and not node.gateway, session.dirty)

        msgs = {}
        msgs[bot.config.freifunk.channel] = []
        msgs[bot.config.freifunk.change_announce_target] = []

        if not initial:
            for node in nodes_new:
                node.firstseen = datetime.datetime.now()
                if node.gateway:
                    msgs[bot.config.freifunk.channel].append("Neues Gateway: {:s}".format(str(node)))
                else:
                    msgs[bot.config.freifunk.channel].append("Neuer Knoten: {:s}".format(str(node)))

            for node in nodes_changed:
                attrs = inspect(node).attrs
                location_updated = False

                for attr in attrs:
                    if (
                        attr.key not in (["lastseen"] + bot.config.freifunk.get_list("change_no_announce"))
                        and attr.history.has_changes()
                    ):
                        if attr.key == "online":
                            msgs[bot.config.freifunk.change_announce_target].append(
                                "Knoten {:s} ist nun {:s}".format(
                                    formatting.bold(str(node.name)),
                                    formatting.color("online", formatting.colors.GREEN)
                                    if attr.value
                                    else formatting.color("offline", formatting.colors.RED),
                                )
                            )
                        elif attr.key == "lat" or attr.key == "lon":
                            if not location_updated:
                                location_updated = True

                                if attrs.lat.history.has_changes():
                                    old_lat = attrs.lat.history.deleted[0]
                                else:
                                    old_lat = attrs.lat.value

                                if attrs.lon.history.has_changes():
                                    old_lon = attrs.lon.history.deleted[0]
                                else:
                                    old_lon = attrs.lon.value

                                if old_lat and old_lon and attrs.lat.value and attrs.lon.value:
                                    msgs[bot.config.freifunk.change_announce_target].append(
                                        "Knoten {:s} änderte seine Position um {:.0f} Meter: {:s}".format(
                                            formatting.bold(str(node.name)),
                                            calc_distance(old_lat, old_lon, attrs.lat.value, attrs.lon.value),
                                            bot.config.freifunk.meshviewer_uri.format(id=node.node_id),
                                        )
                                    )
                                elif attrs.lat.value and attrs.lon.value:
                                    msgs[bot.config.freifunk.change_announce_target].append(
                                        "Knoten {:s} hat nun eine Position: {:s}".format(
                                            formatting.bold(str(node.name)),
                                            bot.config.freifunk.meshviewer_uri.format(id=node.node_id),
                                        )
                                    )
                                else:
                                    msgs[bot.config.freifunk.change_announce_target].append(
                                        "Knoten {:s} hat keine Position mehr".format(formatting.bold(str(node.name)))
                                    )

                        else:
                            msgs[bot.config.freifunk.change_announce_target].append(
                                "Knoten {:s} änderte {:s} von {:s} zu {:s}".format(
                                    formatting.bold(str(node.name)),
                                    str(attr.key),
                                    str(attr.history.deleted[0]),
                                    str(attr.value),
                                )
                            )
    try:
        session.commit()
        check_highscores(bot)
    except:
        session.rollback()
        raise
    finally:
        session.close()

    for target in msgs:
        for msg in msgs[target]:
            bot.msg(target, msg)
Exemple #28
0
def findandreplace(bot, trigger):
    # Don't bother in PM
    if trigger.is_privmsg:
        return

    # Correcting other person vs self.
    rnick = Identifier(trigger.group(1) or trigger.nick)

    search_dict = bot.memory['find_lines']
    # only do something if there is conversation to work with
    if trigger.sender not in search_dict:
        return
    if Identifier(rnick) not in search_dict[trigger.sender]:
        return

    #TODO rest[0] is find, rest[1] is replace. These should be made variables of
    #their own at some point.
    rest = [trigger.group(2), trigger.group(3)]
    rest[0] = rest[0].replace(r'\/', '/')
    rest[1] = rest[1].replace(r'\/', '/')
    me = False  # /me command
    flags = (trigger.group(4) or '')

    # If g flag is given, replace all. Otherwise, replace once.
    if 'g' in flags:
        count = -1
    else:
        count = 1

    # repl is a lambda function which performs the substitution. i flag turns
    # off case sensitivity. re.U turns on unicode replacement.
    if 'i' in flags:
        regex = re.compile(re.escape(rest[0]), re.U | re.I)
        repl = lambda s: re.sub(regex, rest[1], s, count == 1)
    else:
        repl = lambda s: s.replace(rest[0], rest[1], count)

    # Look back through the user's lines in the channel until you find a line
    # where the replacement works
    for line in reversed(search_dict[trigger.sender][rnick]):
        if line.startswith("\x01ACTION"):
            me = True  # /me command
            line = line[8:]
        else:
            me = False
        new_phrase = repl(line)
        if new_phrase != line:  # we are done
            break

    if not new_phrase or new_phrase == line:
        return  # Didn't find anything

    # Save the new "edited" message.
    action = (me and '\x01ACTION ') or ''  # If /me message, prepend \x01ACTION
    templist = search_dict[trigger.sender][rnick]
    templist.append(action + new_phrase)
    search_dict[trigger.sender][rnick] = templist
    bot.memory['find_lines'] = search_dict

    # output
    if not me:
        new_phrase = '%s to say: %s' % (bold('meant'), new_phrase)
    if trigger.group(1):
        phrase = '%s thinks %s %s' % (trigger.nick, rnick, new_phrase)
    else:
        phrase = '%s %s' % (trigger.nick, new_phrase)

    bot.say(phrase)
Exemple #29
0
def url_handler(bot, trigger):
    """ Check for malicious URLs """
    check = True    # Enable URL checking
    strict = False  # Strict mode: kick on malicious URL
    positives = 0   # Number of engines saying it's malicious
    total = 0       # Number of total engines
    use_vt = True   # Use VirusTotal
    if bot.config.has_section('safety'):
        check = bot.config.safety.enabled_by_default
        if check is None:
            # If not set, assume default
            check = True
        else:
            check = bool(check)
    # DB overrides config:
    setting = bot.db.get_channel_value(trigger.sender, 'safety')
    if setting is not None:
        if setting == 'off':
            return  # Not checking
        elif setting in ['on', 'strict', 'local', 'local strict']:
            check = True
        if setting == 'strict' or setting == 'local strict':
            strict = True
        if setting == 'local' or setting == 'local strict':
            use_vt = False

    if not check:
        return  # Not overriden by DB, configured default off

    netloc = urlparse(trigger).netloc
    if any(regex.search(netloc) for regex in known_good):
        return  # Whitelisted

    apikey = bot.config.safety.vt_api_key
    try:
        if apikey is not None and use_vt:
            payload = {'resource': unicode(trigger),
                       'apikey': apikey,
                       'scan': '1'}

            if trigger not in bot.memory['safety_cache']:
                result = web.post(vt_base_api_url + 'report', payload)
                if sys.version_info.major > 2:
                    result = result.decode('utf-8')
                result = json.loads(result)
                age = time.time()
                data = {'positives': result['positives'],
                        'total': result['total'],
                        'age': age}
                bot.memory['safety_cache'][trigger] = data
                if len(bot.memory['safety_cache']) > 1024:
                    _clean_cache(bot)
            else:
                print('using cache')
                result = bot.memory['safety_cache'][trigger]
            positives = result['positives']
            total = result['total']
    except Exception as e:
        LOGGER.debug('Error from checking URL with VT.', exc_info=True)
        pass  # Ignoring exceptions with VT so MalwareDomains will always work

    if unicode(netloc).lower() in malware_domains:
        # malwaredomains is more trustworthy than some VT engines
        # therefor it gets a weight of 10 engines when calculating confidence
        positives += 10
        total += 10

    if positives > 1:
        # Possibly malicious URL detected!
        confidence = '{}%'.format(round((positives / total) * 100))
        msg = 'link posted by %s is possibliy malicious ' % bold(trigger.nick)
        msg += '(confidence %s - %s/%s)' % (confidence, positives, total)
        bot.say('[' + bold(color('WARNING', 'red')) + '] ' + msg)
        if strict:
            bot.write(['KICK', trigger.sender, trigger.nick,
                       'Posted a malicious link'])
Exemple #30
0
def findandreplace(bot, trigger):
    # Don't bother in PM
    if trigger.is_privmsg:
        return

    # Correcting other person vs self.
    rnick = Nick(trigger.group(1) or trigger.nick)

    search_dict = bot.memory['find_lines']
    # only do something if there is conversation to work with
    if trigger.sender not in search_dict:
        return
    if Nick(rnick) not in search_dict[trigger.sender]:
        return

    #TODO rest[0] is find, rest[1] is replace. These should be made variables of
    #their own at some point.
    rest = [trigger.group(3), trigger.group(4)]
    rest[0] = rest[0].replace(r'\/', '/')
    rest[1] = rest[1].replace(r'\/', '/')
    me = False  # /me command
    flags = (trigger.group(5) or '')

    # If g flag is given, replace all. Otherwise, replace once.
    if 'g' in flags:
        count = -1
    else:
        count = 1

    # repl is a lambda function which performs the substitution. i flag turns
    # off case sensitivity. re.U turns on unicode replacement.
    if trigger.group(2).startswith('S'):
        precomp = rest[0]
    else:
        precomp = re.escape(rest[0])
    if 'i' in flags:
        regex = re.compile(precomp, re.U | re.I)
    else:
        regex = re.compile(precomp, re.U)
    repl = lambda s: re.sub(regex, rest[1], s, count == 1)
    # Look back through the user's lines in the channel until you find a line
    # where the replacement works
    for line in reversed(search_dict[trigger.sender][rnick]):
        if line.startswith("\x01ACTION"):
            me = True  # /me command
            line = line[8:]
        else:
            me = False
        new_phrase = repl(line)
        if new_phrase != line:  # we are done
            break

    if not new_phrase or new_phrase == line:
        return  # Didn't find anything

    # Save the new "edited" message.
    action = (me and '\x01ACTION ') or ''  # If /me message, prepend \x01ACTION
    templist = search_dict[trigger.sender][rnick]
    templist.append(action + new_phrase)
    search_dict[trigger.sender][rnick] = templist
    bot.memory['find_lines'] = search_dict

    # output
    if not me:
        new_phrase = '%s to say: %s' % (bold('meant'), new_phrase)
    if trigger.group(1):
        phrase = '%s thinks %s %s' % (trigger.nick, rnick, new_phrase)
    else:
        phrase = '%s %s' % (trigger.nick, new_phrase)

    bot.say(phrase)
Exemple #31
0
def get_prefix():
    prefix = color('[', 'grey') + bold(color('Curse', 'yellow')) + color(']', 'grey')
    return prefix
def get_prefix():
    prefix = color('[', 'grey') + 'deviant' + bold('art') + color(']', 'grey')
    return prefix