Benutzer:Deus Figendi/ChatFormater

Aus Jedipedia

Übertragen von Benutzer:Deus_Figendi/vector.js, weil ich da drauf entwickeln will.

Was ist das?[Bearbeiten]

Was dieses Benutzer-Script tut ist etwas Ähnliches wie bereits Anakins Erweiterung, die global wirkt. Es geht also darum Chat-Logs ansehnlich zu formatieren.

Wie installiere ich das?[Bearbeiten]

Wenn mich nicht alles täuscht einfach in den Skin-Einstellungen bei dem Skin den du benutzt das "Benutzerdefiniertes JavaScript" editieren, den Inhalt der Code-Box unten dort anhängen, speichern und es sollte funktionieren.

Das Script[Bearbeiten]

/*
A WORD ON LICENCIES:
This script was written in less a day so... I'm not
sure if it reaches a hight enough threshold of originality.
'Cause there might be no such law in your country you'll
need a licence anyway.
And: This plattform wants me to use the GDLF but... that
is a document-licence not for software and this is software!

However, so I decided just to multi-licence this work XD

For every licence:
Name: Chat Formater
Version: 1.2
Description: JavaScript that converts some chat-logs into HTML-definition-lists
Author: ©2011 Deus Figendi aka Kai-Uwe Kramer
Contact: http://www.jedipedia.net/wiki/Benutzer_Diskussion:Deus_Figendi

* -------------------------THE BEER-WARE LICENSE------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* http://www.jedipedia.net/wiki/Benutzer_Diskussion:Deus_Figendi schrieb
* diese Datei. Solange Sie diesen Vermerk nicht entfernen, können Sie mit
* der Datei machen, was Sie möchten. Wenn wir uns eines Tages treffen
* und Sie denken, die Datei ist es wert, können Sie mir dafür ein Bier
* ausgeben. Deus Figendi
*
* Für weitere Informationen über diese Lizenz siehe:
* http://people.freebsd.org/~phk/
* ----------------------------------------------------------------------------

------------------------------------GPL---------------------------------------
    (C) 2011  Deus Figendi alias Kai-Uwe Kramer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.


--------------------------------GFDL------------------------------------------
    Copyright (C)  2011 Deus Figendi aka Kai-Uwe Kramer
    Permission is granted to copy, distribute and/or modify this document
    under the terms of the GNU Free Documentation License, Version 1.3
    or any later version published by the Free Software Foundation;
    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
    A copy of the license can be found here: http://www.gnu.org/copyleft/fdl.html


*/

function movePreloadSelect (repitations) {
//moves the preload-<select>-Element to the right if it has the style.marginLeft-Thingy in px (otherwise I'd need CSS3)
if(df_debugmode > 10){    alert ("movePreloadSelect");}
    
    
    if (document.getElementById("stdPreloads")) {
        if (document.getElementById("stdPreloads").parentNode) {
            var ml_text = document.getElementById("stdPreloads").parentNode.style.marginLeft;
            var ml_re = /^(\d+)(.+)$/;
            var ml_re_result = ml_re.exec(ml_text);
            if (ml_re_result) {
                if (ml_re_result[2].trim() == "px") {
                    var num_pixel = parseInt(ml_re_result[1]);
                    num_pixel = parseInt(num_pixel + (23 * (repitations)));
                    document.getElementById("stdPreloads").parentNode.style.marginLeft = String(num_pixel)+"px";
                }
            }
        }
    }
}

function c2c_lineident (input_line) {
/*Tries to identify from what kind of client the logfile was created. Returns an integer: 
 0  = did not identify
 10 = xChat with timestamps (my client)
 11 = xChat without timestamps
 20 = PidGin
 30 = Trillian
 40 = mibbit
 50 = ChatZilla
*/
    

    if (/^(\w{1,3}\s\d{1,2}\s)?\[?\d\d\:\d\d(\:\d\d)?\]?\s{1,2}((\<?[\w\^\-]+\>?)|\*)\s{1,2}.*$/.exec(input_line)) {
        return 10; //xChat mit Timestamps
    } else if (/^\s?((\<?[\w\^\-]+\>?)|\*)\s{1,2}.*$/.exec(input_line)) {
        return 11; //xChat ohne Timestamps
    } else if (/^\(\d\d\:\d\d\:\d\d\)\s\*{0,3}[\w\^\-]+\:?\s.*$/.exec(input_line)) {
        return 20; //PidGin
    } else if (/^\[\d\d\:\d\d\]\s(((\*\s)?\<(\@|\+)?[\w\^\-]+\>?\s.*)|(\*\*\*\s[\w\^\-]+\!.*))$/.exec(input_line)) {
        return 30; //Trillian
    } else if (/^\d\d\:\d\d\s\s?(\*\*\*\s)?[\w\^\-]+\s.*$/.exec(input_line)) {
        return 40; //mibbit
    } else if (/^\[\d{4}\-\d\d\-\d\d\s\d\d\:\d\d:\d\d\]\s(\<|\*\s|\=\-\=\s|\-\-\>\|\s|\|\<\-\-\s)[\w\^\-]*\>?\s.*$/.exec(input_line)) {
        return 50; //ChatZilla
    } else {
        return 0; //nicht erkannt.
    }
}

function find_2_highest(input_array) {
//finds out what indexes in an array are the highest. Returns an array with two elements telling what indexes are the highest.
if(df_debugmode>9){    alert ("find_2_highest");}
    var first = 0;
    var second = 0;
    for (var i = 0; i < input_array.length; i++) {
        if (!isNaN(input_array[i])) {
            if (input_array[i] > input_array[first]) {            
                second = first;
                first = i;
            }
            if (input_array[i] > input_array[second] && i != first) {   
                second = i;
            }
        }
    }
    return (new Array(first,second));
}

function chatlog2chatlog (input_text) {
//Main-function of the Chatlog-Script:
// * Tries to identify the Log-Source
// * Define how to parse the lines
// * Parse the lines and create a <dl>

if(df_debugmode>8){    alert ("chatlog2chatlog");}

// Step one: analyse whats the source:
    var c2c_linearray = input_text.split("\n");
    var c2c_sigdiff = false;
    var c2c_liarray = new Array();
    for (var i = 0; i < 60; i++) { c2c_liarray[i] = 0; }
    var c2c_testline_no = 0;
    var c2c_testline_tx = "";
    var max_runner = 50;
    var return_text = "\n";
    var f2h_return = false;
// Send up to 50 random lines to the c2c_lineident-function and count whats the most frequent found format
    while (!c2c_sigdiff) {
     max_runner--;
     c2c_testline_no = Math.floor(Math.random() * c2c_linearray.length);
     c2c_testline_tx = c2c_linearray[c2c_testline_no];
     c2c_testline_rt = c2c_lineident(c2c_testline_tx);
     if (!c2c_liarray[c2c_testline_rt]) { c2c_liarray[c2c_testline_rt] = 0; }
     c2c_liarray[c2c_testline_rt] ++;
          
       
     if (max_runner % 5 == 0) {
         f2h_return = find_2_highest(c2c_liarray);
// If there is a "significant difference" its clear what type of log it is, so we can break
         if ( c2c_liarray[f2h_return[1]] / c2c_liarray[f2h_return[0]] < 0.3) {
            c2c_sigdiff = true;             
         }
     }
     
     if (max_runner <= 0) {
         c2c_sigdiff = true;
     }
     
    }
if(df_debugmode>7){    alert ("--did analyse: \n"+f2h_return);}
    
// At this point its more or less known whats the input-format. But there must be some corrections done:
    if (f2h_return[0]==10 && f2h_return[1]==40) { f2h_return[0] = 40; } // Because mibbit-lines often look like xChat-lines. The script will set "mibbit" even if its only the second behind xChat. Dirty but works most of the time.
    
    // return_text += "\n"+f2h_return[0];
    
// Step two: Set up an Object that defines a regular
// expression to parse the line and defines wich
// subexpression contains wich field... Also wirtes
// a comment to the output to let the user see if the
// script guessed right.
    if (f2h_return[0]==10) {
        return_text += "<!--\n erkannt als xChat mit Timestamp\n-->\n";
        //xChat mit Timestamp
        var line_analyser = new Object();
        line_analyser.regexp = /^((\w{1,3})\s(\d{1,2})\s)?\[?(\d\d):(\d\d)(\:(\d\d))?\]?\s{1,2}((<?[\w\^\-]+>?)|((\*)\s*([\w\^\-]*)))\s{1,2}(.*)$/;
        line_analyser.date_year = -1;
        line_analyser.date_month = 2;
        line_analyser.date_day = 3;
        line_analyser.time_h = 4;
        line_analyser.time_m = 5;
        line_analyser.time_s = 7;
        line_analyser.nick = 9;
        line_analyser.actionnick = 12;
        line_analyser.isaction = 11;
        line_analyser.action_re = /^\*$/;
        line_analyser.content = 13;
    } else if (f2h_return[0]==11) {
        return_text += "<!--\n erkannt als xChat ohne Timestamp\n-->\n";
        //xChat ohne Timestamp
        var line_analyser = new Object();
        line_analyser.regexp = /^\s?((\<?([\w\^\-]+)\>?)|(\*)\s{1,2}([\w\^\-]+))\s{1,2}(.*)$/;
        line_analyser.date_year = -1;
        line_analyser.date_month = -1;
        line_analyser.date_day = -1;
        line_analyser.time_h = -1;
        line_analyser.time_m = -1;
        line_analyser.time_s = -1;
        line_analyser.nick = 3;
        line_analyser.actionnick = 5;
        line_analyser.isaction = 4;
        line_analyser.action_re = /^\*$/;
        line_analyser.content = 6;
    } else if (f2h_return[0]==20) {
        return_text += "<!--\n erkannt als PidGin mit Timestamp\n-->\n";
        //xChat ohne Timestamp
        var line_analyser = new Object();
        line_analyser.regexp = /^\((\d\d)\:(\d\d)\:(\d\d)\)\s(\*{0,3}([\w\^\-]+)\:?)\s(.*)$/;
        line_analyser.date_year = -1;
        line_analyser.date_month = -1;
        line_analyser.date_day = -1;
        line_analyser.time_h = 1;
        line_analyser.time_m = 2;
        line_analyser.time_s = 3;
        line_analyser.nick = 5;
        line_analyser.actionnick = 5;
        line_analyser.isaction = 4;
        line_analyser.action_re = /^\**[\w\^\-]+\s*$/;
        line_analyser.content = 6;
    } else if (f2h_return[0]==30) {
        return_text += "<!--\n erkannt als Trillian mit Timestamp\n-->\n";
        //xChat ohne Timestamp
        var line_analyser = new Object();
        line_analyser.regexp = /^\[(\d\d)\:(\d\d)\]\s(\*{0,3})\s?\<?[\@\+]?([\w\^\-]+)\>?(\s|\!)(.*)$/;
        line_analyser.date_year = -1;
        line_analyser.date_month = -1;
        line_analyser.date_day = -1;
        line_analyser.time_h = 1;
        line_analyser.time_m = 2;
        line_analyser.time_s = -1;
        line_analyser.nick = 4;
        line_analyser.actionnick = 4;
        line_analyser.isaction = 3;
        line_analyser.action_re = /^\*+$/;
        line_analyser.content = 6;
    } else if (f2h_return[0]==40) {
        return_text += "<!--\n erkannt als mibbit-log mit Timestamp\n-->\n";
        //xChat ohne Timestamp
        var line_analyser = new Object();
        line_analyser.regexp = /^(\d\d)\:(\d\d)\s(\s*\**\s)?([\w\^\-]+)\s(.*)$/;
        line_analyser.date_year = -1;
        line_analyser.date_month = -1;
        line_analyser.date_day = -1;
        line_analyser.time_h = 1;
        line_analyser.time_m = 2;
        line_analyser.time_s = -1;
        line_analyser.nick = 4;
        line_analyser.actionnick = 4;
        line_analyser.isaction = 3;
        line_analyser.action_re = /^\s*\**\s$/;
        line_analyser.content = 5;
    } else if (f2h_return[0]==50) {
        return_text += "<!--\n erkannt als ChatZilla-Log mit Timestamp\n-->\n";
        //xChat ohne Timestamp
        var line_analyser = new Object();
        line_analyser.regexp = /^\[(\d{4})\-(\d\d)\-(\d\d)\s(\d\d)\:(\d\d):(\d\d)\]\s(\<|\*\s|\=\-\=\s|\-\-\>\|\s|\|\<\-\-\s)([\w\^\-]+)\>?\s(.*)$/;
        line_analyser.date_year = 1;
        line_analyser.date_month = 2;
        line_analyser.date_day = 3;
        line_analyser.time_h = 4;
        line_analyser.time_m = 5;
        line_analyser.time_s = 6;
        line_analyser.nick = 8;
        line_analyser.actionnick = 8;
        line_analyser.isaction = 7;
        line_analyser.action_re = /^(\*\s|\=\-\=\s|\-\-\>\|\s|\|\<\-\-\s)$/;
        line_analyser.content = 9;
    } else if (f2h_return[0]==0) {
        return_text += "<!--\n Protokoll-Typ leider nicht erkannt :( das tut mir leid.\n-->\n";        
    } else {
        return_text += "<!--\n Ein Fehler ist aufgetreten: Der Protokoll-Typ \""+f2h_return[0]+"\" wurde erkannt, aber ich weiß gar nicht wie ich damit umgehen soll.-->\n";        
    }
if(df_debugmode>6){    alert ("--f2h: "+f2h_return[0]);}
    
    
    var c2c_arrayarray = new Array();
    var c2c_arrayline1 = new Array();
    var c2c_arrayline2 = new Array();
    var today = new Date();
// Step 3.1: Open the definition-list:
    return_text += "<dl>";
    if (line_analyser) {
if(df_debugmode>5){        alert ("analyting lines...");}
// Step 3.2: For every line do...
        for (var i = 0; i < c2c_linearray.length; i++) {
            // return_text += "\n"+c2c_linearray[i];
// 3.2.1: Parse it by the RegExp:
            c2c_arrayline1 = line_analyser.regexp.exec(c2c_linearray[i]);
            if (c2c_arrayline1) {
// 3.2.2: Check if the line represents an "action":
                c2c_arrayline2[0] = 0;
                if (c2c_arrayline1[line_analyser.isaction]) {
                    if (c2c_arrayline1[line_analyser.isaction].match(line_analyser.action_re)) {
                        c2c_arrayline2[0] = 1;
                    }
                }
                
                
// 3.2.3: Set up some defaulst:
                c2c_arrayline2[1] = today.getFullYear(); //Year
                c2c_arrayline2[2] = today.getMonth();    //Month
                c2c_arrayline2[3] = today.getDate();     //Day
                c2c_arrayline2[4] = ".";                 //Hour
                c2c_arrayline2[5] = ".";                 //Minute
                c2c_arrayline2[6] = "00";                //Second
                c2c_arrayline2[7] = ".";                 //Nickname
                c2c_arrayline2[8] = ".";                 //Content-Line (whats said/happened)
            
// 3.2.4: Overwrite the defaults if real content exists in the line.
//        Nick (7) is set as action-nick if actionnick exists and its an action ^^
//        and is set to the usual nickname if that is false but the usual nick is
//        given. IF BOTH IS FALSE IT KEEPS DEFAULT (".")!!!
                if (c2c_arrayline1[line_analyser.date_year])  { c2c_arrayline2[1] = c2c_arrayline1[line_analyser.date_year]; }
                if (c2c_arrayline1[line_analyser.date_month]) { c2c_arrayline2[2] = c2c_arrayline1[line_analyser.date_month]; }
                if (c2c_arrayline1[line_analyser.date_day])   { c2c_arrayline2[3] = c2c_arrayline1[line_analyser.date_day]; }
                if (c2c_arrayline1[line_analyser.time_h])     { c2c_arrayline2[4] = c2c_arrayline1[line_analyser.time_h]; }
                if (c2c_arrayline1[line_analyser.time_m])     { c2c_arrayline2[5] = c2c_arrayline1[line_analyser.time_m]; }
                if (c2c_arrayline1[line_analyser.time_s])     { c2c_arrayline2[6] = c2c_arrayline1[line_analyser.time_s]; }
                if (c2c_arrayline1[line_analyser.actionnick] && c2c_arrayline2[0]) { c2c_arrayline2[7] = c2c_arrayline1[line_analyser.actionnick]; } else if (c2c_arrayline1[line_analyser.nick])       { c2c_arrayline2[7] = c2c_arrayline1[line_analyser.nick]; }
                if (c2c_arrayline1[line_analyser.content])    { c2c_arrayline2[8] = c2c_arrayline1[line_analyser.content]; }
                
                
                //c2c_arrayarray.push(c2c_arrayline2);

// Step 4: Output, creates the dt- and dd-elements.
                return_text += " <dt style=\"margin-bottom:0;";
// 4.1: If its an action make it grey
                if (c2c_arrayline2[0]) {
                    return_text += " color:#a5a5a5;";
                }
// 4.2: I wanted to use the HTML5-<time>-Element but MediaWiki does not allow that. So I used abbr instead of this and the title is meant as datetime-attribute.
                return_text += "\"><abbr style=\"font-size:xx-small;\" class=\"time\" title=\""+c2c_arrayline2[1];
                //return_text += "\n <dt><time datetime=\""+c2c_arrayline2[1];
                return_text += "-"+c2c_arrayline2[2]+"-"+c2c_arrayline2[3];
// 4.3: Time-component is optional, so when no time is given theres no need to write one.
                if (c2c_arrayline2[4] != ".") {
                    return_text += "T"+c2c_arrayline2[4]+":"+c2c_arrayline2[5];
                    return_text += ":"+c2c_arrayline2[6];
                }
                
                return_text += "\">";
// Okay, for now there is a time written if its given or not. In that case its .:.
                return_text += c2c_arrayline2[4]+":"+c2c_arrayline2[5];
// 4.4: Nick becomes blue :D
                return_text +="</abbr> <span class=\"nick\" style=\"color:#36b;\">"+c2c_arrayline2[7]+"</span></dt>"
                //return_text +="</time> <span class=\"nick\">"+c2c_arrayline2[7]+"</span></dt>"
                return_text += " <dd style=\"margin-bottom:0;";
// 4.5: The action-stuff again, see 4.1
                if (c2c_arrayline2[0]) {
                    return_text += " color:#a5a5a5;";
                }
// 4.6: Close the element, next line.
                return_text += "\">"+c2c_arrayline2[8]+"</dd>"
                // return_text += "\n"+c2c_linearray[i]+"\n--"+c2c_arrayline2.join("\n--")+"\n"+c2c_arrayarray.join("\n");
            } else {
                //RegExp did not match the line. That should not happen
                //(but might e.g. if a line is incomplete)
            }
        }
    } else {
        //line_analyser false. For some reason it was not set maybe the
        //analyser did not get the log-type...
    }
if(df_debugmode>4){    alert ("...done");}
    

// 4.7: Close the case... I mean the dl-Element.
    return_text += "</dl>";
    
// Special-Case: If it is from ChatZilla forget everything and
// throw it into a <pre>-Element. Thanks to Anakin that will look awsome!
    if (f2h_return[0]==50) {
        return_text = "<pre class=\"chatlog\">"+input_text+"</pre>";
    }
    
if(df_debugmode>3){    alert ("EOF: chatlog2chatlog");}
    return return_text;
}

function createChatParser() {
//Creates and displays an input-form.

if(df_debugmode>2){    alert ("createChatParser");}
    var cp_pannel = document.createElement("div");
    cp_pannel.style.position = "fixed";
    cp_pannel.style.top = "50px";
    cp_pannel.style.right = "50px";
    cp_pannel.style.zIndex = "100";
    cp_pannel.style.background = "rgba(180,220,255,0.8)";
    cp_pannel.style.padding = "4px";
    var cp_textarea = document.createElement("textarea");
    cp_textarea.style.display = "block";
    cp_textarea.cols = 60;
    cp_textarea.rows = 13;
    cp_textarea.id = "cp_textarea";
    var cp_convert = document.createElement("button");
    cp_convert.appendChild(document.createTextNode("konvertieren"));
    cp_convert.addEventListener("click",function() { document.getElementById("cp_textarea").value = chatlog2chatlog(document.getElementById("cp_textarea").value);},false);
    var cp_close = document.createElement("button");
    cp_close.appendChild(document.createTextNode("schließen"));
    cp_close.addEventListener("click",function() { document.getElementsByTagName("body")[0].removeChild(this.parentNode);},false);
    
    
    cp_pannel.appendChild(cp_textarea);
    cp_pannel.appendChild(cp_convert);
    cp_pannel.appendChild(cp_close);
    document.getElementsByTagName("body")[0].appendChild(cp_pannel);
if(df_debugmode>1){    alert ("EOF: createChatParser");}
}

function AddChatLogFunctionality() {


//This identifies the edit-page
  if (document.getElementById("toolbar") && document.getElementById("stdPreloads") && document.getElementById("mw-editbutton-extlink")) {
if(df_debugmode>0){    alert ("doOnLoad");}
    var tooldiv = document.getElementById("toolbar"); // find the toolbar
    var ChatButton = document.createElement("span");  // create a new button
    ChatButton.id = "df-editbutton-chatlog";          // name it
    ChatButton.className = "mw-toolbar-editbutton";   // class it ;)
    ChatButton.style.margin = "0";                    // style
    ChatButton.style.padding = "0";                   //   |
    ChatButton.style.bottom = "0";                    //   |
    ChatButton.style.height = "22px";                 //   |
    ChatButton.style.border = "none";                 //   |
    ChatButton.style.width = "23px";                  //   |
    ChatButton.style.display = "inline-block";        //   |
    ChatButton.style.overflow = "hidden";             //   |
    ChatButton.style.backgroundImage = "url(/w/skins/common/images/button_template.png)";
    ChatButton.style.verticalAlign = "middle";        //   V
    ChatButton.style.fontSize = "10px";               // it
    ChatButton.appendChild(document.createTextNode("Chat"));  // Write a caption
    ChatButton.title = "ChatProtokoll";
    ChatButton.style.cursor = "pointer";
    ChatButton.addEventListener("click",function(){ createChatParser(); },false); // give it a function
    tooldiv.appendChild(ChatButton);                  // Display it
    movePreloadSelect(1);                             // And move the Select-Thingy away
  } else {
    //there is not enough DOM ^^ wait a half second and try again...
    window.setTimeout("AddChatLogFunctionality()",500);
  }

}

function doOnLoad () {
//all stuff that should happen on finishing page-load


  if (document.getElementById("toolbar")) {
    AddChatLogFunctionality();
  }


}


df_debugmode = 0;
addOnloadHook(doOnLoad);

Wie bediene ich das?[Bearbeiten]

Wenn man sich im Editier-Modus befindet (das wird überprüft anhand dessen ob die Toolbar existiert), dann fügt das Script eine weitere Schaltfläche die mit "Chat" beschriftet ist hinzu. Klickt man darauf öffnet sich ein kleiner Dialog, in den man seinen Chat-Log einfügen möge. Danach auf "konvertieren" geklickt und der Inhalt der Textbox sollte ein wohlformatiertes Chatlog enthalten, dies kann man dort wieder heraus kopieren und normal da einfügen, wo man es benötigt.

Diese Version unterstützt derzeit ChatZilla, mibbit, PidGin, Trillian und xChat. Wobei ersteres einfach Anakins Variante verwendet. Beispiele/Demos werde ich auf der Diskussionsseite einfügen.