mirror of
https://github.com/gissleh/irc.git
synced 2026-09-29 00:25:33 +00:00
This commit is contained in:
@@ -8,11 +8,17 @@ import (
|
|||||||
|
|
||||||
// A Channel is a target that manages the userlist
|
// A Channel is a target that manages the userlist
|
||||||
type Channel struct {
|
type Channel struct {
|
||||||
|
id string
|
||||||
name string
|
name string
|
||||||
userlist *list.List
|
userlist *list.List
|
||||||
parted bool
|
parted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ID returns a unique ID for the channel target.
|
||||||
|
func (channel *Channel) ID() string {
|
||||||
|
return channel.id
|
||||||
|
}
|
||||||
|
|
||||||
// Kind returns "channel"
|
// Kind returns "channel"
|
||||||
func (channel *Channel) Kind() string {
|
func (channel *Channel) Kind() string {
|
||||||
return "channel"
|
return "channel"
|
||||||
|
|||||||
@@ -87,9 +87,8 @@ type Client struct {
|
|||||||
isupport isupport.ISupport
|
isupport isupport.ISupport
|
||||||
values map[string]interface{}
|
values map[string]interface{}
|
||||||
|
|
||||||
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{id: generateClientID("T")},
|
||||||
status: &Status{},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)}
|
channel = &Channel{
|
||||||
_, _ = client.AddTarget(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{
|
||||||
Nick: event.Nick,
|
id: client.id,
|
||||||
User: event.User,
|
user: list.User{
|
||||||
Host: event.Host,
|
Nick: event.Nick,
|
||||||
}}
|
User: event.User,
|
||||||
|
Host: event.Host,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if accountTag, ok := event.Tags["account"]; ok {
|
||||||
|
query.user.Account = accountTag
|
||||||
|
}
|
||||||
|
|
||||||
id, _ := client.AddTarget(query)
|
_ = client.AddTarget(query)
|
||||||
event.RenderTags["spawned"] = id
|
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()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ func main() {
|
|||||||
|
|
||||||
err := client.Connect(*flagServer, *flagSsl)
|
err := client.Connect(*flagServer, *flagSsl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Failed to connect: %s", err)
|
_, _ = fmt.Fprintf(os.Stderr, "Failed to connect: %s", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ type Event struct {
|
|||||||
preventedDefault bool
|
preventedDefault bool
|
||||||
hidden bool
|
hidden bool
|
||||||
|
|
||||||
targets []Target
|
targets []Target
|
||||||
targetIds map[Target]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEvent makes a new event with Kind, Verb, Time set and Args and Tags initialized.
|
// NewEvent makes a new event with Kind, Verb, Time set and Args and Tags initialized.
|
||||||
@@ -42,8 +41,6 @@ func NewEvent(kind, verb string) Event {
|
|||||||
Args: make([]string, 0, 4),
|
Args: make([]string, 0, 4),
|
||||||
Tags: make(map[string]string),
|
Tags: make(map[string]string),
|
||||||
|
|
||||||
targetIds: make(map[Target]string),
|
|
||||||
|
|
||||||
RenderTags: make(map[string]string),
|
RenderTags: make(map[string]string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +89,7 @@ func (event *Event) Context() context.Context {
|
|||||||
// the current event handler returns.
|
// the current event handler returns.
|
||||||
//
|
//
|
||||||
// A use case for this is to prevent the default input handler from firing
|
// A use case for this is to prevent the default input handler from firing
|
||||||
// on an already prcoessed input event.
|
// on an already processed input event.
|
||||||
func (event *Event) PreventDefault() {
|
func (event *Event) PreventDefault() {
|
||||||
event.preventedDefault = true
|
event.preventedDefault = true
|
||||||
}
|
}
|
||||||
@@ -177,8 +174,8 @@ func (event *Event) StatusTarget() *Status {
|
|||||||
|
|
||||||
func (event *Event) TargetIDs() []string {
|
func (event *Event) TargetIDs() []string {
|
||||||
ids := make([]string, len(event.targets))
|
ids := make([]string, len(event.targets))
|
||||||
for _, value := range event.targetIds {
|
for _, target := range event.targets {
|
||||||
ids = append(ids, value)
|
ids = append(ids, target.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return ids
|
return ids
|
||||||
@@ -202,7 +199,7 @@ func (event *Event) MarshalJSON() ([]byte, error) {
|
|||||||
|
|
||||||
data.Targets = make([]string, 0, len(event.targets))
|
data.Targets = make([]string, 0, len(event.targets))
|
||||||
for _, target := range event.targets {
|
for _, target := range event.targets {
|
||||||
data.Targets = append(data.Targets, event.targetIds[target])
|
data.Targets = append(data.Targets, target.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.Marshal(data)
|
return json.Marshal(data)
|
||||||
|
|||||||
@@ -6,9 +6,15 @@ import (
|
|||||||
|
|
||||||
// A Query is a target for direct messages to and from a specific nick.
|
// A Query is a target for direct messages to and from a specific nick.
|
||||||
type Query struct {
|
type Query struct {
|
||||||
|
id string
|
||||||
user list.User
|
user list.User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ID returns a unique ID for the channel target.
|
||||||
|
func (query *Query) ID() string {
|
||||||
|
return query.id
|
||||||
|
}
|
||||||
|
|
||||||
// Kind returns "channel"
|
// Kind returns "channel"
|
||||||
func (query *Query) Kind() string {
|
func (query *Query) Kind() string {
|
||||||
return "query"
|
return "query"
|
||||||
|
|||||||
@@ -2,6 +2,12 @@ package irc
|
|||||||
|
|
||||||
// A Status contains
|
// A Status contains
|
||||||
type Status struct {
|
type Status struct {
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns a unique ID for the status target.
|
||||||
|
func (status *Status) ID() string {
|
||||||
|
return status.id
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kind returns "status"
|
// Kind returns "status"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package irc
|
|||||||
// A Target is a handler for a message meant for a limited part of the client, like a channel or
|
// A Target is a handler for a message meant for a limited part of the client, like a channel or
|
||||||
// query
|
// query
|
||||||
type Target interface {
|
type Target interface {
|
||||||
|
ID() string
|
||||||
Kind() string
|
Kind() string
|
||||||
Name() string
|
Name() string
|
||||||
Handle(event *Event, client *Client)
|
Handle(event *Event, client *Client)
|
||||||
|
|||||||
Reference in New Issue
Block a user