lrh9's Python 3 IRC Bot Framework

  • 9 Replies
  • 5326 Views
*

lrh9

  • Trusty Member
  • *******
  • Starship Trooper
  • *
  • 282
  • Rome wasn't built in a day.
lrh9's Python 3 IRC Bot Framework
« on: July 13, 2012, 11:07:41 am »
I had been working on an IRC bot framework for a while, and I feel like I've finally got my code polished enough to share with other people. It's a asynchronous I/O bot with an event-oriented framework. Requires Python 3 to run.

Code
import asynchat
import asyncore
import collections
import errno
import socket

try:
    import ssl
except ImportError:
    ssl = False

__verbose__ = True

"""
TODO:
threading support
password support
client abstraction
"""

#
class ParseError(Exception):

    def __init__(self, raw):
        if __verbose__:
            print('ParseError: {raw}'.format(**locals()))
        self.raw = raw

#
def parse_line(raw_line):
    if __verbose__:
         print('parsing line: \"{raw_line}\"'.format(**locals()))
    try:
        if raw_line.startswith(':'):
            prefix, raw = raw_line[1:].split(' ', 1)
        else:
            prefix, raw = (None, raw_line)
        parts = raw.split(' :', 1)
        if len(parts) > 1:
            trailing = parts[1]
        else:
            trailing = None
        parts = parts[0].split(' ')
        command = parts[0]
        parameters = parts[1:]
        if trailing is not None:
            parameters.append(trailing)
    except:
        raise ParseError(raw_line)
    if __verbose__:
        print('prefix: {prefix}'.format(**locals()))
        print('command: {command}'.format(**locals()))
        print('parameters: {parameters}\n'.format(**locals()))
    return prefix, command, parameters

#
class Publisher:

    def __init__(self, subscribers=None):
        if subscribers is None:
            subscribers = collections.defaultdict(set)
        self.subscribers = subscribers

    def add(self, topic, subscriber):
        self.subscribers[topic].add(subscriber)

    def discard(self, topic, subscriber):
        self.subscribers[topic].discard(subscriber)

    def remove(self, topic, subscriber):
        self.subscribers[topic].remove(subscriber)

    def publish(self, topic, *args, **kwargs):
        for subscriber in self.subscribers[topic]:
            try:
                subscriber(topic, *args, **kwargs)
            except Exception as exception:
                for subscriber in self.subscribers[exception]:
                    subscriber(topic, exception, *args, **kwargs)

"""Based on code by Evan Fosmark.

http://dev.guardedcode.com/projects/ircutils/

 Copyright (c) 2010 Evan Fosmark
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE."""

class Connection(asynchat.async_chat):

    def __init__(self,
                 host,
                 publisher=None,
                 port=None,
                 ssl_=False,
                 ipv6=False):
        if port is None:
            port = (6667, 7000)[ssl_]
        self.address = (host, port)
        self.publisher = publisher
        self.ssl_ = ssl_
        if ssl_:
            if ssl:
                self.recv = self._ssl_recv
                self.send = self._ssl_send
            else:
                raise ImportError
        asynchat.async_chat.__init__(self)
        if ipv6:
            self.create_socket(socket.AF_INET6, socket.SOCK_STREAM)
        else:
            self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_terminator(b'\r\n')
        self.collect_incoming_data = self._collect_incoming_data

    #
    def found_terminator(self):
        if __verbose__:
            print('found terminator...')
        data = self._get_data()
        try:
            prefix, command, parameters = parse_line(data.decode())
        except ParseError as error:
            self.publisher.publish(error, self)
        else:
            if __verbose__:
                print('publishing line...\n')
            self.publisher.publish(command, self, prefix, parameters)

    #
    def handle_connect(self):
        if __verbose__:
            print('connection established...')
        if self.ssl_:
            if __verbose__:
                print('initializing ssl...')
            self.ssl_ = ssl.wrap_socket(self.socket, do_handshake_on_connect=False)
            self.set_socket(self.ssl_)
        if __verbose__:
            print('publishing handle_connect...\n')
        self.publisher.publish('handle_connect', self)

    def _ssl_recv(self, buffersize):
        #TODO
        pass
   
    def _ssl_send(self, data):
        #TODO
        pass

    #
    def message(self, command, parameters=tuple(), trailing=None):
        if __verbose__:
            print('messaging...')
            print('command: {command}'.format(**locals()))
            print('parameters: {parameters}'.format(**locals()))
            print('trailing: {trailing}'.format(**locals()))
        parts = [command.upper()]
        if parameters:
            parts.append(' '.join(parameters))
        if trailing:
            parts.append(''.join((':', trailing)))
        message = ''.join((' '.join(parts), '\r\n'))
        data = message.encode()
        if __verbose__:
            print('data: {data}'.format(**locals()))
            print()
        self.push(data)

    #
    def connect(self):
        if __verbose__:
            print('connecting...')
        asynchat.async_chat.connect(self, self.address)
        self.publisher.publish('connect', self)

class Client:
    pass

class Bot:
    pass

if __name__ == '__main__':

    import copy

    def connect(topic, connection):
        connection.message('NICK', (connection.nickname,))
        connection.message('USER', (connection.user, '+B', '*'), trailing=connection.realname)

    def pong(command, connection, prefix, parameters):
        connection.message('PING', (parameters[0],))

    def echo(bot_command, connection, args, bot_args):
        connection.message('NOTICE', (args[2][0],), trailing=bot_args[1][0])

    class PrivateMessageHandler:

        def __init__(self, publisher=None):
            if publisher is None:
                publisher = Publisher()
            self.publisher = publisher

        def __call__(self, command, connection, prefix, parameters):
            bot_prefix, bot_command, bot_parameters = parse_line(parameters[-1])
            self.publisher.publish(bot_command, connection, (prefix, command, parameters), (bot_prefix, bot_parameters))

    class Channel:

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

        def __call__(self, command, connection, prefix, parameters):
            connection.message('JOIN', (self.channel,))

    c = Connection('irc.dal.net', Publisher())
    c.nickname = 'lrh9bot'
    c.user = 'lrh9bot'
    c.realname = 'lrh9bot'
    pub = c.publisher
    add = pub.add
    add('PING', pong)
    add('connect', connect)
    add('376', Channel('#ai'))
    priv_msg = private_message_handler = PrivateMessageHandler()
    priv_msg.publisher.add('ECHO', echo)
    add('PRIVMSG', priv_msg)
    t = Connection('irc.freenode.net', copy.deepcopy(pub))
    t.nickname = 'lrh9bot'
    t.user = 'lrh9bot'
    t.realname = 'lrh9bot'
    t.publisher.add('376', Channel('#irchacks'))
    c.connect()
    t.connect()
   
    asyncore.loop()
« Last Edit: July 26, 2012, 10:58:08 am by lrh9 »

*

Bragi

  • Trusty Member
  • ********
  • Replicant
  • *
  • 564
    • Neural network design blog
Re: lrh9's Python 3 IRC Bot Framework
« Reply #1 on: July 14, 2012, 04:12:48 pm »
Hi Lrh9,
been a long time. I must admit, my python is a bit rusty.  So, with this code, you can connect to an IRC channel?

*

lrh9

  • Trusty Member
  • *******
  • Starship Trooper
  • *
  • 282
  • Rome wasn't built in a day.
Re: lrh9's Python 3 IRC Bot Framework
« Reply #2 on: July 14, 2012, 05:20:12 pm »
Hi Lrh9,
been a long time. I must admit, my python is a bit rusty.  So, with this code, you can connect to an IRC channel?

Yes.

The example code under "if __name__ == '__main__':" will create a connection to the DALnet IRC network, join the #ai channel, and respond to PING commands appropriately.

*

Art

  • At the end of the game, the King and Pawn go into the same box.
  • Trusty Member
  • **********************
  • Colossus
  • *
  • 5865
Re: lrh9's Python 3 IRC Bot Framework
« Reply #3 on: July 14, 2012, 08:18:59 pm »
Nice to see you Larry. It's been a while. I did take your advice and decided to look into Python (3). It really has a lot of great features and capabilities. I've also found numerous tutorial sites and some visual ones on YouTube as well.

Thanks for the tip and don't be a stranger! BTW, weren't you working on a chatbot at some time in the past? How's it progressing or did other studies get it shelved temporarily?
In the world of AI, it's the thought that counts!

*

lrh9

  • Trusty Member
  • *******
  • Starship Trooper
  • *
  • 282
  • Rome wasn't built in a day.
Re: lrh9's Python 3 IRC Bot Framework
« Reply #4 on: July 14, 2012, 09:00:48 pm »
I don't remember any plans to work on a chatbot. I am of course interested in software agents and software agency, but chatbots are just one type of software agent. I'm studying automata theory right now such as finite state machines. Game a.i. programmers have used finite state machines to produce game NPC agents and it seems pretty interesting.

*

Art

  • At the end of the game, the King and Pawn go into the same box.
  • Trusty Member
  • **********************
  • Colossus
  • *
  • 5865
Re: lrh9's Python 3 IRC Bot Framework
« Reply #5 on: July 15, 2012, 12:16:45 am »
Larry,

I remember a program that you were working on called Prometheus, which I think involved an intelligent agent capable of understanding input....

Here...found it but sounds a lot like a chat bot / assistant to me:
#########################################

Prometheus A.I. News and Development Updates
« Reply #27 on: October 07, 2009, 12:25:54 PM »

I just hope I'll be able to construct an a.i. that can have an actual understanding, at least more of an understanding than current a.i. programs do.
In the world of AI, it's the thought that counts!

*

lrh9

  • Trusty Member
  • *******
  • Starship Trooper
  • *
  • 282
  • Rome wasn't built in a day.
Re: lrh9's Python 3 IRC Bot Framework
« Reply #6 on: July 15, 2012, 12:55:06 am »
I think I was stressing the desire to create a software agent that knew what it was talking about the way people do. An agent that wasn't simply referring to symbols and manipulating them, but also understanding that they meant something. That it should know something about them, if you know what I mean.

*

Art

  • At the end of the game, the King and Pawn go into the same box.
  • Trusty Member
  • **********************
  • Colossus
  • *
  • 5865
Re: lrh9's Python 3 IRC Bot Framework
« Reply #7 on: July 15, 2012, 04:19:09 am »
Yes, I seem to recall the thread's direction then. Actually what you've just described would make a solid core foundation for a chatbot or chat assistant. It still seems that some of those "assistants" for smart phones only know how to focus on a key word and search the net without any refinement or understanding.

One key to more intelligent bot type assistants would be understanding root meanings of words, not just the definition but what, for example, Blue, Hot, Eyebrow, Vein, Accelerator, Iced Tea, etc.

It does require some sorting before it gets filed away or even used in the proper context of a conversation.

Usually less than a couple of minutes chatting with a bot and one can tell it is indeed a bot. Time will tell.

At the Chatbot Conference this year, Dr. Wallace spoke of a self learning AIML. I think there are a few videos on the net via YouTube or others.

At any rate, good luck on your project(s)...Prometheus or your IRC-Bot!
In the world of AI, it's the thought that counts!

*

lrh9

  • Trusty Member
  • *******
  • Starship Trooper
  • *
  • 282
  • Rome wasn't built in a day.
Re: lrh9's Python 3 IRC Bot Framework
« Reply #8 on: July 17, 2012, 01:26:21 pm »
Thanks. I don't think I have many more plans for my IRC code. If anything, I would want to write some sort of politics bot that could offer various services such as polling, a rule system, and moderated chat. But that is really just another hobby. I just wanted to share it in case someone here wanted to make an IRC bot for whatever purpose. Someone creates something, another person modifies and/or applies it, we all acquire new knowledge. "Win-win!", in my opinion.

*

lrh9

  • Trusty Member
  • *******
  • Starship Trooper
  • *
  • 282
  • Rome wasn't built in a day.
Re: lrh9's Python 3 IRC Bot Framework
« Reply #9 on: July 26, 2012, 10:58:39 am »
Updated code to fix a bug. Tested and confirmed working now.

 


OpenAI Speech-to-Speech Reasoning Demo
by MikeB (AI News )
March 31, 2024, 01:00:53 pm
Say good-bye to GPUs...
by MikeB (AI News )
March 23, 2024, 09:23:52 am
Google Bard report
by ivan.moony (AI News )
February 14, 2024, 04:42:23 pm
Elon Musk's xAI Grok Chatbot
by MikeB (AI News )
December 11, 2023, 06:26:33 am
Nvidia Hype
by 8pla.net (AI News )
December 06, 2023, 10:04:52 pm
How will the OpenAI CEO being Fired affect ChatGPT?
by 8pla.net (AI News )
December 06, 2023, 09:54:25 pm
Independent AI sovereignties
by WriterOfMinds (AI News )
November 08, 2023, 04:51:21 am
LLaMA2 Meta's chatbot released
by 8pla.net (AI News )
October 18, 2023, 11:41:21 pm

Users Online

275 Guests, 0 Users

Most Online Today: 280. Most Online Ever: 2369 (November 21, 2020, 04:08:13 pm)

Articles