added ISON and NOTIFY

This commit is contained in:
meera 2026-07-19 23:06:00 +03:00
parent f921f53669
commit 55d69d96c1

85
main.go
View File

@ -31,6 +31,7 @@ type Client struct {
conn net.Conn
host string
channels map[string]*Channel
monitorTargets map[string]bool
registered bool
saslRequired bool
saslComplete bool
@ -153,10 +154,11 @@ func handleConn(conn net.Conn) {
reader := bufio.NewReader(conn)
client := &Client{
conn: conn,
host: host,
channels: make(map[string]*Channel),
registered: false,
conn: conn,
host: host,
channels: make(map[string]*Channel),
monitorTargets: make(map[string]bool),
registered: false,
}
defer client.cleanup()
for {
@ -186,6 +188,10 @@ func handleConn(conn net.Conn) {
}
clients[newNick] = client
cliMu.Unlock()
if oldNick != "" {
notifyMonitorsOffline(oldNick)
}
notifyMonitorsOnline(newNick)
for _, ch := range client.channels {
ch.mu.Lock()
if oldNick != "" {
@ -461,6 +467,22 @@ func handleConn(conn net.Conn) {
} else {
fmt.Fprintf(client.conn, ":server 461 %s NAMES :Not enough parameters\r\n", client.nick)
}
case "ISON":
if len(msg.Params) < 1 {
client.fwrite(":server 461 %s ISON :Not enough parameters\r\n", client.nick)
continue
}
requested := msg.Params
var online []string
cliMu.RLock()
for _, nick := range requested {
if _, ok := clients[nick]; ok {
online = append(online, nick)
}
}
cliMu.RUnlock()
client.fwrite(":server 303 %s :%s\r\n", client.nick, strings.Join(online, " "))
// ircv3 stuff
case "CHATHISTORY":
if len(msg.Params) < 4 {
@ -475,6 +497,38 @@ func handleConn(conn net.Conn) {
continue
}
client.serveHistory(subcmd, target, count, msg.Params)
case "MONITOR":
if len(msg.Params) < 1 {
client.fwrite(":server 461 %s MONITOR :Not enough parameters\r\n", client.nick)
continue
}
subcmd := strings.ToUpper(msg.Params[0])
switch subcmd {
case "+":
for _, nick := range msg.Params[1:] {
client.monitorTargets[nick] = true
cliMu.RLock()
if _, ok := clients[nick]; ok {
client.fwrite(":server 730 %s %s :is online\r\n", client.nick, nick)
}
cliMu.RUnlock()
}
case "-":
for _, nick := range msg.Params[1:] {
delete(client.monitorTargets, nick)
}
case "C":
client.monitorTargets = make(map[string]bool)
case "L":
var nicks []string
for nick := range client.monitorTargets {
nicks = append(nicks, nick)
}
client.fwrite(":server 732 %s :%s\r\n", client.nick, strings.Join(nicks, " "))
client.fwrite(":server 733 %s :End of MONITOR list\r\n", client.nick)
default:
client.fwrite(":server 461 %s MONITOR :Invalid subcommand\r\n", client.nick)
}
default:
if client.nick != "" {
fmt.Fprintf(conn, ":server 421 %s %s :Unknown command or command is not implemented\r\n", client.nick, msg.Command)
@ -884,6 +938,7 @@ func (c *Client) checkRegistration() {
return
}
c.registered = true
notifyMonitorsOnline(c.nick)
c.fwrite(":server 001 %s :Welcome to Gocirc, %s!\r\n", c.nick, c.nick)
c.fwrite(":server 002 %s :Your host is server\r\n", c.nick)
c.fwrite(":server 003 %s :This server has %d users right now\r\n", c.nick, len(clients))
@ -1010,6 +1065,7 @@ func (c *Client) cleanup() {
cliMu.Lock()
delete(clients, c.nick)
cliMu.Unlock()
notifyMonitorsOffline(c.nick)
for name, ch := range c.channels {
ch.mu.Lock()
delete(ch.members, c.nick)
@ -1139,3 +1195,24 @@ func scanRows(rows *sql.Rows, channel string) []HistoryMessage {
}
return msgs
}
// IRC MONITOR command stuff
func notifyMonitorsOnline(nick string) {
cliMu.RLock()
defer cliMu.RUnlock()
for _, c := range clients {
if c.monitorTargets[nick] {
c.fwrite(":server 730 %s %s :is online\r\n", c.nick, nick)
}
}
}
func notifyMonitorsOffline(nick string) {
cliMu.RLock()
defer cliMu.RUnlock()
for _, c := range clients {
if c.monitorTargets[nick] {
c.fwrite(":server 731 %s %s :is offline\r\n", c.nick, nick)
}
}
}