Category:Gremlin

From Second Life Wiki
(Redirected from Gremlin)
Jump to navigation Jump to search
KBwarning.png Warning: This is obsolete and the service has been removed.

Created by the Wizardry and Steamworks group.

Web-Related Tree

+-------------+ +-------------+ +---------+ +-----------------------------+ +--------------------------+ | Prowler | | Gremlin | | N2K | | Permanent Primitive URL | | Collaborative Coding | +------+------+ +-------------+ +---------+ +------------+----------------+ +--------------------------+ | | +--------+--------+ +-------------------+-------------------+ | SIM Status | | Population Genetics and Selection | +-----------------+ +-------------------+-------------------+ | +------------+-------------+ | Interactive Bacteria | +--------------------------+

ChangeLog

  • 8-December-2011

Overall, the switch is from using MediaWiki::Bot to MediaWiki::API and querying the wiki directly directly since category listing is sometimes not available (for example, the SecondLife wiki refused to work with me and now it should work properly as well as being the default setting for the [WaS-Gremlin]). I have tested Brilliant Scientist's script and it transfers just fine. Further changes:

  1. Perl Gremlin - Enhanced the regexex, switched to Base64 for search strings, should work faster and is final for the moment.
  2. LSL Gremlin - Fixed the annoying chat lag that delayed lines and stabilized the search. Re-nuked properly now.
  • 8-December-2011

Added nuked version. Added revised LSL script. Revised regex, revised tags, revised search method. Added more tags, lsl, pre, pl, javascript. pre could be useful for notecards and such. Same gremlin overload syntax.

In a Nutshell

Gremlin is a script-search engine, implemented in LSL and perl that scrapes MediaWiki pages (such as the Second Life Wiki) for scripts that have been set visible to Gremlin.

Motivation

Gremlin is one of the greatest collaborative efforts so far [WaS] would like to push forward to developers so that non closed-source scripts may be made available to residents of any multiverses derived from the Linden simulator platform. We would like to do that by offering developers the choice of making their code available to the public right from their wiki of choice.

How to Feed the Gremlin

Any code, posted on any page of the LSL wiki, that you wish Gremlin to be able to access should follow the Wiki LSL-tag overload:

<lsl gremlin="Hello World Script">
default
{
    state_entry()
    {
        llSay(0, "Hello, Avatar!");
    }

    touch_start(integer total_number)
    {
        llSay(0, "Touched.");
    }
}
</lsl>

which binds the string Kira's Awesome Script as the Gremlin identifier for that script.

When the page is saved, for the example above, it will look like this: <lsl gremlin="Hello World Script"> default {

   state_entry()
   {
       llSay(0, "Hello, Avatar!");
   }
   touch_start(integer total_number)
   {
       llSay(0, "Touched.");
   }

} </lsl> which renders properly on the wiki because GeSHi, the wiki extension that does the LSL formatting, adding colors and links to API, does not mind the "gremlin" tag and even hides it, making the sharing transparent.

Optionally, that page should be made part of the Gremlin category by adding at the end of the wiki page:

[[Category:Gremlin]]

since Gremlin searches its own category on every wiki first.

The Gremlin hosted on [WaS]'s Frequency Modulation wiki indexes the following categories:

Category:Gremlin
Category:LSL_Library
Category:Wizardry_and_Steamworks

in that order and returns the first script matching the search. It is up to developers to find good Gremlin strings to set their script apart from other scripts.

The Gremlin perl server-side script also implements lazy regexes around the search string, so the following search string:

Hello World

will also find the Hello World script.

It is up to the individual developer to decide whether they want to share their script using the Gremlin system. It is also up to the individual developer to comment the code and make sure that the script has the necessary header in order to explain the script properly when the resident downloads it. If they do, they would simply have to follow the steps above. The Wizardry and Steamworks group members will convert every script they currently own to be shared with Gremlin to provide a minimal service till others may join.

Gremlin is not limited just to lsl tags, it can also scavenge the following:

<pre gremlin="Some cool pre-preformated snippet">

How it Works

Gremlin uses the MediaWiki API provided by any wiki installation to list all the pages in a category and then proceeds to scrape the

<lsl>

tags from the pages looking for the tag-overload "gremlin". When it sees that tag, it performs the regex on the tag-overload based on the resident's search string. If it matches, the script is then fed directly to the LSL script of the resident's search string in 2044byte chunks. The LSL script then dumps all the data with llOwnerSay to the resident.

Here is an overview of what happens when an user searches for the string cannon:

       .
 ------.------------------------------------------------------------------------------------------------------
       .
       .                                      search: defined +------------+  ##############################
       .                                     +--------------->| First Wiki |  #Gremlin sends the search    #
       .                                    /   categories    +------------+  #query to the server-side    #
  +---------+                +--------+    /      using                       #Gremlin Perl script, which  #
  | Gremlin | search: cannon |Gremlin |   /    MediaWiki API  +------------+  #searches all known wikis    #
  | Client  |--------------->|Server  |--+------------------->| Second Wiki|  #and all definited categories#
  | Script  |  HTTP Request  |Script  |   \      HTTP GET     +------------+  #by scraping for lsl tags    #
  +---LSL---+                +--Perl--+    \     Requests                     #that contain the gremlin    #
       .                                    \                 +------------+  #overload.                   #
       .                                     +--------------->| Third Wiki |  #                            #
       .                                                      +------------+  #In this case:               #
       .                                                        ...etc...     #  <lsl gremlin="cannon">    #
       .                                                                      ##############################
       .
 -------------------------------------------------------------------------------------------------------------
       .                                      #############################################
   +---------+    2k-byte    +--------+       #If the search string is found in any       #
   | Gremlin |  feeds using  |Gremlin |       #<lsl gremlin="strings"> then Gremlinstring #
   | Client  |<--------------|Server  |       #sends it back to the in-world LSL scripts  #
   | Script  |  HTTP Request |Script  |       #in 2kb bursts to work around the 2048byte  #
   +---LSL---+               +--Perl--+       #limitation imposed on http_request.        #
       .                                      #############################################
 ------.------------------------------------------------------------------------------------------------------
       .

Code: Gremlin LSL

Place this code in a primitive and touch it to get a llTextBox and enter a search string.

<lsl gremlin="Gremlin LSL"> ////////////////////////////////////////////////////////// // [K] Kira Komarov - 2011, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // ////////////////////////////////////////////////////////// /// Gremlin - LSL, see Gremlin - Perl ////////////////////////////////////////////////////////// ////////////////////// INTERNALS ///////////////////////// //////////////////////////////////////////////////////////

string gQuery; integer comHandle; string meURL; string script; integer gitra; list lines; integer lock;

run() {

   integer comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
   comHandle = llListen(comChannel, "", llGetOwner(), "");
   llTextBox(llGetOwner(), "\nWelcome to [WaS-Gremlin]. Please enter a search string to look for scripts on the various wikis indexed by this gremlin.\n", comChannel);

}

default {

   state_entry() {
       llSetText("Touch to Search for LSL Scripts", <1,1,1>, 1.0);
   }
   touch_start(integer num_detected) {
       if(llDetectedKey(0) != llGetOwner() || comHandle != 0) return;
       run();
   }
   listen(integer channel, string name, key id, string message) {
       gQuery = message;
       state retrieve;
   }

}

state retrieve {

   state_entry() {
       llSetText("Retrieving... Please wait...", <1,1,1>, 1.0);
       llRequestURL();
   }

   timer() {
       llSetTimerEvent(0);
       script = "";
       llHTTPRequest("http://was.fm/perl/gremlin.pl?name=" + llStringToBase64(gQuery) + "&url=" + llEscapeURL(meURL),[], "");
   }

   http_request(key id, string method, string body) {
       if(method == URL_REQUEST_GRANTED) {
           meURL=body;
           llSetTimerEvent(0.8);
           return;
       }
       if(method != "POST") return;
       if(body == "EOT") {
           llHTTPResponse(id, 200, "OK");
           llReleaseURL(meURL);
           state display;
       }
       if(body == "N/A") {
           llHTTPResponse(id, 200, "OK");
           llOwnerSay("Sorry, could not find anything...");
           llResetScript();
       }
       script += body;
       llHTTPResponse(id, 200, "OK");
   }

   touch_start(integer num) {
       if(llDetectedKey(0)!=llGetOwner()) return;
       llResetScript();
   }

}

state display {

   state_entry() {
       llSetText("Listing...", <1,1,1>, 1.0);
       lines = llParseString2List(script, ["\n"], []);
       gitra=0;
       lock=1;
       llOwnerSay("/* -------------------------- START SCRIPT -------------------------- */");
       llSensorRepeat("", llGetOwner(), lock, 96.0, TWO_PI, 1.01-llGetRegionTimeDilation()); 
   }
   sensor(integer num_detected) {
       if(lock--) return;
       llSensorRemove();
       if(gitra>llGetListLength(lines)) {
           llSensorRemove();
           llOwnerSay("/* --------------------------- END SCRIPT --------------------------- */");
           llResetScript();
           return;
       }
       llOwnerSay(llList2String(lines, gitra++));
       lock=1;
       llSensorRepeat("", llGetOwner(), lock, 96.0, TWO_PI, 1.01-llGetRegionTimeDilation());
   }
   touch_start(integer detected_num) {
       if(llDetectedKey(0)!=llGetOwner()) return;
       llResetScript();
   }

} </lsl>

Nuked LSL with Minify

<lsl> string z;integer x;string y;string w;integer v;list u;integer t;i(){integer s=((integer)("0x"+llGetSubString( (string)llGetOwner(),-8,-1))&0x3FFFFFFF)^0xBFFFFFFF;x=llListen(s,"",llGetOwner(),"");llTextBox(llGetOwner(), "\nWelcome to [WaS-Gremlin]. Please enter a search string to look for scripts.\n",s);}default{state_entry() {llSetText("Touch to search scripts.",<1,1,1>,1.0);}touch_start(integer r){if(llDetectedKey(0)!=llGetOwner() ||x!=0)return;i();}listen(integer q,string p,key o,string n){z=n;state retrieve;}}state retrieve{state_entry(){ llSetText("Retrieving...",<1,1,1>,1.0);llRequestURL();}timer(){llSetTimerEvent(0);w="";llHTTPRequest( "http://was.fm/perl/gremlin.pl?name="+llStringToBase64(z)+"&url="+llEscapeURL(y),[],"");}http_request(key o, string m,string l){if(m==URL_REQUEST_GRANTED){y=l;llSetTimerEvent(0.8);return;}if(m!="POST")return; if(l=="EOT"){llHTTPResponse(o,200,"OK");llReleaseURL(y);state display;}if(l=="N/A"){llHTTPResponse(o,200,"OK"); llOwnerSay("Sorry, could not find anything...");llResetScript();}w+=l;llHTTPResponse(o,200,"OK");}touch_start( integer k){if(llDetectedKey(0)!=llGetOwner())return;llResetScript();}}state display{state_entry(){llSetText("...", <1,1,1>,1.0);u=llParseString2List(w,["\n"],[]);v=0;t=1;llOwnerSay("// START");llSensorRepeat("",llGetOwner(),t, 96.0,6.28318548,1.01-llGetRegionTimeDilation());}sensor(integer r){if(t--)return;llSensorRemove();if(v> llGetListLength(u)){llSensorRemove();llOwnerSay("// END");llResetScript();return;}llOwnerSay(llList2String(u,v++)); t=1;llSensorRepeat("",llGetOwner(),t,96.0,6.28318548,1.01-llGetRegionTimeDilation());}touch_start(integer j) {if(llDetectedKey(0)!=llGetOwner())return;llResetScript();}} </lsl>

Code: Gremlin - Perl

#!/usr/bin/perl -w
##########################################################
## [K] Kira Komarov - 2011, License: GPLv3              ##
## Please see: http://www.gnu.org/licenses/gpl.html     ##
## for legal details, rights of fair usage and          ##
## the disclaimer and warranty conditions.              ##
##########################################################
### Gremlin - Perl
##########################################################
###################### INTERNALS #########################
##########################################################
use strict;
use warnings;
##########################################################
#################### CONFIGURATION #######################
##########################################################
# You may add wikis to this array of hashes.
# protocol may be either http or https
# host is the hostname of the wiki and
# path is where the api.php scripts it to be found
my @LSL_WIKIS = (

"http://was.fm/w/api.php", # WaS Frequency Modulation
"https://wiki.secondlife.com/w/api.php", # SL Wiki

);
# You may add categories here to search in all wikis.
my @WIKI_CATEGORIES = ( "Category:Gremlin" );
# Add tags here separated by | which should be checked
# against the gremlin overload.
my $TAGS = "lsl|pre";
# If this ever changes, change it. Otherwise leave it 
# alone as it is.
my $LSL_HTTP_RESPONSE_LIMIT = 2048;
##########################################################
#################### CONFIGURATION #######################
##########################################################

##########################################################
###################### INTERNALS #########################
##########################################################

use CGI;
use MIME::Base64;
use MediaWiki::API;
use LWP::UserAgent;
use HTTP::Request;

my $q = CGI->new;
my $gremlins = decode_base64($q->param("name"));
my @gremlins_split = split(/ /, $gremlins);
my $wizard = $q->param("url");
$wizard =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
my @gremlin_store;
foreach(@gremlins_split) {
	if($_ =~ /([^\s]+)/) {
		push(@gremlin_store, quotemeta($1));
	}
}
my $gremlin_query = '[^"]*?'.join('.*?', @gremlin_store).'[^"]*?';

my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->agent("[WaS-Gremlin]");

my $mw = MediaWiki::API->new;
foreach (@LSL_WIKIS) {
	$mw->{config}->{api_url} = $_;
	foreach (@WIKI_CATEGORIES) {
		my $articles = $mw->list ( {
		 action => 'query',
		 list => 'categorymembers',
		 cmtitle => $_,
		 cmlimit => '500'
		}) or next;
		foreach (@{$articles}) {
			my $page = $mw->get_page( { title => $_->{title} } )->{'*'};
			$page =~ /.*<($TAGS){1,1}.*?gremlin="$gremlin_query"[^>]*>(.*?)<\/\1>.*/gis or next;
			my $code=$2;
			my @chunk = unpack "(A$LSL_HTTP_RESPONSE_LIMIT)*", $code;
			foreach(@chunk) {
				my $req = new HTTP::Request 'POST', $wizard;
				$req->content_type('text/plain');
				$req->content($_);
				$ua->request($req);
			}
			my $req = new HTTP::Request 'POST', $wizard;
			$req->content("EOT");
			$ua->request($req);
			return Apache2::Const::OK;
		}
	}
}
my $req = new HTTP::Request 'POST', $wizard;
$req->content_type('text/plain');
$req->content("N/A");
$ua->request($req);
return Apache2::Const::OK;

Pages in category "Gremlin"

The following 8 pages are in this category, out of 8 total.