3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-13 07:29:30 +01:00

add ClientDetails struct for getting a snapshot of client state

This commit is contained in:
Shivaram Lingamneni 2019-01-01 13:00:16 -05:00
parent c2b2559ab4
commit 960d51159c
7 changed files with 53 additions and 39 deletions

View File

@ -52,7 +52,7 @@ type ResumeDetails struct {
// Client is an IRC client. // Client is an IRC client.
type Client struct { type Client struct {
account string account string
accountName string accountName string // display name of the account: uncasefolded, '*' if not logged in
atime time.Time atime time.Time
authorized bool authorized bool
awayMessage string awayMessage string
@ -100,6 +100,25 @@ type Client struct {
history *history.Buffer history *history.Buffer
} }
// WhoWas is the subset of client details needed to answer a WHOWAS query
type WhoWas struct {
nick string
nickCasefolded string
username string
hostname string
realname string
}
// ClientDetails is a standard set of details about a client
type ClientDetails struct {
WhoWas
nickMask string
nickMaskCasefolded string
account string
accountName string
}
// NewClient sets up a new client and starts its goroutine. // NewClient sets up a new client and starts its goroutine.
func NewClient(server *Server, conn net.Conn, isTLS bool) { func NewClient(server *Server, conn net.Conn, isTLS bool) {
now := time.Now() now := time.Now()
@ -117,6 +136,7 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) {
flags: modes.NewModeSet(), flags: modes.NewModeSet(),
server: server, server: server,
socket: socket, socket: socket,
accountName: "*",
nick: "*", // * is used until actual nick is given nick: "*", // * is used until actual nick is given
nickCasefolded: "*", nickCasefolded: "*",
nickMaskString: "*", // * is used until actual nick is given nickMaskString: "*", // * is used until actual nick is given

View File

@ -147,9 +147,6 @@ func (client *Client) Account() string {
func (client *Client) AccountName() string { func (client *Client) AccountName() string {
client.stateMutex.RLock() client.stateMutex.RLock()
defer client.stateMutex.RUnlock() defer client.stateMutex.RUnlock()
if client.accountName == "" {
return "*"
}
return client.accountName return client.accountName
} }
@ -217,15 +214,22 @@ func (client *Client) Channels() (result []*Channel) {
} }
func (client *Client) WhoWas() (result WhoWas) { func (client *Client) WhoWas() (result WhoWas) {
return client.Details().WhoWas
}
func (client *Client) Details() (result ClientDetails) {
client.stateMutex.RLock() client.stateMutex.RLock()
defer client.stateMutex.RUnlock() defer client.stateMutex.RUnlock()
result.nicknameCasefolded = client.nickCasefolded result.nick = client.nick
result.nickname = client.nick result.nickCasefolded = client.nickCasefolded
result.username = client.username result.username = client.username
result.hostname = client.hostname result.hostname = client.username
result.realname = client.realname result.realname = client.realname
result.nickMask = client.nickMaskString
result.nickMaskCasefolded = client.nickMaskCasefolded
result.account = client.account
result.accountName = client.accountName
return return
} }

View File

@ -2541,7 +2541,7 @@ func whowasHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Re
} }
} else { } else {
for _, whoWas := range results { for _, whoWas := range results {
rb.Add(nil, server.name, RPL_WHOWASUSER, cnick, whoWas.nickname, whoWas.username, whoWas.hostname, "*", whoWas.realname) rb.Add(nil, server.name, RPL_WHOWASUSER, cnick, whoWas.nick, whoWas.username, whoWas.hostname, "*", whoWas.realname)
} }
} }
if len(nickname) > 0 { if len(nickname) > 0 {

View File

@ -59,7 +59,7 @@ func performNickChange(server *Server, client *Client, target *Client, newnick s
client.server.logger.Debug("nick", fmt.Sprintf("%s changed nickname to %s [%s]", origNickMask, nickname, cfnick)) client.server.logger.Debug("nick", fmt.Sprintf("%s changed nickname to %s [%s]", origNickMask, nickname, cfnick))
if hadNick { if hadNick {
target.server.snomasks.Send(sno.LocalNicks, fmt.Sprintf(ircfmt.Unescape("$%s$r changed nickname to %s"), whowas.nickname, nickname)) target.server.snomasks.Send(sno.LocalNicks, fmt.Sprintf(ircfmt.Unescape("$%s$r changed nickname to %s"), whowas.nick, nickname))
target.server.whoWas.Append(whowas) target.server.whoWas.Append(whowas)
for friend := range target.Friends() { for friend := range target.Friends() {
friend.Send(nil, origNickMask, "NICK", nickname) friend.Send(nil, origNickMask, "NICK", nickname)

View File

@ -500,9 +500,9 @@ func (client *Client) WhoisChannelsNames(target *Client) []string {
func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) { func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
cnick := client.Nick() cnick := client.Nick()
targetInfo := target.WhoWas() targetInfo := target.Details()
rb.Add(nil, client.server.name, RPL_WHOISUSER, cnick, targetInfo.nickname, targetInfo.username, targetInfo.hostname, "*", targetInfo.realname) rb.Add(nil, client.server.name, RPL_WHOISUSER, cnick, targetInfo.nick, targetInfo.username, targetInfo.hostname, "*", targetInfo.realname)
tnick := targetInfo.nickname tnick := targetInfo.nick
whoischannels := client.WhoisChannelsNames(target) whoischannels := client.WhoisChannelsNames(target)
if whoischannels != nil { if whoischannels != nil {
@ -518,9 +518,8 @@ func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
if target.HasMode(modes.TLS) { if target.HasMode(modes.TLS) {
rb.Add(nil, client.server.name, RPL_WHOISSECURE, cnick, tnick, client.t("is using a secure connection")) rb.Add(nil, client.server.name, RPL_WHOISSECURE, cnick, tnick, client.t("is using a secure connection"))
} }
taccount := target.AccountName() if targetInfo.accountName != "*" {
if taccount != "*" { rb.Add(nil, client.server.name, RPL_WHOISACCOUNT, cnick, tnick, targetInfo.accountName, client.t("is logged in as"))
rb.Add(nil, client.server.name, RPL_WHOISACCOUNT, cnick, tnick, taccount, client.t("is logged in as"))
} }
if target.HasMode(modes.Bot) { if target.HasMode(modes.Bot) {
rb.Add(nil, client.server.name, RPL_WHOISBOT, cnick, tnick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.Config().Network.Name))) rb.Add(nil, client.server.name, RPL_WHOISBOT, cnick, tnick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.Config().Network.Name)))

View File

@ -22,15 +22,6 @@ type WhoWasList struct {
accessMutex sync.RWMutex // tier 1 accessMutex sync.RWMutex // tier 1
} }
// WhoWas is an entry in the WhoWasList.
type WhoWas struct {
nicknameCasefolded string
nickname string
username string
hostname string
realname string
}
// NewWhoWasList returns a new WhoWasList // NewWhoWasList returns a new WhoWasList
func NewWhoWasList(size int) *WhoWasList { func NewWhoWasList(size int) *WhoWasList {
return &WhoWasList{ return &WhoWasList{
@ -82,7 +73,7 @@ func (list *WhoWasList) Find(nickname string, limit int) (results []WhoWas) {
// iterate backwards through the ring buffer // iterate backwards through the ring buffer
pos := list.prev(list.end) pos := list.prev(list.end)
for limit == 0 || len(results) < limit { for limit == 0 || len(results) < limit {
if casefoldedNickname == list.buffer[pos].nicknameCasefolded { if casefoldedNickname == list.buffer[pos].nickCasefolded {
results = append(results, list.buffer[pos]) results = append(results, list.buffer[pos])
} }
if pos == list.start { if pos == list.start {

View File

@ -13,11 +13,11 @@ func makeTestWhowas(nick string) WhoWas {
panic(err) panic(err)
} }
return WhoWas{ return WhoWas{
nicknameCasefolded: cfnick, nickCasefolded: cfnick,
nickname: nick, nick: nick,
username: "user", username: "user",
hostname: "oragono.io", hostname: "oragono.io",
realname: "Real Name", realname: "Real Name",
} }
} }
@ -36,48 +36,48 @@ func TestWhoWas(t *testing.T) {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
results = wwl.Find("dan-", 10) results = wwl.Find("dan-", 10)
if len(results) != 1 || results[0].nickname != "dan-" { if len(results) != 1 || results[0].nick != "dan-" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
wwl.Append(makeTestWhowas("slingamn")) wwl.Append(makeTestWhowas("slingamn"))
results = wwl.Find("slingamN", 10) results = wwl.Find("slingamN", 10)
if len(results) != 1 || results[0].nickname != "slingamn" { if len(results) != 1 || results[0].nick != "slingamn" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
wwl.Append(makeTestWhowas("Dan-")) wwl.Append(makeTestWhowas("Dan-"))
results = wwl.Find("dan-", 10) results = wwl.Find("dan-", 10)
// reverse chronological order // reverse chronological order
if len(results) != 2 || results[0].nickname != "Dan-" || results[1].nickname != "dan-" { if len(results) != 2 || results[0].nick != "Dan-" || results[1].nick != "dan-" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
// 0 means no limit // 0 means no limit
results = wwl.Find("dan-", 0) results = wwl.Find("dan-", 0)
if len(results) != 2 || results[0].nickname != "Dan-" || results[1].nickname != "dan-" { if len(results) != 2 || results[0].nick != "Dan-" || results[1].nick != "dan-" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
// a limit of 1 should return the most recent entry only // a limit of 1 should return the most recent entry only
results = wwl.Find("dan-", 1) results = wwl.Find("dan-", 1)
if len(results) != 1 || results[0].nickname != "Dan-" { if len(results) != 1 || results[0].nick != "Dan-" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
wwl.Append(makeTestWhowas("moocow")) wwl.Append(makeTestWhowas("moocow"))
results = wwl.Find("moocow", 10) results = wwl.Find("moocow", 10)
if len(results) != 1 || results[0].nickname != "moocow" { if len(results) != 1 || results[0].nick != "moocow" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
results = wwl.Find("dan-", 10) results = wwl.Find("dan-", 10)
// should have overwritten the original entry, leaving the second // should have overwritten the original entry, leaving the second
if len(results) != 1 || results[0].nickname != "Dan-" { if len(results) != 1 || results[0].nick != "Dan-" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
// overwrite the second entry // overwrite the second entry
wwl.Append(makeTestWhowas("enckse")) wwl.Append(makeTestWhowas("enckse"))
results = wwl.Find("enckse", 10) results = wwl.Find("enckse", 10)
if len(results) != 1 || results[0].nickname != "enckse" { if len(results) != 1 || results[0].nick != "enckse" {
t.Fatalf("incorrect whowas results: %v", results) t.Fatalf("incorrect whowas results: %v", results)
} }
results = wwl.Find("slingamn", 10) results = wwl.Find("slingamn", 10)