<commit_before># -*- coding: utf-8 -*-

"""
weitersager.irc
~~~~~~~~~~~~~~~

Internet Relay Chat

:Copyright: 2007-2015 <NAME>
:License: MIT, see LICENSE for details.
"""

from collections import namedtuple

from irc.bot import SingleServerIRCBot
from irc.buffer import LenientDecodingLineBuffer

from .signals import channel_joined, shutdown_requested
from .util import log, start_thread


class Channel(namedtuple('Channel', 'name password')):
    """An IRC channel with optional password."""

    def __new__(cls, name, *, password=None):
        return super(Channel, cls).__new__(cls, name, password)


class Bot(SingleServerIRCBot):
    """An IRC bot to forward messages to IRC channels."""

    def __init__(self, server_spec, nickname, realname, channels):
        log('Connecting to IRC server {0.host}:{0.port:d} ...', server_spec)

        SingleServerIRCBot.__init__(self, [server_spec], nickname,
            realname)

        # Avoid `UnicodeDecodeError` on non-UTF-8 messages.
        self.connection.buffer_class = LenientDecodingLineBuffer

        # Note: `self.channels` already exists in super class.
        self.channels_to_join = channels

    def start(self):
        """Connect to the server, in a separate thread."""
        start_thread(super().start, self.__class__.__name__)

    def get_version(self):
        return 'Weitersager'

    def on_welcome(self, conn, event):
        """Join channels after connect."""
        log('Connected to {}:{:d}.', *conn.socket.getpeername())

        channel_names = sorted(c.name for c in self.channels_to_join)
        log('Channels to join: {}', ', '.join(channel_names))

        for channel in self.channels_to_join:
            log('Joining channel {} ...', channel.name)
            conn.join(channel.name, channel.password or '')

    def on_nicknameinuse(self, conn, event):
        """Choose another nickname if conflicting."""
        self._nickname += '_'
        conn.nick(self._nickname)

    def on_join(self, conn, event):
        """Successfully joined channel."""
        joined_nick = event.source.nick
        channel_name = event.target

        if joined_nick == self._nickname:
            log('Joined IRC channel: {}', channel_name)
            channel_joined.send(channel_name=channel_name)

    def on_badchannelkey(self, conn, event):
        """Channel could not be joined due to wrong password."""
        channel = event.arguments[0]
        log('Cannot join channel {} (bad key).', channel)

    def on_privmsg(self, conn, event):
        """React on private messages.

        Shut down, for example.
        """
        whonick = event.source.nick
        message = event.arguments[0]
        if message == 'shutdown!':
            log('Shutdown requested on IRC by user {}.', whonick)
            shutdown_requested.send()
            self.die('Shutting down.')  # Joins IRC bot thread.

    def say(self, sender, *, channel_name=None, text=None):
        """Say message on channel."""
        self.connection.privmsg(channel_name, text)


class DummyBot(object):

    def __init__(self, server_spec, nickname, realname, channels):
        self.channels = channels

    def start(self):
        # Fake channel joins.
        for channel in self.channels:
            channel_joined.send(channel_name=channel.name)

    def say(self, sender, *, channel_name=None, text=None):
        log('{}> {}', channel_name, text)


def create_bot(server, nickname, realname, channels):
    """Create and return an IRC bot according to the configuration."""
    if server:
        bot_class = Bot
    else:
        log('No IRC server specified; will write to STDOUT instead.')
        bot_class = DummyBot

    return bot_class(server, nickname, realname, channels)<commit_msg>Extracted shutdown method.<commit_after># -*- coding: utf-8 -*-

"""
weitersager.irc
~~~~~~~~~~~~~~~

Internet Relay Chat

:Copyright: 2007-2015 <NAME>
:License: MIT, see LICENSE for details.
"""

from collections import namedtuple

from irc.bot import SingleServerIRCBot
from irc.buffer import LenientDecodingLineBuffer

from .signals import channel_joined, shutdown_requested
from .util import log, start_thread


class Channel(namedtuple('Channel', 'name password')):
    """An IRC channel with optional password."""

    def __new__(cls, name, *, password=None):
        return super(Channel, cls).__new__(cls, name, password)


class Bot(SingleServerIRCBot):
    """An IRC bot to forward messages to IRC channels."""

    def __init__(self, server_spec, nickname, realname, channels):
        log('Connecting to IRC server {0.host}:{0.port:d} ...', server_spec)

        SingleServerIRCBot.__init__(self, [server_spec], nickname,
            realname)

        # Avoid `UnicodeDecodeError` on non-UTF-8 messages.
        self.connection.buffer_class = LenientDecodingLineBuffer

        # Note: `self.channels` already exists in super class.
        self.channels_to_join = channels

    def start(self):
        """Connect to the server, in a separate thread."""
        start_thread(super().start, self.__class__.__name__)

    def get_version(self):
        return 'Weitersager'

    def on_welcome(self, conn, event):
        """Join channels after connect."""
        log('Connected to {}:{:d}.', *conn.socket.getpeername())

        channel_names = sorted(c.name for c in self.channels_to_join)
        log('Channels to join: {}', ', '.join(channel_names))

        for channel in self.channels_to_join:
            log('Joining channel {} ...', channel.name)
            conn.join(channel.name, channel.password or '')

    def on_nicknameinuse(self, conn, event):
        """Choose another nickname if conflicting."""
        self._nickname += '_'
        conn.nick(self._nickname)

    def on_join(self, conn, event):
        """Successfully joined channel."""
        joined_nick = event.source.nick
        channel_name = event.target

        if joined_nick == self._nickname:
            log('Joined IRC channel: {}', channel_name)
            channel_joined.send(channel_name=channel_name)

    def on_badchannelkey(self, conn, event):
        """Channel could not be joined due to wrong password."""
        channel = event.arguments[0]
        log('Cannot join channel {} (bad key).', channel)

    def on_privmsg(self, conn, event):
        """React on private messages."""
        nickmask = event.source
        text = event.arguments[0]
        if text == 'shutdown!':
            self.shutdown(nickmask)

    def shutdown(self, nickmask):
        """Shut the bot down."""
        log('Shutdown requested by {}.', nickmask)
        shutdown_requested.send()
        self.die('Shutting down.')  # Joins IRC bot thread.

    def say(self, sender, *, channel_name=None, text=None):
        """Say message on channel."""
        self.connection.privmsg(channel_name, text)


class DummyBot(object):

    def __init__(self, server_spec, nickname, realname, channels):
        self.channels = channels

    def start(self):
        # Fake channel joins.
        for channel in self.channels:
            channel_joined.send(channel_name=channel.name)

    def say(self, sender, *, channel_name=None, text=None):
        log('{}> {}', channel_name, text)


def create_bot(server, nickname, realname, channels):
    """Create and return an IRC bot according to the configuration."""
    if server:
        bot_class = Bot
    else:
        log('No IRC server specified; will write to STDOUT instead.')
        bot_class = DummyBot

    return bot_class(server, nickname, realname, channels)
{'fraction_non_alphanumeric': 0.12150026413100898, 'fraction_numerical': 0.0036978341257263604, 'mean_word_length': 2.9238341968911916, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4358361', 'n_tokens_mistral': 2227, 'n_tokens_neox': 2118, 'n_words': 616}