mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-22 03:49:27 +01:00
Get labeled-reply working just fine
This commit is contained in:
parent
470109461b
commit
e0fa97d344
@ -27,7 +27,7 @@ const (
|
|||||||
var (
|
var (
|
||||||
// EnabledSaslMechanisms contains the SASL mechanisms that exist and that we support.
|
// EnabledSaslMechanisms contains the SASL mechanisms that exist and that we support.
|
||||||
// This can be moved to some other data structure/place if we need to load/unload mechs later.
|
// This can be moved to some other data structure/place if we need to load/unload mechs later.
|
||||||
EnabledSaslMechanisms = map[string]func(*Server, *Client, string, []byte) bool{
|
EnabledSaslMechanisms = map[string]func(*Server, *Client, string, []byte, *ResponseBuffer) bool{
|
||||||
"PLAIN": authPlainHandler,
|
"PLAIN": authPlainHandler,
|
||||||
"EXTERNAL": authExternalHandler,
|
"EXTERNAL": authExternalHandler,
|
||||||
}
|
}
|
||||||
@ -128,9 +128,9 @@ func (client *Client) LogoutOfAccount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// successfulSaslAuth means that a SASL auth attempt completed successfully, and is used to dispatch messages.
|
// successfulSaslAuth means that a SASL auth attempt completed successfully, and is used to dispatch messages.
|
||||||
func (client *Client) successfulSaslAuth() {
|
func (client *Client) successfulSaslAuth(rb *ResponseBuffer) {
|
||||||
client.Send(nil, client.server.name, RPL_LOGGEDIN, client.nick, client.nickMaskString, client.account.Name, fmt.Sprintf("You are now logged in as %s", client.account.Name))
|
rb.Add(nil, client.server.name, RPL_LOGGEDIN, client.nick, client.nickMaskString, client.account.Name, fmt.Sprintf("You are now logged in as %s", client.account.Name))
|
||||||
client.Send(nil, client.server.name, RPL_SASLSUCCESS, client.nick, client.t("SASL authentication successful"))
|
rb.Add(nil, client.server.name, RPL_SASLSUCCESS, client.nick, client.t("SASL authentication successful"))
|
||||||
|
|
||||||
// dispatch account-notify
|
// dispatch account-notify
|
||||||
for friend := range client.Friends(caps.AccountNotify) {
|
for friend := range client.Friends(caps.AccountNotify) {
|
||||||
|
156
irc/channel.go
156
irc/channel.go
@ -171,7 +171,7 @@ func (channel *Channel) regenerateMembersCache(noLocksNeeded bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Names sends the list of users joined to the channel to the given client.
|
// Names sends the list of users joined to the channel to the given client.
|
||||||
func (channel *Channel) Names(client *Client) {
|
func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
||||||
currentNicks := channel.nicks(client)
|
currentNicks := channel.nicks(client)
|
||||||
// assemble and send replies
|
// assemble and send replies
|
||||||
maxNamLen := 480 - len(client.server.name) - len(client.nick)
|
maxNamLen := 480 - len(client.server.name) - len(client.nick)
|
||||||
@ -183,7 +183,7 @@ func (channel *Channel) Names(client *Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(buffer)+1+len(nick) > maxNamLen {
|
if len(buffer)+1+len(nick) > maxNamLen {
|
||||||
client.Send(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
||||||
buffer = nick
|
buffer = nick
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -192,8 +192,8 @@ func (channel *Channel) Names(client *Client) {
|
|||||||
buffer += nick
|
buffer += nick
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Send(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
||||||
client.Send(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
|
rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientIsAtLeast returns whether the client has at least the given channel privilege.
|
// ClientIsAtLeast returns whether the client has at least the given channel privilege.
|
||||||
@ -349,42 +349,50 @@ func (channel *Channel) IsEmpty() bool {
|
|||||||
|
|
||||||
// Join joins the given client to this channel (if they can be joined).
|
// Join joins the given client to this channel (if they can be joined).
|
||||||
//TODO(dan): /SAJOIN and maybe a ForceJoin function?
|
//TODO(dan): /SAJOIN and maybe a ForceJoin function?
|
||||||
func (channel *Channel) Join(client *Client, key string) {
|
func (channel *Channel) Join(client *Client, key string, rb *ResponseBuffer) {
|
||||||
if channel.hasClient(client) {
|
if channel.hasClient(client) {
|
||||||
// already joined, no message needs to be sent
|
// already joined, no message needs to be sent
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.IsFull() {
|
if channel.IsFull() {
|
||||||
client.Send(nil, client.server.name, ERR_CHANNELISFULL, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "l"))
|
rb.Add(nil, client.server.name, ERR_CHANNELISFULL, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "l"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !channel.CheckKey(key) {
|
if !channel.CheckKey(key) {
|
||||||
client.Send(nil, client.server.name, ERR_BADCHANNELKEY, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "k"))
|
rb.Add(nil, client.server.name, ERR_BADCHANNELKEY, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "k"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isInvited := channel.lists[modes.InviteMask].Match(client.nickMaskCasefolded)
|
isInvited := channel.lists[modes.InviteMask].Match(client.nickMaskCasefolded)
|
||||||
if channel.flags[modes.InviteOnly] && !isInvited {
|
if channel.flags[modes.InviteOnly] && !isInvited {
|
||||||
client.Send(nil, client.server.name, ERR_INVITEONLYCHAN, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "i"))
|
rb.Add(nil, client.server.name, ERR_INVITEONLYCHAN, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "i"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.lists[modes.BanMask].Match(client.nickMaskCasefolded) &&
|
if channel.lists[modes.BanMask].Match(client.nickMaskCasefolded) &&
|
||||||
!isInvited &&
|
!isInvited &&
|
||||||
!channel.lists[modes.ExceptMask].Match(client.nickMaskCasefolded) {
|
!channel.lists[modes.ExceptMask].Match(client.nickMaskCasefolded) {
|
||||||
client.Send(nil, client.server.name, ERR_BANNEDFROMCHAN, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "b"))
|
rb.Add(nil, client.server.name, ERR_BANNEDFROMCHAN, channel.name, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "b"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
client.server.logger.Debug("join", fmt.Sprintf("%s joined channel %s", client.nick, channel.name))
|
client.server.logger.Debug("join", fmt.Sprintf("%s joined channel %s", client.nick, channel.name))
|
||||||
|
|
||||||
for _, member := range channel.Members() {
|
for _, member := range channel.Members() {
|
||||||
if member.capabilities.Has(caps.ExtendedJoin) {
|
if member == client {
|
||||||
member.Send(nil, client.nickMaskString, "JOIN", channel.name, client.account.Name, client.realname)
|
if member.capabilities.Has(caps.ExtendedJoin) {
|
||||||
|
rb.Add(nil, client.nickMaskString, "JOIN", channel.name, client.account.Name, client.realname)
|
||||||
|
} else {
|
||||||
|
rb.Add(nil, client.nickMaskString, "JOIN", channel.name)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
member.Send(nil, client.nickMaskString, "JOIN", channel.name)
|
if member.capabilities.Has(caps.ExtendedJoin) {
|
||||||
|
member.Send(nil, client.nickMaskString, "JOIN", channel.name, client.account.Name, client.realname)
|
||||||
|
} else {
|
||||||
|
member.Send(nil, client.nickMaskString, "JOIN", channel.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,31 +419,39 @@ func (channel *Channel) Join(client *Client, key string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if client.capabilities.Has(caps.ExtendedJoin) {
|
if client.capabilities.Has(caps.ExtendedJoin) {
|
||||||
client.Send(nil, client.nickMaskString, "JOIN", channel.name, client.account.Name, client.realname)
|
rb.Add(nil, client.nickMaskString, "JOIN", channel.name, client.account.Name, client.realname)
|
||||||
} else {
|
} else {
|
||||||
client.Send(nil, client.nickMaskString, "JOIN", channel.name)
|
rb.Add(nil, client.nickMaskString, "JOIN", channel.name)
|
||||||
}
|
}
|
||||||
// don't send topic when it's an entirely new channel
|
// don't send topic when it's an entirely new channel
|
||||||
if !newChannel {
|
if !newChannel {
|
||||||
channel.SendTopic(client)
|
channel.SendTopic(client, rb)
|
||||||
}
|
}
|
||||||
channel.Names(client)
|
channel.Names(client, rb)
|
||||||
if givenMode != nil {
|
if givenMode != nil {
|
||||||
for _, member := range channel.Members() {
|
for _, member := range channel.Members() {
|
||||||
member.Send(nil, client.server.name, "MODE", channel.name, fmt.Sprintf("+%v", *givenMode), client.nick)
|
if member == client {
|
||||||
|
rb.Add(nil, client.server.name, "MODE", channel.name, fmt.Sprintf("+%v", *givenMode), client.nick)
|
||||||
|
} else {
|
||||||
|
member.Send(nil, client.server.name, "MODE", channel.name, fmt.Sprintf("+%v", *givenMode), client.nick)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part parts the given client from this channel, with the given message.
|
// Part parts the given client from this channel, with the given message.
|
||||||
func (channel *Channel) Part(client *Client, message string) {
|
func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer) {
|
||||||
if !channel.hasClient(client) {
|
if !channel.hasClient(client) {
|
||||||
client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
|
rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, member := range channel.Members() {
|
for _, member := range channel.Members() {
|
||||||
member.Send(nil, client.nickMaskString, "PART", channel.name, message)
|
if member == client {
|
||||||
|
rb.Add(nil, client.nickMaskString, "PART", channel.name, message)
|
||||||
|
} else {
|
||||||
|
member.Send(nil, client.nickMaskString, "PART", channel.name, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
channel.Quit(client)
|
channel.Quit(client)
|
||||||
|
|
||||||
@ -443,9 +459,9 @@ func (channel *Channel) Part(client *Client, message string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SendTopic sends the channel topic to the given client.
|
// SendTopic sends the channel topic to the given client.
|
||||||
func (channel *Channel) SendTopic(client *Client) {
|
func (channel *Channel) SendTopic(client *Client, rb *ResponseBuffer) {
|
||||||
if !channel.hasClient(client) {
|
if !channel.hasClient(client) {
|
||||||
client.Send(nil, client.server.name, ERR_NOTONCHANNEL, client.nick, channel.name, client.t("You're not on that channel"))
|
rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.nick, channel.name, client.t("You're not on that channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,23 +473,23 @@ func (channel *Channel) SendTopic(client *Client) {
|
|||||||
channel.stateMutex.RUnlock()
|
channel.stateMutex.RUnlock()
|
||||||
|
|
||||||
if topic == "" {
|
if topic == "" {
|
||||||
client.Send(nil, client.server.name, RPL_NOTOPIC, client.nick, name, client.t("No topic is set"))
|
rb.Add(nil, client.server.name, RPL_NOTOPIC, client.nick, name, client.t("No topic is set"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Send(nil, client.server.name, RPL_TOPIC, client.nick, name, topic)
|
rb.Add(nil, client.server.name, RPL_TOPIC, client.nick, name, topic)
|
||||||
client.Send(nil, client.server.name, RPL_TOPICTIME, client.nick, name, topicSetBy, strconv.FormatInt(topicSetTime.Unix(), 10))
|
rb.Add(nil, client.server.name, RPL_TOPICTIME, client.nick, name, topicSetBy, strconv.FormatInt(topicSetTime.Unix(), 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTopic sets the topic of this channel, if the client is allowed to do so.
|
// SetTopic sets the topic of this channel, if the client is allowed to do so.
|
||||||
func (channel *Channel) SetTopic(client *Client, topic string) {
|
func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffer) {
|
||||||
if !(client.flags[modes.Operator] || channel.hasClient(client)) {
|
if !(client.flags[modes.Operator] || channel.hasClient(client)) {
|
||||||
client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
|
rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.HasMode(modes.OpOnlyTopic) && !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
|
if channel.HasMode(modes.OpOnlyTopic) && !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
|
||||||
client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
|
rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +504,11 @@ func (channel *Channel) SetTopic(client *Client, topic string) {
|
|||||||
channel.stateMutex.Unlock()
|
channel.stateMutex.Unlock()
|
||||||
|
|
||||||
for _, member := range channel.Members() {
|
for _, member := range channel.Members() {
|
||||||
member.Send(nil, client.nickMaskString, "TOPIC", channel.name, topic)
|
if member == client {
|
||||||
|
rb.Add(nil, client.nickMaskString, "TOPIC", channel.name, topic)
|
||||||
|
} else {
|
||||||
|
member.Send(nil, client.nickMaskString, "TOPIC", channel.name, topic)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
go channel.server.channelRegistry.StoreChannel(channel, false)
|
go channel.server.channelRegistry.StoreChannel(channel, false)
|
||||||
@ -513,14 +533,14 @@ func (channel *Channel) CanSpeak(client *Client) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TagMsg sends a tag message to everyone in this channel who can accept them.
|
// TagMsg sends a tag message to everyone in this channel who can accept them.
|
||||||
func (channel *Channel) TagMsg(msgid string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client) {
|
func (channel *Channel) TagMsg(msgid string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, rb *ResponseBuffer) {
|
||||||
channel.sendMessage(msgid, "TAGMSG", []caps.Capability{caps.MessageTags}, minPrefix, clientOnlyTags, client, nil)
|
channel.sendMessage(msgid, "TAGMSG", []caps.Capability{caps.MessageTags}, minPrefix, clientOnlyTags, client, nil, rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendMessage sends a given message to everyone on this channel.
|
// sendMessage sends a given message to everyone on this channel.
|
||||||
func (channel *Channel) sendMessage(msgid, cmd string, requiredCaps []caps.Capability, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message *string) {
|
func (channel *Channel) sendMessage(msgid, cmd string, requiredCaps []caps.Capability, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message *string, rb *ResponseBuffer) {
|
||||||
if !channel.CanSpeak(client) {
|
if !channel.CanSpeak(client) {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,26 +574,26 @@ func (channel *Channel) sendMessage(msgid, cmd string, requiredCaps []caps.Capab
|
|||||||
}
|
}
|
||||||
|
|
||||||
if message == nil {
|
if message == nil {
|
||||||
member.SendFromClient(msgid, client, messageTagsToUse, cmd, channel.name)
|
rb.AddFromClient(msgid, client, messageTagsToUse, cmd, channel.name)
|
||||||
} else {
|
} else {
|
||||||
member.SendFromClient(msgid, client, messageTagsToUse, cmd, channel.name, *message)
|
rb.AddFromClient(msgid, client, messageTagsToUse, cmd, channel.name, *message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SplitPrivMsg sends a private message to everyone in this channel.
|
// SplitPrivMsg sends a private message to everyone in this channel.
|
||||||
func (channel *Channel) SplitPrivMsg(msgid string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
func (channel *Channel) SplitPrivMsg(msgid string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage, rb *ResponseBuffer) {
|
||||||
channel.sendSplitMessage(msgid, "PRIVMSG", minPrefix, clientOnlyTags, client, &message)
|
channel.sendSplitMessage(msgid, "PRIVMSG", minPrefix, clientOnlyTags, client, &message, rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SplitNotice sends a private message to everyone in this channel.
|
// SplitNotice sends a private message to everyone in this channel.
|
||||||
func (channel *Channel) SplitNotice(msgid string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage) {
|
func (channel *Channel) SplitNotice(msgid string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message SplitMessage, rb *ResponseBuffer) {
|
||||||
channel.sendSplitMessage(msgid, "NOTICE", minPrefix, clientOnlyTags, client, &message)
|
channel.sendSplitMessage(msgid, "NOTICE", minPrefix, clientOnlyTags, client, &message, rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) sendSplitMessage(msgid, cmd string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message *SplitMessage) {
|
func (channel *Channel) sendSplitMessage(msgid, cmd string, minPrefix *modes.Mode, clientOnlyTags *map[string]ircmsg.TagValue, client *Client, message *SplitMessage, rb *ResponseBuffer) {
|
||||||
if !channel.CanSpeak(client) {
|
if !channel.CanSpeak(client) {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,25 +615,33 @@ func (channel *Channel) sendSplitMessage(msgid, cmd string, minPrefix *modes.Mod
|
|||||||
tagsToUse = clientOnlyTags
|
tagsToUse = clientOnlyTags
|
||||||
}
|
}
|
||||||
|
|
||||||
if message == nil {
|
if member == client {
|
||||||
member.SendFromClient(msgid, client, tagsToUse, cmd, channel.name)
|
if message == nil {
|
||||||
|
rb.AddFromClient(msgid, client, tagsToUse, cmd, channel.name)
|
||||||
|
} else {
|
||||||
|
rb.AddSplitMessageFromClient(msgid, client, tagsToUse, cmd, channel.name, *message)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
member.SendSplitMsgFromClient(msgid, client, tagsToUse, cmd, channel.name, *message)
|
if message == nil {
|
||||||
|
member.SendFromClient(msgid, client, tagsToUse, cmd, channel.name)
|
||||||
|
} else {
|
||||||
|
member.SendSplitMsgFromClient(msgid, client, tagsToUse, cmd, channel.name, *message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) applyModeMemberNoMutex(client *Client, mode modes.Mode, op modes.ModeOp, nick string) *modes.ModeChange {
|
func (channel *Channel) applyModeMemberNoMutex(client *Client, mode modes.Mode, op modes.ModeOp, nick string, rb *ResponseBuffer) *modes.ModeChange {
|
||||||
if nick == "" {
|
if nick == "" {
|
||||||
//TODO(dan): shouldn't this be handled before it reaches this function?
|
//TODO(dan): shouldn't this be handled before it reaches this function?
|
||||||
client.Send(nil, client.server.name, ERR_NEEDMOREPARAMS, "MODE", client.t("Not enough parameters"))
|
rb.Add(nil, client.server.name, ERR_NEEDMOREPARAMS, "MODE", client.t("Not enough parameters"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
casefoldedName, err := CasefoldName(nick)
|
casefoldedName, err := CasefoldName(nick)
|
||||||
target := channel.server.clients.Get(casefoldedName)
|
target := channel.server.clients.Get(casefoldedName)
|
||||||
if err != nil || target == nil {
|
if err != nil || target == nil {
|
||||||
client.Send(nil, client.server.name, ERR_NOSUCHNICK, client.nick, nick, client.t("No such nick"))
|
rb.Add(nil, client.server.name, ERR_NOSUCHNICK, client.nick, nick, client.t("No such nick"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,7 +656,7 @@ func (channel *Channel) applyModeMemberNoMutex(client *Client, mode modes.Mode,
|
|||||||
channel.stateMutex.Unlock()
|
channel.stateMutex.Unlock()
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
client.Send(nil, client.server.name, ERR_USERNOTINCHANNEL, client.nick, channel.name, client.t("They aren't on that channel"))
|
rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.nick, channel.name, client.t("They aren't on that channel"))
|
||||||
return nil
|
return nil
|
||||||
} else if already {
|
} else if already {
|
||||||
return nil
|
return nil
|
||||||
@ -642,7 +670,7 @@ func (channel *Channel) applyModeMemberNoMutex(client *Client, mode modes.Mode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ShowMaskList shows the given list to the client.
|
// ShowMaskList shows the given list to the client.
|
||||||
func (channel *Channel) ShowMaskList(client *Client, mode modes.Mode) {
|
func (channel *Channel) ShowMaskList(client *Client, mode modes.Mode, rb *ResponseBuffer) {
|
||||||
// choose appropriate modes
|
// choose appropriate modes
|
||||||
var rpllist, rplendoflist string
|
var rpllist, rplendoflist string
|
||||||
if mode == modes.BanMask {
|
if mode == modes.BanMask {
|
||||||
@ -660,14 +688,14 @@ func (channel *Channel) ShowMaskList(client *Client, mode modes.Mode) {
|
|||||||
channel.stateMutex.RLock()
|
channel.stateMutex.RLock()
|
||||||
// XXX don't acquire any new locks in this section, besides Socket.Write
|
// XXX don't acquire any new locks in this section, besides Socket.Write
|
||||||
for mask := range channel.lists[mode].masks {
|
for mask := range channel.lists[mode].masks {
|
||||||
client.Send(nil, client.server.name, rpllist, nick, channel.name, mask)
|
rb.Add(nil, client.server.name, rpllist, nick, channel.name, mask)
|
||||||
}
|
}
|
||||||
channel.stateMutex.RUnlock()
|
channel.stateMutex.RUnlock()
|
||||||
|
|
||||||
client.Send(nil, client.server.name, rplendoflist, nick, channel.name, client.t("End of list"))
|
rb.Add(nil, client.server.name, rplendoflist, nick, channel.name, client.t("End of list"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) applyModeMask(client *Client, mode modes.Mode, op modes.ModeOp, mask string) bool {
|
func (channel *Channel) applyModeMask(client *Client, mode modes.Mode, op modes.ModeOp, mask string, rb *ResponseBuffer) bool {
|
||||||
list := channel.lists[mode]
|
list := channel.lists[mode]
|
||||||
if list == nil {
|
if list == nil {
|
||||||
// This should never happen, but better safe than panicky.
|
// This should never happen, but better safe than panicky.
|
||||||
@ -675,12 +703,12 @@ func (channel *Channel) applyModeMask(client *Client, mode modes.Mode, op modes.
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (op == modes.List) || (mask == "") {
|
if (op == modes.List) || (mask == "") {
|
||||||
channel.ShowMaskList(client, mode)
|
channel.ShowMaskList(client, mode, rb)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
|
if !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
|
||||||
client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
|
rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,21 +733,21 @@ func (channel *Channel) Quit(client *Client) {
|
|||||||
client.removeChannel(channel)
|
client.removeChannel(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) Kick(client *Client, target *Client, comment string) {
|
func (channel *Channel) Kick(client *Client, target *Client, comment string, rb *ResponseBuffer) {
|
||||||
if !(client.flags[modes.Operator] || channel.hasClient(client)) {
|
if !(client.flags[modes.Operator] || channel.hasClient(client)) {
|
||||||
client.Send(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
|
rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
|
if !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !channel.hasClient(target) {
|
if !channel.hasClient(target) {
|
||||||
client.Send(nil, client.server.name, ERR_USERNOTINCHANNEL, client.nick, channel.name, client.t("They aren't on that channel"))
|
rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.nick, channel.name, client.t("They aren't on that channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !channel.ClientHasPrivsOver(client, target) {
|
if !channel.ClientHasPrivsOver(client, target) {
|
||||||
client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
|
rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -738,14 +766,14 @@ func (channel *Channel) Kick(client *Client, target *Client, comment string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invite invites the given client to the channel, if the inviter can do so.
|
// Invite invites the given client to the channel, if the inviter can do so.
|
||||||
func (channel *Channel) Invite(invitee *Client, inviter *Client) {
|
func (channel *Channel) Invite(invitee *Client, inviter *Client, rb *ResponseBuffer) {
|
||||||
if channel.flags[modes.InviteOnly] && !channel.ClientIsAtLeast(inviter, modes.ChannelOperator) {
|
if channel.flags[modes.InviteOnly] && !channel.ClientIsAtLeast(inviter, modes.ChannelOperator) {
|
||||||
inviter.Send(nil, inviter.server.name, ERR_CHANOPRIVSNEEDED, channel.name, inviter.t("You're not a channel operator"))
|
rb.Add(nil, inviter.server.name, ERR_CHANOPRIVSNEEDED, channel.name, inviter.t("You're not a channel operator"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !channel.hasClient(inviter) {
|
if !channel.hasClient(inviter) {
|
||||||
inviter.Send(nil, inviter.server.name, ERR_NOTONCHANNEL, channel.name, inviter.t("You're not on that channel"))
|
rb.Add(nil, inviter.server.name, ERR_NOTONCHANNEL, channel.name, inviter.t("You're not on that channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,9 +792,9 @@ func (channel *Channel) Invite(invitee *Client, inviter *Client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO(dan): should inviter.server.name here be inviter.nickMaskString ?
|
//TODO(dan): should inviter.server.name here be inviter.nickMaskString ?
|
||||||
inviter.Send(nil, inviter.server.name, RPL_INVITING, invitee.nick, channel.name)
|
rb.Add(nil, inviter.server.name, RPL_INVITING, invitee.nick, channel.name)
|
||||||
invitee.Send(nil, inviter.nickMaskString, "INVITE", invitee.nick, channel.name)
|
invitee.Send(nil, inviter.nickMaskString, "INVITE", invitee.nick, channel.name)
|
||||||
if invitee.flags[modes.Away] {
|
if invitee.flags[modes.Away] {
|
||||||
inviter.Send(nil, inviter.server.name, RPL_AWAY, invitee.nick, invitee.awayMessage)
|
rb.Add(nil, inviter.server.name, RPL_AWAY, invitee.nick, invitee.awayMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func (cm *ChannelManager) Get(name string) *Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Join causes `client` to join the channel named `name`, creating it if necessary.
|
// Join causes `client` to join the channel named `name`, creating it if necessary.
|
||||||
func (cm *ChannelManager) Join(client *Client, name string, key string) error {
|
func (cm *ChannelManager) Join(client *Client, name string, key string, rb *ResponseBuffer) error {
|
||||||
server := client.server
|
server := client.server
|
||||||
casefoldedName, err := CasefoldChannel(name)
|
casefoldedName, err := CasefoldChannel(name)
|
||||||
if err != nil || len(casefoldedName) > server.Limits().ChannelLen {
|
if err != nil || len(casefoldedName) > server.Limits().ChannelLen {
|
||||||
@ -74,7 +74,7 @@ func (cm *ChannelManager) Join(client *Client, name string, key string) error {
|
|||||||
entry.pendingJoins += 1
|
entry.pendingJoins += 1
|
||||||
cm.Unlock()
|
cm.Unlock()
|
||||||
|
|
||||||
entry.channel.Join(client, key)
|
entry.channel.Join(client, key, rb)
|
||||||
|
|
||||||
cm.maybeCleanup(entry, true)
|
cm.maybeCleanup(entry, true)
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ func (cm *ChannelManager) maybeCleanup(entry *channelManagerEntry, afterJoin boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Part parts `client` from the channel named `name`, deleting it if it's empty.
|
// Part parts `client` from the channel named `name`, deleting it if it's empty.
|
||||||
func (cm *ChannelManager) Part(client *Client, name string, message string) error {
|
func (cm *ChannelManager) Part(client *Client, name string, message string, rb *ResponseBuffer) error {
|
||||||
casefoldedName, err := CasefoldChannel(name)
|
casefoldedName, err := CasefoldChannel(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errNoSuchChannel
|
return errNoSuchChannel
|
||||||
@ -120,7 +120,7 @@ func (cm *ChannelManager) Part(client *Client, name string, message string) erro
|
|||||||
if entry == nil {
|
if entry == nil {
|
||||||
return errNoSuchChannel
|
return errNoSuchChannel
|
||||||
}
|
}
|
||||||
entry.channel.Part(client, message)
|
entry.channel.Part(client, message, rb)
|
||||||
cm.maybeCleanup(entry, false)
|
cm.maybeCleanup(entry, false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ChanServNotice sends the client a notice from ChanServ.
|
// ChanServNotice sends the client a notice from ChanServ.
|
||||||
func (client *Client) ChanServNotice(text string) {
|
func (rb *ResponseBuffer) ChanServNotice(text string) {
|
||||||
client.Send(nil, fmt.Sprintf("ChanServ!services@%s", client.server.name), "NOTICE", client.nick, text)
|
rb.Add(nil, fmt.Sprintf("ChanServ!services@%s", rb.target.server.name), "NOTICE", rb.target.nick, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// chanservReceiveNotice handles NOTICEs that ChanServ receives.
|
// chanservReceiveNotice handles NOTICEs that ChanServ receives.
|
||||||
func (server *Server) chanservNoticeHandler(client *Client, message string) {
|
func (server *Server) chanservNoticeHandler(client *Client, message string, rb *ResponseBuffer) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
// chanservReceiveNotice handles NOTICEs that ChanServ receives.
|
// chanservReceiveNotice handles NOTICEs that ChanServ receives.
|
||||||
func (server *Server) chanservPrivmsgHandler(client *Client, message string) {
|
func (server *Server) chanservPrivmsgHandler(client *Client, message string, rb *ResponseBuffer) {
|
||||||
var params []string
|
var params []string
|
||||||
for _, p := range strings.Split(message, " ") {
|
for _, p := range strings.Split(message, " ") {
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
@ -31,7 +31,7 @@ func (server *Server) chanservPrivmsgHandler(client *Client, message string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(params) < 1 {
|
if len(params) < 1 {
|
||||||
client.ChanServNotice(client.t("You need to run a command"))
|
rb.ChanServNotice(client.t("You need to run a command"))
|
||||||
//TODO(dan): dump CS help here
|
//TODO(dan): dump CS help here
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -41,57 +41,57 @@ func (server *Server) chanservPrivmsgHandler(client *Client, message string) {
|
|||||||
|
|
||||||
if command == "register" {
|
if command == "register" {
|
||||||
if len(params) < 2 {
|
if len(params) < 2 {
|
||||||
client.ChanServNotice(client.t("Syntax: REGISTER <channel>"))
|
rb.ChanServNotice(client.t("Syntax: REGISTER <channel>"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
server.chanservRegisterHandler(client, params[1])
|
server.chanservRegisterHandler(client, params[1], rb)
|
||||||
} else {
|
} else {
|
||||||
client.ChanServNotice(client.t("Sorry, I don't know that command"))
|
rb.ChanServNotice(client.t("Sorry, I don't know that command"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// chanservRegisterHandler handles the ChanServ REGISTER subcommand.
|
// chanservRegisterHandler handles the ChanServ REGISTER subcommand.
|
||||||
func (server *Server) chanservRegisterHandler(client *Client, channelName string) {
|
func (server *Server) chanservRegisterHandler(client *Client, channelName string, rb *ResponseBuffer) {
|
||||||
if !server.channelRegistrationEnabled {
|
if !server.channelRegistrationEnabled {
|
||||||
client.ChanServNotice(client.t("Channel registration is not enabled"))
|
rb.ChanServNotice(client.t("Channel registration is not enabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
channelKey, err := CasefoldChannel(channelName)
|
channelKey, err := CasefoldChannel(channelName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.ChanServNotice(client.t("Channel name is not valid"))
|
rb.ChanServNotice(client.t("Channel name is not valid"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
channelInfo := server.channels.Get(channelKey)
|
channelInfo := server.channels.Get(channelKey)
|
||||||
if channelInfo == nil || !channelInfo.ClientIsAtLeast(client, modes.ChannelOperator) {
|
if channelInfo == nil || !channelInfo.ClientIsAtLeast(client, modes.ChannelOperator) {
|
||||||
client.ChanServNotice(client.t("You must be an oper on the channel to register it"))
|
rb.ChanServNotice(client.t("You must be an oper on the channel to register it"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.account == &NoAccount {
|
if client.account == &NoAccount {
|
||||||
client.ChanServNotice(client.t("You must be logged in to register a channel"))
|
rb.ChanServNotice(client.t("You must be logged in to register a channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// this provides the synchronization that allows exactly one registration of the channel:
|
// this provides the synchronization that allows exactly one registration of the channel:
|
||||||
err = channelInfo.SetRegistered(client.AccountName())
|
err = channelInfo.SetRegistered(client.AccountName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.ChanServNotice(err.Error())
|
rb.ChanServNotice(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// registration was successful: make the database reflect it
|
// registration was successful: make the database reflect it
|
||||||
go server.channelRegistry.StoreChannel(channelInfo, true)
|
go server.channelRegistry.StoreChannel(channelInfo, true)
|
||||||
|
|
||||||
client.ChanServNotice(fmt.Sprintf(client.t("Channel %s successfully registered"), channelName))
|
rb.ChanServNotice(fmt.Sprintf(client.t("Channel %s successfully registered"), channelName))
|
||||||
|
|
||||||
server.logger.Info("chanserv", fmt.Sprintf("Client %s registered channel %s", client.nick, channelName))
|
server.logger.Info("chanserv", fmt.Sprintf("Client %s registered channel %s", client.nick, channelName))
|
||||||
server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Channel registered $c[grey][$r%s$c[grey]] by $c[grey][$r%s$c[grey]]"), channelName, client.nickMaskString))
|
server.snomasks.Send(sno.LocalChannels, fmt.Sprintf(ircfmt.Unescape("Channel registered $c[grey][$r%s$c[grey]] by $c[grey][$r%s$c[grey]]"), channelName, client.nickMaskString))
|
||||||
|
|
||||||
// give them founder privs
|
// give them founder privs
|
||||||
change := channelInfo.applyModeMemberNoMutex(client, modes.ChannelFounder, modes.Add, client.NickCasefolded())
|
change := channelInfo.applyModeMemberNoMutex(client, modes.ChannelFounder, modes.Add, client.NickCasefolded(), rb)
|
||||||
if change != nil {
|
if change != nil {
|
||||||
//TODO(dan): we should change the name of String and make it return a slice here
|
//TODO(dan): we should change the name of String and make it return a slice here
|
||||||
//TODO(dan): unify this code with code in modes.go
|
//TODO(dan): unify this code with code in modes.go
|
||||||
|
@ -593,12 +593,12 @@ func (client *Client) LoggedIntoAccount() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
|
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
|
||||||
func (client *Client) RplISupport() {
|
func (client *Client) RplISupport(rb *ResponseBuffer) {
|
||||||
translatedISupport := client.t("are supported by this server")
|
translatedISupport := client.t("are supported by this server")
|
||||||
for _, tokenline := range client.server.ISupport().CachedReply {
|
for _, tokenline := range client.server.ISupport().CachedReply {
|
||||||
// ugly trickery ahead
|
// ugly trickery ahead
|
||||||
tokenline = append(tokenline, translatedISupport)
|
tokenline = append(tokenline, translatedISupport)
|
||||||
client.Send(nil, client.server.name, RPL_ISUPPORT, append([]string{client.nick}, tokenline...)...)
|
rb.Add(nil, client.server.name, RPL_ISUPPORT, append([]string{client.nick}, tokenline...)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
610
irc/handlers.go
610
irc/handlers.go
File diff suppressed because it is too large
Load Diff
@ -658,7 +658,7 @@ func GenerateHelpIndices(lm *languages.Manager) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sendHelp sends the client help of the given string.
|
// sendHelp sends the client help of the given string.
|
||||||
func (client *Client) sendHelp(name string, text string) {
|
func (client *Client) sendHelp(name string, text string, rb *ResponseBuffer) {
|
||||||
splitName := strings.Split(name, " ")
|
splitName := strings.Split(name, " ")
|
||||||
textLines := strings.Split(text, "\n")
|
textLines := strings.Split(text, "\n")
|
||||||
|
|
||||||
@ -666,14 +666,14 @@ func (client *Client) sendHelp(name string, text string) {
|
|||||||
args := splitName
|
args := splitName
|
||||||
args = append(args, line)
|
args = append(args, line)
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
client.Send(nil, client.server.name, RPL_HELPSTART, args...)
|
rb.Add(nil, client.server.name, RPL_HELPSTART, args...)
|
||||||
} else {
|
} else {
|
||||||
client.Send(nil, client.server.name, RPL_HELPTXT, args...)
|
rb.Add(nil, client.server.name, RPL_HELPTXT, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args := splitName
|
args := splitName
|
||||||
args = append(args, client.t("End of /HELPOP"))
|
args = append(args, client.t("End of /HELPOP"))
|
||||||
client.Send(nil, client.server.name, RPL_ENDOFHELP, args...)
|
rb.Add(nil, client.server.name, RPL_ENDOFHELP, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHelpIndex returns the help index for the given language.
|
// GetHelpIndex returns the help index for the given language.
|
||||||
|
@ -169,7 +169,7 @@ func ParseChannelModeChanges(params ...string) (modes.ModeChanges, map[rune]bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ApplyChannelModeChanges applies a given set of mode changes.
|
// ApplyChannelModeChanges applies a given set of mode changes.
|
||||||
func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, changes modes.ModeChanges) modes.ModeChanges {
|
func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, changes modes.ModeChanges, rb *ResponseBuffer) modes.ModeChanges {
|
||||||
// so we only output one warning for each list type when full
|
// so we only output one warning for each list type when full
|
||||||
listFullWarned := make(map[modes.Mode]bool)
|
listFullWarned := make(map[modes.Mode]bool)
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
|
|||||||
switch change.Mode {
|
switch change.Mode {
|
||||||
case modes.BanMask, modes.ExceptMask, modes.InviteMask:
|
case modes.BanMask, modes.ExceptMask, modes.InviteMask:
|
||||||
if isListOp(change) {
|
if isListOp(change) {
|
||||||
channel.ShowMaskList(client, change.Mode)
|
channel.ShowMaskList(client, change.Mode, rb)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
|
|||||||
case modes.Add:
|
case modes.Add:
|
||||||
if channel.lists[change.Mode].Length() >= client.server.Limits().ChanListModes {
|
if channel.lists[change.Mode].Length() >= client.server.Limits().ChanListModes {
|
||||||
if !listFullWarned[change.Mode] {
|
if !listFullWarned[change.Mode] {
|
||||||
client.Send(nil, client.server.name, ERR_BANLISTFULL, client.Nick(), channel.Name(), change.Mode.String(), client.t("Channel list is full"))
|
rb.Add(nil, client.server.name, ERR_BANLISTFULL, client.Nick(), channel.Name(), change.Mode.String(), client.t("Channel list is full"))
|
||||||
listFullWarned[change.Mode] = true
|
listFullWarned[change.Mode] = true
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -289,7 +289,7 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
change := channel.applyModeMemberNoMutex(client, change.Mode, change.Op, change.Arg)
|
change := channel.applyModeMemberNoMutex(client, change.Mode, change.Op, change.Arg, rb)
|
||||||
if change != nil {
|
if change != nil {
|
||||||
applied = append(applied, *change)
|
applied = append(applied, *change)
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ func (manager *MonitorManager) List(client *Client) (nicks []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
metadataSubcommands = map[string]func(server *Server, client *Client, msg ircmsg.IrcMessage) bool{
|
metadataSubcommands = map[string]func(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool{
|
||||||
"-": monitorRemoveHandler,
|
"-": monitorRemoveHandler,
|
||||||
"+": monitorAddHandler,
|
"+": monitorAddHandler,
|
||||||
"c": monitorClearHandler,
|
"c": monitorClearHandler,
|
||||||
|
@ -20,17 +20,17 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func performNickChange(server *Server, client *Client, target *Client, newnick string) bool {
|
func performNickChange(server *Server, client *Client, target *Client, newnick string, rb *ResponseBuffer) bool {
|
||||||
nickname := strings.TrimSpace(newnick)
|
nickname := strings.TrimSpace(newnick)
|
||||||
cfnick, err := CasefoldName(nickname)
|
cfnick, err := CasefoldName(nickname)
|
||||||
|
|
||||||
if len(nickname) < 1 {
|
if len(nickname) < 1 {
|
||||||
client.Send(nil, server.name, ERR_NONICKNAMEGIVEN, client.nick, client.t("No nickname given"))
|
rb.Add(nil, server.name, ERR_NONICKNAMEGIVEN, client.nick, client.t("No nickname given"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil || len(nickname) > server.Limits().NickLen || restrictedNicknames[cfnick] {
|
if err != nil || len(nickname) > server.Limits().NickLen || restrictedNicknames[cfnick] {
|
||||||
client.Send(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, nickname, client.t("Erroneous nickname"))
|
rb.Add(nil, server.name, ERR_ERRONEUSNICKNAME, client.nick, nickname, client.t("Erroneous nickname"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,10 +43,10 @@ func performNickChange(server *Server, client *Client, target *Client, newnick s
|
|||||||
origNickMask := target.NickMaskString()
|
origNickMask := target.NickMaskString()
|
||||||
err = client.server.clients.SetNick(target, nickname)
|
err = client.server.clients.SetNick(target, nickname)
|
||||||
if err == errNicknameInUse {
|
if err == errNicknameInUse {
|
||||||
client.Send(nil, server.name, ERR_NICKNAMEINUSE, client.nick, nickname, client.t("Nickname is already in use"))
|
rb.Add(nil, server.name, ERR_NICKNAMEINUSE, client.nick, nickname, client.t("Nickname is already in use"))
|
||||||
return false
|
return false
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "NICK", fmt.Sprintf(client.t("Could not set or change nickname: %s"), err.Error()))
|
rb.Add(nil, server.name, ERR_UNKNOWNERROR, client.nick, "NICK", fmt.Sprintf(client.t("Could not set or change nickname: %s"), err.Error()))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,18 +39,18 @@ func extractParam(line string) (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// nickservNoticeHandler handles NOTICEs that NickServ receives.
|
// nickservNoticeHandler handles NOTICEs that NickServ receives.
|
||||||
func (server *Server) nickservNoticeHandler(client *Client, message string) {
|
func (server *Server) nickservNoticeHandler(client *Client, message string, rb *ResponseBuffer) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
// nickservPrivmsgHandler handles PRIVMSGs that NickServ receives.
|
// nickservPrivmsgHandler handles PRIVMSGs that NickServ receives.
|
||||||
func (server *Server) nickservPrivmsgHandler(client *Client, message string) {
|
func (server *Server) nickservPrivmsgHandler(client *Client, message string, rb *ResponseBuffer) {
|
||||||
command, params := extractParam(message)
|
command, params := extractParam(message)
|
||||||
command = strings.ToLower(command)
|
command = strings.ToLower(command)
|
||||||
|
|
||||||
if command == "help" {
|
if command == "help" {
|
||||||
for _, line := range strings.Split(nickservHelp, "\n") {
|
for _, line := range strings.Split(nickservHelp, "\n") {
|
||||||
client.Notice(line)
|
rb.Notice(line)
|
||||||
}
|
}
|
||||||
} else if command == "register" {
|
} else if command == "register" {
|
||||||
// get params
|
// get params
|
||||||
@ -58,30 +58,30 @@ func (server *Server) nickservPrivmsgHandler(client *Client, message string) {
|
|||||||
|
|
||||||
// fail out if we need to
|
// fail out if we need to
|
||||||
if username == "" {
|
if username == "" {
|
||||||
client.Notice(client.t("No username supplied"))
|
rb.Notice(client.t("No username supplied"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
server.nickservRegisterHandler(client, username, passphrase)
|
server.nickservRegisterHandler(client, username, passphrase, rb)
|
||||||
} else if command == "identify" {
|
} else if command == "identify" {
|
||||||
// get params
|
// get params
|
||||||
username, passphrase := extractParam(params)
|
username, passphrase := extractParam(params)
|
||||||
|
|
||||||
server.nickservIdentifyHandler(client, username, passphrase)
|
server.nickservIdentifyHandler(client, username, passphrase, rb)
|
||||||
} else {
|
} else {
|
||||||
client.Notice(client.t("Command not recognised. To see the available commands, run /NS HELP"))
|
rb.Notice(client.t("Command not recognised. To see the available commands, run /NS HELP"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) nickservRegisterHandler(client *Client, username, passphrase string) {
|
func (server *Server) nickservRegisterHandler(client *Client, username, passphrase string, rb *ResponseBuffer) {
|
||||||
certfp := client.certfp
|
certfp := client.certfp
|
||||||
if passphrase == "" && certfp == "" {
|
if passphrase == "" && certfp == "" {
|
||||||
client.Notice(client.t("You need to either supply a passphrase or be connected via TLS with a client cert"))
|
rb.Notice(client.t("You need to either supply a passphrase or be connected via TLS with a client cert"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !server.accountRegistration.Enabled {
|
if !server.accountRegistration.Enabled {
|
||||||
client.Notice(client.t("Account registration has been disabled"))
|
rb.Notice(client.t("Account registration has been disabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ func (server *Server) nickservRegisterHandler(client *Client, username, passphra
|
|||||||
if server.accountRegistration.AllowMultiplePerConnection {
|
if server.accountRegistration.AllowMultiplePerConnection {
|
||||||
client.LogoutOfAccount()
|
client.LogoutOfAccount()
|
||||||
} else {
|
} else {
|
||||||
client.Notice(client.t("You're already logged into an account"))
|
rb.Notice(client.t("You're already logged into an account"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ func (server *Server) nickservRegisterHandler(client *Client, username, passphra
|
|||||||
casefoldedAccount, err := CasefoldName(account)
|
casefoldedAccount, err := CasefoldName(account)
|
||||||
// probably don't need explicit check for "*" here... but let's do it anyway just to make sure
|
// probably don't need explicit check for "*" here... but let's do it anyway just to make sure
|
||||||
if err != nil || username == "*" {
|
if err != nil || username == "*" {
|
||||||
client.Notice(client.t("Account name is not valid"))
|
rb.Notice(client.t("Account name is not valid"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ func (server *Server) nickservRegisterHandler(client *Client, username, passphra
|
|||||||
_, err := tx.Get(accountKey)
|
_, err := tx.Get(accountKey)
|
||||||
if err != buntdb.ErrNotFound {
|
if err != buntdb.ErrNotFound {
|
||||||
//TODO(dan): if account verified key doesn't exist account is not verified, calc the maximum time without verification and expire and continue if need be
|
//TODO(dan): if account verified key doesn't exist account is not verified, calc the maximum time without verification and expire and continue if need be
|
||||||
client.Notice(client.t("Account already exists"))
|
rb.Notice(client.t("Account already exists"))
|
||||||
return errAccountCreation
|
return errAccountCreation
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ func (server *Server) nickservRegisterHandler(client *Client, username, passphra
|
|||||||
// account could not be created and relevant numerics have been dispatched, abort
|
// account could not be created and relevant numerics have been dispatched, abort
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != errAccountCreation {
|
if err != errAccountCreation {
|
||||||
client.Notice(client.t("Account registration failed"))
|
rb.Notice(client.t("Account registration failed"))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ func (server *Server) nickservRegisterHandler(client *Client, username, passphra
|
|||||||
if err == errCertfpAlreadyExists {
|
if err == errCertfpAlreadyExists {
|
||||||
errMsg = "An account already exists for your certificate fingerprint"
|
errMsg = "An account already exists for your certificate fingerprint"
|
||||||
}
|
}
|
||||||
client.Notice(errMsg)
|
rb.Notice(errMsg)
|
||||||
removeFailedAccRegisterData(server.store, casefoldedAccount)
|
removeFailedAccRegisterData(server.store, casefoldedAccount)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -196,23 +196,23 @@ func (server *Server) nickservRegisterHandler(client *Client, username, passphra
|
|||||||
server.accounts[casefoldedAccount] = &account
|
server.accounts[casefoldedAccount] = &account
|
||||||
client.account = &account
|
client.account = &account
|
||||||
|
|
||||||
client.Notice(client.t("Account created"))
|
rb.Notice(client.t("Account created"))
|
||||||
client.Send(nil, server.name, RPL_LOGGEDIN, client.nick, client.nickMaskString, account.Name, fmt.Sprintf(client.t("You are now logged in as %s"), account.Name))
|
rb.Add(nil, server.name, RPL_LOGGEDIN, client.nick, client.nickMaskString, account.Name, fmt.Sprintf(client.t("You are now logged in as %s"), account.Name))
|
||||||
client.Send(nil, server.name, RPL_SASLSUCCESS, client.nick, client.t("Authentication successful"))
|
rb.Add(nil, server.name, RPL_SASLSUCCESS, client.nick, client.t("Authentication successful"))
|
||||||
server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Account registered $c[grey][$r%s$c[grey]] by $c[grey][$r%s$c[grey]]"), account.Name, client.nickMaskString))
|
server.snomasks.Send(sno.LocalAccounts, fmt.Sprintf(ircfmt.Unescape("Account registered $c[grey][$r%s$c[grey]] by $c[grey][$r%s$c[grey]]"), account.Name, client.nickMaskString))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Notice(client.t("Account registration failed"))
|
rb.Notice(client.t("Account registration failed"))
|
||||||
removeFailedAccRegisterData(server.store, casefoldedAccount)
|
removeFailedAccRegisterData(server.store, casefoldedAccount)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *Server) nickservIdentifyHandler(client *Client, username, passphrase string) {
|
func (server *Server) nickservIdentifyHandler(client *Client, username, passphrase string, rb *ResponseBuffer) {
|
||||||
// fail out if we need to
|
// fail out if we need to
|
||||||
if !server.accountAuthenticationEnabled {
|
if !server.accountAuthenticationEnabled {
|
||||||
client.Notice(client.t("Login has been disabled"))
|
rb.Notice(client.t("Login has been disabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ func (server *Server) nickservIdentifyHandler(client *Client, username, passphra
|
|||||||
// keep it the same as in the ACC CREATE stage
|
// keep it the same as in the ACC CREATE stage
|
||||||
accountKey, err := CasefoldName(username)
|
accountKey, err := CasefoldName(username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
client.Notice(client.t("Could not login with your username/password"))
|
rb.Notice(client.t("Could not login with your username/password"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +259,7 @@ func (server *Server) nickservIdentifyHandler(client *Client, username, passphra
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
client.Notice(fmt.Sprintf(client.t("You're now logged in as %s"), accountName))
|
rb.Notice(fmt.Sprintf(client.t("You're now logged in as %s"), accountName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,10 +306,10 @@ func (server *Server) nickservIdentifyHandler(client *Client, username, passphra
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
client.Notice(fmt.Sprintf(client.t("You're now logged in as %s"), accountName))
|
rb.Notice(fmt.Sprintf(client.t("You're now logged in as %s"), accountName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Notice(client.t("Could not login with your TLS certificate or supplied username/password"))
|
rb.Notice(client.t("Could not login with your TLS certificate or supplied username/password"))
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ func (rb *ResponseBuffer) AddSplitMessageFromClient(msgid string, from *Client,
|
|||||||
func (rb *ResponseBuffer) Send() error {
|
func (rb *ResponseBuffer) Send() error {
|
||||||
// fall out if no messages to send
|
// fall out if no messages to send
|
||||||
if len(rb.messages) == 0 {
|
if len(rb.messages) == 0 {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// make batch and all if required
|
// make batch and all if required
|
||||||
@ -126,3 +126,8 @@ func (rb *ResponseBuffer) Send() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice sends the client the given notice from the server.
|
||||||
|
func (rb *ResponseBuffer) Notice(text string) {
|
||||||
|
rb.Add(nil, rb.target.server.name, "NOTICE", rb.target.nick, text)
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@ const (
|
|||||||
sceneNickMask = "=Scene=!%s@npc.fakeuser.invalid"
|
sceneNickMask = "=Scene=!%s@npc.fakeuser.invalid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sendRoleplayMessage(server *Server, client *Client, source string, targetString string, isAction bool, message string) {
|
func sendRoleplayMessage(server *Server, client *Client, source string, targetString string, isAction bool, message string, rb *ResponseBuffer) {
|
||||||
if isAction {
|
if isAction {
|
||||||
message = fmt.Sprintf("\x01ACTION %s (%s)\x01", message, client.nick)
|
message = fmt.Sprintf("\x01ACTION %s (%s)\x01", message, client.nick)
|
||||||
} else {
|
} else {
|
||||||
@ -26,17 +26,17 @@ func sendRoleplayMessage(server *Server, client *Client, source string, targetSt
|
|||||||
if cerr == nil {
|
if cerr == nil {
|
||||||
channel := server.channels.Get(target)
|
channel := server.channels.Get(target)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, client.t("No such channel"))
|
rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, client.t("No such channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !channel.CanSpeak(client) {
|
if !channel.CanSpeak(client) {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !channel.flags[modes.ChanRoleplaying] {
|
if !channel.flags[modes.ChanRoleplaying] {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDRP, channel.name, client.t("Channel doesn't have roleplaying mode available"))
|
rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, channel.name, client.t("Channel doesn't have roleplaying mode available"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,28 +44,32 @@ func sendRoleplayMessage(server *Server, client *Client, source string, targetSt
|
|||||||
if member == client && !client.capabilities.Has(caps.EchoMessage) {
|
if member == client && !client.capabilities.Has(caps.EchoMessage) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
member.Send(nil, source, "PRIVMSG", channel.name, message)
|
if member == client {
|
||||||
|
rb.Add(nil, source, "PRIVMSG", channel.name, message)
|
||||||
|
} else {
|
||||||
|
member.Send(nil, source, "PRIVMSG", channel.name, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target, err := CasefoldName(targetString)
|
target, err := CasefoldName(targetString)
|
||||||
user := server.clients.Get(target)
|
user := server.clients.Get(target)
|
||||||
if err != nil || user == nil {
|
if err != nil || user == nil {
|
||||||
client.Send(nil, server.name, ERR_NOSUCHNICK, client.nick, target, client.t("No such nick"))
|
rb.Add(nil, server.name, ERR_NOSUCHNICK, client.nick, target, client.t("No such nick"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !user.flags[modes.UserRoleplaying] {
|
if !user.flags[modes.UserRoleplaying] {
|
||||||
client.Send(nil, client.server.name, ERR_CANNOTSENDRP, user.nick, client.t("User doesn't have roleplaying mode enabled"))
|
rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, user.nick, client.t("User doesn't have roleplaying mode enabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Send(nil, source, "PRIVMSG", user.nick, message)
|
user.Send(nil, source, "PRIVMSG", user.nick, message)
|
||||||
if client.capabilities.Has(caps.EchoMessage) {
|
if client.capabilities.Has(caps.EchoMessage) {
|
||||||
client.Send(nil, source, "PRIVMSG", user.nick, message)
|
rb.Add(nil, source, "PRIVMSG", user.nick, message)
|
||||||
}
|
}
|
||||||
if user.flags[modes.Away] {
|
if user.flags[modes.Away] {
|
||||||
//TODO(dan): possibly implement cooldown of away notifications to users
|
//TODO(dan): possibly implement cooldown of away notifications to users
|
||||||
client.Send(nil, server.name, RPL_AWAY, user.nick, user.awayMessage)
|
rb.Add(nil, server.name, RPL_AWAY, user.nick, user.awayMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,8 +458,12 @@ func (server *Server) tryRegister(c *Client) {
|
|||||||
c.Send(nil, server.name, RPL_CREATED, c.nick, fmt.Sprintf(c.t("This server was created %s"), server.ctime.Format(time.RFC1123)))
|
c.Send(nil, server.name, RPL_CREATED, c.nick, fmt.Sprintf(c.t("This server was created %s"), server.ctime.Format(time.RFC1123)))
|
||||||
//TODO(dan): Look at adding last optional [<channel modes with a parameter>] parameter
|
//TODO(dan): Look at adding last optional [<channel modes with a parameter>] parameter
|
||||||
c.Send(nil, server.name, RPL_MYINFO, c.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
|
c.Send(nil, server.name, RPL_MYINFO, c.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
|
||||||
c.RplISupport()
|
|
||||||
server.MOTD(c)
|
rb := NewResponseBuffer(c)
|
||||||
|
c.RplISupport(rb)
|
||||||
|
server.MOTD(c, rb)
|
||||||
|
rb.Send()
|
||||||
|
|
||||||
c.Send(nil, c.nickMaskString, RPL_UMODEIS, c.nick, c.ModeString())
|
c.Send(nil, c.nickMaskString, RPL_UMODEIS, c.nick, c.ModeString())
|
||||||
if server.logger.IsLoggingRawIO() {
|
if server.logger.IsLoggingRawIO() {
|
||||||
c.Notice(c.t("This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
|
c.Notice(c.t("This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
|
||||||
@ -478,8 +482,10 @@ func (server *Server) tryRegister(c *Client) {
|
|||||||
} else {
|
} else {
|
||||||
c.Send(nil, c.nickMaskString, "JOIN", channel.name)
|
c.Send(nil, c.nickMaskString, "JOIN", channel.name)
|
||||||
}
|
}
|
||||||
channel.SendTopic(c)
|
// reuse the last rb
|
||||||
channel.Names(c)
|
channel.SendTopic(c, rb)
|
||||||
|
channel.Names(c, rb)
|
||||||
|
rb.Send()
|
||||||
|
|
||||||
// construct and send fake modestring if necessary
|
// construct and send fake modestring if necessary
|
||||||
c.stateMutex.RLock()
|
c.stateMutex.RLock()
|
||||||
@ -511,21 +517,21 @@ func (client *Client) t(originalString string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MOTD serves the Message of the Day.
|
// MOTD serves the Message of the Day.
|
||||||
func (server *Server) MOTD(client *Client) {
|
func (server *Server) MOTD(client *Client, rb *ResponseBuffer) {
|
||||||
server.configurableStateMutex.RLock()
|
server.configurableStateMutex.RLock()
|
||||||
motdLines := server.motdLines
|
motdLines := server.motdLines
|
||||||
server.configurableStateMutex.RUnlock()
|
server.configurableStateMutex.RUnlock()
|
||||||
|
|
||||||
if len(motdLines) < 1 {
|
if len(motdLines) < 1 {
|
||||||
client.Send(nil, server.name, ERR_NOMOTD, client.nick, client.t("MOTD File is missing"))
|
rb.Add(nil, server.name, ERR_NOMOTD, client.nick, client.t("MOTD File is missing"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Send(nil, server.name, RPL_MOTDSTART, client.nick, fmt.Sprintf(client.t("- %s Message of the day - "), server.name))
|
rb.Add(nil, server.name, RPL_MOTDSTART, client.nick, fmt.Sprintf(client.t("- %s Message of the day - "), server.name))
|
||||||
for _, line := range motdLines {
|
for _, line := range motdLines {
|
||||||
client.Send(nil, server.name, RPL_MOTD, client.nick, line)
|
rb.Add(nil, server.name, RPL_MOTD, client.nick, line)
|
||||||
}
|
}
|
||||||
client.Send(nil, server.name, RPL_ENDOFMOTD, client.nick, client.t("End of MOTD command"))
|
rb.Add(nil, server.name, RPL_ENDOFMOTD, client.nick, client.t("End of MOTD command"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// wordWrap wraps the given text into a series of lines that don't exceed lineWidth characters.
|
// wordWrap wraps the given text into a series of lines that don't exceed lineWidth characters.
|
||||||
@ -650,7 +656,7 @@ func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
|
|||||||
// rplWhoReply returns the WHO reply between one user and another channel/user.
|
// rplWhoReply returns the WHO reply between one user and another channel/user.
|
||||||
// <channel> <user> <host> <server> <nick> ( "H" / "G" ) ["*"] [ ( "@" / "+" ) ]
|
// <channel> <user> <host> <server> <nick> ( "H" / "G" ) ["*"] [ ( "@" / "+" ) ]
|
||||||
// :<hopcount> <real name>
|
// :<hopcount> <real name>
|
||||||
func (target *Client) rplWhoReply(channel *Channel, client *Client) {
|
func (target *Client) rplWhoReply(channel *Channel, client *Client, rb *ResponseBuffer) {
|
||||||
channelName := "*"
|
channelName := "*"
|
||||||
flags := ""
|
flags := ""
|
||||||
|
|
||||||
@ -667,13 +673,13 @@ func (target *Client) rplWhoReply(channel *Channel, client *Client) {
|
|||||||
flags += channel.ClientPrefixes(client, target.capabilities.Has(caps.MultiPrefix))
|
flags += channel.ClientPrefixes(client, target.capabilities.Has(caps.MultiPrefix))
|
||||||
channelName = channel.name
|
channelName = channel.name
|
||||||
}
|
}
|
||||||
target.Send(nil, target.server.name, RPL_WHOREPLY, target.nick, channelName, client.Username(), client.Hostname(), client.server.name, client.Nick(), flags, strconv.Itoa(client.hops)+" "+client.Realname())
|
rb.Add(nil, target.server.name, RPL_WHOREPLY, target.nick, channelName, client.Username(), client.Hostname(), client.server.name, client.Nick(), flags, strconv.Itoa(client.hops)+" "+client.Realname())
|
||||||
}
|
}
|
||||||
|
|
||||||
func whoChannel(client *Client, channel *Channel, friends ClientSet) {
|
func whoChannel(client *Client, channel *Channel, friends ClientSet, rb *ResponseBuffer) {
|
||||||
for _, member := range channel.Members() {
|
for _, member := range channel.Members() {
|
||||||
if !client.flags[modes.Invisible] || friends[client] {
|
if !client.flags[modes.Invisible] || friends[client] {
|
||||||
client.rplWhoReply(channel, member)
|
client.rplWhoReply(channel, member, rb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1140,7 +1146,7 @@ func (matcher *elistMatcher) Matches(channel *Channel) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RplList returns the RPL_LIST numeric for the given channel.
|
// RplList returns the RPL_LIST numeric for the given channel.
|
||||||
func (target *Client) RplList(channel *Channel) {
|
func (target *Client) RplList(channel *Channel, rb *ResponseBuffer) {
|
||||||
// get the correct number of channel members
|
// get the correct number of channel members
|
||||||
var memberCount int
|
var memberCount int
|
||||||
if target.flags[modes.Operator] || channel.hasClient(target) {
|
if target.flags[modes.Operator] || channel.hasClient(target) {
|
||||||
@ -1153,44 +1159,7 @@ func (target *Client) RplList(channel *Channel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target.Send(nil, target.server.name, RPL_LIST, target.nick, channel.name, strconv.Itoa(memberCount), channel.topic)
|
rb.Add(nil, target.server.name, RPL_LIST, target.nick, channel.name, strconv.Itoa(memberCount), channel.topic)
|
||||||
}
|
|
||||||
|
|
||||||
// NAMES [<channel>{,<channel>}]
|
|
||||||
func namesHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|
||||||
var channels []string
|
|
||||||
if len(msg.Params) > 0 {
|
|
||||||
channels = strings.Split(msg.Params[0], ",")
|
|
||||||
}
|
|
||||||
//var target string
|
|
||||||
//if len(msg.Params) > 1 {
|
|
||||||
// target = msg.Params[1]
|
|
||||||
//}
|
|
||||||
|
|
||||||
if len(channels) == 0 {
|
|
||||||
for _, channel := range server.channels.Channels() {
|
|
||||||
channel.Names(client)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// limit regular users to only listing one channel
|
|
||||||
if !client.flags[modes.Operator] {
|
|
||||||
channels = channels[:1]
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, chname := range channels {
|
|
||||||
casefoldedChname, err := CasefoldChannel(chname)
|
|
||||||
channel := server.channels.Get(casefoldedChname)
|
|
||||||
if err != nil || channel == nil {
|
|
||||||
if len(chname) > 0 {
|
|
||||||
client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, chname, client.t("No such channel"))
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
channel.Names(client)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResumeDetails are the details that we use to resume connections.
|
// ResumeDetails are the details that we use to resume connections.
|
||||||
|
Loading…
Reference in New Issue
Block a user