blob: 0d8bdd715f835fc32c1b873eb93d7c0d6e25c376 [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 }
1012}
1013
Zesstra@Morgengrauen4090ca62016-07-19 00:22:34 +02001014static varargs int schreib(string str,string pretext,int called_by_itself,
1015 string statuslines)
1016{
MG Mud User88f12472016-06-24 23:31:02 +02001017 int err;
1018
1019 if (str=="?"||str=="-?") {
1020 write("Syntax: schreib <Titel>\n"
1021 " beginnt einen neuen Artikel in der Zeitung.\n");
1022 return 1;
1023 }
1024
1025 if (!this_interactive() || !this_interactive()->query_real_name()) return 0;
1026 if (!called_by_itself && extern_call() && !pretext)
1027 str=this_interactive()->_unparsed_args()||"";
1028 if (called_by_itself && str=="~q") {
1029 write("Abgebrochen.\n");
1030 return 1;
1031 }
1032 if (!CatchNewsError(
1033 NEWSSERVER->AskAllowedWrite(GROUP),
1034 "Diese Rubrik ist leider schon randvoll!")) return 1;
1035 if (!called_by_itself)
1036 write("Neuer Artikel in Rubrik "+GROUP+":\n");
1037 if (!str || str=="" || str=="artikel") {
1038 input_to("schreib", INPUT_PROMPT, "Titel des Artikels: ", pretext,1);
1039 return 1;
1040 }
1041 // writer=this_interactive()->query_real_name();
1042 message=allocate(6);
1043 message[M_BOARD]=GROUP;
1044 message[M_TITLE]=killctrl(str);
1045 message[M_MESSAGE]=statuslines;
1046 write("Titel ist: "+str+".\n\
1047Gib jetzt Deinen Text ein,\n\
1048** oder . wenn Du fertig bist, ~q zum Abbrechen, ~h fuer eine Hilfsseite.\n");
1049 nedit("PostNote",pretext);
1050 return 1;
1051}
1052
1053static varargs Reply(string str,string newtitle) {
1054 mixed dummy,replytitle,s;
1055 int nr;
1056
1057 if ((dummy=(str||newtitle))=="?"||dummy=="-?") {
1058 write("Der Antworte-Befehl ist doppelt belegt.\n"
1059 "1. (Zeitung): Schreibe Antwort auf einen Artikel in der Zeitung.\n"
1060 " Syntax: antworte\n"
1061 " antworte auf artikel <nr> [neuer Titel]\n"
1062 " reply [auf artikel <nr> | to note <nr>] [neuer Titel]\n"
1063 "2. aehnlich 'sage':\n"
1064 " Du tippst zum Beispiel:\n"
1065 " antworte ja, das weiss ich\n"
1066 " Alle Spieler im Raum sehen dann:\n"
1067 " <Dein Name> antwortet: ja, das weiss ich.\n"
1068 "Bitte beachte, dass jede Syntax, die auf den antworte-Befehl der "
1069 "Zeitung\npasst, auch von der Zeitung ausgewertet wird.\n");
1070 return 1;
1071 }
1072
1073 if (str&&
1074 ((sscanf(lower_case(str),"auf artikel %d",dummy)==1 &&
1075 str=this_player()->_unparsed_args()[12..])||
1076 (sscanf(lower_case(str),"to note %d",dummy)==1 &&
1077 str=this_player()->_unparsed_args()[8..]))) {
1078 mixed notes;
1079 notes=NEWSSERVER->GetNotes(GROUP);
1080 if (dummy<1||dummy>sizeof(notes))
1081 return write("Einen Artikel mit der Nummer "+dummy+
1082 " gibt es in dieser Rubrik nicht.\n"),1;
1083 dummy--;
1084 replytitle=({notes[dummy][M_TITLE],notes[dummy][M_WRITER],
1085 notes[dummy][M_TIME],GetTID(notes[dummy]),GROUP});
1086 DEBUGVAR(str);
1087 if (!newtitle&&str&&sizeof(str)&&sscanf(str,"%d %s",dummy,str)==2)
1088 newtitle=str;
1089 }
1090 else if (!str||!sizeof(str)) {
1091 if (!lasttitle) return
1092 write("Du hast noch gar nichts gelesen, worauf Du "
1093 "antworten koenntest.\n"),1;
1094 replytitle=lasttitle;
1095 }
1096 else return 0;
1097
1098// return ComposeReply(replytitle);
1099//}
1100//
1101//
1102//ComposeReply(mixed replytitle) {
1103
1104 if (!newtitle) {
1105 if (replytitle[0][0..7]=="Re: Re: ") newtitle="Re^3: "+replytitle[0][8..];
1106 else if (sscanf(replytitle[0],"Re^%d: %s",nr,newtitle))
1107 newtitle="Re^"+(nr+1)+": "+newtitle;
1108 else newtitle="Re: "+replytitle[0];
1109 }
1110 return schreib(newtitle,0,0,
1111 STATUSESCAPE+" rn="+replytitle[LAST_WRITER]+
1112 " rt="+replytitle[LAST_TIME]+
1113 " rg="+replytitle[LAST_GROUP]+"\n"+
1114 STATUSESCAPE+" tid="+replytitle[LAST_TID]+"\n");
1115}
1116
1117static Reply2(str) {
1118 str = this_player()->_unparsed_args();
1119 if (!str||str[0..11]=="auf artikel "||str[0..7]=="to note ")
1120 return Reply(str);
1121 return Reply(0,str);
1122}
1123
1124static void InformPlayers(string group,string player,string text)
1125{
1126 object *players;
1127 int i;
1128 mixed data;
1129 string ig;
1130
1131 players=users();
1132 ig=lower_case(player)+".news";
1133 for (i=sizeof(players)-1;i>=0;i--) {
1134 data=players[i]->QueryProp(P_WAITFOR);
1135 if (pointerp(data)&&(member(data,"Mpa")>-1)) {
1136 data=players[i]->QueryProp(P_READ_NEWS);
1137 if (mappingp(data)&&(data[group]>0)) {
1138 data=players[i]->QueryProp(P_IGNORE);
1139 if ((!pointerp(data))||(member(data,ig)==-1))
1140 tell_object(players[i],text);
1141 }
1142 }
1143 }
1144}
1145
1146static PostNote(text) {
1147 int err;
1148 string sig;
1149
1150 if (!text) {
1151 write("Abbruch! Artikel landet im Reisswolf.\n");
1152 return 1;
1153 }
1154 if (!sizeof(old_explode(text,"\n")-
1155 ({"q","quit"," **","** ","ende","","exit"," "})
1156 ) )
1157 return write("\
1158ACHTUNG: Wolltest Du wirklich einen Artikel ohne Inhalt in die mpa setzen?\n\
1159Artikel ohne erkennbaren Inhalt werden NICHT veroeffentlicht. Bitte ueber-\n\
1160pruef Deine Syntax, falls Du keinen Artikel schreiben wolltest, oder schreib\n\
1161auch ein bisschen Text!\n\
1162Artikel landet im Reisswolf.\n"),1;
1163 if (!message[M_MESSAGE])
1164 message[M_MESSAGE] = text;
1165 else
1166 message[M_MESSAGE]+=text;
1167 if (sig=read_file("/players/"+geteuid(this_interactive())+"/.signature"))
1168 message[M_MESSAGE]+=sig;
1169 if (!CatchNewsError(NEWSSERVER->WriteNote(message),
1170 "Diese Rubrik ist voll. Mist, da war jemand schneller...")) {
1171 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");
1172 return 0;
1173 }
1174 write("OK, Artikel ist veroeffentlicht.\n");
1175 say(capitalize(TP->name())+
1176 " hat einen Artikel in der Zeitung veroeffentlicht.\n");
1177 if (geteuid(TP)!="sitopanaki")
1178 InformPlayers(message[M_BOARD],geteuid(this_interactive()),
1179 "* MPA: Neuer Artikel von "+
1180 capitalize(geteuid(this_interactive()))+
1181 " in Rubrik \""+message[M_BOARD]+"\".\n");
1182 message=0; /* Platz sparen! */
1183 return 1;
1184}
1185
1186
1187//static // allowing aliasing *Rumata* 5/8/96
1188inhalt(str) {
1189 int i,endflag,timeout;
1190 string *gruppen,s,txt,suche;
1191 mixed messages;
1192
1193 if (str=="?"||str=="-?") return
1194 write("Syntax: inhalt [<rubrik>] [ende] [suche <text>]\n"),1;
1195
1196 str=(!str)?({}):explode(str," ");
1197
1198 if (sizeof(str) && (str[0]=="neu" || str[0]=="neues") )
1199 return ReadNextUnread("liste"),1;
1200
1201 if (endflag=member(str,"ende")+1) str-=({"ende"});
1202 if (((i=member(str,"suche")) != -1) && (sizeof(str) > i)) {
1203 suche=lower_case(implode(str[i+1..]," "));
1204 str=str[0..i-1];
1205 }
1206 else
1207 suche=0;
1208 if (!sizeof(str)) {
1209 str=GROUP;
1210 if (!pointerp(messages=NEWSSERVER->GetNotes(str))){
1211 str=GROUP=DEFAULTGROUP;
1212 if (!pointerp(messages=NEWSSERVER->GetNotes(str)))
1213 return notify_fail("Seltsam, irgendwie geht hier einiges schief...\n"),0;
1214 }
1215 }
1216 else {
1217 str=GetGroupName(str[0]);
1218 if (!str) return 1;
1219 messages=NEWSSERVER->GetNotes(str);
1220 }
1221 timeout=abs(read_until[str]);
1222 s="Inhalt der Rubrik "+str+":\n\n";
1223 if (!pointerp(messages) || !sizeof(messages))
1224 return
1225 write(s+"Zur Zeit befinden sich keine Artikel in dieser Rubrik.\n"),1;
1226 if (suche)
1227 s+="Suche nach '"+suche+"' in der Rubrik ergab folgende Treffer:\n\n";
1228 else
1229 if (sizeof(messages)==1)
1230 s+="Zur Zeit befindet sich ein Artikel in der Rubrik:\n\n";
1231 else
1232 s+="Zur Zeit befinden sich "+sizeof(messages)+
1233 " Artikel in der Rubrik:\n\n";
1234 if (endflag&&(sizeof(messages)>16)&&
1235 messages[sizeof(messages)-16][M_TIME]>=timeout) timeout=-1;
1236 for (i=(endflag?(((endflag=sizeof(messages)-15)<0)?0:endflag):0);
1237 i<sizeof(messages);i++)
1238 {
1239 txt=sprintf("%2d.%s%-48s%4d (%-11s) %s\n",i+1,
1240 (((timeout>=0) && timeout<messages[i][M_TIME] )?
1241 ( (timeout=-1),"*"):" "),messages[i][M_TITLE],
1242 sizeof(explode(messages[i][M_MESSAGE],"\n")),
1243 messages[i][M_WRITER],
1244 dtime(messages[i][M_TIME])[5..11]);
1245 if (!suche || (strstr(lower_case(txt), suche) != -1))
1246 s+=txt;
1247 }
1248 if (endflag) write(s);
1249 else this_player()->More(s);
1250 return 1;
1251}
1252
1253
1254static artikel(str) {
1255 return lies(str);
1256}
1257
1258
Zesstra@Morgengrauen795a0e12016-07-19 00:17:42 +02001259static int loesche(string str) {
MG Mud User88f12472016-06-24 23:31:02 +02001260 int num;
1261 mixed *messages;
1262
1263 if (str=="?"||str=="-?") return
1264 write("Syntax: loesche artikel <nr>\n"
1265 " (bezieht sich immer auf die aktuelle Rubrik.\n"),1;
1266
1267 if (!str || sscanf(str,"artikel %d",num)!=1 || num<=0)
1268 return notify_fail("WELCHEN Artikel willst Du loeschen ?\n"),0;
1269 num--;
1270 messages=(NEWSSERVER->GetNotes(GROUP));
1271 if (sizeof(messages)<=num) return
1272 notify_fail("So viele Artikel sind da nicht!\n"),0;
1273
1274 write("Rubrik "+GROUP+", Artikel "+(num+1)+
1275 " von "+capitalize(messages[num][M_WRITER])+
1276 " vom "+dtime(messages[num][M_TIME])[5..26]+
1277 ",\nTitel: "+messages[num][M_TITLE]+",\n\n");
1278
1279 /* (ueberfluessige Abfrage, macht schon /secure/news)
1280 if (!IS_LEARNER(TI) && lower_case(messages[num][M_WRITER])!=geteuid(TI))
1281 return
1282 write("Nicht geloescht - du darfst nur eigene Artikel loeschen.\n"),1;
1283 */
1284
1285 switch (NEWSSERVER->RemoveNote(GROUP, num)){
1286 case 1: write("Artikel ist geloescht.\n");
1287 say(this_player()->name()+" loescht einen Artikel aus der Zeitung.\n");
1288 return 1;
1289 case -1: write("Diesen Artikel darfst Du nicht loeschen.\n");
1290 say(this_player()->name()+" versucht vergeblich, einen Artikel zu loeschen.\n");
1291 return 1;
1292 case -3: write("So viele Artikel sind da nicht !\n");
1293 return 1;
1294 default: write("Interner Fehler. Bitte Erzmagier verstaendigen !\n");
1295 return 1;
Zesstra@Morgengrauen4090ca62016-07-19 00:22:34 +02001296 }
1297 return 0;
MG Mud User88f12472016-06-24 23:31:02 +02001298}
1299
1300// Low-level Funktion zum Abonnieren/Abbestellen von Rubriken
1301// bestellen==0 -> abbestellen, bestellen!=0 -> bestellen
1302// Rueckgabe: 0, wenn der gewuenschte Zustand schon eingestellt war, sonst 1
1303private int _subscribe(string groupname, int bestellen) {
1304
1305 int timeout = read_until[groupname];
1306 // gar nicht abonniert/abbestellt?
1307 if (!bestellen && timeout < 0)
1308 return 0;
1309 else if (bestellen && timeout > 0)
1310 return 0;
1311
1312 // wenn noch kein timeout, erstmal auf 1 setzen
1313 timeout ||= 1;
1314
1315 // -1 fuer abbestellen, +1 fuer bestellen
1316 if (bestellen)
1317 read_until[groupname] = abs(timeout);
1318 else
1319 read_until[groupname] = -timeout;
1320
1321 if (environment())
1322 environment()->SetProp(P_READ_NEWS, read_until);
1323
1324 return 1;
1325}
1326
1327static Unsubscribe(str) {
1328 int timeout;
1329 if (str=="?"||str=="-?") return
1330 write("Syntax: unsubscribe <rubrik>"
1331 " oder: bestelle <rubrik> ab\n"),1;
1332 str=GetGroupName(str);
1333 if (!str) return 1;
1334 if (!_subscribe(str,0)) {
1335 notify_fail("Die Rubrik hast Du gar nicht abonniert!\n");
1336 return 0;
1337 }
1338 else {
1339 write("Rubrik "+str+" abbestellt.\n");
1340 }
1341 return 1;
1342}
1343
1344
1345static Bestelle(str) { /* ab ! */
1346 if (!str || !sscanf(str,"%s ab",str)) return _notify_fail(
1347 "Die Syntax ist: 'bestelle <rubrik> ab', "
1348 "oder meinst Du 'abonniere'?\n"),0;
1349 return Unsubscribe(str);
1350}
1351
1352static Subscribe(str) {
1353 int timeout;
1354 if (str=="?"||str=="-?") return
1355 write("Syntax: abonniere <rubrik>\n"
1356 " oder: subscribe <rubrik>\n"),1;
1357 str=GetGroupName(str);
1358 if (!str) return 1;
1359 if (!_subscribe(str,1)) {
1360 notify_fail("Die Rubrik hast Du doch schon abonniert!\n");
1361 return 0;
1362 }
1363 else {
1364 write("Rubrik "+str+" abonniert.\n");
1365 }
1366 return 1;
1367}
1368
1369// Legt die anfaenglichen Abonnements eines Neulesers fest und bestellt alle
1370// anderen ab.
1371private void InitialSubscriptions() {
1372 // alle abbestellen. ;-)
1373 // Alternative: fuer alle _subscribe(,0) rufen
1374 if (!query_once_interactive(environment()))
1375 return;
1376 string *gruppen = NEWSSERVER->GetGroups();
1377 int *vals = allocate(sizeof(gruppen),-1);
1378 read_until = mkmapping(gruppen,vals);
1379
1380 // jetzt die vorausgewaehlten bestellen
1381 foreach(string gruppe : INITIAL_SUBSCRIPTIONS) {
1382 if (member(gruppen, gruppe) > -1)
1383 _subscribe(gruppe,1);
1384 }
1385 // und ggf. noch die eigene Gildenrubrik
1386 string gilde = environment()->QueryProp(P_GUILD);
1387 if (stringp(gilde)
1388 && member(gruppen, "gilden."+gilde) > -1)
1389 _subscribe("gilden."+gilde,1);
1390
1391 environment()->SetProp(P_READ_NEWS, read_until);
1392}
1393
1394static MoveMessage(str) {
1395 int num,i;
1396 mixed msg/*,expl*/;
1397 string gr;
1398 if (str=="?"||str=="-?") return
1399 write("Syntax: verlege artikel <nr> nach <rubrik>\n"
1400 " Artikel und Rubrik muessen explizit angegeben werden.\n"),1;
1401 if (!str || sscanf(str,"artikel %d nach %s",num,gr)!=2) return (int)notify_fail(
1402 "verlege artikel <nr> nach <rubrik>, oder was?\n");
1403 if (!(gr=GetGroupName(gr))) return 1;
Zesstra@Morgengrauen0e0ac492016-07-19 00:13:51 +02001404 if (gr == GROUP)
1405 {
1406 write("Das waere reichlich sinnlos, nicht wahr?\n");
1407 return 1;
1408 }
MG Mud User88f12472016-06-24 23:31:02 +02001409 if (!(CatchNewsError(NEWSSERVER->AskAllowedWrite(gr),"Die Rubrik ist leider voll.\n"))) return 1;
1410
1411 if (!pointerp(msg=NEWSSERVER->GetNotes(GROUP)))
1412 return notify_fail("Seltsam, die Rubrik '"+GROUP+
1413 "' gibt es nicht mehr...\n"), 0;
1414
1415 num--;
1416 if (sizeof(msg)<=num) return
1417 notify_fail("So viele Nachrichten sind da nicht !\n"),0;
1418 msg=msg[num];
1419 if (geteuid(TI) != lower_case(msg[M_WRITER])) {
1420 if (!IS_LEARNER(TI)) return
1421 write("Du darfst nur Deine eigenen Artikel verlegen.\n"),1;
1422 write("WARNUNG: Das ist nicht Dein eigener Artikel!\n");
1423 }
1424 // return (int)notify_fail("Man darf zur Zeit nur eigene Artikel verlegen.\n");
1425 if (!CatchNewsError(NEWSSERVER->RemoveNote(GROUP,num),"Dieser Fehler kann eigentlich nicht auftreten"))
1426 write("Warnung! Konnte Artikel an alter Position nicht loeschen.\n");
1427 else write("Artikel von Rubrik "+GROUP+" entfernt.\n");
1428
1429 msg[M_MESSAGE]=
1430 sprintf("%s on=%s ot=%d og=%s\n",
1431 STATUSESCAPE,msg[M_WRITER],msg[M_TIME],msg[M_BOARD])
1432 +msg[M_MESSAGE];
1433
1434/*
1435 expl=explode(msg[M_MESSAGE],"\n");
1436 for (i=0;(IS_STATUSLINE(expl[i][0..2]));i++);
1437 msg[M_MESSAGE]=( (i) ? implode(expl[0..i-1],"\n")+"\n" : "" ) +
1438 "[Verlegt von "+msg[M_BOARD]+", "+msg[M_WRITER]+", "+
1439 dtime(msg[M_TIME])[5..26]+"]:\n"+
1440 implode(expl[i..],"\n")+"\n";
1441*/
1442
1443 msg[M_BOARD]=gr;
1444 NEWSSERVER->WriteNote(msg);
1445 write("Artikel nach Rubrik "+gr+" verlegt.\n");
1446 return 1;
1447}
1448
1449static MoveTrash()
1450{
1451 if (!pointerp(lasttitle)||sizeof(lasttitle)<LAST_SIZEOF) return
1452 write("Was denn bitte? Du hast noch gar nichts gelesen!\n"),1;
1453 if (lasttitle[LAST_GROUP]!=GROUP) return
1454 write("Nix gibts! Du hast die Rubrik gewechselt!\n"),1;
1455 return MoveMessage(sprintf("artikel %d nach muell",lasttitle[LAST_NR]+1));
1456}
1457
1458static SaveMessage(str) {
1459 mixed num;
1460 mixed *messages;
1461
1462 if (intp(str)) num=str;
1463 if ((!num && (!str || str=="" || sscanf(str,"artikel %d",num)!=1)) || num<=0) {
1464 notify_fail("Welchen Artikel willst Du abspeichern?\n");
1465 return 0;
1466 }
1467 if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP)))
1468 return notify_fail("Seltsam, die Rubrik '"+GROUP+
1469 "' gibt es nicht mehr...\n"), 0;
1470 num--;
1471 if (sizeof(messages)<=num) {
1472 notify_fail("So viele Nachrichten sind da nicht !\n");
1473 return 0;
1474 }
1475 if(write_file(SAVEMSGPATH(TP),Message2string(num,messages,M2S_REMOTE)+"\n"))
1476 write(break_string(
1477 "Inhalt des Artikels wurde nach "+SAVEMSGPATH(TP)+" gespeichert.\n"));
1478 else
1479 write(break_string(
1480 "Fehler beim Schreiben nach "+SAVEMSGPATH(TP)+"!\n"));
1481 return 1;
1482}
1483
1484
1485static MailMessage(str) {
1486 mixed num,rec,group;
1487 mixed *messages;
1488
1489// printf("%O\n",inherit_list(environment(TP)));
1490// if (member(query_actions(this_player()),"mail")<0)
1491// tut nicht wegen anderer Implemtierung von AddCmd in Raeumen
1492
1493 if (str=="?"||str=="-?") return
1494 write("Syntax: versende artikel <nr> an <adresse>\n"),1;
1495
1496 str=TP->_unparsed_args(); // wegen Mailadressen
1497 if (str) str=lower_case(str);
1498
1499 if (!IS_SEER(TP) && !IS_POST(environment(TP)))
1500 return notify_fail("Du musst in ein Postamt gehen, "
1501 "um etwas versenden zu koennen.\n"),0;
1502
1503 num=0;
1504
1505 if (!str || (sscanf(str,"artikel %d an %s",num,rec)!=2 &&
1506 sscanf(str,"note %d to %s",num,rec)!=2 &&
1507 sscanf(str,"note to %s",rec)!=1 &&
1508 sscanf(str,"artikel an %s",rec)!=1)){
1509 if (!str || str[0..6]=="artikel"||str[0..3]=="note") return
1510 write("Welchen Artikel willst Du versenden, und wohin?\n"),1;
1511 else return
1512 notify_fail("Welchen Artikel willst Du versenden, und wohin?\n"),0;
1513 }
1514 if (!num&&(!pointerp(lasttitle)||sizeof(lasttitle)<LAST_SIZEOF))
1515 return write("Du hast scheinbar noch nichts gelesen, worauf man sich "
1516 "beziehen kann.\nGib notfalls die Nummer des Artikels an.\n"),1;
1517
1518 // printf("lasttitle= %O\nnum=%d\n",lasttitle,num);
1519
1520 if (!pointerp(messages=
1521 NEWSSERVER->GetNotes(group=(num?GROUP:lasttitle[LAST_GROUP]))))
1522 return notify_fail("Seltsam, die Rubrik gibt es nicht mehr...\n"), 0;
1523
1524 if (!pointerp(messages)||!sizeof(messages))
1525 return write("Die Rubrik "+group+" ist leer.\n"),1;
1526 if (num<0||sizeof(messages)<num) return
1527 write("Einen Artikel mit Nummer "+num+" gibt es in Rubrik "+group+
1528 " nicht!\n"),1;
1529
1530 if (num) num--;
1531 else {
1532 int h;
1533 num=-1;
1534 if (pointerp(messages)) {
1535 for (h=sizeof(messages)-1;
1536 (h>=0 && messages[h][M_TIME]>=lasttitle[LAST_TIME]);h--)
1537 if (messages[h][M_TIME]==lasttitle[LAST_TIME] &&
1538 lower_case(messages[h][M_WRITER])==
1539 lower_case(lasttitle[LAST_WRITER]))
1540 num=h;
1541 }
1542 if (num<0)
1543 return notify_fail("Konnte Artikel nicht wiederfinden, "
1544 "bitte gib die Nummer an.\n"),0;
1545 }
1546 MAILER->do_mail( rec,
1547 "MPA: "+messages[num][M_TITLE]+" ("+messages[num][M_WRITER]+")",
1548 Message2string(num,messages,M2S_REMOTE,group)+"\n");
1549 return 1;
1550}
1551
1552
1553
1554HelpPage(str) {
1555 if (str!="mpa"&&str!="zeitung") return 0;
1556 this_player()->More(read_file(HELPPAGE)+
1557 (IS_LEARNER(TP) ? read_file(WIZHELPPAGE) : ""));
1558 return 1;
1559}
1560
1561/*--------------------------------------------------------------------------*/
1562
1563protected void NotifyMove(object dest, object oldenv, int method) {
1564 ::NotifyMove(dest, oldenv, method);
1565
1566 // P_READ_NEWS aus dem Spieler holen.
1567 if (objectp(environment()) && query_once_interactive(environment())) {
1568 read_until=environment()->QueryProp(P_READ_NEWS);
1569 }
1570
1571 if (!mappingp(read_until) || !sizeof(read_until))
1572 InitialSubscriptions();
1573}
1574
1575int GetTID(mixed message) {
1576 string dummy;
1577 int tid;
1578 return (sscanf(message[M_MESSAGE],"%s" STATUSESCAPE " tid=%d",dummy,tid)==2)
1579 ? tid : message[M_TIME];
1580}
1581