]>
Commit | Line | Data |
---|---|---|
d5c004ba GB |
1 | #include <stdio.h> |
2 | #include <stdarg.h> | |
3 | #include "../lib/version.h" | |
4 | #include "../core/error.h" | |
5 | #include "../nterfacer/library.h" | |
6 | #include "../nterfacer/nterfacer.h" | |
7 | #include "a4stats.h" | |
8 | ||
9 | MODULE_VERSION(""); | |
10 | ||
11 | static struct service_node *a4stats_node; | |
12 | ||
13 | static void a4stats_nt_query_cb(const struct DBAPIResult *result, void *uarg) { | |
14 | struct rline *ri = uarg; | |
15 | int i; | |
16 | ||
17 | if (result) { | |
18 | ri_append(ri, "%s", result->success ? "OK" : "FAILED"); | |
19 | ||
20 | if (result->success) { | |
21 | ri_append(ri, "%d", result->fields); | |
22 | ||
f79faea1 GB |
23 | while (result->next(result)) { |
24 | for (i = 0; i < result->fields; i++) { | |
25 | const char *field = result->get(result, i); | |
26 | ri_append(ri, "%s", field ? field : ""); | |
27 | } | |
28 | } | |
d5c004ba GB |
29 | } |
30 | ||
31 | result->clear(result); | |
32 | } else | |
33 | ri_append(ri, "FAILED"); | |
34 | ||
35 | ri_final(ri); | |
36 | } | |
37 | ||
f79faea1 | 38 | static int handle_getchannel(struct rline *ri, int argc, char **argv) { |
6a35e41d | 39 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT timestamp, active, privacy, deleted FROM ? WHERE name = ?", "Ts", "channels", argv[0]); |
f79faea1 GB |
40 | return 0; |
41 | } | |
42 | ||
d5c004ba | 43 | static int handle_getlines(struct rline *ri, int argc, char **argv) { |
92898969 GB |
44 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11," |
45 | "h12, h13, h14, h15, h16, h17, h18, h19, h20, h21, h22, h23 " | |
5e0e2ad6 | 46 | "FROM ? WHERE name = ?", "Ts", "channels", argv[0]); |
5bf3ab9d | 47 | |
d5c004ba GB |
48 | return 0; |
49 | } | |
50 | ||
51 | static int handle_getusers(struct rline *ri, int argc, char **argv) { | |
f79faea1 GB |
52 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT users.account, users.accountid, users.seen, users.rating, users.lines, users.chars, users.words, users.h0, users.h1, users.h2, users.h3, users.h4, users.h5, users.h6, users.h7, users.h8, users.h9, users.h10, users.h11, users." |
53 | "h12, users.h13, users.h14, users.h15, users.h16, users.h17, users.h18, users.h19, users.h20, users.h21, users.h22, users.h23, users." | |
54 | "last, users.quote, users.quotereset, users.mood_happy, users.mood_sad, users.questions, users.yelling, users.caps, users." | |
55 | "slaps, users.slapped, users.highlights, users.kicks, users.kicked, users.ops, users.deops, users.actions, users.skitzo, users.foul, users." | |
cf5ac373 | 56 | "firstseen, users.curnick FROM ? LEFT JOIN ? ON channels.id = users.channelid WHERE channels.name = ? AND users.quote IS NOT NULL ORDER BY lines DESC LIMIT 25", "TTs", "users", "channels", argv[0]); |
5bf3ab9d | 57 | |
d5c004ba GB |
58 | return 0; |
59 | } | |
60 | ||
61 | static int handle_getkicks(struct rline *ri, int argc, char **argv) { | |
cf5ac373 GB |
62 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT kicks.kicker, kicks.kickerid, ukicker.seen, ukicker.curnick, kicks.victim, kicks.victimid, uvictim.seen, uvictim.curnick, kicks.timestamp, kicks.reason " |
63 | "FROM ? " | |
64 | "LEFT JOIN ? ON channels.id = kicks.channelid " | |
8d6e0508 GB |
65 | "LEFT JOIN ? AS ukicker ON (ukicker.channelid = channels.id AND kicks.kickerid = ukicker.accountid AND kicks.kicker = ukicker.account) " |
66 | "LEFT JOIN ? AS uvictim ON (uvictim.channelid = channels.id AND kicks.victimid = uvictim.accountid AND kicks.victim = uvictim.account) " | |
cf5ac373 | 67 | "WHERE channels.name = ? ORDER BY kicks.timestamp DESC LIMIT 10", "TTTTs", "kicks", "channels", "users", "users", argv[0]); |
5bf3ab9d | 68 | |
d5c004ba GB |
69 | return 0; |
70 | } | |
71 | ||
72 | static int handle_gettopics(struct rline *ri, int argc, char **argv) { | |
cf5ac373 GB |
73 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT topics.topic, topics.timestamp, topics.setby, topics.setbyid, users.seen, users.curnick " |
74 | "FROM ? " | |
75 | "LEFT JOIN ? ON channels.id = topics.channelid " | |
8d6e0508 | 76 | "LEFT JOIN ? ON (users.channelid = channels.id AND topics.setbyid = users.accountid AND topics.setby = users.account) " |
cf5ac373 | 77 | "WHERE channels.name = ? ORDER BY topics.timestamp DESC LIMIT 10", "TTTs", "topics", "channels", "users", argv[0]); |
5bf3ab9d | 78 | |
d5c004ba GB |
79 | return 0; |
80 | } | |
81 | ||
82 | static int handle_getuser(struct rline *ri, int argc, char **argv) { | |
988ec9e0 GB |
83 | #define USER_QUERY(b) "SELECT users.account, users.accountid, users.seen, users.rating, users.lines, users.chars, users.words, " \ |
84 | "users.h0, users.h1, users.h2, users.h3, users.h4, users.h5, users.h6, users.h7, users.h8, users.h9, " \ | |
85 | "users.h10, users.h11, users.h12, users.h13, users.h14, users.h15, users.h16, users.h17, users.h18, " \ | |
86 | "users.h19, users.h20, users.h21, users.h22, users.h23, users.last, users.quote, users.quotereset, " \ | |
87 | "users.mood_happy, users.mood_sad, users.questions, users.yelling, users.caps, users.slaps, users.slapped, " \ | |
88 | "users.highlights, users.kicks, users.kicked, users.ops, users.deops, users.actions, users.skitzo, " \ | |
89 | "users.foul, users.firstseen, users.curnick FROM ? LEFT JOIN ? ON channels.id = users.channelid WHERE channels.name = ? AND " b | |
cf5ac373 GB |
90 | |
91 | /* | |
92 | Possible cases: | |
93 | accountid = 0, account = "username" -> new-style account, look up latest account for user | |
94 | accountid = 0, account = "#username" -> legacy account or user not authed, look up using "username" (remove #) | |
95 | accountid = <some value>, account = <unused> -> new-style account, look up by account id | |
96 | */ | |
97 | ||
98 | if (argv[1][0] == '#') { | |
988ec9e0 | 99 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USER_QUERY("(users.accountid = 0 AND users.account = ?)"), |
cf5ac373 GB |
100 | "TTss", "users", "channels", argv[0], &(argv[1][1])); |
101 | } else if (atoi(argv[2]) == 0) { | |
988ec9e0 | 102 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USER_QUERY("(users.accountid != 0 AND users.account = ?) ORDER BY users.accountid DESC LIMIT 1"), |
cf5ac373 GB |
103 | "TTss", "users", "channels", argv[0], argv[1]); |
104 | } else { | |
988ec9e0 | 105 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USER_QUERY("(users.accountid = ?)"), |
cf5ac373 GB |
106 | "TTss", "users", "channels", argv[0], argv[2]); |
107 | } | |
5bf3ab9d | 108 | |
d5c004ba GB |
109 | return 0; |
110 | } | |
111 | ||
28d6a377 GB |
112 | static int handle_getrelations(struct rline *ri, int argc, char **argv) { |
113 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT relations.first, relations.firstid, ufirst.curnick, ufirst.seen, relations.second, relations.secondid, usecond.curnick, usecond.seen, relations.seen, relations.score " | |
114 | "FROM ? " | |
115 | "LEFT JOIN ? ON relations.channelid = channels.id " | |
8d6e0508 GB |
116 | "LEFT JOIN ? AS ufirst ON (ufirst.channelid = channels.id AND relations.firstid = ufirst.accountid AND relations.first = ufirst.account) " |
117 | "LEFT JOIN ? AS usecond ON (usecond.channelid = channels.id AND relations.secondid = usecond.accountid AND relations.second = usecond.account) " | |
bb5f314f | 118 | "WHERE channels.name = ? ORDER BY score DESC LIMIT 50", |
28d6a377 GB |
119 | "TTTTs", "relations", "channels", "users", "users", argv[0]); |
120 | ||
121 | return 0; | |
122 | } | |
123 | ||
124 | static int handle_getuserrelations(struct rline *ri, int argc, char **argv) { | |
988ec9e0 GB |
125 | #define USERREALTIONS_QUERY(b) "SELECT relations.first, relations.firstid, ufirst.curnick, ufirst.seen, relations.second, relations.secondid, usecond.curnick, usecond.seen, relations.seen, relations.score " \ |
126 | "FROM ? " \ | |
127 | "LEFT JOIN ? ON relations.channelid = channels.id " \ | |
128 | "LEFT JOIN ? AS ufirst ON (ufirst.channelid = channels.id AND relations.firstid = ufirst.accountid AND relations.first = ufirst.account) " \ | |
129 | "LEFT JOIN ? AS usecond ON (usecond.channelid = channels.id AND relations.secondid = usecond.accountid AND relations.second = usecond.account) " \ | |
bb5f314f | 130 | "WHERE channels.name = ? AND " b " ORDER BY score DESC LIMIT 25" |
28d6a377 GB |
131 | /* |
132 | Possible cases: | |
133 | accountid = 0, account = "username" -> new-style account, look up latest account for user | |
134 | accountid = 0, account = "#username" -> legacy account or user not authed, look up using "username" (remove #) | |
135 | accountid = <some value>, account = <unused> -> new-style account, look up by account id | |
136 | */ | |
137 | ||
138 | if (argv[1][0] == '#') { | |
988ec9e0 | 139 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USERREALTIONS_QUERY("(relations.first = ? AND relations.firstid = 0 OR relations.second = ? AND relations.secondid = 0)"), |
8d6e0508 | 140 | "TTTTsss", "relations", "channels", "users", "users", argv[0], &(argv[1][1]), &(argv[1][1])); |
28d6a377 | 141 | } else if (atoi(argv[2]) == 0) { |
988ec9e0 | 142 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USERREALTIONS_QUERY("(ROW(relations.first, relations.firstid) = " |
28d6a377 | 143 | "(SELECT account, accountid FROM ? WHERE accountid != 0 AND account = ? ORDER BY accountid DESC LIMIT 1) OR " |
988ec9e0 | 144 | "ROW(relations.second, relations.secondid) = (SELECT account, accountid FROM ? WHERE accountid != 0 AND account = ? ORDER BY accountid DESC LIMIT 1))"), |
28d6a377 GB |
145 | "TTTTsTsTs", "relations", "channels", "users", "users", argv[0], "users", argv[1], "users", argv[1]); |
146 | } else { | |
988ec9e0 | 147 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USERREALTIONS_QUERY("(relations.firstid = ? OR relations.secondid = ?)"), |
28d6a377 GB |
148 | "TTTTsssss", "relations", "channels", "users", "users", argv[0], argv[1], argv[2], argv[1], argv[2]); |
149 | } | |
150 | ||
151 | return 0; | |
152 | } | |
153 | ||
899f2ee4 GB |
154 | static int handle_setprivacy(struct rline *ri, int argc, char **argv) { |
155 | a4statsdb->squery(a4statsdb, "UPDATE ? SET privacy = ? WHERE name = ?", "Tss", "channels", argv[1], argv[0]); | |
156 | return ri_final(ri); | |
157 | } | |
158 | ||
e0311e96 | 159 | static int handle_finduser(struct rline *ri, int argc, char **argv) { |
bb5f314f | 160 | a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT users.account, users.accountid, users.seen, users.curnick, channels.privacy " |
28d6a377 GB |
161 | "FROM ? " |
162 | "LEFT JOIN ? ON channels.id = users.channelid " | |
bb5f314f GB |
163 | "WHERE channels.name = ? AND (lines > 5 OR accountid != 0) AND (LOWER(curnick) LIKE ? OR LOWER(account) LIKE ?) ORDER BY seen DESC LIMIT 150", |
164 | "TTsss", "users", "channels", argv[0], argv[1], argv[1]); | |
e0311e96 GB |
165 | |
166 | return 0; | |
167 | } | |
168 | ||
d5c004ba GB |
169 | void _init(void) { |
170 | a4stats_node = register_service("a4stats"); | |
171 | if (!a4stats_node) | |
172 | return; | |
173 | ||
f79faea1 | 174 | register_handler(a4stats_node, "getchannel", 1, handle_getchannel); |
d5c004ba GB |
175 | register_handler(a4stats_node, "getlines", 1, handle_getlines); |
176 | register_handler(a4stats_node, "getusers", 1, handle_getusers); | |
177 | register_handler(a4stats_node, "getkicks", 1, handle_getkicks); | |
178 | register_handler(a4stats_node, "gettopics", 1, handle_gettopics); | |
5bf3ab9d | 179 | register_handler(a4stats_node, "getuser", 3, handle_getuser); |
28d6a377 GB |
180 | register_handler(a4stats_node, "getrelations", 1, handle_getrelations); |
181 | register_handler(a4stats_node, "getuserrelations", 3, handle_getuserrelations); | |
899f2ee4 | 182 | register_handler(a4stats_node, "setprivacy", 2, handle_setprivacy); |
bb5f314f | 183 | register_handler(a4stats_node, "finduser", 2, handle_finduser); |
d5c004ba GB |
184 | } |
185 | ||
186 | void _fini(void) { | |
187 | if (a4stats_node) | |
188 | deregister_service(a4stats_node); | |
189 | } |