mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-13 07:29:30 +01:00
commit
dc87ae7ef1
@ -275,6 +275,7 @@ func (server *Server) RunClient(conn clientConn) {
|
|||||||
client.rawHostname = session.rawHostname
|
client.rawHostname = session.rawHostname
|
||||||
client.proxiedIP = session.proxiedIP
|
client.proxiedIP = session.proxiedIP
|
||||||
|
|
||||||
|
server.stats.Add()
|
||||||
client.run(session)
|
client.run(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,6 +360,15 @@ func (client *Client) IPString() string {
|
|||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// t returns the translated version of the given string, based on the languages configured by the client.
|
||||||
|
func (client *Client) t(originalString string) string {
|
||||||
|
languageManager := client.server.Config().languageManager
|
||||||
|
if !languageManager.Enabled() {
|
||||||
|
return originalString
|
||||||
|
}
|
||||||
|
return languageManager.Translate(client.Languages(), originalString)
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// command goroutine
|
// command goroutine
|
||||||
//
|
//
|
||||||
@ -922,21 +932,6 @@ func (client *Client) LoggedIntoAccount() bool {
|
|||||||
return client.Account() != ""
|
return client.Account() != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
|
|
||||||
func (client *Client) RplISupport(rb *ResponseBuffer) {
|
|
||||||
translatedISupport := client.t("are supported by this server")
|
|
||||||
nick := client.Nick()
|
|
||||||
config := client.server.Config()
|
|
||||||
for _, cachedTokenLine := range config.Server.isupport.CachedReply {
|
|
||||||
length := len(cachedTokenLine) + 2
|
|
||||||
tokenline := make([]string, length)
|
|
||||||
tokenline[0] = nick
|
|
||||||
copy(tokenline[1:], cachedTokenLine)
|
|
||||||
tokenline[length-1] = translatedISupport
|
|
||||||
rb.Add(nil, client.server.name, RPL_ISUPPORT, tokenline...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quit sets the given quit message for the client.
|
// Quit sets the given quit message for the client.
|
||||||
// (You must ensure separately that destroy() is called, e.g., by returning `true` from
|
// (You must ensure separately that destroy() is called, e.g., by returning `true` from
|
||||||
// the command handler or calling it yourself.)
|
// the command handler or calling it yourself.)
|
||||||
@ -1095,16 +1090,8 @@ func (client *Client) destroy(session *Session) {
|
|||||||
|
|
||||||
client.server.accounts.Logout(client)
|
client.server.accounts.Logout(client)
|
||||||
|
|
||||||
// send quit messages to friends
|
client.server.stats.Remove(registered, client.HasMode(modes.Invisible),
|
||||||
if registered {
|
client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator))
|
||||||
client.server.stats.ChangeTotal(-1)
|
|
||||||
}
|
|
||||||
if client.HasMode(modes.Invisible) {
|
|
||||||
client.server.stats.ChangeInvisible(-1)
|
|
||||||
}
|
|
||||||
if client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator) {
|
|
||||||
client.server.stats.ChangeOperators(-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// this happens under failure to return from BRB
|
// this happens under failure to return from BRB
|
||||||
if quitMessage == "" {
|
if quitMessage == "" {
|
||||||
|
@ -1638,14 +1638,7 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
|
|
||||||
// LUSERS [<mask> [<server>]]
|
// LUSERS [<mask> [<server>]]
|
||||||
func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
//TODO(vegax87) Fix network statistics and additional parameters
|
server.Lusers(client, rb)
|
||||||
totalCount, invisibleCount, operCount := server.stats.GetStats()
|
|
||||||
|
|
||||||
rb.Add(nil, server.name, RPL_LUSERCLIENT, client.nick, fmt.Sprintf(client.t("There are %[1]d users and %[2]d invisible on %[3]d server(s)"), totalCount-invisibleCount, invisibleCount, 1))
|
|
||||||
rb.Add(nil, server.name, RPL_LUSEROP, client.nick, strconv.Itoa(operCount), client.t("IRC Operators online"))
|
|
||||||
rb.Add(nil, server.name, RPL_LUSERCHANNELS, client.nick, strconv.Itoa(server.channels.Len()), client.t("channels formed"))
|
|
||||||
rb.Add(nil, server.name, RPL_LUSERME, client.nick, fmt.Sprintf(client.t("I have %[1]d clients and %[2]d servers"), totalCount, 1))
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2583,7 +2576,7 @@ func userhostHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *
|
|||||||
// VERSION
|
// VERSION
|
||||||
func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
rb.Add(nil, server.name, RPL_VERSION, client.nick, Ver, server.name)
|
rb.Add(nil, server.name, RPL_VERSION, client.nick, Ver, server.name)
|
||||||
client.RplISupport(rb)
|
server.RplISupport(client, rb)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +164,11 @@ func (lm *Manager) Count() int {
|
|||||||
return len(lm.Languages)
|
return len(lm.Languages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enabled returns whether translation is enabled.
|
||||||
|
func (lm *Manager) Enabled() bool {
|
||||||
|
return len(lm.translations) != 0
|
||||||
|
}
|
||||||
|
|
||||||
// Translators returns the languages we have and the translators.
|
// Translators returns the languages we have and the translators.
|
||||||
func (lm *Manager) Translators() []string {
|
func (lm *Manager) Translators() []string {
|
||||||
var tlist sort.StringSlice
|
var tlist sort.StringSlice
|
||||||
|
@ -50,6 +50,8 @@ const (
|
|||||||
RPL_TRACELOG = "261"
|
RPL_TRACELOG = "261"
|
||||||
RPL_TRACEEND = "262"
|
RPL_TRACEEND = "262"
|
||||||
RPL_TRYAGAIN = "263"
|
RPL_TRYAGAIN = "263"
|
||||||
|
RPL_LOCALUSERS = "265"
|
||||||
|
RPL_GLOBALUSERS = "266"
|
||||||
RPL_WHOISCERTFP = "276"
|
RPL_WHOISCERTFP = "276"
|
||||||
RPL_AWAY = "301"
|
RPL_AWAY = "301"
|
||||||
RPL_USERHOST = "302"
|
RPL_USERHOST = "302"
|
||||||
|
@ -386,7 +386,7 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
|
|||||||
c.SetRegistered()
|
c.SetRegistered()
|
||||||
|
|
||||||
// count new user in statistics
|
// count new user in statistics
|
||||||
server.stats.ChangeTotal(1)
|
server.stats.Register()
|
||||||
server.monitorManager.AlertAbout(c, true)
|
server.monitorManager.AlertAbout(c, true)
|
||||||
|
|
||||||
server.playRegistrationBurst(session)
|
server.playRegistrationBurst(session)
|
||||||
@ -410,7 +410,8 @@ func (server *Server) playRegistrationBurst(session *Session) {
|
|||||||
session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
|
session.Send(nil, server.name, RPL_MYINFO, d.nick, server.name, Ver, supportedUserModesString, supportedChannelModesString)
|
||||||
|
|
||||||
rb := NewResponseBuffer(session)
|
rb := NewResponseBuffer(session)
|
||||||
c.RplISupport(rb)
|
server.RplISupport(c, rb)
|
||||||
|
server.Lusers(c, rb)
|
||||||
server.MOTD(c, rb)
|
server.MOTD(c, rb)
|
||||||
rb.Send(true)
|
rb.Send(true)
|
||||||
|
|
||||||
@ -426,11 +427,34 @@ func (server *Server) playRegistrationBurst(session *Session) {
|
|||||||
session.client.nickTimer.Touch(nil)
|
session.client.nickTimer.Touch(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// t returns the translated version of the given string, based on the languages configured by the client.
|
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
|
||||||
func (client *Client) t(originalString string) string {
|
func (server *Server) RplISupport(client *Client, rb *ResponseBuffer) {
|
||||||
// TODO(slingamn) investigate a fast path for this, using an atomic load to see if translation is disabled
|
translatedISupport := client.t("are supported by this server")
|
||||||
languages := client.Languages()
|
nick := client.Nick()
|
||||||
return client.server.Languages().Translate(languages, originalString)
|
config := server.Config()
|
||||||
|
for _, cachedTokenLine := range config.Server.isupport.CachedReply {
|
||||||
|
length := len(cachedTokenLine) + 2
|
||||||
|
tokenline := make([]string, length)
|
||||||
|
tokenline[0] = nick
|
||||||
|
copy(tokenline[1:], cachedTokenLine)
|
||||||
|
tokenline[length-1] = translatedISupport
|
||||||
|
rb.Add(nil, server.name, RPL_ISUPPORT, tokenline...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) Lusers(client *Client, rb *ResponseBuffer) {
|
||||||
|
nick := client.Nick()
|
||||||
|
stats := server.stats.GetValues()
|
||||||
|
|
||||||
|
rb.Add(nil, server.name, RPL_LUSERCLIENT, nick, fmt.Sprintf(client.t("There are %[1]d users and %[2]d invisible on %[3]d server(s)"), stats.Total-stats.Invisible, stats.Invisible, 1))
|
||||||
|
rb.Add(nil, server.name, RPL_LUSEROP, nick, strconv.Itoa(stats.Operators), client.t("IRC Operators online"))
|
||||||
|
rb.Add(nil, server.name, RPL_LUSERUNKNOWN, nick, strconv.Itoa(stats.Unknown), client.t("unregistered connections"))
|
||||||
|
rb.Add(nil, server.name, RPL_LUSERCHANNELS, nick, strconv.Itoa(server.channels.Len()), client.t("channels formed"))
|
||||||
|
rb.Add(nil, server.name, RPL_LUSERME, nick, fmt.Sprintf(client.t("I have %[1]d clients and %[2]d servers"), stats.Total, 1))
|
||||||
|
total := strconv.Itoa(stats.Total)
|
||||||
|
max := strconv.Itoa(stats.Max)
|
||||||
|
rb.Add(nil, server.name, RPL_LOCALUSERS, nick, total, max, fmt.Sprintf(client.t("Current local users %[1]s, max %[2]s"), total, max))
|
||||||
|
rb.Add(nil, server.name, RPL_GLOBALUSERS, nick, total, max, fmt.Sprintf(client.t("Current global users %[1]s, max %[2]s"), total, max))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MOTD serves the Message of the Day.
|
// MOTD serves the Message of the Day.
|
||||||
|
83
irc/stats.go
83
irc/stats.go
@ -4,43 +4,74 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Stats contains the numbers of total, invisible and operators on the server
|
type StatsValues struct {
|
||||||
type Stats struct {
|
Unknown int // unregistered clients
|
||||||
sync.RWMutex
|
Total int // registered clients, including invisible
|
||||||
|
Max int // high-water mark of registered clients
|
||||||
Total int
|
|
||||||
Invisible int
|
Invisible int
|
||||||
Operators int
|
Operators int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeTotal increments the total user count on server
|
// Stats tracks statistics for a running server
|
||||||
func (s *Stats) ChangeTotal(i int) {
|
type Stats struct {
|
||||||
s.Lock()
|
StatsValues
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.Total += i
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeInvisible increments the invisible count
|
// Adds an unregistered client
|
||||||
func (s *Stats) ChangeInvisible(i int) {
|
func (s *Stats) Add() {
|
||||||
s.Lock()
|
s.mutex.Lock()
|
||||||
defer s.Unlock()
|
s.Unknown += 1
|
||||||
|
s.mutex.Unlock()
|
||||||
s.Invisible += i
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeOperators increases the operator count
|
// Transition a client from unregistered to registered
|
||||||
func (s *Stats) ChangeOperators(i int) {
|
func (s *Stats) Register() {
|
||||||
s.Lock()
|
s.mutex.Lock()
|
||||||
defer s.Unlock()
|
s.Unknown -= 1
|
||||||
|
s.Total += 1
|
||||||
|
if s.Max < s.Total {
|
||||||
|
s.Max = s.Total
|
||||||
|
}
|
||||||
|
s.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
s.Operators += i
|
// Modify the Invisible count
|
||||||
|
func (s *Stats) ChangeInvisible(increment int) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
s.Invisible += increment
|
||||||
|
s.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify the Operator count
|
||||||
|
func (s *Stats) ChangeOperators(increment int) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
s.Operators += increment
|
||||||
|
s.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a user from the server
|
||||||
|
func (s *Stats) Remove(registered, invisible, operator bool) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
if registered {
|
||||||
|
s.Total -= 1
|
||||||
|
} else {
|
||||||
|
s.Unknown -= 1
|
||||||
|
}
|
||||||
|
if invisible {
|
||||||
|
s.Invisible -= 1
|
||||||
|
}
|
||||||
|
if operator {
|
||||||
|
s.Operators -= 1
|
||||||
|
}
|
||||||
|
s.mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStats retrives total, invisible and oper count
|
// GetStats retrives total, invisible and oper count
|
||||||
func (s *Stats) GetStats() (int, int, int) {
|
func (s *Stats) GetValues() (result StatsValues) {
|
||||||
s.Lock()
|
s.mutex.Lock()
|
||||||
defer s.Unlock()
|
result = s.StatsValues
|
||||||
|
s.mutex.Unlock()
|
||||||
return s.Total, s.Invisible, s.Operators
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user