From: pk910 Date: Tue, 20 Sep 2011 20:45:06 +0000 (+0200) Subject: added cmd_invite and cmd_inviteme X-Git-Tag: v5.3~393 X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=069168049ebca1ee438d2c8b7f8bb9d7d5c4b982;p=NeonServV5.git added cmd_invite and cmd_inviteme --- diff --git a/bot_NeonServ.c b/bot_NeonServ.c index c426cac..9c144bd 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -195,6 +195,13 @@ static const struct default_language_entry msgtab[] = { {"NS_UNBANALL_FAIL", "$b%s$b could not find any bans in %s."}, /* {ARGS: "NeonServ", "#TestChan"} */ {"NS_UNBANME_DONE", "removed $b%d$b masks from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */ {"NS_UNBANME_FAIL", "$b%s$b could not find any bans matching %s."}, /* {ARGS: "NeonServ", "TestUser!TestIdent@TestUser.user.WebGamesNet"} */ + {"NS_INVITE_RESTRICTION", "%s doesn't want to be invited to %s."}, + {"NS_INVITE_TIMEOUT", "%s has already been invited to $b%s$b."}, + {"NS_INVITE_ON_CHAN", "%s is already in $b%s$b."}, + {"NS_INVITE_DONE_USER", "You have been invited to join $b%s$b by %s. (Do $b/msg %s %1$s uset noinvite 1$b if you don't want to be invited to %1$s anymore.)"}, + {"NS_INVITE_DONE", "Invited $b%s$b to join %s."}, + {"NS_INVITEME_ON_CHAN", "You are already in $b%s$b."}, + {"NS_INVITEME_DONE", "You have been invited to join %s."}, {NULL, NULL} }; @@ -244,7 +251,8 @@ INCLUDE ALL CMD's HERE //#include "cmd_neonserv_open.c" #include "cmd_neonserv_topic.c" #include "cmd_neonserv_mode.c" -//#include "cmd_neonserv_invite.c" +#include "cmd_neonserv_invite.c" +#include "cmd_neonserv_inviteme.c" //#include "cmd_neonserv_info.c" #include "cmd_neonserv_netinfo.c" #include "cmd_neonserv_peek.c" @@ -428,11 +436,12 @@ void init_NeonServ() { register_command(BOTID, "mode", neonserv_cmd_mode, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_getop", 0); register_command(BOTID, "version", neonserv_cmd_version, 0, 0, NULL, 0); register_command(BOTID, "peek", neonserv_cmd_peek, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN, NULL, 0); - //register_command(BOTID, "info", neonserv_cmd_info, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN, NULL, 0); register_command(BOTID, "uset", neonserv_cmd_uset, 0, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, NULL, 0); register_command(BOTID, "unban", neonserv_cmd_unban, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_canban", 0); register_command(BOTID, "unbanall", neonserv_cmd_unbanall, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_canban", 0); register_command(BOTID, "unbanme", neonserv_cmd_unbanme, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_canban", 0); + register_command(BOTID, "invite", neonserv_cmd_invite, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_canop", 0); + register_command(BOTID, "inviteme", neonserv_cmd_inviteme, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_getinvite", 0); register_command(BOTID, "trace", neonserv_cmd_trace, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, NULL, 400); register_command(BOTID, "register", neonserv_cmd_register, 2, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG, NULL, 100); diff --git a/cmd_neonserv_invite.c b/cmd_neonserv_invite.c new file mode 100644 index 0000000..e578cf9 --- /dev/null +++ b/cmd_neonserv_invite.c @@ -0,0 +1,158 @@ + +/* +* argv[0] - nick / *auth +*/ +static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup); +static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth); +static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout); +static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan); +static int neonserv_cmd_invite_is_timeout(char *nick, char *chan); +static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout); + + +struct neonserv_cmd_invite_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + struct Event *event; + char *nick; +}; + +struct neonserv_cmd_invite_timeout { + char *nick; + char *chan; + + struct neonserv_cmd_invite_timeout *next; +}; + +static struct neonserv_cmd_invite_timeout *first_timeout = NULL, *last_timeout = NULL; + +static CMD_BIND(neonserv_cmd_invite) { + if(neonserv_cmd_invite_is_timeout(argv[0], chan->name)) { + reply(getTextBot(), user, "NS_INVITE_TIMEOUT", argv[0], chan->name); + return; + } + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + cuser->flags |= USERFLAG_ISTMPUSER; + } else if(getChanUser(cuser, chan)) { + reply(getTextBot(), user, "NS_INVITE_ON_CHAN", cuser->nick, chan->name); + /* BUG + This check does not work if the user is invisible (CHMODE +D/+d) + to fix this we'd need to request the full userlist... + this is really senseless to invite a simple user so we simply mark this bug as unsolvable. + */ + return; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + neonserv_cmd_invite_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth); + } else { + struct neonserv_cmd_invite_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->event = event; + cache->nick = strdup(argv[0]); + get_userauth(cuser, neonserv_cmd_invite_nick_lookup, cache); + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup) { + struct neonserv_cmd_invite_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + neonserv_cmd_invite_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, ((user->flags & USERFLAG_ISAUTHED) ? user->auth : NULL)); + free(cache->nick); + free(cache); +} + +static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) { + if(auth) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + //check if the user has set noinvite + printf_mysql_query("SELECT `id` FROM `noinvite` WHERE `uid` = '%s' AND `cid` = '%d'", row[0], chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(textclient, user, "NS_INVITE_RESTRICTION", nick, chan->name); + return; + } + } + } + struct neonserv_cmd_invite_timeout *timeout = neonserv_cmd_invite_add_timeout(nick, chan->name); + timeq_add(INVITE_TIMEOUT, neonserv_cmd_invite_timeout_timeout, timeout); + putsock(client, "INVITE %s %s", nick, chan->name); + struct UserNode *tmpu = getUserByNick(nick); + if(!tmpu) { + tmpu = createTempUser(nick); + tmpu->flags |= USERFLAG_ISTMPUSER | (auth ? USERFLAG_ISAUTHED : 0); + if(auth) + strcpy(tmpu->auth, auth); + } + reply(textclient, tmpu, "NS_INVITE_DONE_USER", chan->name, user->nick, client->user->nick); + reply(textclient, user, "NS_INVITE_DONE", nick, chan->name); +} + +static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout) { + struct neonserv_cmd_invite_timeout *entry = data; + neonserv_cmd_invite_del_timeout(entry); +} + +static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan) { + struct neonserv_cmd_invite_timeout *entry = malloc(sizeof(*entry)); + if (!entry) { + perror("malloc() failed"); + return NULL; + } + entry->next = NULL; + entry->nick = strdup(nick); + entry->chan = strdup(chan); + if(last_timeout) { + last_timeout->next = entry; + last_timeout = entry; + } else { + last_timeout = entry; + first_timeout = entry; + } + return entry; +} + +static int neonserv_cmd_invite_is_timeout(char *nick, char *chan) { + if(!first_timeout) return 0; + struct neonserv_cmd_invite_timeout *entry; + for(entry = first_timeout; entry; entry = entry->next) { + if(!stricmp(entry->nick, nick) && !stricmp(entry->chan, chan)) + return 1; + } + return 0; +} + +static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout) { + struct neonserv_cmd_invite_timeout *entry, *prev = NULL; + for(entry = first_timeout; entry; entry = entry->next) { + if(entry == timeout) { + if(prev) + prev->next = entry->next; + else + first_timeout = entry->next; + break; + } else + prev = entry; + } + if(last_timeout == timeout) + last_timeout = prev; + free(timeout->nick); + free(timeout->chan); + free(timeout); +} diff --git a/cmd_neonserv_inviteme.c b/cmd_neonserv_inviteme.c new file mode 100644 index 0000000..e5c5319 --- /dev/null +++ b/cmd_neonserv_inviteme.c @@ -0,0 +1,18 @@ + +/* +* no arguments +*/ + +static CMD_BIND(neonserv_cmd_inviteme) { + if(getChanUser(user, chan)) { + reply(getTextBot(), user, "NS_INVITEME_ON_CHAN", chan->name); + /* BUG + This check does not work if the user is invisible (CHMODE +D/+d) + to fix this we'd need to request the full userlist... + this is really senseless to invite a simple user so we simply mark this bug as unsolvable. + */ + return; + } + putsock(client, "INVITE %s %s", user->nick, chan->name); + reply(getTextBot(), user, "NS_INVITEME_DONE", chan->name); +} diff --git a/main.h b/main.h index 9aa15a0..115d15e 100644 --- a/main.h +++ b/main.h @@ -62,6 +62,7 @@ #define MAXNUMPARAMS 200 /* maximum number of parameters in one line */ #define MAXLANGUAGES 5 #define MAXMODES 6 +#define INVITE_TIMEOUT 30 //valid nick chars #define VALID_NICK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{|}~[\\]^-_`"