libnmdc/UserInfo.go

178 lines
4.4 KiB
Go
Raw Normal View History

2016-02-12 04:03:42 +00:00
// libnmdc project UserInfo.go
package libnmdc
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
2016-02-12 04:03:42 +00:00
)
type UserFlag byte
const (
FLAG_NORMAL UserFlag = 1
FLAG_AWAY_1 UserFlag = 2
FLAG_AWAY_2 UserFlag = 3
FLAG_SERVER_1 UserFlag = 4
FLAG_SERVER_2 UserFlag = 5
FLAG_SERVER_AWAY_1 UserFlag = 6
FLAG_SERVER_AWAY_2 UserFlag = 7
FLAG_FIREBALL_1 UserFlag = 8
FLAG_FIREBALL_2 UserFlag = 9
FLAG_FIREBALL_AWAY_1 UserFlag = 10
FLAG_FIREBALL_AWAY_2 UserFlag = 11
)
type ConnectionMode rune
const (
CONNECTIONMODE_ACTIVE ConnectionMode = 'A'
CONNECTIONMODE_PASSIVE ConnectionMode = 'P'
CONNECTIONMODE_SOCKS5 ConnectionMode = '5'
)
// This structure represents a user connected to a hub.
type UserInfo struct {
Nick string
Description string
ClientTag string
ClientVersion string
2016-02-12 04:03:42 +00:00
Email string
ShareSize uint64
ConnectionMode ConnectionMode
Flag UserFlag
Slots uint64
Speed string
HubsUnregistered uint64
HubsRegistered uint64
HubsOperator uint64
IsOperator bool
2016-02-12 04:03:42 +00:00
}
var rx_myinfo *regexp.Regexp
var rx_myinfo_notag *regexp.Regexp
func init() {
// $ALL <nick> <description>$ $<connection><flag>$<e-mail>$<sharesize>$
HEAD := `(?ms)^\$ALL ([^ ]+) `
FOOT := `\$.\$([^$]+)\$([^$]*)\$([0-9]*)\$$`
rx_myinfo = regexp.MustCompile(HEAD + `([^<]*)<(.+?) V:([^,]+),M:(.),H:([0-9]+)/([0-9]+)/([0-9]+),S:([0-9]+)>` + FOOT)
rx_myinfo_notag = regexp.MustCompile(HEAD + `([^$]*)` + FOOT) // Fallback for no tag
2016-02-12 04:03:42 +00:00
/*
sample := ""
// sample = "$ALL Betty description<ApexDC++ V:1.4.3,M:P,H:9/0/2,S:1>$ $0.01\x01$xyz@xyz.com$53054999578$"
// sample = "$ALL ivysaur80 $P$10A$$0$"
// sample = "$ALL SHINY_IVYSAUR <ncdc V:1.19.1-12-g5561,M:P,H:1/0/0,S:10>$ $0.005Q$$0$"
// sample = "$ALL mappu desccccc<HexChat V:2.12.1,M:P,H:1/0/0,S:0>$ $p$$0$"
2016-02-12 04:03:42 +00:00
u := UserInfo{}
err := u.fromMyINFO(sample)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Printf("%+v\n", u)
}
panic("")
2016-02-12 04:03:42 +00:00
*/
}
func NewUserInfo(username string) *UserInfo {
return &UserInfo{
Nick: username,
ConnectionMode: CONNECTIONMODE_PASSIVE,
HubsUnregistered: 1,
}
}
func maybeParse(str string, dest *uint64, default_val uint64) {
sz, err := strconv.ParseUint(str, 10, 64)
if err == nil {
*dest = sz
} else {
*dest = default_val
}
}
func (this *UserInfo) fromMyINFO(protomsg string) error {
// Normal format (with tag in exact V/M/H/S order)
2016-02-12 04:03:42 +00:00
matches := rx_myinfo.FindStringSubmatch(protomsg)
if matches != nil {
this.Nick = matches[1]
this.Description = NMDCUnescape(matches[2])
this.ClientTag = NMDCUnescape(matches[3])
this.ClientVersion = matches[4]
2016-02-12 04:03:42 +00:00
this.ConnectionMode = ConnectionMode(matches[4][0])
maybeParse(matches[6], &this.HubsUnregistered, 0)
maybeParse(matches[7], &this.HubsRegistered, 0)
maybeParse(matches[8], &this.HubsOperator, 0)
maybeParse(matches[9], &this.Slots, 0)
if len(matches[10]) > 1 {
this.Speed = matches[10][:len(matches[10])-2]
} else {
this.Speed = ""
}
this.Flag = UserFlag(matches[10][len(matches[10])-1])
this.Email = NMDCUnescape(matches[11])
maybeParse(matches[12], &this.ShareSize, 0)
2016-02-12 04:03:42 +00:00
return nil
}
// No-tag format, used in early connection
matches = rx_myinfo_notag.FindStringSubmatch(protomsg)
if matches != nil {
this.Nick = matches[1]
this.Description = NMDCUnescape(matches[2])
this.ClientTag = ""
this.ClientVersion = "0"
2016-02-12 04:03:42 +00:00
this.ConnectionMode = CONNECTIONMODE_PASSIVE
this.HubsUnregistered = 0
this.HubsRegistered = 0
this.HubsOperator = 0
this.Slots = 0
if len(matches[3]) > 1 {
this.Speed = matches[3][:len(matches[3])-2]
} else {
this.Speed = ""
}
this.Flag = UserFlag(matches[3][len(matches[3])-1])
this.Email = NMDCUnescape(matches[4])
maybeParse(matches[5], &this.ShareSize, 0)
2016-02-12 04:03:42 +00:00
return nil
}
fmt.Printf("PARSE: malformed\n")
2016-02-12 04:03:42 +00:00
// Couldn't get anything out of it...
return errors.New("Malformed MyINFO")
}
// Returns the MyINFO command, WITH leading $MyINFO, and WITHOUT trailing pipe
func (this *UserInfo) toMyINFO() string {
return fmt.Sprintf(
"$MyINFO $ALL %s %s<%s V:%s,M:%c,H:%d/%d/%d,S:%d>$ $%s%c$%s$%d$",
2016-02-12 04:03:42 +00:00
this.Nick,
this.Description,
this.ClientTag,
strings.Replace(this.ClientVersion, ",", "-", -1), // just in case
2016-02-12 04:03:42 +00:00
this.ConnectionMode,
this.HubsUnregistered,
this.HubsRegistered,
this.HubsOperator,
this.Slots,
this.Speed,
this.Flag,
this.Email,
this.ShareSize,
)
}