ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/account/mychan.C
Revision: 1.7
Committed: Sat Sep 22 14:27:30 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +1 -0 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# Content
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 }