def join(self, sock, source, name): user = self.users[sock] if name not in self.channels: channel = self.channels[name] = Channel(name) else: channel = self.channels[name] if user in channel.users: return user.channels.append(name) channel.users.append(user) self._notify(channel.users, Message("JOIN", name, prefix=user.prefix)) if channel.topic: self.fire(reply(sock, RPL_TOPIC(channel.topic))) else: self.fire(reply(sock, RPL_NOTOPIC(channel.name))) self.fire( reply( sock, RPL_NAMEREPLY(channel.name, [x.prefix for x in channel.users]))) self.fire(reply(sock, RPL_ENDOFNAMES(channel.name)))
def mode(self, sock, source, mask, mode=None, params=None): if mask.startswith('#'): if mask not in self.channels: return self.fire(reply(sock, ERR_NOSUCHCHANNEL(mask))) channel = self.channels[mask] if not params: self.fire(reply(sock, RPL_CHANNELMODEIS(channel.name, channel.mode))) elif mask not in self.users: return self.fire(reply(sock, ERR_NOSUCHNICK(mask)))
def list(self, sock, source): self.fire(reply(sock, RPL_LISTSTART())) for channel in self.channels.values(): self.fire( reply( sock, RPL_LIST(channel, str(len(channel.users)), channel.topic or ''))) self.fire(reply(sock, RPL_LISTEND()))
def signon(self, sock, source): user = self.users[sock] if user.signon: return user.signon = time() self.fire(reply(sock, RPL_WELCOME(self.network))) self.fire(reply(sock, RPL_YOURHOST(self.host, self.version))) self.fire(reply(sock, ERR_NOMOTD()))
def _on_event(self, event, *args, **kwargs): name = event.name if name in ("generate_events",) or name.endswith("_done"): return if name.endswith("_complete") and isinstance(args[0], response): e, value = args if value is None: return values = (value,) if not isinstance(value, (GeneratorType, tuple, list)) else value sock, source = e.args[:2] args = e.args[2:] for value in values: if isinstance(value, Message): self.fire(reply(sock, value)) elif isinstance(value, Event): self.fire(value) else: self.logger.warn( u("Handler for {0:s} returned unknown type {1} ({2})").format( name, value.__class__.__name__, repr(value) ) ) elif isinstance(event, response): sock = args[0] user = User.objects.filter(sock=sock).first() if user and not user.registered and event.name not in ("nick", "cap", "pass", "user"): return self.fire(reply(sock, ERR_NOTREGISTERED())) if event.name not in self.command: event.stop() return self.fire(reply(sock, ERR_UNKNOWNCOMMAND(event.name))) component = self.command[event.name] handlers = (x for x in type(component).handlers() if event.name in x.names) handler = next(handlers, None) assert handler is not None argspec = getargspec(handler) args = list(argspec.args) for skip in ("self", "event"): if args and args[0] == skip: del args[0] if len(args) < (len(args) - len(argspec.defaults or ())): event.stop() return self.fire(reply(sock, ERR_NEEDMOREPARAMS(event.name))) event.complete = True event.complete_channels = ("server",) self.fire(event, "commands")
def signon(self, sock, source): user = self.users[sock] if user.signon: return user.signon = time() self.fire(reply(sock, RPL_WELCOME(self.network))) self.fire(reply(sock, RPL_YOURHOST(self.host, self.version))) self.fire(reply(sock, ERR_NOMOTD())) # Force users to join #circuits self.fire(response.create("join", sock, source, "#circuits"))
def on_privmsg_or_notice(self, event, sock, source, target, message): user = User.objects.filter(sock=sock).first() prefix = user.prefix or joinprefix(*source) if target and target[0] in (u("&"), u("#"),): channel = Channel.objects.filter(name=target).first() if channel is None: return ERR_NOSUCHCHANNEL(target) if u("n") in channel.modes: if not user.oper and user not in channel.users: return ERR_CANNOTSENDTOCHAN(channel.name) if u("m") in channel.modes: if not user.oper and user not in chain(channel.operators, channel.voiced): return ERR_CANNOTSENDTOCHAN(channel.name) self.notify( channel.users, _Message(u("PRIVMSG"), target, message, prefix=prefix), user ) else: user = User.objects.filter(nick=target).first() if user is None: return ERR_NOSUCHNICK(target) return reply( user.sock, _Message( event.name.upper(), target, message, prefix=prefix ) )
def signon(self, sock, source): version = u"{0}-{1}".format(self.server.name, self.server.version) umodes = u"".join(user_modes.keys()) chmodes = u"".join(channel_modes.keys()) self.fire(reply(sock, RPL_WELCOME(self.server.network))) self.fire(reply(sock, RPL_YOURHOST(self.server.host, version))) self.fire(reply(sock, RPL_CREATED(self.server.created))) self.fire(reply(sock, RPL_MYINFO(self.server.host, version, umodes, chmodes))) result = yield self.call(supports()) self.fire(reply(sock, RPL_ISUPPORT(tuple(chain(*result.value))))) self.fire(response.create("lusers", sock, source)) self.fire(response.create("motd", sock, source))
def on_privmsg_or_notice(self, event, sock, source, target, message): user = User.objects.filter(sock=sock).first() prefix = user.prefix or joinprefix(*source) if target.startswith(u"#"): channel = Channel.objects.filter(name=target).first() if channel is None: return ERR_NOSUCHCHANNEL(target) if "n" in channel.modes: if not user.oper and user not in channel.users: return ERR_CANNOTSENDTOCHAN(channel.name) if "m" in channel.modes: if not user.oper and user not in chain(channel.operators, channel.voiced): return ERR_CANNOTSENDTOCHAN(channel.name) self.notify(channel.users, _Message(u"PRIVMSG", target, message, prefix=prefix), user) else: user = User.objects.filter(nick=target).first() if user is None: return ERR_NOSUCHNICK(target) return reply( user.sock, _Message(event.name.upper(), target, message, prefix=prefix))
def _on_event(self, event, *args, **kwargs): if event.name.endswith("_done"): return if isinstance(event, response): if event.name not in self.commands: event.stop() self.fire(reply(args[0], ERR_UNKNOWNCOMMAND(event.name)))
def connect(self, sock, *args): host, port = args[:2] self.pending[sock] = True self.fire(reply(sock, Message(u"NOTICE", u"*", u"*** Looking up your hostname..."))) e = task(check_host, sock) e.complete = True e.complete_channels = ("server",) self.fire(e, "threadpool")
def privmsg(self, sock, source, target, message): user = self.users[sock] if target.startswith("#"): if target not in self.channels: return self.fire(reply(sock, ERR_NOSUCHCHANNEL(target))) channel = self.channels[target] self._notify( channel.users, Message("PRIVMSG", target, message, prefix=user.prefix), user) else: if target not in self.nicks: return self.fire(reply(sock, ERR_NOSUCHNICK(target))) self.fire( reply(self.nicks[target].sock, Message("PRIVMSG", target, message, prefix=user.prefix)))
def nick(self, sock, source, nick): user = self.users[sock] if nick in self.nicks: return self.fire(reply(sock, ERR_NICKNAMEINUSE(nick))) if not user.registered: user.registered = True self.fire(response.create("signon", sock, user)) user.nick = nick self.nicks[nick] = user
def join(self, sock, source, name): user = self.users[sock] if name not in self.channels: channel = self.channels[name] = Channel(name) else: channel = self.channels[name] if user in channel.users: return user.channels.append(name) channel.users.append(user) self._notify( channel.users, Message("JOIN", name, prefix=user.prefix) ) self.fire(reply(sock, RPL_NOTOPIC(name))) self.fire(reply(sock, RPL_NAMEREPLY(channel))) self.fire(reply(sock, RPL_ENDOFNAMES()))
def connect(self, sock, *args): host, port = args[:2] self.pending[sock] = True self.fire( reply(sock, Message(u"NOTICE", u"*", u"*** Looking up your hostname..."))) e = task(check_host, sock) e.complete = True e.complete_channels = ("server", ) self.fire(e, "threadpool")
def kill(self, sock, source, target, reason=None): user = User.objects.filter(sock=sock).first() if not user.oper: return ERR_NOPRIVILEGES() nick = User.objects.filter(nick=target).first() if nick is None: return ERR_NOSUCHNICK(target) reason = u("Killed by {0}: {1}").format(user.nick, reason or nick.nick) self.fire(response.create("quit", nick.sock, nick.source, reason, disconnect=False)) self.fire(reply(nick.sock, ERROR(nick.host, reason)), "server") Timer(1, close(nick.sock), "server").register(self)
def privmsg(self, sock, source, target, message): user = self.users[sock] if target.startswith("#"): if target not in self.channels: return self.fire(reply(sock, ERR_NOSUCHCHANNEL(target))) channel = self.channels[target] self._notify( channel.users, Message("PRIVMSG", target, message, prefix=user.prefix), user ) else: if target not in self.nicks: return self.fire(reply(sock, ERR_NOSUCHNICK(target))) self.fire( reply( self.nicks[target].sock, Message("PRIVMSG", target, message, prefix=user.prefix) ) )
def poll(self): now = int(time()) reason = u("Ping timeout: {0} seconds") for user in User.objects.all(): if user.lastping and not user.lastpong and ((now - user.lastping) > self.timeout): delta = now - user.lastping self.fire(response.create("quit", user.sock, user.source, reason.format(delta))) self.fire(reply(user.sock, ERROR(user.host, reason.format(delta))), "server") Timer(1, close(user.sock), "server").register(self) else: self.fire(write(user.sock, bytes(PING(self.server.host)))) user.lastping = int(time()) user.lastpong = None user.save()
def _user_message(self, event, sock, source, target, message): user = User.objects.filter(sock=sock).first() user.lastmessage = int(time()) user.save() nick = User.objects.filter(nick=target).first() if nick is None: return ERR_NOSUCHNICK(target) self.fire( reply( nick.sock, _Message(event.name.upper(), nick.nick, message, prefix=user.prefix) ), "server" ) if nick.away: return RPL_AWAY(nick.nick, nick.away)
def kill(self, sock, source, target, reason=None): user = User.objects.filter(sock=sock).first() if not user.oper: return ERR_NOPRIVILEGES() nick = User.objects.filter(nick=target).first() if nick is None: return ERR_NOSUCHNICK(target) reason = u("Killed: {0}").format(reason) if reason else nick.nick self.fire( response.create("quit", nick.sock, nick.source, reason, disconnect=False)) self.fire(reply(nick.sock, ERROR(reason)), "server") Timer(1, close(nick.sock), "server").register(self)
def task_complete(self, e, value): _, sock = e.args del self.pending[sock] self.fire(reply(sock, Message(u"NOTICE", u"*", u"*** Found your hostname"))) user = User.objects.filter(sock=sock).first() if user.userinfo is None: userinfo = UserInfo() userinfo.save() user.userinfo = userinfo user.save() user.userinfo.host = value user.userinfo.save() if user.registered: return signon(sock, user.source)
def task_complete(self, e, value): _, sock = e.args del self.pending[sock] self.fire( reply(sock, Message(u"NOTICE", u"*", u"*** Found your hostname"))) user = User.objects.filter(sock=sock).first() if user.userinfo is None: userinfo = UserInfo() userinfo.save() user.userinfo = userinfo user.save() user.userinfo.host = value user.userinfo.save() if user.registered: return signon(sock, user.source)
def task_complete(self, e, value): _, sock = e.args del self.pending[sock] self.fire(reply(sock, Message(u("NOTICE"), u("*"), u("*** Found your hostname")))) user = User.objects.filter(sock=sock).first() if user.userinfo is None: userinfo = UserInfo() userinfo.save() user.userinfo = userinfo user.save() user.userinfo.host = value user.userinfo.save() if user.registered: self.fire(signon(user.sock, user.source)) else: self.logger.warn(u("User {0} is not registered!").format(user.nick))
def who(self, sock, source, mask): if mask.startswith("#"): if mask not in self.channels: return self.fire(reply(sock, ERR_NOSUCHCHANNEL(mask))) channel = self.channels[mask] for user in channel.users: self.fire(reply(sock, RPL_WHOREPLY(user, mask, self.host))) self.fire(reply(sock, RPL_ENDOFWHO(mask))) else: if mask not in self.nicks: return self.fire(reply(sock, ERR_NOSUCHNICK(mask))) user = self.nicks[mask] self.fire(reply(sock, RPL_WHOREPLY(user, mask, self.host))) self.fire(reply(sock, RPL_ENDOFWHO(mask)))
def send_channel_list(self, sock, channels): self.fire(reply(sock, _M(u"321", "Channel Users Name"))) for channel, count, topic in channels: self.fire(reply(sock, RPL_LIST(channel, count, topic or ''))) self.fire(reply(sock, RPL_LISTEND()))
def broadcast(self, users, message, *exclude): for user in users: if user in exclude: continue self.fire(reply(user.sock, message))
def _on_event(self, event, *args, **kwargs): name = event.name if name in ("generate_events", ) or name.endswith("_done"): return if name.endswith("_complete") and isinstance(args[0], response): e, value = args if value is None: return values = ((value, ) if not isinstance(value, ( GeneratorType, tuple, list, )) else value) sock, source = e.args[:2] args = e.args[2:] for value in values: if isinstance(value, Message): self.fire(reply(sock, value)) elif isinstance(value, Event): self.fire(value) else: self.logger.warn((u"Handler for {0:s} returned " u"unknown type {1:s} ({2:s})").format( name, value.__class__.__name__, repr(value))) elif isinstance(event, response): sock = args[0] user = User.objects.filter(sock=sock).first() if user and not user.registered and event.name not in ( "nick", "cap", "pass", "user", ): return self.fire(reply(sock, ERR_NOTREGISTERED())) if event.name not in self.command: event.stop() return self.fire(reply(sock, ERR_UNKNOWNCOMMAND(event.name))) component = self.command[event.name] handlers = (x for x in type(component).handlers() if event.name in x.names) handler = next(handlers, None) assert handler is not None argspec = getargspec(handler) args = list(argspec.args) for skip in ( "self", "event", ): if args and args[0] == skip: del args[0] if len(args) < (len(args) - len(argspec.defaults or ())): event.stop() return self.fire(reply(sock, ERR_NEEDMOREPARAMS(event.name))) event.complete = True event.complete_channels = ("server", ) self.fire(event, "commands")
def _notify(self, users, message, exclude=None): for user in users: if exclude is not None and user is exclude: continue self.fire(reply(user.sock, message))
def ping(self, event, sock, source, server): event.stop() self.fire(reply(sock, Message("PONG", server)))