major: fixed bug in joinchannel, added INVITE command
This commit is contained in:
parent
0898143876
commit
c859f99b1e
5
go.mod
5
go.mod
@ -2,4 +2,7 @@ module ircserve
|
||||
|
||||
go 1.26.3
|
||||
|
||||
require github.com/ergochat/irc-go v0.6.0
|
||||
require (
|
||||
github.com/ergochat/irc-go v0.6.0
|
||||
github.com/mattn/go-sqlite3 v1.14.48
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@ -1,2 +1,4 @@
|
||||
github.com/ergochat/irc-go v0.6.0 h1:Y0AGV76aeihJfCtLaQh+OyJKFiKGrYC0VTkeMZ6XW28=
|
||||
github.com/ergochat/irc-go v0.6.0/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0=
|
||||
github.com/mattn/go-sqlite3 v1.14.48 h1:7XHIgl0a8HwOaiK4E47ozLkST78rR9+OtNGx27D/TFs=
|
||||
github.com/mattn/go-sqlite3 v1.14.48/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
|
||||
|
||||
112
main.go
112
main.go
@ -171,19 +171,25 @@ func handleConn(conn net.Conn) {
|
||||
client.fwrite(":server 433 * %s :Nickname is already in use\r\n", newNick)
|
||||
} else {
|
||||
oldNick := client.nick
|
||||
client.nick = newNick
|
||||
|
||||
cliMu.Lock()
|
||||
if oldNick != "" {
|
||||
// nick change
|
||||
cliMu.Lock()
|
||||
delete(clients, oldNick)
|
||||
clients[newNick] = client
|
||||
cliMu.Unlock()
|
||||
for _, ch := range client.channels {
|
||||
ch.mu.Lock()
|
||||
}
|
||||
clients[newNick] = client
|
||||
cliMu.Unlock()
|
||||
for _, ch := range client.channels {
|
||||
ch.mu.Lock()
|
||||
if oldNick != "" {
|
||||
delete(ch.members, oldNick)
|
||||
ch.members[newNick] = client
|
||||
ch.mu.Unlock()
|
||||
} else {
|
||||
delete(ch.members, "")
|
||||
}
|
||||
client.nick = newNick
|
||||
ch.members[newNick] = client
|
||||
ch.mu.Unlock()
|
||||
}
|
||||
if oldNick != "" {
|
||||
for _, ch := range client.channels {
|
||||
broadcastNames(ch)
|
||||
}
|
||||
@ -192,15 +198,12 @@ func handleConn(conn net.Conn) {
|
||||
other.fwrite(":%s NICK %s\r\n", oldNick, newNick)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client.nick = newNick
|
||||
cliMu.Lock()
|
||||
clients[newNick] = client
|
||||
cliMu.Unlock()
|
||||
}
|
||||
|
||||
client.checkRegistration()
|
||||
}
|
||||
}
|
||||
|
||||
case "CAP":
|
||||
if len(msg.Params) < 1 {
|
||||
client.fwrite(":server 461 %s CAP :Not enough parameters\r\n", client.nick)
|
||||
@ -210,7 +213,7 @@ func handleConn(conn net.Conn) {
|
||||
switch subcmd {
|
||||
case "LS":
|
||||
// explicitly tell we only support PLAIN SASL, as well as chathistory
|
||||
client.fwrite(":server CAP * LS :sasl=PLAIN chathistory\r\n")
|
||||
client.fwrite(":server CAP * LS :sasl=PLAIN sasl chathistory\r\n")
|
||||
|
||||
case "REQ":
|
||||
if len(msg.Params) >= 2 && strings.Contains(strings.ToLower(msg.Params[1]), "sasl") {
|
||||
@ -335,6 +338,44 @@ func handleConn(conn net.Conn) {
|
||||
text := msg.Params[1]
|
||||
sendNotice(client, target, text)
|
||||
}
|
||||
case "INVITE":
|
||||
if !client.registered {
|
||||
client.sendUnregisteredNotice()
|
||||
continue
|
||||
}
|
||||
if len(msg.Params) < 2 {
|
||||
client.fwrite(":server 461 %s INVITE :Not enough parameters\r\n", client.nick)
|
||||
continue
|
||||
}
|
||||
targetNick := msg.Params[0]
|
||||
channelName := normalizeChannelName(msg.Params[1])
|
||||
|
||||
cliMu.RLock()
|
||||
target, ok := clients[targetNick]
|
||||
cliMu.RUnlock()
|
||||
if !ok {
|
||||
client.fwrite(":server 401 %s %s :No such nick\r\n", client.nick, targetNick)
|
||||
continue
|
||||
}
|
||||
|
||||
chMu.Lock()
|
||||
ch, ok := channels[channelName]
|
||||
chMu.Unlock()
|
||||
if !ok {
|
||||
client.fwrite(":server 403 %s %s :No such channel\r\n", client.nick, channelName)
|
||||
continue
|
||||
}
|
||||
|
||||
ch.mu.RLock()
|
||||
_, inChannel := ch.members[client.nick]
|
||||
ch.mu.RUnlock()
|
||||
if !inChannel {
|
||||
client.fwrite(":server 442 %s %s :You're not on that channel\r\n", client.nick, channelName)
|
||||
continue
|
||||
}
|
||||
client.fwrite(":server 341 %s %s %s\r\n", client.nick, targetNick, channelName)
|
||||
target.fwrite(":%s INVITE %s :%s\r\n", client.nick, targetNick, channelName)
|
||||
|
||||
case "QUIT":
|
||||
if !client.registered {
|
||||
client.sendUnregisteredNotice()
|
||||
@ -394,6 +435,7 @@ func handleConn(conn net.Conn) {
|
||||
} else {
|
||||
fmt.Fprintf(client.conn, ":server 461 %s NAMES :Not enough parameters\r\n", client.nick)
|
||||
}
|
||||
// ircv3 stuff
|
||||
case "CHATHISTORY":
|
||||
if len(msg.Params) < 3 {
|
||||
client.fwrite(":server 461 %s CHATHISTORY :Not enough parameters\r\n", client.nick)
|
||||
@ -624,9 +666,10 @@ func handleMode(sender *Client, channelName, mode, targetNick string) {
|
||||
sender.fwrite(":server 501 %s :Unknown MODE flag\r\n", sender.nick)
|
||||
}
|
||||
}
|
||||
|
||||
func joinChannel(c *Client, name string) {
|
||||
name = normalizeChannelName(name)
|
||||
|
||||
// get or create channel
|
||||
chMu.Lock()
|
||||
ch, ok := channels[name]
|
||||
if !ok {
|
||||
@ -634,13 +677,9 @@ func joinChannel(c *Client, name string) {
|
||||
name: name,
|
||||
members: make(map[string]*Client),
|
||||
ops: make(map[string]bool),
|
||||
history: nil,
|
||||
description: "none",
|
||||
}
|
||||
channels[name] = ch
|
||||
if globalOps[c.nick] {
|
||||
ch.ops[c.nick] = true
|
||||
}
|
||||
}
|
||||
if globalOps[c.nick] {
|
||||
ch.ops[c.nick] = true
|
||||
@ -648,20 +687,47 @@ func joinChannel(c *Client, name string) {
|
||||
chMu.Unlock()
|
||||
|
||||
ch.mu.Lock()
|
||||
// reject duplicate join
|
||||
if _, exists := ch.members[c.nick]; exists {
|
||||
ch.mu.Unlock()
|
||||
c.fwrite(":server 443 %s %s %s :is already on channel\r\n",
|
||||
c.nick, c.nick, name)
|
||||
return
|
||||
}
|
||||
// clean up stale empty nick
|
||||
delete(ch.members, "")
|
||||
// add new member
|
||||
ch.members[c.nick] = c
|
||||
c.channels[name] = ch
|
||||
ch.mu.Unlock()
|
||||
|
||||
// echo JOIN to client
|
||||
fmt.Fprintf(c.conn, ":%s JOIN %s\r\n", c.nick, name)
|
||||
// broadcast JOIN to others
|
||||
for _, member := range ch.members {
|
||||
fmt.Fprintf(member.conn, ":%s JOIN %s\r\n", c.nick, name)
|
||||
if member != c {
|
||||
fmt.Fprintf(member.conn, ":%s JOIN %s\r\n", c.nick, name)
|
||||
}
|
||||
}
|
||||
|
||||
// topic
|
||||
if ch.description != "" {
|
||||
c.fwrite(":server 332 %s %s :%s\r\n", c.nick, name, ch.description)
|
||||
} else {
|
||||
c.fwrite(":server 331 %s %s :No topic is set\r\n", c.nick, name)
|
||||
}
|
||||
|
||||
// names list
|
||||
c.sendNames(ch)
|
||||
|
||||
// MODE if op
|
||||
if ch.ops[c.nick] {
|
||||
for _, member := range ch.members {
|
||||
member.fwrite(":server MODE %s +o %s\r\n", name, c.nick)
|
||||
}
|
||||
}
|
||||
c.sendNames(ch)
|
||||
}
|
||||
|
||||
func (c *Client) partChannel(name string) {
|
||||
chMu.Lock()
|
||||
ch, ok := channels[name]
|
||||
@ -809,7 +875,7 @@ func storeMessage(ch *Channel, sender *Client, target, text string) {
|
||||
msg := HistoryMessage{
|
||||
MsgID: fmt.Sprintf("%d", time.Now().UnixNano()),
|
||||
Time: time.Now(),
|
||||
Prefix: fmt.Sprintf("%s!%s@%s", sender.nick, sender.user, sender.host),
|
||||
Prefix: fmt.Sprintf("%s!%s@%s", sender.nick, sender.user, "host"), // for privacy reasons
|
||||
Command: "PRIVMSG",
|
||||
Params: []string{target},
|
||||
Text: text,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user