Mirror of github.com/gissleh/irc
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
3.3 KiB

package irc
import (
"strings"
"github.com/gissleh/irc/list"
)
// A Channel is a target that manages the userlist
type Channel struct {
id string
name string
userlist *list.List
parted bool
}
// ID returns a unique ID for the channel target.
func (channel *Channel) ID() string {
return channel.id
}
// Kind returns "channel"
func (channel *Channel) Kind() string {
return "channel"
}
// Name gets the channel name
func (channel *Channel) Name() string {
return channel.name
}
func (channel *Channel) State() ClientStateTarget {
return ClientStateTarget{
Kind: "channel",
Name: channel.name,
Users: channel.userlist.Users(),
}
}
// UserList gets the channel userlist
func (channel *Channel) UserList() list.Immutable {
return channel.userlist.Immutable()
}
// Parted returnes whether the channel has been parted
func (channel *Channel) Parted() bool {
return channel.parted
}
// AddHandler handles messages routed to this channel by the client's event loop
func (channel *Channel) Handle(event *Event, client *Client) {
switch event.Name() {
case "packet.join":
{
// Support extended-join
account := ""
if accountArg := event.Arg(1); accountArg != "" && accountArg != "*" {
account = accountArg
}
channel.userlist.Insert(list.User{
Nick: event.Nick,
User: event.User,
Host: event.Host,
Account: account,
})
}
case "packet.part", "packet.quit":
{
channel.userlist.Remove(event.Nick)
}
case "packet.kick":
{
channel.userlist.Remove(event.Arg(1))
}
case "packet.nick":
{
channel.userlist.Rename(event.Nick, event.Arg(0))
}
case "packet.account":
{
newAccount := event.Arg(0)
if newAccount != "*" && newAccount != "" {
channel.userlist.Patch(event.Nick, list.UserPatch{Account: newAccount})
} else {
channel.userlist.Patch(event.Nick, list.UserPatch{ClearAccount: true})
}
}
case "packet.away":
{
if event.Text != "" {
channel.userlist.Patch(event.Nick, list.UserPatch{Away: event.Text})
} else {
channel.userlist.Patch(event.Nick, list.UserPatch{ClearAway: true})
}
}
case "packet.chghost":
{
newUser := event.Arg(0)
newHost := event.Arg(1)
channel.userlist.Patch(event.Nick, list.UserPatch{User: newUser, Host: newHost})
}
case "packet.353": // NAMES
{
channel.userlist.SetAutoSort(false)
tokens := strings.Split(event.Text, " ")
for _, token := range tokens {
channel.userlist.InsertFromNamesToken(token)
}
}
case "packet.366": // End of NAMES
{
channel.userlist.SetAutoSort(true)
}
case "packet.mode":
{
isupport := client.ISupport()
plus := false
argIndex := 2
for _, ch := range event.Arg(1) {
if ch == '+' {
plus = true
continue
}
if ch == '-' {
plus = false
continue
}
arg := ""
if isupport.ModeTakesArgument(ch, plus) {
arg = event.Arg(argIndex)
argIndex++
}
if isupport.IsPermissionMode(ch) {
if plus {
channel.userlist.AddMode(arg, ch)
} else {
channel.userlist.RemoveMode(arg, ch)
}
} else {
// TODO: track non-permission modes
}
}
}
case "packet.privmsg", "ctcp.action":
{
if accountTag, ok := event.Tags["account"]; ok && accountTag != "" {
channel.userlist.Patch(event.Nick, list.UserPatch{Account: accountTag})
}
}
}
}