From dacd393fefeabafd1306533dd6c5a56e0ab347cc Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Sun, 27 Feb 2011 18:48:35 +0100 Subject: Initial commit --- plugins/rejoin.cpp | 186 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 plugins/rejoin.cpp (limited to 'plugins/rejoin.cpp') diff --git a/plugins/rejoin.cpp b/plugins/rejoin.cpp new file mode 100644 index 0000000..a60d0a8 --- /dev/null +++ b/plugins/rejoin.cpp @@ -0,0 +1,186 @@ +/* TODO + * 470 forwarding to another channel implementieren + * evtl timeout implementieren + * aus config folgendes lesen: + * rejoinen? + * wie lange warten? + * + */ + +#include +#include +#include + +using namespace std; + +#include "../TConnectionInterface.h" +#include "../TPluginParentLight.h" +#include "../TUserList.h" +#include "../mytypes.h" +#include "../myfuncs.h" +#include "../TConfigReadOnly.h" + + +#define FLAGS_INVITE 1 +#define FLAGS_UNBAN 2 + +struct entry_t +{ + char state; + char flags; + int cnt; + int max; + time_t last; + string name; +}; + +int calc_wait (int cnt); + +extern "C" void init(int* csize, int* conndefault, int* chandefault, int* sessdefault) +{ + *csize=sizeof(list*); + *conndefault=PFLAGS_EXEC_ONEVENT; *chandefault=0; *sessdefault=0; +} + +extern "C" void plugin (plugincontext* context, ircmessage msg, TPluginParentLight* parent, TConfigReadOnly& config, int reason) +{ + list *liste=*static_cast **>(context->data); + if (liste==0) + { + liste=new list; + *static_cast **>(context->data)=liste; + } + + if (reason&PFLAGS_EXEC_ONEVENT) + { + if ((msg.command=="KICK") && (lcase(ntharg(msg.params,2))==lcase(parent->get_parent()->get_nick()))) //wir wurden gekickt? sauerei! + { + cout << "we got kicked from " << ntharg(msg.params,1) << endl; + if (config.get_valid_boolean(parent->get_parent()->get_networkname() + "." + ntharg(msg.params,1) + ".rejoin", false)) + { + cout << " trying to rejoin" << endl; + + entry_t tmp; + tmp.state=1; + tmp.flags=0; + tmp.last=time(NULL)+1; //fake time to wait 1 second ONCE + tmp.cnt=0; + tmp.max=config.get_valid_integer(parent->get_parent()->get_networkname() + "." + ntharg(msg.params,1) + ".rejoin_tries", 10); + tmp.name=ntharg(msg.params,1); + liste->push_back(tmp); + + context->flags |= PFLAGS_EXEC_ALWAYS; + } + } + } + + if (reason&PFLAGS_EXEC_ALWAYS) + { + for (list::iterator it=liste->begin(); it!=liste->end(); it++) + { + switch (it->state) + { + case 1: + if (time(NULL)>(it->last+calc_wait(it->cnt))) + { + parent->get_parent()->send("join "+it->name); + it->state=2; + } + break; + case 2: //waiting for JOIN answer + if ((ucase(msg.command)=="JOIN") && (ucase(msg.origin)==ucase(parent->get_parent()->get_nick()))) + { + it->state=99; + } + else + { + if ((lcase(ntharg(msg.params,1))==lcase(parent->get_parent()->get_nick())) && (lcase(ntharg(msg.params, 2))==lcase(it->name))) + { + int numcmd=atoi(msg.command.c_str()); + switch (numcmd) + { + case 471: //channel is full + it->last=time(NULL); + it->state=1; + it->cnt++; + break; + case 473: //inviteonly + if (!(it->flags&FLAGS_INVITE)) //try inviting via chanserv only once. if it fails once, it will fail forever! + { + it->flags|=FLAGS_INVITE; + parent->get_parent()->send("PRIVMSG ChanServ :invite "+it->name); + it->state=3; + } + else + { + it->last=time(NULL); + it->state=1; + it->cnt++; + } + break; + case 474: //banned + if (!(it->flags&FLAGS_UNBAN)) //try unbanning only once. + { + it->flags|=FLAGS_UNBAN; + parent->get_parent()->send("PRIVMSG ChanServ :unban "+it->name); + it->state=3; + } + else + { + it->last=time(NULL); + it->state=1; + it->cnt++; + } + break; + + case 475: //bad key, no such chan, too many chans. fatal. + case 403: + case 405: + it->state=99; + break; + } + } + } + break; + + case 3: //waiting for CHANSERV answer + if ( ((msg.command=="401") && (ucase(ntharg(msg.params,2))=="CHANSERV")) || ((msg.command=="NOTICE") && (ucase(msg.origin)=="CHANSERV")) ) + { + //answer arrived or no chanserv? + it->last=time(NULL); + it->state=1; + } + + break; + } + } + + bool temp=true; + while (temp) + { + temp=false; + for (list::iterator it=liste->begin(); it!=liste->end(); it++) + { + if ((it->state==99) || ((it->max!=0) && (it->cnt > it->max))) + { + cout << "cleanup: removing entry for channel " << it->name << "..." << endl; + liste->erase(it); + temp=true; + break; + } + } + } + + } +} + +int calc_wait (int cnt) +{ + int tmp; + + tmp=1 << cnt; + if (tmp>30) + tmp=30; + + return tmp; +} -- cgit v1.2.1