ScriptFup2Warning include

From 40tude Dialog Wiki


Xpost & Fup2-Warning (Include-File)

This script automatically adds a Crosspost and Followup-To-warning to your outgoing messages. It is able to automatically choose a language version of the warning based on the groups your article is posted to.

This is how it looks like, if you crosspost a article to and alabama.test, Followup-To

X'Post: <>,<news:alabama.test>
F'up2 : <>
This is a signature.

Install & Setup the script

Please note that this script is an include-file!.
You have to copy the following script inside a new custom script (for example "INCLUDE_OBSending_Crosspost_FollowupTo_Warning").
To configure this script, have a look at the instructions in the script. Note that you don't have to configure anything if you're content with the output depicted in the sample above. It works out of the box, but if you want to except certain groups from the warning, or if you want to have the warning language dependant, please follow the instructions in the script.
When you're done configuring, safe it. Please don't compile this custom script. After that you have to add the following lines to your OnBeforeSending-Script:

{$I INCLUDE_OBSending_Crosspost_FollowupTo_Warning.ds}


Crosspost_FollowupTo_Warning ( Message, Servername, IsEmail );

This may look like this:

program OnBeforeSendingMessage;
{$I INCLUDE_OBSending_Crosspost_FollowupTo_Warning.ds}

function OnBeforeSendingMessage(var Message: TStringlist; Servername: string; IsEmail: boolean):boolean;

  Crosspost_FollowupTo_Warning ( Message, Servername, IsEmail );

  //possibly some other calls to scripts



Just compile this OnBeforeSending-Script now to get your include-file to work. Please note that whenever you reconfigure the Crosspost_FollowupTo_Warning custom script, you have to recompile the OnBeforeSending-Script afterwards to apply the changes.

The script


2005-09-27: += Creation (Korbinian Abenthum ) As of today, this script is not thoroughly tested. If you notice anything wrong, please notify people in your 40tude Dialog newsgroup or change it yourself.


//----------- Insert Crosspost and Followup-To Waning into outgoing articles
//            Version 1 (beta) - Date: 2005/09/27
//            Check the source code and make a backup before use :)

// ***** --USER-->  You can specify the maximum number of language versions here.
// ***** --USER-->  If you get an error when sending a message (array out of bounds
// ***** --USER-->  or some such), try to increase this number to at least equal
// ***** --USER-->  the number of languages you defined below.
// ***** --USER-->  Leave it as it is for the moment.

// ***** --USER-->  Set to "true" to make newsgroups clickable:
// ***** --USER-->       Follow-Up to: <>
// ***** --USER-->  Set to "false" otherwise:
// ***** --USER-->       Follow-Up to:

// ***** --USER-->  Now scroll down about one page to finish the setup of the script

const CFW_NEWLINE =#13+#10;
const CFW_ANY_GROUP = ',';
const CFW_MAXINT = 2147483647;

type CFW_TPatterns = Array [1..CFW_MAX_LANGUAGES] of record 
                        newsgroupPatterns : TStringList;
                        insertWarningAtEndOftext: Boolean;
                        textFup : string;
                        textCross : string;
                        textCrossFup : string;
//For ease of use in the Init-method, we will keep these two variables global.
var CFW_Patterns : CFW_TPatterns;
    CFW_PatternCount : integer;

procedure CFW_AddLanguage( newsgroupPatterns : TStringList;
                           insertWarningAtEndOfText : Boolean;
                           textFup : string;
                           textCross : string;
                           textCrossFup : string );
  CFW_PatternCount := CFW_PatternCount + 1;
  CFW_Patterns[CFW_PatternCount].newsgroupPatterns := newsgroupPatterns;
  CFW_Patterns[CFW_PatternCount].insertWarningAtEndOfText := insertWarningAtEndOfText;
  CFW_Patterns[CFW_PatternCount].textFup := textFup;
  CFW_Patterns[CFW_PatternCount].textCross := textCross;
  CFW_Patterns[CFW_PatternCount].textCrossFup := textCrossFup;

procedure CFW_Init();
var newsgroupPatterns : TStringList;
  CFW_PatternCount := 0;

// ***** --USER-->  +-------------------------------------------------------------+
// ***** --USER-->  |      ***** Specify your language versions *HERE* *****      |
// ***** --USER-->  +-------------------------------------------------------------+
 To create a set of language versions, you have to add lines like in the following example.
 The example will add a German warning to German speaking groups, no warning when crossposting to Big8 + alt.*,
 and an English warning everywhere else.

    //Language Version 1: All x'posted groups are german speaking
    newsgroupPatterns := TStringList.Create;
    newsgroupPatterns.Add( ',de.' );  //Group Pattern 1
    newsgroupPatterns.Add( '.de.' );  //Group Pattern 2
    newsgroupPatterns.Add( ',at.' );  //Group Pattern 3
    newsgroupPatterns.Add( '.at.' );  //Group Pattern 4
    newsgroupPatterns.Add( ',ch.' );  //Group Pattern 5
    newsgroupPatterns.Add( '.ch.' );  //Group Pattern 6
    CFW_AddLanguage(newsgroupPatterns, true,
      'Follow-Up nach: $F'+CFW_NEWLINE+'Follow-Up bitte beachten',                                   //Follow-Up text
      'Crossposted nach: $N',                                                                        //Crosspost text
      'Crossposted nach: $N'+CFW_NEWLINE+'Follow-Up nach: $F'+CFW_NEWLINE+'Follow-Up bitte beachten' //Follow-Up & Crosspost text

    //Language Version 2: Articles to Big8 + alt.*, Crosspost and Follow-Up warnings are usually futile there,
    //                    so we make the warning text empty
    newsgroupPatterns := TStringList.Create;
    newsgroupPatterns.Add( ',alt.' );
    newsgroupPatterns.Add( ',comp.' );
    newsgroupPatterns.Add( ',rec.' );
    newsgroupPatterns.Add( ',sci.' );
    newsgroupPatterns.Add( ',soc.' );
    newsgroupPatterns.Add( ',humanities.' );
    newsgroupPatterns.Add( ',talk.' );
    newsgroupPatterns.Add( ',news.' );
    newsgroupPatterns.Add( ',misc.' );
    CFW_AddLanguage(newsgroupPatterns, true, '', '', '' );

    //Language Version 3: Speak english everywhere else
    newsgroupPatterns := TStringList.Create;
    newsgroupPatterns.Add( CFW_ANY_GROUP ); //Group Pattern CFW_ANY_GROUP matches any group
    CFW_AddLanguage(newsgroupPatterns, true,
                    'F''Up2: $F',
                    'X''Posted to: $N',
                    'X''Posted to: $N'+CFW_NEWLINE+'F''Up2: $F'+CFW_NEWLINE+'Respect Follow-Up please'

A couple of notes:
1) First matching language version wins. In the example above, the English version is only used
   if the crosspost is neither exclusively to German speaking groups nor exclusively to Big8 + alt.*
2) *All* crossposted groups have to be matched by a language version, otherwise it is not applied
3) You can add as many group patterns as you want, but each in its own line, and between inverted commas
4) A comma denotes the beginning and the end of a newsgroup name.
   E.g. the pattern ",de." does not match "", but it matches ""
   That's why the German language version adds ".de." as well as ",de."
5) If you want to put the warning at the beginning of an article, change the second parameter of the
   CFW_Addlanguage call from "true" (puts it at the end, just above the signature)
   to "false" (puts it at the beginning of the body)
6) You can and have to specify the warning text for a pure Followup, a Crosspost and
   a Crosspost *with* Followup seperately as the last three parameters of the call to CFW_AddLanguage.
   Put the marker "$F" at the place where you want the Followup-To groups.
   Put the marker "$N" where you want the crosspost newsgroups to appear in your warning.
   Any text has to be enclosed in inverted commas. If you want an inverted comma as part of your warning,
   simply double it: "''".
   If you want a linebreak as part of your warning, add "'+CFW_NEWLINE+'"
7) The script will make sure that there is (at least) one empty line above the warning
   (or below if it is located at the beginning of the article)
8) Sorry that it is so complicated, but that comes with the territory.
   You don't have to change anything if you're happy with a brief, English warning.
   If you can't figure it out, please ask in your favourite 40tude Dialog newsgroup.
   If you can make these configuration instructions any clearer, feel free to do so.

As always when inserting text by script: You must not insert any characters that are not part of ASCII
i.e. no umlauts or any characters with diacriticals
If such a thing is necessary, one has to extend the script by inserting an appropriate text depending
on the charset used in the article


// Put your language version definitions below

    //Just speak english everywhere
    newsgroupPatterns := TStringList.Create;
    newsgroupPatterns.Add( CFW_ANY_GROUP );
    CFW_AddLanguage(newsgroupPatterns, true,
                    'F''Up2: $F',
                    'X''Post: $N',
                    'X''Post: $N'+CFW_NEWLINE+'F''Up2 : $F'

// ***** --USER-->  +-----------------------------------------------------------+
// ***** --USER-->  |     ***** Nothing to configure below this point *****     |
// ***** --USER-->  +-----------------------------------------------------------+

//returns the index of the matching language, or zero (0) if no matching language was found
function GetMatchingLanguage( newsgroups : string) : integer;
var languageGroup, pattern : integer;
    groupPatterns : TStringList;
    noPatternFound : boolean;
    oneGroup, restOfGroups : string;
    commaIndex : integer;
  newsgroups := newsgroups + ','; //add a comma at the end

  for languageGroup:=1 to CFW_PatternCount do begin //for every language
    groupPatterns := CFW_Patterns[languageGroup].newsgroupPatterns;
    restOfGroups := newsgroups;
    commaIndex := 0;
    repeat //for every group crossposted to
      restOfGroups := copy(restOfGroups, commaIndex+1, CFW_MAXINT);
      commaIndex := AnsiPos(',', restOfGroups);
      oneGroup := ',' + copy(restOfGroups, 1, commaIndex);

      noPatternFound := true;
      for pattern:=0 to groupPatterns.Count-1 do begin //for every pattern in the current language
        noPatternFound := AnsiPos(groupPatterns.strings[pattern], oneGroup)<=0;
        if NOT noPatternFound then break; //Fast Pass
      if noPatternFound then break;      
    until commaIndex=length(restOfGroups);
    if NOT noPatternFound then begin
      result := languageGroup;
  //No matching language found => return errorcode (0)
  result := 0;

const CFW_NEWSGROUPS_HEADER = 'Newsgroups: ';
const CFW_FOLLOWUPTO_HEADER  = 'Followup-To: ';

function Crosspost_FollowupTo_Warning(var Message: TStringlist; Servername: string; IsEmail: boolean):boolean;
var newsgroups    : string;
    followupTo    : string;
    warningText   : string;
    line          : integer;
    languageId    : integer;
    firstBodyLine : integer;
    noSignature   : boolean;
  result := true;
  if IsEmail then exit;

  //Retrieve newsgroups: and followup-to: headers
  for line:=0 to Message.count-1 do begin

      //look for the Newsgroups: header
      if AnsiPos(CFW_NEWSGROUPS_HEADER, message.strings[line])=1 then begin
        newsgroups := Copy(message.strings[line], Length(CFW_NEWSGROUPS_HEADER)+1, CFW_MAXINT);

      //look for the Followup-To: header
      if AnsiPos(CFW_FOLLOWUPTO_HEADER, message.strings[line])=1 then begin
        followupTo := Copy(message.strings[line], Length(CFW_FOLLOWUPTO_HEADER)+1, CFW_MAXINT);

      if message.strings[line]='' then break; //End of Header
  end; //for

  if (AnsiPos(',', newsgroups)<=0) AND (followupTo='') then exit; //Fast Fail
  //Find the matching language version
  languageId := GetMatchingLanguage( newsgroups );
  if languageID = 0 then begin
    WriteToLog('Script Crosspost_FollowupTo_Warning: Could not find a languagePack matching the newsgroups "'+newsgroups+'"', 3);

  //make the newsgroups clickable if desired
    if (followupTo<>'') AND (AnsiLowerCase(followupTo)<>'poster') then begin
      followupTo := '<news:'+followupTo+'>';
    newsgroups := '<news:'+StringReplace( newsgroups, ',', '>,<news:', [rfReplaceAll])+'>'; 

  //Construct the warning lines
  if AnsiPos(',', newsgroups)>0 then begin //crosspost
    if followupTo<>'' then
        warningText :=  CFW_Patterns[languageId].textCrossFup
        warningText :=  CFW_Patterns[languageId].textCross;
  else begin //no crosspost, must be a fup, otherwise we exited earlier!
    warningText :=  CFW_Patterns[languageId].textFup;
  warningText := StringReplace( warningText, '$N', newsgroups, [rfReplaceAll]); 
  warningText := StringReplace( warningText, '$F', followupTo, [rfReplaceAll]);
  if (Trim(warningText)='') then exit; //no warning, nothing to do
  //Determine the position to insert the warning
  // First find the first line of the body
  while message.strings[line]<>'' do begin
      line := line + 1;
      if line = message.Count then begin
        WriteToLog('Script Crosspost_FollowupTo_Warning: Broken article! It has no line separating header from body.', 4);
  firstBodyLine := line + 1;
  // Then find the line where we will insert the warning
  // Also make sure that there is at least one empty line between text and warning
  if CFW_Patterns[languageId].insertWarningAtEndOfText then begin //insert at bottom of the body (above signature)
    noSignature := true;
    for line:= Message.count-1 downto firstBodyLine do begin
      if message.strings[line]=CFW_SIGNATURE_DELIMITER then begin
        noSignature := false;
    if (noSignature) then line := message.Count;
    if (Trim(message.strings[line-1])<>'') then begin
      message.insert(line, '');
      line := line + 1;
  else begin //insert at the top of the body
    line := firstBodyLine;
    //make sure there is one empty line between warning and article.
    if Trim(message.strings[firstBodyLine])<>'' then message.Insert(firstBodyLine, '');
  //Insert 'em
  message.Insert(line, warningText);