def _join(self, sock, source, name): user = models.User.objects.filter(sock=sock).first() if name and name[0] not in self.parent.chantypes: return ERR_NOSUCHCHANNEL(name) if VALID_CHANNEL_REGEX.match(name) is None: return ERR_NOSUCHCHANNEL(name) if len(name) > self.parent.channellen: return ERR_NOSUCHCHANNEL(name) replies = [JOIN(name, prefix=user.prefix)] channel = models.Channel.objects.filter(name=name).first() if channel is None: channel = models.Channel(name=name) channel.save() if user in channel.users: return type = name[0] nchannels = len([x for x in user.channels if channel.type == type]) chanlimit = self.parent.chanlimit.get(type, None) if chanlimit and nchannels >= chanlimit: return ERR_TOOMANYCHANNELS(name) self.notify(channel.users[:], JOIN(name, prefix=user.prefix)) user.channels.append(channel) user.save() if not channel.users: replies.append( MODE(name, u"+o {0}".format(user.nick), prefix=self.server.host)) channel.operators.append(user) channel.save() channel.users.append(user) channel.save() self.fire( response.create("topic", sock, source, channel.name, joined=True), "server") self.fire(response.create("names", sock, source, channel.name), "server") return replies
def who(self, sock, source, mask): if mask.startswith(u"#"): channel = models.Channel.objects.filter(name=mask).first() if channel is None: return ERR_NOSUCHCHANNEL(mask) replies = [] for user in channel.users: userinfo = user.userinfo status = u("G") if user.away else u("H") status += (u("*") if user.oper else u("")) status += (u("@") if user in channel.operators else u("")) status += (u("+") if user in channel.voiced else u("")) replies.append( RPL_WHOREPLY(channel.name, userinfo.user, userinfo.host, self.parent.server.host, user.nick, status, 0, userinfo.name or "")) replies.append(RPL_ENDOFWHO(mask)) return replies else: user = models.User.objects.filter(nick=mask).first() if user is None: return ERR_NOSUCHNICK(mask) userinfo = user.userinfo status = u("G") if user.away else u("H") status += (u("*") if user.oper else u("")) return (RPL_WHOREPLY(mask, userinfo.user, userinfo.host, self.parent.server.host, user.nick, status, 0, userinfo.naem), RPL_ENDOFWHO(mask))
def topic(self, sock, source, name, topic=None, **kwargs): user = models.User.objects.filter(sock=sock).first() channel = models.Channel.objects.filter(name=name).first() if channel is None: return ERR_NOSUCHCHANNEL(name) _topic, _topic_setter, _topic_timestamp = channel.topic if topic is None and not _topic: if kwargs.get("joined", False): return return RPL_NOTOPIC(channel.name) if topic is None: return (RPL_TOPIC(channel.name, _topic), RPL_TOPICWHO(channel.name, _topic_setter, _topic_timestamp)) if not user.oper and u"t" in channel.modes and user not in channel.operators: return ERR_CHANOPRIVSNEEDED(channel.name) channel.topic = (topic, user.prefix) self.notify(channel.users[:], TOPIC(channel.name, topic, prefix=user.prefix))
def kick(self, sock, source, name, nick, reason=None): user = models.User.objects.filter(sock=sock).first() channel = models.Channel.objects.filter(name=name).first() if channel is None: return ERR_NOSUCHCHANNEL(name) if not user.oper and user not in channel.operators: return ERR_CHANOPRIVSNEEDED(channel.name) if nick not in imap(attrgetter("nick"), channel.users): return ERR_USERNOTINCHANNEL(nick, channel.name) nick = models.User.objects.filter(nick=nick).first() self.notify( channel.users[:], Message(u"KICK", channel.name, nick.nick, reason or nick.nick, prefix=user.prefix)) nick.channels.remove(channel) nick.save() channel.users.remove(nick) if user in channel.operators: channel.operators.remove(user) if user in channel.voiced: channel.voiced.remove(user) channel.save() if not channel.users: channel.delete()
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 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 names(self, sock, source, name): channel = models.Channel.objects.filter(name=name).first() if channel is None: return ERR_NOSUCHCHANNEL(name) return [ RPL_NAMEREPLY(channel.name, channel.userprefixes), RPL_ENDOFNAMES(name), ]
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 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 topic(self, sock, source, name, topic=None): user = models.User.objects.filter(sock=sock).first() channel = models.Channel.objects.filter(name=name).first() if channel is None: return ERR_NOSUCHCHANNEL(name) if topic is None and not channel.topic: return RPL_NOTOPIC(channel.name) if topic is None: return RPL_TOPIC(channel.name, channel.topic) if not user.oper and u"t" in channel.modes and user not in channel.operators: return ERR_CHANOPRIVSNEEDED(channel.name) channel.topic = topic channel.save() self.notify(channel.users[:], TOPIC(channel.name, topic, prefix=user.prefix))
def mode(self, sock, source, *args): """MODE command This command allows the user to display modes of another user or channel and set modes of other users and channels. """ if not args: return ERR_NEEDMOREPARAMS(u"MODE") user = User.objects.filter(sock=sock).first() args = iter(args) mask = next(args) if mask.startswith(u("#")): channel = Channel.objects.filter(name=mask).first() if channel is None: return ERR_NOSUCHCHANNEL(mask) mode = next(args, None) if mode is None: return RPL_CHANNELMODEIS(channel.name, u("+{0}").format(channel.modes)) return self._process_channel_modes(user, channel, [mode] + list(args)) else: nick = User.objects.filter(nick=mask).first() if nick is None: return ERR_NOSUCHNICK(mask) if user.nick != nick.nick: return ERR_USERSDONTMATCH() mode = next(args, None) if mode is None: return RPL_UMODEIS(u("+{0}").format(nick.modes)) return process_user_modes(nick, [mode] + list(args))