From: pk910 Date: Wed, 28 Sep 2011 21:06:39 +0000 (+0200) Subject: added event_invite & event_topic X-Git-Tag: v5.3~360 X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=f4b7f94b43a5dd88478455e336615d69bbafafb2;p=NeonServV5.git added event_invite & event_topic --- diff --git a/ChanUser.c b/ChanUser.c index 0a61188..c31e202 100644 --- a/ChanUser.c +++ b/ChanUser.c @@ -13,6 +13,8 @@ struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user) { chanuser->flags = 0; chanuser->user = user; chanuser->chan = chan; + + chanuser->changeTime = 0; chanuser->next_user = chan->user; chan->user = chanuser; @@ -34,6 +36,8 @@ struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *us chanuser->flags = CHANUSERFLAG_INVISIBLE; chanuser->user = user; chanuser->chan = chan; + + chanuser->changeTime = 0; chanuser->next_user = chan->user; chan->user = chanuser; diff --git a/ChanUser.h b/ChanUser.h index fd64f19..076b7f7 100644 --- a/ChanUser.h +++ b/ChanUser.h @@ -1,5 +1,6 @@ #ifndef _ChanUser_h #define _ChanUser_h +#include "main.h" #define CHANUSERFLAG_OPPED 0x01 #define CHANUSERFLAG_VOICED 0x02 @@ -15,6 +16,9 @@ struct ChanUser { struct ChanNode *chan; struct UserNode *user; + int chageEvents; + time_t changeTime; + struct ChanUser *next_user; struct ChanUser *next_chan; }; diff --git a/IRCEvents.c b/IRCEvents.c index d85dff9..58efd37 100644 --- a/IRCEvents.c +++ b/IRCEvents.c @@ -164,7 +164,7 @@ FUNC_EVENT(privctcp, privctcp_func_t, BIND_TYPE_PRIVCTCP, (struct UserNode *user FUNC_BIND(invite, invite_func_t, BIND_TYPE_INVITE) FUNC_UNBIND(invite, invite_func_t, BIND_TYPE_INVITE) -FUNC_EVENT(invite, invite_func_t, BIND_TYPE_INVITE, (struct UserNode *user, char *channel), (user, channel)) +FUNC_EVENT(invite, invite_func_t, BIND_TYPE_INVITE, (struct ClientSocket *client, struct UserNode *user, char *channel), (client, user, channel)) FUNC_BIND(raw, raw_func_t, BIND_TYPE_RAW) FUNC_UNBIND(raw, raw_func_t, BIND_TYPE_RAW) diff --git a/IRCEvents.h b/IRCEvents.h index b92669f..e08803e 100644 --- a/IRCEvents.h +++ b/IRCEvents.h @@ -76,10 +76,10 @@ int bind_privctcp(privctcp_func_t *func); void unbind_privctcp(privctcp_func_t *func); int event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text); -typedef void invite_func_t(struct UserNode *user, char *channel); +typedef void invite_func_t(struct ClientSocket *client, struct UserNode *user, char *channel); int bind_invite(invite_func_t *func); void unbind_invite(invite_func_t *func); -int event_invite(struct UserNode *user, char *channel); +int event_invite(struct ClientSocket *client, struct UserNode *user, char *channel); typedef void raw_func_t(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc); int bind_raw(raw_func_t *func); diff --git a/IRCParser.c b/IRCParser.c index 60ba4ef..336b198 100644 --- a/IRCParser.c +++ b/IRCParser.c @@ -321,7 +321,7 @@ static IRC_CMD(raw_324) { //MODE LIST static IRC_CMD(raw_invite) { if(from == NULL || argc < 2) return 0; struct UserNode *user = getUserByMask(from); - event_invite(user, argv[1]); + event_invite(client, user, argv[1]); return 1; } diff --git a/bot_NeonServ.c b/bot_NeonServ.c index 2d17bd1..dba2e6a 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -220,6 +220,11 @@ static const struct default_language_entry msgtab[] = { {"NS_SEARCH_HEADER", "The following channels were found:"}, {"NS_COMMAND_BINDING", "$b%s$b is a binding of %s %s"}, /* {ARGS: "TestCommand", "TestFunction", "TestParameters"} */ {"NS_COMMAND_ACCESS", "You need at least %d channel access and %d oper access to execute this command."}, /* {ARGS: 500, 100} */ + {"NS_TOPIC_ACCESS", "You lack sufficient access in %s to change the topic."}, /* {ARGS: "#TestChan"} */ + {"NS_BOTWAR_DETECTED", "$b$k4BOTWAR DETECTED!$k Please check the channel configuration!$b"}, + {"NS_BOTWAR_REPORTED", "A supporter has been informed to help you preventing botwars in the future."}, + {"NS_BOTWAR_ALERT", "$b$k4BOTWAR ALERT:$k$b Botwar in $b%s$b detected. (opponent: $b%s$b) Please join and help them preventing Botwars."}, /* {ARGS: "#TestChan", "OtherBot"} */ + {"NS_INVITE_FAIL", "$b%s$b is not registered with %s or suspended."}, /* {ARGS: "#TestChan", "NeonServ"} */ {NULL, NULL} }; @@ -308,6 +313,7 @@ INCLUDE ALL CMD's HERE #include "cmd_neonserv_raw.c" #include "cmd_neonserv_reloadlang.c" #include "cmd_neonserv_oplog.c" +//#include "cmd_neonserv_rename.c" //HARDCODED FUN CMD's //#include "cmd_neonserv_iplocate.c" @@ -321,8 +327,8 @@ INCLUDE ALL CMD's HERE //#include "event_neonserv_mode.c" #include "event_neonserv_ctcp.c" #include "event_neonserv_notice.c" -//#include "event_neonserv_invite.c" -//#include "event_neonserv_topic.c" +#include "event_neonserv_invite.c" +#include "event_neonserv_topic.c" static struct ClientSocket *getBotForChannel(struct ChanNode *chan) { struct ClientSocket *bot, *use_bot = NULL, *second_bot = NULL, *third_bot = NULL; @@ -521,6 +527,8 @@ void init_NeonServ() { bind_chanctcp(neonserv_event_chanctcp); bind_privctcp(neonserv_event_privctcp); bind_channotice(neonserv_event_channotice); + bind_topic(neonserv_event_topic); + bind_invite(neonserv_event_invite); set_trigger_callback(BOTID, neonserv_trigger_callback); diff --git a/event_neonserv_invite.c b/event_neonserv_invite.c new file mode 100644 index 0000000..c25aff4 --- /dev/null +++ b/event_neonserv_invite.c @@ -0,0 +1,25 @@ + +static void neonserv_event_invite(struct ClientSocket *client, struct UserNode *user, char *channel) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(client, user, "NS_INVITE_FAIL", channel, client->user->nick); + return; + } + int botid = atoi(row[0]); + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + struct ChanNode *chan = getChanByName(channel); + if(chan && isUserOnChan(bot->user, chan)) { + reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name); + } else + putsock(bot, "JOIN %s", channel); + } +} + diff --git a/event_neonserv_topic.c b/event_neonserv_topic.c new file mode 100644 index 0000000..1dc2b51 --- /dev/null +++ b/event_neonserv_topic.c @@ -0,0 +1,97 @@ + +struct neonserv_event_topic_cache { + struct ClientSocket *client; + struct UserNode *user; + struct ChanNode *chan; + char *new_topic; +}; + +static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup); +static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic); + +static void neonserv_event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic) { + struct ClientSocket *client = getBotForChannel(chan); + if(!client) return; //we can't "see" this event + if(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonserv_event_topic_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->user = user; + cache->chan = chan; + cache->new_topic = strdup(new_topic); + get_userauth(user, neonserv_event_topic_nick_lookup, cache); + } else + neonserv_event_topic_async1(client, user, chan, new_topic); +} + +static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup) { + struct neonserv_event_topic_cache *cache = data; + if(user) { + neonserv_event_topic_async1(cache->client, cache->user, cache->chan, cache->new_topic); + } + free(cache->new_topic); + free(cache); +} + +static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic) { + MYSQL_RES *res; + MYSQL_ROW row, defaultrow = NULL, chanuserrow; + int uaccess = 0; + printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaultrow = mysql_fetch_row(res); + } + int changetopic = atoi((row[0] ? row[0] : defaultrow[0])); + int topicsnarf = atoi((row[1] ? row[1] : defaultrow[1])); + if((user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + chanuserrow = mysql_fetch_row(res); + if(chanuserrow) + uaccess = ((atoi(chanuserrow[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuserrow[0])); + } + if(uaccess < changetopic) { + //undo topic change + struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid)); + struct ChanUser *chanuser = getChanUser(user, chan); + if(!chanuser) return; //flying super cow? + if(time(0) - chanuser->changeTime > BOTWAR_DETECTION_TIME) { + chanuser->changeTime = time(0); + chanuser->chageEvents = 1; + } else { + chanuser->chageEvents++; + if(chanuser->chageEvents >= BOTWAR_DETECTION_EVENTS || chanuser->chageEvents < 0) { + //BOTWAR! + chanuser->changeTime = time(0); + if(chanuser->chageEvents > 0) { + putsock(client, "NOTICE @%s :%s %s", chan->name, get_language_string(user, "NS_BOTWAR_DETECTED"), (BOTWAR_ALERT_CHAN ? get_language_string(user, "NS_BOTWAR_REPORTED") : "")); + if(BOTWAR_ALERT_CHAN) { + struct ChanNode *alertchan = getChanByName(BOTWAR_ALERT_CHAN); + struct ClientSocket *alertclient; + if(alertchan && (alertclient = getBotForChannel(chan)) != NULL) { + char msgBuf[MAXLEN]; + putsock(alertclient, "PRIVMSG %s :%s", alertchan->name, build_language_string(user, msgBuf, "NS_BOTWAR_ALERT", chan->name, user->nick)); + } + } + } + chanuser->chageEvents = -2; + return; + } + } + reply(textclient, user, "NS_TOPIC_ACCESS", chan->name); + putsock(client, "TOPIC %s :%s", chan->name, chan->topic); + } else if(uaccess >= topicsnarf) { + printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(new_topic), chan->channel_id); + } +} + diff --git a/main.h b/main.h index 115d15e..0731781 100644 --- a/main.h +++ b/main.h @@ -4,6 +4,9 @@ #define NEONSERV_VERSION "5.0.1-dev" #include "config.h" +#ifndef BOTWAR_ALERT_CHAN +#define BOTWAR_ALERT_CHAN NULL +#endif #include #include @@ -63,6 +66,8 @@ #define MAXLANGUAGES 5 #define MAXMODES 6 #define INVITE_TIMEOUT 30 +#define BOTWAR_DETECTION_TIME 7 +#define BOTWAR_DETECTION_EVENTS 6 //valid nick chars #define VALID_NICK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{|}~[\\]^-_`"