1
0
Fork 0
mirror of https://github.com/fluffle/goirc synced 2025-05-14 19:43:20 +00:00

First steps towards client interface.

- Move all exported vars to Config struct;
- Plumbing for Config.Me etc;
- Constants and INIT/REGISTER handler from github.com/iopred;
This commit is contained in:
Alex Bramley 2013-02-18 01:36:17 +00:00
parent 39882dafd4
commit a323372a0b
5 changed files with 130 additions and 97 deletions

View file

@ -3,7 +3,6 @@ package client
import (
"bufio"
"crypto/tls"
"errors"
"fmt"
"github.com/fluffle/goirc/state"
"github.com/fluffle/golog/logging"
@ -14,15 +13,6 @@ import (
// An IRC connection is represented by this struct.
type Conn struct {
// Connection related vars people will care about
Me *state.Nick
Host string
Network string
Connected bool
// Deprecated: future work to turn Conn into an interface will break this.
// Use the State field to store external state that handlers might need.
State interface{}
// Contains parameters that people can tweak to change client behaviour.
cfg *Config
@ -40,6 +30,7 @@ type Conn struct {
io *bufio.ReadWriter
in chan *Line
out chan string
connected bool
// Control channels to goroutines
cSend, cLoop, cPing chan bool
@ -54,6 +45,9 @@ type Config struct {
// Set this to provide the Nick, Ident and Name for the client to use.
Me *state.Nick
// Hostname to connect to and optional connect password.
Server, Pass string
// Are we connecting via SSL? Do we care about certificate validity?
SSL bool
SSLConfig *tls.Config
@ -72,21 +66,19 @@ type Config struct {
}
func NewConfig(nick string, args ...string) *Config {
ident := "goirc"
if len(args) > 0 && args[0] != "" {
ident = args[0]
}
name := "Powered by GoIRC"
if len(args) > 1 && args[1] != "" {
name = args[1]
}
cfg := &Config{
Me: state.NewNick(nick),
PingFreq: 3 * time.Minute,
NewNick: func(s string) string { return s + "_" },
}
cfg.Me = state.NewNick(nick)
cfg.Me.Ident = ident
cfg.Me.Name = name
cfg.Me.Ident = "goirc"
if len(args) > 0 && args[0] != "" {
cfg.Me.Ident = args[0]
}
cfg.Me.Name = "Powered by GoIRC"
if len(args) > 1 && args[1] != "" {
cfg.Me.Name = args[1]
}
return cfg
}
@ -99,10 +91,9 @@ func SimpleClient(nick string, args ...string) (*Conn, error) {
func Client(cfg *Config) (*Conn, error) {
logging.InitFromFlags()
if cfg.Me == nil || cfg.Me.Nick == "" || cfg.Me.Ident == "" {
return nil, fmt.Errorf("Must provide a valid state.Nick in cfg.Me.")
return nil, fmt.Errorf("irc.Client(): Both cfg.Nick and cfg.Ident must be non-empty.")
}
conn := &Conn{
Me: cfg.Me,
cfg: cfg,
in: make(chan *Line, 32),
out: make(chan string, 32),
@ -119,17 +110,25 @@ func Client(cfg *Config) (*Conn, error) {
return conn, nil
}
func (conn *Conn) Connected() bool {
return conn.connected
}
func (conn *Conn) Config() *Config {
return conn.cfg
}
func (conn *Conn) StateTracker() state.Tracker {
return conn.st
}
func (conn *Conn) EnableStateTracking() {
if conn.st == nil {
n := conn.Me
n := conn.cfg.Me
conn.st = state.NewTracker(n.Nick)
conn.Me = conn.st.Me()
conn.Me.Ident = n.Ident
conn.Me.Name = n.Name
conn.cfg.Me = conn.st.Me()
conn.cfg.Me.Ident = n.Ident
conn.cfg.Me.Name = n.Name
conn.addSTHandlers()
}
}
@ -142,10 +141,6 @@ func (conn *Conn) DisableStateTracking() {
}
}
func (conn *Conn) StateTracker() state.Tracker {
return conn.st
}
// Per-connection state initialisation.
func (conn *Conn) initialise() {
conn.io = nil
@ -160,43 +155,45 @@ func (conn *Conn) initialise() {
// on the connection to the IRC server, set Conn.SSL to true before calling
// Connect(). The port will default to 6697 if ssl is enabled, and 6667
// otherwise. You can also provide an optional connect password.
func (conn *Conn) Connect(host string, pass ...string) error {
if conn.Connected {
return errors.New(fmt.Sprintf(
"irc.Connect(): already connected to %s, cannot connect to %s",
conn.Host, host))
func (conn *Conn) ConnectTo(host string, pass ...string) error {
conn.cfg.Server = host
if len(pass) > 0 {
conn.cfg.Pass = pass[0]
}
return conn.Connect()
}
func (conn *Conn) Connect() error {
if conn.cfg.Server == "" {
return fmt.Errorf("irc.Connect(): cfg.Server must be non-empty")
}
if conn.connected {
return fmt.Errorf("irc.Connect(): Cannot connect to %s, already connected.", conn.cfg.Server)
}
if conn.cfg.SSL {
if !hasPort(host) {
host += ":6697"
if !hasPort(conn.cfg.Server) {
conn.cfg.Server += ":6697"
}
logging.Info("irc.Connect(): Connecting to %s with SSL.", host)
if s, err := tls.Dial("tcp", host, conn.cfg.SSLConfig); err == nil {
logging.Info("irc.Connect(): Connecting to %s with SSL.", conn.cfg.Server)
if s, err := tls.Dial("tcp", conn.cfg.Server, conn.cfg.SSLConfig); err == nil {
conn.sock = s
} else {
return err
}
} else {
if !hasPort(host) {
host += ":6667"
if !hasPort(conn.cfg.Server) {
conn.cfg.Server += ":6667"
}
logging.Info("irc.Connect(): Connecting to %s without SSL.", host)
if s, err := net.Dial("tcp", host); err == nil {
logging.Info("irc.Connect(): Connecting to %s without SSL.", conn.cfg.Server)
if s, err := net.Dial("tcp", conn.cfg.Server); err == nil {
conn.sock = s
} else {
return err
}
}
conn.Host = host
conn.Connected = true
conn.connected = true
conn.postConnect()
if len(pass) > 0 {
conn.Pass(pass[0])
}
conn.Nick(conn.Me.Nick)
conn.User(conn.Me.Ident, conn.Me.Name)
conn.dispatch(&Line{Cmd: REGISTER})
return nil
}
@ -348,12 +345,12 @@ func (conn *Conn) shutdown() {
func (conn *Conn) String() string {
str := "GoIRC Connection\n"
str += "----------------\n\n"
if conn.Connected {
str += "Connected to " + conn.Host + "\n\n"
if conn.connected {
str += "Connected to " + conn.cfg.Server + "\n\n"
} else {
str += "Not currently connected!\n\n"
}
str += conn.Me.String() + "\n"
str += conn.cfg.Me.String() + "\n"
if conn.st != nil {
str += conn.st.String() + "\n"
}