diff --git a/client.go b/client.go index e0dd5be..aeb5772 100644 --- a/client.go +++ b/client.go @@ -255,7 +255,7 @@ func (client *Client) Connect(addr string, ssl bool) (err error) { }) if err != nil { if !client.Destroyed() { - client.EmitNonBlocking(NewErrorEvent("connect", "Connect failed: "+err.Error())) + client.EmitNonBlocking(NewErrorEvent("connect", "TLS connect failed: "+err.Error(), "connect_failed_tls", err)) } return err } @@ -263,7 +263,7 @@ func (client *Client) Connect(addr string, ssl bool) (err error) { conn, err = net.Dial("tcp", addr) if err != nil { if !client.Destroyed() { - client.EmitNonBlocking(NewErrorEvent("connect", "Connect failed: "+err.Error())) + client.EmitNonBlocking(NewErrorEvent("connect", "Connect failed: "+err.Error(), "connect_failed", err)) } return err } @@ -283,7 +283,7 @@ func (client *Client) Connect(addr string, ssl bool) (err error) { for { line, err := reader.ReadString('\n') if err != nil { - client.EmitNonBlocking(NewErrorEvent("read", "Read failed: "+err.Error())) + client.EmitNonBlocking(NewErrorEvent("read", "Read failed: "+err.Error(), "read_failed", err)) break } line = replacer.Replace(line) @@ -295,7 +295,7 @@ func (client *Client) Connect(addr string, ssl bool) (err error) { client.mutex.RUnlock() if !hasQuit { - client.EmitNonBlocking(NewErrorEvent("parse", "Read failed: "+err.Error())) + client.EmitNonBlocking(NewErrorEvent("parse", "Parse failed: "+err.Error(), "parse_failed", err)) } continue } @@ -366,7 +366,7 @@ func (client *Client) Send(line string) error { _ = conn.SetWriteDeadline(time.Now().Add(time.Second * 30)) _, err := conn.Write([]byte(line)) if err != nil { - client.EmitNonBlocking(NewErrorEvent("write", err.Error())) + client.EmitNonBlocking(NewErrorEvent("write", "Write failed:"+err.Error(), "connect_failed", err)) _ = client.Disconnect(false) } @@ -508,7 +508,7 @@ func (client *Client) EmitInput(line string, target Target) context.Context { client.mutex.RLock() if target != nil && client.TargetByID(target.ID()) == nil { - client.EmitNonBlocking(NewErrorEvent("invalid_target", "Target does not exist.")) + client.EmitNonBlocking(NewErrorEvent("target", "Target does not exist.", "target_do_not_exist", nil)) ctx, cancel := context.WithCancel(context.Background()) cancel() diff --git a/event_error.go b/event_error.go index b31f665..1880cbf 100644 --- a/event_error.go +++ b/event_error.go @@ -2,9 +2,24 @@ package irc // NewErrorEvent makes an event of kind `error` and verb `code` with the text. // It's absolutely trivial, but it's good to have standarized. -func NewErrorEvent(code, text string) Event { +func NewErrorEvent(code, text, i18nKey string, raw error) Event { + return NewErrorEventTarget(nil, code, text, i18nKey, raw) +} + +func NewErrorEventTarget(target Target, code, text, i18nKey string, raw error) Event { event := NewEvent("error", code) event.Text = text + if target != nil { + event.targets = append(event.targets, target) + } + + if i18nKey != "" { + event.Tags["i18n_key"] = i18nKey + } + if raw != nil { + event.Tags["raw"] = raw.Error() + } + return event } diff --git a/handlers/ctcp.go b/handlers/ctcp.go index 46c7bca..fe05511 100644 --- a/handlers/ctcp.go +++ b/handlers/ctcp.go @@ -52,7 +52,7 @@ func CTCP(event *irc.Event, client *irc.Client) { args := strings.SplitN(event.Text, " ", 2) targetName := args[0] if targetName == "" { - client.EmitNonBlocking(irc.NewErrorEvent("ctcp.pingarg", "/ping needs an argument")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "/ping needs an argument", "usage_ping", nil)) break } diff --git a/handlers/input.go b/handlers/input.go index a1a3436..7118621 100644 --- a/handlers/input.go +++ b/handlers/input.go @@ -17,7 +17,7 @@ func Input(event *irc.Event, client *irc.Client) { targetName, text := ircutil.ParseArgAndText(event.Text) if targetName == "" || text == "" { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /msg ")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /msg ", "usage_msg", nil)) break } @@ -34,13 +34,13 @@ func Input(event *irc.Event, client *irc.Client) { event.PreventDefault() if event.Text == "" { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /text ")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /text ", "usage_text", nil)) break } target := event.Target("query", "channel") if target == nil { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel or query")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Target is not a channel or query", "target_not_channel_or_query", nil)) break } @@ -57,13 +57,13 @@ func Input(event *irc.Event, client *irc.Client) { event.PreventDefault() if event.Text == "" { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /me ")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /me ", "usage_me", nil)) break } target := event.Target("query", "channel") if target == nil { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel or query")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Target is not a channel or query", "target_not_channel_or_query", nil)) break } @@ -93,7 +93,7 @@ func Input(event *irc.Event, client *irc.Client) { targetName, text := ircutil.ParseArgAndText(event.Text) if targetName == "" || text == "" { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /describe ")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /describe ", "usage_describe", nil)) break } @@ -122,7 +122,7 @@ func Input(event *irc.Event, client *irc.Client) { event.PreventDefault() if event.Text == "" { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /m ")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /m ", "usage_m", nil)) break } @@ -131,7 +131,7 @@ func Input(event *irc.Event, client *irc.Client) { } else if status := event.StatusTarget(); status != nil { client.SendQueuedf("MODE %s %s", client.Nick(), event.Text) } else { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel or status")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Target is not a channel or status", "channel_not_channel_or_status", nil)) } } diff --git a/handlers/mroleplay.go b/handlers/mroleplay.go index 62981ff..9fe080a 100644 --- a/handlers/mroleplay.go +++ b/handlers/mroleplay.go @@ -70,13 +70,13 @@ func MRoleplay(event *irc.Event, client *irc.Client) { isAction := event.Verb() == "npcac" nick, text := ircutil.ParseArgAndText(event.Text) if nick == "" || text == "" { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /"+event.Verb()+" ")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /"+event.Verb()+" ", "usage_"+event.Verb(), nil)) break } channel := event.ChannelTarget() if channel == nil { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Target is not a channel", "target_not_channel", nil)) break } @@ -99,13 +99,13 @@ func MRoleplay(event *irc.Event, client *irc.Client) { case "input.scenec", "input.narratorc": { if event.Text == "" { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /"+event.Verb()+" ")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /"+event.Verb()+" ", "usage_"+event.Verb(), nil)) break } channel := event.ChannelTarget() if channel == nil { - client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel")) + client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Target is not a channel", "target_not_channel", nil)) break }