6 #define CHANSERVSYNC_END_TIMEOUT 5
8 static void neonserv_cmd_chanservsync_notice_listener(struct UserNode *user, struct UserNode *target, char *message);
9 static void neonserv_cmd_chanservsync_free_cache();
11 struct neonserv_cmd_chanservsync_cache {
12 struct ClientSocket *client, *textclient;
13 struct UserNode *user;
14 struct ChanNode *chan;
19 struct neonserv_cmd_chanservsync_cache *neonserv_cmd_chanservsync_used = NULL;
20 const char* neonserv_cmd_chanservsync_supported[] = {"ChanServ", NULL};
22 static CMD_BIND(neonserv_cmd_chanservsync) {
23 if(neonserv_cmd_chanservsync_used && time(0) - neonserv_cmd_chanservsync_used->last_response < CHANSERVSYNC_END_TIMEOUT) {
24 reply(getTextBot(), user, "NS_CHANSERVSYNC_INUSE");
27 if(neonserv_cmd_chanservsync_used) {
28 neonserv_cmd_chanservsync_free_cache();
30 char *botnick = "ChanServ";
33 if(argv[0][0] == '!') {
44 for(tmp = user->auth; *tmp; tmp++)
45 seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
46 for(tmp = chan->name; *tmp; tmp++)
47 seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
48 for(tmp = botnick; *tmp; tmp++)
49 seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp));
50 sprintf(synckey, "!%08x!", seed);
51 if(strcmp(synckey, key)) {
53 const char **supp = neonserv_cmd_chanservsync_supported;
55 if(!stricmp(*supp, botnick)) {
62 reply(getTextBot(), user, "NS_CHANSERVSYNC_UNSUPPORTED", botnick, client->user->nick);
64 reply(getTextBot(), user, "NS_CHANSERVSYNC_KEY", client->user->nick, botnick, botnick, synckey);
67 struct neonserv_cmd_chanservsync_cache *cache = malloc(sizeof(*cache));
69 perror("malloc() failed");
72 cache->client = client;
73 cache->textclient = getTextBot();
76 cache->botnick = strdup(botnick);
77 cache->last_response = time(0);
78 neonserv_cmd_chanservsync_used = cache;
79 putsock(client, "PRIVMSG %s :users %s", botnick, chan->name);
80 bind_privnotice(neonserv_cmd_chanservsync_notice_listener);
83 static void neonserv_cmd_chanservsync_notice_listener(struct UserNode *user, struct UserNode *target, char *message) {
84 if(neonserv_cmd_chanservsync_used && neonserv_cmd_chanservsync_used->client->user == target && !stricmp(user->nick, neonserv_cmd_chanservsync_used->botnick)) {
85 //we've got a notice from our bot...
86 //let's try parsing it....
90 while(*p == ' ') //skip leading spaces (airb0t)
98 while((q = strstr(p, " "))) {
104 tokens[tokensPos++] = p;
109 tokens[tokensPos++] = p;
111 if(tokensPos < 2) return;
112 int caccess = atoi(tokens[0]);
113 if(caccess < 1 || caccess > 500) return;
114 char *username = tokens[1];
116 time_t now = time(0);
117 time_t seen_time = now; //now - now = 0 (never)
118 neonserv_cmd_chanservsync_used->last_response = now;
119 if(strlen(username) < 3) return;
120 //ok we have access and username... maybe there is something else we can parse???
124 if(!stricmp("normal", tokens[2]) || !stricmp("suspended", tokens[2]) || !stricmp("bot", tokens[2])) {
127 seen = merge_argv(tokens, 3, tokensPos);
129 } else if (tokensPos > 3) {
130 if(!stricmp("normal", tokens[tokensPos-1]) || !stricmp("suspended", tokens[tokensPos-1]) || !stricmp("bot", tokens[tokensPos-1])) {
131 status = tokens[tokensPos-1];
132 seen = merge_argv(tokens, 2, tokensPos-1);
134 seen = merge_argv(tokens, 2, tokensPos);
137 seen = merge_argv(tokens, 2, tokensPos);
140 if(status && !stricmp(status, "suspended")) {
141 flags |= DB_CHANUSER_SUSPENDED;
144 if(!stricmp(seen, "here"))
146 else if(stricmp(seen, "never"))
147 seen_time = strToTime(user, seen);
149 seen_time = now - seen_time;
150 reply(neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, "\002PARSED LINE!\002 Access: %d User: %s Seen: %lu State: %d", caccess, username, (unsigned long) seen_time, flags);
154 static void neonserv_cmd_chanservsync_free_cache() {
155 free(neonserv_cmd_chanservsync_used->botnick);
156 free(neonserv_cmd_chanservsync_used);
157 unbind_privnotice(neonserv_cmd_chanservsync_notice_listener);
158 neonserv_cmd_chanservsync_used = NULL;