home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #7 / amigamamagazinepolishissue1998.iso / rozrywka / rpg / amigamud / src / scenario / email.m next >
Text File  |  1997-05-30  |  14KB  |  569 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1997 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * email.m - allow the player to interact with usenet electronic mail.
  9.  */
  10.  
  11. /* NOTE: this current setup is intended for use with Matt Dillon's UUCP
  12.    and mail distribution, version 1.13D or later. To use it with other
  13.    forms of mail, you will perhaps need to change various things.
  14.    Dependencies: UUMAIL: for mail files, T:, sendmail, uuxqt. Note that
  15.    lately, the UUCP package has been owned by Michael B. Smith. As of
  16.    this writing, the latest release of it is UUCP-V1.17b4. The code here
  17.    makes no attempt to read the Config file for UUCP, so it uses only
  18.    the default locations for things, and assumes the needed commands will
  19.    be in the path for MUDServ. */
  20.  
  21. /* NOTE: this file currently depends on news.m for some player values */
  22.  
  23. /* NOTE: the code here uses the normal place for mail files, i.e. the
  24.    UUMAIL: assign. Thus, you should create a MUD character whose name is
  25.    the same as any names that normally use your system for mail, otherwise
  26.    someone could create them and then would get the outside-of-MUD mail
  27.    intended for that person, and could send out mail seemingly from that
  28.    person. */
  29.  
  30. use t_streets
  31.  
  32. private tp_email CreateTable()$
  33. use tp_email
  34.  
  35. define tp_email p_pRunUUXQT CreateBoolProp()$
  36. NewsThing@p_pRunUUXQT := true$
  37.  
  38. define tp_email p_pEmailAliases CreateThingListProp()$
  39. define tp_email p_alName CreateStringProp()$
  40. define tp_email p_alAddress CreateStringProp()$
  41.  
  42. define tp_email p_pEmailTo CreateStringProp()$
  43. define tp_email p_pEmailSubject CreateStringProp()$
  44. define tp_email p_pEmailString CreateStringProp()$
  45.  
  46. define tp_email g_email CreateGrammar()$
  47.  
  48. define tp_email proc mv_help()bool:
  49.     Print(
  50. "Commands in the telegram office are:\n\n"
  51. "  info - some additional comments on MUD email\n"
  52. "  read - read your mail\n"
  53. "  name/realname <name> - set your real name to <name>\n"
  54. "  mail <person> [subject] - send a new letter to the given person\n"
  55. "  delete - delete all of your mail\n"
  56. "  alias <name> <address> - create an alias for use with 'mail'\n"
  57. "  alias <name> - delete an alias\n"
  58. "  alias - list all aliases\n"
  59.     );
  60.     true
  61. corp;
  62.  
  63. Verb0(g_email, "help", 0, mv_help)$
  64. Synonym(g_email, "help", "?")$
  65.  
  66. define tp_email proc mv_info()bool:
  67.  
  68.     Print(
  69. "Your name in the 'name' command can be quoted or not, it doesn't matter. "
  70. "<person> in the 'mail' command must be quoted if the name contains "
  71. "characters other than letters. Remember that the basic parser in use was "
  72. "designed to parse English-language-like input, so it will interpret, e.g.\n"
  73. "   mail fred@big.company.COM\n"
  74. "as 'mail fred @ big' followed by 'company' followed by 'COM'. This is not "
  75. "what you intended. The optional subject on the 'mail' command can be either "
  76. "quoted or not - it depends on whether you put punctuation characters in. "
  77. "You will soon find that using email via MUD is a chore - if you need to do "
  78. "it a lot, you should try to get a normal email connection.\n"
  79.     );
  80.     true
  81. corp;
  82.  
  83. Verb0(g_email, "info", 0, mv_info)$
  84.  
  85. VerbTail(g_email, "name", nv_name)$
  86. Synonym(g_email, "name", "realname")$
  87.  
  88. define tp_email proc emailSendLetter(string s)void:
  89.     int fd;
  90.     string cmd;
  91.     thing me;
  92.  
  93.     me := Me();
  94.     if s = "" then
  95.     Print("Empty letter - not sent.\n");
  96.     else
  97.     /* note: server runs atomically, so no conflict over the temp file */
  98.     fd := FileOpenForWrite("T:MUD.letter");
  99.     if fd = 0 then
  100.         Print("Sorry - can't open letter file.\n");
  101.     else
  102.         Log("'" + me@p_pName + "' mailing to " + me@p_pEmailTo + "\n");
  103.         FileWrite(fd, "X-MailSoftware: AmigaMUD telegram office\n");
  104.         FileWrite(fd, "\n");
  105.         FileWrite(fd, s);
  106.         FileClose(fd);
  107.         cmd := "sendmail < T:MUD.letter -f \"" + me@p_pName +
  108.         "\" -t " + me@p_pEmailTo;
  109.         if me@p_pEmailSubject ~= "" then
  110.         cmd := cmd + " -s \"" + me@p_pEmailSubject + "\"";
  111.         fi;
  112.         cmd := cmd + " -R \"" + me@p_pNRealName + "\"";
  113.         Execute(cmd);
  114.         Execute("delete T:MUD.letter");
  115.         /* do this so that local mail, as in name@here, will work */
  116.         if NewsThing@p_pRunUUXQT then
  117.         Execute("uuxqt");
  118.         fi;
  119.     fi;
  120.     fi;
  121.     me -- p_pEmailTo;
  122.     me -- p_pEmailSubject;
  123. corp;
  124.  
  125. define tp_email proc mv_mail()bool:
  126.     thing me, alias;
  127.     string target;
  128.     list thing aliases;
  129.     int count;
  130.     string subject;
  131.  
  132.     target := GetWord();
  133.     if target = "" then
  134.     Print("You must specify an address to mail to.\n");
  135.     false
  136.     else
  137.     me := Me();
  138.     if me@p_pNRealName = "" then
  139.         Print("You cannot email until you have a realname set up.\n");
  140.         false
  141.     else
  142.         aliases := me@p_pEmailAliases;
  143.         if aliases ~= nil then
  144.         count := Count(aliases);
  145.         while count ~= 0 do
  146.             count := count - 1;
  147.             alias := aliases[count];
  148.             if alias@p_alName == target then
  149.             target := alias@p_alAddress;
  150.             fi;
  151.         od;
  152.         fi;
  153.         if target = "" or Index(target, " ") >= 0 then
  154.         Print("Invalid mail target.\n");
  155.         false
  156.         else
  157.         me@p_pEmailTo := target;
  158.         if not CanEdit() then
  159.             Print("To: " + target + "\n");
  160.         fi;
  161.         subject := GetTail();
  162.         if subject ~= "" then
  163.             if SubString(subject, 0, 1) = "\"" then
  164.             subject :=
  165.                 SubString(subject, 1, Length(subject) - 2);
  166.             fi;
  167.             me@p_pEmailSubject := subject;
  168.             if not CanEdit() then
  169.             Print("Subject: ");
  170.             Print(subject);
  171.             Print("\n");
  172.             fi;
  173.         fi;
  174.         GetDocument("email> ", "Enter email letter", "",
  175.                 emailSendLetter, true)
  176.         fi
  177.     fi
  178.     fi
  179. corp;
  180.  
  181. VerbTail(g_email, "mail", mv_mail)$
  182.  
  183. define tp_email proc emailParse(string input)void: corp;
  184. define tp_email proc emailLetterParse(string line)void: corp;
  185.  
  186. define tp_email proc emailAllDone()void:
  187.     thing me;
  188.     int fd;
  189.  
  190.     me := Me();
  191.     fd := me@p_pNFd;
  192.     if fd ~= 0 then
  193.     FileClose(fd);
  194.     me@p_pNFd := 0;
  195.     fi;
  196.     me -- p_pEmailString;
  197.     me -- p_pEmailTo;
  198.     me -- p_pEmailSubject;
  199.     ignore SetPrompt("telegram office> ");
  200.     ignore SetCharacterInputAction(emailParse);
  201. corp;
  202.  
  203. define tp_email proc emailFindLetter()bool:
  204.     thing me;
  205.     int fd, colon;
  206.     string line, header;
  207.  
  208.     me := Me();
  209.     if me@p_pEmailString ~= "" then
  210.     true
  211.     else
  212.     fd := me@p_pNFd;
  213.     while
  214.         line := FileRead(fd);
  215.         line ~= "" and Index(line, "From ") ~= 0
  216.     do
  217.     od;
  218.     if line ~= "" then
  219.         me@p_pEmailString := line;
  220.         true
  221.     else
  222.         false
  223.     fi
  224.     fi
  225. corp;
  226.  
  227. define tp_email proc emailShowPage()bool:
  228.     thing me;
  229.     int fd, length, n, width, len;
  230.     string line;
  231.     bool moreLetter;
  232.  
  233.     me := Me();
  234.     fd := me@p_pNFd;
  235.     length := TextHeight(0);
  236.     width := TextWidth(0);
  237.     n := 1;
  238.     line := me@p_pEmailString;
  239.     if line ~= "" then
  240.     me -- p_pEmailString;
  241.     Print(line);
  242.     Print("\n");
  243.     n := 2;
  244.     fi;
  245.     moreLetter := true;
  246.     while
  247.     if n >= length then
  248.         false
  249.     else
  250.         line := FileRead(fd);
  251.         if line = "" then
  252.         moreLetter := false;
  253.         false
  254.         elif Index(line, "From ") = 0 then
  255.         me@p_pEmailString := line;
  256.         moreLetter := false;
  257.         false
  258.         else
  259.         true
  260.         fi
  261.     fi
  262.     do
  263.     Print(line);
  264.     Print("\n");
  265.     len := Length(line);
  266.     if len <= width then
  267.         n := n + 1;
  268.     else
  269.         n := n + (len + width - 4) / (width - 9);
  270.     fi;
  271.     if Index(line, "From: ") = 0 then
  272.         line := SubString(line, 6, Length(line) - 6);
  273.         len := Index(line, " (");
  274.         if len > 0 then
  275.         line := SubString(line, 0, len);
  276.         fi;
  277.         me@p_pEmailTo := line;
  278.     elif Index(line, "Subject: ") = 0 then
  279.         line := SubString(line, 9, Length(line) - 9);
  280.         if line ~= "" then
  281.         me@p_pEmailSubject := "Re: " + line;
  282.         fi;
  283.     fi;
  284.     od;
  285.     moreLetter
  286. corp;
  287.  
  288. define tp_email proc emailSetLetter()void:
  289.  
  290.     ignore SetPrompt("Nrq? ");
  291.     ignore SetCharacterInputAction(emailLetterParse);
  292. corp;
  293.  
  294. define tp_email proc emailMoreParse(string line)void:
  295.  
  296.     if line = "" or line == "c" then
  297.     if not emailShowPage() then
  298.         emailSetLetter();
  299.     fi;
  300.     elif line == "n" then
  301.     if emailFindLetter() then
  302.         if not emailShowPage() then
  303.         emailSetLetter();
  304.         fi;
  305.     else
  306.         emailAllDone();
  307.     fi;
  308.     elif line == "q" then
  309.     emailAllDone();
  310.     else
  311.     Print("Options are:\n"
  312.         "  c - continue reading this letter\n"
  313.         "  n - go on to next letter\n"
  314.         "  q - quit reading mail\n"
  315.         "Empty line is equivalent to 'r'\n"
  316.     );
  317.     fi;
  318. corp;
  319.  
  320. define tp_email proc emailSetMore()void:
  321.  
  322.     ignore SetPrompt("[M O R E] Cnq? ");
  323.     ignore SetCharacterInputAction(emailMoreParse);
  324. corp;
  325.  
  326. replace emailLetterParse(string line)void:
  327.     thing me;
  328.  
  329.     me := Me();
  330.     if line == "r" then
  331.     if me@p_pNRealName = "" then
  332.         Print("You cannot email until you have a realname set up.\n");
  333.     else
  334.         if not CanEdit() then
  335.         Print("To: " + me@p_pEmailTo + "\n");
  336.         if me@p_pEmailSubject ~= "" then
  337.             Print("Subject: ");
  338.             Print(me@p_pEmailSubject);
  339.             Print("\n");
  340.         fi;
  341.         fi;
  342.         ignore GetDocument("reply> ", "Enter email reply", "",
  343.                    emailSendLetter, true);
  344.     fi;
  345.     elif line = "" or line == "n" then
  346.     if emailFindLetter() then
  347.         if emailShowPage() then
  348.         emailSetMore();
  349.         fi;
  350.     else
  351.         emailAllDone();
  352.     fi;
  353.     elif line == "q" then
  354.     emailAllDone();
  355.     else
  356.     Print("Options are:\n\n"
  357.         "  r - reply to this letter\n"
  358.         "  n - read next letter\n"
  359.         "  q - quit reading mail\n"
  360.         "Empty line is equivalent to 'n'\n"
  361.     );
  362.     fi;
  363. corp;
  364.  
  365. define tp_email proc emailResetHandler()void:
  366.  
  367.     Me()@p_pNFd := 0;
  368.     emailAllDone();
  369. corp;
  370.  
  371. define tp_email proc mv_read()bool:
  372.     thing me;
  373.     int fd;
  374.     action a;
  375.  
  376.     me := Me();
  377.     fd := FileOpenForRead("UUMAIL:" + me@p_pName);
  378.     if fd = 0 then
  379.     Print("No mail for " + me@p_pName + "\n");
  380.     else
  381.     me@p_pNFd := fd;
  382.     if emailFindLetter() then
  383.         if emailShowPage() then
  384.         emailSetMore();
  385.         else
  386.         emailSetLetter();
  387.         fi;
  388.     else
  389.         Print("Mailbox is invalid - no header found!\n");
  390.     fi;
  391.     fi;
  392.     true
  393. corp;
  394.  
  395. Verb0(g_email, "read", 0, mv_read)$
  396.  
  397. replace emailParse(string input)void:
  398.     string word;
  399.  
  400.     SetTail(input);
  401.     word := GetWord();
  402.     if word ~= "" then
  403.     if FindAnyWord(g_email, word) ~= 0 then
  404.         ignore Parse(g_email, input);
  405.     else
  406.         ignore Parse(G, input);
  407.     fi;
  408.     fi;
  409. corp;
  410.  
  411. define tp_email proc mv_delete()bool:
  412.  
  413.     Execute("delete \"UUMAIL:" + Me()@p_pName + "\"");
  414.     Print("All mail deleted.\n");
  415.     true
  416. corp;
  417.  
  418. Verb0(g_email, "delete", 0, mv_delete)$
  419.  
  420. define tp_email proc mv_alias()bool:
  421.     int count;
  422.     list thing aliases;
  423.     thing alias;
  424.     string name, address;
  425.     bool found;
  426.  
  427.     aliases := Me()@p_pEmailAliases;
  428.     name := GetWord();
  429.     if name = "" then
  430.     if aliases = nil then
  431.         Print("You currently have no email aliases set up.\n");
  432.     else
  433.         Print("Current aliases:\n");
  434.         count := Count(aliases);
  435.         while count ~= 0 do
  436.         count := count - 1;
  437.         alias := aliases[count];
  438.         Print("  ");
  439.         Print(alias@p_alName);
  440.         Print(" => ");
  441.         Print(alias@p_alAddress);
  442.         Print("\n");
  443.         od;
  444.     fi;
  445.     else
  446.     address := GetTail();
  447.     found := false;
  448.     if aliases ~= nil then
  449.         count := Count(aliases);
  450.         while count ~= 0 and not found do
  451.         count := count - 1;
  452.         alias := aliases[count];
  453.         if alias@p_alName == name then
  454.             found := true;
  455.         fi;
  456.         od;
  457.     fi;
  458.     Print("Alias \"");
  459.     Print(name);
  460.     Print("\" ");
  461.     if address = "" then
  462.         if found then
  463.         DelElement(aliases, alias);
  464.         Print("removed.\n");
  465.         else
  466.         Print("does not exist.\n");
  467.         fi;
  468.     else
  469.         if SubString(address, 0, 1) = "\"" then
  470.         address := SubString(address, 1, Length(address) - 2);
  471.         fi;
  472.         if found then
  473.         alias@p_alAddress := address;
  474.         Print("updated.\n");
  475.         else
  476.         if aliases = nil then
  477.             aliases := CreateThingList();
  478.             Me()@p_pEmailAliases := aliases;
  479.         fi;
  480.         alias := CreateThing(nil);
  481.         alias@p_alName := name;
  482.         alias@p_alAddress := address;
  483.         AddTail(aliases, alias);
  484.         Print("added.\n");
  485.         fi;
  486.     fi;
  487.     fi;
  488.     true
  489. corp;
  490.  
  491. VerbTail(g_email, "alias", mv_alias)$
  492.  
  493. define tp_email proc emailEnter()status:
  494.     thing me;
  495.  
  496.     me := Me();
  497.     if Character(me@p_pName) = nil then
  498.     /* cannot do this stuff with machines! */
  499.     OPrint(Capitalize(CharacterNameS(me)) + " will not enter.\n");
  500.     fail
  501.     else
  502.     AddHead(me@p_pEnterActions, emailResetHandler);
  503.     AddHead(me@p_pExitActions, emailAllDone);
  504.     me@p_pNSaveHandler := SetCharacterInputAction(emailParse);
  505.     me@p_pNSavePrompt := SetPrompt("telegram office> ");
  506.     continue
  507.     fi
  508. corp;
  509.  
  510. define tp_email proc emailExit()status:
  511.     thing me;
  512.  
  513.     me := Me();
  514.     DelElement(me@p_pEnterActions, emailResetHandler);
  515.     DelElement(me@p_pExitActions, emailAllDone);
  516.     ignore SetCharacterInputAction(me@p_pNSaveHandler);
  517.     ignore SetPrompt(me@p_pNSavePrompt);
  518.     me -- p_pEmailTo;
  519.     me -- p_pEmailSubject;
  520.     continue
  521. corp;
  522.  
  523. define tp_email r_emailRoom CreateThing(r_indoors)$
  524. SetupRoom(r_emailRoom, "in the telegram office",
  525.     "In this room, there are additional commands which are used to read, "
  526.     "reply to, and send electronic mail letters. Use 'help' to find out "
  527.     "how to use the service provided here.")$
  528. r_emailRoom@p_rNoMachines := true$
  529. Connect(r_ne1, r_emailRoom, D_EAST)$
  530. Connect(r_ne1, r_emailRoom, D_ENTER)$
  531. ExtendDesc(r_ne1,
  532.     "To the east is a modest brick building of simple, but functional "
  533.     "architecture. A single wooden door without any windows opens directly "
  534.     "onto the sidewalk. Hanging by the door is a sign which reads \"Telegram "
  535.     "Office\". Small windows on each side of the door are firmly shut, and "
  536.     "each is covered by a green pull-down roller blind.")$
  537. AddEastChecker(r_ne1, emailEnter, false)$
  538. AddEnterChecker(r_ne1, emailEnter, false)$
  539. AddWestChecker(r_emailRoom, emailExit, false)$
  540. AddExitChecker(r_emailRoom, emailExit, false)$
  541. Sign(r_ne1, "sign;hanging.door;sign,hanging,by,the", "","\"Telegram Office\"")$
  542. Scenery(r_ne1,
  543.     "building;modest,brick."
  544.     "brick."
  545.     "door;wooden,windowless."
  546.     "blind;green,pull-down,pull,down,roller")$
  547.  
  548. define tp_email TELEGRAM_OFFICE_ID NextEffectId()$
  549. define tp_email proc drawEMailRoom()void:
  550.  
  551.     if not KnowsEffect(nil, TELEGRAM_OFFICE_ID) then
  552.     DefineEffect(nil, TELEGRAM_OFFICE_ID);
  553.     GSetImage(nil, "Town/telegramOffice");
  554.     IfFound(nil);
  555.         ShowCurrentImage();
  556.     Else(nil);
  557.         TextBox("Read and post", "usenet mail", "here");
  558.     Fi(nil);
  559.     EndEffect();
  560.     fi;
  561.     CallEffect(nil, TELEGRAM_OFFICE_ID);
  562. corp;
  563.  
  564. RoomGraphics(r_emailRoom, "Telegram", "Office", NextMapGroup(), 0.0, 0.0,
  565.          drawEMailRoom)$
  566.  
  567. unuse tp_email
  568. unuse t_streets
  569.