1 |
/** |
2 |
* mychan.C: Registered channels |
3 |
* |
4 |
* Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team |
5 |
* Rights to this code are as documented in COPYING. |
6 |
* |
7 |
* |
8 |
* Portions of this file were derived from sources bearing the following license: |
9 |
* Rights to this code are documented in doc/pod/license.pod. |
10 |
* Copyright © 2005-2007 Atheme Project (http://www.atheme.org) |
11 |
*/ |
12 |
|
13 |
#include "atheme.h" |
14 |
#include <libermyth.h> |
15 |
#include <account/chanacs.h> |
16 |
#include <account/mychan.h> |
17 |
#include <account/myuser.h> |
18 |
|
19 |
mychan_t::map_type mychan_t::map; |
20 |
mychan_t::callbacks mychan_t::callback; |
21 |
|
22 |
/*************** |
23 |
* M Y C H A N * |
24 |
***************/ |
25 |
|
26 |
/* private destructor for mychan_t. */ |
27 |
void |
28 |
mychan_t::_destroy () |
29 |
{ |
30 |
node_t *n, *tn; |
31 |
|
32 |
return_if_fail (this != NULL); |
33 |
|
34 |
if (!(runflags & RF_STARTING)) |
35 |
slog (LG_DEBUG, "mychan_delete(): %s", name); |
36 |
|
37 |
/* remove the chanacs shiz */ |
38 |
LIST_FOREACH_SAFE (n, tn, chanacs.head) |
39 |
{ |
40 |
object_unref (n->data); |
41 |
} |
42 |
|
43 |
/* delete the metadata */ |
44 |
clear_metadata (); |
45 |
|
46 |
mychan_t::map.erase (name); |
47 |
|
48 |
delete this; |
49 |
|
50 |
cnt.mychan--; |
51 |
} |
52 |
|
53 |
mychan_t * |
54 |
mychan_t::create (char const * const name) |
55 |
{ |
56 |
mychan_t *mc; |
57 |
|
58 |
return_val_if_fail ((mc = mychan_t::find (name)) == NULL, mc); |
59 |
|
60 |
if (!(runflags & RF_STARTING)) |
61 |
slog (LG_DEBUG, "mychan_t::create(): %s", name); |
62 |
|
63 |
mc = new mychan_t; |
64 |
|
65 |
strlcpy (mc->name, name, CHANNELLEN); |
66 |
mc->registered = NOW; |
67 |
mc->chan = channel_find (name); |
68 |
|
69 |
mychan_t::map[mc->name] = mc; |
70 |
|
71 |
cnt.mychan++; |
72 |
|
73 |
return mc; |
74 |
} |
75 |
|
76 |
mychan_t * |
77 |
mychan_t::find (char const * const name) |
78 |
{ |
79 |
mychan_t::map_type::iterator it = mychan_t::map.find (name); |
80 |
if (it == mychan_t::map.end ()) |
81 |
return NULL; |
82 |
|
83 |
return it->second; |
84 |
} |
85 |
|
86 |
/* Check if there is anyone on the channel fulfilling the conditions. |
87 |
* Fairly expensive, but this is sometimes necessary to avoid |
88 |
* inappropriate drops. -- jilles */ |
89 |
bool |
90 |
mychan_t::isused () |
91 |
{ |
92 |
node_t *n; |
93 |
channel_t *c; |
94 |
chanuser_t *cu; |
95 |
|
96 |
if (chan == NULL) |
97 |
return false; |
98 |
LIST_FOREACH (n, c->members.head) |
99 |
{ |
100 |
cu = static_cast<chanuser_t *> (n->data); |
101 |
if (chanacs_user_flags (this, cu->user) & CA_USEDUPDATE) |
102 |
return true; |
103 |
} |
104 |
return false; |
105 |
} |
106 |
|
107 |
unsigned |
108 |
mychan_t::num_founders () |
109 |
{ |
110 |
node_t *n; |
111 |
chanacs_t *ca; |
112 |
int count = 0; |
113 |
|
114 |
LIST_FOREACH (n, chanacs.head) |
115 |
{ |
116 |
ca = static_cast<chanacs_t *> (n->data); |
117 |
if (ca->myuser != NULL && ca->level & CA_FOUNDER) |
118 |
count++; |
119 |
} |
120 |
return count; |
121 |
} |
122 |
|
123 |
char const * const |
124 |
mychan_t::founder_names () |
125 |
{ |
126 |
node_t *n; |
127 |
chanacs_t *ca; |
128 |
static char names[512]; |
129 |
|
130 |
names[0] = '\0'; |
131 |
LIST_FOREACH (n, chanacs.head) |
132 |
{ |
133 |
ca = static_cast<chanacs_t *> (n->data); |
134 |
if (ca->myuser != NULL && ca->level & CA_FOUNDER) |
135 |
{ |
136 |
if (names[0] != '\0') |
137 |
strlcat (names, ", ", sizeof names); |
138 |
strlcat (names, ca->myuser->name, sizeof names); |
139 |
} |
140 |
} |
141 |
|
142 |
return names; |
143 |
} |
144 |
|
145 |
/* Find a user fulfilling the conditions who can take another channel */ |
146 |
myuser_t * |
147 |
mychan_t::pick_candidate (unsigned int minlevel, int maxtime) |
148 |
{ |
149 |
node_t *n; |
150 |
chanacs_t *ca; |
151 |
myuser_t *mu; |
152 |
|
153 |
LIST_FOREACH (n, chanacs.head) |
154 |
{ |
155 |
ca = static_cast<chanacs_t *> (n->data); |
156 |
if (ca->level & CA_AKICK) |
157 |
continue; |
158 |
mu = ca->myuser; |
159 |
if (mu == NULL || ca->level & CA_FOUNDER) |
160 |
continue; |
161 |
if ((ca->level & minlevel) == minlevel |
162 |
&& (maxtime == 0 |
163 |
|| !mu->logins.empty () |
164 |
|| NOW - mu->lastlogin < maxtime)) |
165 |
{ |
166 |
if (has_priv_myuser (mu, PRIV_REG_NOLIMIT)) |
167 |
return mu; |
168 |
|
169 |
if (mu->num_channels () < me.maxchans) |
170 |
return mu; |
171 |
} |
172 |
} |
173 |
return NULL; |
174 |
} |
175 |
|
176 |
/* Pick a suitable successor |
177 |
* Note: please do not make this dependent on currently being in |
178 |
* the channel or on IRC; this would give an unfair advantage to |
179 |
* 24*7 clients and bots. |
180 |
* -- jilles */ |
181 |
myuser_t * |
182 |
mychan_t::pick_successor () |
183 |
{ |
184 |
myuser_t *mu; |
185 |
|
186 |
/* full privs? */ |
187 |
mu = pick_candidate (CA_FOUNDER_0 & ca_all & ~CA_FOUNDER, 7 * 86400); |
188 |
if (mu != NULL) |
189 |
return mu; |
190 |
mu = pick_candidate (CA_FOUNDER_0 & ca_all & ~CA_FOUNDER, 0); |
191 |
if (mu != NULL) |
192 |
return mu; |
193 |
/* someone with +R then? (old successor has this, but not sop) */ |
194 |
mu = pick_candidate (CA_RECOVER, 7 * 86400); |
195 |
if (mu != NULL) |
196 |
return mu; |
197 |
mu = pick_candidate (CA_RECOVER, 0); |
198 |
if (mu != NULL) |
199 |
return mu; |
200 |
/* an op perhaps? */ |
201 |
mu = pick_candidate (CA_OP, 7 * 86400); |
202 |
if (mu != NULL) |
203 |
return mu; |
204 |
mu = pick_candidate (CA_OP, 0); |
205 |
if (mu != NULL) |
206 |
return mu; |
207 |
/* just an active user with access */ |
208 |
mu = pick_candidate (0, 7 * 86400); |
209 |
if (mu != NULL) |
210 |
return mu; |
211 |
/* ok you can't say we didn't try */ |
212 |
return pick_candidate (0, 0); |
213 |
} |
214 |
|
215 |
// frees memory used by channels on shutdown |
216 |
void |
217 |
mychan_t::cleanup () |
218 |
{ |
219 |
#if 0 |
220 |
mychan_t::map_type::iterator it = mychan_t::map.begin (); |
221 |
mychan_t::map_type::iterator et = mychan_t::map.end (); |
222 |
|
223 |
while (it != et) |
224 |
{ |
225 |
delete it->second; |
226 |
++it; |
227 |
} |
228 |
#endif |
229 |
} |