|
@@ -1,3 +1,4 @@
|
|
|
+
|
|
|
package ircclient
|
|
|
|
|
|
import (
|
|
@@ -19,8 +20,19 @@ import (
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
-const VERSION string = "red-green.com/irc-client 0.1.0"
|
|
|
+
|
|
|
+var VERSION string = GetModuleVersion()
|
|
|
|
|
|
+func GetModuleVersion() string {
|
|
|
+ modules := GetModules()
|
|
|
+ version, has := modules["git.red-green.com/RedGreen/irc-client"]
|
|
|
+ if has {
|
|
|
+ return version
|
|
|
+ }
|
|
|
+ return "git.red-green.com/irc-client"
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
func StrInArray(strings []string, str string) bool {
|
|
|
for _, s := range strings {
|
|
|
if s == str {
|
|
@@ -30,14 +42,16 @@ func StrInArray(strings []string, str string) bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
+
|
|
|
type IRCMsg struct {
|
|
|
- MsgParts []string
|
|
|
- From string
|
|
|
- To string
|
|
|
- Cmd string
|
|
|
- Msg string
|
|
|
+ MsgParts []string
|
|
|
+ From string
|
|
|
+ To string
|
|
|
+ Cmd string
|
|
|
+ Msg string
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func NameLower(name string) string {
|
|
|
|
|
|
|
|
@@ -57,6 +71,8 @@ func Match(name1 string, name2 string) bool {
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
func IRCNick(from string) string {
|
|
|
if from[0] == ':' {
|
|
|
from = from[1:]
|
|
@@ -74,30 +90,33 @@ IRCParse - split line into IRCMsg
|
|
|
Everything after " :" is the Msg.
|
|
|
Everything before " :" is split into MsgParts[].
|
|
|
|
|
|
-If >= 3 MsgParts {
|
|
|
- To = MsgParts[2]
|
|
|
-}
|
|
|
-if >= 2 MsgParts {
|
|
|
- From = IrcNic(MsgParts[0])
|
|
|
- Cmd = MsgParts[1]
|
|
|
-} else {
|
|
|
- Cmd = MsgParts[0]
|
|
|
-}
|
|
|
+ If >= 3 MsgParts {
|
|
|
+ To = MsgParts[2]
|
|
|
+ }
|
|
|
+
|
|
|
+ if >= 2 MsgParts {
|
|
|
+ From = IrcNic(MsgParts[0])
|
|
|
+ Cmd = MsgParts[1]
|
|
|
+ } else {
|
|
|
+
|
|
|
+ Cmd = MsgParts[0]
|
|
|
+ }
|
|
|
|
|
|
Example Messages:
|
|
|
|
|
|
:irc.red-green.com 001 test :Welcome to IRC
|
|
|
^From ^Cmd ^Msg
|
|
|
- ^To
|
|
|
+
|
|
|
+ ^To
|
|
|
+
|
|
|
^0 ^1 ^2 MsgParts[]
|
|
|
|
|
|
PING :1234567890
|
|
|
^Cmd ^Msg
|
|
|
^0 MsgParts[]
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
*/
|
|
|
+
|
|
|
+
|
|
|
func IRCParse(line string) IRCMsg {
|
|
|
var pos int = strings.Index(line, " :")
|
|
|
var results IRCMsg
|
|
@@ -119,6 +138,19 @@ func IRCParse(line string) IRCMsg {
|
|
|
if len(results.MsgParts) >= 3 {
|
|
|
results.To = results.MsgParts[2]
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ if results.Cmd == "PRIVMSG" {
|
|
|
+ if (results.Msg[0] == '\x01') && (results.Msg[len(results.Msg)-1] == '\x01') {
|
|
|
+ results.Cmd = "CTCP"
|
|
|
+ results.Msg = results.Msg[1 : len(results.Msg)-1]
|
|
|
+ if strings.HasPrefix(results.Msg, "ACTION ") {
|
|
|
+ results.Cmd = "ACTION"
|
|
|
+ results.Msg = results.Msg[7:]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return results
|
|
|
}
|
|
|
|
|
@@ -140,20 +172,25 @@ func oldIRCParse(line string) []string {
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
type IRCWrite struct {
|
|
|
- To string
|
|
|
- Output string
|
|
|
+ To string
|
|
|
+ Output string
|
|
|
}
|
|
|
|
|
|
+
|
|
|
type IRCConfig struct {
|
|
|
- Port int `json:"Port"`
|
|
|
- Hostname string `json:"Hostname"`
|
|
|
- UseTLS bool `json:"UseTLS"`
|
|
|
- UseSASL bool `json:"UseSASL"`
|
|
|
- Insecure bool `json:"Insecure"`
|
|
|
- Nick string `json:"Nick"`
|
|
|
- Username string `json:"Username"`
|
|
|
- Realname string `json:"Realname"`
|
|
|
+ Port int `json:"Port"`
|
|
|
+ Hostname string `json:"Hostname"`
|
|
|
+ UseTLS bool `json:"UseTLS"`
|
|
|
+ UseSASL bool `json:"UseSASL"`
|
|
|
+ Insecure bool `json:"Insecure"`
|
|
|
+ Nick string `json:"Nick"`
|
|
|
+ Username string `json:"Username"`
|
|
|
+ Realname string `json:"Realname"`
|
|
|
Password string `json:"Password"`
|
|
|
ServerPassword string `json:"ServerPassword"`
|
|
|
AutoJoin []string `json:"AutoJoin"`
|
|
@@ -162,45 +199,57 @@ type IRCConfig struct {
|
|
|
Flood_Num int `json:"FloodNum"`
|
|
|
Flood_Time int `json:"FloodTime"`
|
|
|
Flood_Delay int `json:"FloodDelay"`
|
|
|
- Debug_Output bool `json:"Debug"`
|
|
|
+ Debug_Output bool `json:"Debug"`
|
|
|
}
|
|
|
|
|
|
type IRCClient struct {
|
|
|
IRCConfig
|
|
|
- MyNick string
|
|
|
- OnExit func() // Called on exit
|
|
|
- Socket net.Conn
|
|
|
- Reader *bufio.Reader
|
|
|
- ReadChannel chan IRCMsg
|
|
|
- ReadEvents []string
|
|
|
- WriteChannel chan IRCWrite
|
|
|
- DelChannel chan string
|
|
|
- Registered bool
|
|
|
- ISupport map[string]string
|
|
|
- wg sync.WaitGroup
|
|
|
- Mutex sync.Mutex
|
|
|
+ MyNick string
|
|
|
+ OnExit func() // Called on exit
|
|
|
+ Socket net.Conn
|
|
|
+ Reader *bufio.Reader
|
|
|
+ ReadChannel chan IRCMsg
|
|
|
+ ReadEvents []string
|
|
|
+ WriteChannel chan IRCWrite
|
|
|
+ DelChannel chan string
|
|
|
+ Registered bool
|
|
|
+ ISupport map[string]string
|
|
|
+ wg sync.WaitGroup
|
|
|
+ Mutex sync.Mutex
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (Config *IRCClient) GetNick() string {
|
|
|
Config.Mutex.Lock()
|
|
|
defer Config.Mutex.Unlock()
|
|
|
return Config.MyNick
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (Config *IRCClient) SetNick(nick string) {
|
|
|
Config.Mutex.Lock()
|
|
|
defer Config.Mutex.Unlock()
|
|
|
Config.MyNick = nick
|
|
|
}
|
|
|
|
|
|
-func (Config *IRCClient) IsAuto(ch string) bool {
|
|
|
- return StrInArray(Config.AutoJoin, ch)
|
|
|
+
|
|
|
+func (Config *IRCClient) IsAuto(channel string) bool {
|
|
|
+ return StrInArray(Config.AutoJoin, channel)
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
func (Config *IRCClient) Connect() bool {
|
|
|
var err error
|
|
|
|
|
|
|
|
|
+
|
|
|
+ if Config.Version == "" {
|
|
|
+ Config.Version = VERSION
|
|
|
+ }
|
|
|
+
|
|
|
if Config.Flood_Num == 0 {
|
|
|
Config.Flood_Num = 5
|
|
|
}
|
|
@@ -277,7 +326,7 @@ func (Config *IRCClient) Connect() bool {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
func (Config *IRCClient) write(output string) error {
|
|
|
var err error
|
|
|
if Config.Debug_Output {
|
|
@@ -289,6 +338,7 @@ func (Config *IRCClient) write(output string) error {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (Config *IRCClient) WriterRoutine() {
|
|
|
var err error
|
|
|
var throttle ThrottleBuffer
|
|
@@ -297,7 +347,7 @@ func (Config *IRCClient) WriterRoutine() {
|
|
|
Flood.Init(Config.Flood_Num, Config.Flood_Time)
|
|
|
|
|
|
defer Config.wg.Done()
|
|
|
- throttle.init()
|
|
|
+ throttle.Init()
|
|
|
|
|
|
|
|
|
var sigChannel chan os.Signal = make(chan os.Signal, 1)
|
|
@@ -386,6 +436,7 @@ func (Config *IRCClient) WriterRoutine() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (Config *IRCClient) Close() {
|
|
|
Config.Socket.Close()
|
|
|
Config.PriorityWrite("")
|
|
@@ -395,6 +446,7 @@ func (Config *IRCClient) Close() {
|
|
|
Config.wg.Wait()
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func RandomNick(nick string) string {
|
|
|
var result string = nick + "-"
|
|
|
result += strconv.Itoa(rand.Intn(1000))
|
|
@@ -402,6 +454,8 @@ func RandomNick(nick string) string {
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
func (Config *IRCClient) PriorityWrite(output string) {
|
|
|
Config.WriteChannel <- IRCWrite{To: "", Output: output}
|
|
|
}
|
|
@@ -426,6 +480,14 @@ func (Config *IRCClient) Action(to string, message string) {
|
|
|
Config.WriteTo(to, fmt.Sprintf("PRIVMSG %s :\x01ACTION %s\x01", to, message))
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
func (Config *IRCClient) ReaderRoutine() {
|
|
|
defer Config.wg.Done()
|
|
|
var registering bool
|
|
@@ -465,52 +527,29 @@ func (Config *IRCClient) ReaderRoutine() {
|
|
|
Config.MyNick = newNick
|
|
|
Config.PriorityWrite("NICK " + newNick)
|
|
|
}
|
|
|
- case "PRIVMSG":
|
|
|
-
|
|
|
- if (results.Msg[0] == '\x01') && (results.Msg[len(results.Msg)-1] == '\x01') {
|
|
|
-
|
|
|
- results.Cmd = "CTCP"
|
|
|
- results.Msg = results.Msg[1 : len(results.Msg)-1]
|
|
|
- if Config.Debug_Output {
|
|
|
- log.Println("CTCP:", results.Msg)
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if strings.HasPrefix(results.Msg, "ACTION ") {
|
|
|
- results.Cmd = "ACTION"
|
|
|
- results.Msg = results.Msg[7:]
|
|
|
- }
|
|
|
-
|
|
|
- if strings.HasPrefix(results.Msg, "PING ") {
|
|
|
- Config.WriteTo(IRCNick(results.From),
|
|
|
- fmt.Sprintf("NOTICE %s :\x01PING %s\x01",
|
|
|
- IRCNick(results.From),
|
|
|
- results.Msg[5:]))
|
|
|
- }
|
|
|
-
|
|
|
- if results.Msg == "VERSION" {
|
|
|
-
|
|
|
- var version string
|
|
|
- if Config.Version != "" {
|
|
|
- version = Config.Version + " " + VERSION
|
|
|
- } else {
|
|
|
- version = VERSION
|
|
|
- }
|
|
|
- Config.WriteTo(IRCNick(results.From),
|
|
|
- fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01",
|
|
|
- IRCNick(results.From), version))
|
|
|
- }
|
|
|
-
|
|
|
- if results.Msg == "TIME" {
|
|
|
-
|
|
|
- var now time.Time = time.Now()
|
|
|
- Config.WriteTo(IRCNick(results.From),
|
|
|
- fmt.Sprintf("NOTICE %s :\x01TIME %s\x01",
|
|
|
- IRCNick(results.From),
|
|
|
- now.Format(time.ANSIC)))
|
|
|
+ case "CTCP":
|
|
|
+ if strings.HasPrefix(results.Msg, "PING ") {
|
|
|
+ Config.WriteTo(IRCNick(results.From),
|
|
|
+ fmt.Sprintf("NOTICE %s :\x01%s\x01",
|
|
|
+ IRCNick(results.From),
|
|
|
+ results.Msg))
|
|
|
+ } else if strings.HasPrefix(results.Msg, "VERSION") {
|
|
|
+ var version string
|
|
|
+ if Config.Version != "" {
|
|
|
+ version = Config.Version + " " + VERSION
|
|
|
+ } else {
|
|
|
+ version = VERSION
|
|
|
}
|
|
|
+ Config.WriteTo(IRCNick(results.From),
|
|
|
+ fmt.Sprintf("NOTICE %s :\x01VERSION %s\x01",
|
|
|
+ IRCNick(results.From), version))
|
|
|
+ } else if strings.HasPrefix(results.Msg, "TIME") {
|
|
|
+ var now time.Time = time.Now()
|
|
|
+ Config.WriteTo(IRCNick(results.From),
|
|
|
+ fmt.Sprintf("NOTICE %s :\x01TIME %s\x01",
|
|
|
+ IRCNick(results.From),
|
|
|
+ now.Format(time.ANSIC)))
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
} else {
|
|
|
|