added user invite timeout
[srvx.git] / src / chanserv.c
index 897790d7fa32152ca158fd9bc5e1ff357f9e1357..0a8faccdb31985fcc9dd72642960db8e8aac9254 100644 (file)
@@ -57,6 +57,7 @@
 #define KEY_NODELETE_LEVEL          "nodelete_level"
 #define KEY_MAX_USERINFO_LENGTH     "max_userinfo_length"
 #define KEY_GIVEOWNERSHIP_PERIOD    "giveownership_timeout"
+#define KEY_INVITED_INTERVAL           "invite_timeout"
 
 /* ChanServ database */
 #define KEY_CHANNELS                "channels"
@@ -499,6 +500,8 @@ static struct
     unsigned long   db_backup_frequency;
     unsigned long   channel_expire_frequency;
     unsigned long   dnr_expire_frequency;
+    
+    unsigned long   invited_timeout;
 
     unsigned long   info_delay;
     unsigned long   adjust_delay;
@@ -541,6 +544,12 @@ struct listData
     struct helpfile_table table;
 };
 
+struct ChanUser
+{
+       struct userNode *user;
+    struct chanNode *chan;
+};
+
 enum note_access_type
 {
     NOTE_SET_CHANNEL_ACCESS,
@@ -4286,10 +4295,28 @@ static CHANSERV_FUNC(cmd_mode)
     return 1;
 }
 
+static void
+chanserv_del_invite_mark(void *data)
+{
+       struct ChanUser *chanuser = data;
+       struct chanNode *channel = chanuser->chan;
+       unsigned int i;
+       if(!channel) return;
+       for(i = 0; i < channel->invited.used; i++)
+    {
+        if(channel->invited.list[i] == chanuser->user) {
+                       userList_remove(&channel->invited, chanuser->user);
+               }
+       }
+       free(chanuser);
+}
+
 static CHANSERV_FUNC(cmd_invite)
 {
     struct userData *uData;
     struct userNode *invite;
+    struct ChanUser *chanuser;
+    unsigned int i;
 
     uData = GetChannelUser(channel->channel_info, user->handle_info);
 
@@ -4309,6 +4336,14 @@ static CHANSERV_FUNC(cmd_invite)
         reply("CSMSG_ALREADY_PRESENT", invite->nick, channel->name);
         return 0;
     }
+    
+    for(i = 0; i < channel->invited.used; i++)
+    {
+        if(channel->invited.list[i] == invite) {
+            reply("CSMSG_ALREADY_INVITED", invite->nick, channel->name);
+            return 0;
+        }
+    }
 
     if(user != invite)
     {
@@ -4324,6 +4359,12 @@ static CHANSERV_FUNC(cmd_invite)
     if(argc > 1)
         reply("CSMSG_INVITED_USER", argv[1], channel->name);
 
+    userList_append(&channel->invited, invite);
+    chanuser = calloc(1, sizeof(*chanuser));
+    chanuser->user=invite;
+    chanuser->chan=channel;
+    timeq_add(now + chanserv_conf.invited_timeout, chanserv_del_invite_mark, chanuser);
+
     return 1;
 }
 
@@ -6492,6 +6533,13 @@ handle_join(struct modeNode *mNode)
     if(channel->members.used > cData->max)
         cData->max = channel->members.used;
 
+    for(i = 0; i < channel->invited.used; i++)
+    {
+        if(channel->invited.list[i] == user) {
+            userList_remove(&channel->invited, user);
+        }
+    }
+
     /* Check for bans.  If they're joining through a ban, one of two
      * cases applies:
      *   1: Join during a netburst, by riding the break.  Kick them
@@ -7056,6 +7104,8 @@ chanserv_conf_read(void)
     chanserv_conf.channel_expire_delay = str ? ParseInterval(str) : 86400*30;
     str = database_get_data(conf_node, KEY_DNR_EXPIRE_FREQ, RECDB_QSTRING);
     chanserv_conf.dnr_expire_frequency = str ? ParseInterval(str) : 3600;
+    str = database_get_data(conf_node, KEY_INVITED_INTERVAL, RECDB_QSTRING);
+    chanserv_conf.invited_timeout = str ? ParseInterval(str) : 600*2;
     str = database_get_data(conf_node, KEY_NODELETE_LEVEL, RECDB_QSTRING);
     chanserv_conf.nodelete_level = str ? atoi(str) : 1;
     str = database_get_data(conf_node, KEY_MAX_CHAN_USERS, RECDB_QSTRING);