|
@@ -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()
|