Added basic IRC library fully written in Fun. Some fixes. (0.41.12)
This commit is contained in:
parent
abd0f5c0d6
commit
9d70f29379
3 changed files with 111 additions and 13 deletions
|
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
project(fun VERSION 0.41.11 LANGUAGES C)
|
||||
project(fun VERSION 0.41.12 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
|
|
|||
|
|
@ -58,23 +58,19 @@ if (!c.connect())
|
|||
|
||||
c.register(nick, user, real, pass)
|
||||
|
||||
// Process greetings and auto-respond to PINGs
|
||||
// Process greetings and auto-respond to PINGs (briefly)
|
||||
start = dt.now_ms()
|
||||
while (dt.now_ms() - start < 3000)
|
||||
while (dt.now_ms() - start < 1500)
|
||||
handle_lines(c)
|
||||
|
||||
// Join #funlang and speak
|
||||
// Join #funlang and speak once
|
||||
c.join(channel)
|
||||
dt.sleep_ms(500)
|
||||
c.privmsg(channel, real)
|
||||
|
||||
// Read a bit more to display echoes/traffic
|
||||
start2 = dt.now_ms()
|
||||
while (dt.now_ms() - start2 < 2000)
|
||||
// Stay connected: continuously read and print lines; auto-respond to PINGs
|
||||
print("Listening (press Ctrl-C to quit)...")
|
||||
while (true)
|
||||
handle_lines(c)
|
||||
|
||||
c.quit("bye")
|
||||
dt.sleep_ms(200)
|
||||
c.close()
|
||||
|
||||
print("Done.")
|
||||
// avoid busy loop if no data
|
||||
dt.sleep_ms(50)
|
||||
|
|
|
|||
102
examples/net/irc_echo_bot.fun
Normal file
102
examples/net/irc_echo_bot.fun
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env fun
|
||||
|
||||
/*
|
||||
* IRC Echo Bot example using lib/net/irc.fun
|
||||
*
|
||||
* Connects to an IRC server, registers, joins #funlang, and listens for
|
||||
* messages. If a message contains "!echo <text>", the bot replies with <text>.
|
||||
*
|
||||
* Notes:
|
||||
* - Works over plain TCP. For TLS, point host/port to a local TLS tunnel
|
||||
* (e.g., stunnel) and set use_tls=1.
|
||||
*/
|
||||
|
||||
#include <net/irc.fun>
|
||||
#include <strings.fun>
|
||||
#include <io/console.fun>
|
||||
#include <utils/datetime.fun>
|
||||
|
||||
// --- Configuration ---
|
||||
// freenode (plain): host="chat.freenode.net", port=6667, use_tls=0
|
||||
// For TLS via a local tunnel to remote 6697: host="127.0.0.1", port=<local>, use_tls=1
|
||||
host = "chat.freenode.net"
|
||||
port = 6667
|
||||
use_tls = 0
|
||||
|
||||
bot_nick = "FunEchoBot" // Choose an unused nickname
|
||||
bot_user = "funecho"
|
||||
bot_real = "Fun Echo Bot"
|
||||
bot_pass = "" // Optional network password (not NickServ)
|
||||
channel = "#fun-lang"
|
||||
|
||||
// Globals used by the callback
|
||||
g_client = nil
|
||||
g_dt = DateTime()
|
||||
|
||||
// Extract nick from a prefix of form "nick!user@host" or just "nick"
|
||||
fun prefix_nick(prefix)
|
||||
p = to_string(prefix)
|
||||
ex = find(p, "!")
|
||||
if (ex >= 0)
|
||||
return substr(p, 0, ex)
|
||||
at = find(p, "@")
|
||||
if (at >= 0)
|
||||
return substr(p, 0, at)
|
||||
return p
|
||||
|
||||
// Callback for IRCClient.pump(line, msg)
|
||||
fun on_line(line, msg)
|
||||
// Print all received lines to console
|
||||
print(line)
|
||||
|
||||
cmd = msg["command"]
|
||||
if (cmd == "PRIVMSG")
|
||||
params = msg["params"]
|
||||
trg = ""
|
||||
if (len(params) > 0)
|
||||
trg = params[0]
|
||||
txt = msg["trailing"]
|
||||
|
||||
// Decide reply target: channel or private
|
||||
reply_to = trg
|
||||
if (str_to_upper(trg) == str_to_upper(bot_nick))
|
||||
reply_to = prefix_nick(msg["prefix"]) // PM -> reply to user
|
||||
|
||||
// Detect command pattern: !echo <text>
|
||||
if (len(txt) >= 6)
|
||||
if (substr(txt, 0, 6) == "!echo ")
|
||||
echo_text = substr(txt, 6, len(txt) - 6)
|
||||
if (g_client != nil)
|
||||
g_client.privmsg(reply_to, echo_text)
|
||||
|
||||
// --- Main flow ---
|
||||
mode = " (plain)"
|
||||
if (use_tls == 1)
|
||||
mode = " (TLS via tunnel)"
|
||||
print("Connecting to " + host + ":" + to_string(port) + mode)
|
||||
|
||||
c = IRCClient(host, port, use_tls)
|
||||
if (!c.connect())
|
||||
print("Failed to connect.")
|
||||
exit(1)
|
||||
|
||||
g_client = c
|
||||
|
||||
c.register(bot_nick, bot_user, bot_real, bot_pass)
|
||||
|
||||
// Process greetings and auto-respond to PINGs via pump()
|
||||
start = g_dt.now_ms()
|
||||
while (g_dt.now_ms() - start < 3000)
|
||||
c.pump(on_line)
|
||||
|
||||
// Join the channel and announce
|
||||
c.join(channel)
|
||||
g_dt.sleep_ms(500)
|
||||
c.privmsg(channel, "FunEchoBot online. Say: !echo <your text>")
|
||||
|
||||
// Stay connected and keep handling messages until interrupted
|
||||
print("Listening (press Ctrl-C to quit)...")
|
||||
while (true)
|
||||
c.pump(on_line)
|
||||
// avoid busy loop when there's no data
|
||||
g_dt.sleep_ms(50)
|
||||
Loading…
Add table
Add a link
Reference in a new issue