|
@ -89,7 +89,6 @@ type Client struct { |
|
|
|
|
|
|
|
|
status *Status |
|
|
status *Status |
|
|
targets []Target |
|
|
targets []Target |
|
|
targetIds map[Target]string |
|
|
|
|
|
|
|
|
|
|
|
handlers []Handler |
|
|
handlers []Handler |
|
|
} |
|
|
} |
|
@ -105,13 +104,12 @@ func New(ctx context.Context, config Config) *Client { |
|
|
capEnabled: make(map[string]bool), |
|
|
capEnabled: make(map[string]bool), |
|
|
capData: make(map[string]string), |
|
|
capData: make(map[string]string), |
|
|
config: config.WithDefaults(), |
|
|
config: config.WithDefaults(), |
|
|
targetIds: make(map[Target]string, 16), |
|
|
|
|
|
status: &Status{}, |
|
|
|
|
|
|
|
|
status: &Status{id: generateClientID("T")}, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
client.ctx, client.cancel = context.WithCancel(ctx) |
|
|
client.ctx, client.cancel = context.WithCancel(ctx) |
|
|
|
|
|
|
|
|
_, _ = client.AddTarget(client.status) |
|
|
|
|
|
|
|
|
_ = client.AddTarget(client.status) |
|
|
|
|
|
|
|
|
go client.handleEventLoop() |
|
|
go client.handleEventLoop() |
|
|
go client.handleSendLoop() |
|
|
go client.handleSendLoop() |
|
@ -220,7 +218,7 @@ func (client *Client) State() ClientState { |
|
|
|
|
|
|
|
|
for _, target := range client.targets { |
|
|
for _, target := range client.targets { |
|
|
tstate := target.State() |
|
|
tstate := target.State() |
|
|
tstate.ID = client.targetIds[target] |
|
|
|
|
|
|
|
|
tstate.ID = target.ID() |
|
|
|
|
|
|
|
|
state.Targets = append(state.Targets, tstate) |
|
|
state.Targets = append(state.Targets, tstate) |
|
|
} |
|
|
} |
|
@ -484,7 +482,7 @@ func (client *Client) EmitInput(line string, target Target) context.Context { |
|
|
event := ParseInput(line) |
|
|
event := ParseInput(line) |
|
|
|
|
|
|
|
|
client.mutex.RLock() |
|
|
client.mutex.RLock() |
|
|
if target != nil && client.targetIds[target] == "" { |
|
|
|
|
|
|
|
|
if target != nil && client.TargetByID(target.ID()) == nil { |
|
|
client.EmitNonBlocking(NewErrorEvent("invalid_target", "Target does not exist.")) |
|
|
client.EmitNonBlocking(NewErrorEvent("invalid_target", "Target does not exist.")) |
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background()) |
|
|
ctx, cancel := context.WithCancel(context.Background()) |
|
@ -496,12 +494,10 @@ func (client *Client) EmitInput(line string, target Target) context.Context { |
|
|
if target != nil { |
|
|
if target != nil { |
|
|
client.mutex.RLock() |
|
|
client.mutex.RLock() |
|
|
event.targets = append(event.targets, target) |
|
|
event.targets = append(event.targets, target) |
|
|
event.targetIds[target] = client.targetIds[target] |
|
|
|
|
|
client.mutex.RUnlock() |
|
|
client.mutex.RUnlock() |
|
|
} else { |
|
|
} else { |
|
|
client.mutex.RLock() |
|
|
client.mutex.RLock() |
|
|
event.targets = append(event.targets, client.status) |
|
|
event.targets = append(event.targets, client.status) |
|
|
event.targetIds[client.status] = client.targetIds[client.status] |
|
|
|
|
|
client.mutex.RUnlock() |
|
|
client.mutex.RUnlock() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -594,6 +590,20 @@ func (client *Client) Target(kind string, name string) Target { |
|
|
return nil |
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TargetByID gets a target by kind and name
|
|
|
|
|
|
func (client *Client) TargetByID(id string) Target { |
|
|
|
|
|
client.mutex.RLock() |
|
|
|
|
|
defer client.mutex.RUnlock() |
|
|
|
|
|
|
|
|
|
|
|
for _, target := range client.targets { |
|
|
|
|
|
if target.ID() == id { |
|
|
|
|
|
return target |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Targets gets all targets of the given kinds.
|
|
|
// Targets gets all targets of the given kinds.
|
|
|
func (client *Client) Targets(kinds ...string) []Target { |
|
|
func (client *Client) Targets(kinds ...string) []Target { |
|
|
if len(kinds) == 0 { |
|
|
if len(kinds) == 0 { |
|
@ -658,7 +668,7 @@ func (client *Client) Query(name string) *Query { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// AddTarget adds a target to the client, generating a unique ID for it.
|
|
|
// AddTarget adds a target to the client, generating a unique ID for it.
|
|
|
func (client *Client) AddTarget(target Target) (id string, err error) { |
|
|
|
|
|
|
|
|
func (client *Client) AddTarget(target Target) (err error) { |
|
|
client.mutex.Lock() |
|
|
client.mutex.Lock() |
|
|
defer client.mutex.Unlock() |
|
|
defer client.mutex.Unlock() |
|
|
|
|
|
|
|
@ -672,14 +682,11 @@ func (client *Client) AddTarget(target Target) (id string, err error) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
id = generateClientID("T") |
|
|
|
|
|
client.targets = append(client.targets, target) |
|
|
client.targets = append(client.targets, target) |
|
|
client.targetIds[target] = id |
|
|
|
|
|
|
|
|
|
|
|
event := NewEvent("hook", "add_target") |
|
|
event := NewEvent("hook", "add_target") |
|
|
event.Args = []string{client.targetIds[target], target.Kind(), target.Name()} |
|
|
|
|
|
|
|
|
event.Args = []string{target.ID(), target.Kind(), target.Name()} |
|
|
event.targets = []Target{target} |
|
|
event.targets = []Target{target} |
|
|
event.targetIds[target] = id |
|
|
|
|
|
client.EmitNonBlocking(event) |
|
|
client.EmitNonBlocking(event) |
|
|
|
|
|
|
|
|
return |
|
|
return |
|
@ -696,15 +703,14 @@ func (client *Client) RemoveTarget(target Target) (id string, err error) { |
|
|
|
|
|
|
|
|
for i := range client.targets { |
|
|
for i := range client.targets { |
|
|
if target == client.targets[i] { |
|
|
if target == client.targets[i] { |
|
|
id = client.targetIds[target] |
|
|
|
|
|
|
|
|
id = target.ID() |
|
|
|
|
|
|
|
|
event := NewEvent("hook", "remove_target") |
|
|
event := NewEvent("hook", "remove_target") |
|
|
event.Args = []string{client.targetIds[target], target.Kind(), target.Name()} |
|
|
|
|
|
|
|
|
event.Args = []string{target.ID(), target.Kind(), target.Name()} |
|
|
client.EmitNonBlocking(event) |
|
|
client.EmitNonBlocking(event) |
|
|
|
|
|
|
|
|
client.targets[i] = client.targets[len(client.targets)-1] |
|
|
client.targets[i] = client.targets[len(client.targets)-1] |
|
|
client.targets = client.targets[:len(client.targets)-1] |
|
|
client.targets = client.targets[:len(client.targets)-1] |
|
|
delete(client.targetIds, target) |
|
|
|
|
|
|
|
|
|
|
|
// Ensure the channel has been parted
|
|
|
// Ensure the channel has been parted
|
|
|
if channel, ok := target.(*Channel); ok && !channel.parted { |
|
|
if channel, ok := target.(*Channel); ok && !channel.parted { |
|
@ -1218,8 +1224,12 @@ func (client *Client) handleEvent(event *Event) { |
|
|
var channel *Channel |
|
|
var channel *Channel |
|
|
|
|
|
|
|
|
if event.Nick == client.nick { |
|
|
if event.Nick == client.nick { |
|
|
channel = &Channel{name: event.Arg(0), userlist: list.New(&client.isupport)} |
|
|
|
|
|
_, _ = client.AddTarget(channel) |
|
|
|
|
|
|
|
|
channel = &Channel{ |
|
|
|
|
|
id: generateClientID("T"), |
|
|
|
|
|
name: event.Arg(0), |
|
|
|
|
|
userlist: list.New(&client.isupport), |
|
|
|
|
|
} |
|
|
|
|
|
_ = client.AddTarget(channel) |
|
|
} else { |
|
|
} else { |
|
|
channel = client.Channel(event.Arg(0)) |
|
|
channel = client.Channel(event.Arg(0)) |
|
|
} |
|
|
} |
|
@ -1317,14 +1327,20 @@ func (client *Client) handleEvent(event *Event) { |
|
|
if targetName == client.nick { |
|
|
if targetName == client.nick { |
|
|
target := client.Target("query", targetName) |
|
|
target := client.Target("query", targetName) |
|
|
if target == nil { |
|
|
if target == nil { |
|
|
query := &Query{user: list.User{ |
|
|
|
|
|
|
|
|
query := &Query{ |
|
|
|
|
|
id: client.id, |
|
|
|
|
|
user: list.User{ |
|
|
Nick: event.Nick, |
|
|
Nick: event.Nick, |
|
|
User: event.User, |
|
|
User: event.User, |
|
|
Host: event.Host, |
|
|
Host: event.Host, |
|
|
}} |
|
|
|
|
|
|
|
|
}, |
|
|
|
|
|
} |
|
|
|
|
|
if accountTag, ok := event.Tags["account"]; ok { |
|
|
|
|
|
query.user.Account = accountTag |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
id, _ := client.AddTarget(query) |
|
|
|
|
|
event.RenderTags["spawned"] = id |
|
|
|
|
|
|
|
|
_ = client.AddTarget(query) |
|
|
|
|
|
event.RenderTags["spawned"] = query.id |
|
|
|
|
|
|
|
|
target = query |
|
|
target = query |
|
|
} |
|
|
} |
|
@ -1406,7 +1422,6 @@ func (client *Client) handleEvent(event *Event) { |
|
|
channels = append(channels, channel.Name()) |
|
|
channels = append(channels, channel.Name()) |
|
|
|
|
|
|
|
|
rejoinEvent.targets = append(rejoinEvent.targets, target) |
|
|
rejoinEvent.targets = append(rejoinEvent.targets, target) |
|
|
rejoinEvent.targetIds[target] = client.targetIds[target] |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
client.mutex.RUnlock() |
|
|
client.mutex.RUnlock() |
|
@ -1452,7 +1467,6 @@ func (client *Client) handleInTargets(nick string, event *Event) { |
|
|
target.Handle(event, client) |
|
|
target.Handle(event, client) |
|
|
|
|
|
|
|
|
event.targets = append(event.targets, target) |
|
|
event.targets = append(event.targets, target) |
|
|
event.targetIds[target] = client.targetIds[target] |
|
|
|
|
|
} |
|
|
} |
|
|
case *Query: |
|
|
case *Query: |
|
|
{ |
|
|
{ |
|
@ -1460,7 +1474,6 @@ func (client *Client) handleInTargets(nick string, event *Event) { |
|
|
target.Handle(event, client) |
|
|
target.Handle(event, client) |
|
|
|
|
|
|
|
|
event.targets = append(event.targets, target) |
|
|
event.targets = append(event.targets, target) |
|
|
event.targetIds[target] = client.targetIds[target] |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
case *Status: |
|
|
case *Status: |
|
@ -1469,7 +1482,6 @@ func (client *Client) handleInTargets(nick string, event *Event) { |
|
|
target.Handle(event, client) |
|
|
target.Handle(event, client) |
|
|
|
|
|
|
|
|
event.targets = append(event.targets, target) |
|
|
event.targets = append(event.targets, target) |
|
|
event.targetIds[target] = client.targetIds[target] |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -1488,7 +1500,6 @@ func (client *Client) handleInTarget(target Target, event *Event) { |
|
|
target.Handle(event, client) |
|
|
target.Handle(event, client) |
|
|
|
|
|
|
|
|
event.targets = append(event.targets, target) |
|
|
event.targets = append(event.targets, target) |
|
|
event.targetIds[target] = client.targetIds[target] |
|
|
|
|
|
|
|
|
|
|
|
client.mutex.RUnlock() |
|
|
client.mutex.RUnlock() |
|
|
} |
|
|
} |
|
|