Package: miniirc
miniircA relatively simple thread-safe(-ish) IRC client framework.To install miniirc, simply runpip3 install miniirc.If you have previously used miniirc, you may want to read thedeprecations list(last updated 2020-04-28).This repository is available on bothGitHubandGitLab.Parametersirc=miniirc.IRC(ip,port,nick,channels=None,*,ssl=None,ident=None,realname=None,persist=True,debug=False,ns_identity=None,auto_connect=True,ircv3_caps=set(),quit_message='I grew sick and died.',ping_interval=60,ping_timeout=None,verify_ssl=True,executor=None)Note that everything before the * is a positional argument.Typical usageYou don't need to add every argument, and theip,port,nick, andchannelsarguments should be specified as positional arguments.irc=miniirc.IRC('irc.example.com',6697,'my-bot',['#my-channel'],ns_identity=('my-bot','hunter2'),executor=concurrent.futures.ThreadPoolExecutor(),keepnick=True)If you are not doing anything with the main thread after connecting to IRC,
please callirc.wait_until_disconnected()to prevent Python from trying to
shut down while miniirc is still connected, breaking thread pools (in
Python 3.9 and later).irc.wait_until_disconnected()Parameter descriptionsParameterDescriptionipThe IP/hostname of the IRC server to connect to.portThe port to connect to.nickThe nickname of the bot.channelsThe channels to join on connect. This can be an iterable containing strings (list, set, etc), or (since v1.5.0) a comma-delimited string.sslEnable TLS/SSL. IfNone, TLS is disabled unless the port is6697.identThe ident to use, defaults tonick.realnameThe realname to use, defaults tonickas well.persistWhether to automatically reconnect.debugEnables debug mode, prints all IRC messages. This can also be a file-like object (with write mode enabled) if you want debug messages to be written into a file instead of being printed to stdout, or a function (for examplelogging.debug).ns_identityThe NickServ account to use as a tuple/list of length 2 (('<user>', '<password>')). For compatibility, this can be a string ('<user> <password>').auto_connectRunsirc.connect()straight away.ircv3_capsA set() of additional IRCv3 capabilities to request. SASL is auto-added ifns_identityis specified.connect_modesA mode string (for example'+B') of UMODEs to set when connected.quit_messageSets the default quit message. This can be modified per-quit withirc.disconnect().ping_intervalIf no packets are sent or received for this amount of seconds, miniirc will send aPING, and if no reply is sent, after the ping timeout, miniirc will attempt to reconnect. Set toNoneto disable.ping_timeoutThe ping timeout used alongside the aboveping_intervaloption, if unspecified will default toping_interval.verify_sslVerifies TLS/SSL certificates. Disabling this is not recommended as it opens the IRC connection up to MiTM attacks. If you have trouble with certificate verification, try runningpip3 install certififirst.executorAn instance ofconcurrent.futures.ThreadPoolExecutorto use when running handlers.keepnickIf enabled, miniirc will attempt to obtain the original nick like ZNC's *keepnick.irc.nickwill be the original nickname rather than the current one.The only mandatory parameters areip,port, andnick.FunctionsFunctionDescriptionchange_parser(parser=...)See the message parser section for documentation.connect()Connects to the IRC server if not already connected.ctcp(target, *msg, reply=False, tags=None)Sends aCTCPrequest or reply totarget.debug(...)Debug, callsprint(...)if debug mode is on.disconnect(msg=..., *, auto_reconnect=False)Disconnects from the IRC server.auto_reconnectwill be overridden byself.persistif set toTrue.Handler(...)An event handler, seeHandlersfor more info.me(target, *msg, tags=None)Sends a/me(CTCP ACTION) totarget.msg(target, *msg, tags=None)Sends aPRIVMSGtotarget.targetshould not contain spaces or start with a colon.notice(target, *msg, tags=None)Sends aNOTICEtotarget.targetshould not contain spaces or start with a colon.quote(*msg, force=False, tags=None)Sends a raw message to IRC, useforce=Trueto send while disconnected. Do not send multiple commands in oneirc.quote(), as the newlines will be stripped and it will be sent as one command. Thetagsparameter optionally allows you to add adictwith IRCv3 client tags (all starting in+), and will not be sent to IRC servers that do not support client tags.send(*msg, force=False, tags=None)Sends a command to the IRC server, treating every positional argument as a parameter. The usage of this is recommended overirc.quote()unless you know what you are doing.wait_until_disconnected()Waits until the IRC server is disconnected and automatic reconnecting is turned off.Note that ifforce=Falseonirc.quote(orirc.msgetc is called) while
miniirc is not connected, messages will be temporarily stored and then sent
once miniirc is connected. Settingforce=Truewill throw errors if miniirc is
completely disconnected (irc.connectedisNone).irc.quote and irc.sendThe two functionsirc.quoteandirc.sendmay sound similar, however are
fundamentally different:irc.quote()joins all provided arguments with spaces
and sends them as a raw message to IRC, whileirc.send()treats each argument
as a parameter. If arguments passed toirc.send()contain spaces, they are
replaced with U+00A0 (a non-breaking space, visually similar to a regular
space however not interpreted as one).Examplesirc.quote('PRIVMSG', '#channel :Hello,', 'world!')sends "Hello, world!"
to #channel.irc.quote('PRIVMSG', '#channel', 'Hello, world!')is invalid ("Hello," and
"world!" are sent as separate parameters).irc.send('PRIVMSG', '#channel', 'Hello, world!')will send "Hello, world!"
to "#channel".irc.send('PRIVMSG', '#channel :Hello,', 'world!')will send "world!" to#channel\xa0:Hello,, where\xa0is a non-breaking space.If you are unsure and do not need compatibility with miniirc <1.5.0, useirc.send().PRIVMSGis just used as an example, if you need to sendPRIVMSGs useirc.msg()instead.VariablesThese variables should not be changed outsideminiirc.py.VariableDescriptionactive_capsAsetof IRCv3 capabilities that have been successfully negotiated with the IRC server. This is empty while disconnected.connectedA boolean (orNone),Truewhen miniirc is connected,Falsewhen miniirc is connecting, andNonewhen miniirc is not connected.current_nickThe bot/client's current nickname. Do not modify this, and use this instead ofirc.nickwhen getting the bot's current nickname.isupportAdictwith values (not necessarily strings) fromISUPPORTmessages sent to the client.msglenThe maximum length (in bytes) of messages (including\r\n). This is automatically changed if the server supports theoragono.io/maxline-2capability.nickThe nickname to use when connecting to IRC. Until miniirc v2.0.0, you should only use or modify this while disconnected, as it is currently automatically updated with nickname changes.The following arguments passed tominiirc.IRCare also available:ip,port,channels,ssl,ident,realname,persist,connect_modes,quit_message,ping_interval,verify_ssl.Handlersminiirc.Handlerandminiirc.CmdHandlerare function decorators that add
functions to an event handler list. Functions in this list are called in their
own thread when their respective IRC event(s) is/are received. Handlers may
work on every IRC object in existence (miniirc.Handler) or only on
specific IRC objects (irc.Handler).The basic syntax for a handler is as followed, where*eventsis a list of events (PRIVMSG,NOTICE, etc) are called.importminiirc@miniirc.Handler(*events,colon=False)defhandler(irc,hostmask,args):# irc:      An 'IRC' object.# hostmask: A 'hostmask' object.# args:     A list containing the arguments sent to the command. Everything#             following the first `:` in the command is put into one item#             (args[-1]). If "colon" is "False", the leading ":" (if any)#             is automatically removed. To prevent your code from horribly#             breaking, always set it to False unless you know what you are#             doing.passRecommendations when using handlers:If you don't need support for miniirc <1.4.0 and are parsing the last
parameter, settingcolontoFalseis strongly recommended. If thecolonparameter is omitted, it defaults toTrue, however this will
change when miniirc v2.0.0 is released.AlthoughHandlerandCmdHandlercurrently accept any object that can be
converted to a string, every event is converted to a string internally.Not specifying theircv3parameter when it is not required
prevents a redundantdictfrom being created.To add handlers to a specificIRCobject and not every one in existence,
useirc.Handlerandirc.CmdHandlerinstead. If you want to create aBotorClientclass and automatically add handlers toIRCobjects
created inside it, seemaking existing functions handlers.Hostmask objectHostmasks are tuples with the format('user', 'ident', 'hostname'). Ifidentandhostnamearen't sent from the server, they will be filled in with the
previous value. If a command is received without a hostmask, all thehostmaskelements will be set to the name of the command. This is deprecated, however,
and when miniirc v2.0.0 is released thehostmaskelements will be set to
empty strings.Making existing functions handlersYou can make existing functions handlers (for example class instance methods)
withirc.Handler(*events)(handler_function). You probably don't want to useminiirc.Handlerfor class instance methods, as this will create a handler
that gets triggered for everyIRCobject.You can also add multiple handlers of the same type easily:add_handler=irc.Handler('PRIVMSG',colon=False)add_handler(handler_1)add_handler(self.instance_handler)This is useful if you want to create aBot(orClient) class and add
class-specific handlers without creating global process-wide handlers or
creating a wrapper function for every class instance.IRCv3 supportIRCv3 tagsIf you want your handler to support IRCv3 message tags, you need to addircv3=Trueto theHandlerorCmdHandlerdecorator. You will need to add atagsparameter to your function afterhostmask. IRCv3 tags are sent to the
handlers asdicts, with values of either strings orTrue.miniirc will automatically un-escape IRCv3 tag values.importminiirc@miniirc.Handler(*events,colon=False,ircv3=True)defhandler(irc,hostmask,tags,args):passIRCv3 capabilitiesYou can handle IRCv3 capabilities before connecting using a handler.
You must useforce=Trueon anyirc.quote()called here, as when this is
called, miniirc may not yet be fully connected. Do not use thecolonargument
forHandlerwhen creating these handlers to avoid unexpected side-effects.importminiirc@miniirc.Handler('IRCv3 my-cap-name')defhandler(irc,hostmask,args):# Process the capability here# IRCv3.2 capabilities:#   args = ['my-cap-name', 'IRCv3.2-parameters']# IRCv3.1 capabilities:#   args = ['my-cap-name']# Remove the capability from the processing list.irc.finish_negotiation(args[0])# This can also be 'my-cap-name'.Custom message parsers (not recommended)If the IRC server you are connecting to supports a non-standard message syntax, you can
create custom message parsers. These are called with the raw message (as astr) and
can either returnNoneto ignore the message or a 4-tuple (cmd, hostmask, tags, args)
that will then be sent on to the handlers. The items in this 4-tuple should be the same
type as the items expected by handlers (andcmdshould be a string).Message parser exampleThis message parser makes the normal parser allow~as an IRCv3 tag prefix character.importminiircdefmy_message_parser(msg):ifmsg.startswith('~'):msg='@'+msg[1:]returnminiirc.ircv3_message_parser(msg)Changing message parsersTo change message parsers, you can useirc.change_parser(func=...). Iffuncis not
specified, it will default to the built-in parser. You can only change message parsers
on-the-fly (for example in an IRCv3 CAP handler). If you need to change message parsers
before connecting, you can disableauto_connectand change it then.irc=miniirc.IRC(...,auto_connect=False)irc.change_parser(my_message_parser)irc.connect()Handling multiple eventsIf you want to handle multiple events and/or be able to get the name of the
event being triggered, you can useirc.CmdHandler. This will pass an extracommandargument to the handler function (betweenircandhostmask),
containing a string with the command name (such asPRIVMSG).Catch-all handlersPlease do not use these unless there is no other alternative.If you want to handleeveryevent, you can use catch-all handlers. To create
these, you can callirc.CmdHandler()withoutany parameters. Note that this
handler will be called many times while connecting (and once connected).You cannot callirc.Handler()without parameters.Exampleimportminiirc# Not required, however this makes sure miniirc isn't outdated.assertminiirc.ver>=(1,8,2)@miniirc.Handler('PRIVMSG','NOTICE',colon=True)defhandler(irc,hostmask,args):print(hostmask[0],'sent a message to',args[0],'with content',args[1])# nickname sent a message to #channel with content :Hello, world!@miniirc.CmdHandler('PRIVMSG','NOTICE',colon=False)defcmdhandler(irc,command,hostmask,args):print(hostmask[0],'sent a',command,'to',args[0],'with content',args[1])# nickname sent a PRIVMSG to #channel with content Hello, world!This will print a line whenever the bot gets aPRIVMSGorNOTICE.Misc functionsminiirc provides the following helper functions:NameDescriptionminiirc.get_ca_certs()Runscertifi.where()ifcertifiis installed, otherwise returnsNone.miniirc.ircv3_message_parser(msg)The default IRCv2/IRCv3 message parser, returnscmd, hostmask, tags, args.miniirc.verA tuple containing version information.miniirc.versionTheCTCP VERSIONreply, can be changed.The version numbering system should be similar toSemVer,
however backwards compatibility is preserved where possible when major releases
change.Python version supportPython 3.3 and below are unsupported and do not work with miniirc.Python 3.4, 3.5, and 3.6 are currently supported, but support will likely be
dropped in miniirc v2.1.0. Major bugfixes may be backported to v2.0 for a
few months after v2.1's release.Python 3.7 and above should work with the latest stable version of miniirc.If there is a bug/error in Python 3.4 or newer, please open an issue or pull
request onGitHuborGitLab.If you are using Python 3.7 or an older version of Python, I strongly
recommend updating. Later versions of Python include features such as f-strings
that make software development easier.miniirc_extrasIf you want more advanced(-ish) features such as user tracking, you can useminiirc_extras(GitHub,GitLab). Note that miniirc_extras
is still in beta and there will be breaking API changes in the future.DeprecationsIf miniirc v2.0.0 is ever released, the following breaking changes will
(probably) be made:Internal-only attributesirc.handlers,irc.sock, andirc.sendq(please do not use these) will be renamed. Again, please do not use these.irc.nickwill always be the nickname used when connecting to IRC rather
than the current nickname, useirc.current_nickfor the current nickname
(since v1.4.3).irc.ns_identitywill be stored as a tuple instead of a string, for example('username', 'password with spaces')instead of'username password with spaces'. Both formats are currently accepted and
will be accepted in thens_identitykeyword argument.No exceptions will be raised inirc.quote/irc.sendwithforce=Truewhen the socket is closed. Instead of relying on these exceptions, useirc.connectedwhich is set toNonewhen completely disconnected.As stated in the Python version support section, Python 3.4 support will be
dropped in miniirc v2.1.0, however bugfixes will be backported for a few
months.Thecolonkeyword argument toHandlerandCmdHandlerwill default toFalseinstead ofTrue.Unspecified hostmasks will be an empty string instead of the command. Don't
rely on this "feature" if possible, simply ignore the hostmask if you do
not need it.Theextended-joincapability will be requested by default, useargs[0]instead ofargs[-1]to get the channel from aJOINevent.Thetagskeyword argument will be read-only.Working examples/implementationsHere is a list of some (open-source) bots using miniirc, in alphabetical order:irc-rss-feed-bot- Posts RSS entry titles and shortened URLs to IRC
channels.Python 3.8+irc-url-title-bot- Gets webpage titles from URLs posted in IRC channels.Python 3.8+lurklite- A generic configurable IRC bot.GitHublink.stdinbot- A very simple bot that dumps stdin to an IRC channel.GitHublink.Want to add your own bot/client to this list? Open an issue onGitHuborGitLab.