irctk

libircclient binding for scripts
git clone https://a3nm.net/git/irctk/
Log | Files | Refs | README

commit c1a4b653a468ce26d8cd83ca0e5d05daedbb7c18
Author: Antoine Amarilli <ant.amarilli@free.fr>
Date:   Thu, 13 Jan 2011 03:24:48 +0100

working quite well in fact ^^

Diffstat:
irctest.c | 424+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 424 insertions(+), 0 deletions(-)

diff --git a/irctest.c b/irctest.c @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2004-2009 Georgy Yunaev gyunaev@ulduzsoft.com + * + * This example is free, and not covered by LGPL license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. By using it you may give me some credits in your + * program, but you don't have to. + * + * + * This example tests most features of libirc. It can join the specific + * channel, welcoming all the people there, and react on some messages - + * 'help', 'quit', 'dcc chat', 'dcc send', 'ctcp'. Also it can reply to + * CTCP requests, receive DCC files and accept DCC chats. + * + * Features used: + * - nickname parsing; + * - handling 'channel' event to track the messages; + * - handling dcc and ctcp events; + * - using internal ctcp rely procedure; + * - generating channel messages; + * - handling dcc send and dcc chat events; + * - initiating dcc send and dcc chat. + * + * $Id: irctest.c 73 2009-01-03 11:14:59Z gyunaev $ + */ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> + +#include "libircclient.h" + +#include <unistd.h> +#include <pthread.h> + +#define CREATE_THREAD(id,func,param) (pthread_create (id, 0, func, (void *) param) != 0) +#define THREAD_FUNCTION(funcname) static void * funcname (void * arg) +#define thread_id_t pthread_t +#define _GNU_SOURCE + + +/* + * We store data in IRC session context. + */ +typedef struct +{ + char * channel; + char * nick; + +} irc_ctx_t; + + + +/* + * Params that we give to our threads. + */ +typedef struct +{ + irc_session_t * session; + const char * phrase; + const char * channel; + int timer; + +} spam_params_t; + + +THREAD_FUNCTION(irc_listen) +{ + irc_session_t * sp = (irc_session_t *) arg; + + irc_run(sp); + + return 0; +} + +THREAD_FUNCTION(gen_spam) +{ + /*spam_params_t * sp = (spam_params_t *) arg; + int res; + + printf("FINI %d\n", res);*/ + + return 0; +} + + +void addlog (const char * fmt, ...) +{ + FILE * fp; + char buf[1024]; + va_list va_alist; + + va_start (va_alist, fmt); +#if defined (WIN32) + _vsnprintf (buf, sizeof(buf), fmt, va_alist); +#else + vsnprintf (buf, sizeof(buf), fmt, va_alist); +#endif + va_end (va_alist); + + printf ("%s\n", buf); + + if ( (fp = fopen ("irctest.log", "ab")) != 0 ) + { + fprintf (fp, "%s\n", buf); + fclose (fp); + } +} + + +void dump_event (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) +{ + char buf[512]; + int cnt; + + buf[0] = '\0'; + + for ( cnt = 0; cnt < count; cnt++ ) + { + if ( cnt ) + strcat (buf, "|"); + + strcat (buf, params[cnt]); + } + + + addlog ("Event \"%s\", origin: \"%s\", params: %d [%s]", event, origin ? origin : "NULL", cnt, buf); +} + + +void event_join (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) +{ + dump_event (session, event, origin, params, count); + irc_cmd_user_mode (session, "+i"); + irc_cmd_msg (session, params[0], "Hi all"); + + irc_ctx_t * ctx = (irc_ctx_t *) irc_get_ctx (session); + + if ( !origin ) + return; + + // We need to know whether WE are joining the channel, or someone else. + // To do this, we compare the origin with our nick. + // Note that we have set LIBIRC_OPTION_STRIPNICKS to obtain 'parsed' nicks. + if ( !strcmp(origin, ctx->nick) ) + { + static spam_params_t spam1; + //thread_id_t tid; + + spam1.session = session; + spam1.channel = ctx->channel; + + spam1.phrase = "HEHE"; + + spam1.timer = 2; + +/* printf ("We just joined the channel %s; starting the spam threads\n", params[1]); + + if ( CREATE_THREAD (&tid, gen_spam, &spam1) ) + printf ("CREATE_THREAD failed: %s\n", strerror(errno)); + else + printf ("Spammer thread was started successfully.\n");*/ + } + else + { + char textbuf[168]; + sprintf (textbuf, "Hey, %s, hi!", origin); + irc_cmd_msg (session, params[0], textbuf); + } +} + + +void event_connect (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) +{ + irc_ctx_t * ctx = (irc_ctx_t *) irc_get_ctx (session); + dump_event (session, event, origin, params, count); + + irc_cmd_join (session, ctx->channel, 0); +} + + +void event_privmsg (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) +{ + dump_event (session, event, origin, params, count); + + printf ("'%s' said me (%s): %s\n", + origin ? origin : "someone", + params[0], params[1] ); +} + + +void dcc_recv_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length) +{ + static int count = 1; + char buf[12]; + + switch (status) + { + case LIBIRC_ERR_CLOSED: + printf ("DCC %d: chat closed\n", id); + break; + + case 0: + if ( !data ) + { + printf ("DCC %d: chat connected\n", id); + irc_dcc_msg (session, id, "Hehe"); + } + else + { + printf ("DCC %d: %s\n", id, data); + sprintf (buf, "DCC [%d]: %d", id, count++); + irc_dcc_msg (session, id, buf); + } + break; + + default: + printf ("DCC %d: error %s\n", id, irc_strerror(status)); + break; + } +} + + +void dcc_file_recv_callback (irc_session_t * session, irc_dcc_t id, int status, void * ctx, const char * data, unsigned int length) +{ + if ( status == 0 && length == 0 ) + { + printf ("File sent successfully\n"); + + if ( ctx ) + fclose ((FILE*) ctx); + } + else if ( status ) + { + printf ("File sent error: %d\n", status); + + if ( ctx ) + fclose ((FILE*) ctx); + } + else + { + if ( ctx ) + fwrite (data, 1, length, (FILE*) ctx); + printf ("File sent progress: %d\n", length); + } +} + + +void event_channel (irc_session_t * session, const char * event, const char * origin, const char ** params, unsigned int count) +{ + char nickbuf[128]; + + if ( count != 2 ) + return; + + printf ("'%s' said in channel %s: %s\n", + origin ? origin : "someone", + params[0], params[1] ); + + if ( !origin ) + return; + + irc_target_get_nick (origin, nickbuf, sizeof(nickbuf)); + + if ( !strcmp (params[1], "quit") ) + irc_cmd_quit (session, "of course, Master!"); + + if ( !strcmp (params[1], "help") ) + { + irc_cmd_msg (session, params[0], "quit, help, dcc chat, dcc send, ctcp"); + } + + if ( !strcmp (params[1], "ctcp") ) + { + irc_cmd_ctcp_request (session, nickbuf, "PING 223"); + irc_cmd_ctcp_request (session, nickbuf, "FINGER"); + irc_cmd_ctcp_request (session, nickbuf, "VERSION"); + irc_cmd_ctcp_request (session, nickbuf, "TIME"); + } + + if ( !strcmp (params[1], "dcc chat") ) + { + irc_dcc_t dccid; + irc_dcc_chat (session, 0, nickbuf, dcc_recv_callback, &dccid); + printf ("DCC chat ID: %d\n", dccid); + } + + if ( !strcmp (params[1], "dcc send") ) + { + irc_dcc_t dccid; + irc_dcc_sendfile (session, 0, nickbuf, "irctest.c", dcc_file_recv_callback, &dccid); + printf ("DCC send ID: %d\n", dccid); + } + + if ( !strcmp (params[1], "topic") ) + irc_cmd_topic (session, params[0], 0); + else if ( strstr (params[1], "topic ") == params[1] ) + irc_cmd_topic (session, params[0], params[1] + 6); + + if ( strstr (params[1], "mode ") == params[1] ) + irc_cmd_channel_mode (session, params[0], params[1] + 5); + + if ( strstr (params[1], "nick ") == params[1] ) + irc_cmd_nick (session, params[1] + 5); + + if ( strstr (params[1], "whois ") == params[1] ) + irc_cmd_whois (session, params[1] + 5); +} + + +void irc_event_dcc_chat (irc_session_t * session, const char * nick, const char * addr, irc_dcc_t dccid) +{ + printf ("DCC chat [%d] requested from '%s' (%s)\n", dccid, nick, addr); + + irc_dcc_accept (session, dccid, 0, dcc_recv_callback); +} + + +void irc_event_dcc_send (irc_session_t * session, const char * nick, const char * addr, const char * filename, unsigned long size, irc_dcc_t dccid) +{ + FILE * fp; + printf ("DCC send [%d] requested from '%s' (%s): %s (%lu bytes)\n", dccid, nick, addr, filename, size); + + if ( (fp = fopen ("file", "wb")) == 0 ) + abort(); + + irc_dcc_accept (session, dccid, fp, dcc_file_recv_callback); +} + +void event_numeric (irc_session_t * session, unsigned int event, const char * origin, const char ** params, unsigned int count) +{ + char buf[24]; + sprintf (buf, "%d", event); + + dump_event (session, buf, origin, params, count); +} + + +int main (int argc, char **argv) +{ + irc_callbacks_t callbacks; + irc_ctx_t ctx; + irc_session_t * s; + + if ( argc != 4 ) + { + printf ("Usage: %s <server> <nick> <channel>\n", argv[0]); + return 1; + } + + memset (&callbacks, 0, sizeof(callbacks)); + + callbacks.event_connect = event_connect; + callbacks.event_join = event_join; + callbacks.event_nick = dump_event; + callbacks.event_quit = dump_event; + callbacks.event_part = dump_event; + callbacks.event_mode = dump_event; + callbacks.event_topic = dump_event; + callbacks.event_kick = dump_event; + callbacks.event_channel = event_channel; + callbacks.event_privmsg = event_privmsg; + callbacks.event_notice = dump_event; + callbacks.event_invite = dump_event; + callbacks.event_umode = dump_event; + callbacks.event_ctcp_rep = dump_event; + callbacks.event_ctcp_action = dump_event; + callbacks.event_unknown = dump_event; + callbacks.event_numeric = event_numeric; + + //callbacks.event_dcc_chat_req = irc_event_dcc_chat; + //callbacks.event_dcc_send_req = irc_event_dcc_send; + + s = irc_create_session (&callbacks); + + if ( !s ) + { + printf ("Could not create session\n"); + return 1; + } + + ctx.channel = argv[3]; + ctx.nick = argv[2]; + + irc_set_ctx (s, &ctx); + + irc_option_set (s, LIBIRC_OPTION_STRIPNICKS); + + if ( irc_connect (s, argv[1], 6667, 0, argv[2], 0, 0) ) + { + printf ("Could not connect: %s\n", irc_strerror (irc_errno(s))); + return 1; + } + + + thread_id_t tid; + if ( CREATE_THREAD (&tid, irc_listen, s) ) + printf ("CREATE_THREAD failed: %s\n", strerror(errno)); + else + printf ("Listener thread was started successfully.\n"); + + void **value_ptr; + char *line = NULL; + int res, size=100; + + line = (char*) malloc(size+1); + + while ( (res = getline((char**) &line, (size_t*) &size, stdin)) != -1 ) + { + if ( irc_cmd_msg (s, ctx.channel, line) ) + break; + + line = NULL; + } + + free(line); + + //pthread_join(tid, value_ptr); + + return 1; +}