mirror of
https://github.com/ergochat/ergo.git
synced 2025-12-20 02:00:11 -08:00
Merge remote-tracking branch 'origin/master' into cleanup
Conflicts: irc/client.go irc/commands.go irc/constants.go irc/reply.go irc/server.go irc/types.go
This commit is contained in:
commit
39b7c2a915
12 changed files with 323 additions and 268 deletions
235
irc/commands.go
235
irc/commands.go
|
|
@ -1,7 +1,6 @@
|
|||
package irc
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.text/unicode/norm"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
|
@ -115,14 +114,14 @@ func ParseLine(line string) (command StringCode, args []string) {
|
|||
_, line = splitArg(line)
|
||||
}
|
||||
arg, line := splitArg(line)
|
||||
command = StringCode(strings.ToUpper(arg))
|
||||
command = StringCode(NewName(strings.ToUpper(arg)))
|
||||
for len(line) > 0 {
|
||||
if strings.HasPrefix(line, ":") {
|
||||
args = append(args, norm.NFC.String(line[len(":"):]))
|
||||
args = append(args, line[len(":"):])
|
||||
break
|
||||
}
|
||||
arg, line = splitArg(line)
|
||||
args = append(args, norm.NFKC.String(arg))
|
||||
args = append(args, arg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -148,8 +147,8 @@ func NewUnknownCommand(args []string) *UnknownCommand {
|
|||
|
||||
type PingCommand struct {
|
||||
BaseCommand
|
||||
server string
|
||||
server2 string
|
||||
server Name
|
||||
server2 Name
|
||||
}
|
||||
|
||||
func (cmd *PingCommand) String() string {
|
||||
|
|
@ -161,10 +160,10 @@ func NewPingCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
msg := &PingCommand{
|
||||
server: args[0],
|
||||
server: NewName(args[0]),
|
||||
}
|
||||
if len(args) > 1 {
|
||||
msg.server2 = args[1]
|
||||
msg.server2 = NewName(args[1])
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
|
@ -173,8 +172,8 @@ func NewPingCommand(args []string) (Command, error) {
|
|||
|
||||
type PongCommand struct {
|
||||
BaseCommand
|
||||
server1 string
|
||||
server2 string
|
||||
server1 Name
|
||||
server2 Name
|
||||
}
|
||||
|
||||
func (cmd *PongCommand) String() string {
|
||||
|
|
@ -186,10 +185,10 @@ func NewPongCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
message := &PongCommand{
|
||||
server1: args[0],
|
||||
server1: NewName(args[0]),
|
||||
}
|
||||
if len(args) > 1 {
|
||||
message.server2 = args[1]
|
||||
message.server2 = NewName(args[1])
|
||||
}
|
||||
return message, nil
|
||||
}
|
||||
|
|
@ -231,7 +230,7 @@ func NewPassCommand(args []string) (Command, error) {
|
|||
|
||||
type NickCommand struct {
|
||||
BaseCommand
|
||||
nickname string
|
||||
nickname Name
|
||||
}
|
||||
|
||||
func (m *NickCommand) String() string {
|
||||
|
|
@ -243,21 +242,21 @@ func NewNickCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
return &NickCommand{
|
||||
nickname: args[0],
|
||||
nickname: NewName(args[0]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type UserCommand struct {
|
||||
BaseCommand
|
||||
username string
|
||||
realname string
|
||||
username Name
|
||||
realname Text
|
||||
}
|
||||
|
||||
// USER <username> <hostname> <servername> <realname>
|
||||
type RFC1459UserCommand struct {
|
||||
UserCommand
|
||||
hostname string
|
||||
servername string
|
||||
hostname Name
|
||||
servername Name
|
||||
}
|
||||
|
||||
func (cmd *RFC1459UserCommand) String() string {
|
||||
|
|
@ -298,17 +297,17 @@ func NewUserCommand(args []string) (Command, error) {
|
|||
mode: uint8(mode),
|
||||
unused: args[2],
|
||||
}
|
||||
msg.username = args[0]
|
||||
msg.realname = args[3]
|
||||
msg.username = NewName(args[0])
|
||||
msg.realname = NewText(args[3])
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
msg := &RFC1459UserCommand{
|
||||
hostname: args[1],
|
||||
servername: args[2],
|
||||
hostname: NewName(args[1]),
|
||||
servername: NewName(args[2]),
|
||||
}
|
||||
msg.username = args[0]
|
||||
msg.realname = args[3]
|
||||
msg.username = NewName(args[0])
|
||||
msg.realname = NewText(args[3])
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +315,7 @@ func NewUserCommand(args []string) (Command, error) {
|
|||
|
||||
type QuitCommand struct {
|
||||
BaseCommand
|
||||
message string
|
||||
message Text
|
||||
}
|
||||
|
||||
func (cmd *QuitCommand) String() string {
|
||||
|
|
@ -326,7 +325,7 @@ func (cmd *QuitCommand) String() string {
|
|||
func NewQuitCommand(args []string) (Command, error) {
|
||||
msg := &QuitCommand{}
|
||||
if len(args) > 0 {
|
||||
msg.message = args[0]
|
||||
msg.message = NewText(args[0])
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
|
@ -335,7 +334,7 @@ func NewQuitCommand(args []string) (Command, error) {
|
|||
|
||||
type JoinCommand struct {
|
||||
BaseCommand
|
||||
channels map[string]string
|
||||
channels map[Name]Text
|
||||
zero bool
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +344,7 @@ func (cmd *JoinCommand) String() string {
|
|||
|
||||
func NewJoinCommand(args []string) (Command, error) {
|
||||
msg := &JoinCommand{
|
||||
channels: make(map[string]string),
|
||||
channels: make(map[Name]Text),
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
|
|
@ -365,7 +364,7 @@ func NewJoinCommand(args []string) (Command, error) {
|
|||
}
|
||||
}
|
||||
for i, channel := range channels {
|
||||
msg.channels[channel] = keys[i]
|
||||
msg.channels[NewName(channel)] = NewText(keys[i])
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
|
|
@ -375,13 +374,13 @@ func NewJoinCommand(args []string) (Command, error) {
|
|||
|
||||
type PartCommand struct {
|
||||
BaseCommand
|
||||
channels []string
|
||||
message string
|
||||
channels []Name
|
||||
message Text
|
||||
}
|
||||
|
||||
func (cmd *PartCommand) Message() string {
|
||||
func (cmd *PartCommand) Message() Text {
|
||||
if cmd.message == "" {
|
||||
return cmd.Client().Nick()
|
||||
return cmd.Client().Nick().Text()
|
||||
}
|
||||
return cmd.message
|
||||
}
|
||||
|
|
@ -395,10 +394,10 @@ func NewPartCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
msg := &PartCommand{
|
||||
channels: strings.Split(args[0], ","),
|
||||
channels: NewNames(strings.Split(args[0], ",")),
|
||||
}
|
||||
if len(args) > 1 {
|
||||
msg.message = args[1]
|
||||
msg.message = NewText(args[1])
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
|
@ -407,8 +406,8 @@ func NewPartCommand(args []string) (Command, error) {
|
|||
|
||||
type PrivMsgCommand struct {
|
||||
BaseCommand
|
||||
target string
|
||||
message string
|
||||
target Name
|
||||
message Text
|
||||
}
|
||||
|
||||
func (cmd *PrivMsgCommand) String() string {
|
||||
|
|
@ -420,8 +419,8 @@ func NewPrivMsgCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
return &PrivMsgCommand{
|
||||
target: args[0],
|
||||
message: args[1],
|
||||
target: NewName(args[0]),
|
||||
message: NewText(args[1]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -429,9 +428,9 @@ func NewPrivMsgCommand(args []string) (Command, error) {
|
|||
|
||||
type TopicCommand struct {
|
||||
BaseCommand
|
||||
channel string
|
||||
channel Name
|
||||
setTopic bool
|
||||
topic string
|
||||
topic Text
|
||||
}
|
||||
|
||||
func (cmd *TopicCommand) String() string {
|
||||
|
|
@ -443,11 +442,11 @@ func NewTopicCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
msg := &TopicCommand{
|
||||
channel: args[0],
|
||||
channel: NewName(args[0]),
|
||||
}
|
||||
if len(args) > 1 {
|
||||
msg.setTopic = true
|
||||
msg.topic = args[1]
|
||||
msg.topic = NewText(args[1])
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
|
@ -483,18 +482,18 @@ func (changes ModeChanges) String() string {
|
|||
|
||||
type ModeCommand struct {
|
||||
BaseCommand
|
||||
nickname string
|
||||
nickname Name
|
||||
changes ModeChanges
|
||||
}
|
||||
|
||||
// MODE <nickname> *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
|
||||
func NewUserModeCommand(args []string) (Command, error) {
|
||||
func NewUserModeCommand(nickname Name, args []string) (Command, error) {
|
||||
cmd := &ModeCommand{
|
||||
nickname: args[0],
|
||||
nickname: nickname,
|
||||
changes: make(ModeChanges, 0),
|
||||
}
|
||||
|
||||
for _, modeChange := range args[1:] {
|
||||
for _, modeChange := range args {
|
||||
if len(modeChange) == 0 {
|
||||
continue
|
||||
}
|
||||
|
|
@ -560,17 +559,16 @@ func (changes ChannelModeChanges) String() (str string) {
|
|||
|
||||
type ChannelModeCommand struct {
|
||||
BaseCommand
|
||||
channel string
|
||||
channel Name
|
||||
changes ChannelModeChanges
|
||||
}
|
||||
|
||||
// MODE <channel> *( ( "-" / "+" ) *<modes> *<modeparams> )
|
||||
func NewChannelModeCommand(args []string) (Command, error) {
|
||||
func NewChannelModeCommand(channel Name, args []string) (Command, error) {
|
||||
cmd := &ChannelModeCommand{
|
||||
channel: args[0],
|
||||
channel: channel,
|
||||
changes: make(ChannelModeChanges, 0),
|
||||
}
|
||||
args = args[1:]
|
||||
|
||||
for len(args) > 0 {
|
||||
if len(args[0]) == 0 {
|
||||
|
|
@ -617,17 +615,18 @@ func NewModeCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
|
||||
if IsChannel(args[0]) {
|
||||
return NewChannelModeCommand(args)
|
||||
name := NewName(args[0])
|
||||
if name.IsChannel() {
|
||||
return NewChannelModeCommand(name, args[1:])
|
||||
} else {
|
||||
return NewUserModeCommand(args)
|
||||
return NewUserModeCommand(name, args[1:])
|
||||
}
|
||||
}
|
||||
|
||||
type WhoisCommand struct {
|
||||
BaseCommand
|
||||
target string
|
||||
masks []string
|
||||
target Name
|
||||
masks []Name
|
||||
}
|
||||
|
||||
// WHOIS [ <target> ] <mask> *( "," <mask> )
|
||||
|
|
@ -647,8 +646,8 @@ func NewWhoisCommand(args []string) (Command, error) {
|
|||
}
|
||||
|
||||
return &WhoisCommand{
|
||||
target: target,
|
||||
masks: strings.Split(masks, ","),
|
||||
target: NewName(target),
|
||||
masks: NewNames(strings.Split(masks, ",")),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -658,7 +657,7 @@ func (msg *WhoisCommand) String() string {
|
|||
|
||||
type WhoCommand struct {
|
||||
BaseCommand
|
||||
mask string
|
||||
mask Name
|
||||
operatorOnly bool
|
||||
}
|
||||
|
||||
|
|
@ -667,7 +666,7 @@ func NewWhoCommand(args []string) (Command, error) {
|
|||
cmd := &WhoCommand{}
|
||||
|
||||
if len(args) > 0 {
|
||||
cmd.mask = args[0]
|
||||
cmd.mask = NewName(args[0])
|
||||
}
|
||||
|
||||
if (len(args) > 1) && (args[1] == "o") {
|
||||
|
|
@ -683,7 +682,7 @@ func (msg *WhoCommand) String() string {
|
|||
|
||||
type OperCommand struct {
|
||||
PassCommand
|
||||
name string
|
||||
name Name
|
||||
}
|
||||
|
||||
func (msg *OperCommand) String() string {
|
||||
|
|
@ -701,7 +700,7 @@ func NewOperCommand(args []string) (Command, error) {
|
|||
}
|
||||
|
||||
cmd := &OperCommand{
|
||||
name: args[0],
|
||||
name: NewName(args[0]),
|
||||
}
|
||||
cmd.password = []byte(args[1])
|
||||
return cmd, nil
|
||||
|
|
@ -740,12 +739,12 @@ func NewCapCommand(args []string) (Command, error) {
|
|||
// HAPROXY support
|
||||
type ProxyCommand struct {
|
||||
BaseCommand
|
||||
net string
|
||||
sourceIP string
|
||||
destIP string
|
||||
sourcePort string
|
||||
destPort string
|
||||
hostname string // looked up in socket thread
|
||||
net Name
|
||||
sourceIP Name
|
||||
destIP Name
|
||||
sourcePort Name
|
||||
destPort Name
|
||||
hostname Name // looked up in socket thread
|
||||
}
|
||||
|
||||
func (msg *ProxyCommand) String() string {
|
||||
|
|
@ -757,18 +756,18 @@ func NewProxyCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
return &ProxyCommand{
|
||||
net: args[0],
|
||||
sourceIP: args[1],
|
||||
destIP: args[2],
|
||||
sourcePort: args[3],
|
||||
destPort: args[4],
|
||||
hostname: LookupHostname(args[1]),
|
||||
net: NewName(args[0]),
|
||||
sourceIP: NewName(args[1]),
|
||||
destIP: NewName(args[2]),
|
||||
sourcePort: NewName(args[3]),
|
||||
destPort: NewName(args[4]),
|
||||
hostname: LookupHostname(NewName(args[1])),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type AwayCommand struct {
|
||||
BaseCommand
|
||||
text string
|
||||
text Text
|
||||
away bool
|
||||
}
|
||||
|
||||
|
|
@ -780,7 +779,7 @@ func NewAwayCommand(args []string) (Command, error) {
|
|||
cmd := &AwayCommand{}
|
||||
|
||||
if len(args) > 0 {
|
||||
cmd.text = args[0]
|
||||
cmd.text = NewText(args[0])
|
||||
cmd.away = true
|
||||
}
|
||||
|
||||
|
|
@ -789,7 +788,7 @@ func NewAwayCommand(args []string) (Command, error) {
|
|||
|
||||
type IsOnCommand struct {
|
||||
BaseCommand
|
||||
nicks []string
|
||||
nicks []Name
|
||||
}
|
||||
|
||||
func (msg *IsOnCommand) String() string {
|
||||
|
|
@ -802,27 +801,27 @@ func NewIsOnCommand(args []string) (Command, error) {
|
|||
}
|
||||
|
||||
return &IsOnCommand{
|
||||
nicks: args,
|
||||
nicks: NewNames(args),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type MOTDCommand struct {
|
||||
BaseCommand
|
||||
target string
|
||||
target Name
|
||||
}
|
||||
|
||||
func NewMOTDCommand(args []string) (Command, error) {
|
||||
cmd := &MOTDCommand{}
|
||||
if len(args) > 0 {
|
||||
cmd.target = args[0]
|
||||
cmd.target = NewName(args[0])
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
type NoticeCommand struct {
|
||||
BaseCommand
|
||||
target string
|
||||
message string
|
||||
target Name
|
||||
message Text
|
||||
}
|
||||
|
||||
func (cmd *NoticeCommand) String() string {
|
||||
|
|
@ -834,20 +833,20 @@ func NewNoticeCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
return &NoticeCommand{
|
||||
target: args[0],
|
||||
message: args[1],
|
||||
target: NewName(args[0]),
|
||||
message: NewText(args[1]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type KickCommand struct {
|
||||
BaseCommand
|
||||
kicks map[string]string
|
||||
comment string
|
||||
kicks map[Name]Name
|
||||
comment Text
|
||||
}
|
||||
|
||||
func (msg *KickCommand) Comment() string {
|
||||
func (msg *KickCommand) Comment() Text {
|
||||
if msg.comment == "" {
|
||||
return msg.Client().Nick()
|
||||
return msg.Client().Nick().Text()
|
||||
}
|
||||
return msg.comment
|
||||
}
|
||||
|
|
@ -856,13 +855,13 @@ func NewKickCommand(args []string) (Command, error) {
|
|||
if len(args) < 2 {
|
||||
return nil, NotEnoughArgsError
|
||||
}
|
||||
channels := strings.Split(args[0], ",")
|
||||
users := strings.Split(args[1], ",")
|
||||
channels := NewNames(strings.Split(args[0], ","))
|
||||
users := NewNames(strings.Split(args[1], ","))
|
||||
if (len(channels) != len(users)) && (len(users) != 1) {
|
||||
return nil, NotEnoughArgsError
|
||||
}
|
||||
cmd := &KickCommand{
|
||||
kicks: make(map[string]string),
|
||||
kicks: make(map[Name]Name),
|
||||
}
|
||||
for index, channel := range channels {
|
||||
if len(users) == 1 {
|
||||
|
|
@ -872,48 +871,48 @@ func NewKickCommand(args []string) (Command, error) {
|
|||
}
|
||||
}
|
||||
if len(args) > 2 {
|
||||
cmd.comment = args[2]
|
||||
cmd.comment = NewText(args[2])
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
type ListCommand struct {
|
||||
BaseCommand
|
||||
channels []string
|
||||
target string
|
||||
channels []Name
|
||||
target Name
|
||||
}
|
||||
|
||||
func NewListCommand(args []string) (Command, error) {
|
||||
cmd := &ListCommand{}
|
||||
if len(args) > 0 {
|
||||
cmd.channels = strings.Split(args[0], ",")
|
||||
cmd.channels = NewNames(strings.Split(args[0], ","))
|
||||
}
|
||||
if len(args) > 1 {
|
||||
cmd.target = args[1]
|
||||
cmd.target = NewName(args[1])
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
type NamesCommand struct {
|
||||
BaseCommand
|
||||
channels []string
|
||||
target string
|
||||
channels []Name
|
||||
target Name
|
||||
}
|
||||
|
||||
func NewNamesCommand(args []string) (Command, error) {
|
||||
cmd := &NamesCommand{}
|
||||
if len(args) > 0 {
|
||||
cmd.channels = strings.Split(args[0], ",")
|
||||
cmd.channels = NewNames(strings.Split(args[0], ","))
|
||||
}
|
||||
if len(args) > 1 {
|
||||
cmd.target = args[1]
|
||||
cmd.target = NewName(args[1])
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
type DebugCommand struct {
|
||||
BaseCommand
|
||||
subCommand string
|
||||
subCommand Name
|
||||
}
|
||||
|
||||
func NewDebugCommand(args []string) (Command, error) {
|
||||
|
|
@ -922,27 +921,27 @@ func NewDebugCommand(args []string) (Command, error) {
|
|||
}
|
||||
|
||||
return &DebugCommand{
|
||||
subCommand: strings.ToUpper(args[0]),
|
||||
subCommand: NewName(strings.ToUpper(args[0])),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type VersionCommand struct {
|
||||
BaseCommand
|
||||
target string
|
||||
target Name
|
||||
}
|
||||
|
||||
func NewVersionCommand(args []string) (Command, error) {
|
||||
cmd := &VersionCommand{}
|
||||
if len(args) > 0 {
|
||||
cmd.target = args[0]
|
||||
cmd.target = NewName(args[0])
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
type InviteCommand struct {
|
||||
BaseCommand
|
||||
nickname string
|
||||
channel string
|
||||
nickname Name
|
||||
channel Name
|
||||
}
|
||||
|
||||
func NewInviteCommand(args []string) (Command, error) {
|
||||
|
|
@ -951,28 +950,28 @@ func NewInviteCommand(args []string) (Command, error) {
|
|||
}
|
||||
|
||||
return &InviteCommand{
|
||||
nickname: args[0],
|
||||
channel: args[1],
|
||||
nickname: NewName(args[0]),
|
||||
channel: NewName(args[1]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type TimeCommand struct {
|
||||
BaseCommand
|
||||
target string
|
||||
target Name
|
||||
}
|
||||
|
||||
func NewTimeCommand(args []string) (Command, error) {
|
||||
cmd := &TimeCommand{}
|
||||
if len(args) > 0 {
|
||||
cmd.target = args[0]
|
||||
cmd.target = NewName(args[0])
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
type KillCommand struct {
|
||||
BaseCommand
|
||||
nickname string
|
||||
comment string
|
||||
nickname Name
|
||||
comment Text
|
||||
}
|
||||
|
||||
func NewKillCommand(args []string) (Command, error) {
|
||||
|
|
@ -980,16 +979,16 @@ func NewKillCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
return &KillCommand{
|
||||
nickname: args[0],
|
||||
comment: args[1],
|
||||
nickname: NewName(args[0]),
|
||||
comment: NewText(args[1]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type WhoWasCommand struct {
|
||||
BaseCommand
|
||||
nicknames []string
|
||||
nicknames []Name
|
||||
count int64
|
||||
target string
|
||||
target Name
|
||||
}
|
||||
|
||||
func NewWhoWasCommand(args []string) (Command, error) {
|
||||
|
|
@ -997,13 +996,13 @@ func NewWhoWasCommand(args []string) (Command, error) {
|
|||
return nil, NotEnoughArgsError
|
||||
}
|
||||
cmd := &WhoWasCommand{
|
||||
nicknames: strings.Split(args[0], ","),
|
||||
nicknames: NewNames(strings.Split(args[0], ",")),
|
||||
}
|
||||
if len(args) > 1 {
|
||||
cmd.count, _ = strconv.ParseInt(args[1], 10, 64)
|
||||
}
|
||||
if len(args) > 2 {
|
||||
cmd.target = args[2]
|
||||
cmd.target = NewName(args[2])
|
||||
}
|
||||
return cmd, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue