mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-22 18:52:41 +01:00
commit
dc87ae7ef1
@ -275,6 +275,7 @@ func (server *Server) RunClient(conn clientConn) {
|
||||
client.rawHostname = session.rawHostname
|
||||
client.proxiedIP = session.proxiedIP
|
||||
|
||||
server.stats.Add()
|
||||
client.run(session)
|
||||
}
|
||||
|
||||
@ -359,6 +360,15 @@ func (client *Client) IPString() string {
|
||||
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
|
||||
//
|
||||
@ -922,21 +932,6 @@ func (client *Client) LoggedIntoAccount() bool {
|
||||
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.
|
||||
// (You must ensure separately that destroy() is called, e.g., by returning `true` from
|
||||
// the command handler or calling it yourself.)
|
||||
@ -1095,16 +1090,8 @@ func (client *Client) destroy(session *Session) {
|
||||
|
||||
client.server.accounts.Logout(client)
|
||||
|
||||
// send quit messages to friends
|
||||
if registered {
|
||||
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)
|
||||
}
|
||||
client.server.stats.Remove(registered, client.HasMode(modes.Invisible),
|
||||
client.HasMode(modes.Operator) || client.HasMode(modes.LocalOperator))
|
||||
|
||||
// this happens under failure to return from BRB
|
||||
if quitMessage == "" {
|
||||
|
@ -1638,14 +1638,7 @@ func listHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
||||
|
||||
// LUSERS [<mask> [<server>]]
|
||||
func lusersHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||
//TODO(vegax87) Fix network statistics and additional parameters
|
||||
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))
|
||||
|
||||
server.Lusers(client, rb)
|
||||
return false
|
||||
}
|
||||
|
||||
@ -2583,7 +2576,7 @@ func userhostHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *
|
||||
// VERSION
|
||||
func versionHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||
rb.Add(nil, server.name, RPL_VERSION, client.nick, Ver, server.name)
|
||||
client.RplISupport(rb)
|
||||
server.RplISupport(client, rb)
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,11 @@ func (lm *Manager) Count() int {
|
||||
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.
|
||||
func (lm *Manager) Translators() []string {
|
||||
var tlist sort.StringSlice
|
||||
|
@ -50,6 +50,8 @@ const (
|
||||
RPL_TRACELOG = "261"
|
||||
RPL_TRACEEND = "262"
|
||||
RPL_TRYAGAIN = "263"
|
||||
RPL_LOCALUSERS = "265"
|
||||
RPL_GLOBALUSERS = "266"
|
||||
RPL_WHOISCERTFP = "276"
|
||||
RPL_AWAY = "301"
|
||||
RPL_USERHOST = "302"
|
||||
|
@ -386,7 +386,7 @@ func (server *Server) tryRegister(c *Client, session *Session) (exiting bool) {
|
||||
c.SetRegistered()
|
||||
|
||||
// count new user in statistics
|
||||
server.stats.ChangeTotal(1)
|
||||
server.stats.Register()
|
||||
server.monitorManager.AlertAbout(c, true)
|
||||
|
||||
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)
|
||||
|
||||
rb := NewResponseBuffer(session)
|
||||
c.RplISupport(rb)
|
||||
server.RplISupport(c, rb)
|
||||
server.Lusers(c, rb)
|
||||
server.MOTD(c, rb)
|
||||
rb.Send(true)
|
||||
|
||||
@ -426,11 +427,34 @@ func (server *Server) playRegistrationBurst(session *Session) {
|
||||
session.client.nickTimer.Touch(nil)
|
||||
}
|
||||
|
||||
// t returns the translated version of the given string, based on the languages configured by the client.
|
||||
func (client *Client) t(originalString string) string {
|
||||
// TODO(slingamn) investigate a fast path for this, using an atomic load to see if translation is disabled
|
||||
languages := client.Languages()
|
||||
return client.server.Languages().Translate(languages, originalString)
|
||||
// RplISupport outputs our ISUPPORT lines to the client. This is used on connection and in VERSION responses.
|
||||
func (server *Server) RplISupport(client *Client, rb *ResponseBuffer) {
|
||||
translatedISupport := client.t("are supported by this server")
|
||||
nick := client.Nick()
|
||||
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.
|
||||
|
83
irc/stats.go
83
irc/stats.go
@ -4,43 +4,74 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Stats contains the numbers of total, invisible and operators on the server
|
||||
type Stats struct {
|
||||
sync.RWMutex
|
||||
|
||||
Total int
|
||||
type StatsValues struct {
|
||||
Unknown int // unregistered clients
|
||||
Total int // registered clients, including invisible
|
||||
Max int // high-water mark of registered clients
|
||||
Invisible int
|
||||
Operators int
|
||||
}
|
||||
|
||||
// ChangeTotal increments the total user count on server
|
||||
func (s *Stats) ChangeTotal(i int) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
// Stats tracks statistics for a running server
|
||||
type Stats struct {
|
||||
StatsValues
|
||||
|
||||
s.Total += i
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// ChangeInvisible increments the invisible count
|
||||
func (s *Stats) ChangeInvisible(i int) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.Invisible += i
|
||||
// Adds an unregistered client
|
||||
func (s *Stats) Add() {
|
||||
s.mutex.Lock()
|
||||
s.Unknown += 1
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
|
||||
// ChangeOperators increases the operator count
|
||||
func (s *Stats) ChangeOperators(i int) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
// Transition a client from unregistered to registered
|
||||
func (s *Stats) Register() {
|
||||
s.mutex.Lock()
|
||||
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
|
||||
func (s *Stats) GetStats() (int, int, int) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
return s.Total, s.Invisible, s.Operators
|
||||
func (s *Stats) GetValues() (result StatsValues) {
|
||||
s.mutex.Lock()
|
||||
result = s.StatsValues
|
||||
s.mutex.Unlock()
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user