Browse Source

LIST: Start implementing ELIST conditions

tags/v0.8.1
Daniel Oaks 7 years ago
parent
commit
8a6ba6f9cc
1 changed files with 71 additions and 14 deletions
  1. 71
    14
      irc/server.go

+ 71
- 14
irc/server.go View File

@@ -352,6 +352,7 @@ func (server *Server) setISupport() {
352 352
 	server.isupport.Add("CHANMODES", strings.Join([]string{Modes{BanMask, ExceptMask, InviteMask}.String(), "", Modes{UserLimit, Key}.String(), Modes{InviteOnly, Moderated, NoOutside, OpOnlyTopic, ChanRoleplaying, Secret}.String()}, ","))
353 353
 	server.isupport.Add("CHANNELLEN", strconv.Itoa(server.limits.ChannelLen))
354 354
 	server.isupport.Add("CHANTYPES", "#")
355
+	server.isupport.Add("ELIST", "U")
355 356
 	server.isupport.Add("EXCEPTS", "")
356 357
 	server.isupport.Add("INVEX", "")
357 358
 	server.isupport.Add("KICKLEN", strconv.Itoa(server.limits.KickLen))
@@ -1885,22 +1886,73 @@ func kickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1885 1886
 	return false
1886 1887
 }
1887 1888
 
1888
-// LIST [<channel>{,<channel>} [<server>]]
1889
+// elistMatcher takes and matches ELIST conditions
1890
+type elistMatcher struct {
1891
+	MinClientsActive bool
1892
+	MinClients       int
1893
+	MaxClientsActive bool
1894
+	MaxClients       int
1895
+}
1896
+
1897
+// Matches checks whether the given channel matches our matches.
1898
+func (matcher *elistMatcher) Matches(channel *Channel) bool {
1899
+	channel.membersMutex.RLock()
1900
+	defer channel.membersMutex.RUnlock()
1901
+
1902
+	if matcher.MinClientsActive {
1903
+		if len(channel.members) < matcher.MinClients {
1904
+			return false
1905
+		}
1906
+	}
1907
+
1908
+	if matcher.MaxClientsActive {
1909
+		if matcher.MaxClients < len(channel.members) {
1910
+			return false
1911
+		}
1912
+	}
1913
+
1914
+	return true
1915
+}
1916
+
1917
+// LIST [<channel>{,<channel>}] [<elistcond>{,<elistcond>}]
1889 1918
 func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1919
+	// get channels
1890 1920
 	var channels []string
1891
-	if len(msg.Params) > 0 {
1892
-		channels = strings.Split(msg.Params[0], ",")
1893
-	}
1894
-	var target string
1895
-	if len(msg.Params) > 1 {
1896
-		target = msg.Params[1]
1921
+	for _, param := range msg.Params {
1922
+		if 0 < len(param) && param[0] == '#' {
1923
+			for _, channame := range strings.Split(param, ",") {
1924
+				if 0 < len(channame) && channame[0] == '#' {
1925
+					channels = append(channels, channame)
1926
+				}
1927
+			}
1928
+		}
1897 1929
 	}
1898 1930
 
1899
-	//TODO(dan): target server when we have multiple servers
1900
-	//TODO(dan): we should continue just fine if it's this current server though
1901
-	if target != "" {
1902
-		client.Send(nil, server.name, ERR_NOSUCHSERVER, client.nick, target, "No such server")
1903
-		return false
1931
+	// get elist conditions
1932
+	var matcher elistMatcher
1933
+	for _, param := range msg.Params {
1934
+		if len(param) < 1 {
1935
+			continue
1936
+		}
1937
+
1938
+		if param[0] == '<' {
1939
+			param = param[1:]
1940
+			val, err := strconv.Atoi(param)
1941
+			if err != nil {
1942
+				continue
1943
+			}
1944
+			matcher.MaxClientsActive = true
1945
+			matcher.MaxClients = val - 1 // -1 because < means less than the given number
1946
+		}
1947
+		if param[0] == '>' {
1948
+			param = param[1:]
1949
+			val, err := strconv.Atoi(param)
1950
+			if err != nil {
1951
+				continue
1952
+			}
1953
+			matcher.MinClientsActive = true
1954
+			matcher.MinClients = val + 1 // +1 because > means more than the given number
1955
+		}
1904 1956
 	}
1905 1957
 
1906 1958
 	if len(channels) == 0 {
@@ -1909,7 +1961,9 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1909 1961
 			if !client.flags[Operator] && channel.flags[Secret] {
1910 1962
 				continue
1911 1963
 			}
1912
-			client.RplList(channel)
1964
+			if matcher.Matches(channel) {
1965
+				client.RplList(channel)
1966
+			}
1913 1967
 		}
1914 1968
 		server.channels.ChansLock.RUnlock()
1915 1969
 	} else {
@@ -1927,13 +1981,16 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1927 1981
 				}
1928 1982
 				continue
1929 1983
 			}
1930
-			client.RplList(channel)
1984
+			if matcher.Matches(channel) {
1985
+				client.RplList(channel)
1986
+			}
1931 1987
 		}
1932 1988
 	}
1933 1989
 	client.Send(nil, server.name, RPL_LISTEND, client.nick, "End of LIST")
1934 1990
 	return false
1935 1991
 }
1936 1992
 
1993
+// RplList returns the RPL_LIST numeric for the given channel.
1937 1994
 func (target *Client) RplList(channel *Channel) {
1938 1995
 	channel.membersMutex.RLock()
1939 1996
 	defer channel.membersMutex.RUnlock()

Loading…
Cancel
Save