]> jfr.im git - irc/quakenet/newserv.git/blame - chanprofile/chanprofile.c
Merge - fixed conflicts in chanserv/authcmds/authhistory.c.
[irc/quakenet/newserv.git] / chanprofile / chanprofile.c
CommitLineData
6cf96ae3 1
2#include "chanprofile.h"
3#include "../channel/channel.h"
4#include "../control/control.h"
5#include "../newsearch/newsearch.h"
6
7#include <stdio.h>
8#include <string.h>
9#include <stdlib.h>
10
11unsigned int activeprofiles;
12struct chanprofile *cptable[CPHASHSIZE];
13
14struct chanprofile *getcprec(nick *np) {
15 unsigned int hash=0,mhash;
16 unsigned int ccount=0;
17 unsigned int clen=0;
18 unsigned int i;
19 struct chanprofile *cpp;
20
21 struct channel **cs=(np->channels->content);
22
23 ccount=np->channels->cursi;
24
25 for (i=0;i<np->channels->cursi;i++) {
26 clen+=cs[i]->index->name->length;
c54295ef 27 hash ^= (unsigned long)cs[i];
6cf96ae3 28 }
29
30 mhash=hash%CPHASHSIZE;
31
32 for (cpp=cptable[mhash];cpp;cpp=cpp->next) {
33 if ((cpp->hashval==hash) && (cpp->ccount==ccount) &&
34 (cpp->clen==clen))
35 return cpp;
36 }
37
38 cpp=malloc(sizeof(struct chanprofile));
39
40 cpp->clones=0;
41 cpp->hashval=hash;
42 cpp->ccount=ccount;
43 cpp->clen=clen;
44 cpp->nicks=NULL;
45 cpp->next=cptable[mhash];
46 cptable[mhash]=cpp;
47
48 activeprofiles++;
49
50 return cpp;
51}
52
53void popprofiles() {
54 unsigned int i;
55 struct chanprofile *cpp;
56 nick *np;
57
58 /* Create the chanprofile records and count clones for each profile */
59 for (i=0;i<NICKHASHSIZE;i++) {
60 for (np=nicktable[i];np;np=np->next) {
61 cpp=getcprec(np);
62 cpp->clones++;
63 }
64 }
65
66 /* Allocate space for nick array in each profile */
67 for (i=0;i<CPHASHSIZE;i++) {
68 for (cpp=cptable[i];cpp;cpp=cpp->next) {
69 cpp->nicks=(nick **)malloc(cpp->clones * sizeof(nick *));
70 cpp->clones=0;
71 }
72 }
73
74 /* Populate the nick arrays */
75 for (i=0;i<NICKHASHSIZE;i++) {
76 for (np=nicktable[i];np;np=np->next) {
77 cpp=getcprec(np);
78 cpp->nicks[cpp->clones++]=np;
79 }
80 }
81}
82
83void clearprofiles() {
84 unsigned int i;
85 struct chanprofile *cpp, *ncpp;
86
87 for (i=0;i<CPHASHSIZE;i++) {
88 for (cpp=cptable[i];cpp;cpp=ncpp) {
89 ncpp=cpp->next;
90 free(cpp->nicks);
91 free(cpp);
92 }
93 cptable[i]=NULL;
94 }
95
96 activeprofiles=0;
97}
98
99int cpcompare(const void *a, const void *b) {
6f8dfee9 100 const struct chanprofile **cpa=(const struct chanprofile **)a, **cpb=(const struct chanprofile **)b;
6cf96ae3 101
102 return (*cpb)->clones - (*cpa)->clones;
103}
104
105void reportprofile(nick *sender, struct chanprofile *cpp) {
106 channel **cps, *cp;
107 unsigned int i;
108 nick *np;
109 char buf[1024];
110 unsigned int repwidth=80;
111 unsigned int bufpos;
0da2a4ae
CP
112 searchCtx ctx;
113
6cf96ae3 114 controlreply(sender,"============================================================");
115
116 if (cpp->ccount==0) {
117 controlreply(sender,"(no channels): %u users",cpp->clones);
118 return;
119 }
120
121 controlreply(sender,"Channels (%u):",cpp->ccount);
122
123 np=cpp->nicks[0];
124 cps=np->channels->content;
125 bufpos=0;
126 for (i=0;i<np->channels->cursi;i++) {
127 cp=cps[i];
128 if (bufpos && ((bufpos + cp->index->name->length) > repwidth)) {
129 controlreply(sender," %s",buf);
130 bufpos=0;
131 }
132
133 bufpos += sprintf(buf+bufpos,"%s ",cp->index->name->content);
134 }
135
136 if (bufpos)
137 controlreply(sender," %s",buf);
138
139 controlreply(sender,"Users (%u):",cpp->clones);
0da2a4ae
CP
140
141 ctx.reply = controlreply;
6cf96ae3 142 for (i=0;i<cpp->clones;i++) {
0da2a4ae 143 printnick(&ctx, sender,cpp->nicks[i]);
6cf96ae3 144 }
145}
146
147int reportprofiles(void *source, int cargc, char **cargv) {
148 unsigned int i,j;
149 struct chanprofile **cpary, *cpp;
150 unsigned int repnum=20;
151 nick *sender=source;
152
153 if (cargc>0)
154 repnum=strtoul(cargv[0],NULL,10);
155
156 popprofiles();
157
158 /* Make a big fat array */
159 cpary=malloc(activeprofiles*sizeof(struct chanprofile *));
160 for (i=0,j=0;i<CPHASHSIZE;i++)
161 for (cpp=cptable[i];cpp;cpp=cpp->next)
162 cpary[j++]=cpp;
163
164 controlreply(sender,"Populated array, lest number=%u (should be %u)",j,activeprofiles);
165
166 qsort(cpary, activeprofiles, sizeof(struct chanprofile *), cpcompare);
167
168 controlreply(sender,"Top %u channel profiles (%u total):",repnum,activeprofiles);
169
170 for (i=0;i<repnum;i++) {
171 reportprofile(sender,cpary[i]);
172 }
173
174 controlreply(sender,"--- End of list.");
175
176 clearprofiles();
177
178 return CMD_OK;
179}
180
181void _init() {
182 memset(cptable,0,sizeof(cptable));
183 registercontrolhelpcmd("chanprofiles",NO_DEVELOPER,1,reportprofiles,"Usage: chanprofiles [count]\nDisplays the most common channel profiles. count defaults to 20.");
184}
185
186void _fini() {
187 deregistercontrolcmd("chanprofiles",reportprofiles);
188}
189