]> jfr.im git - irc/quakenet/newserv.git/blame - a4stats/nterfacer_a4stats.c
a4stats: Fix getuserrelations query.
[irc/quakenet/newserv.git] / a4stats / nterfacer_a4stats.c
CommitLineData
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
9MODULE_VERSION("");
10
11static struct service_node *a4stats_node;
12
13static 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 38static 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 43static 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
51static 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
61static 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
72static 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
82static 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
112static 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) "
28d6a377
GB
118 "WHERE channels.name = ? ORDER BY score DESC LIMIT 25",
119 "TTTTs", "relations", "channels", "users", "users", argv[0]);
120
121 return 0;
122}
123
124static 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) " \
d504208d 130 "WHERE channels.name = ? AND " b " ORDER BY score DESC LIMIT 10"
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
154static 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 159static int handle_finduser(struct rline *ri, int argc, char **argv) {
28d6a377
GB
160 a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT users.account, users.accountid, users.seen, users.curnick, channels.name, channels.privacy "
161 "FROM ? "
162 "LEFT JOIN ? ON channels.id = users.channelid "
8d6e0508 163 "WHERE (lines > 5 OR accountid != 0) AND (LOWER(curnick) LIKE ? OR LOWER(account) LIKE ?) ORDER BY seen DESC LIMIT 150",
28d6a377 164 "TTss", "users", "channels", argv[0], argv[0]);
e0311e96
GB
165
166 return 0;
167}
168
169static int handle_findchan(struct rline *ri, int argc, char **argv) {
28d6a377 170 a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, "SELECT name, privacy FROM ? WHERE active = 1 AND LOWER(name) LIKE ? LIMIT 25",
e0311e96
GB
171 "Ts", "channels", argv[0]);
172
173 return 0;
174}
175
e0311e96 176static int handle_getuserchans(struct rline *ri, int argc, char **argv) {
988ec9e0
GB
177#define USERCHANS_QUERY(b) "SELECT channels.name, channels.privacy, users.account, users.accountid, users.curnick, users.firstseen, users.seen " \
178 "FROM ? " \
179 "JOIN ? ON channels.id = users.channelid " \
180 "WHERE channels.active = 1 AND " b " ORDER BY channels.name"
e0311e96
GB
181 /*
182 Possible cases:
183 accountid = 0, account = "username" -> new-style account, look up latest account for user
184 accountid = 0, account = "#username" -> legacy account or user not authed, look up using "username" (remove #)
185 accountid = <some value>, account = <unused> -> new-style account, look up by account id
186 */
187
188 if (argv[0][0] == '#') {
988ec9e0 189 a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USERCHANS_QUERY("users.accountid = 0 AND users.account = ?"),
e0311e96
GB
190 "TTs", "users", "channels", &(argv[0][1]));
191 } else if (atoi(argv[1]) == 0) {
988ec9e0 192 a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USERCHANS_QUERY("ROW(users.account, users.accountid) = (SELECT account, accountid FROM ? WHERE users.accountid != 0 AND users.account = ? ORDER BY users.accountid DESC LIMIT 1)"),
28d6a377 193 "TTTs", "users", "channels", "users", argv[0]);
e0311e96
GB
194 } else {
195 a4statsdb->query(a4statsdb, a4stats_nt_query_cb, ri, USERCHANS_QUERY("users.accountid = ?"),
196 "TTs", "users", "channels", argv[1]);
197 }
198
199 return 0;
200}
201
d5c004ba
GB
202void _init(void) {
203 a4stats_node = register_service("a4stats");
204 if (!a4stats_node)
205 return;
206
f79faea1 207 register_handler(a4stats_node, "getchannel", 1, handle_getchannel);
d5c004ba
GB
208 register_handler(a4stats_node, "getlines", 1, handle_getlines);
209 register_handler(a4stats_node, "getusers", 1, handle_getusers);
210 register_handler(a4stats_node, "getkicks", 1, handle_getkicks);
211 register_handler(a4stats_node, "gettopics", 1, handle_gettopics);
5bf3ab9d 212 register_handler(a4stats_node, "getuser", 3, handle_getuser);
28d6a377
GB
213 register_handler(a4stats_node, "getrelations", 1, handle_getrelations);
214 register_handler(a4stats_node, "getuserrelations", 3, handle_getuserrelations);
899f2ee4 215 register_handler(a4stats_node, "setprivacy", 2, handle_setprivacy);
e0311e96
GB
216 register_handler(a4stats_node, "finduser", 1, handle_finduser);
217 register_handler(a4stats_node, "findchan", 1, handle_findchan);
218 register_handler(a4stats_node, "getuserchans", 2, handle_getuserchans);
d5c004ba
GB
219}
220
221void _fini(void) {
222 if (a4stats_node)
223 deregister_service(a4stats_node);
224}