IRC Notify für neue Posts

Dieses Projekt ermöglicht es, einen Eggdrop-Bot neue Beiträge aus einem Woltlab Bulletin Board (WBB) in einem beliebigen IRC-Channel ankündigen zu lassen. Das Projekt besteht aus 2 Teilen:

  1. einem Modul für den Eggdrop, um über eine einfache Schnittstelle Daten an den Bot zu senden und
  2. einem Hack für das WBB, damit das Board besagte Schnittstelle bedienen kann.


zugehöriger Thread auf dem BlackBoard

Das Eggdrop Remote Modul


Dieses Modul ist universell einsetzbar, es nimmt einfach Zeilen an und sendet sie an den IRC-Server. Es muss in den Eggdrop einkompiliert werden. Dazu werden 2 Dateien benötigt, ein Makefile und der Quellcode des Moduls. Beide Dateien gehören in das Unterverzeichnis src/mod/remote.mod des Eggdrop-Verzeichnisses.

Beim Makefile gilt zu beachten, dass die Leerräume zu Beginn einer Zeile tatsächlich TAB-Spaces und keine Leerzeichen sind.

Die beiden Dateien des Remote-Moduls können auch als *.tar.gz-Archiv heruntergeladen werden.

Makefile

# Makefile for src/mod/remote.mod/

srcdir = .


doofus:
@echo ""
@echo "Let's try this from the right directory..."
@echo ""
@cd ../../../ && make

static: ../remote.o

modules: ../../../remote.$(MOD_EXT)

../remote.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -DMAKING_MODS -c $(srcdir)/remote.c
@rm -f ../remote.o
mv remote.o ../

../../../remote.$(MOD_EXT): ../remote.o
$(LD) -o ../../../remote.$(MOD_EXT) ../remote.o
$(STRIP) ../../../remote.$(MOD_EXT)

depend:
$(CC) $(CFLAGS) $(CPPFLAGS) -MM $(srcdir)/remote.c > .depend

clean:
@rm -f .depend *.o *.$(MOD_EXT) *~
distclean: clean

#safety hash
../remote.o: .././remote.mod/remote.c ../../../src/mod/module.h
../../../src/main.h ../../../src/lang.h ../../../src/eggdrop.h
../../../src/flags.h ../../../src/proto.h ../../../lush.h
../../../src/misc_file.h ../../../src/cmdt.h ../../../src/tclegg.h
../../../src/tclhash.h ../../../src/chan.h ../../../src/users.h
../../../src/compat/compat.h ../../../src/compat/inet_aton.h
../../../src/compat/snprintf.h ../../../src/compat/memset.h
../../../src/compat/memcpy.h ../../../src/compat/strcasecmp.h
../../../src/mod/modvals.h ../../../src/tandem.h

remote.c

#define MODULE_NAME "remote"

/* remote.c V0.1
*
* Eggdrop module 12/2002 by Zirias
*
* This module just listens on a socket for lines to put on the IRC-server
* The socket is protected by a password.
* Very handy if you want to have any other software give messages in a
* channel through your bot. Just make it send the password followed by a
* newline-character and then the line for IRC to the socket.
*
* ATTENTION, there is no syntax checking at all. Your program has to
* provide a correct IRC protocol line like
*
* PRIVMSG #chan :this is just an example
*
* For now, the password has to be set in this source file. Maybe this
* will be changed.
*/

// Config:

#define PORT 12345
#define PASS "Password"

// End Config

#define MAKING_REMOTE

#include "src/mod/module.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>

static Function *global = NULL;

static int remote_sock, remote_conn, cl_len;
static struct sockaddr_in cl_addr, svr_addr;
static char buffer[1024];

static int remote_expmem() {
return 0;
}

static void remote_report(int idx, int details) {
}

static int readline(int fd, char *buf, int maxlen, int to_sec, int to_usec) {
fd_set rfds;
struct timeval tv;
char *ptr=buf;
int i=0;

FD_ZERO(&rfds);
FD_SET(fd,&rfds);
tv.tv_sec=to_sec;
tv.tv_usec=to_usec;
while (i<maxlen) {
if (select(fd+1,&rfds,NULL,NULL,&tv)<1) { i=-1; break; }
i++;
do recv(fd,ptr,1,0); while (*ptr=='r');
if (*ptr=='n') {
*ptr='';
break;
}
ptr++;
}
return i;
}

static void remote_data() {
if ((remote_conn=accept(remote_sock,(struct sockaddr *)&cl_addr, &cl_len))>0) {
if (readline(remote_conn,(char *)&buffer,1023,3,0)>0) {
if (strcmp(PASS,(char *)&buffer)==0) {
if (readline(remote_conn,(char *)&buffer,1023,3,0)>0) {
dprintf(DP_SERVER,"%sn",(char *)&buffer);
}
}
}
close(remote_conn);
}
}

static char *remote_close() {
del_hook(HOOK_SECONDLY,(Function) remote_data);
close(remote_sock);
return NULL;
}

EXPORT_SCOPE char *remote_start();

static Function remote_table[] = {
(Function) remote_start,
(Function) remote_close,
(Function) remote_expmem,
(Function) remote_report,
};

char *remote_start(Function *func_table) {
int socket_flags;
global = func_table;
module_register(MODULE_NAME,remote_table,0,1);
if ((remote_sock=socket(AF_INET, SOCK_STREAM, 0))<0) {
return "socket()";
} else {
socket_flags=fcntl(remote_sock,F_GETFL);
socket_flags|=O_NONBLOCK;
fcntl(remote_sock,F_SETFL,socket_flags);
svr_addr.sin_family=AF_INET;
svr_addr.sin_addr.s_addr=htonl(INADDR_ANY);
svr_addr.sin_port=htons(PORT);
if (bind(remote_sock,(struct sockaddr *)&svr_addr, sizeof(svr_addr))<0) {
return "bind()";
} else {
add_hook(HOOK_SECONDLY,(Function) remote_data);
listen(remote_sock,5);
return NULL;
}
}
}

Der WBB-Hack


Zum Einbau in das WBB müssen 2 Dateien gepatcht werden (addreply.php und newthread.php) und eine weitere Datei ergänzt werden.

addreply.php

Hier ist zu Beginn hinter der Zeile

require("./acp/lib/class_parse.php");

folgender Abschnitt zu ergänzen:

//IRC-Notify-Hack by Zirias:
require("./irc_notify.php");
//END Hack.


Außerdem muss nach dem Eintragen eines neuen Beitrags in die Datenbank die entsprechende Funktion aufgerufen werden, um einen neuen Beitrag anzukündigen. Dies geschieht, indem nach der Zeile

$postid = $db->insert_id();

folgender Aufruf ergänzt wird:

//IRC-Notify-Hack by Zirias:
irc_notify($wbbuserdata['username'],$postid,$threadid);
//END Hack.

newthread.php

Auch hier ist zu Beginn hinter der Zeile

require("./acp/lib/global.php");

folgender Abschnitt zu ergänzen:

//IRC-Notify-Hack by Zirias:
require("./irc_notify.php");
//END Hack.


Hier muss nach dem Anlegen eines neuen Themas in der Datenbank die Funktion aufgerufen werden, um einen neuen Beitrag im Channel anzukündigen. Dazu ist nach der Zeile

$postid = $db->insert_id();

ebenfalls folgendes hinzuzufügen:

//IRC-Notify-Hack by Zirias:
irc_notify($wbbuserdata['username'],$postid,$threadid);
//END Hack.



Was noch fehlt, ist das PHP-Skript, in welchem die nötigen Funktionen definiert sind:

irc_announce.php

<?php

/* irc_notify.php
* 12/2002 by Zirias
*
* announces new threads in IRC via an eggdrop using my remote module
*/

//Config:

$thread_url="http://my.boards.host.net/thread.php";
$egg_host="my.bots.host.net";
$egg_port="12345";
$egg_pass="Password";
$channel="#mychan";

//END Config.

function irc_notify($poster,$postid,$threadid) {
global $thread_url,$egg_host,$egg_port,$egg_pass,$channel,$db,$n,$allowedgroup;
$thread=$db->query_first("SELECT a.prefix, a.topic, b.title, a.boardid
FROM bb{$n}_threads a
LEFT JOIN bb{$n}_boards b ON a.boardid=b.boardid
WHERE a.threadid={$threadid}");
$perm=$db->query_first("SELECT can_view_board
FROM bb{$n}_permissions
WHERE boardid={$thread[boardid]} AND groupid={$allowedgroup}");
$trans=array_flip(get_html_translation_table(HTML_ENTITIES));
$boardname=strtr($thread['title'],$trans);
$prefixname=($thread['prefix'] != '') ? '['.strtr($thread['prefix'],$trans).'] ' : '';
$threadname=strtr($thread['topic'],$trans);
if ($perm['can_view_board']==1) {
if ($fp=@fsockopen($egg_host,$egg_port,$errno,$errstr,30)) {
fputs($fp,$egg_pass."rn");
fputs($fp,"PRIVMSG $channel :Neuer Post von 37$poster37: ");
fputs($fp,"$thread_url?postid=$postid#post$postid ");
fputs($fp,"02Forum02: $boardname ");
fputs($fp,"02Thread02: $prefixname$threadnamern");
fclose($fp);
}
}
}

?>

Letzte Aktualisierung 28.05.2006 von LX