Send Names reply in multiple messages.

This commit is contained in:
Jeremy Latt 2013-06-02 22:07:50 -07:00
parent 0001131095
commit f133f3691d
8 changed files with 235 additions and 133 deletions

View File

@ -32,11 +32,11 @@ func (set ChannelSet) Remove(channel *Channel) {
} }
func (set ChannelSet) Ids() (ids []RowId) { func (set ChannelSet) Ids() (ids []RowId) {
ids = []RowId{} ids = make([]RowId, len(set))
var i = 0
for channel := range set { for channel := range set {
if channel.id != nil { ids[i] = *(channel.id)
ids = append(ids, *channel.id) i++
}
} }
return ids return ids
} }
@ -67,15 +67,18 @@ func NewChannel(s *Server, name string) *Channel {
func (channel *Channel) Save(q Queryable) bool { func (channel *Channel) Save(q Queryable) bool {
if channel.id == nil { if channel.id == nil {
if err := InsertChannel(q, channel); err != nil { if err := InsertChannel(q, channel); err != nil {
log.Println(err)
return false return false
} }
channelId, err := FindChannelIdByName(q, channel.name) channelId, err := FindChannelIdByName(q, channel.name)
if err != nil { if err != nil {
log.Println(err)
return false return false
} }
channel.id = &channelId channel.id = &channelId
} else { } else {
if err := UpdateChannel(q, channel); err != nil { if err := UpdateChannel(q, channel); err != nil {
log.Println(err)
return false return false
} }
} }
@ -120,6 +123,10 @@ func (channel *Channel) GetTopic(replier Replier) {
replier.Replies() <- RplTopic(channel) replier.Replies() <- RplTopic(channel)
} }
func (channel *Channel) GetUsers(replier Replier) {
replier.Replies() <- NewNamesReply(channel)
}
func (channel *Channel) Replies() chan<- Reply { func (channel *Channel) Replies() chan<- Reply {
return channel.replies return channel.replies
} }
@ -128,6 +135,10 @@ func (channel *Channel) Id() string {
return channel.name return channel.name
} }
func (channel *Channel) Nick() string {
return channel.name
}
func (channel *Channel) PublicId() string { func (channel *Channel) PublicId() string {
return channel.name return channel.name
} }
@ -140,33 +151,33 @@ func (channel *Channel) String() string {
return channel.Id() return channel.Id()
} }
func (channel *Channel) Join(user *User) {
channel.members.Add(user)
user.channels.Add(channel)
channel.Replies() <- RplJoin(channel, user)
channel.GetTopic(user)
channel.GetUsers(user)
}
// //
// commands // commands
// //
func (m *JoinCommand) HandleChannel(channel *Channel) { func (m *JoinCommand) HandleChannel(channel *Channel) {
client := m.Client() client := m.Client()
user := client.user
if channel.key != m.channels[channel.name] { if channel.key != m.channels[channel.name] {
client.user.Replies() <- ErrBadChannelKey(channel) client.Replies() <- ErrBadChannelKey(channel)
return return
} }
channel.members.Add(user) channel.Join(client.user)
user.channels.Add(channel)
channel.Replies() <- RplJoin(channel, user)
channel.GetTopic(user)
user.Replies() <- RplNamReply(channel)
user.Replies() <- RplEndOfNames(channel.server)
} }
func (m *PartCommand) HandleChannel(channel *Channel) { func (m *PartCommand) HandleChannel(channel *Channel) {
user := m.Client().user user := m.Client().user
if !channel.members[user] { if !channel.members[user] {
user.replies <- ErrNotOnChannel(channel) user.Replies() <- ErrNotOnChannel(channel)
return return
} }

View File

@ -48,7 +48,6 @@ func NewClient(server *Server, conn net.Conn) *Client {
func (c *Client) readConn(recv <-chan string) { func (c *Client) readConn(recv <-chan string) {
for str := range recv { for str := range recv {
m, err := ParseCommand(str) m, err := ParseCommand(str)
if err != nil { if err != nil {
if err == NotEnoughArgsError { if err == NotEnoughArgsError {
@ -59,7 +58,7 @@ func (c *Client) readConn(recv <-chan string) {
continue continue
} }
m.SetClient(c) m.SetBase(c)
c.server.commands <- m c.server.commands <- m
} }
} }
@ -69,7 +68,7 @@ func (c *Client) writeConn(write chan<- string, replies <-chan Reply) {
if DEBUG_CLIENT { if DEBUG_CLIENT {
log.Printf("%s ← %s : %s", c, reply.Source(), reply) log.Printf("%s ← %s : %s", c, reply.Source(), reply)
} }
write <- reply.Format(c) reply.Format(c, write)
} }
} }

View File

@ -11,12 +11,13 @@ type Command interface {
Client() *Client Client() *Client
User() *User User() *User
Source() Identifier Source() Identifier
Reply(Reply)
HandleServer(*Server) HandleServer(*Server)
} }
type EditableCommand interface { type EditableCommand interface {
Command Command
SetClient(*Client) SetBase(*Client)
} }
var ( var (
@ -46,25 +47,19 @@ func (command *BaseCommand) Client() *Client {
} }
func (command *BaseCommand) User() *User { func (command *BaseCommand) User() *User {
if command.Client() == nil { return command.Client().user
return nil
}
return command.User()
} }
func (command *BaseCommand) SetClient(c *Client) { func (command *BaseCommand) SetBase(c *Client) {
*command = BaseCommand{c} *command = BaseCommand{c}
} }
func (command *BaseCommand) Source() Identifier { func (command *BaseCommand) Source() Identifier {
client := command.Client() return command.client
if client == nil { }
return nil
} func (command *BaseCommand) Reply(reply Reply) {
if client.user != nil { command.client.Replies() <- reply
return client.user
}
return client
} }
func ParseCommand(line string) (EditableCommand, error) { func ParseCommand(line string) (EditableCommand, error) {
@ -116,9 +111,8 @@ func (cmd *UnknownCommand) String() string {
func NewUnknownCommand(command string, args []string) *UnknownCommand { func NewUnknownCommand(command string, args []string) *UnknownCommand {
return &UnknownCommand{ return &UnknownCommand{
BaseCommand: BaseCommand{}, command: command,
command: command, args: args,
args: args,
} }
} }
@ -139,8 +133,7 @@ func NewPingCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &PingCommand{ msg := &PingCommand{
BaseCommand: BaseCommand{}, server: args[0],
server: args[0],
} }
if len(args) > 1 { if len(args) > 1 {
msg.server2 = args[1] msg.server2 = args[1]
@ -165,8 +158,7 @@ func NewPongCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
message := &PongCommand{ message := &PongCommand{
BaseCommand: BaseCommand{}, server1: args[0],
server1: args[0],
} }
if len(args) > 1 { if len(args) > 1 {
message.server2 = args[1] message.server2 = args[1]
@ -190,8 +182,7 @@ func NewPassCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
return &PassCommand{ return &PassCommand{
BaseCommand: BaseCommand{}, password: args[0],
password: args[0],
}, nil }, nil
} }
@ -211,8 +202,7 @@ func NewNickCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
return &NickCommand{ return &NickCommand{
BaseCommand: BaseCommand{}, nickname: args[0],
nickname: args[0],
}, nil }, nil
} }
@ -236,10 +226,9 @@ func NewUserMsgCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &UserMsgCommand{ msg := &UserMsgCommand{
BaseCommand: BaseCommand{}, user: args[0],
user: args[0], unused: args[2],
unused: args[2], realname: args[3],
realname: args[3],
} }
mode, err := strconv.ParseUint(args[1], 10, 8) mode, err := strconv.ParseUint(args[1], 10, 8)
if err == nil { if err == nil {
@ -260,9 +249,7 @@ func (cmd *QuitCommand) String() string {
} }
func NewQuitCommand(args []string) (EditableCommand, error) { func NewQuitCommand(args []string) (EditableCommand, error) {
msg := &QuitCommand{ msg := &QuitCommand{}
BaseCommand: BaseCommand{},
}
if len(args) > 0 { if len(args) > 0 {
msg.message = args[0] msg.message = args[0]
} }
@ -283,8 +270,7 @@ func (cmd *JoinCommand) String() string {
func NewJoinCommand(args []string) (EditableCommand, error) { func NewJoinCommand(args []string) (EditableCommand, error) {
msg := &JoinCommand{ msg := &JoinCommand{
BaseCommand: BaseCommand{}, channels: make(map[string]string),
channels: make(map[string]string),
} }
if len(args) == 0 { if len(args) == 0 {
@ -327,8 +313,7 @@ func NewPartCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &PartCommand{ msg := &PartCommand{
BaseCommand: BaseCommand{}, channels: strings.Split(args[0], ","),
channels: strings.Split(args[0], ","),
} }
if len(args) > 1 { if len(args) > 1 {
msg.message = args[1] msg.message = args[1]
@ -353,9 +338,8 @@ func NewPrivMsgCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
return &PrivMsgCommand{ return &PrivMsgCommand{
BaseCommand: BaseCommand{}, target: args[0],
target: args[0], message: args[1],
message: args[1],
}, nil }, nil
} }
@ -384,8 +368,7 @@ func NewTopicCommand(args []string) (EditableCommand, error) {
return nil, NotEnoughArgsError return nil, NotEnoughArgsError
} }
msg := &TopicCommand{ msg := &TopicCommand{
BaseCommand: BaseCommand{}, channel: args[0],
channel: args[0],
} }
if len(args) > 1 { if len(args) > 1 {
msg.topic = args[1] msg.topic = args[1]
@ -409,8 +392,7 @@ func NewModeCommand(args []string) (EditableCommand, error) {
} }
cmd := &ModeCommand{ cmd := &ModeCommand{
BaseCommand: BaseCommand{}, nickname: args[0],
nickname: args[0],
} }
if len(args) > 1 { if len(args) > 1 {

View File

@ -12,7 +12,7 @@ const (
type NickServCommand interface { type NickServCommand interface {
HandleNickServ(*NickServ) HandleNickServ(*NickServ)
Client() *Client Client() *Client
SetClient(*Client) SetBase(*Client)
} }
type NickServ struct { type NickServ struct {
@ -56,7 +56,7 @@ func (ns *NickServ) HandlePrivMsg(m *PrivMsgCommand) {
return return
} }
cmd.SetClient(m.Client()) cmd.SetBase(m.Client())
if ns.Debug() { if ns.Debug() {
log.Printf("%s ← %s %s", ns, cmd.Client(), cmd) log.Printf("%s ← %s %s", ns, cmd.Client(), cmd)
} }
@ -106,7 +106,8 @@ func (m *RegisterCommand) HandleNickServ(ns *NickServ) {
return return
} }
user := NewUser(client.nick, ns.server).SetPassword(m.password) user := NewUser(client.nick, ns.server)
user.SetPassword(m.password)
Save(ns.server.db, user) Save(ns.server.db, user)
ns.Reply(client, "You have registered.") ns.Reply(client, "You have registered.")

View File

@ -23,6 +23,10 @@ type Savable interface {
Save(q Queryable) bool Save(q Queryable) bool
} }
type Loadable interface {
Load(q Queryable) bool
}
// //
// general // general
// //
@ -89,6 +93,10 @@ func Save(db *sql.DB, s Savable) {
Transact(db, s.Save) Transact(db, s.Save)
} }
func Load(db *sql.DB, l Loadable) {
Transact(db, l.Load)
}
// //
// general purpose sql // general purpose sql
// //
@ -99,7 +107,7 @@ func findId(q Queryable, sql string, args ...interface{}) (rowId RowId, err erro
return return
} }
func Count(q Queryable, sql string, args ...interface{}) (count uint, err error) { func countRows(q Queryable, sql string, args ...interface{}) (count uint, err error) {
row := q.QueryRow(sql, args...) row := q.QueryRow(sql, args...)
err = row.Scan(&count) err = row.Scan(&count)
return return
@ -162,20 +170,20 @@ func FindChannelByName(q Queryable, name string) (cr *ChannelRow) {
return return
} }
func InsertUser(q Queryable, user *User) (err error) { func InsertUser(q Queryable, row *UserRow) (err error) {
_, err = q.Exec("INSERT INTO user (nick, hash) VALUES (?, ?)", _, err = q.Exec("INSERT INTO user (nick, hash) VALUES (?, ?)",
user.nick, user.hash) row.nick, row.hash)
return return
} }
func UpdateUser(q Queryable, user *User) (err error) { func UpdateUser(q Queryable, row *UserRow) (err error) {
_, err = q.Exec("UPDATE user SET nick = ?, hash = ? WHERE id = ?", _, err = q.Exec("UPDATE user SET nick = ?, hash = ? WHERE id = ?",
user.nick, user.hash, *(user.id)) row.nick, row.hash, row.id)
return return
} }
func DeleteUser(q Queryable, user *User) (err error) { func DeleteUser(q Queryable, id RowId) (err error) {
_, err = q.Exec("DELETE FROM user WHERE id = ?", *(user.id)) _, err = q.Exec("DELETE FROM user WHERE id = ?", id)
return return
} }
@ -211,14 +219,12 @@ func FindChannelIdByName(q Queryable, name string) (RowId, error) {
return findId(q, "SELECT id FROM channel WHERE name = ?", name) return findId(q, "SELECT id FROM channel WHERE name = ?", name)
} }
func FindChannelsForUser(q Queryable, userId RowId) (crs []*ChannelRow, err error) { func findChannels(q Queryable, where string, args ...interface{}) (crs []*ChannelRow, err error) {
query := ` FROM channel WHERE id IN count, err := countRows(q, "SELECT COUNT(id) FROM channel "+where, args...)
(SELECT channel_id from user_channel WHERE user_id = ?)`
count, err := Count(q, "SELECT COUNT(id)"+query, userId)
if err != nil { if err != nil {
return return
} }
rows, err := q.Query("SELECT id, name"+query, userId) rows, err := q.Query("SELECT id, name FROM channel "+where, args...)
if err != nil { if err != nil {
return return
} }
@ -236,6 +242,17 @@ func FindChannelsForUser(q Queryable, userId RowId) (crs []*ChannelRow, err erro
return return
} }
func FindChannelsForUser(q Queryable, userId RowId) (crs []*ChannelRow, err error) {
crs, err = findChannels(q,
"WHERE id IN (SELECT channel_id from user_channel WHERE user_id = ?)", userId)
return
}
func FindAllChannels(q Queryable) (crs []*ChannelRow, err error) {
crs, err = findChannels(q, "")
return
}
func InsertChannel(q Queryable, channel *Channel) (err error) { func InsertChannel(q Queryable, channel *Channel) (err error) {
_, err = q.Exec("INSERT INTO channel (name) VALUES (?)", channel.name) _, err = q.Exec("INSERT INTO channel (name) VALUES (?)", channel.name)
return return

View File

@ -17,7 +17,7 @@ type Replier interface {
} }
type Reply interface { type Reply interface {
Format(client *Client) string Format(*Client, chan<- string)
Source() Identifier Source() Identifier
} }
@ -31,7 +31,7 @@ func (reply *BaseReply) Source() Identifier {
} }
type StringReply struct { type StringReply struct {
BaseReply *BaseReply
code string code string
} }
@ -40,13 +40,13 @@ func NewStringReply(source Identifier, code string,
message := fmt.Sprintf(format, args...) message := fmt.Sprintf(format, args...)
fullMessage := fmt.Sprintf(":%s %s %s", source.Id(), code, message) fullMessage := fmt.Sprintf(":%s %s %s", source.Id(), code, message)
return &StringReply{ return &StringReply{
BaseReply: BaseReply{source, fullMessage}, BaseReply: &BaseReply{source, fullMessage},
code: code, code: code,
} }
} }
func (reply *StringReply) Format(client *Client) string { func (reply *StringReply) Format(client *Client, write chan<- string) {
return reply.message write <- reply.message
} }
func (reply *StringReply) String() string { func (reply *StringReply) String() string {
@ -55,19 +55,23 @@ func (reply *StringReply) String() string {
} }
type NumericReply struct { type NumericReply struct {
BaseReply *BaseReply
code int code int
} }
func NewNumericReply(source Identifier, code int, format string, func NewNumericReply(source Identifier, code int, format string,
args ...interface{}) *NumericReply { args ...interface{}) *NumericReply {
return &NumericReply{ return &NumericReply{
BaseReply: BaseReply{source, fmt.Sprintf(format, args...)}, BaseReply: &BaseReply{source, fmt.Sprintf(format, args...)},
code: code, code: code,
} }
} }
func (reply *NumericReply) Format(client *Client) string { func (reply *NumericReply) Format(client *Client, write chan<- string) {
write <- reply.FormatString(client)
}
func (reply *NumericReply) FormatString(client *Client) string {
return fmt.Sprintf(":%s %03d %s %s", reply.Source().Id(), reply.code, return fmt.Sprintf(":%s %03d %s %s", reply.Source().Id(), reply.code,
client.Nick(), reply.message) client.Nick(), reply.message)
} }
@ -77,6 +81,53 @@ func (reply *NumericReply) String() string {
reply.source, reply.code, reply.message) reply.source, reply.code, reply.message)
} }
// names reply
type NamesReply struct {
*BaseReply
channel *Channel
}
func NewNamesReply(channel *Channel) Reply {
return &NamesReply{
BaseReply: &BaseReply{
source: channel,
},
}
}
const (
MAX_REPLY_LEN = 510 // 512 - CRLF
)
func joinedLen(names []string) int {
var l = len(names) - 1 // " " between names
for _, name := range names {
l += len(name)
}
return l
}
func (reply *NamesReply) Format(client *Client, write chan<- string) {
base := RplNamReply(reply.channel, []string{})
baseLen := len(base.FormatString(client))
tooLong := func(names []string) bool {
return (baseLen + joinedLen(names)) > MAX_REPLY_LEN
}
var start = 0
nicks := reply.channel.Nicks()
for i := range nicks {
if (i > start) && tooLong(nicks[start:i]) {
RplNamReply(reply.channel, nicks[start:i-1]).Format(client, write)
start = i - 1
}
}
if start < (len(nicks) - 1) {
RplNamReply(reply.channel, nicks[start:]).Format(client, write)
}
RplEndOfNames(reply.channel).Format(client, write)
}
// messaging replies // messaging replies
func RplPrivMsg(source Identifier, target Identifier, message string) Reply { func RplPrivMsg(source Identifier, target Identifier, message string) Reply {
@ -118,7 +169,7 @@ func RplWelcome(source Identifier, client *Client) Reply {
"Welcome to the Internet Relay Network %s", client.Id()) "Welcome to the Internet Relay Network %s", client.Id())
} }
func RplYourHost(server *Server, target *Client) Reply { func RplYourHost(server *Server) Reply {
return NewNumericReply(server, RPL_YOURHOST, return NewNumericReply(server, RPL_YOURHOST,
"Your host is %s, running version %s", server.name, VERSION) "Your host is %s, running version %s", server.name, VERSION)
} }
@ -152,10 +203,9 @@ func RplInvitingMsg(channel *Channel, invitee *Client) Reply {
"%s %s", channel.name, invitee.Nick()) "%s %s", channel.name, invitee.Nick())
} }
func RplNamReply(channel *Channel) Reply { func RplNamReply(channel *Channel, names []string) *NumericReply {
// TODO multiple names and splitting based on message size return NewNumericReply(channel.server, RPL_NAMREPLY, "= %s :%s",
return NewNumericReply(channel.server, RPL_NAMREPLY, channel.name, strings.Join(names, " "))
"= %s :%s", channel.name, strings.Join(channel.Nicks(), " "))
} }
func RplEndOfNames(source Identifier) Reply { func RplEndOfNames(source Identifier) Reply {

View File

@ -41,17 +41,34 @@ func NewServer(name string) *Server {
} }
go server.receiveCommands(commands) go server.receiveCommands(commands)
NewNickServ(server) NewNickServ(server)
Transact(server.db, func(q Queryable) bool { Load(server.db, server)
urs, err := FindAllUsers(server.db) return server
if err != nil { }
func (server *Server) Load(q Queryable) bool {
crs, err := FindAllChannels(q)
if err != nil {
log.Println(err)
return false
}
for _, cr := range crs {
channel := server.GetOrMakeChannel(cr.name)
channel.id = &(cr.id)
}
urs, err := FindAllUsers(q)
if err != nil {
log.Println(err)
return false
}
for _, ur := range urs {
user := NewUser(ur.nick, server)
user.SetHash(ur.hash)
if !user.Load(q) {
return false return false
} }
for _, ur := range urs { }
NewUser(ur.nick, server).SetHash(ur.hash) return true
}
return false
})
return server
} }
func (server *Server) receiveCommands(commands <-chan Command) { func (server *Server) receiveCommands(commands <-chan Command) {
@ -115,7 +132,7 @@ func (s *Server) tryRegister(c *Client) {
c.registered = true c.registered = true
replies := []Reply{ replies := []Reply{
RplWelcome(s, c), RplWelcome(s, c),
RplYourHost(s, c), RplYourHost(s),
RplCreated(s), RplCreated(s),
RplMyInfo(s), RplMyInfo(s),
} }
@ -318,21 +335,21 @@ func (m *PrivMsgCommand) HandleServer(s *Server) {
if m.TargetIsChannel() { if m.TargetIsChannel() {
channel := s.channels[m.target] channel := s.channels[m.target]
if channel == nil { if channel == nil {
user.Replies() <- ErrNoSuchChannel(s, m.target) m.Client().Replies() <- ErrNoSuchChannel(s, m.target)
return return
} }
channel.Commands() <- m channel.commands <- m
return return
} }
target := s.users[m.target] target := s.users[m.target]
if target == nil { if target == nil {
user.Replies() <- ErrNoSuchNick(s, m.target) m.Client().Replies() <- ErrNoSuchNick(s, m.target)
return return
} }
target.Commands() <- m target.commands <- m
} }
func (m *ModeCommand) HandleServer(s *Server) { func (m *ModeCommand) HandleServer(s *Server) {

View File

@ -16,7 +16,7 @@ type UserCommand interface {
} }
type User struct { type User struct {
id *RowId id RowId
nick string nick string
hash []byte hash []byte
server *Server server *Server
@ -64,50 +64,80 @@ func NewUser(nick string, server *Server) *User {
return user return user
} }
func (user *User) Row() *UserRow {
return &UserRow{user.id, user.nick, user.hash}
}
func (user *User) Create(q Queryable) bool {
var err error
if err := InsertUser(q, user.Row()); err != nil {
log.Println(err)
return false
}
user.id, err = FindUserIdByNick(q, user.nick)
if err != nil {
log.Println(err)
return false
}
return true
}
func (user *User) Save(q Queryable) bool { func (user *User) Save(q Queryable) bool {
if user.id == nil { if err := UpdateUser(q, user.Row()); err != nil {
if err := InsertUser(q, user); err != nil { log.Println(err)
return false return false
}
userId, err := FindUserIdByNick(q, user.nick)
if err != nil {
return false
}
user.id = &userId
} else {
if err := UpdateUser(q, user); err != nil {
return false
}
} }
userId := *(user.id)
channelIds := user.channels.Ids() channelIds := user.channels.Ids()
if len(channelIds) == 0 { if len(channelIds) == 0 {
if err := DeleteAllUserChannels(q, userId); err != nil { if err := DeleteAllUserChannels(q, user.id); err != nil {
log.Println(err)
return false return false
} }
} else { } else {
if err := DeleteOtherUserChannels(q, userId, channelIds); err != nil { if err := DeleteOtherUserChannels(q, user.id, channelIds); err != nil {
log.Println(err)
return false return false
} }
if err := InsertUserChannels(q, userId, channelIds); err != nil { if err := InsertUserChannels(q, user.id, channelIds); err != nil {
log.Println(err)
return false return false
} }
} }
return true return true
} }
func (user *User) SetPassword(password string) *User { func (user *User) Delete(q Queryable) bool {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) err := DeleteUser(q, user.id)
if err != nil { if err != nil {
panic("bcrypt failed; cannot generate password hash") log.Println(err)
return false
} }
return user.SetHash(hash) return true
} }
func (user *User) SetHash(hash []byte) *User { func (user *User) Load(q Queryable) bool {
crs, err := FindChannelsForUser(q, user.id)
if err != nil {
log.Println(err)
return false
}
for _, cr := range crs {
user.server.GetOrMakeChannel(cr.name).Join(user)
}
return true
}
func (user *User) SetPassword(password string) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
log.Panicln(err)
}
user.SetHash(hash)
}
func (user *User) SetHash(hash []byte) {
user.hash = hash user.hash = hash
return user
} }
func (user *User) receiveCommands(commands <-chan UserCommand) { func (user *User) receiveCommands(commands <-chan UserCommand) {
@ -149,10 +179,6 @@ func (user *User) String() string {
return user.Id() return user.Id()
} }
func (user *User) Commands() chan<- UserCommand {
return user.commands
}
func (user *User) Login(c *Client, nick string, password string) bool { func (user *User) Login(c *Client, nick string, password string) bool {
if nick != c.nick { if nick != c.nick {
return false return false
@ -172,8 +198,7 @@ func (user *User) Login(c *Client, nick string, password string) bool {
c.user = user c.user = user
for channel := range user.channels { for channel := range user.channels {
channel.GetTopic(c) channel.GetTopic(c)
c.Replies() <- RplNamReply(channel) channel.GetUsers(c)
c.Replies() <- RplEndOfNames(channel.server)
} }
return true return true
} }