Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

commands.go 19KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. package irc
  2. import (
  3. "errors"
  4. "fmt"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. )
  9. type editableCommand interface {
  10. Command
  11. SetCode(StringCode)
  12. SetClient(*Client)
  13. }
  14. type checkPasswordCommand interface {
  15. LoadPassword(*Server)
  16. CheckPassword()
  17. }
  18. type parseCommandFunc func([]string) (editableCommand, error)
  19. var (
  20. NotEnoughArgsError = errors.New("not enough arguments")
  21. ErrParseCommand = errors.New("failed to parse message")
  22. parseCommandFuncs = map[StringCode]parseCommandFunc{
  23. AWAY: NewAwayCommand,
  24. CAP: NewCapCommand,
  25. DEBUG: NewDebugCommand,
  26. INVITE: NewInviteCommand,
  27. ISON: NewIsOnCommand,
  28. JOIN: NewJoinCommand,
  29. KICK: NewKickCommand,
  30. KILL: NewKillCommand,
  31. LIST: NewListCommand,
  32. MODE: NewModeCommand,
  33. MOTD: NewMOTDCommand,
  34. NAMES: NewNamesCommand,
  35. NICK: NewNickCommand,
  36. NOTICE: NewNoticeCommand,
  37. OPER: NewOperCommand,
  38. PART: NewPartCommand,
  39. PASS: NewPassCommand,
  40. PING: NewPingCommand,
  41. PONG: NewPongCommand,
  42. PRIVMSG: NewPrivMsgCommand,
  43. PROXY: NewProxyCommand,
  44. QUIT: NewQuitCommand,
  45. TIME: NewTimeCommand,
  46. TOPIC: NewTopicCommand,
  47. USER: NewUserCommand,
  48. VERSION: NewVersionCommand,
  49. WHO: NewWhoCommand,
  50. WHOIS: NewWhoisCommand,
  51. WHOWAS: NewWhoWasCommand,
  52. }
  53. )
  54. type BaseCommand struct {
  55. client *Client
  56. code StringCode
  57. }
  58. func (command *BaseCommand) Client() *Client {
  59. return command.client
  60. }
  61. func (command *BaseCommand) SetClient(client *Client) {
  62. command.client = client
  63. }
  64. func (command *BaseCommand) Code() StringCode {
  65. return command.code
  66. }
  67. func (command *BaseCommand) SetCode(code StringCode) {
  68. command.code = code
  69. }
  70. func ParseCommand(line string) (cmd editableCommand, err error) {
  71. code, args := ParseLine(line)
  72. constructor := parseCommandFuncs[code]
  73. if constructor == nil {
  74. cmd = NewUnknownCommand(args)
  75. } else {
  76. cmd, err = constructor(args)
  77. }
  78. if cmd != nil {
  79. cmd.SetCode(code)
  80. }
  81. return
  82. }
  83. var (
  84. spacesExpr = regexp.MustCompile(` +`)
  85. )
  86. func splitArg(line string) (arg string, rest string) {
  87. parts := spacesExpr.Split(line, 2)
  88. if len(parts) > 0 {
  89. arg = parts[0]
  90. }
  91. if len(parts) > 1 {
  92. rest = parts[1]
  93. }
  94. return
  95. }
  96. func ParseLine(line string) (command StringCode, args []string) {
  97. args = make([]string, 0)
  98. if strings.HasPrefix(line, ":") {
  99. _, line = splitArg(line)
  100. }
  101. arg, line := splitArg(line)
  102. command = StringCode(NewName(strings.ToUpper(arg)))
  103. for len(line) > 0 {
  104. if strings.HasPrefix(line, ":") {
  105. args = append(args, line[len(":"):])
  106. break
  107. }
  108. arg, line = splitArg(line)
  109. args = append(args, arg)
  110. }
  111. return
  112. }
  113. // <command> [args...]
  114. type UnknownCommand struct {
  115. BaseCommand
  116. args []string
  117. }
  118. func (cmd *UnknownCommand) String() string {
  119. return fmt.Sprintf("UNKNOWN(command=%s, args=%s)", cmd.Code(), cmd.args)
  120. }
  121. func NewUnknownCommand(args []string) *UnknownCommand {
  122. return &UnknownCommand{
  123. args: args,
  124. }
  125. }
  126. // PING <server1> [ <server2> ]
  127. type PingCommand struct {
  128. BaseCommand
  129. server Name
  130. server2 Name
  131. }
  132. func (cmd *PingCommand) String() string {
  133. return fmt.Sprintf("PING(server=%s, server2=%s)", cmd.server, cmd.server2)
  134. }
  135. func NewPingCommand(args []string) (editableCommand, error) {
  136. if len(args) < 1 {
  137. return nil, NotEnoughArgsError
  138. }
  139. msg := &PingCommand{
  140. server: NewName(args[0]),
  141. }
  142. if len(args) > 1 {
  143. msg.server2 = NewName(args[1])
  144. }
  145. return msg, nil
  146. }
  147. // PONG <server> [ <server2> ]
  148. type PongCommand struct {
  149. BaseCommand
  150. server1 Name
  151. server2 Name
  152. }
  153. func (cmd *PongCommand) String() string {
  154. return fmt.Sprintf("PONG(server1=%s, server2=%s)", cmd.server1, cmd.server2)
  155. }
  156. func NewPongCommand(args []string) (editableCommand, error) {
  157. if len(args) < 1 {
  158. return nil, NotEnoughArgsError
  159. }
  160. message := &PongCommand{
  161. server1: NewName(args[0]),
  162. }
  163. if len(args) > 1 {
  164. message.server2 = NewName(args[1])
  165. }
  166. return message, nil
  167. }
  168. // PASS <password>
  169. type PassCommand struct {
  170. BaseCommand
  171. hash []byte
  172. password []byte
  173. err error
  174. }
  175. func (cmd *PassCommand) String() string {
  176. return fmt.Sprintf("PASS(password=%s)", cmd.password)
  177. }
  178. func (cmd *PassCommand) LoadPassword(server *Server) {
  179. cmd.hash = server.password
  180. }
  181. func (cmd *PassCommand) CheckPassword() {
  182. if cmd.hash == nil {
  183. return
  184. }
  185. cmd.err = ComparePassword(cmd.hash, cmd.password)
  186. }
  187. func NewPassCommand(args []string) (editableCommand, error) {
  188. if len(args) < 1 {
  189. return nil, NotEnoughArgsError
  190. }
  191. return &PassCommand{
  192. password: []byte(args[0]),
  193. }, nil
  194. }
  195. // NICK <nickname>
  196. type NickCommand struct {
  197. BaseCommand
  198. nickname Name
  199. }
  200. func (m *NickCommand) String() string {
  201. return fmt.Sprintf("NICK(nickname=%s)", m.nickname)
  202. }
  203. func NewNickCommand(args []string) (editableCommand, error) {
  204. if len(args) != 1 {
  205. return nil, NotEnoughArgsError
  206. }
  207. return &NickCommand{
  208. nickname: NewName(args[0]),
  209. }, nil
  210. }
  211. type UserCommand struct {
  212. BaseCommand
  213. username Name
  214. realname Text
  215. }
  216. // USER <username> <hostname> <servername> <realname>
  217. type RFC1459UserCommand struct {
  218. UserCommand
  219. hostname Name
  220. servername Name
  221. }
  222. func (cmd *RFC1459UserCommand) String() string {
  223. return fmt.Sprintf("USER(username=%s, hostname=%s, servername=%s, realname=%s)",
  224. cmd.username, cmd.hostname, cmd.servername, cmd.realname)
  225. }
  226. // USER <user> <mode> <unused> <realname>
  227. type RFC2812UserCommand struct {
  228. UserCommand
  229. mode uint8
  230. unused string
  231. }
  232. func (cmd *RFC2812UserCommand) String() string {
  233. return fmt.Sprintf("USER(username=%s, mode=%d, unused=%s, realname=%s)",
  234. cmd.username, cmd.mode, cmd.unused, cmd.realname)
  235. }
  236. func (cmd *RFC2812UserCommand) Flags() []UserMode {
  237. flags := make([]UserMode, 0)
  238. if (cmd.mode & 4) == 4 {
  239. flags = append(flags, WallOps)
  240. }
  241. if (cmd.mode & 8) == 8 {
  242. flags = append(flags, Invisible)
  243. }
  244. return flags
  245. }
  246. func NewUserCommand(args []string) (editableCommand, error) {
  247. if len(args) != 4 {
  248. return nil, NotEnoughArgsError
  249. }
  250. mode, err := strconv.ParseUint(args[1], 10, 8)
  251. if err == nil {
  252. msg := &RFC2812UserCommand{
  253. mode: uint8(mode),
  254. unused: args[2],
  255. }
  256. msg.username = NewName(args[0])
  257. msg.realname = NewText(args[3])
  258. return msg, nil
  259. }
  260. msg := &RFC1459UserCommand{
  261. hostname: NewName(args[1]),
  262. servername: NewName(args[2]),
  263. }
  264. msg.username = NewName(args[0])
  265. msg.realname = NewText(args[3])
  266. return msg, nil
  267. }
  268. // QUIT [ <Quit Command> ]
  269. type QuitCommand struct {
  270. BaseCommand
  271. message Text
  272. }
  273. func (cmd *QuitCommand) String() string {
  274. return fmt.Sprintf("QUIT(message=%s)", cmd.message)
  275. }
  276. func NewQuitCommand(args []string) (editableCommand, error) {
  277. msg := &QuitCommand{}
  278. if len(args) > 0 {
  279. msg.message = NewText(args[0])
  280. }
  281. return msg, nil
  282. }
  283. // JOIN ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0"
  284. type JoinCommand struct {
  285. BaseCommand
  286. channels map[Name]Text
  287. zero bool
  288. }
  289. func (cmd *JoinCommand) String() string {
  290. return fmt.Sprintf("JOIN(channels=%s, zero=%t)", cmd.channels, cmd.zero)
  291. }
  292. func NewJoinCommand(args []string) (editableCommand, error) {
  293. msg := &JoinCommand{
  294. channels: make(map[Name]Text),
  295. }
  296. if len(args) == 0 {
  297. return nil, NotEnoughArgsError
  298. }
  299. if args[0] == "0" {
  300. msg.zero = true
  301. return msg, nil
  302. }
  303. channels := strings.Split(args[0], ",")
  304. keys := make([]string, len(channels))
  305. if len(args) > 1 {
  306. for i, key := range strings.Split(args[1], ",") {
  307. keys[i] = key
  308. }
  309. }
  310. for i, channel := range channels {
  311. msg.channels[NewName(channel)] = NewText(keys[i])
  312. }
  313. return msg, nil
  314. }
  315. // PART <channel> *( "," <channel> ) [ <Part Command> ]
  316. type PartCommand struct {
  317. BaseCommand
  318. channels []Name
  319. message Text
  320. }
  321. func (cmd *PartCommand) Message() Text {
  322. if cmd.message == "" {
  323. return cmd.Client().Nick().Text()
  324. }
  325. return cmd.message
  326. }
  327. func (cmd *PartCommand) String() string {
  328. return fmt.Sprintf("PART(channels=%s, message=%s)", cmd.channels, cmd.message)
  329. }
  330. func NewPartCommand(args []string) (editableCommand, error) {
  331. if len(args) < 1 {
  332. return nil, NotEnoughArgsError
  333. }
  334. msg := &PartCommand{
  335. channels: NewNames(strings.Split(args[0], ",")),
  336. }
  337. if len(args) > 1 {
  338. msg.message = NewText(args[1])
  339. }
  340. return msg, nil
  341. }
  342. // PRIVMSG <target> <message>
  343. type PrivMsgCommand struct {
  344. BaseCommand
  345. target Name
  346. message Text
  347. }
  348. func (cmd *PrivMsgCommand) String() string {
  349. return fmt.Sprintf("PRIVMSG(target=%s, message=%s)", cmd.target, cmd.message)
  350. }
  351. func NewPrivMsgCommand(args []string) (editableCommand, error) {
  352. if len(args) < 2 {
  353. return nil, NotEnoughArgsError
  354. }
  355. return &PrivMsgCommand{
  356. target: NewName(args[0]),
  357. message: NewText(args[1]),
  358. }, nil
  359. }
  360. // TOPIC [newtopic]
  361. type TopicCommand struct {
  362. BaseCommand
  363. channel Name
  364. setTopic bool
  365. topic Text
  366. }
  367. func (cmd *TopicCommand) String() string {
  368. return fmt.Sprintf("TOPIC(channel=%s, topic=%s)", cmd.channel, cmd.topic)
  369. }
  370. func NewTopicCommand(args []string) (editableCommand, error) {
  371. if len(args) < 1 {
  372. return nil, NotEnoughArgsError
  373. }
  374. msg := &TopicCommand{
  375. channel: NewName(args[0]),
  376. }
  377. if len(args) > 1 {
  378. msg.setTopic = true
  379. msg.topic = NewText(args[1])
  380. }
  381. return msg, nil
  382. }
  383. type ModeChange struct {
  384. mode UserMode
  385. op ModeOp
  386. }
  387. func (change *ModeChange) String() string {
  388. return fmt.Sprintf("%s%s", change.op, change.mode)
  389. }
  390. type ModeChanges []*ModeChange
  391. func (changes ModeChanges) String() string {
  392. if len(changes) == 0 {
  393. return ""
  394. }
  395. op := changes[0].op
  396. str := changes[0].op.String()
  397. for _, change := range changes {
  398. if change.op == op {
  399. str += change.mode.String()
  400. } else {
  401. op = change.op
  402. str += " " + change.op.String()
  403. }
  404. }
  405. return str
  406. }
  407. type ModeCommand struct {
  408. BaseCommand
  409. nickname Name
  410. changes ModeChanges
  411. }
  412. // MODE <nickname> *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
  413. func NewUserModeCommand(nickname Name, args []string) (editableCommand, error) {
  414. cmd := &ModeCommand{
  415. nickname: nickname,
  416. changes: make(ModeChanges, 0),
  417. }
  418. for _, modeChange := range args {
  419. if len(modeChange) == 0 {
  420. continue
  421. }
  422. op := ModeOp(modeChange[0])
  423. if (op != Add) && (op != Remove) {
  424. return nil, ErrParseCommand
  425. }
  426. for _, mode := range modeChange[1:] {
  427. cmd.changes = append(cmd.changes, &ModeChange{
  428. mode: UserMode(mode),
  429. op: op,
  430. })
  431. }
  432. }
  433. return cmd, nil
  434. }
  435. func (cmd *ModeCommand) String() string {
  436. return fmt.Sprintf("MODE(nickname=%s, changes=%s)", cmd.nickname, cmd.changes)
  437. }
  438. type ChannelModeChange struct {
  439. mode ChannelMode
  440. op ModeOp
  441. arg string
  442. }
  443. func (change *ChannelModeChange) String() (str string) {
  444. if (change.op == Add) || (change.op == Remove) {
  445. str = change.op.String()
  446. }
  447. str += change.mode.String()
  448. if change.arg != "" {
  449. str += " " + change.arg
  450. }
  451. return
  452. }
  453. type ChannelModeChanges []*ChannelModeChange
  454. func (changes ChannelModeChanges) String() (str string) {
  455. if len(changes) == 0 {
  456. return
  457. }
  458. str = "+"
  459. if changes[0].op == Remove {
  460. str = "-"
  461. }
  462. for _, change := range changes {
  463. str += change.mode.String()
  464. }
  465. for _, change := range changes {
  466. if change.arg == "" {
  467. continue
  468. }
  469. str += " " + change.arg
  470. }
  471. return
  472. }
  473. type ChannelModeCommand struct {
  474. BaseCommand
  475. channel Name
  476. changes ChannelModeChanges
  477. }
  478. // MODE <channel> *( ( "-" / "+" ) *<modes> *<modeparams> )
  479. func NewChannelModeCommand(channel Name, args []string) (editableCommand, error) {
  480. cmd := &ChannelModeCommand{
  481. channel: channel,
  482. changes: make(ChannelModeChanges, 0),
  483. }
  484. for len(args) > 0 {
  485. if len(args[0]) == 0 {
  486. args = args[1:]
  487. continue
  488. }
  489. modeArg := args[0]
  490. op := ModeOp(modeArg[0])
  491. if (op == Add) || (op == Remove) {
  492. modeArg = modeArg[1:]
  493. } else {
  494. op = List
  495. }
  496. skipArgs := 1
  497. for _, mode := range modeArg {
  498. change := &ChannelModeChange{
  499. mode: ChannelMode(mode),
  500. op: op,
  501. }
  502. switch change.mode {
  503. case Key, BanMask, ExceptMask, InviteMask, UserLimit,
  504. ChannelOperator, ChannelCreator, Voice:
  505. if len(args) > skipArgs {
  506. change.arg = args[skipArgs]
  507. skipArgs += 1
  508. }
  509. }
  510. cmd.changes = append(cmd.changes, change)
  511. }
  512. args = args[skipArgs:]
  513. }
  514. return cmd, nil
  515. }
  516. func (msg *ChannelModeCommand) String() string {
  517. return fmt.Sprintf("MODE(channel=%s, changes=%s)", msg.channel, msg.changes)
  518. }
  519. func NewModeCommand(args []string) (editableCommand, error) {
  520. if len(args) == 0 {
  521. return nil, NotEnoughArgsError
  522. }
  523. name := NewName(args[0])
  524. if name.IsChannel() {
  525. return NewChannelModeCommand(name, args[1:])
  526. } else {
  527. return NewUserModeCommand(name, args[1:])
  528. }
  529. }
  530. type WhoisCommand struct {
  531. BaseCommand
  532. target Name
  533. masks []Name
  534. }
  535. // WHOIS [ <target> ] <mask> *( "," <mask> )
  536. func NewWhoisCommand(args []string) (editableCommand, error) {
  537. if len(args) < 1 {
  538. return nil, NotEnoughArgsError
  539. }
  540. var masks string
  541. var target string
  542. if len(args) > 1 {
  543. target = args[0]
  544. masks = args[1]
  545. } else {
  546. masks = args[0]
  547. }
  548. return &WhoisCommand{
  549. target: NewName(target),
  550. masks: NewNames(strings.Split(masks, ",")),
  551. }, nil
  552. }
  553. func (msg *WhoisCommand) String() string {
  554. return fmt.Sprintf("WHOIS(target=%s, masks=%s)", msg.target, msg.masks)
  555. }
  556. type WhoCommand struct {
  557. BaseCommand
  558. mask Name
  559. operatorOnly bool
  560. }
  561. // WHO [ <mask> [ "o" ] ]
  562. func NewWhoCommand(args []string) (editableCommand, error) {
  563. cmd := &WhoCommand{}
  564. if len(args) > 0 {
  565. cmd.mask = NewName(args[0])
  566. }
  567. if (len(args) > 1) && (args[1] == "o") {
  568. cmd.operatorOnly = true
  569. }
  570. return cmd, nil
  571. }
  572. func (msg *WhoCommand) String() string {
  573. return fmt.Sprintf("WHO(mask=%s, operatorOnly=%t)", msg.mask, msg.operatorOnly)
  574. }
  575. type OperCommand struct {
  576. PassCommand
  577. name Name
  578. }
  579. func (msg *OperCommand) String() string {
  580. return fmt.Sprintf("OPER(name=%s, password=%s)", msg.name, msg.password)
  581. }
  582. func (msg *OperCommand) LoadPassword(server *Server) {
  583. msg.hash = server.operators[msg.name]
  584. }
  585. // OPER <name> <password>
  586. func NewOperCommand(args []string) (editableCommand, error) {
  587. if len(args) < 2 {
  588. return nil, NotEnoughArgsError
  589. }
  590. cmd := &OperCommand{
  591. name: NewName(args[0]),
  592. }
  593. cmd.password = []byte(args[1])
  594. return cmd, nil
  595. }
  596. type CapCommand struct {
  597. BaseCommand
  598. subCommand CapSubCommand
  599. capabilities CapabilitySet
  600. }
  601. func (msg *CapCommand) String() string {
  602. return fmt.Sprintf("CAP(subCommand=%s, capabilities=%s)",
  603. msg.subCommand, msg.capabilities)
  604. }
  605. func NewCapCommand(args []string) (editableCommand, error) {
  606. if len(args) < 1 {
  607. return nil, NotEnoughArgsError
  608. }
  609. cmd := &CapCommand{
  610. subCommand: CapSubCommand(strings.ToUpper(args[0])),
  611. capabilities: make(CapabilitySet),
  612. }
  613. if len(args) > 1 {
  614. strs := spacesExpr.Split(args[1], -1)
  615. for _, str := range strs {
  616. cmd.capabilities[Capability(str)] = true
  617. }
  618. }
  619. return cmd, nil
  620. }
  621. // HAPROXY support
  622. type ProxyCommand struct {
  623. BaseCommand
  624. net Name
  625. sourceIP Name
  626. destIP Name
  627. sourcePort Name
  628. destPort Name
  629. hostname Name // looked up in socket thread
  630. }
  631. func (msg *ProxyCommand) String() string {
  632. return fmt.Sprintf("PROXY(sourceIP=%s, sourcePort=%s)", msg.sourceIP, msg.sourcePort)
  633. }
  634. func NewProxyCommand(args []string) (editableCommand, error) {
  635. if len(args) < 5 {
  636. return nil, NotEnoughArgsError
  637. }
  638. return &ProxyCommand{
  639. net: NewName(args[0]),
  640. sourceIP: NewName(args[1]),
  641. destIP: NewName(args[2]),
  642. sourcePort: NewName(args[3]),
  643. destPort: NewName(args[4]),
  644. hostname: LookupHostname(NewName(args[1])),
  645. }, nil
  646. }
  647. type AwayCommand struct {
  648. BaseCommand
  649. text Text
  650. away bool
  651. }
  652. func (msg *AwayCommand) String() string {
  653. return fmt.Sprintf("AWAY(%s)", msg.text)
  654. }
  655. func NewAwayCommand(args []string) (editableCommand, error) {
  656. cmd := &AwayCommand{}
  657. if len(args) > 0 {
  658. cmd.text = NewText(args[0])
  659. cmd.away = true
  660. }
  661. return cmd, nil
  662. }
  663. type IsOnCommand struct {
  664. BaseCommand
  665. nicks []Name
  666. }
  667. func (msg *IsOnCommand) String() string {
  668. return fmt.Sprintf("ISON(nicks=%s)", msg.nicks)
  669. }
  670. func NewIsOnCommand(args []string) (editableCommand, error) {
  671. if len(args) == 0 {
  672. return nil, NotEnoughArgsError
  673. }
  674. return &IsOnCommand{
  675. nicks: NewNames(args),
  676. }, nil
  677. }
  678. type MOTDCommand struct {
  679. BaseCommand
  680. target Name
  681. }
  682. func NewMOTDCommand(args []string) (editableCommand, error) {
  683. cmd := &MOTDCommand{}
  684. if len(args) > 0 {
  685. cmd.target = NewName(args[0])
  686. }
  687. return cmd, nil
  688. }
  689. type NoticeCommand struct {
  690. BaseCommand
  691. target Name
  692. message Text
  693. }
  694. func (cmd *NoticeCommand) String() string {
  695. return fmt.Sprintf("NOTICE(target=%s, message=%s)", cmd.target, cmd.message)
  696. }
  697. func NewNoticeCommand(args []string) (editableCommand, error) {
  698. if len(args) < 2 {
  699. return nil, NotEnoughArgsError
  700. }
  701. return &NoticeCommand{
  702. target: NewName(args[0]),
  703. message: NewText(args[1]),
  704. }, nil
  705. }
  706. type KickCommand struct {
  707. BaseCommand
  708. kicks map[Name]Name
  709. comment Text
  710. }
  711. func (msg *KickCommand) Comment() Text {
  712. if msg.comment == "" {
  713. return msg.Client().Nick().Text()
  714. }
  715. return msg.comment
  716. }
  717. func NewKickCommand(args []string) (editableCommand, error) {
  718. if len(args) < 2 {
  719. return nil, NotEnoughArgsError
  720. }
  721. channels := NewNames(strings.Split(args[0], ","))
  722. users := NewNames(strings.Split(args[1], ","))
  723. if (len(channels) != len(users)) && (len(users) != 1) {
  724. return nil, NotEnoughArgsError
  725. }
  726. cmd := &KickCommand{
  727. kicks: make(map[Name]Name),
  728. }
  729. for index, channel := range channels {
  730. if len(users) == 1 {
  731. cmd.kicks[channel] = users[0]
  732. } else {
  733. cmd.kicks[channel] = users[index]
  734. }
  735. }
  736. if len(args) > 2 {
  737. cmd.comment = NewText(args[2])
  738. }
  739. return cmd, nil
  740. }
  741. type ListCommand struct {
  742. BaseCommand
  743. channels []Name
  744. target Name
  745. }
  746. func NewListCommand(args []string) (editableCommand, error) {
  747. cmd := &ListCommand{}
  748. if len(args) > 0 {
  749. cmd.channels = NewNames(strings.Split(args[0], ","))
  750. }
  751. if len(args) > 1 {
  752. cmd.target = NewName(args[1])
  753. }
  754. return cmd, nil
  755. }
  756. type NamesCommand struct {
  757. BaseCommand
  758. channels []Name
  759. target Name
  760. }
  761. func NewNamesCommand(args []string) (editableCommand, error) {
  762. cmd := &NamesCommand{}
  763. if len(args) > 0 {
  764. cmd.channels = NewNames(strings.Split(args[0], ","))
  765. }
  766. if len(args) > 1 {
  767. cmd.target = NewName(args[1])
  768. }
  769. return cmd, nil
  770. }
  771. type DebugCommand struct {
  772. BaseCommand
  773. subCommand Name
  774. }
  775. func NewDebugCommand(args []string) (editableCommand, error) {
  776. if len(args) == 0 {
  777. return nil, NotEnoughArgsError
  778. }
  779. return &DebugCommand{
  780. subCommand: NewName(strings.ToUpper(args[0])),
  781. }, nil
  782. }
  783. type VersionCommand struct {
  784. BaseCommand
  785. target Name
  786. }
  787. func NewVersionCommand(args []string) (editableCommand, error) {
  788. cmd := &VersionCommand{}
  789. if len(args) > 0 {
  790. cmd.target = NewName(args[0])
  791. }
  792. return cmd, nil
  793. }
  794. type InviteCommand struct {
  795. BaseCommand
  796. nickname Name
  797. channel Name
  798. }
  799. func NewInviteCommand(args []string) (editableCommand, error) {
  800. if len(args) < 2 {
  801. return nil, NotEnoughArgsError
  802. }
  803. return &InviteCommand{
  804. nickname: NewName(args[0]),
  805. channel: NewName(args[1]),
  806. }, nil
  807. }
  808. type TimeCommand struct {
  809. BaseCommand
  810. target Name
  811. }
  812. func NewTimeCommand(args []string) (editableCommand, error) {
  813. cmd := &TimeCommand{}
  814. if len(args) > 0 {
  815. cmd.target = NewName(args[0])
  816. }
  817. return cmd, nil
  818. }
  819. type KillCommand struct {
  820. BaseCommand
  821. nickname Name
  822. comment Text
  823. }
  824. func NewKillCommand(args []string) (editableCommand, error) {
  825. if len(args) < 2 {
  826. return nil, NotEnoughArgsError
  827. }
  828. return &KillCommand{
  829. nickname: NewName(args[0]),
  830. comment: NewText(args[1]),
  831. }, nil
  832. }
  833. type WhoWasCommand struct {
  834. BaseCommand
  835. nicknames []Name
  836. count int64
  837. target Name
  838. }
  839. func NewWhoWasCommand(args []string) (editableCommand, error) {
  840. if len(args) < 1 {
  841. return nil, NotEnoughArgsError
  842. }
  843. cmd := &WhoWasCommand{
  844. nicknames: NewNames(strings.Split(args[0], ",")),
  845. }
  846. if len(args) > 1 {
  847. cmd.count, _ = strconv.ParseInt(args[1], 10, 64)
  848. }
  849. if len(args) > 2 {
  850. cmd.target = NewName(args[2])
  851. }
  852. return cmd, nil
  853. }