mirror of
https://github.com/gissleh/irc.git
synced 2026-10-15 17:42:53 +00:00
Added input handling and m_roleplay client-side handlers (...)
- Added Client.EmitInput() - Added ircutil.ParseArgAndText for common /msg <target> <message...> type inputs - Added target getters for Event - Added default handling for input events that haven't been killed - Removed handler_debug - Changed timeout for interaction to 2s - Fixed comment typo in event_packet.go
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"git.aiterp.net/gisle/irc"
|
||||
"git.aiterp.net/gisle/irc/ircutil"
|
||||
)
|
||||
|
||||
// Input handles the default input.
|
||||
func Input(event *irc.Event, client *irc.Client) {
|
||||
switch event.Name() {
|
||||
|
||||
// /msg sends an action to a target specified before the message.
|
||||
case "input.msg":
|
||||
{
|
||||
targetName, text := ircutil.ParseArgAndText(event.Text)
|
||||
if targetName == "" || text == "" {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /msg <target> <text...>"))
|
||||
break
|
||||
}
|
||||
|
||||
overhead := client.PrivmsgOverhead(targetName, true)
|
||||
cuts := ircutil.CutMessage(text, overhead)
|
||||
for _, cut := range cuts {
|
||||
client.Sendf("PRIVMSG %s :%s", targetName, cut)
|
||||
}
|
||||
|
||||
event.Kill()
|
||||
}
|
||||
|
||||
// /text (or text without a command) sends a message to the target.
|
||||
case "input.text":
|
||||
{
|
||||
if event.Text == "" {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /text <text...>"))
|
||||
break
|
||||
}
|
||||
|
||||
target := event.Target("query", "channel")
|
||||
if target == nil {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel or query"))
|
||||
break
|
||||
}
|
||||
|
||||
overhead := client.PrivmsgOverhead(target.Name(), false)
|
||||
cuts := ircutil.CutMessage(event.Text, overhead)
|
||||
for _, cut := range cuts {
|
||||
client.SendQueuedf("PRIVMSG %s :%s", target.Name(), cut)
|
||||
}
|
||||
|
||||
event.Kill()
|
||||
}
|
||||
|
||||
// /me and /action sends a CTCP ACTION.
|
||||
case "input.me", "input.action":
|
||||
{
|
||||
if event.Text == "" {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /me <text...>"))
|
||||
break
|
||||
}
|
||||
|
||||
target := event.Target("query", "channel")
|
||||
if target == nil {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel or query"))
|
||||
break
|
||||
}
|
||||
|
||||
overhead := client.PrivmsgOverhead(target.Name(), true)
|
||||
cuts := ircutil.CutMessage(event.Text, overhead)
|
||||
for _, cut := range cuts {
|
||||
client.SendCTCP("ACTION", target.Name(), false, cut)
|
||||
}
|
||||
|
||||
event.Kill()
|
||||
}
|
||||
|
||||
// /describe sends an action to a target specified before the message, like /msg.
|
||||
case "input.describe":
|
||||
{
|
||||
targetName, text := ircutil.ParseArgAndText(event.Text)
|
||||
if targetName == "" || text == "" {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /describe <target> <text...>"))
|
||||
break
|
||||
}
|
||||
|
||||
overhead := client.PrivmsgOverhead(targetName, true)
|
||||
cuts := ircutil.CutMessage(text, overhead)
|
||||
for _, cut := range cuts {
|
||||
client.SendCTCP("ACTION", targetName, false, cut)
|
||||
}
|
||||
|
||||
event.Kill()
|
||||
}
|
||||
|
||||
// /m is a shorthand for /mode that targets the current channel
|
||||
case "input.m":
|
||||
{
|
||||
if event.Text == "" {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /m <text...>"))
|
||||
break
|
||||
}
|
||||
|
||||
channel := event.ChannelTarget()
|
||||
if channel != nil {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel"))
|
||||
break
|
||||
}
|
||||
|
||||
client.SendQueuedf("MODE %s %s", channel.Name(), event.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/gisle/irc"
|
||||
"git.aiterp.net/gisle/irc/ircutil"
|
||||
)
|
||||
|
||||
// MRoleplay is a handler that adds commands for cutting NPC commands, as well as cleaning up
|
||||
// the input from the server. It's named after Charybdis IRCd's m_roleplay module.
|
||||
func MRoleplay(event *irc.Event, client *irc.Client) {
|
||||
switch event.Name() {
|
||||
case "packet.privmsg", "ctcp.action":
|
||||
{
|
||||
// Detect m_roleplay
|
||||
if strings.HasPrefix(event.Nick, "\x1F") {
|
||||
event.Nick = event.Nick[1 : len(event.Nick)-2]
|
||||
if event.Verb() == "PRIVMSG" {
|
||||
event.RenderTags["mRoleplay"] = "npc"
|
||||
} else {
|
||||
event.RenderTags["mRoleplay"] = "npca"
|
||||
}
|
||||
} else if strings.HasPrefix(event.Nick, "=") {
|
||||
event.RenderTags["mRoleplay"] = "scene"
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
||||
lastSpace := strings.LastIndex(event.Text, " ")
|
||||
lastParanthesis := strings.LastIndex(event.Text, "(")
|
||||
if lastParanthesis != -1 && lastSpace != -1 && lastParanthesis == lastSpace+1 {
|
||||
event.Text = event.Text[:lastSpace]
|
||||
}
|
||||
}
|
||||
case "input.npcc", "input.npcac":
|
||||
{
|
||||
isAction := event.Verb() == "npcac"
|
||||
nick, text := ircutil.ParseArgAndText(event.Text)
|
||||
if nick == "" || text == "" {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /"+event.Verb()+" <nick> <text...>"))
|
||||
break
|
||||
}
|
||||
|
||||
channel := event.ChannelTarget()
|
||||
if channel == nil {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel"))
|
||||
break
|
||||
}
|
||||
|
||||
overhead := ircutil.MessageOverhead("\x1f"+nick+"\x1f", client.Nick(), "npc.fakeuser.invalid", channel.Name(), isAction)
|
||||
cuts := ircutil.CutMessage(event.Text, overhead)
|
||||
|
||||
for _, cut := range cuts {
|
||||
npcCommand := "NPCA"
|
||||
if event.Verb() == "npcc" {
|
||||
npcCommand = "NPC"
|
||||
}
|
||||
|
||||
client.SendQueuedf("%s %s :%s", npcCommand, channel.Name(), cut)
|
||||
}
|
||||
|
||||
event.Kill()
|
||||
}
|
||||
case "input.scenec":
|
||||
{
|
||||
if event.Text == "" {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Usage: /scenec <text...>"))
|
||||
break
|
||||
}
|
||||
|
||||
channel := event.ChannelTarget()
|
||||
if channel == nil {
|
||||
client.EmitNonBlocking(irc.NewErrorEvent("input", "Target is not a channel"))
|
||||
break
|
||||
}
|
||||
|
||||
overhead := ircutil.MessageOverhead("=Scene=", client.Nick(), "npc.fakeuser.invalid", channel.Name(), false)
|
||||
cuts := ircutil.CutMessage(event.Text, overhead)
|
||||
for _, cut := range cuts {
|
||||
client.SendQueuedf("SCENE %s :%s", channel.Name(), cut)
|
||||
}
|
||||
|
||||
event.Kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Package handlers contain extra handlers that add features to an IRC client that are not
|
||||
// always necessary. This includes most input handlers and features. If something adds
|
||||
// a IRCv3 cap, it should not be here, however.
|
||||
package handlers
|
||||
Reference in New Issue
Block a user