Limitsbot

# compile using "nim c -d:release --threads:on ChessBot.nim"
import std/net, std/strutils, std/osproc, std/streams, std/os, std/threadpool

const SERVER = "irc.ircnow.org"
const POR = 6667
const CHANNEL = "#chess_arena"
const NICK = "ChessBot"
const ADMINS = ["Limits", "jrmu"]
const AUTHOR = "Limits"
const GNUCHESS_PATH = "/usr/local/bin/gnuchess"

var ch: Channel[string]
open(ch)

proc readLineTimeout(readStream: Stream): int =
  while true:
    let k = readStream.readLine
    while not ch.trySend(k):
      sleep(10)

proc printLines(socket: Socket, channel: string, text: string) =
  for line in text.split("\n"):
    socket.send("PRIVMSG " & channel & " :" & line & "\n")

let gnuchess = startProcess(GNUCHESS_PATH, args = ["-m"])
discard spawn readLineTimeout(gnuchess.outputStream)

sleep(1000)
let s = ch.peek
for _ in 1..<s:
  discard ch.recv

let socket = newSocket()
socket.connect(SERVER, Port(POR))

socket.send("NICK " & NICK & "\n")
socket.send("USER " & NICK & " * 0 :IRC Chess Bot\n")

while true:
  var data = socket.recvLine().split()
  echo("IRC: ", data)
  if data[0] == "PING":
    socket.send("PONG " & data[1] & "\n")
  elif data[0] == "":
    discard
  elif data[1] == "001":
    socket.send("JOIN " & CHANNEL & "\n")
  elif data[1] == "PRIVMSG" and data[3] == ":!chess":
    if data.len > 4:
      case data[4]
      of "hello": socket.send("PRIVMSG " & data[2] & " :HELLO " & data[0].split("!")[0][1 .. ^1] & "\n")
      of "author": socket.send("PRIVMSG " & data[2] & " :Author = " & AUTHOR & "\n")
      of "version": socket.send("PRIVMSG " & data[2] & " :Version = 0.1.0\n")
      of "gnuchess":
        gnuchess.inputstream.writeLine(data[5..^1].join(" "))
        gnuchess.inputstream.flush
        sleep(100)
        let s = ch.peek
        for _ in 1..<s:
          let k = ch.recv
          socket.send("PRIVMSG " & data[2] & " :" & k & "\n")
        discard ch.recv
      of "quit":
        if ADMINS.contains(data[0].split("!")[0][1 .. ^1]):
          socket.send("PRIVMSG " & data[2] & " :BYE\n")
          gnuchess.close
          socket.close
          break
      of "admins":
        socket.send("PRIVMSG " & data[2] & " :" & ADMINS.join(" ") & "\n")
      of "help":
        socket.printLines(data[2], """ChessBot
!chess author		prints author
!chess version		prints version
!chess gnuchess <cmd>	executes cmd in gnuchess and prints the output
!chess admins		prints bot admins
!chess quit		quits the ChessBot (only executable by bot admins)
!chess help		prints this message""")
    else:
      socket.send("PRIVMSG " & data[2] & " :Needs an argument\n")