🏳️‍⚧️🏳️‍🌈 | 🇳🇴 | Speedrunner & Challenge runner || Nioh 2


So today has actually been a productive day, which is… not always a thing for me, let's just say that. Especially lately.

Anyway, today I finalised the first real command for my own Twitch chat bot, YomiOnoBot: !yomi-info. It's not a complicated command or anything, but the work put into it underpins a lot of the stuff I want the bot to do Eventually™, so it's not all bad.


At a basic level, the !yomi-info command enables chatters (and strimmer!) to look up stuff about the Nioh 2 Underworld:

< chatter> !yomi-help
< YomiOnoBot> For info on a floor of the Underworld, say !yomi-info <floor number>, e.g. !yomi-info 5
< chatter> !yomi-info 5
< YomiOnoBot> Floor 5 consists of Sunomata into Imagawa Yoshimoto

Simple as you like. This part is not super important, except insofar as it gives people something to type in chat.

What is a lot cooler to me is the underlying functionality, specifically the NillaryCommand and UnaryCommand classes that allows rapid addition of new commands to the bot:

struct NilaryCommand: Command {
  let name: String
  let impl: (_ context: LexieBot, _ caller: IRCUserID, _ target: IRCChannelName) -> ()

  func call(context: LexieBot, caller: IRCUserID, target: IRCChannelName, module: any CommandModule, name: any StringProtocol, argstr: (any StringProtocol)? = nil) {
    impl(context, caller, target)
  }
}

struct UnaryCommand<ArgumentType>: Command where ArgumentType: LosslessStringConvertible {
  let name: String
  let impl: (_ context: LexieBot, _ caller: IRCUserID, _ target: IRCChannelName, _ argument: ArgumentType) -> ()

  func call(context: LexieBot, caller: IRCUserID, target: IRCChannelName, module: any CommandModule, name: any StringProtocol, argstr: (any StringProtocol)?) {
    guard
      let argument = argstr
        .map({ $0.trimmingCharacters(in: .whitespacesAndNewlines) })
        .flatMap({ ArgumentType(String($0)) })
    else {
      context.say(
        context.ircClient,
        target,
        message: "Invalid argument to command, see !\(module.name)-help for info."
      )

      return
    }

    impl(context, caller, target, argument)
  }
}
syntax highlighting by codehost

You must log in to comment.