initial upload
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
# toxio: turn any CLI program/script into a Tox bot
|
||||
# deps: toxcore, nim-toxcore
|
||||
# created by Luxferre in 2024, released into public domain
|
||||
|
||||
import toxcore, times, sets, osproc, streams
|
||||
from threadpool import spawn
|
||||
from std/os import sleep
|
||||
from std/cmdline import paramCount, paramStr
|
||||
|
||||
# command line parameters
|
||||
if paramCount() < 4:
|
||||
echo "Usage: toxio name datafile [w|r] cmd"
|
||||
quit(1)
|
||||
let
|
||||
botname = paramStr(1)
|
||||
toxdatafile = paramStr(2)
|
||||
writeperm: bool = (paramStr(3) == "w")
|
||||
subcmd = paramStr(4)
|
||||
|
||||
# read Tox save data
|
||||
var toxconfig = ""
|
||||
try:
|
||||
toxconfig = readFile(toxdatafile)
|
||||
except IOError:
|
||||
stderr.writeLine "Cannot read the Tox data file!"
|
||||
quit(1)
|
||||
|
||||
# bootstrap constants
|
||||
const
|
||||
bootstrapHost = "46.101.197.175"
|
||||
bootstrapKey = "CD133B521159541FB1D326DE9850F5E56A6C724B5B8E5EB5CD8D950408E95707".toPublicKey
|
||||
bootstrapPort = 33445
|
||||
|
||||
# declare the bot type to wrap GC-safe data
|
||||
type Bot = ref object
|
||||
tox: Tox
|
||||
datafile: string
|
||||
activeFriends: HashSet[Friend]
|
||||
sproc: Process
|
||||
|
||||
# input loop procedure
|
||||
proc inputloop(bot: Bot) =
|
||||
var gline = ""
|
||||
while bot.sproc.outputStream.readLine(gline):
|
||||
for f in bot.activeFriends.items:
|
||||
bot.tox.send(f, gline, TOX_MESSAGE_TYPE_NORMAL)
|
||||
bot.sproc.outputStream.flush()
|
||||
|
||||
# GC-safe bot callbacks
|
||||
proc cbs(bot: Bot) =
|
||||
# what do do on a new friend request (only in write-enable mode)
|
||||
if writeperm:
|
||||
bot.tox.onFriendRequest do (pk: PublicKey; msg: string):
|
||||
discard bot.tox.addFriendNoRequest(pk)
|
||||
try:
|
||||
writeFile(bot.datafile, bot.tox.saveData)
|
||||
except IOError:
|
||||
stderr.writeLine "Cannot write the Tox data file!"
|
||||
|
||||
# what to do on a new message
|
||||
bot.tox.onFriendMessage do (f: Friend; msg: string; kind: MessageType):
|
||||
if msg == "/toxiostop": # temporarily unsubscribe from the output
|
||||
bot.activeFriends.excl(f)
|
||||
else:
|
||||
bot.activeFriends.incl(f) # first-time activation
|
||||
bot.sproc.inputStream.writeLine msg
|
||||
bot.sproc.inputStream.flush()
|
||||
|
||||
# bot options description
|
||||
proc botopt(opts: Options) =
|
||||
opts.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE
|
||||
opts.saveData = toxconfig
|
||||
|
||||
# spawn the subprocess
|
||||
var subproc:Process
|
||||
|
||||
try:
|
||||
subproc = startProcess(subcmd, options={poEvalCommand,poStdErrToStdOut,poInteractive,poUsePath})
|
||||
stderr.writeLine "Subprocess started"
|
||||
except:
|
||||
stderr.writeLine "Cannot spawn the subprocess command!"
|
||||
quit(1)
|
||||
|
||||
# init the bot
|
||||
let iobot = Bot(tox:initTox(botopt))
|
||||
iobot.tox.name = botname
|
||||
iobot.datafile = toxdatafile
|
||||
iobot.cbs()
|
||||
iobot.tox.bootstrap(bootstrapHost, bootstrapKey, bootstrapPort)
|
||||
iobot.tox.statusMessage = "Serving " & subcmd
|
||||
iobot.sproc = subproc
|
||||
stderr.writeLine iobot.tox.name, " online at ", iobot.tox.address
|
||||
|
||||
# run the input loop
|
||||
spawn inputloop(iobot)
|
||||
|
||||
# run the toxcore loop
|
||||
while true:
|
||||
iterate(iobot.tox)
|
||||
sleep inMilliseconds(iobot.tox.iterationInterval)
|
||||
Reference in New Issue
Block a user