| /* Das Servicepaket der Morgengrauen-Presseagentur. Eine erweiterte Zeitung. |
| Teilweise zur alten Zeitung identisch. |
| |
| unter Verwendung der Zeitung von Jof, voellig umgeschrieben. |
| |
| (C) Nov 1993 - 1996 Loco@Morgengrauen |
| |
| Verwendung ausserhalb von Morgengrauen ist gestattet unter folgenden |
| Bedingungen: |
| - Benutzung erfolgt auf eigene Gefahr. Jegliche Verantwortung wird |
| abgelehnt. Bugs ausserhalb von MG sind nicht mein Problem. |
| - Auch in veraenderten oder abgeleiteten Objekten muss ein Hinweis auf |
| die Herkunft erhalten bleiben. |
| - Bitte fragt mich vorher! |
| Ein Update-Service besteht nicht. Ruecknahme dieser Lizenz ist jederzeit |
| moeglich. Und wer nicht in der Lage ist, neue Versionen selber anzupassen, |
| hat in der Administration eines Muds nichts zu suchen. |
| |
| |
| 04.11.93 Erste brauchbare Version |
| (... seitdem viele Aenderungen ...) |
| 13.09.95 ca 02:00 erwarte mpa |
| 13.09.95 ca 23:00 RebuildGroupList() |
| 15.09.95 vorlaeufig ausgebaut |
| 16.09. anders wieder eingebaut, und Kleinigkeiten |
| 05.12.95 ca 19:20 Spieler koennen nur noch eigene Artikel loeschen/verl. |
| 07.12.95 ca 23:00 Keine Anzeige der Statuszeile. Statuszeilen beginnen |
| mit ~#!, sind damit nicht mit dem Editor erzeugbar. |
| 20.12.95 ca 17:00 uebergehe thread/antworten |
| 31.01.96 wiederhole/uncatchup |
| 22.04.96 Aufraeumen ignorierter threads. ALPHA! |
| 24.04.96 + - . als Adressierungen, zeitungsmeldung |
| 02.10.96 Kleinigkeiten |
| 08.10.96 Kleinigkeiten |
| 05.12.96 antworte auf artikel <nr>, reply <neuer titel>, |
| versende artikel, Abkuerzungen fuer Rubrikennamen, |
| Layoutaenderungen, |
| Herkunft bei verlegten Artikeln in Statuszeile |
| |
| Letzte Aenderung: |
| 04.11.06 Zesstra Anpassung an das neue Verhalten von inherit_list() in LD |
| |
| */ |
| |
| #include <properties.h> |
| #include <language.h> |
| #include <news.h> |
| #include <wizlevels.h> |
| #include <ansi.h> |
| #include <input_to.h> |
| #include "/mail/post.h" |
| |
| inherit "/std/thing"; |
| inherit NEDIT; |
| /* |
| #define DEBUG(x) if (funcall(symbol_function('find_player),"zesstra"))\ |
| tell_object(funcall(symbol_function('find_player),"zesstra"),\ |
| "MPA: "+x+"\n") |
| #define DEBUGVAR(x) DEBUG(sprintf(x+":\n%O\n",x)) |
| */ |
| #define DEBUGVAR(x) |
| |
| // Konfiguration, ggf mudabhaengig |
| #define DEFAULTGROUP "allgemeines" |
| #define MINIHELPPAGE "p/service/loco/doc/mini-mpa.txt" |
| #define HELPPAGE "/p/service/loco/doc/mpa" |
| #define WIZHELPPAGE "/p/service/loco/doc/mpa.wiz" |
| #define SAVEMSGPATH(pl) ("/open/News/"+(geteuid(pl))+".news") |
| #define IS_POST(r) (member(inherit_list(r),STDPOST+".c")>=0) |
| #define INITIAL_SUBSCRIPTIONS \ |
| ({ "bekanntmachungen", \ |
| "d.ebene", \ |
| "d.wueste", \ |
| "d.inseln", \ |
| "d.unterwelt", \ |
| "d.dschungel", \ |
| "d.gebirge", \ |
| "d.polar", \ |
| "d.wald", \ |
| "d.fernwest", \ |
| "d.vland", \ |
| "d.anfaenger", \ |
| "entwicklung", \ |
| }) |
| |
| // Makros etc. |
| |
| #define TP this_player() |
| #define TI this_interactive() |
| #define STATUSESCAPE "~#!" |
| #define IS_STATUSLINE(s) ((s[0..1]=="#!")||(s[0..2]=="~#!")) |
| //#define IS_STATUSLINE(s) (s[0..2]=="~#!") |
| // in Rubrik muell fanden sich tatsaechlich noch solche uralten notes... |
| #define IGNOREGROUP "*ignored*" |
| #define NNADWMSG "*NNADWMSG*" |
| #define SYSTEMGROUPS ({IGNOREGROUP,NNADWMSG}) |
| |
| // Aufbau der ignoregroup: |
| // ([group1:([tid1:lasttime1,tid2:lasttime2,...]),group2:...]) |
| |
| // Flags fuer Message2string() |
| #define M2S_VT100 1 |
| #define M2S_ANSI M2S_VT100 |
| #define M2S_REMOTE 2 |
| |
| // Format von lasttitle |
| #define LAST_TITLE 0 |
| #define LAST_WRITER 1 |
| #define LAST_TIME 2 |
| #define LAST_TID 3 |
| #define LAST_GROUP 4 |
| #define LAST_NR 5 |
| #define LAST_SIZEOF 6 |
| |
| |
| mapping read_until; |
| mixed lasttitle; // Aufbau s.o. |
| mixed message; |
| int deadTID; |
| string GROUP; |
| |
| int GetTID(mixed message); |
| private void InitialSubscriptions(); |
| |
| create() |
| { |
| ::create(); |
| seteuid(getuid()); |
| GROUP="bekanntmachungen"; |
| SetProp(P_SHORT,"Die Zeitung"); |
| SetProp(P_NAME,"Zeitung"); |
| SetProp(P_WEIGHT, 50); |
| SetProp(P_SIZE, 35); |
| SetProp(P_MATERIAL, ([MAT_PAPER: 100]) ); |
| SetProp(P_GENDER, FEMALE); |
| AddId(({"nn","zeitung","servicepaket","mpa"})); |
| SetProp(P_NODROP, |
| "Das persoenliche Servicepaket der MPA kann man nicht wegwerfen.\n"); |
| SetProp(P_NEVERDROP, 1); |
| |
| if (!read_until) read_until=(["muell":-1]); |
| } |
| |
| static mixed _query_read_msg() { return long(); } |
| |
| long() { |
| return "\ |
| Dies ist das Servicepaket der MPA (Morgengrauens Presse Agentur) -\n\ |
| die Zeitung des Morgengrauens.\n\ |
| Du kannst damit aktuelle Artikel lesen und schreiben, mit folgenden Befehlen:\n\ |
| 'nn [rubrik]' (Neueste Nachrichten) wuehlt die Rubrik durch und schaut,\n\ |
| ob was neu ist. Der erste ungelesene Artikel wird angezeigt.\n\ |
| Ohne Argument werden alle Rubriken durchwuehlt.\n\ |
| 'hilfe mpa' Ausfuehrliche Hilfsseite. Lesen dringend empfohlen!\n\ |
| Weitere Befehle:\n\ |
| rubriken [neu] bestelle <rubrik> ab\n\ |
| [lies ]rubrik <rubrik> abonniere <rubrik>\n\ |
| inhalt [<rubrik>|neu|suche <text>] wiederhole ...\n\ |
| nn <rubriken>|<liste> uebergehe ...\n\ |
| [lies ]artikel <nummer>"+ |
| ( (IS_LEARNER(TP)) ? " speichere artikel <nr>" : "" )+"\n\ |
| schreib <titel> versende artikel [nr] an <adresse>\n\ |
| antworte [auf artikel <nr>] [titel] verlege artikel <nr> nach <rubrik>\n\ |
| loesche artikel <nr> zeitungsmeldung [neue Meldung]\n\ |
| verbrenne zeitung wenn Dir alles zuviel wird....\n\ |
| "+ (IS_SEER(TP) ? "\ |
| Mit 'mail' bzw 'mail <spieler>' kannst Du Post lesen und schreiben.\n\ |
| " : "" )+"\ |
| Eingebaute aliase: note, catchup, reply, unsubscribe, subscribe, uncatchup.\n\ |
| Viele Befehle geben mit '<befehl> ?' einige Syntaxhinweise.\n\ |
| Aktuelle Rubrik: "+GROUP+"\n\ |
| "; |
| } |
| |
| |
| init() |
| { |
| ::init(); |
| |
| add_action("schreib","schreib"); |
| add_action("schreib","schreibe"); |
| add_action("schreib","note"); |
| add_action("LiesArtikel","lies"); |
| add_action("artikel","artikel"); |
| add_action("loesche","loesch"); |
| add_action("loesche","loesche"); |
| add_action("rubrik","rubrik"); |
| add_action("inhalt","inhalt"); |
| add_action("rubriken","rubriken"); |
| add_action("ReadNextUnread","nn"); |
| add_action("Catchup","catchup"); |
| add_action("Catchup","uebergeh"); |
| add_action("Catchup","uebergehe"); |
| add_action("Uncatchup","wiederhol"); |
| add_action("Uncatchup","wiederhole"); |
| add_action("Uncatchup","uncatchup"); |
| add_action("Reply","antwort"); |
| add_action("Reply","antworte"); |
| add_action("Reply2","reply"); |
| add_action("HelpPage","hilfe"); |
| add_action("HelpPage","man"); |
| add_action("Unsubscribe","unsubscribe"); |
| add_action("Bestelle","bestell"); |
| add_action("Bestelle","bestelle"); |
| add_action("Subscribe","subscribe"); |
| add_action("Subscribe","abonnier"); |
| add_action("Subscribe","abonniere"); |
| add_action("MoveMessage","verleg"); |
| add_action("MoveMessage","verlege"); |
| add_action("SetNNADWMSG","zeitungsmeldung"); |
| add_action("Ignore","ignorier"); |
| add_action("Ignore","ignoriere"); |
| add_action("MailMessage","versende"); |
| add_action("verbrennen","verbrenne"); |
| |
| if (IS_SEER(TP)) { |
| add_action("Mail","mail"); |
| } |
| if (IS_LEARNER(TP)) { |
| add_action("SaveMessage","speicher"); |
| add_action("SaveMessage","speichere"); |
| add_action("ReadNextUnread","read"); /* NF Compatibility Special */ |
| } |
| if (IS_ELDER(TP)) |
| { |
| add_action("MoveTrash","trash"); |
| } |
| init_rescue(); |
| } |
| |
| verbrennen(str) { |
| if (!str || !id(str)) return 0; |
| write("Du verbrennst Deine Zeitung mit groesstem Vergnuegen.\n"); |
| say(TP->Name(WER)+" verbrennt "+ |
| TP->QueryPossPronoun(FEMALE, WEN, SINGULAR)+" Zeitung in einem " |
| "Freudenfeuer.\n"); |
| remove(1); |
| return 1; |
| } |
| |
| // KillGroup - loescht eine nicht mehr benoetigte Rubrik aus der Liste. |
| // Aufruf aus rubriken() und ReadNextUnread(), wenn die gueltige |
| // Rubrikenliste sowieso schon abgerufen wurde. |
| |
| static KillGroup(name) { read_until=m_copy_delete(read_until,name); } |
| |
| /* RebuildGroupList() - tut doch nicht so, weil /secure/news anders arbeitet. |
| * Bleibt vorerst zum Nachschlagen. |
| static RegisterGroup(name) { read_until[name]=1; } |
| static RebuildGroupList() { |
| mixed groups; |
| if ((pointerp(groups=NEWSSERVER->GetGroups()))&&(sizeof(groups))) { |
| map(m_indices(read_until)-groups-SYSTEMGROUPS,#'KillGroup); |
| map(groups-m_indices(read_until),#'RegisterGroup); |
| } |
| TP->SetProp(P_READ_NEWS,read_until); |
| } |
| */ |
| |
| |
| _set_autoloadobj(mixed arg) { |
| |
| if (pointerp(arg) && sizeof(arg)>=2) |
| { |
| read_until=arg[1]; |
| } |
| else { |
| if (TP) |
| read_until=((TP->QueryProp(P_READ_NEWS))||([])); |
| } |
| |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| } |
| |
| _query_autoloadobj() { |
| return 1; |
| } |
| |
| static Mail(str) { |
| object mailer; |
| if (this_interactive()!=this_player()) return 0; |
| mailer=clone_object(MAILER); |
| mailer->SetOfficeName("mpa Kurierdienst"); |
| mailer->do_mail( ((!str)||(str=="mail")) ? 0 : TP->_unparsed_args() ); |
| return 1; |
| } |
| |
| static varargs string Message2string(mixed msg,mixed messages,int flag,string group) { |
| // Aufrufe: (Nummer,Notes[,flag[,group]]) oder (Note,Notes[,flag[,group]]) |
| // flag: M2S_VT100 : ggf ANSI-Codes verwenden |
| // M2S_REMOTE: Rubrik und Artikelnummer ausgeben (speichern, versenden) |
| // Achtung: Wenn flag&M2S_REMOTE, muss msg int sein |
| // group: Name der Rubrik, wenn nicht aktuelle Rubrik. Nur bei M2S_REMOTE |
| |
| string txt,hs,s,*m,s2; |
| int i,hi,thisnr,ansiflag; |
| |
| if (flag&M2S_REMOTE) txt="Rubrik: "+(group?group:GROUP)+", Artikel: "+ |
| (intp(msg)?to_string(msg+1):"???")+" von "+sizeof(messages)+"\n"; |
| else txt=""; |
| |
| if (intp(msg)) { |
| thisnr=msg; |
| msg=messages[msg]; |
| } else thisnr=-1; |
| if (!msg) return 0; |
| |
| ansiflag=(flag&M2S_VT100)&&(this_player()->QueryProp(P_TTY)!="dumb"); |
| |
| txt += (ansiflag?ANSI_BOLD:"")+ msg[M_TITLE]+(ansiflag?ANSI_NORMAL:"")+ |
| " ("+msg[M_WRITER]+", "+ |
| dtime(msg[M_TIME])[5..26]+"):\n"; |
| // if (geteuid(TP)=="sitopanaki") txt+="TID="+GetTID(msg)+"\n"; // Debug |
| if (!IS_STATUSLINE(msg[M_MESSAGE])) |
| return txt+"\n"+msg[M_MESSAGE]; |
| m=explode(msg[M_MESSAGE],"\n"); |
| while (IS_STATUSLINE(m[0])) { |
| // txt+=m[0]+"\n"; // ### |
| if (sscanf(m[0],"%s rn=%s rt=%d rg=%s",hs,s,hi,hs)==4 || |
| sscanf(m[0],"%s rn=%s rt=%d",hs,s,hi)==3) |
| { |
| int nr,h; |
| nr=-1; |
| if (pointerp(messages)) |
| { |
| for (h=((thisnr>=0) ? thisnr-1 : sizeof(messages)-1); |
| (h>=0 && messages[h][M_TIME]>=hi);h--) |
| if (messages[h][M_TIME]==hi && |
| lower_case(messages[h][M_WRITER])==lower_case(s)) |
| nr=h; |
| } |
| txt+="[Bezug: Artikel "+((nr>=0) ? (nr+1) : |
| (hs==STATUSESCAPE||hs==(group?group:GROUP)?"(geloescht?)":"in "+hs))+ |
| " von "+capitalize(s)+" vom "+dtime(hi)[5..26]+"]\n"; |
| } |
| if (sscanf(m[0],"%s on=%s ot=%d og=%s",hs,s,hi,hs)==4) { |
| txt+="[Autor: "+s+", "+dtime(hi)[5..26]+", verlegt von "+hs+"]\n"; |
| } |
| m=m[1..]; |
| } |
| return txt+"\n"+implode(m,"\n"); |
| } |
| |
| static varargs lies(mixed str) { |
| mixed num; |
| mixed *messages; |
| int tid; |
| |
| if (str=="?"||str=="-?") return |
| write("Syntax: lies <nr>\n" |
| " artikel <nr>\n" |
| "Siehe auch: nn\n"),1; |
| |
| if (intp(str)) num=str; |
| if ((!num && (!str || str=="" || sscanf(str,"%d",num)!=1)) || num<=0) { |
| notify_fail("WELCHE Nachricht willst Du lesen?\n"); |
| return 0; |
| } |
| if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP))) |
| return notify_fail("Seltsam, die Rubrik '"+GROUP+ |
| "' gibt es nicht mehr...\n"), 0; |
| num--; |
| if (sizeof(messages)<=num) { |
| notify_fail("So viele Artikel sind da nicht!\n"); |
| return 0; |
| } |
| |
| lasttitle=({messages[num][M_TITLE],messages[num][M_WRITER], |
| messages[num][M_TIME],GetTID(messages[num]),GROUP,num}); |
| this_player()->More(Message2string(messages[num],messages,M2S_VT100)); |
| if (this_player() && IS_LEARNER(this_player())) |
| this_player()->save_me(1); |
| return 1; |
| } |
| |
| static varargs mixed GetGroupName(mixed g,mixed groups) { |
| /* Name einer Rubrik. g ist int oder string, enthaelt Name oder Nummer |
| (ab 1 numeriert) */ |
| mixed i,expr,gg; |
| if (!g) return write("Du solltest schon die Rubrik angeben.\n"),0; |
| if (!groups) groups=NEWSSERVER->GetGroups(); |
| if (intp(i=g) || sscanf(g,"%d",i)) { |
| if (i>0 && i<=sizeof(groups)) return groups[i-1]; |
| write("Eine Rubrik mit der Nummer "+i+" gibt es leider nicht.\n"); |
| return 0; |
| } |
| g=lower_case(g); |
| switch(g){ |
| case ".": return GROUP; |
| case "+": return groups[(member(groups,GROUP)+1)%sizeof(groups)]; |
| case "-": |
| return groups[(member(groups,GROUP)-1+sizeof(groups))%sizeof(groups)]; |
| } |
| |
| // Existiert die Rubrik genau so? |
| if (member(groups,g)>-1) return g; |
| |
| g = regreplace(g,"[[\\]\\*()?]","",1); |
| // haerteres Kriterium: Alle Abschnitte angegeben |
| expr="^"+implode(explode(g,"."),"[^\\.]*\\.")+"[^\\.]*$"; |
| // write("REGEXP="+expr+"\n"); |
| gg=regexp(groups,expr); |
| if (sizeof(gg)==1) return gg[0]; |
| |
| // weicheres Kriterium: Nicht alle Abschnitte angegeben |
| expr="^(.*\\.)*"+implode(explode(g,"."),".*\\.")+".*$"; |
| // write("REGEXP="+expr+"\n"); |
| gg=regexp(groups,expr); |
| |
| if (!sizeof(gg)) { |
| write("Eine Rubrik '"+g+"' gibt es hier leider nicht.\n"); |
| return 0; |
| } |
| |
| if (sizeof(gg)==1) return gg[0]; |
| |
| write(break_string("Die Rubrik "+g+" ist nicht eindeutig. Wahrscheinlich " |
| "meinst Du eine der folgenden: "+implode(gg,", ")+".\n",78)); |
| return 0; |
| } |
| |
| static rubrik(str) |
| { |
| mixed *gruppen; |
| mixed news; |
| int anz,i; |
| |
| if (str=="?"||str=="-?") return |
| write("Syntax: rubrik <rubrik>\n" |
| " wechselt die aktuelle Rubrik. Es wird die Nummer der Rubrik,\n" |
| " ihr Name oder jede eindeutige Abkuerzung akzeptiert.\n"),1; |
| |
| if (!str || str==0) { |
| if (!pointerp(news=NEWSSERVER->GetNotes(GROUP))){ |
| GROUP=DEFAULTGROUP; |
| if (!pointerp(news=NEWSSERVER->GetNotes(GROUP))) |
| return notify_fail("Seltsam, irgendwie geht hier einiges schief...\n"),0; |
| } |
| return write("Aktuelle Rubrik: "+GROUP+" ("+sizeof(news)+" Artikel).\n"),1; |
| } |
| str=GetGroupName(str); |
| if (!str) return 1; |
| GROUP=str; |
| news=NEWSSERVER->GetNotes(GROUP); |
| write(break_string("Ok, Du hast die Rubrik "+GROUP+" mit "+sizeof(news)+ |
| " Artikel"+(sizeof(news)==1?"":"n")+" aufgeschlagen.\n", |
| 78)); |
| return 1; |
| } |
| |
| LiesArtikel(str) { |
| string s1; |
| int i1; |
| if ( !str ) return 0; |
| if (sscanf(str,"rubrik %s",s1)) |
| return rubrik(s1); |
| if (sscanf(str,"%d",i1)) |
| return lies(to_int(i1)); |
| if (sscanf(str,"artikel %s",s1)) |
| return lies(s1); |
| } |
| |
| |
| /* Ueberpruefe, ob in Rubrik tote threads ignoriert werden. Tot bedeutet, |
| dass der letzte darin uebergangene Artikel bereits expired ist UND |
| keine Artikel aus diesem thread mehr vorhanden sind. |
| ACHTUNG: Es kann passieren, dass dazwischen noch ein neuer Artikel |
| dazugekommen ist. |
| Hier wird auf expired geprueft und ggf Variable deadTID gesetzt. Wird beim |
| Lesen mit nn ein Artikel mit dieser TID gefunden (passiert direkt hinter |
| Pruefung), wird deadTID wieder auf 0 gesetzt. Ist deadTID beim Umschalten |
| auf naechste Rubrik !=0, ist der thread tot. |
| */ |
| |
| static int CheckThreads(string rubrik,int timeout) { |
| mixed tids; |
| int i; |
| |
| // deadTID=0; |
| tids=m_indices(read_until[IGNOREGROUP][rubrik]); |
| for (i=sizeof(tids)-1;i>=0&&!deadTID;i--) |
| if (read_until[IGNOREGROUP][rubrik][tids[i]]<timeout) deadTID=tids[i]; |
| return 1; |
| } |
| |
| static int rubriken(mixed arg) |
| { |
| mixed *gruppen, *messages; |
| mixed news; |
| int anz,i,lasttime,timeout,foundone; |
| string s; |
| |
| if (arg=="?"||arg=="-?") return |
| write("Syntax: rubriken listet alle Rubriken\n" |
| " rubriken neu nur Rubriken mit ungelesenen Artikeln\n"),1; |
| |
| gruppen=NEWSSERVER->GetGroups(); |
| map(m_indices(read_until)-gruppen-SYSTEMGROUPS,#'KillGroup); // '); |
| s="\nEs gibt zur Zeit "; |
| anz=sizeof(gruppen); |
| if (anz==0) { |
| write(s+"keine Rubriken (wie seltsam ...)\n"); |
| return 1; |
| } |
| s+=anz+" Rubrik"+(anz==1 ? "" : "en")+"."; |
| if (arg=="neu") s+="\nDavon enthalten neue Artikel:\n\n"; |
| else s+="\n(* oder x: enthaelt neue Artikel, x oder -: abbestellt, " |
| ">: aktuelle Rubrik)\n\n"; |
| for (i=0;i<anz;i++) { |
| timeout=read_until[gruppen[i]]; |
| /* GetNewsTime lieferte leider manchmal was falsches :-( */ |
| /* jetzt hoffentlich richtig? Wenn nicht, das if ausklammern */ |
| if ( arg!="neu" || (lasttime=NEWSSERVER->GetNewsTime(gruppen[i])) > timeout) { |
| messages=NEWSSERVER->GetNotes(gruppen[i]); |
| if (!messages || !sizeof(messages)) lasttime=0; |
| else lasttime=messages[sizeof(messages)-1][M_TIME]; |
| foundone=1; |
| } |
| if (arg!="neu" || (timeout>=0 && lasttime>abs(timeout))) |
| s+=sprintf("%s%s%3d\. %-39.39s: ", |
| ((gruppen[i]==GROUP)?">":" "), |
| ((lasttime>abs(timeout)) ? ((timeout<0) ? "x" : "*") |
| : ((timeout<0) ? "-" : " ") ), |
| i+1,gruppen[i])+ |
| (lasttime ? sprintf("%3d Artikel (%s)\n", |
| sizeof(messages), |
| // ((sizeof(messages)==1) ? ". " : "en."), |
| dtime(lasttime)[5..12]+ctime(lasttime)[<2..]) : |
| " - leer -\n"); |
| } |
| if (arg=="neu"&&!foundone) s+="Keine Rubrik enthaelt neue Artikel.\n"; |
| this_player()->More(s); |
| return 1; |
| } |
| |
| #define M_READNEXT 1 |
| #define M_LISTNEW 2 |
| #define M_LISTNEWGR 3 |
| #define M_READGR 4 |
| |
| static ReadNextUnread(str) |
| { |
| string *groups,group; |
| mixed *messages; |
| int curgr,curmsg,timeout,start,nrgroups,sog,mode; |
| |
| if (str=="mail") return Mail(0); /* NF Compatibility Special */ |
| |
| if (str=="?"||str=="-?") return |
| write("Syntax: nn naechster neuer Artikel\n" |
| " nn <rubrik> in entspr. Rubrik, wenn da was neu ist\n" |
| " nn rubriken Liste der Rubriken mit neuen Artikeln\n" |
| " nn liste Liste der ungelesenen Artikel\n"),1; |
| |
| groups=NEWSSERVER->GetGroups(); |
| deadTID=0; |
| map(m_indices(read_until)-groups-SYSTEMGROUPS,#'KillGroup); //' |
| nrgroups=sizeof(groups); |
| if (str && str!="rubriken" && str!="liste"){ |
| if (!group=GetGroupName(str)) return 1; |
| } |
| else |
| group=0; |
| if (group && (curgr=member(groups,group)+1)) { |
| --curgr; |
| if (curgr<0 || curgr>=sizeof(groups)) |
| return notify_fail("Nee... so eine Rubrik gibts hier nicht.\n"),0; |
| GROUP=group; |
| start=curgr+1; |
| mode=M_READGR; |
| write("Rubrik "+(curgr+1)+": "+GROUP+"\n"); |
| } else { |
| switch (str) { |
| case 0: mode=M_READNEXT; break; |
| case "liste": mode=M_LISTNEW; write("Du hast noch nicht gelesen:\n"); break; |
| case "rubriken": return rubriken("neu"); |
| default: |
| notify_fail("\ |
| Diesen Parameter verstehe ich nicht. Entweder gar nichts, \"liste\"\n\ |
| \"rubriken\", oder Name bzw. Nummer einer Rubrik.\n"); |
| return 0; |
| } |
| curgr=member(groups,GROUP); |
| start=curgr+nrgroups; |
| } |
| if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP))){ |
| GROUP=DEFAULTGROUP; |
| if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP))) |
| return notify_fail("Seltsam, irgendwie geht hier einiges schief...\n"),0; |
| } |
| timeout=read_until[GROUP]; |
| curmsg=0; |
| sog=sizeof(messages); |
| while (curgr<start) { |
| ++curmsg; |
| if (curmsg>sog) { |
| if (deadTID) |
| read_until[IGNOREGROUP][GROUP]= |
| m_copy_delete(read_until[IGNOREGROUP][GROUP],deadTID); |
| ++curgr; |
| deadTID=0; |
| if (mode!=M_READGR) { |
| GROUP=groups[curgr%nrgroups]; |
| timeout=read_until[GROUP]; |
| if (!timeout) read_until[GROUP]=1; // Nimm neue Gruppen in Liste auf |
| if (timeout<0 || timeout>=NEWSSERVER->GetNewsTime(GROUP)) { |
| sog=0; /* Ueberlistung: Gruppe hat nix neues oder */ |
| curmsg=1; /* ist unsubscribed */ |
| } |
| else { |
| messages=NEWSSERVER->GetNotes(GROUP); |
| curmsg=0; |
| sog=sizeof(messages); |
| } |
| } |
| } else { |
| if ((timeout>=0 || mode==M_READGR) && messages[curmsg-1][M_TIME] > abs(timeout)) { |
| if (pointerp(this_player()->QueryProp(P_IGNORE)) && |
| member(this_player()->QueryProp(P_IGNORE), |
| lower_case(messages[curmsg-1][M_WRITER])+".news") != -1) { |
| printf("Uebergehe ignorierten Artikel %d von %s in Rubrik %s.\n", |
| curmsg,messages[curmsg-1][M_WRITER],GROUP); |
| read_until[GROUP]=messages[curmsg-1][M_TIME]; |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| } else if |
| (read_until[IGNOREGROUP]&& |
| read_until[IGNOREGROUP][GROUP]&& |
| CheckThreads(GROUP,messages[0][M_TIME])&& /* Tote threads weg */ |
| read_until[IGNOREGROUP][GROUP][GetTID(messages[curmsg-1])]) { |
| printf("Uebergehe Artikel %d aus ignoriertem Thread.\n",curmsg); |
| read_until[IGNOREGROUP][GROUP][GetTID(messages[curmsg-1])]= |
| messages[curmsg-1][M_TIME]; |
| if (deadTID&&deadTID==GetTID(messages[curmsg-1])) deadTID=0; |
| read_until[GROUP]=messages[curmsg-1][M_TIME]; |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| } else { |
| write("\nRubrik "+(curgr%nrgroups+1)+": "+GROUP+", Artikel: "+curmsg+" von "+sog+"\n"); |
| if (mode==M_LISTNEW) { |
| write(sprintf(" %-45s [%-11s] %s\n",messages[curmsg-1][M_TITLE], |
| messages[curmsg-1][M_WRITER], |
| dtime(messages[curmsg-1][M_TIME])[5..16])); |
| } else { /* mode == M_READNEXT || mode==M_READGR */ |
| if (timeout>=0) read_until[GROUP]=messages[curmsg-1][M_TIME]; |
| else read_until[GROUP]=-messages[curmsg-1][M_TIME]; |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| return (lies(""+curmsg)); |
| } |
| } |
| } |
| /* sonst mach einfach garnix. Schleife laeuft weiter. */ |
| } |
| } |
| switch(mode) { |
| case M_LISTNEW: return 1; |
| case M_READNEXT: write((read_until[NNADWMSG]||"Nix Neues auf der Welt.") |
| +"\n"); break; |
| case M_READGR: write("Nix Neues in dieser Rubrik.\n"); break; |
| } |
| return 1; |
| } |
| |
| |
| static SetNNADWMSG(str) { |
| if (str=="?"||str=="-?") return |
| write("Syntax: zeitungsmeldung <neue Meldung> setzt Meldung\n" |
| " zeitungsmeldung loescht Meldung\n"),1; |
| if (!read_until[NNADWMSG]) { |
| write("Du hast zur Zeit keine eigene NNADW-Meldung definiert.\n"); |
| if (!str) return 1; |
| } |
| else write("Deine alte NNADW-Meldung war:\n"+read_until[NNADWMSG]+"\n"); |
| if (!str) { |
| read_until=m_copy_delete(read_until,NNADWMSG); |
| write("Meldung ist geloescht, es gilt wieder die Standardmeldung.\n"); |
| } else { |
| read_until[NNADWMSG]=this_player()->_unparsed_args(); |
| write("Deine neue Meldung lautet jetzt:\n"+read_until[NNADWMSG]+"\n"); |
| } |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| return 1; |
| } |
| |
| varargs int InterpretTime(mixed a,int flag) { |
| // string oder string * |
| // akzeptiert folgende Formate: |
| // dd.mm.jj (Rueckgabe: 0:00 des entsprechenden Tages) |
| // vor [<anz> d|tagen] [<anz> h|stunden] [<anz> m|minuten] |
| // flag=1: "inklusive": bei dd.mm.jj-Format 23:59:59 statt 0:00 Uhr |
| |
| int i,j,k,t,nrargs; |
| string s; |
| if (stringp(a)) a=explode(a," "); |
| |
| // printf("%O\n",a); |
| |
| if ((nrargs=sscanf(a[0],"%d.%d.%d",i,j,k))==3 || |
| (nrargs=sscanf(a[0],"%d.%d.",i,j))==2) { |
| // Datum -> Zeit: Funktioniert im Zeitraum 1973 - ca. 2090 |
| // in Zeitzonen mit ganzen Stunden ggue Rechneruhr. |
| if (nrargs==2) |
| k=70+time()/31536000; |
| if (k<70) k+=100; |
| if (k>1970) k-=1900; |
| if (k<70||k>150) return |
| write("Unzulaessiges Jahr (erlaubt: 70-heute).\n"),0; |
| t=(k-70)*31536000; |
| |
| if (i<1||i>31) return write("Unzulaessiger Tag (erlaubt: 1-31).\n"),0; |
| if (j<1||j>12) return write("Unzulaessiger Monat (erlaubt: 1-12).\n"),0; |
| // printf("%d.%d.%d\n",i,j,k); |
| s=ctime(t); |
| if ((j>2) && !(k%4)) t+=86400; // Schaltjahrkorrektur fuer Monate>=3 |
| t+=({ 0, 2678400, 5097600, 7776000, |
| 10368000, 13046400, 15638400, 18316800, |
| 20995200, 23587200, 26265600, 28857600})[j-1]; |
| t+=86400*(i-1); |
| t+=86400*(32-to_int(s[8..9])); // Schaltjahrkorrektur |
| t-=3600*to_int(s[11..12]); // Zeitzonenkorrektur |
| t-=3600*to_int(ctime(t)[11..12]); // Sommerzeitkorrektur |
| // write("Kontrolle: "+dtime(t)+"\n"); |
| if (nrargs==2 && t>time()) t-=31536000; |
| return (flag?t+86399:t); |
| } |
| |
| t=0; |
| if (a[0]=="vor") for (i=sizeof(a)-1;i>0;i--) { |
| switch (a[i]) { |
| case "m": |
| case "minuten": |
| case "min": |
| case "minute": |
| t+=60*to_int(a[i-1]); |
| break; |
| case "h": |
| case "stunde": |
| case "stunden": |
| case "s": |
| t+=3600*to_int(a[i-1]); |
| break; |
| case "d": |
| case "tag": |
| case "tage": |
| case "t": |
| t+=86400*to_int(a[i-1]); |
| break; |
| default: |
| if (!to_int(a[i])) |
| write("Argumentfehler: Kann nichts mit '"+a[i]+"' anfangen.\n"); |
| } |
| return time()-t; |
| } |
| else return write("Argumentfehler.\n"),0; |
| } |
| |
| static Catchup(string str) |
| { |
| int welche,zeit,i; |
| string gr; |
| mixed groups,news,args; |
| |
| if (!pointerp(NEWSSERVER->GetNotes(GROUP))) |
| return notify_fail("Seltsam, die Rubrik '"+GROUP+ |
| "' gibt es nicht mehr...\n"), 0; |
| |
| str=this_player()->_unparsed_args(); // wg. Datum |
| if (str) str=lower_case(str); |
| else str=GROUP; // default: aktuelle Rubrik komplett. |
| |
| if (str=="?"|| str=="-?") return CatchupSyntax(); |
| |
| // uebergehe Antworten (Thread ignorieren) |
| if (str&&(str[0..6]=="antwort"||str=="thread")) { |
| if (!pointerp(lasttitle)) return |
| write("Du hast bisher noch keinen Artikel gelesen, damit kann ich nicht wissen,\nwelchen Thread du uebergehen willst.\n"),1; |
| if (!read_until[IGNOREGROUP]) read_until[IGNOREGROUP]=([]); |
| if (!read_until[IGNOREGROUP][GROUP]) read_until[IGNOREGROUP][GROUP]=([]); |
| if (read_until[IGNOREGROUP][GROUP][lasttitle[3]]) { |
| read_until[IGNOREGROUP][GROUP]=m_copy_delete(read_until[IGNOREGROUP][GROUP],lasttitle[3]); |
| write("Dieser Thread wird jetzt nicht mehr uebergangen.\n"); |
| } else { |
| read_until[IGNOREGROUP][GROUP][lasttitle[3]]=lasttitle[2]; |
| write("Dieser Thread wird ab sofort uebergangen.\nFalls das ein Irrtum war, wiederhole den Befehl augenblicklich.\n"); |
| } |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| return 1; |
| } |
| |
| groups=NEWSSERVER->GetGroups(); |
| |
| args=explode(str," "); |
| |
| // Uebergehe alles |
| |
| if (args[0]=="alle" || args[0]=="alles" || args[0]=="all") { |
| if (sizeof(args)<=1) zeit=time()-1; |
| else if (args[1]!="bis") return CatchupSyntax(); |
| else if (sizeof(args)<3) return CatchupSyntax(); |
| |
| else zeit=InterpretTime(args[2..],1); |
| if (zeit>time()) zeit=time()-1; |
| write("Uebergehe alle Rubriken bis "+dtime(zeit)+".\n"); |
| for (welche=0;welche<sizeof(groups);++welche) { |
| gr=groups[welche]; |
| // zeit=NEWSSERVER->GetNewsTime(gr); |
| if (abs(read_until[gr])<zeit) |
| read_until[gr]=(read_until[gr]>=0)?zeit:-zeit; |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| } |
| return 1; |
| } |
| |
| // Anzahl Artikel |
| |
| if (sizeof(args)>=2 && args[1]=="artikel") { |
| if (!to_int(args[0])) return CatchupSyntax(); |
| news=NEWSSERVER->GetNotes(GROUP); |
| for (i=sizeof(news)-1;i>=0&&news[i][M_TIME]>read_until[GROUP];i--); |
| welche=i+to_int(args[0]); |
| if (welche>=sizeof(news)) welche=sizeof(news)-1; |
| write("Uebergehe die naechsten "+(welche-i)+" Artikel in Rubrik "+ |
| GROUP+"\n."); |
| if (welche>=0) { |
| zeit=news[welche][M_TIME]; |
| read_until[GROUP]=(read_until[GROUP]>=0)?zeit:-zeit; |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| } |
| return 1; |
| } |
| |
| // einzelne Rubrik. |
| |
| if (!(gr=GetGroupName(args[0]))) return 1; |
| news=NEWSSERVER->GetNotes(gr); |
| if (!sizeof(news)) { |
| write("Rubrik "+gr+" ist leer.\n"); |
| return 1; |
| } |
| // zeit=news[sizeof(news)-1][M_TIME]; |
| if (sizeof(args)<=1) |
| zeit=time(); |
| else |
| if (args[1]!="bis") return CatchupSyntax(); |
| else |
| zeit=InterpretTime(args[2..],1); |
| if (zeit>time()) zeit=time(); |
| read_until[gr]=zeit; |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| write("Uebergehe "+gr+" bis "+dtime(zeit)+",\nletzter Artikel war vom "+ |
| dtime(NEWSSERVER->GetNewsTime(gr))+"\n"); |
| return 1; |
| } |
| |
| |
| static Ignore(str) { |
| if (str=="thread"||str=="antworten") return Catchup(str); |
| return 0; |
| } |
| |
| static CatchupSyntax() { |
| write("Syntax des Befehls uebergehe (oder catchup):\n" |
| " uebergehe [rubrik] (default: aktuelle Rubrik)\n" |
| " uebergehe alles (in allen Rubriken)\n" |
| " uebergehe <anz> artikel (in akt. Rubrik)\n" |
| " uebergehe [rubrik]|alles bis <tag>.<monat>.[<jahr>]\n" |
| " uebergehe [rubrik]|alles bis vor <zeit> wobei\n" |
| " <zeit> = [<n> d|tage] [<n> h|stunden] [<n> m|min|minuten]\n" |
| " uebergehe thread|antworten (entspr. 'ignoriere thread')\n"); |
| |
| return 1; |
| } |
| |
| |
| static int UncatchupSyntax() |
| { |
| notify_fail( |
| "Syntax: wiederhole <anz> [artikel]\n" |
| " wiederhole [ab vor] [<anz> m|minute[n]] [<anz> h|stunde[n]] [<anz> d|tag[e]]\n" |
| " wiederhole ab tag.monat[.jahr]\n" |
| " wiederhole alles\n" |
| "Der wiederhole- oder uncatchup-Befehl bezieht sich immer auf die aktuelle\n" |
| "Rubrik und markiert die angegebenen Artikel wieder als ungelesen.\n" |
| "Zeiten (2. Syntax) sind rueckwaerts ab aktueller Uhrzeit gerechnet.\n"),0; |
| return 0; |
| } |
| |
| |
| static Uncatchup(string str) |
| { |
| mixed args; |
| int i,zeit; |
| int mode; // 0 = nix, 1=Anzahl Artikel, 2=Zeit, 3=alles |
| |
| str=this_player()->_unparsed_args(); // wg. Datum |
| if ( !TP || !str || !stringp(str) || str=="?" || str=="-?" ) |
| return UncatchupSyntax(); |
| |
| if (!pointerp(NEWSSERVER->GetNotes(GROUP))) |
| return notify_fail("Seltsam, die Rubrik '"+GROUP+ |
| "' gibt es nicht mehr...\n"), 0; |
| |
| args=({""})+explode(lower_case(str)," "); |
| if (args[1]=="ab") { |
| mode=2; |
| if (sizeof(args)<3) |
| return UncatchupSyntax(); |
| zeit=InterpretTime(args[2..]); |
| } else { |
| zeit=time(); |
| for (i=sizeof(args)-1;i>0;i--) { |
| switch(args[i]){ |
| case "alles": |
| case "alle": |
| case "all": |
| if (mode&&mode!=3) return |
| notify_fail("Bitte nur Zeit ODER alles ODER Anzahl angeben!\n"),0; |
| mode=3; |
| break; |
| case "minuten": |
| case "minute": |
| case "m": |
| case "stunden": |
| case "stunde": |
| case "h": |
| case "tage": |
| case "tag": |
| case "d": |
| if (mode&&mode!=2) return |
| notify_fail("Bitte nur Zeit/Datum ODER alles ODER " |
| "Anzahl angeben!\n"),0; |
| mode=2; |
| zeit-=(((args[i][0]=='m') ? 60 : |
| ((args[i][0]=='s' || args[i][0]=='h') ? 3600 : 86400)) |
| *to_int(args[i-1])); |
| i--; |
| break; |
| case "artikel": |
| if (mode&&mode!=1) return |
| notify_fail("Bitte nur Zeit/Datum ODER alles ODER " |
| "Anzahl angeben!\n"),0; |
| mode=1; |
| zeit=to_int(args[i-1]); |
| i--; |
| break; |
| case "ab": |
| return |
| notify_fail("Bitte nur Zeit/Datum ODER alles ODER " |
| "Anzahl angeben!\n"),0; |
| default: |
| if (!to_int(args[i])) |
| return notify_fail("Unbekanntes Argument '"+args[i]+ |
| "'! Aktion abgebrochen.\n"),0; |
| if (mode&&mode!=1) return |
| notify_fail("Bitte nur Zeit/Datum ODER alles ODER " |
| "Anzahl angeben!\n"),0; |
| mode=1; |
| zeit=to_int(args[i]); |
| } |
| } |
| } |
| |
| switch(mode){ |
| case 0: |
| return notify_fail("Gib bitte irgendeine Einheit an " |
| "(Hilfe mit wiederhole -?)!\n"); |
| case 2: |
| read_until[GROUP]=(read_until[GROUP]>=0)?zeit:-zeit; |
| write(break_string("Markiere alle Artikel in Rubrik "+GROUP+ |
| " seit "+dtime(zeit)+" als ungelesen.\n",78)); |
| break; |
| case 3: |
| read_until[GROUP]=(read_until[GROUP]>=0?1:-1); |
| write("Markiere die komplette Rubrik "+GROUP+" als ungelesen.\n"); |
| break; |
| case 1: |
| write(break_string("Markiere die letzten "+zeit+ |
| " gelesenen Artikel in Rubrik "+GROUP+" als ungelesen.\n",78)); |
| { int h; mixed notes; |
| notes=NEWSSERVER->GetNotes(GROUP); |
| h=sizeof(notes)-1; |
| while ( (h>=0) && (abs(read_until[GROUP]) < notes[h][M_TIME]) ) { |
| h--; |
| } |
| if (h==-1||h<zeit) |
| read_until[GROUP]= |
| (read_until[GROUP]>=0)?1:-1; |
| else |
| read_until[GROUP]=( |
| (read_until[GROUP]>=0)?notes[h-zeit][M_TIME] |
| :-notes[h-zeit][M_TIME]); |
| } |
| } |
| write("Ok. Du kannst die als ungelesen markierten Artikel " |
| "mit nn nochmal lesen.\n"); |
| |
| if (TP) TP->SetProp(P_READ_NEWS,read_until); |
| return 1; |
| } |
| |
| |
| QueryRead() { |
| return read_until; |
| } |
| |
| static CatchNewsError(int err,string text4minus3) { |
| switch (err) { |
| case 1: return 1; |
| case -1: write("Du darfst in dieser Rubrik nicht schreiben!\n"); return 0; |
| case -2: write("Die Rubrik gibt es nicht mehr, sehr seltsam...\n"); return 0; |
| case -3: write(text4minus3+"\n"); return 0; |
| default: write("Interner Fehler "+err+", Erzmagier verstaendigen!\n"); return 0; |
| } |
| } |
| |
| static varargs schreib(str,pretext,called_by_itself,statuslines) { |
| int err; |
| |
| if (str=="?"||str=="-?") { |
| write("Syntax: schreib <Titel>\n" |
| " beginnt einen neuen Artikel in der Zeitung.\n"); |
| return 1; |
| } |
| |
| if (!this_interactive() || !this_interactive()->query_real_name()) return 0; |
| if (!called_by_itself && extern_call() && !pretext) |
| str=this_interactive()->_unparsed_args()||""; |
| if (called_by_itself && str=="~q") { |
| write("Abgebrochen.\n"); |
| return 1; |
| } |
| if (!CatchNewsError( |
| NEWSSERVER->AskAllowedWrite(GROUP), |
| "Diese Rubrik ist leider schon randvoll!")) return 1; |
| if (!called_by_itself) |
| write("Neuer Artikel in Rubrik "+GROUP+":\n"); |
| if (!str || str=="" || str=="artikel") { |
| input_to("schreib", INPUT_PROMPT, "Titel des Artikels: ", pretext,1); |
| return 1; |
| } |
| // writer=this_interactive()->query_real_name(); |
| message=allocate(6); |
| message[M_BOARD]=GROUP; |
| message[M_TITLE]=killctrl(str); |
| message[M_MESSAGE]=statuslines; |
| write("Titel ist: "+str+".\n\ |
| Gib jetzt Deinen Text ein,\n\ |
| ** oder . wenn Du fertig bist, ~q zum Abbrechen, ~h fuer eine Hilfsseite.\n"); |
| nedit("PostNote",pretext); |
| return 1; |
| } |
| |
| static varargs Reply(string str,string newtitle) { |
| mixed dummy,replytitle,s; |
| int nr; |
| |
| if ((dummy=(str||newtitle))=="?"||dummy=="-?") { |
| write("Der Antworte-Befehl ist doppelt belegt.\n" |
| "1. (Zeitung): Schreibe Antwort auf einen Artikel in der Zeitung.\n" |
| " Syntax: antworte\n" |
| " antworte auf artikel <nr> [neuer Titel]\n" |
| " reply [auf artikel <nr> | to note <nr>] [neuer Titel]\n" |
| "2. aehnlich 'sage':\n" |
| " Du tippst zum Beispiel:\n" |
| " antworte ja, das weiss ich\n" |
| " Alle Spieler im Raum sehen dann:\n" |
| " <Dein Name> antwortet: ja, das weiss ich.\n" |
| "Bitte beachte, dass jede Syntax, die auf den antworte-Befehl der " |
| "Zeitung\npasst, auch von der Zeitung ausgewertet wird.\n"); |
| return 1; |
| } |
| |
| if (str&& |
| ((sscanf(lower_case(str),"auf artikel %d",dummy)==1 && |
| str=this_player()->_unparsed_args()[12..])|| |
| (sscanf(lower_case(str),"to note %d",dummy)==1 && |
| str=this_player()->_unparsed_args()[8..]))) { |
| mixed notes; |
| notes=NEWSSERVER->GetNotes(GROUP); |
| if (dummy<1||dummy>sizeof(notes)) |
| return write("Einen Artikel mit der Nummer "+dummy+ |
| " gibt es in dieser Rubrik nicht.\n"),1; |
| dummy--; |
| replytitle=({notes[dummy][M_TITLE],notes[dummy][M_WRITER], |
| notes[dummy][M_TIME],GetTID(notes[dummy]),GROUP}); |
| DEBUGVAR(str); |
| if (!newtitle&&str&&sizeof(str)&&sscanf(str,"%d %s",dummy,str)==2) |
| newtitle=str; |
| } |
| else if (!str||!sizeof(str)) { |
| if (!lasttitle) return |
| write("Du hast noch gar nichts gelesen, worauf Du " |
| "antworten koenntest.\n"),1; |
| replytitle=lasttitle; |
| } |
| else return 0; |
| |
| // return ComposeReply(replytitle); |
| //} |
| // |
| // |
| //ComposeReply(mixed replytitle) { |
| |
| if (!newtitle) { |
| if (replytitle[0][0..7]=="Re: Re: ") newtitle="Re^3: "+replytitle[0][8..]; |
| else if (sscanf(replytitle[0],"Re^%d: %s",nr,newtitle)) |
| newtitle="Re^"+(nr+1)+": "+newtitle; |
| else newtitle="Re: "+replytitle[0]; |
| } |
| return schreib(newtitle,0,0, |
| STATUSESCAPE+" rn="+replytitle[LAST_WRITER]+ |
| " rt="+replytitle[LAST_TIME]+ |
| " rg="+replytitle[LAST_GROUP]+"\n"+ |
| STATUSESCAPE+" tid="+replytitle[LAST_TID]+"\n"); |
| } |
| |
| static Reply2(str) { |
| str = this_player()->_unparsed_args(); |
| if (!str||str[0..11]=="auf artikel "||str[0..7]=="to note ") |
| return Reply(str); |
| return Reply(0,str); |
| } |
| |
| static void InformPlayers(string group,string player,string text) |
| { |
| object *players; |
| int i; |
| mixed data; |
| string ig; |
| |
| players=users(); |
| ig=lower_case(player)+".news"; |
| for (i=sizeof(players)-1;i>=0;i--) { |
| data=players[i]->QueryProp(P_WAITFOR); |
| if (pointerp(data)&&(member(data,"Mpa")>-1)) { |
| data=players[i]->QueryProp(P_READ_NEWS); |
| if (mappingp(data)&&(data[group]>0)) { |
| data=players[i]->QueryProp(P_IGNORE); |
| if ((!pointerp(data))||(member(data,ig)==-1)) |
| tell_object(players[i],text); |
| } |
| } |
| } |
| } |
| |
| static PostNote(text) { |
| int err; |
| string sig; |
| |
| if (!text) { |
| write("Abbruch! Artikel landet im Reisswolf.\n"); |
| return 1; |
| } |
| if (!sizeof(old_explode(text,"\n")- |
| ({"q","quit"," **","** ","ende","","exit"," "}) |
| ) ) |
| return write("\ |
| ACHTUNG: Wolltest Du wirklich einen Artikel ohne Inhalt in die mpa setzen?\n\ |
| Artikel ohne erkennbaren Inhalt werden NICHT veroeffentlicht. Bitte ueber-\n\ |
| pruef Deine Syntax, falls Du keinen Artikel schreiben wolltest, oder schreib\n\ |
| auch ein bisschen Text!\n\ |
| Artikel landet im Reisswolf.\n"),1; |
| if (!message[M_MESSAGE]) |
| message[M_MESSAGE] = text; |
| else |
| message[M_MESSAGE]+=text; |
| if (sig=read_file("/players/"+geteuid(this_interactive())+"/.signature")) |
| message[M_MESSAGE]+=sig; |
| if (!CatchNewsError(NEWSSERVER->WriteNote(message), |
| "Diese Rubrik ist voll. Mist, da war jemand schneller...")) { |
| 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"); |
| return 0; |
| } |
| write("OK, Artikel ist veroeffentlicht.\n"); |
| say(capitalize(TP->name())+ |
| " hat einen Artikel in der Zeitung veroeffentlicht.\n"); |
| if (geteuid(TP)!="sitopanaki") |
| InformPlayers(message[M_BOARD],geteuid(this_interactive()), |
| "* MPA: Neuer Artikel von "+ |
| capitalize(geteuid(this_interactive()))+ |
| " in Rubrik \""+message[M_BOARD]+"\".\n"); |
| message=0; /* Platz sparen! */ |
| return 1; |
| } |
| |
| |
| //static // allowing aliasing *Rumata* 5/8/96 |
| inhalt(str) { |
| int i,endflag,timeout; |
| string *gruppen,s,txt,suche; |
| mixed messages; |
| |
| if (str=="?"||str=="-?") return |
| write("Syntax: inhalt [<rubrik>] [ende] [suche <text>]\n"),1; |
| |
| str=(!str)?({}):explode(str," "); |
| |
| if (sizeof(str) && (str[0]=="neu" || str[0]=="neues") ) |
| return ReadNextUnread("liste"),1; |
| |
| if (endflag=member(str,"ende")+1) str-=({"ende"}); |
| if (((i=member(str,"suche")) != -1) && (sizeof(str) > i)) { |
| suche=lower_case(implode(str[i+1..]," ")); |
| str=str[0..i-1]; |
| } |
| else |
| suche=0; |
| if (!sizeof(str)) { |
| str=GROUP; |
| if (!pointerp(messages=NEWSSERVER->GetNotes(str))){ |
| str=GROUP=DEFAULTGROUP; |
| if (!pointerp(messages=NEWSSERVER->GetNotes(str))) |
| return notify_fail("Seltsam, irgendwie geht hier einiges schief...\n"),0; |
| } |
| } |
| else { |
| str=GetGroupName(str[0]); |
| if (!str) return 1; |
| messages=NEWSSERVER->GetNotes(str); |
| } |
| timeout=abs(read_until[str]); |
| s="Inhalt der Rubrik "+str+":\n\n"; |
| if (!pointerp(messages) || !sizeof(messages)) |
| return |
| write(s+"Zur Zeit befinden sich keine Artikel in dieser Rubrik.\n"),1; |
| if (suche) |
| s+="Suche nach '"+suche+"' in der Rubrik ergab folgende Treffer:\n\n"; |
| else |
| if (sizeof(messages)==1) |
| s+="Zur Zeit befindet sich ein Artikel in der Rubrik:\n\n"; |
| else |
| s+="Zur Zeit befinden sich "+sizeof(messages)+ |
| " Artikel in der Rubrik:\n\n"; |
| if (endflag&&(sizeof(messages)>16)&& |
| messages[sizeof(messages)-16][M_TIME]>=timeout) timeout=-1; |
| for (i=(endflag?(((endflag=sizeof(messages)-15)<0)?0:endflag):0); |
| i<sizeof(messages);i++) |
| { |
| txt=sprintf("%2d.%s%-48s%4d (%-11s) %s\n",i+1, |
| (((timeout>=0) && timeout<messages[i][M_TIME] )? |
| ( (timeout=-1),"*"):" "),messages[i][M_TITLE], |
| sizeof(explode(messages[i][M_MESSAGE],"\n")), |
| messages[i][M_WRITER], |
| dtime(messages[i][M_TIME])[5..11]); |
| if (!suche || (strstr(lower_case(txt), suche) != -1)) |
| s+=txt; |
| } |
| if (endflag) write(s); |
| else this_player()->More(s); |
| return 1; |
| } |
| |
| |
| static artikel(str) { |
| return lies(str); |
| } |
| |
| |
| static loesche(str) { |
| int num; |
| mixed *messages; |
| |
| if (str=="?"||str=="-?") return |
| write("Syntax: loesche artikel <nr>\n" |
| " (bezieht sich immer auf die aktuelle Rubrik.\n"),1; |
| |
| if (!str || sscanf(str,"artikel %d",num)!=1 || num<=0) |
| return notify_fail("WELCHEN Artikel willst Du loeschen ?\n"),0; |
| num--; |
| messages=(NEWSSERVER->GetNotes(GROUP)); |
| if (sizeof(messages)<=num) return |
| notify_fail("So viele Artikel sind da nicht!\n"),0; |
| |
| write("Rubrik "+GROUP+", Artikel "+(num+1)+ |
| " von "+capitalize(messages[num][M_WRITER])+ |
| " vom "+dtime(messages[num][M_TIME])[5..26]+ |
| ",\nTitel: "+messages[num][M_TITLE]+",\n\n"); |
| |
| /* (ueberfluessige Abfrage, macht schon /secure/news) |
| if (!IS_LEARNER(TI) && lower_case(messages[num][M_WRITER])!=geteuid(TI)) |
| return |
| write("Nicht geloescht - du darfst nur eigene Artikel loeschen.\n"),1; |
| */ |
| |
| switch (NEWSSERVER->RemoveNote(GROUP, num)){ |
| case 1: write("Artikel ist geloescht.\n"); |
| say(this_player()->name()+" loescht einen Artikel aus der Zeitung.\n"); |
| return 1; |
| case -1: write("Diesen Artikel darfst Du nicht loeschen.\n"); |
| say(this_player()->name()+" versucht vergeblich, einen Artikel zu loeschen.\n"); |
| return 1; |
| case -3: write("So viele Artikel sind da nicht !\n"); |
| return 1; |
| default: write("Interner Fehler. Bitte Erzmagier verstaendigen !\n"); |
| return 1; |
| } |
| } |
| |
| // Low-level Funktion zum Abonnieren/Abbestellen von Rubriken |
| // bestellen==0 -> abbestellen, bestellen!=0 -> bestellen |
| // Rueckgabe: 0, wenn der gewuenschte Zustand schon eingestellt war, sonst 1 |
| private int _subscribe(string groupname, int bestellen) { |
| |
| int timeout = read_until[groupname]; |
| // gar nicht abonniert/abbestellt? |
| if (!bestellen && timeout < 0) |
| return 0; |
| else if (bestellen && timeout > 0) |
| return 0; |
| |
| // wenn noch kein timeout, erstmal auf 1 setzen |
| timeout ||= 1; |
| |
| // -1 fuer abbestellen, +1 fuer bestellen |
| if (bestellen) |
| read_until[groupname] = abs(timeout); |
| else |
| read_until[groupname] = -timeout; |
| |
| if (environment()) |
| environment()->SetProp(P_READ_NEWS, read_until); |
| |
| return 1; |
| } |
| |
| static Unsubscribe(str) { |
| int timeout; |
| if (str=="?"||str=="-?") return |
| write("Syntax: unsubscribe <rubrik>" |
| " oder: bestelle <rubrik> ab\n"),1; |
| str=GetGroupName(str); |
| if (!str) return 1; |
| if (!_subscribe(str,0)) { |
| notify_fail("Die Rubrik hast Du gar nicht abonniert!\n"); |
| return 0; |
| } |
| else { |
| write("Rubrik "+str+" abbestellt.\n"); |
| } |
| return 1; |
| } |
| |
| |
| static Bestelle(str) { /* ab ! */ |
| if (!str || !sscanf(str,"%s ab",str)) return _notify_fail( |
| "Die Syntax ist: 'bestelle <rubrik> ab', " |
| "oder meinst Du 'abonniere'?\n"),0; |
| return Unsubscribe(str); |
| } |
| |
| static Subscribe(str) { |
| int timeout; |
| if (str=="?"||str=="-?") return |
| write("Syntax: abonniere <rubrik>\n" |
| " oder: subscribe <rubrik>\n"),1; |
| str=GetGroupName(str); |
| if (!str) return 1; |
| if (!_subscribe(str,1)) { |
| notify_fail("Die Rubrik hast Du doch schon abonniert!\n"); |
| return 0; |
| } |
| else { |
| write("Rubrik "+str+" abonniert.\n"); |
| } |
| return 1; |
| } |
| |
| // Legt die anfaenglichen Abonnements eines Neulesers fest und bestellt alle |
| // anderen ab. |
| private void InitialSubscriptions() { |
| // alle abbestellen. ;-) |
| // Alternative: fuer alle _subscribe(,0) rufen |
| if (!query_once_interactive(environment())) |
| return; |
| string *gruppen = NEWSSERVER->GetGroups(); |
| int *vals = allocate(sizeof(gruppen),-1); |
| read_until = mkmapping(gruppen,vals); |
| |
| // jetzt die vorausgewaehlten bestellen |
| foreach(string gruppe : INITIAL_SUBSCRIPTIONS) { |
| if (member(gruppen, gruppe) > -1) |
| _subscribe(gruppe,1); |
| } |
| // und ggf. noch die eigene Gildenrubrik |
| string gilde = environment()->QueryProp(P_GUILD); |
| if (stringp(gilde) |
| && member(gruppen, "gilden."+gilde) > -1) |
| _subscribe("gilden."+gilde,1); |
| |
| environment()->SetProp(P_READ_NEWS, read_until); |
| } |
| |
| static MoveMessage(str) { |
| int num,i; |
| mixed msg/*,expl*/; |
| string gr; |
| if (str=="?"||str=="-?") return |
| write("Syntax: verlege artikel <nr> nach <rubrik>\n" |
| " Artikel und Rubrik muessen explizit angegeben werden.\n"),1; |
| if (!str || sscanf(str,"artikel %d nach %s",num,gr)!=2) return (int)notify_fail( |
| "verlege artikel <nr> nach <rubrik>, oder was?\n"); |
| if (!(gr=GetGroupName(gr))) return 1; |
| if (!(CatchNewsError(NEWSSERVER->AskAllowedWrite(gr),"Die Rubrik ist leider voll.\n"))) return 1; |
| |
| if (!pointerp(msg=NEWSSERVER->GetNotes(GROUP))) |
| return notify_fail("Seltsam, die Rubrik '"+GROUP+ |
| "' gibt es nicht mehr...\n"), 0; |
| |
| num--; |
| if (sizeof(msg)<=num) return |
| notify_fail("So viele Nachrichten sind da nicht !\n"),0; |
| msg=msg[num]; |
| if (geteuid(TI) != lower_case(msg[M_WRITER])) { |
| if (!IS_LEARNER(TI)) return |
| write("Du darfst nur Deine eigenen Artikel verlegen.\n"),1; |
| write("WARNUNG: Das ist nicht Dein eigener Artikel!\n"); |
| } |
| // return (int)notify_fail("Man darf zur Zeit nur eigene Artikel verlegen.\n"); |
| if (!CatchNewsError(NEWSSERVER->RemoveNote(GROUP,num),"Dieser Fehler kann eigentlich nicht auftreten")) |
| write("Warnung! Konnte Artikel an alter Position nicht loeschen.\n"); |
| else write("Artikel von Rubrik "+GROUP+" entfernt.\n"); |
| |
| msg[M_MESSAGE]= |
| sprintf("%s on=%s ot=%d og=%s\n", |
| STATUSESCAPE,msg[M_WRITER],msg[M_TIME],msg[M_BOARD]) |
| +msg[M_MESSAGE]; |
| |
| /* |
| expl=explode(msg[M_MESSAGE],"\n"); |
| for (i=0;(IS_STATUSLINE(expl[i][0..2]));i++); |
| msg[M_MESSAGE]=( (i) ? implode(expl[0..i-1],"\n")+"\n" : "" ) + |
| "[Verlegt von "+msg[M_BOARD]+", "+msg[M_WRITER]+", "+ |
| dtime(msg[M_TIME])[5..26]+"]:\n"+ |
| implode(expl[i..],"\n")+"\n"; |
| */ |
| |
| msg[M_BOARD]=gr; |
| NEWSSERVER->WriteNote(msg); |
| write("Artikel nach Rubrik "+gr+" verlegt.\n"); |
| return 1; |
| } |
| |
| static MoveTrash() |
| { |
| if (!pointerp(lasttitle)||sizeof(lasttitle)<LAST_SIZEOF) return |
| write("Was denn bitte? Du hast noch gar nichts gelesen!\n"),1; |
| if (lasttitle[LAST_GROUP]!=GROUP) return |
| write("Nix gibts! Du hast die Rubrik gewechselt!\n"),1; |
| return MoveMessage(sprintf("artikel %d nach muell",lasttitle[LAST_NR]+1)); |
| } |
| |
| static SaveMessage(str) { |
| mixed num; |
| mixed *messages; |
| |
| if (intp(str)) num=str; |
| if ((!num && (!str || str=="" || sscanf(str,"artikel %d",num)!=1)) || num<=0) { |
| notify_fail("Welchen Artikel willst Du abspeichern?\n"); |
| return 0; |
| } |
| if (!pointerp(messages=NEWSSERVER->GetNotes(GROUP))) |
| return notify_fail("Seltsam, die Rubrik '"+GROUP+ |
| "' gibt es nicht mehr...\n"), 0; |
| num--; |
| if (sizeof(messages)<=num) { |
| notify_fail("So viele Nachrichten sind da nicht !\n"); |
| return 0; |
| } |
| if(write_file(SAVEMSGPATH(TP),Message2string(num,messages,M2S_REMOTE)+"\n")) |
| write(break_string( |
| "Inhalt des Artikels wurde nach "+SAVEMSGPATH(TP)+" gespeichert.\n")); |
| else |
| write(break_string( |
| "Fehler beim Schreiben nach "+SAVEMSGPATH(TP)+"!\n")); |
| return 1; |
| } |
| |
| |
| static MailMessage(str) { |
| mixed num,rec,group; |
| mixed *messages; |
| |
| // printf("%O\n",inherit_list(environment(TP))); |
| // if (member(query_actions(this_player()),"mail")<0) |
| // tut nicht wegen anderer Implemtierung von AddCmd in Raeumen |
| |
| if (str=="?"||str=="-?") return |
| write("Syntax: versende artikel <nr> an <adresse>\n"),1; |
| |
| str=TP->_unparsed_args(); // wegen Mailadressen |
| if (str) str=lower_case(str); |
| |
| if (!IS_SEER(TP) && !IS_POST(environment(TP))) |
| return notify_fail("Du musst in ein Postamt gehen, " |
| "um etwas versenden zu koennen.\n"),0; |
| |
| num=0; |
| |
| if (!str || (sscanf(str,"artikel %d an %s",num,rec)!=2 && |
| sscanf(str,"note %d to %s",num,rec)!=2 && |
| sscanf(str,"note to %s",rec)!=1 && |
| sscanf(str,"artikel an %s",rec)!=1)){ |
| if (!str || str[0..6]=="artikel"||str[0..3]=="note") return |
| write("Welchen Artikel willst Du versenden, und wohin?\n"),1; |
| else return |
| notify_fail("Welchen Artikel willst Du versenden, und wohin?\n"),0; |
| } |
| if (!num&&(!pointerp(lasttitle)||sizeof(lasttitle)<LAST_SIZEOF)) |
| return write("Du hast scheinbar noch nichts gelesen, worauf man sich " |
| "beziehen kann.\nGib notfalls die Nummer des Artikels an.\n"),1; |
| |
| // printf("lasttitle= %O\nnum=%d\n",lasttitle,num); |
| |
| if (!pointerp(messages= |
| NEWSSERVER->GetNotes(group=(num?GROUP:lasttitle[LAST_GROUP])))) |
| return notify_fail("Seltsam, die Rubrik gibt es nicht mehr...\n"), 0; |
| |
| if (!pointerp(messages)||!sizeof(messages)) |
| return write("Die Rubrik "+group+" ist leer.\n"),1; |
| if (num<0||sizeof(messages)<num) return |
| write("Einen Artikel mit Nummer "+num+" gibt es in Rubrik "+group+ |
| " nicht!\n"),1; |
| |
| if (num) num--; |
| else { |
| int h; |
| num=-1; |
| if (pointerp(messages)) { |
| for (h=sizeof(messages)-1; |
| (h>=0 && messages[h][M_TIME]>=lasttitle[LAST_TIME]);h--) |
| if (messages[h][M_TIME]==lasttitle[LAST_TIME] && |
| lower_case(messages[h][M_WRITER])== |
| lower_case(lasttitle[LAST_WRITER])) |
| num=h; |
| } |
| if (num<0) |
| return notify_fail("Konnte Artikel nicht wiederfinden, " |
| "bitte gib die Nummer an.\n"),0; |
| } |
| MAILER->do_mail( rec, |
| "MPA: "+messages[num][M_TITLE]+" ("+messages[num][M_WRITER]+")", |
| Message2string(num,messages,M2S_REMOTE,group)+"\n"); |
| return 1; |
| } |
| |
| |
| |
| HelpPage(str) { |
| if (str!="mpa"&&str!="zeitung") return 0; |
| this_player()->More(read_file(HELPPAGE)+ |
| (IS_LEARNER(TP) ? read_file(WIZHELPPAGE) : "")); |
| return 1; |
| } |
| |
| /*--------------------------------------------------------------------------*/ |
| |
| protected void NotifyMove(object dest, object oldenv, int method) { |
| ::NotifyMove(dest, oldenv, method); |
| |
| // P_READ_NEWS aus dem Spieler holen. |
| if (objectp(environment()) && query_once_interactive(environment())) { |
| read_until=environment()->QueryProp(P_READ_NEWS); |
| } |
| |
| if (!mappingp(read_until) || !sizeof(read_until)) |
| InitialSubscriptions(); |
| } |
| |
| int GetTID(mixed message) { |
| string dummy; |
| int tid; |
| return (sscanf(message[M_MESSAGE],"%s" STATUSESCAPE " tid=%d",dummy,tid)==2) |
| ? tid : message[M_TIME]; |
| } |
| |