2016-09-02 05:54:54 +00:00
|
|
|
package main
|
|
|
|
|
2017-09-13 05:51:51 +00:00
|
|
|
import (
|
2017-12-02 07:50:51 +00:00
|
|
|
"fmt"
|
2017-12-11 11:01:24 +00:00
|
|
|
"sort"
|
2017-12-02 07:50:51 +00:00
|
|
|
"strings"
|
2017-09-13 05:51:51 +00:00
|
|
|
"sync"
|
2017-12-02 07:50:51 +00:00
|
|
|
"time"
|
2017-12-11 11:01:24 +00:00
|
|
|
|
|
|
|
"gopkg.in/sorcix/irc.v2"
|
2017-09-13 05:51:51 +00:00
|
|
|
)
|
2017-04-15 21:31:16 +00:00
|
|
|
|
2016-09-02 05:54:54 +00:00
|
|
|
type Channel struct {
|
2016-09-04 09:22:33 +00:00
|
|
|
Entity
|
2016-09-02 05:54:54 +00:00
|
|
|
|
2017-09-13 05:51:51 +00:00
|
|
|
clients *sync.Map
|
2017-12-11 11:01:24 +00:00
|
|
|
logs map[int64]*ChannelLog
|
2016-09-02 05:54:54 +00:00
|
|
|
|
|
|
|
topic string
|
|
|
|
topictime int64
|
2017-12-02 07:50:51 +00:00
|
|
|
|
|
|
|
sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
type ChannelLog struct {
|
|
|
|
Timestamp int64
|
|
|
|
Client string
|
|
|
|
IP string
|
2017-12-15 01:39:18 +00:00
|
|
|
Account int64
|
2017-12-02 07:50:51 +00:00
|
|
|
Action string
|
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
2021-06-25 06:00:33 +00:00
|
|
|
const logsPerPage = 25
|
2017-12-02 07:50:51 +00:00
|
|
|
|
|
|
|
func (cl *ChannelLog) Identifier(index int) string {
|
2017-12-11 11:01:24 +00:00
|
|
|
return fmt.Sprintf("%03d%02d", index, cl.Timestamp%100)
|
2017-12-02 07:50:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (cl *ChannelLog) Print(index int, channel string) string {
|
2017-12-11 11:01:24 +00:00
|
|
|
return strings.TrimSpace(fmt.Sprintf("%s %s %s %4s %s", time.Unix(0, cl.Timestamp).Format(time.Stamp), channel, cl.Identifier(index), cl.Action, cl.Message))
|
2016-09-02 05:54:54 +00:00
|
|
|
}
|
2017-09-13 05:51:51 +00:00
|
|
|
|
|
|
|
func NewChannel(identifier string) *Channel {
|
|
|
|
c := &Channel{}
|
2021-06-25 06:00:33 +00:00
|
|
|
c.Initialize(entityChannel, identifier)
|
2017-09-13 05:51:51 +00:00
|
|
|
|
|
|
|
c.clients = new(sync.Map)
|
2017-12-11 11:01:24 +00:00
|
|
|
c.logs = make(map[int64]*ChannelLog)
|
2017-09-13 05:51:51 +00:00
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
2017-12-02 07:50:51 +00:00
|
|
|
|
|
|
|
func (c *Channel) Log(client *Client, action string, message string) {
|
|
|
|
c.Lock()
|
|
|
|
defer c.Unlock()
|
|
|
|
|
2017-12-11 11:01:24 +00:00
|
|
|
// TODO: Log size limiting, max capacity will be 999 entries
|
2017-12-02 07:50:51 +00:00
|
|
|
// Log hash of IP address which is used later when connecting/joining
|
|
|
|
|
2017-12-11 11:01:24 +00:00
|
|
|
nano := time.Now().UTC().UnixNano()
|
|
|
|
c.logs[nano] = &ChannelLog{Timestamp: nano, Client: client.identifier, IP: client.iphash, Account: client.account, Action: action, Message: message}
|
2017-12-02 07:50:51 +00:00
|
|
|
}
|
|
|
|
|
2017-12-15 01:39:18 +00:00
|
|
|
func (c *Channel) RevealLog(page int, showAll bool) []string {
|
2017-12-02 07:50:51 +00:00
|
|
|
c.RLock()
|
|
|
|
defer c.RUnlock()
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
// Trim old channel logs periodically
|
|
|
|
// Add pagination
|
|
|
|
var ls []string
|
|
|
|
logsRemain := false
|
|
|
|
j := 0
|
2017-12-11 11:01:24 +00:00
|
|
|
|
|
|
|
var nanos int64arr
|
|
|
|
for n := range c.logs {
|
|
|
|
nanos = append(nanos, n)
|
|
|
|
}
|
|
|
|
sort.Sort(nanos)
|
|
|
|
|
|
|
|
// To perform the opertion you want
|
|
|
|
var l *ChannelLog
|
|
|
|
var ok bool
|
|
|
|
for i, nano := range nanos {
|
|
|
|
if l, ok = c.logs[nano]; !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-06-25 06:00:33 +00:00
|
|
|
if page == -1 || i >= (logsPerPage*(page-1)) {
|
2017-12-15 01:39:18 +00:00
|
|
|
if showAll || (l.Action != irc.JOIN && l.Action != irc.PART) {
|
2021-06-25 06:00:33 +00:00
|
|
|
if page > -1 && j == logsPerPage {
|
2017-12-11 11:01:24 +00:00
|
|
|
logsRemain = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
ls = append(ls, l.Print(i, c.identifier))
|
|
|
|
j++
|
2017-12-02 07:50:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(ls) == 0 {
|
|
|
|
ls = append(ls, "No log entries match criteria")
|
|
|
|
} else {
|
2017-12-15 01:39:18 +00:00
|
|
|
filterType := "all entries"
|
2017-12-02 07:50:51 +00:00
|
|
|
if page > -1 {
|
|
|
|
filterType = fmt.Sprintf("page %d", page)
|
|
|
|
}
|
|
|
|
ls = append([]string{fmt.Sprintf("Revealing %s (%s)", c.identifier, filterType)}, ls...)
|
|
|
|
|
|
|
|
finishedMessage := fmt.Sprintf("Finished revealing %s", c.identifier)
|
|
|
|
if logsRemain {
|
|
|
|
finishedMessage = fmt.Sprintf("Additional log entries on page %d", page+1)
|
|
|
|
}
|
|
|
|
ls = append(ls, finishedMessage)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ls
|
|
|
|
}
|
|
|
|
|
2017-12-15 01:39:18 +00:00
|
|
|
func (c *Channel) RevealInfo(identifier string) (string, int64) {
|
2017-12-02 07:50:51 +00:00
|
|
|
if len(identifier) != 5 {
|
2017-12-11 11:01:24 +00:00
|
|
|
return "", 0
|
2017-12-02 07:50:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c.RLock()
|
|
|
|
defer c.RUnlock()
|
|
|
|
|
2017-12-11 11:01:24 +00:00
|
|
|
var nanos int64arr
|
|
|
|
for n := range c.logs {
|
|
|
|
nanos = append(nanos, n)
|
|
|
|
}
|
|
|
|
sort.Sort(nanos)
|
|
|
|
|
|
|
|
var l *ChannelLog
|
|
|
|
var ok bool
|
|
|
|
for i, nano := range nanos {
|
|
|
|
if l, ok = c.logs[nano]; !ok {
|
|
|
|
continue
|
|
|
|
} else if l.Identifier(i) == identifier {
|
|
|
|
return l.IP, l.Account
|
2017-12-02 07:50:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-11 11:01:24 +00:00
|
|
|
return "", 0
|
2017-12-02 07:50:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Channel) HasClient(client string) bool {
|
|
|
|
_, ok := c.clients.Load(client)
|
|
|
|
return ok
|
|
|
|
}
|
2017-12-20 09:06:42 +00:00
|
|
|
|
|
|
|
func (c *Channel) clientCount() int {
|
|
|
|
ccount := 0
|
|
|
|
c.clients.Range(func(k, v interface{}) bool {
|
|
|
|
ccount++
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
return ccount
|
|
|
|
}
|