# Copyright (c) 2014 Tobias Marquardt
#
# Distributed under terms of the (2-clause) BSD license.
"""
Low level functions for creation of irc client messages, as well as classes
with constants for string commands, numeric commands and error responses.
Specification: RFC 2812 'IRC: Client Protocol'.
"""
__all__ = ['Err']
class Cmd:
""" Commands """
# Message Registration
PASS = 'PASS'
NICK = 'NICK'
USER = 'USER'
QUIT = 'QUIT'
MODE = 'MODE'
# Channel Operations
JOIN = 'JOIN'
PART = 'PART'
KICK = 'KICK'
TOPIC = 'TOPIC'
# Sending Messages
PRIVMSG = 'PRIVMSG'
# Miscellaneous
PING = 'PING'
PONG = 'PONG'
class UserMode:
""" User Modes
User modes apply server-wide. So user mode 'o' should not be confused
with channel mode 'o'.
"""
AWAY = 'a'
INVISIBLE = 'i'
WALLOPS_RECEIVER = 'w'
RESTRICTED = 'r'
OPERATOR = 'o'
LOCAL_OPERATOR = 'O'
NOTICES_RECEIVER = 's'
class ChannelMode:
""" Channel Modes """
# Channel modes affecting a single user
OPERATOR = 'o'
VOICE = 'v'
# Channel modes affecting the channel itself
# Not yet implemented...
class Rpl:
""" Command Replies """
WELCOME = 1
NAMREPLY = 353
ENDOFNAMES = 366
TOPIC = 332
[docs]class Err:
""" Error Replies
Contains numerical constants for errors as defined by the irc client
protocol as well as the keywords of error specific parameters.
Error numbers and parameters are passed to
:py:meth:`handle_error(self, error, **params)<fredirc.IRCHandler.handle_error()>`.
You can take a look at :py:attr:`.ERROR_PARAMETERS` to find out the
parameter keywords for a particular error.
See the :ref:`beginner's guide<guide_handle-errors>` for an example on how
to use this class to handle errors.
"""
NOSUCHNICK = 401
NOSUCHSERVER = 402
NOSUCHCHANNEL = 403
CANNOTSENDTOCHAN = 404
TOOMANYCHANNELS = 405
WASNOSUCHNICK = 406
TOOMANYTARGETS = 407
NOSUCHSERVICE = 408
NOORIGIN = 409
NORECIPIENT = 411
NOTEXTTOSEND = 412
NOTOPLEVEL = 413
WILDTOPLEVEL = 414
BADMASK = 415
UNKNOWNCOMMAND = 421
NOMOTD = 422
NOADMININFO = 423
FILEERROR = 424
NONICKNAMEGIVEN = 431
ERRONEUSNICKNAME = 432
NICKNAMEINUSE = 433
NICKCOLLISION = 436
UNAVAILRESOURCE = 437
USERNOTINCHANNEL = 441
NOTONCHANNEL = 442
USERONCHANNEL = 443
NOLOGIN = 444
SUMMONDISABLED = 445
USERSDISABLED = 446
NOTREGISTERED = 451
NEEDMOREPARAMS = 461
ALREADYREGISTRED = 462
NOPERMFORHOST = 463
PASSWDMISMATCH = 464
YOUREBANNEDCREEP = 465
KEYSET = 467
YOUWILLBEBANNED = 466
CHANNELISFULL = 471
UNKNOWNMODE = 472
INVITEONLYCHAN = 473
BANNEDFROMCHAN = 474
BADCHANNELKEY = 475
BADCHANMASK = 476
NOCHANMODES = 477
BANLISTFULL = 478
NOPRIVILEGES = 481
CHANOPRIVSNEEDED = 482
CANTKILLSERVER = 483
RESTRICTED = 484
UNIQOPPRIVSNEEDED = 485
NOOPERHOST = 491
UMODEUNKNOWNFLAG = 501
USERSDONTMATCH = 502
ERROR_PARAMETERS = {
NOSUCHNICK: ['nick', 'message'],
NOSUCHSERVER: ['server_name', 'message'],
NOSUCHCHANNEL: ['channel_name', 'message'],
CANNOTSENDTOCHAN: ['channel_name', 'message'],
TOOMANYCHANNELS: ['channel_name', 'message'],
WASNOSUCHNICK: ['nick', 'message'],
TOOMANYTARGETS: ['target', 'message'],
NOSUCHSERVICE: ['service_name', 'message'],
NOORIGIN: ['message'],
NORECIPIENT: ['message'],
NOTEXTTOSEND: ['message'],
NOTOPLEVEL: ['mask', 'message'],
WILDTOPLEVEL: ['mask', 'message'],
BADMASK: ['mask', 'message'],
UNKNOWNCOMMAND: ['command', 'message'],
NOMOTD: ['message'],
NOADMININFO: ['server', 'message'],
FILEERROR: ['message'],
NONICKNAMEGIVEN: ['message'],
ERRONEUSNICKNAME: ['nick', 'message'],
NICKNAMEINUSE: ['nick', 'message'],
NICKCOLLISION: ['nick', 'message'],
UNAVAILRESOURCE: ['nick', 'message'],
USERNOTINCHANNEL: ['nick', 'channel', 'message'],
NOTONCHANNEL: ['channel', 'message'],
USERONCHANNEL: ['user', 'channel', 'message'],
NOLOGIN: ['user', 'channel', 'message'],
SUMMONDISABLED: ['message'],
USERSDISABLED: ['message'],
NOTREGISTERED: ['message'],
NEEDMOREPARAMS: ['command', 'message'],
ALREADYREGISTRED: ['message'],
NOPERMFORHOST: ['message'],
PASSWDMISMATCH: ['message'],
YOUREBANNEDCREEP: ['message'],
YOUWILLBEBANNED: [],
KEYSET: ['channel', 'message'],
CHANNELISFULL: ['channel', 'message'],
UNKNOWNMODE: ['mode', 'message'],
INVITEONLYCHAN: ['channel', 'message'],
BANNEDFROMCHAN: ['channel', 'message'],
BADCHANNELKEY: ['channel', 'message'],
BADCHANMASK: ['channel', 'message'],
NOCHANMODES: ['channel', 'message'],
BANLISTFULL: ['channel', 'message'],
NOPRIVILEGES: ['message'],
CHANOPRIVSNEEDED: ['channel', 'message'],
CANTKILLSERVER: ['message'],
RESTRICTED: ['message'],
UNIQOPPRIVSNEEDED: ['message'],
NOOPERHOST: ['message'],
UMODEUNKNOWNFLAG: ['message'],
USERSDONTMATCH: ['message'],
}
def nick(name):
return '{nick_cmd} {name}'.format(
nick_cmd=Cmd.NICK, name=name)
def password(pwd=None):
if pwd:
return '{pass_cmd} :{password}'.format(
pass_cmd=Cmd.PASS, password=pwd)
else:
return Cmd.PASS
def user(user_name, real_name, invisible=False, receive_wallops=False):
# TODO set mode correctly
mode = 0
return '{user_cmd} {user} {mode} * :{real_name}'.format(
user_cmd=Cmd.USER, user=user_name, mode=mode, real_name=real_name)
def quit(message=None):
if message:
return '{quit_cmd} :{message}'.format(
quit_cmd=Cmd.QUIT, message=message)
else:
return Cmd.QUIT
def join(channels):
return '{join_cmd} {channels}'.format(
join_cmd=Cmd.JOIN, channels=','.join(channels))
def pong(server):
return '{pong_cmd} :{server}'.format(
pong_cmd=Cmd.PONG, server=server)
def privmsg(target, message, sender=None):
if not sender:
sender = ''
return ':{sender} {msg_cmd} {target} :{message}'.format(
sender=sender, msg_cmd=Cmd.PRIVMSG, target=target, message=message)
def part(channels, message):
return '{part_cmd} {channels} :{message}'.format(
part_cmd=Cmd.PART, channels=','.join(channels), message=message)
def kick(channels, users, message=None):
if not message:
message = ''
return '{kick_cmd} {channels} {users} :{message}'.format(
kick_cmd=Cmd.KICK, channels=','.join(channels), users=','.join(users),
message=message)
def channel_mode(channel, mode_change):
"""
Args:
mode_change (ChannelModelChange)
"""
change = '+' if mode_change.added else '-'
return '{mode_cmd} {channel} {change}{mode} {params}'.format(
mode_cmd=Cmd.MODE, channel=channel, change=change,
mode=mode_change.mode, params=' '.join(mode_change.params))