1
0
Fork 0
forked from fun/fun

Added basic IRC library fully written in Fun. Some fixes. (0.41.12)

This commit is contained in:
Johannes Findeisen 2026-05-26 02:45:56 +02:00
commit 9d70f29379
3 changed files with 111 additions and 13 deletions

View file

@ -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)

View file

@ -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)

View 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)