blob: ed1f0ac43babd65062ff31579ddbe9e72d8e74d1 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001/* Das Servicepaket der Morgengrauen-Presseagentur. Eine erweiterte Zeitung.
2 Teilweise zur alten Zeitung identisch.
3
4 unter Verwendung der Zeitung von Jof, voellig umgeschrieben.
5
6 (C) Nov 1993 - 1996 Loco@Morgengrauen
7
8 Verwendung ausserhalb von Morgengrauen ist gestattet unter folgenden
9 Bedingungen:
10 - Benutzung erfolgt auf eigene Gefahr. Jegliche Verantwortung wird
11 abgelehnt. Bugs ausserhalb von MG sind nicht mein Problem.
12 - Auch in veraenderten oder abgeleiteten Objekten muss ein Hinweis auf
13 die Herkunft erhalten bleiben.
14 - Bitte fragt mich vorher!
15 Ein Update-Service besteht nicht. Ruecknahme dieser Lizenz ist jederzeit
16 moeglich. Und wer nicht in der Lage ist, neue Versionen selber anzupassen,
17 hat in der Administration eines Muds nichts zu suchen.
18
19
20 04.11.93 Erste brauchbare Version
21 (... seitdem viele Aenderungen ...)
22 13.09.95 ca 02:00 erwarte mpa
23 13.09.95 ca 23:00 RebuildGroupList()
24 15.09.95 vorlaeufig ausgebaut
25 16.09. anders wieder eingebaut, und Kleinigkeiten
26 05.12.95 ca 19:20 Spieler koennen nur noch eigene Artikel loeschen/verl.
27 07.12.95 ca 23:00 Keine Anzeige der Statuszeile. Statuszeilen beginnen
28 mit ~#!, sind damit nicht mit dem Editor erzeugbar.
29 20.12.95 ca 17:00 uebergehe thread/antworten
30 31.01.96 wiederhole/uncatchup
31 22.04.96 Aufraeumen ignorierter threads. ALPHA!
32 24.04.96 + - . als Adressierungen, zeitungsmeldung
33 02.10.96 Kleinigkeiten
34 08.10.96 Kleinigkeiten
35 05.12.96 antworte auf artikel <nr>, reply <neuer titel>,
36 versende artikel, Abkuerzungen fuer Rubrikennamen,
37 Layoutaenderungen,
38 Herkunft bei verlegten Artikeln in Statuszeile
39
40 Letzte Aenderung:
41 04.11.06 Zesstra Anpassung an das neue Verhalten von inherit_list() in LD
42
43*/
44
45#include <properties.h>
46#include <language.h>
47#include <news.h>
48#include <wizlevels.h>
49#include <ansi.h>
50#include <input_to.h>
51#include "/mail/post.h"
52
53inherit "/std/thing";
54inherit NEDIT;
55/*
56#define DEBUG(x) if (funcall(symbol_function('find_player),"zesstra"))\
57 tell_object(funcall(symbol_function('find_player),"zesstra"),\
58 "MPA: "+x+"\n")
59#define DEBUGVAR(x) DEBUG(sprintf(x+":\n%O\n",x))
60*/
61#define DEBUGVAR(x)
62
63// Konfiguration, ggf mudabhaengig
64#define DEFAULTGROUP "allgemeines"
65#define MINIHELPPAGE "p/service/loco/doc/mini-mpa.txt"
66#define HELPPAGE "/p/service/loco/doc/mpa"
67#define WIZHELPPAGE "/p/service/loco/doc/mpa.wiz"
68#define SAVEMSGPATH(pl) ("/open/News/"+(geteuid(pl))+".news")
69#define IS_POST(r) (member(inherit_list(r),STDPOST+".c")>=0)
70#define INITIAL_SUBSCRIPTIONS \
71 ({ "bekanntmachungen", \
72 "d.ebene", \
73 "d.wueste", \
74 "d.inseln", \
75 "d.unterwelt", \
76 "d.dschungel", \
77 "d.gebirge", \
78 "d.polar", \
79 "d.wald", \
80 "d.fernwest", \
81 "d.vland", \
82 "d.anfaenger", \
83 "entwicklung", \
84 })
85
86// Makros etc.
87
88#define TP this_player()
89#define TI this_interactive()
90#define STATUSESCAPE "~#!"
91#define IS_STATUSLINE(s) ((s[0..1]=="#!")||(s[0..2]=="~#!"))
92//#define IS_STATUSLINE(s) (s[0..2]=="~#!")
93// in Rubrik muell fanden sich tatsaechlich noch solche uralten notes...
94#define IGNOREGROUP "*ignored*"
95#define NNADWMSG "*NNADWMSG*"
96#define SYSTEMGROUPS ({IGNOREGROUP,NNADWMSG})
97
98// Aufbau der ignoregroup:
99// ([group1:([tid1:lasttime1,tid2:lasttime2,...]),group2:...])
100
101// Flags fuer Message2string()
102#define M2S_VT100 1
103#define M2S_ANSI M2S_VT100
104#define M2S_REMOTE 2
105
106// Format von lasttitle
107#define LAST_TITLE 0
108#define LAST_WRITER 1
109#define LAST_TIME 2
110#define LAST_TID 3
111#define LAST_GROUP 4
112#define LAST_NR 5
113#define LAST_SIZEOF 6
114
115
116mapping read_until;
117mixed lasttitle; // Aufbau s.o.
118mixed message;
119int deadTID;
120string GROUP;
121
122int GetTID(mixed message);
123private void InitialSubscriptions();
124
Zesstra@Morgengrauen795a0e12016-07-19 00:17:42 +0200125protected void create()
MG Mud User88f12472016-06-24 23:31:02 +0200126{
127 ::create();
128 seteuid(getuid());
129 GROUP="bekanntmachungen";
130 SetProp(P_SHORT,"Die Zeitung");
131 SetProp(P_NAME,"Zeitung");
132 SetProp(P_WEIGHT, 50);
133 SetProp(P_SIZE, 35);
134 SetProp(P_MATERIAL, ([MAT_PAPER: 100]) );
135 SetProp(P_GENDER, FEMALE);
136 AddId(({"nn","zeitung","servicepaket","mpa"}));
137 SetProp(P_NODROP,
138 "Das persoenliche Servicepaket der MPA kann man nicht wegwerfen.\n");
139 SetProp(P_NEVERDROP, 1);
140
141 if (!read_until) read_until=(["muell":-1]);
142}
143
144static mixed _query_read_msg() { return long(); }
145
146long() {
147 return "\
148Dies ist das Servicepaket der MPA (Morgengrauens Presse Agentur) -\n\
149die Zeitung des Morgengrauens.\n\
150Du kannst damit aktuelle Artikel lesen und schreiben, mit folgenden Befehlen:\n\
151 'nn [rubrik]' (Neueste Nachrichten) wuehlt die Rubrik durch und schaut,\n\
152 ob was neu ist. Der erste ungelesene Artikel wird angezeigt.\n\
153 Ohne Argument werden alle Rubriken durchwuehlt.\n\
154 'hilfe mpa' Ausfuehrliche Hilfsseite. Lesen dringend empfohlen!\n\
155Weitere Befehle:\n\
156 rubriken [neu] bestelle <rubrik> ab\n\
157 [lies ]rubrik <rubrik> abonniere <rubrik>\n\
158 inhalt [<rubrik>|neu|suche <text>] wiederhole ...\n\
159 nn <rubriken>|<liste> uebergehe ...\n\
160 [lies ]artikel <nummer>"+
161 ( (IS_LEARNER(TP)) ? " speichere artikel <nr>" : "" )+"\n\
162 schreib <titel> versende artikel [nr] an <adresse>\n\
163 antworte [auf artikel <nr>] [titel] verlege artikel <nr> nach <rubrik>\n\
164 loesche artikel <nr> zeitungsmeldung [neue Meldung]\n\
165 verbrenne zeitung wenn Dir alles zuviel wird....\n\
166"+ (IS_SEER(TP) ? "\
167Mit 'mail' bzw 'mail <spieler>' kannst Du Post lesen und schreiben.\n\
168" : "" )+"\
169Eingebaute aliase: note, catchup, reply, unsubscribe, subscribe, uncatchup.\n\
170Viele Befehle geben mit '<befehl> ?' einige Syntaxhinweise.\n\
171Aktuelle Rubrik: "+GROUP+"\n\
172";
173}
174
175
Zesstra@Morgengrauen795a0e12016-07-19 00:17:42 +0200176void init()
MG Mud User88f12472016-06-24 23:31:02 +0200177{
178 ::init();
179
180 add_action("schreib","schreib");
181 add_action("schreib","schreibe");
182 add_action("schreib","note");
183 add_action("LiesArtikel","lies");
184 add_action("artikel","artikel");
185 add_action("loesche","loesch");
186 add_action("loesche","loesche");
187 add_action("rubrik","rubrik");
188 add_action("inhalt","inhalt");
189 add_action("rubriken","rubriken");
190 add_action("ReadNextUnread","nn");
191 add_action("Catchup","catchup");
192 add_action("Catchup","uebergeh");
193 add_action("Catchup","uebergehe");
194 add_action("Uncatchup","wiederhol");
195 add_action("Uncatchup","wiederhole");
196 add_action("Uncatchup","uncatchup");
197 add_action("Reply","antwort");
198 add_action("Reply","antworte");
199 add_action("Reply2","reply");
200 add_action("HelpPage","hilfe");
201 add_action("HelpPage","man");
202 add_action("Unsubscribe","unsubscribe");
203 add_action("Bestelle","bestell");
204 add_action("Bestelle","bestelle");
205 add_action("Subscribe","subscribe");
206 add_action("Subscribe","abonnier");
207 add_action("Subscribe","abonniere");
208 add_action("MoveMessage","verleg");
209 add_action("MoveMessage","verlege");
210 add_action("SetNNADWMSG","zeitungsmeldung");
211 add_action("Ignore","ignorier");
212 add_action("Ignore","ignoriere");
213 add_action("MailMessage","versende");
214 add_action("verbrennen","verbrenne");
215
216 if (IS_SEER(TP)) {
217 add_action("Mail","mail");
218 }
219 if (IS_LEARNER(TP)) {
220 add_action("SaveMessage","speicher");
221 add_action("SaveMessage","speichere");
222 add_action("ReadNextUnread","read"); /* NF Compatibility Special */
223 }
224 if (IS_ELDER(TP))
225 {
226 add_action("MoveTrash","trash");
227 }
228 init_rescue();
229}
230
Zesstra@Morgengrauen795a0e12016-07-19 00:17:42 +0200231int verbrennen(string str) {
MG Mud User88f12472016-06-24 23:31:02 +0200232 if (!str || !id(str)) return 0;
233 write("Du verbrennst Deine Zeitung mit groesstem Vergnuegen.\n");
234 say(TP->Name(WER)+" verbrennt "+
235 TP->QueryPossPronoun(FEMALE, WEN, SINGULAR)+" Zeitung in einem "
236 "Freudenfeuer.\n");
237 remove(1);
238 return 1;
239}
240
241// KillGroup - loescht eine nicht mehr benoetigte Rubrik aus der Liste.
242// Aufruf aus rubriken() und ReadNextUnread(), wenn die gueltige
243// Rubrikenliste sowieso schon abgerufen wurde.
244
Zesstra@Morgengrauen4090ca62016-07-19 00:22:34 +0200245static void KillGroup(string name) { read_until=m_copy_delete(read_until,name); }
MG Mud User88f12472016-06-24 23:31:02 +0200246
247/* RebuildGroupList() - tut doch nicht so, weil /secure/news anders arbeitet.
248 * Bleibt vorerst zum Nachschlagen.
249static RegisterGroup(name) { read_until[name]=1; }
250static RebuildGroupList() {
251 mixed groups;
252 if ((pointerp(groups=NEWSSERVER->GetGroups()))&&(sizeof(groups))) {
253 map(m_indices(read_until)-groups-SYSTEMGROUPS,#'KillGroup);
254 map(groups-m_indices(read_until),#'RegisterGroup);
255 }
256 TP->SetProp(P_READ_NEWS,read_until);
257}
258*/
259
260
Zesstra@Morgengrauen795a0e12016-07-19 00:17:42 +0200261void _set_autoloadobj(mixed arg) {
MG Mud User88f12472016-06-24 23:31:02 +0200262
263 if (pointerp(arg) && sizeof(arg)>=2)
264 {
265 read_until=arg[1];
266 }
267 else {
268 if (TP)
269 read_until=((TP->QueryProp(P_READ_NEWS))||([]));
270 }
271
272 if (TP) TP->SetProp(P_READ_NEWS,read_until);
273}
274
275_query_autoloadobj() {
276 return 1;
277}
278
279static Mail(str) {
280 object mailer;
281 if (this_interactive()!=this_player()) return 0;
282 mailer=clone_object(MAILER);
283 mailer->SetOfficeName("mpa Kurierdienst");
284 mailer->do_mail( ((!str)||(str=="mail")) ? 0 : TP->_unparsed_args() );
285 return 1;
286}
287
288static varargs string Message2string(mixed msg,mixed messages,int flag,string group) {
289 // Aufrufe: (Nummer,Notes[,flag[,group]]) oder (Note,Notes[,flag[,group]])
290 // flag: M2S_VT100 : ggf ANSI-Codes verwenden
291 // M2S_REMOTE: Rubrik und Artikelnummer ausgeben (speichern, versenden)
292 // Achtung: Wenn flag&M2S_REMOTE, muss msg int sein
293 // group: Name der Rubrik, wenn nicht aktuelle Rubrik. Nur bei M2S_REMOTE
294
295 string txt,hs,s,*m,s2;
296 int i,hi,thisnr,ansiflag;
297
298 if (flag&M2S_REMOTE) txt="Rubrik: "+(group?group:GROUP)+", Artikel: "+
299 (intp(msg)?to_string(msg+1):"???")+" von "+sizeof(messages)+"\n";
300 else txt="";
301
302 if (intp(msg)) {
303 thisnr=msg;
304 msg=messages[msg];
305 } else thisnr=-1;
306 if (!msg) return 0;
307
308 ansiflag=(flag&M2S_VT100)&&(this_player()->QueryProp(P_TTY)!="dumb");
309
310 txt += (ansiflag?ANSI_BOLD:"")+ msg[M_TITLE]+(ansiflag?ANSI_NORMAL:"")+
311 " ("+msg[M_WRITER]+", "+
312 dtime(msg[M_TIME])[5..26]+"):\n";
313// if (geteuid(TP)=="sitopanaki") txt+="TID="+GetTID(msg)+"\n"; // Debug
314 if (!IS_STATUSLINE(msg[M_MESSAGE]))
315 return txt+"\n"+msg[M_MESSAGE];
316 m=explode(msg[M_MESSAGE],"\n");
317 while (IS_STATUSLINE(m[0])) {
318// txt+=m[0]+"\n"; // ###
319 if (sscanf(m[0],"%s rn=%s rt=%d rg=%s",hs,s,hi,hs)==4 ||
320 sscanf(m[0],"%s rn=%s rt=%d",hs,s,hi)==3)
321 {
322 int nr,h;
323 nr=-1;
324 if (pointerp(messages))
325 {
326 for (h=((thisnr>=0) ? thisnr-1 : sizeof(messages)-1);
327 (h>=0 && messages[h][M_TIME]>=hi);h--)
328 if (messages[h][M_TIME]==hi &&
329 lower_case(messages[h][M_WRITER])==lower_case(s))
330 nr=h;
331 }
332 txt+="[Bezug: Artikel "+((nr>=0) ? (nr+1) :
333 (hs==STATUSESCAPE||hs==(group?group:GROUP)?"(geloescht?)":"in "+hs))+
334 " von "+capitalize(s)+" vom "+dtime(hi)[5..26]+"]\n";
335 }
336 if (sscanf(m[0],"%s on=%s ot=%d og=%s",hs,s,hi,hs)==4) {
337 txt+="[Autor: "+s+", "+dtime(hi)[5..26]+", verlegt von "+hs+"]\n";
338 }
339 m=m[1..];
340 }
341 return txt+"\n"+implode(m,"\n");
342}
343
344static varargs lies(mixed str) {
345 mixed num;
346 mixed *messages;
347 int tid;
348
349 if (str=="?"||str=="-?") return
350 write("Syntax: lies <nr>\n"
351 " artikel <nr>\n"
352 "Siehe auch: nn\n"),1;
353
354 if (intp(str)) num=str;
355 if ((!num && (!str || str=="" || sscanf(str,"%d",num)!=1)) || num<=0) {
356 notify_fail("WELCHE Nachricht willst Du lesen?\n");
357 return 0;
358 }
359 if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP)))
360 return notify_fail("Seltsam, die Rubrik '"+GROUP+
361 "' gibt es nicht mehr...\n"), 0;
362 num--;
363 if (sizeof(messages)<=num) {
364 notify_fail("So viele Artikel sind da nicht!\n");
365 return 0;
366 }
367
368 lasttitle=({messages[num][M_TITLE],messages[num][M_WRITER],
369 messages[num][M_TIME],GetTID(messages[num]),GROUP,num});
370 this_player()->More(Message2string(messages[num],messages,M2S_VT100));
371 if (this_player() && IS_LEARNER(this_player()))
372 this_player()->save_me(1);
373 return 1;
374}
375
376static varargs mixed GetGroupName(mixed g,mixed groups) {
377 /* Name einer Rubrik. g ist int oder string, enthaelt Name oder Nummer
378 (ab 1 numeriert) */
379 mixed i,expr,gg;
380 if (!g) return write("Du solltest schon die Rubrik angeben.\n"),0;
381 if (!groups) groups=NEWSSERVER->GetGroups();
382 if (intp(i=g) || sscanf(g,"%d",i)) {
383 if (i>0 && i<=sizeof(groups)) return groups[i-1];
384 write("Eine Rubrik mit der Nummer "+i+" gibt es leider nicht.\n");
385 return 0;
386 }
387 g=lower_case(g);
388 switch(g){
389 case ".": return GROUP;
390 case "+": return groups[(member(groups,GROUP)+1)%sizeof(groups)];
391 case "-":
392 return groups[(member(groups,GROUP)-1+sizeof(groups))%sizeof(groups)];
393 }
394
395 // Existiert die Rubrik genau so?
396 if (member(groups,g)>-1) return g;
397
398 g = regreplace(g,"[[\\]\\*()?]","",1);
399 // haerteres Kriterium: Alle Abschnitte angegeben
400 expr="^"+implode(explode(g,"."),"[^\\.]*\\.")+"[^\\.]*$";
401// write("REGEXP="+expr+"\n");
402 gg=regexp(groups,expr);
403 if (sizeof(gg)==1) return gg[0];
404
405 // weicheres Kriterium: Nicht alle Abschnitte angegeben
406 expr="^(.*\\.)*"+implode(explode(g,"."),".*\\.")+".*$";
407// write("REGEXP="+expr+"\n");
408 gg=regexp(groups,expr);
409
410 if (!sizeof(gg)) {
411 write("Eine Rubrik '"+g+"' gibt es hier leider nicht.\n");
412 return 0;
413 }
414
415 if (sizeof(gg)==1) return gg[0];
416
417 write(break_string("Die Rubrik "+g+" ist nicht eindeutig. Wahrscheinlich "
418 "meinst Du eine der folgenden: "+implode(gg,", ")+".\n",78));
419 return 0;
420}
421
422static rubrik(str)
423{
424 mixed *gruppen;
425 mixed news;
426 int anz,i;
427
428 if (str=="?"||str=="-?") return
429 write("Syntax: rubrik <rubrik>\n"
430 " wechselt die aktuelle Rubrik. Es wird die Nummer der Rubrik,\n"
431 " ihr Name oder jede eindeutige Abkuerzung akzeptiert.\n"),1;
432
433 if (!str || str==0) {
434 if (!pointerp(news=NEWSSERVER->GetNotes(GROUP))){
435 GROUP=DEFAULTGROUP;
436 if (!pointerp(news=NEWSSERVER->GetNotes(GROUP)))
437 return notify_fail("Seltsam, irgendwie geht hier einiges schief...\n"),0;
438 }
439 return write("Aktuelle Rubrik: "+GROUP+" ("+sizeof(news)+" Artikel).\n"),1;
440 }
441 str=GetGroupName(str);
442 if (!str) return 1;
443 GROUP=str;
444 news=NEWSSERVER->GetNotes(GROUP);
445 write(break_string("Ok, Du hast die Rubrik "+GROUP+" mit "+sizeof(news)+
446 " Artikel"+(sizeof(news)==1?"":"n")+" aufgeschlagen.\n",
447 78));
448 return 1;
449}
450
451LiesArtikel(str) {
452 string s1;
453 int i1;
454 if ( !str ) return 0;
455 if (sscanf(str,"rubrik %s",s1))
456 return rubrik(s1);
457 if (sscanf(str,"%d",i1))
458 return lies(to_int(i1));
459 if (sscanf(str,"artikel %s",s1))
460 return lies(s1);
461}
462
463
464/* Ueberpruefe, ob in Rubrik tote threads ignoriert werden. Tot bedeutet,
465 dass der letzte darin uebergangene Artikel bereits expired ist UND
466 keine Artikel aus diesem thread mehr vorhanden sind.
467 ACHTUNG: Es kann passieren, dass dazwischen noch ein neuer Artikel
468 dazugekommen ist.
469 Hier wird auf expired geprueft und ggf Variable deadTID gesetzt. Wird beim
470 Lesen mit nn ein Artikel mit dieser TID gefunden (passiert direkt hinter
471 Pruefung), wird deadTID wieder auf 0 gesetzt. Ist deadTID beim Umschalten
472 auf naechste Rubrik !=0, ist der thread tot.
473*/
474
475static int CheckThreads(string rubrik,int timeout) {
476 mixed tids;
477 int i;
478
479// deadTID=0;
480 tids=m_indices(read_until[IGNOREGROUP][rubrik]);
481 for (i=sizeof(tids)-1;i>=0&&!deadTID;i--)
482 if (read_until[IGNOREGROUP][rubrik][tids[i]]<timeout) deadTID=tids[i];
483 return 1;
484}
485
486static int rubriken(mixed arg)
487{
488 mixed *gruppen, *messages;
489 mixed news;
490 int anz,i,lasttime,timeout,foundone;
491 string s;
492
493 if (arg=="?"||arg=="-?") return
494 write("Syntax: rubriken listet alle Rubriken\n"
495 " rubriken neu nur Rubriken mit ungelesenen Artikeln\n"),1;
496
497 gruppen=NEWSSERVER->GetGroups();
498 map(m_indices(read_until)-gruppen-SYSTEMGROUPS,#'KillGroup); // ');
499 s="\nEs gibt zur Zeit ";
500 anz=sizeof(gruppen);
501 if (anz==0) {
502 write(s+"keine Rubriken (wie seltsam ...)\n");
503 return 1;
504 }
505 s+=anz+" Rubrik"+(anz==1 ? "" : "en")+".";
506 if (arg=="neu") s+="\nDavon enthalten neue Artikel:\n\n";
507 else s+="\n(* oder x: enthaelt neue Artikel, x oder -: abbestellt, "
508 ">: aktuelle Rubrik)\n\n";
509 for (i=0;i<anz;i++) {
510 timeout=read_until[gruppen[i]];
511 /* GetNewsTime lieferte leider manchmal was falsches :-( */
512 /* jetzt hoffentlich richtig? Wenn nicht, das if ausklammern */
513 if ( arg!="neu" || (lasttime=NEWSSERVER->GetNewsTime(gruppen[i])) > timeout) {
514 messages=NEWSSERVER->GetNotes(gruppen[i]);
515 if (!messages || !sizeof(messages)) lasttime=0;
516 else lasttime=messages[sizeof(messages)-1][M_TIME];
517 foundone=1;
518 }
519 if (arg!="neu" || (timeout>=0 && lasttime>abs(timeout)))
520 s+=sprintf("%s%s%3d\. %-39.39s: ",
521 ((gruppen[i]==GROUP)?">":" "),
522 ((lasttime>abs(timeout)) ? ((timeout<0) ? "x" : "*")
523 : ((timeout<0) ? "-" : " ") ),
524 i+1,gruppen[i])+
525 (lasttime ? sprintf("%3d Artikel (%s)\n",
526 sizeof(messages),
527 // ((sizeof(messages)==1) ? ". " : "en."),
528 dtime(lasttime)[5..12]+ctime(lasttime)[<2..]) :
529 " - leer -\n");
530 }
531 if (arg=="neu"&&!foundone) s+="Keine Rubrik enthaelt neue Artikel.\n";
532 this_player()->More(s);
533 return 1;
534}
535
536#define M_READNEXT 1
537#define M_LISTNEW 2
538#define M_LISTNEWGR 3
539#define M_READGR 4
540
541static ReadNextUnread(str)
542{
543 string *groups,group;
544 mixed *messages;
545 int curgr,curmsg,timeout,start,nrgroups,sog,mode;
546
547 if (str=="mail") return Mail(0); /* NF Compatibility Special */
548
549 if (str=="?"||str=="-?") return
550 write("Syntax: nn naechster neuer Artikel\n"
551 " nn <rubrik> in entspr. Rubrik, wenn da was neu ist\n"
552 " nn rubriken Liste der Rubriken mit neuen Artikeln\n"
553 " nn liste Liste der ungelesenen Artikel\n"),1;
554
555 groups=NEWSSERVER->GetGroups();
556 deadTID=0;
557 map(m_indices(read_until)-groups-SYSTEMGROUPS,#'KillGroup); //'
558 nrgroups=sizeof(groups);
559 if (str && str!="rubriken" && str!="liste"){
560 if (!group=GetGroupName(str)) return 1;
561 }
562 else
563 group=0;
564 if (group && (curgr=member(groups,group)+1)) {
565 --curgr;
566 if (curgr<0 || curgr>=sizeof(groups))
567 return notify_fail("Nee... so eine Rubrik gibts hier nicht.\n"),0;
568 GROUP=group;
569 start=curgr+1;
570 mode=M_READGR;
571 write("Rubrik "+(curgr+1)+": "+GROUP+"\n");
572 } else {
573 switch (str) {
574 case 0: mode=M_READNEXT; break;
575 case "liste": mode=M_LISTNEW; write("Du hast noch nicht gelesen:\n"); break;
576 case "rubriken": return rubriken("neu");
577 default:
578 notify_fail("\
579Diesen Parameter verstehe ich nicht. Entweder gar nichts, \"liste\"\n\
580\"rubriken\", oder Name bzw. Nummer einer Rubrik.\n");
581 return 0;
582 }
583 curgr=member(groups,GROUP);
584 start=curgr+nrgroups;
585 }
586 if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP))){
587 GROUP=DEFAULTGROUP;
588 if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP)))
589 return notify_fail("Seltsam, irgendwie geht hier einiges schief...\n"),0;
590 }
591 timeout=read_until[GROUP];
592 curmsg=0;
593 sog=sizeof(messages);
594 while (curgr<start) {
595 ++curmsg;
596 if (curmsg>sog) {
597 if (deadTID)
598 read_until[IGNOREGROUP][GROUP]=
599 m_copy_delete(read_until[IGNOREGROUP][GROUP],deadTID);
600 ++curgr;
601 deadTID=0;
602 if (mode!=M_READGR) {
603 GROUP=groups[curgr%nrgroups];
604 timeout=read_until[GROUP];
605 if (!timeout) read_until[GROUP]=1; // Nimm neue Gruppen in Liste auf
606 if (timeout<0 || timeout>=NEWSSERVER->GetNewsTime(GROUP)) {
607 sog=0; /* Ueberlistung: Gruppe hat nix neues oder */
608 curmsg=1; /* ist unsubscribed */
609 }
610 else {
611 messages=NEWSSERVER->GetNotes(GROUP);
612 curmsg=0;
613 sog=sizeof(messages);
614 }
615 }
616 } else {
617 if ((timeout>=0 || mode==M_READGR) && messages[curmsg-1][M_TIME] > abs(timeout)) {
618 if (pointerp(this_player()->QueryProp(P_IGNORE)) &&
619 member(this_player()->QueryProp(P_IGNORE),
620 lower_case(messages[curmsg-1][M_WRITER])+".news") != -1) {
621 printf("Uebergehe ignorierten Artikel %d von %s in Rubrik %s.\n",
622 curmsg,messages[curmsg-1][M_WRITER],GROUP);
623 read_until[GROUP]=messages[curmsg-1][M_TIME];
624 if (TP) TP->SetProp(P_READ_NEWS,read_until);
625 } else if
626 (read_until[IGNOREGROUP]&&
627 read_until[IGNOREGROUP][GROUP]&&
628 CheckThreads(GROUP,messages[0][M_TIME])&& /* Tote threads weg */
629 read_until[IGNOREGROUP][GROUP][GetTID(messages[curmsg-1])]) {
630 printf("Uebergehe Artikel %d aus ignoriertem Thread.\n",curmsg);
631 read_until[IGNOREGROUP][GROUP][GetTID(messages[curmsg-1])]=
632 messages[curmsg-1][M_TIME];
633 if (deadTID&&deadTID==GetTID(messages[curmsg-1])) deadTID=0;
634 read_until[GROUP]=messages[curmsg-1][M_TIME];
635 if (TP) TP->SetProp(P_READ_NEWS,read_until);
636 } else {
637 write("\nRubrik "+(curgr%nrgroups+1)+": "+GROUP+", Artikel: "+curmsg+" von "+sog+"\n");
638 if (mode==M_LISTNEW) {
639 write(sprintf(" %-45s [%-11s] %s\n",messages[curmsg-1][M_TITLE],
640 messages[curmsg-1][M_WRITER],
641 dtime(messages[curmsg-1][M_TIME])[5..16]));
642 } else { /* mode == M_READNEXT || mode==M_READGR */
643 if (timeout>=0) read_until[GROUP]=messages[curmsg-1][M_TIME];
644 else read_until[GROUP]=-messages[curmsg-1][M_TIME];
645 if (TP) TP->SetProp(P_READ_NEWS,read_until);
646 return (lies(""+curmsg));
647 }
648 }
649 }
650 /* sonst mach einfach garnix. Schleife laeuft weiter. */
651 }
652 }
653 switch(mode) {
654 case M_LISTNEW: return 1;
655 case M_READNEXT: write((read_until[NNADWMSG]||"Nix Neues auf der Welt.")
656 +"\n"); break;
657 case M_READGR: write("Nix Neues in dieser Rubrik.\n"); break;
658 }
659 return 1;
660}
661
662
663static SetNNADWMSG(str) {
664 if (str=="?"||str=="-?") return
665 write("Syntax: zeitungsmeldung <neue Meldung> setzt Meldung\n"
666 " zeitungsmeldung loescht Meldung\n"),1;
667 if (!read_until[NNADWMSG]) {
668 write("Du hast zur Zeit keine eigene NNADW-Meldung definiert.\n");
669 if (!str) return 1;
670 }
671 else write("Deine alte NNADW-Meldung war:\n"+read_until[NNADWMSG]+"\n");
672 if (!str) {
673 read_until=m_copy_delete(read_until,NNADWMSG);
674 write("Meldung ist geloescht, es gilt wieder die Standardmeldung.\n");
675 } else {
676 read_until[NNADWMSG]=this_player()->_unparsed_args();
677 write("Deine neue Meldung lautet jetzt:\n"+read_until[NNADWMSG]+"\n");
678 }
679 if (TP) TP->SetProp(P_READ_NEWS,read_until);
680 return 1;
681}
682
683varargs int InterpretTime(mixed a,int flag) {
684 // string oder string *
685 // akzeptiert folgende Formate:
686 // dd.mm.jj (Rueckgabe: 0:00 des entsprechenden Tages)
687 // vor [<anz> d|tagen] [<anz> h|stunden] [<anz> m|minuten]
688 // flag=1: "inklusive": bei dd.mm.jj-Format 23:59:59 statt 0:00 Uhr
689
690 int i,j,k,t,nrargs;
691 string s;
692 if (stringp(a)) a=explode(a," ");
693
694// printf("%O\n",a);
695
696 if ((nrargs=sscanf(a[0],"%d.%d.%d",i,j,k))==3 ||
697 (nrargs=sscanf(a[0],"%d.%d.",i,j))==2) {
698 // Datum -> Zeit: Funktioniert im Zeitraum 1973 - ca. 2090
699 // in Zeitzonen mit ganzen Stunden ggue Rechneruhr.
700 if (nrargs==2)
701 k=70+time()/31536000;
702 if (k<70) k+=100;
703 if (k>1970) k-=1900;
704 if (k<70||k>150) return
705 write("Unzulaessiges Jahr (erlaubt: 70-heute).\n"),0;
706 t=(k-70)*31536000;
707
708 if (i<1||i>31) return write("Unzulaessiger Tag (erlaubt: 1-31).\n"),0;
709 if (j<1||j>12) return write("Unzulaessiger Monat (erlaubt: 1-12).\n"),0;
710// printf("%d.%d.%d\n",i,j,k);
711 s=ctime(t);
712 if ((j>2) && !(k%4)) t+=86400; // Schaltjahrkorrektur fuer Monate>=3
713 t+=({ 0, 2678400, 5097600, 7776000,
714 10368000, 13046400, 15638400, 18316800,
715 20995200, 23587200, 26265600, 28857600})[j-1];
716 t+=86400*(i-1);
717 t+=86400*(32-to_int(s[8..9])); // Schaltjahrkorrektur
718 t-=3600*to_int(s[11..12]); // Zeitzonenkorrektur
719 t-=3600*to_int(ctime(t)[11..12]); // Sommerzeitkorrektur
720// write("Kontrolle: "+dtime(t)+"\n");
721 if (nrargs==2 && t>time()) t-=31536000;
722 return (flag?t+86399:t);
723 }
724
725 t=0;
726 if (a[0]=="vor") for (i=sizeof(a)-1;i>0;i--) {
727 switch (a[i]) {
728 case "m":
729 case "minuten":
730 case "min":
731 case "minute":
732 t+=60*to_int(a[i-1]);
733 break;
734 case "h":
735 case "stunde":
736 case "stunden":
737 case "s":
738 t+=3600*to_int(a[i-1]);
739 break;
740 case "d":
741 case "tag":
742 case "tage":
743 case "t":
744 t+=86400*to_int(a[i-1]);
745 break;
746 default:
747 if (!to_int(a[i]))
748 write("Argumentfehler: Kann nichts mit '"+a[i]+"' anfangen.\n");
749 }
750 return time()-t;
751 }
752 else return write("Argumentfehler.\n"),0;
753}
754
755static Catchup(string str)
756{
757 int welche,zeit,i;
758 string gr;
759 mixed groups,news,args;
760
761 if (!pointerp(NEWSSERVER->GetNotes(GROUP)))
762 return notify_fail("Seltsam, die Rubrik '"+GROUP+
763 "' gibt es nicht mehr...\n"), 0;
764
765 str=this_player()->_unparsed_args(); // wg. Datum
766 if (str) str=lower_case(str);
767 else str=GROUP; // default: aktuelle Rubrik komplett.
768
769 if (str=="?"|| str=="-?") return CatchupSyntax();
770
771 // uebergehe Antworten (Thread ignorieren)
772 if (str&&(str[0..6]=="antwort"||str=="thread")) {
773 if (!pointerp(lasttitle)) return
774 write("Du hast bisher noch keinen Artikel gelesen, damit kann ich nicht wissen,\nwelchen Thread du uebergehen willst.\n"),1;
775 if (!read_until[IGNOREGROUP]) read_until[IGNOREGROUP]=([]);
776 if (!read_until[IGNOREGROUP][GROUP]) read_until[IGNOREGROUP][GROUP]=([]);
777 if (read_until[IGNOREGROUP][GROUP][lasttitle[3]]) {
778 read_until[IGNOREGROUP][GROUP]=m_copy_delete(read_until[IGNOREGROUP][GROUP],lasttitle[3]);
779 write("Dieser Thread wird jetzt nicht mehr uebergangen.\n");
780 } else {
781 read_until[IGNOREGROUP][GROUP][lasttitle[3]]=lasttitle[2];
782 write("Dieser Thread wird ab sofort uebergangen.\nFalls das ein Irrtum war, wiederhole den Befehl augenblicklich.\n");
783 }
784 if (TP) TP->SetProp(P_READ_NEWS,read_until);
785 return 1;
786 }
787
788 groups=NEWSSERVER->GetGroups();
789
790 args=explode(str," ");
791
792 // Uebergehe alles
793
794 if (args[0]=="alle" || args[0]=="alles" || args[0]=="all") {
795 if (sizeof(args)<=1) zeit=time()-1;
796 else if (args[1]!="bis") return CatchupSyntax();
797 else if (sizeof(args)<3) return CatchupSyntax();
798
799 else zeit=InterpretTime(args[2..],1);
800 if (zeit>time()) zeit=time()-1;
801 write("Uebergehe alle Rubriken bis "+dtime(zeit)+".\n");
802 for (welche=0;welche<sizeof(groups);++welche) {
803 gr=groups[welche];
804// zeit=NEWSSERVER->GetNewsTime(gr);
805 if (abs(read_until[gr])<zeit)
806 read_until[gr]=(read_until[gr]>=0)?zeit:-zeit;
807 if (TP) TP->SetProp(P_READ_NEWS,read_until);
808 }
809 return 1;
810 }
811
812 // Anzahl Artikel
813
814 if (sizeof(args)>=2 && args[1]=="artikel") {
815 if (!to_int(args[0])) return CatchupSyntax();
816 news=NEWSSERVER->GetNotes(GROUP);
817 for (i=sizeof(news)-1;i>=0&&news[i][M_TIME]>read_until[GROUP];i--);
818 welche=i+to_int(args[0]);
819 if (welche>=sizeof(news)) welche=sizeof(news)-1;
820 write("Uebergehe die naechsten "+(welche-i)+" Artikel in Rubrik "+
821 GROUP+"\n.");
822 if (welche>=0) {
823 zeit=news[welche][M_TIME];
824 read_until[GROUP]=(read_until[GROUP]>=0)?zeit:-zeit;
825 if (TP) TP->SetProp(P_READ_NEWS,read_until);
826 }
827 return 1;
828 }
829
830 // einzelne Rubrik.
831
832 if (!(gr=GetGroupName(args[0]))) return 1;
833 news=NEWSSERVER->GetNotes(gr);
834 if (!sizeof(news)) {
835 write("Rubrik "+gr+" ist leer.\n");
836 return 1;
837 }
838// zeit=news[sizeof(news)-1][M_TIME];
839 if (sizeof(args)<=1)
840 zeit=time();
841 else
842 if (args[1]!="bis") return CatchupSyntax();
843 else
844 zeit=InterpretTime(args[2..],1);
845 if (zeit>time()) zeit=time();
846 read_until[gr]=zeit;
847 if (TP) TP->SetProp(P_READ_NEWS,read_until);
848 write("Uebergehe "+gr+" bis "+dtime(zeit)+",\nletzter Artikel war vom "+
849 dtime(NEWSSERVER->GetNewsTime(gr))+"\n");
850 return 1;
851}
852
853
854static Ignore(str) {
855 if (str=="thread"||str=="antworten") return Catchup(str);
856 return 0;
857}
858
859static CatchupSyntax() {
860 write("Syntax des Befehls uebergehe (oder catchup):\n"
861 " uebergehe [rubrik] (default: aktuelle Rubrik)\n"
862 " uebergehe alles (in allen Rubriken)\n"
863 " uebergehe <anz> artikel (in akt. Rubrik)\n"
864 " uebergehe [rubrik]|alles bis <tag>.<monat>.[<jahr>]\n"
865 " uebergehe [rubrik]|alles bis vor <zeit> wobei\n"
866 " <zeit> = [<n> d|tage] [<n> h|stunden] [<n> m|min|minuten]\n"
867 " uebergehe thread|antworten (entspr. 'ignoriere thread')\n");
868
869 return 1;
870}
871
872
873static int UncatchupSyntax()
874{
875 notify_fail(
876 "Syntax: wiederhole <anz> [artikel]\n"
877 " wiederhole [ab vor] [<anz> m|minute[n]] [<anz> h|stunde[n]] [<anz> d|tag[e]]\n"
878 " wiederhole ab tag.monat[.jahr]\n"
879 " wiederhole alles\n"
880 "Der wiederhole- oder uncatchup-Befehl bezieht sich immer auf die aktuelle\n"
881 "Rubrik und markiert die angegebenen Artikel wieder als ungelesen.\n"
882 "Zeiten (2. Syntax) sind rueckwaerts ab aktueller Uhrzeit gerechnet.\n"),0;
883 return 0;
884}
885
886
887static Uncatchup(string str)
888{
889 mixed args;
890 int i,zeit;
891 int mode; // 0 = nix, 1=Anzahl Artikel, 2=Zeit, 3=alles
892
893 str=this_player()->_unparsed_args(); // wg. Datum
894 if ( !TP || !str || !stringp(str) || str=="?" || str=="-?" )
895 return UncatchupSyntax();
896
897 if (!pointerp(NEWSSERVER->GetNotes(GROUP)))
898 return notify_fail("Seltsam, die Rubrik '"+GROUP+
899 "' gibt es nicht mehr...\n"), 0;
900
901 args=({""})+explode(lower_case(str)," ");
902 if (args[1]=="ab") {
903 mode=2;
904 if (sizeof(args)<3)
905 return UncatchupSyntax();
906 zeit=InterpretTime(args[2..]);
907 } else {
908 zeit=time();
909 for (i=sizeof(args)-1;i>0;i--) {
910 switch(args[i]){
911 case "alles":
912 case "alle":
913 case "all":
914 if (mode&&mode!=3) return
915 notify_fail("Bitte nur Zeit ODER alles ODER Anzahl angeben!\n"),0;
916 mode=3;
917 break;
918 case "minuten":
919 case "minute":
920 case "m":
921 case "stunden":
922 case "stunde":
923 case "h":
924 case "tage":
925 case "tag":
926 case "d":
927 if (mode&&mode!=2) return
928 notify_fail("Bitte nur Zeit/Datum ODER alles ODER "
929 "Anzahl angeben!\n"),0;
930 mode=2;
931 zeit-=(((args[i][0]=='m') ? 60 :
932 ((args[i][0]=='s' || args[i][0]=='h') ? 3600 : 86400))
933 *to_int(args[i-1]));
934 i--;
935 break;
936 case "artikel":
937 if (mode&&mode!=1) return
938 notify_fail("Bitte nur Zeit/Datum ODER alles ODER "
939 "Anzahl angeben!\n"),0;
940 mode=1;
941 zeit=to_int(args[i-1]);
942 i--;
943 break;
944 case "ab":
945 return
946 notify_fail("Bitte nur Zeit/Datum ODER alles ODER "
947 "Anzahl angeben!\n"),0;
948 default:
949 if (!to_int(args[i]))
950 return notify_fail("Unbekanntes Argument '"+args[i]+
951 "'! Aktion abgebrochen.\n"),0;
952 if (mode&&mode!=1) return
953 notify_fail("Bitte nur Zeit/Datum ODER alles ODER "
954 "Anzahl angeben!\n"),0;
955 mode=1;
956 zeit=to_int(args[i]);
957 }
958 }
959 }
960
961 switch(mode){
962 case 0:
963 return notify_fail("Gib bitte irgendeine Einheit an "
964 "(Hilfe mit wiederhole -?)!\n");
965 case 2:
966 read_until[GROUP]=(read_until[GROUP]>=0)?zeit:-zeit;
967 write(break_string("Markiere alle Artikel in Rubrik "+GROUP+
968 " seit "+dtime(zeit)+" als ungelesen.\n",78));
969 break;
970 case 3:
971 read_until[GROUP]=(read_until[GROUP]>=0?1:-1);
972 write("Markiere die komplette Rubrik "+GROUP+" als ungelesen.\n");
973 break;
974 case 1:
975 write(break_string("Markiere die letzten "+zeit+
976 " gelesenen Artikel in Rubrik "+GROUP+" als ungelesen.\n",78));
977 { int h; mixed notes;
978 notes=NEWSSERVER->GetNotes(GROUP);
979 h=sizeof(notes)-1;
980 while ( (h>=0) && (abs(read_until[GROUP]) < notes[h][M_TIME]) ) {
981 h--;
982 }
983 if (h==-1||h<zeit)
984 read_until[GROUP]=
985 (read_until[GROUP]>=0)?1:-1;
986 else
987 read_until[GROUP]=(
988 (read_until[GROUP]>=0)?notes[h-zeit][M_TIME]
989 :-notes[h-zeit][M_TIME]);
990 }
991 }
992 write("Ok. Du kannst die als ungelesen markierten Artikel "
993 "mit nn nochmal lesen.\n");
994
995 if (TP) TP->SetProp(P_READ_NEWS,read_until);
996 return 1;
997}
998
999
Zesstra@Morgengrauen4090ca62016-07-19 00:22:34 +02001000mapping QueryRead() {
1001 return read_until;
MG Mud User88f12472016-06-24 23:31:02 +02001002}
1003
Zesstra@Morgengrauen4090ca62016-07-19 00:22:34 +02001004static int CatchNewsError(int err,string text4minus3) {
MG Mud User88f12472016-06-24 23:31:02 +02001005 switch (err) {
1006 case 1: return 1;
1007 case -1: write("Du darfst in dieser Rubrik nicht schreiben!\n"); return 0;
1008 case -2: write("Die Rubrik gibt es nicht mehr, sehr seltsam...\n"); return 0;
1009 case -3: write(text4minus3+"\n"); return 0;
1010 default: write("Interner Fehler "+err+", Erzmagier verstaendigen!\n"); return 0;
1011 }
Zesstra66b76672016-08-31 22:43:33 +02001012 return 0;
MG Mud User88f12472016-06-24 23:31:02 +02001013}
1014
Zesstra@Morgengrauen4090ca62016-07-19 00:22:34 +02001015static varargs int schreib(string str,string pretext,int called_by_itself,
1016 string statuslines)
1017{
MG Mud User88f12472016-06-24 23:31:02 +02001018 int err;
1019
1020 if (str=="?"||str=="-?") {
1021 write("Syntax: schreib <Titel>\n"
1022 " beginnt einen neuen Artikel in der Zeitung.\n");
1023 return 1;
1024 }
1025
1026 if (!this_interactive() || !this_interactive()->query_real_name()) return 0;
1027 if (!called_by_itself && extern_call() && !pretext)
1028 str=this_interactive()->_unparsed_args()||"";
1029 if (called_by_itself && str=="~q") {
1030 write("Abgebrochen.\n");
1031 return 1;
1032 }
1033 if (!CatchNewsError(
1034 NEWSSERVER->AskAllowedWrite(GROUP),
1035 "Diese Rubrik ist leider schon randvoll!")) return 1;
1036 if (!called_by_itself)
1037 write("Neuer Artikel in Rubrik "+GROUP+":\n");
1038 if (!str || str=="" || str=="artikel") {
1039 input_to("schreib", INPUT_PROMPT, "Titel des Artikels: ", pretext,1);
1040 return 1;
1041 }
1042 // writer=this_interactive()->query_real_name();
1043 message=allocate(6);
1044 message[M_BOARD]=GROUP;
1045 message[M_TITLE]=killctrl(str);
1046 message[M_MESSAGE]=statuslines;
1047 write("Titel ist: "+str+".\n\
1048Gib jetzt Deinen Text ein,\n\
1049** oder . wenn Du fertig bist, ~q zum Abbrechen, ~h fuer eine Hilfsseite.\n");
1050 nedit("PostNote",pretext);
1051 return 1;
1052}
1053
1054static varargs Reply(string str,string newtitle) {
1055 mixed dummy,replytitle,s;
1056 int nr;
1057
1058 if ((dummy=(str||newtitle))=="?"||dummy=="-?") {
1059 write("Der Antworte-Befehl ist doppelt belegt.\n"
1060 "1. (Zeitung): Schreibe Antwort auf einen Artikel in der Zeitung.\n"
1061 " Syntax: antworte\n"
1062 " antworte auf artikel <nr> [neuer Titel]\n"
1063 " reply [auf artikel <nr> | to note <nr>] [neuer Titel]\n"
1064 "2. aehnlich 'sage':\n"
1065 " Du tippst zum Beispiel:\n"
1066 " antworte ja, das weiss ich\n"
1067 " Alle Spieler im Raum sehen dann:\n"
1068 " <Dein Name> antwortet: ja, das weiss ich.\n"
1069 "Bitte beachte, dass jede Syntax, die auf den antworte-Befehl der "
1070 "Zeitung\npasst, auch von der Zeitung ausgewertet wird.\n");
1071 return 1;
1072 }
1073
1074 if (str&&
1075 ((sscanf(lower_case(str),"auf artikel %d",dummy)==1 &&
1076 str=this_player()->_unparsed_args()[12..])||
1077 (sscanf(lower_case(str),"to note %d",dummy)==1 &&
1078 str=this_player()->_unparsed_args()[8..]))) {
1079 mixed notes;
1080 notes=NEWSSERVER->GetNotes(GROUP);
1081 if (dummy<1||dummy>sizeof(notes))
1082 return write("Einen Artikel mit der Nummer "+dummy+
1083 " gibt es in dieser Rubrik nicht.\n"),1;
1084 dummy--;
1085 replytitle=({notes[dummy][M_TITLE],notes[dummy][M_WRITER],
1086 notes[dummy][M_TIME],GetTID(notes[dummy]),GROUP});
1087 DEBUGVAR(str);
1088 if (!newtitle&&str&&sizeof(str)&&sscanf(str,"%d %s",dummy,str)==2)
1089 newtitle=str;
1090 }
1091 else if (!str||!sizeof(str)) {
1092 if (!lasttitle) return
1093 write("Du hast noch gar nichts gelesen, worauf Du "
1094 "antworten koenntest.\n"),1;
1095 replytitle=lasttitle;
1096 }
1097 else return 0;
1098
1099// return ComposeReply(replytitle);
1100//}
1101//
1102//
1103//ComposeReply(mixed replytitle) {
1104
1105 if (!newtitle) {
1106 if (replytitle[0][0..7]=="Re: Re: ") newtitle="Re^3: "+replytitle[0][8..];
1107 else if (sscanf(replytitle[0],"Re^%d: %s",nr,newtitle))
1108 newtitle="Re^"+(nr+1)+": "+newtitle;
1109 else newtitle="Re: "+replytitle[0];
1110 }
1111 return schreib(newtitle,0,0,
1112 STATUSESCAPE+" rn="+replytitle[LAST_WRITER]+
1113 " rt="+replytitle[LAST_TIME]+
1114 " rg="+replytitle[LAST_GROUP]+"\n"+
1115 STATUSESCAPE+" tid="+replytitle[LAST_TID]+"\n");
1116}
1117
1118static Reply2(str) {
1119 str = this_player()->_unparsed_args();
1120 if (!str||str[0..11]=="auf artikel "||str[0..7]=="to note ")
1121 return Reply(str);
1122 return Reply(0,str);
1123}
1124
1125static void InformPlayers(string group,string player,string text)
1126{
1127 object *players;
1128 int i;
1129 mixed data;
1130 string ig;
1131
1132 players=users();
1133 ig=lower_case(player)+".news";
1134 for (i=sizeof(players)-1;i>=0;i--) {
1135 data=players[i]->QueryProp(P_WAITFOR);
1136 if (pointerp(data)&&(member(data,"Mpa")>-1)) {
1137 data=players[i]->QueryProp(P_READ_NEWS);
1138 if (mappingp(data)&&(data[group]>0)) {
1139 data=players[i]->QueryProp(P_IGNORE);
1140 if ((!pointerp(data))||(member(data,ig)==-1))
1141 tell_object(players[i],text);
1142 }
1143 }
1144 }
1145}
1146
1147static PostNote(text) {
1148 int err;
1149 string sig;
1150
1151 if (!text) {
1152 write("Abbruch! Artikel landet im Reisswolf.\n");
1153 return 1;
1154 }
1155 if (!sizeof(old_explode(text,"\n")-
1156 ({"q","quit"," **","** ","ende","","exit"," "})
1157 ) )
1158 return write("\
1159ACHTUNG: Wolltest Du wirklich einen Artikel ohne Inhalt in die mpa setzen?\n\
1160Artikel ohne erkennbaren Inhalt werden NICHT veroeffentlicht. Bitte ueber-\n\
1161pruef Deine Syntax, falls Du keinen Artikel schreiben wolltest, oder schreib\n\
1162auch ein bisschen Text!\n\
1163Artikel landet im Reisswolf.\n"),1;
1164 if (!message[M_MESSAGE])
1165 message[M_MESSAGE] = text;
1166 else
1167 message[M_MESSAGE]+=text;
1168 if (sig=read_file("/players/"+geteuid(this_interactive())+"/.signature"))
1169 message[M_MESSAGE]+=sig;
1170 if (!CatchNewsError(NEWSSERVER->WriteNote(message),
1171 "Diese Rubrik ist voll. Mist, da war jemand schneller...")) {
1172 write("Versuch, Platz in der Rubrik zu finden, dann kannst Du mir ~r nochmal\nin den Text einsteigen und ihn anschliessend veroeffentlichen.\n(Vorschlag: Einen veralteten Artikel abhaengen oder verlegen.\n");
1173 return 0;
1174 }
1175 write("OK, Artikel ist veroeffentlicht.\n");
1176 say(capitalize(TP->name())+
1177 " hat einen Artikel in der Zeitung veroeffentlicht.\n");
1178 if (geteuid(TP)!="sitopanaki")
1179 InformPlayers(message[M_BOARD],geteuid(this_interactive()),
1180 "* MPA: Neuer Artikel von "+
1181 capitalize(geteuid(this_interactive()))+
1182 " in Rubrik \""+message[M_BOARD]+"\".\n");
1183 message=0; /* Platz sparen! */
1184 return 1;
1185}
1186
1187
1188//static // allowing aliasing *Rumata* 5/8/96
1189inhalt(str) {
1190 int i,endflag,timeout;
1191 string *gruppen,s,txt,suche;
1192 mixed messages;
1193
1194 if (str=="?"||str=="-?") return
1195 write("Syntax: inhalt [<rubrik>] [ende] [suche <text>]\n"),1;
1196
1197 str=(!str)?({}):explode(str," ");
1198
1199 if (sizeof(str) && (str[0]=="neu" || str[0]=="neues") )
1200 return ReadNextUnread("liste"),1;
1201
1202 if (endflag=member(str,"ende")+1) str-=({"ende"});
1203 if (((i=member(str,"suche")) != -1) && (sizeof(str) > i)) {
1204 suche=lower_case(implode(str[i+1..]," "));
1205 str=str[0..i-1];
1206 }
1207 else
1208 suche=0;
1209 if (!sizeof(str)) {
1210 str=GROUP;
1211 if (!pointerp(messages=NEWSSERVER->GetNotes(str))){
1212 str=GROUP=DEFAULTGROUP;
1213 if (!pointerp(messages=NEWSSERVER->GetNotes(str)))
1214 return notify_fail("Seltsam, irgendwie geht hier einiges schief...\n"),0;
1215 }
1216 }
1217 else {
1218 str=GetGroupName(str[0]);
1219 if (!str) return 1;
1220 messages=NEWSSERVER->GetNotes(str);
1221 }
1222 timeout=abs(read_until[str]);
1223 s="Inhalt der Rubrik "+str+":\n\n";
1224 if (!pointerp(messages) || !sizeof(messages))
1225 return
1226 write(s+"Zur Zeit befinden sich keine Artikel in dieser Rubrik.\n"),1;
1227 if (suche)
1228 s+="Suche nach '"+suche+"' in der Rubrik ergab folgende Treffer:\n\n";
1229 else
1230 if (sizeof(messages)==1)
1231 s+="Zur Zeit befindet sich ein Artikel in der Rubrik:\n\n";
1232 else
1233 s+="Zur Zeit befinden sich "+sizeof(messages)+
1234 " Artikel in der Rubrik:\n\n";
1235 if (endflag&&(sizeof(messages)>16)&&
1236 messages[sizeof(messages)-16][M_TIME]>=timeout) timeout=-1;
1237 for (i=(endflag?(((endflag=sizeof(messages)-15)<0)?0:endflag):0);
1238 i<sizeof(messages);i++)
1239 {
1240 txt=sprintf("%2d.%s%-48s%4d (%-11s) %s\n",i+1,
1241 (((timeout>=0) && timeout<messages[i][M_TIME] )?
1242 ( (timeout=-1),"*"):" "),messages[i][M_TITLE],
1243 sizeof(explode(messages[i][M_MESSAGE],"\n")),
1244 messages[i][M_WRITER],
1245 dtime(messages[i][M_TIME])[5..11]);
1246 if (!suche || (strstr(lower_case(txt), suche) != -1))
1247 s+=txt;
1248 }
1249 if (endflag) write(s);
1250 else this_player()->More(s);
1251 return 1;
1252}
1253
1254
1255static artikel(str) {
1256 return lies(str);
1257}
1258
1259
Zesstra@Morgengrauen795a0e12016-07-19 00:17:42 +02001260static int loesche(string str) {
MG Mud User88f12472016-06-24 23:31:02 +02001261 int num;
1262 mixed *messages;
1263
1264 if (str=="?"||str=="-?") return
1265 write("Syntax: loesche artikel <nr>\n"
1266 " (bezieht sich immer auf die aktuelle Rubrik.\n"),1;
1267
1268 if (!str || sscanf(str,"artikel %d",num)!=1 || num<=0)
1269 return notify_fail("WELCHEN Artikel willst Du loeschen ?\n"),0;
1270 num--;
1271 messages=(NEWSSERVER->GetNotes(GROUP));
1272 if (sizeof(messages)<=num) return
1273 notify_fail("So viele Artikel sind da nicht!\n"),0;
1274
1275 write("Rubrik "+GROUP+", Artikel "+(num+1)+
1276 " von "+capitalize(messages[num][M_WRITER])+
1277 " vom "+dtime(messages[num][M_TIME])[5..26]+
1278 ",\nTitel: "+messages[num][M_TITLE]+",\n\n");
1279
1280 /* (ueberfluessige Abfrage, macht schon /secure/news)
1281 if (!IS_LEARNER(TI) && lower_case(messages[num][M_WRITER])!=geteuid(TI))
1282 return
1283 write("Nicht geloescht - du darfst nur eigene Artikel loeschen.\n"),1;
1284 */
1285
1286 switch (NEWSSERVER->RemoveNote(GROUP, num)){
1287 case 1: write("Artikel ist geloescht.\n");
1288 say(this_player()->name()+" loescht einen Artikel aus der Zeitung.\n");
1289 return 1;
1290 case -1: write("Diesen Artikel darfst Du nicht loeschen.\n");
1291 say(this_player()->name()+" versucht vergeblich, einen Artikel zu loeschen.\n");
1292 return 1;
1293 case -3: write("So viele Artikel sind da nicht !\n");
1294 return 1;
1295 default: write("Interner Fehler. Bitte Erzmagier verstaendigen !\n");
1296 return 1;
Zesstra@Morgengrauen4090ca62016-07-19 00:22:34 +02001297 }
1298 return 0;
MG Mud User88f12472016-06-24 23:31:02 +02001299}
1300
1301// Low-level Funktion zum Abonnieren/Abbestellen von Rubriken
1302// bestellen==0 -> abbestellen, bestellen!=0 -> bestellen
1303// Rueckgabe: 0, wenn der gewuenschte Zustand schon eingestellt war, sonst 1
1304private int _subscribe(string groupname, int bestellen) {
1305
1306 int timeout = read_until[groupname];
1307 // gar nicht abonniert/abbestellt?
1308 if (!bestellen && timeout < 0)
1309 return 0;
1310 else if (bestellen && timeout > 0)
1311 return 0;
1312
1313 // wenn noch kein timeout, erstmal auf 1 setzen
1314 timeout ||= 1;
1315
1316 // -1 fuer abbestellen, +1 fuer bestellen
1317 if (bestellen)
1318 read_until[groupname] = abs(timeout);
1319 else
1320 read_until[groupname] = -timeout;
1321
1322 if (environment())
1323 environment()->SetProp(P_READ_NEWS, read_until);
1324
1325 return 1;
1326}
1327
1328static Unsubscribe(str) {
1329 int timeout;
1330 if (str=="?"||str=="-?") return
1331 write("Syntax: unsubscribe <rubrik>"
1332 " oder: bestelle <rubrik> ab\n"),1;
1333 str=GetGroupName(str);
1334 if (!str) return 1;
1335 if (!_subscribe(str,0)) {
1336 notify_fail("Die Rubrik hast Du gar nicht abonniert!\n");
1337 return 0;
1338 }
1339 else {
1340 write("Rubrik "+str+" abbestellt.\n");
1341 }
1342 return 1;
1343}
1344
1345
1346static Bestelle(str) { /* ab ! */
1347 if (!str || !sscanf(str,"%s ab",str)) return _notify_fail(
1348 "Die Syntax ist: 'bestelle <rubrik> ab', "
1349 "oder meinst Du 'abonniere'?\n"),0;
1350 return Unsubscribe(str);
1351}
1352
1353static Subscribe(str) {
1354 int timeout;
1355 if (str=="?"||str=="-?") return
1356 write("Syntax: abonniere <rubrik>\n"
1357 " oder: subscribe <rubrik>\n"),1;
1358 str=GetGroupName(str);
1359 if (!str) return 1;
1360 if (!_subscribe(str,1)) {
1361 notify_fail("Die Rubrik hast Du doch schon abonniert!\n");
1362 return 0;
1363 }
1364 else {
1365 write("Rubrik "+str+" abonniert.\n");
1366 }
1367 return 1;
1368}
1369
1370// Legt die anfaenglichen Abonnements eines Neulesers fest und bestellt alle
1371// anderen ab.
1372private void InitialSubscriptions() {
1373 // alle abbestellen. ;-)
1374 // Alternative: fuer alle _subscribe(,0) rufen
1375 if (!query_once_interactive(environment()))
1376 return;
1377 string *gruppen = NEWSSERVER->GetGroups();
1378 int *vals = allocate(sizeof(gruppen),-1);
1379 read_until = mkmapping(gruppen,vals);
1380
1381 // jetzt die vorausgewaehlten bestellen
1382 foreach(string gruppe : INITIAL_SUBSCRIPTIONS) {
1383 if (member(gruppen, gruppe) > -1)
1384 _subscribe(gruppe,1);
1385 }
1386 // und ggf. noch die eigene Gildenrubrik
1387 string gilde = environment()->QueryProp(P_GUILD);
1388 if (stringp(gilde)
1389 && member(gruppen, "gilden."+gilde) > -1)
1390 _subscribe("gilden."+gilde,1);
1391
1392 environment()->SetProp(P_READ_NEWS, read_until);
1393}
1394
1395static MoveMessage(str) {
1396 int num,i;
1397 mixed msg/*,expl*/;
1398 string gr;
1399 if (str=="?"||str=="-?") return
1400 write("Syntax: verlege artikel <nr> nach <rubrik>\n"
1401 " Artikel und Rubrik muessen explizit angegeben werden.\n"),1;
1402 if (!str || sscanf(str,"artikel %d nach %s",num,gr)!=2) return (int)notify_fail(
1403 "verlege artikel <nr> nach <rubrik>, oder was?\n");
1404 if (!(gr=GetGroupName(gr))) return 1;
Zesstra@Morgengrauen0e0ac492016-07-19 00:13:51 +02001405 if (gr == GROUP)
1406 {
1407 write("Das waere reichlich sinnlos, nicht wahr?\n");
1408 return 1;
1409 }
MG Mud User88f12472016-06-24 23:31:02 +02001410 if (!(CatchNewsError(NEWSSERVER->AskAllowedWrite(gr),"Die Rubrik ist leider voll.\n"))) return 1;
1411
1412 if (!pointerp(msg=NEWSSERVER->GetNotes(GROUP)))
1413 return notify_fail("Seltsam, die Rubrik '"+GROUP+
1414 "' gibt es nicht mehr...\n"), 0;
1415
1416 num--;
1417 if (sizeof(msg)<=num) return
1418 notify_fail("So viele Nachrichten sind da nicht !\n"),0;
1419 msg=msg[num];
1420 if (geteuid(TI) != lower_case(msg[M_WRITER])) {
1421 if (!IS_LEARNER(TI)) return
1422 write("Du darfst nur Deine eigenen Artikel verlegen.\n"),1;
1423 write("WARNUNG: Das ist nicht Dein eigener Artikel!\n");
1424 }
1425 // return (int)notify_fail("Man darf zur Zeit nur eigene Artikel verlegen.\n");
1426 if (!CatchNewsError(NEWSSERVER->RemoveNote(GROUP,num),"Dieser Fehler kann eigentlich nicht auftreten"))
1427 write("Warnung! Konnte Artikel an alter Position nicht loeschen.\n");
1428 else write("Artikel von Rubrik "+GROUP+" entfernt.\n");
1429
1430 msg[M_MESSAGE]=
1431 sprintf("%s on=%s ot=%d og=%s\n",
1432 STATUSESCAPE,msg[M_WRITER],msg[M_TIME],msg[M_BOARD])
1433 +msg[M_MESSAGE];
1434
1435/*
1436 expl=explode(msg[M_MESSAGE],"\n");
1437 for (i=0;(IS_STATUSLINE(expl[i][0..2]));i++);
1438 msg[M_MESSAGE]=( (i) ? implode(expl[0..i-1],"\n")+"\n" : "" ) +
1439 "[Verlegt von "+msg[M_BOARD]+", "+msg[M_WRITER]+", "+
1440 dtime(msg[M_TIME])[5..26]+"]:\n"+
1441 implode(expl[i..],"\n")+"\n";
1442*/
1443
1444 msg[M_BOARD]=gr;
1445 NEWSSERVER->WriteNote(msg);
1446 write("Artikel nach Rubrik "+gr+" verlegt.\n");
1447 return 1;
1448}
1449
1450static MoveTrash()
1451{
1452 if (!pointerp(lasttitle)||sizeof(lasttitle)<LAST_SIZEOF) return
1453 write("Was denn bitte? Du hast noch gar nichts gelesen!\n"),1;
1454 if (lasttitle[LAST_GROUP]!=GROUP) return
1455 write("Nix gibts! Du hast die Rubrik gewechselt!\n"),1;
1456 return MoveMessage(sprintf("artikel %d nach muell",lasttitle[LAST_NR]+1));
1457}
1458
1459static SaveMessage(str) {
1460 mixed num;
1461 mixed *messages;
1462
1463 if (intp(str)) num=str;
1464 if ((!num && (!str || str=="" || sscanf(str,"artikel %d",num)!=1)) || num<=0) {
1465 notify_fail("Welchen Artikel willst Du abspeichern?\n");
1466 return 0;
1467 }
1468 if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP)))
1469 return notify_fail("Seltsam, die Rubrik '"+GROUP+
1470 "' gibt es nicht mehr...\n"), 0;
1471 num--;
1472 if (sizeof(messages)<=num) {
1473 notify_fail("So viele Nachrichten sind da nicht !\n");
1474 return 0;
1475 }
1476 if(write_file(SAVEMSGPATH(TP),Message2string(num,messages,M2S_REMOTE)+"\n"))
1477 write(break_string(
1478 "Inhalt des Artikels wurde nach "+SAVEMSGPATH(TP)+" gespeichert.\n"));
1479 else
1480 write(break_string(
1481 "Fehler beim Schreiben nach "+SAVEMSGPATH(TP)+"!\n"));
1482 return 1;
1483}
1484
1485
1486static MailMessage(str) {
1487 mixed num,rec,group;
1488 mixed *messages;
1489
1490// printf("%O\n",inherit_list(environment(TP)));
1491// if (member(query_actions(this_player()),"mail")<0)
1492// tut nicht wegen anderer Implemtierung von AddCmd in Raeumen
1493
1494 if (str=="?"||str=="-?") return
1495 write("Syntax: versende artikel <nr> an <adresse>\n"),1;
1496
1497 str=TP->_unparsed_args(); // wegen Mailadressen
1498 if (str) str=lower_case(str);
1499
1500 if (!IS_SEER(TP) && !IS_POST(environment(TP)))
1501 return notify_fail("Du musst in ein Postamt gehen, "
1502 "um etwas versenden zu koennen.\n"),0;
1503
1504 num=0;
1505
1506 if (!str || (sscanf(str,"artikel %d an %s",num,rec)!=2 &&
1507 sscanf(str,"note %d to %s",num,rec)!=2 &&
1508 sscanf(str,"note to %s",rec)!=1 &&
1509 sscanf(str,"artikel an %s",rec)!=1)){
1510 if (!str || str[0..6]=="artikel"||str[0..3]=="note") return
1511 write("Welchen Artikel willst Du versenden, und wohin?\n"),1;
1512 else return
1513 notify_fail("Welchen Artikel willst Du versenden, und wohin?\n"),0;
1514 }
1515 if (!num&&(!pointerp(lasttitle)||sizeof(lasttitle)<LAST_SIZEOF))
1516 return write("Du hast scheinbar noch nichts gelesen, worauf man sich "
1517 "beziehen kann.\nGib notfalls die Nummer des Artikels an.\n"),1;
1518
1519 // printf("lasttitle= %O\nnum=%d\n",lasttitle,num);
1520
1521 if (!pointerp(messages=
1522 NEWSSERVER->GetNotes(group=(num?GROUP:lasttitle[LAST_GROUP]))))
1523 return notify_fail("Seltsam, die Rubrik gibt es nicht mehr...\n"), 0;
1524
1525 if (!pointerp(messages)||!sizeof(messages))
1526 return write("Die Rubrik "+group+" ist leer.\n"),1;
1527 if (num<0||sizeof(messages)<num) return
1528 write("Einen Artikel mit Nummer "+num+" gibt es in Rubrik "+group+
1529 " nicht!\n"),1;
1530
1531 if (num) num--;
1532 else {
1533 int h;
1534 num=-1;
1535 if (pointerp(messages)) {
1536 for (h=sizeof(messages)-1;
1537 (h>=0 && messages[h][M_TIME]>=lasttitle[LAST_TIME]);h--)
1538 if (messages[h][M_TIME]==lasttitle[LAST_TIME] &&
1539 lower_case(messages[h][M_WRITER])==
1540 lower_case(lasttitle[LAST_WRITER]))
1541 num=h;
1542 }
1543 if (num<0)
1544 return notify_fail("Konnte Artikel nicht wiederfinden, "
1545 "bitte gib die Nummer an.\n"),0;
1546 }
1547 MAILER->do_mail( rec,
1548 "MPA: "+messages[num][M_TITLE]+" ("+messages[num][M_WRITER]+")",
1549 Message2string(num,messages,M2S_REMOTE,group)+"\n");
1550 return 1;
1551}
1552
1553
1554
1555HelpPage(str) {
1556 if (str!="mpa"&&str!="zeitung") return 0;
1557 this_player()->More(read_file(HELPPAGE)+
1558 (IS_LEARNER(TP) ? read_file(WIZHELPPAGE) : ""));
1559 return 1;
1560}
1561
1562/*--------------------------------------------------------------------------*/
1563
1564protected void NotifyMove(object dest, object oldenv, int method) {
1565 ::NotifyMove(dest, oldenv, method);
1566
1567 // P_READ_NEWS aus dem Spieler holen.
1568 if (objectp(environment()) && query_once_interactive(environment())) {
1569 read_until=environment()->QueryProp(P_READ_NEWS);
1570 }
1571
1572 if (!mappingp(read_until) || !sizeof(read_until))
1573 InitialSubscriptions();
1574}
1575
1576int GetTID(mixed message) {
1577 string dummy;
1578 int tid;
1579 return (sscanf(message[M_MESSAGE],"%s" STATUSESCAPE " tid=%d",dummy,tid)==2)
1580 ? tid : message[M_TIME];
1581}
1582