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

File Contents

# Content
1 /**
2 * os_logonnews.C: Logon News stuff...
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 * Copyright © 2005-2006 William Pitcock <nenolod -at- nenolod.net>
10 * Rights to this code are as documented in doc/pod/license.pod.
11 *
12 * $Id: os_logonnews.C,v 1.5 2007-09-16 18:54:43 pippijn Exp $
13 */
14
15 #include "atheme.h"
16 #include <libermyth.h>
17 #include <ermyth/module.h>
18
19 static char const rcsid[] = "$Id: os_logonnews.C,v 1.5 2007-09-16 18:54:43 pippijn Exp $";
20
21 REGISTER_MODULE ("operserv/logonnews", false, "William Pitcock <nenolod -at- nenolod.net>");
22
23 E cmdvec os_cmdtree;
24
25 static void os_cmd_logonnews (sourceinfo_t *si, int parc, char *parv[]);
26 static void write_newsdb (void);
27 static void load_newsdb (void);
28
29 command_t const os_logonnews = { "LOGONNEWS", "Manages logon news.", PRIV_GLOBAL, 3, os_cmd_logonnews };
30
31 struct logonnews_
32 {
33 char *nick;
34 char *target;
35 time_t news_ts;
36 char *story;
37 };
38
39 typedef struct logonnews_ logonnews_t;
40
41 list_t logon_news;
42
43 static void
44 write_newsdb (void)
45 {
46 FILE *f;
47 node_t *n;
48 logonnews_t *l;
49
50 if (!(f = fopen (DATADIR "/news.db.new", "w")))
51 {
52 slog (LG_DEBUG, "write_newsdb(): cannot write news database: %s", strerror (errno));
53 return;
54 }
55
56 LIST_FOREACH (n, logon_news.head)
57 {
58 l = static_cast<logonnews_t *> (n->data);
59 fprintf (f, "GL %s %s %ld %s\n", l->nick, l->target, l->news_ts, l->story);
60 }
61
62 fclose (f);
63
64 if ((rename (DATADIR "/news.db.new", DATADIR "/news.db")) < 0)
65 {
66 slog (LG_DEBUG, "write_newsdb(): couldn't rename news database.");
67 return;
68 }
69 }
70
71 static void
72 load_newsdb (void)
73 {
74 FILE *f;
75 node_t *n;
76 char *item, rBuf[BUFSIZE];
77
78 if (!(f = fopen (DATADIR "/news.db", "r")))
79 {
80 slog (LG_DEBUG, "read_newsdb(): cannot open news database: %s", strerror (errno));
81 return;
82 }
83
84 while (fgets (rBuf, BUFSIZE, f))
85 {
86 item = strtok (rBuf, " ");
87 strip (item);
88
89 if (!strcmp (item, "GL"))
90 {
91 char *nick = strtok (NULL, " ");
92 char *target = strtok (NULL, " ");
93 char *news_ts = strtok (NULL, " ");
94 char *story = strtok (NULL, "");
95 logonnews_t *l;
96
97 if (!nick || !target || !news_ts || !story)
98 continue;
99
100 l = new logonnews_t;
101 l->nick = sstrdup (nick);
102 l->target = sstrdup (target);
103 l->news_ts = atol (news_ts);
104 l->story = sstrdup (story);
105
106 n = node_create ();
107 node_add (l, n, &logon_news);
108 }
109 }
110
111 fclose (f);
112 }
113
114 static void
115 display_news (user_t *u)
116 {
117 node_t *n;
118 logonnews_t *l;
119 char dBuf[BUFSIZE];
120 struct tm tm;
121 int count = 0;
122
123 /* abort if it's an internal client */
124 if (is_internal_client (u))
125 return;
126
127 if (logon_news.count > 0)
128 {
129 notice (globsvs.nick, u->nick, "*** \2Message(s) of the Day\2 ***");
130
131 LIST_FOREACH_PREV (n, logon_news.tail)
132 {
133 l = static_cast<logonnews_t *> (n->data);
134 tm = *localtime (&l->news_ts);
135 strftime (dBuf, BUFSIZE, "%H:%M on %m/%d/%y", &tm);
136 notice (globsvs.nick, u->nick, "[\2%s\2] Notice from %s, posted %s:", l->target, l->nick, dBuf);
137 notice (globsvs.nick, u->nick, "%s", l->story);
138 count++;
139
140 /* only display three latest entries, max. */
141 if (count == 3)
142 break;
143 }
144
145 notice (globsvs.nick, u->nick, "*** \2End of Message(s) of the Day\2 ***");
146 }
147 }
148
149 static void
150 os_cmd_logonnews (sourceinfo_t *si, int parc, char *parv[])
151 {
152 char *action = parv[0];
153 char *target = parv[1];
154 char *story = parv[2];
155 logonnews_t *l;
156 node_t *n;
157
158 if (!action)
159 {
160 command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "LOGONNEWS");
161 command_fail (si, fault::needmoreparams, "Syntax: LOGONNEWS ADD|DEL|LIST [target] [message]");
162 return;
163 }
164
165 if (!strcasecmp (action, "ADD"))
166 {
167 if (!target || !story)
168 {
169 command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "LOGONNEWS ADD");
170 command_fail (si, fault::needmoreparams, "Syntax: LOGONNEWS ADD <target> <message>");
171 return;
172 }
173
174 l = new logonnews_t;
175 l->nick = sstrdup (get_source_name (si));
176 l->news_ts = NOW;
177 l->story = sstrdup (story);
178 l->target = sstrdup (target);
179
180 n = node_create ();
181 node_add (l, n, &logon_news);
182
183 write_newsdb ();
184
185 command_success_nodata (si, "Added entry to logon news.");
186 logcommand (si, CMDLOG_ADMIN, "LOGONNEWS ADD %s %s", target, story);
187 return;
188 }
189 else if (!strcasecmp (action, "DEL"))
190 {
191 int x = 0;
192 int id;
193
194 if (!target)
195 {
196 command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "LOGONNEWS DEL");
197 command_fail (si, fault::needmoreparams, "Syntax: LOGONNEWS DEL <id>");
198 return;
199 }
200
201 id = atoi (target);
202
203 if (id <= 0)
204 {
205 command_fail (si, fault::badparams, STR_INVALID_PARAMS, "LOGONNEWS DEL");
206 command_fail (si, fault::badparams, "Syntax: LOGONNEWS DEL <id>");
207 return;
208 }
209
210 /* search for it */
211 LIST_FOREACH (n, logon_news.head)
212 {
213 l = static_cast<logonnews_t *> (n->data);
214 x++;
215
216 if (x == id)
217 {
218 logcommand (si, CMDLOG_ADMIN, "LOGONNEWS DEL %s %s", l->target, l->story);
219
220 node_del (n, &logon_news);
221
222 sfree (l->nick);
223 sfree (l->target);
224 sfree (l->story);
225 delete l;
226
227 write_newsdb ();
228
229 command_success_nodata (si, "Deleted entry %d from logon news.", id);
230 return;
231 }
232 }
233
234 command_fail (si, fault::nosuch_target, "Entry %d not found in logon news.", id);
235 return;
236 }
237 else if (!strcasecmp (action, "LIST"))
238 {
239 int x = 0;
240
241 LIST_FOREACH (n, logon_news.head)
242 {
243 l = static_cast<logonnews_t *> (n->data);
244 x++;
245
246 command_success_nodata (si, "%d: [\2%s\2] by \2%s\2, \2%s\2", x, l->target, l->nick, l->story);
247 }
248
249 command_success_nodata (si, "End of list.");
250 logcommand (si, CMDLOG_GET, "LOGONNEWS LIST");
251 return;
252 }
253 else
254 {
255 command_fail (si, fault::badparams, STR_INVALID_PARAMS, "LOGONNEWS");
256 command_fail (si, fault::needmoreparams, "Syntax: LOGONNEWS ADD|DEL|LIST [target] [message]");
257 return;
258 }
259 }
260
261 bool
262 _modinit (module *m)
263 {
264 user_t::callback.add.attach (display_news);
265 os_cmdtree << os_logonnews;
266 load_newsdb ();
267
268 return true;
269 }
270
271 void
272 _moddeinit (void)
273 {
274 user_t::callback.add.detach (display_news);
275 os_cmdtree >> os_logonnews;
276 }