All Projects → meshy → framewirc

meshy / framewirc

Licence: BSD-2-Clause license
An IRC toolkit built upon Python 3's asyncio module

Programming Languages

python
139335 projects - #7 most used programming language
Makefile
30231 projects

Projects that are alternatives of or similar to framewirc

Matterircd
Connect to your mattermost or slack using your IRC-client of choice.
Stars: ✭ 241 (+569.44%)
Mutual labels:  irc
CloudBot
CloudBot - The simple, fast, expandable, open-source Python IRC Bot!
Stars: ✭ 69 (+91.67%)
Mutual labels:  irc
parser-tests
Tests for IRC Parsers
Stars: ✭ 35 (-2.78%)
Mutual labels:  irc
Ios
IRCCloud iOS App
Stars: ✭ 243 (+575%)
Mutual labels:  irc
Snooful
The most complete bot for moderation, utility, and fun in Reddit Chat.
Stars: ✭ 13 (-63.89%)
Mutual labels:  irc
critter
Chat bot relaying messages between IRC and Gitter
Stars: ✭ 16 (-55.56%)
Mutual labels:  irc
Phabulous
A Phabricator bot for Slack
Stars: ✭ 222 (+516.67%)
Mutual labels:  irc
phenny
My fork of phenny lives on at https://github.com/vtluug/phenny. This tree is now unmaintained.
Stars: ✭ 15 (-58.33%)
Mutual labels:  irc
jChat
jChat is an overlay that allows you to show your Twitch chat on screen with OBS, XSplit, and any other streaming software that supports browser sources.
Stars: ✭ 106 (+194.44%)
Mutual labels:  irc
newserv
QuakeNet's modular services
Stars: ✭ 20 (-44.44%)
Mutual labels:  irc
Android
IRCCloud Android App
Stars: ✭ 244 (+577.78%)
Mutual labels:  irc
ergo
A modern IRC server (daemon/ircd) written in Go.
Stars: ✭ 1,916 (+5222.22%)
Mutual labels:  irc
etcdircd
An ircd backed by etcd
Stars: ✭ 76 (+111.11%)
Mutual labels:  irc
Anope
Anope IRC Services
Stars: ✭ 241 (+569.44%)
Mutual labels:  irc
helpmebot
Helpmebot
Stars: ✭ 16 (-55.56%)
Mutual labels:  irc
Jenni
jenni was a python IRC bot. Project is closed. Try Sopel instead, https://sopel.chat/
Stars: ✭ 232 (+544.44%)
Mutual labels:  irc
freenode-exodus
Projects and channels that have decided to leave Freenode. (Final leave count: 1056)
Stars: ✭ 130 (+261.11%)
Mutual labels:  irc
Limnoria
A robust, full-featured, and user/programmer-friendly Python IRC bot, with many existing plugins. Successor of the well-known Supybot.
Stars: ✭ 578 (+1505.56%)
Mutual labels:  irc
communi-sailfish
The first and foremost IRC client for Sailfish OS
Stars: ✭ 34 (-5.56%)
Mutual labels:  irc
solanum
An IRCd for unified networks
Stars: ✭ 179 (+397.22%)
Mutual labels:  irc

FramewIRC

An IRC framework built upon Python 3's asyncio module.

Still immature, but a good foundation (I think).

Focuses on allowing the developer to pick only as much of the stack as required.

Installation

pip install framewirc

Quickstart

Here's a simple bot. Let's call it "snarkbot". Whenever it hears a particular phrase, it responds with a gif.

It probably gets old rather quickly. (I think I may be writing autobiographical documentation.)

import asyncio

from framewirc import filters, parsers
from framewirc.client import Client
from framewirc.commands import PRIVMSG
from framewirc.handlers import basic_handlers
from framewirc.strings import to_unicode


quips = {
    'shame': 'https://raw.githubusercontent.com/meshy/gifs/master/shame-bell.gif',
    'YOLO': 'https://raw.githubusercontent.com/meshy/gifs/master/who-said-yolo.gif',
}


@filters.allow(PRIVMSG)
@parsers.apply_message_parser(parsers.privmsg)
def snarky_response(client, channel, raw_body, **kwargs):
    body = to_unicode(raw_body)

    for trigger, riposte in quips.items():
        if trigger in body:
            client.privmsg(channel, riposte)


class SnarkyClient(Client):
    handlers = basic_handlers + (snarky_response,)
    nick = 'snarkbot'
    real_name = 'framewirc bot'


SnarkyClient().connect_to('irc.example.com')
asyncio.get_event_loop().run_forever()

Concepts

Unfortunately, there's no "One True Way" when it comes to IRC. Many networks and servers have their own way of doing things that are not entirely compatible with others. There's nothing wrong with this, exactly, but it does mean that until this library is a little more mature, it might not correctly deal with all these eccentricities. If you find an issue that is not correctly dealt with, please log an issue on github.

IRC message format

It's probably useful to have some idea of how the IRC protocol works. All messages in both directions must adhere to the (simple) rules:

  • Messages are represented as bytes.

    There is no default encoding, so sometimes one just has to guess! To guess how to turn these streams of bytes into Python strings, we have elected to use cChardet in strings.to_unicode when utf8 fails. If you know the encoding, you can override this behaviour.

  • Messages have a relatively simple structure.

    Generally, a message can be seen to have four distinct parts: a prefix, a command, a number of parameters, and a suffix. The parts that are required depend on the command. Only the command is always required. This is the structure of a message:

    :colon-indicated-prefix COMMAND some parameters :Suffix following the colon
    

    We represent the messages that come from the network with our own subclass of bytes called ReceivedMessage. It has prefix, command, parameters, and suffix added for convinience. The prefix and command parts are represented as unicode strings, parametersis a tuple of unicode strings, but suffix is a bytestring. This allows for custom logic in decoding arbitrary text from the network.

  • Messages have a maximum length of 512 bytes.

    This means that when we want to send something longer to the network, we have to split it up into smaller chunks. This can be done using messages.chunk_message.

Connecting

To connect to an IRC network, create a Client object, and call its connect_to method to join the network of your choice. This creates a Connection, and an asyncio.Task that will be invoked in the event loop. The Client will be responsible for sending a nick and real name once it has.

If there are any actions that need to be completed on connection, this is probably the time to do it. The Client.on_connect method can be overridden to add things like connecting to particular rooms, or sending a password to an authentication bot. (Don't forget to call super though!)

Handling commands from the network

When the Connection receives a message, the Client will send that message (and itself) to every one of its handlers in turn. This allows them to make a decision about how they will deal with the message.

As most of your handlers will not need to deal with every message that comes in, we can remove the boilerplate of if message.command == MYCOMMAND through use of the decorators in the filters module. The allow filter only allows messages through to the handler that are in its whitelist. The deny filter does the opposite. eg:

# Rather than this:
def my_command_handler(client, message):
    if message.command != MYCOMMAND:
        return
    do_useful_logic(message)

# It's nicer to have this:
@allow(MYCOMMAND)
def my_simpler_command_handler(client, message):
    do_useful_logic(message)

Sending commands to the network

The Client has a couple of helper methods for sending commands to the network. You can send messages to users or channels with Client.privmsg(), and change your nick with Client.set_nick(). You can also join channels with Client.join() and leave them with Client.part(). As there are a number of other very common actions, expect this part of the API to change and expand.

To send other messages to the network, you need to construct an appropriate byte string, and pass it to Connection.send. You will probably not want to do this by hand, so use the messages.build_message method to help you.

Still to come

Features that I am hoping to implement in future:

  • More message parsers

    At the moment, we only have a special parser for PRIVMSG messages, but there is room for loads more.

  • Handle more text encodings.

    At the moment, the to_unicode method is a little prone to errors when cChardet provides a non standard encoding.

  • Find a nicely overridable way to remove the basic_handlers boilerplate from Client subclasses that still allows ways to customise the behaviour.

  • Full API documentation.

    I would really like to document the full API, not just the basics. I'd also like to explain my rationale for the design decisions I took, and how the library contrasts to what is currently available elsewhere.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].