The Everything 2 Auto-Noder is a JeffMagnus product that facilitates auto-noding on the Everything system. An old version of this script may have been partially responsbile for crashing E2, so be careful.

Contact me with any questions, comments, suggestions, and nude pictures of your motherboard.


#!/usr/bin/perl -w
#
# The New JeffMagnus Auto-Noder
#
#
use strict;

use lib ("/home/jc82/lib/perl5/site_perl/5.005/");

# Create a user agent object
use LWP::UserAgent;
use CGI;

my %numeric_types = ('person', 249, 'place', 252, 'idea', 251, 'thing', 250);

sub main
{
  my $ua = new LWP::UserAgent;
  $ua->agent('Auto-JeffMagnus/2.0 (' . $ua->agent . ')');

  $| = 1;

  my ( $stage, $key, %nodes );

  $stage = 1;

  while(<>)
  {
    chomp;
    if($stage == 1)
    {
      $stage = 2;
      $key = $_;
    }
    elsif($stage == 2)
    {
      $nodes{$key}->{'type'} = $_;
      $stage = 3;
    }
    elsif($stage == 3)
    {
      if($_ eq "----")
      {
        $stage = 1;
      }
      else
      {
        $nodes{$key}->{'text'}.="$_\n";
      }
    }
  }

  foreach $key (keys %nodes)
  {
    print "Creating [$key]...\n";
    
    my ( $node_id, $parent_node_id, $isnew ) = create_shell($key, $ua);
    unless(defined $node_id)
    {
      warn "Error creating [$key]!";
      open(SLOP, ">>node.error") or next;
      print SLOP "$key\n";
      print SLOP "$nodes{$key}->{'type'}\n";
      print SLOP "$nodes{$key}->{'text'}\n";
      print SLOP "----\n";
      close SLOP;
      next;
    }

    unless($isnew)
    {
      print 'Already has writeup. Replacing ';
    }
    print "Node-ID: [$node_id] Parent-Node-ID: [$parent_node_id]\n";

    if(populate_shell($node_id, $parent_node_id, $isnew, $nodes{$key}->{'type'},
      $nodes{$key}->{'text'}, $ua))
    {
      print "Noding should have worked...\n";
    }
    else
    {
      print "Failed to create...\n";
    }
  }

  return 0;
}

sub create_shell
{
  my ( $title, $ua ) = @_;
  my ( $node_id, $parent_node_id, $isnew );
  
  # Create a request
  my $req = new HTTP::Request
    POST => 'http://www.everything2.com/?node_id=365128&lastnode_id=124';

  $req->content_type('application/x-www-form-urlencoded');
  $req->header('Cookie' =>
    'userpass=Your User Name and Encrypted Password; path=/; expires= 10y');

  my $oneCGI = new CGI({'node'=>$title, 'op'=>'new',
    'type'=>'e2node', 'createit'=>'Create It!'});
    
  $req->content($oneCGI->query_string());

  # Pass request to the user agent and get a response back
  my $res = $ua->request($req);

  # Check the outcome of the response
  if ($res->is_success)
  {
    $_ = $res->content;

    if( $_ =~ /<INPUT TYPE=HIDDEN NAME=\"node\" VALUE=\"(\d*)\">
        <INPUT TYPE=checkbox NAME=writeup_notnew VALUE=1>
        \(Don't display in \"New Writeups\"\)
        <p><b>Enter your writeup<\/b><br>
        <TEXTAREA NAME=\"writeup_doctext\" ROWS=20 COLS=60 wrap=virtual>
        <\/TEXTAREA><br>
        <INPUT TYPE=hidden NAME=\"writeup_parent_e2node\" VALUE=\"(\d*)\">/ )
    {
      $node_id = $1;
      $parent_node_id = $2;
      $isnew = 1;
    }
    if( $_ =~ /<INPUT TYPE=HIDDEN NAME=\"node_id\" VALUE=\"(\d*)\"><b>Set/ )
    {
      $node_id = $1;
      $isnew = 0;
    }
    if( $_ =~ /<INPUT TYPE=hidden NAME=\"writeup_parent_e2node\" VALUE=\"(\d*)\">
        <INPUT TYPE=\"submit\" NAME=\"sexisgood\" VALUE=\"sumbit\">/ )
    {
      $parent_node_id = $1;
    }
  }

  return ( $node_id, $parent_node_id, $isnew );
} # end create shell

sub populate_shell
{
  my ( $node_id, $parent_node_id, $isnew, $type, $text, $ua ) = @_;
  
  # Create a request
  my $req = new HTTP::Request
    POST => 'http://www.everything2.com/?node_id=365128&lastnode_id=124';

  $req->content_type('application/x-www-form-urlencoded');
  $req->header('Cookie' =>
    'userpass=Your User Name and Encrypted Password; path=/; expires= 10y');

  my $oneCGI;
  
  if($isnew)
  {
    $oneCGI = new CGI({'node'=>'new writeup', 'op'=>'new', 'type'=>'writeup',
      'node'=>$node_id, 'writeup_doctext'=>$text,
      'writeup_parent_e2node'=>$parent_node_id, 'writeuptype'=>$type});
  }
  else
  {
    $oneCGI = new CGI({'node_id'=>$node_id,
      'writeup_wrtype_writeuptype'=>$numeric_types{$type},
      'writeup_doctext'=>$text, 'writeup_parent_e2node'=>$parent_node_id});
  }
    
  $req->content($oneCGI->query_string());

  # Pass request to the user agent and get a response back
  my $res = $ua->request($req);

  # Check the outcome of the response
  if ($res->is_success)
  {
    return 1;
  }

  return 0;
}

&main;
The very fact that JeffMagus has proven this possible means that others will follow, with or without his code. If I were to implement an autonoder I would probably use cURL or wget or Perl Net::HTTP rather than Lynx, but no matter.

This is why I believe there should be an interface for E2 Imports, where one submits a single marked up file -- I guess one should earn XP before being allowed to use it.

Perhaps, like Slashdot, E2 should provide thinking time -- a period of time after editing a node during which node creation is not allowed. This wouldn't bother human noders, since they would not type quickly enough to notice, but an autonoder would barf.

Name
E2 autonoder
Purpose
To make autonoding faster, easier, more portable and generally more feasible, to lessen pointless cut-and-pasting, in hopes that saved time will be spent writing bad poetry and guides to how to get laid (hint hint).
Justification
Why write this, when there already are at least 3 autonoders (jes-whatever/novalis's, JeffMagnus', rescdsk's) in existence? Well, for the latter two, they aren't published. I don't believe in security through obscurity... and as for first one, honestly, lynx isn't really the way to do it. Advantages this one has to e2auto.pl:
  1. Faster (downloads don't need get finished... although I should add /<html>/ after the second read, ah well)
  2. More portable (there isn't lynx in win32)
  3. More reliable (lynx and persistent cookies are bane all around... Eraser_ for one couldn't make it work)
  4. More functional (the previous one seemed to break under certain conditions
  5. Easier to find with search box (E2 seems to have real problems handling '.' with searches...)
  6. Doesn't overwiden the node window with too long lines and <pre>-tags ok, ok, I'll shut up now, was just a bit disappointed...
Usage
Get the source, save it, mangle to make it usable if necessary (see E2 node tracker for more instructions, I'm too tired to copy them here right now), run "./autonode.pl filename" where filename is name of file containing node data. Log in, and cry out in joy as E2 grows.
To-do
  • Configurability
  • Noding in alphabetic order instead of random perl internal hash order
  • Faster 2nd download
  • Option to allow some nodes enter ENN ('*' in front of type, for example)
... as you can see, most are trivial, expect new version shortly, I suppose...
Source, version 0.1 (initial public release, seems to work):

#!/usr/bin/perl -w

$sleep=5;

use Socket;
use CGI qw(escape);

if (!@ARGV) {
    print <<EOT
Usage: $0 <nodefile>

Syntax for nodefile:

name
type
body text
body text
...
----
name
type
body text
body text
...
----

name: name of node, as you would write it in search box.
type: person/place/idea/thing
EOT
;
    exit;
}

$|++;

print "Username: ";
$username=<STDIN>;
chomp $username;
system "stty", "-echo";
print "Password: ";
$userpass=<STDIN>;
chomp($userpass);
system "stty", "echo";
print "\n";  # Need this, since user's return won't be echoed

open(FILE,$ARGV[0]) or die "can't open nodefile!";
while (<FILE>) {
    chomp;
    $title=$_;
    $type=<FILE>;
    chomp $type;
    if ($type =~ m/(person|place|idea|thing)/) {
        $type=$1;
    } else {
        print "invalid type: $type\n";
        exit;
    }
    $text="";
    while ((defined ($a=<FILE>)) && ($a ne "----\n")) {
        $text.="$a";
    }
    chomp $text;
    $node{$title}=[$type,$text];
}
close(FILE);

print "Logging in... ";
consock(SOCK,"everything2.com",80) or die "can't connect!";
hotfh(SOCK);
print "connected. sending... ";
print SOCK
"GET /?op=login&node_id=109&lastnode_id=0&user=$username&".
"passwd=$userpass HTTP/1.0\r\n\r\n";
print "sent. reading... ";
while (<SOCK>) {
    if (/Set-Cookie: userpass=(.*?); /mi) {
        $cookie=$1;
        last;
        }
}
close(SOCK);
die "couldn't log in!" if !$cookie;
print "read.\nCookie: $cookie\n";

for $i (keys %node) {
    my $content;
    my $name=escape($i);
    my $body=escape($node{$i}[1]);
    my $node_id;
    my $type=$node{$i}[0];
    
    $content="node=$name&op=new&type=e2node";

    print "creating nodeshell for [$i] (if not already created)... ";
    consock(SOCK,"everything2.com",80) or die "can't connect";
    hotfh(SOCK) or die "can't unblock";
    
    print "connected. sending... ";

        print SOCK
"POST / HTTP/1.0\r\nCookie: userpass=$cookie\r\n".
"Content-length: ".(length $content)."\r\n\r\n$content\r\n";
        
        print "sent. reading... ";
            
    while (<SOCK>) {
        if (/<A HREF="\/index.pl\?node_id=\d+&lastnode_id=(\d+)">/i) {
            $node_id=$1;
            last;
        }
    }
    close(SOCK);
    
    print "done.\n";
    if (!$node_id) {
        print "Couldn't find node_id! Something is wrong.\n";
        exit;
    }
    print "node_id: $node_id\n";
    print "Creating writeup for [$i] ... ";
    consock(SOCK,"everything2.com",80) or die "can't connect";
    hotfh(SOCK) or die "can't unblock";
    
    $content="node=new+writeup&".
         "op=new&".
         "type=writeup&".
         "node=$node_id".
         "&writeup_notnew=1&".
         "writeup_doctext=$body&".
         "writeup_parent_e2node=$node_id&".
         "writeuptype-$type.x=0&".
         "writeuptype-$type.y=0";
    
    print "sending... ";
    print SOCK
"POST / HTTP/1.0\r\nCookie: userpass=$cookie\r\n".
"Content-length: ".(length $content)."\r\n\r\n$content\r\n";
    print "sent. reading... ";
    while (<SOCK>) { }
    print "done. It should be created! Sleeping for $sleep seconds now.\n";
    sleep($sleep);
}


sub hotfh {
        my $ofh;
        $ofh = select $_[0];
        $|++;
        select $ofh;
}

sub consock {
# SYNTAX: consock(filehandle, address, port)
        my ($remote, $port, $iaddr, $paddr, $proto, $fh, $sval);
        $fh = $_[0];
        $remote = $_[1];
        $port = $_[2];
        if (!($iaddr = inet_aton($remote))) {
                return;
        }
        $paddr = sockaddr_in($port, $iaddr);
        $proto = getprotobyname('tcp');
        socket($fh, PF_INET, SOCK_STREAM, $proto);

        $sval = connect($fh, $paddr);
        return $sval;
}

P.S. some people never learn...

A PHP Noding Library

This PHP library (and sample client) was written from the perl sources above. It was written to facilitate the creation of custom web-based noding environments for doing all sorts of stuff. It was written quickly (in about two hours); but it serves the purpose.

I am personally going to use this library to create a sort of automatic template that I can use to hammer out kanji. It will do things for me like automatically grabbing all of the readings for a kanji, an ASCII picture, etc. from sources on the web and assembling them into a node template to which I may add my own additional content; allowing me to focus more on putting my own personal writings and research into the node rather than having to do all of the fact-gathering grunt work by hand.

This was tested under PHP4, although it should work with PHP3. YMMV.


File 1 of 2:
e2auto.php.inc


<?php

define(E2DEBUG,1);

function _e2_debug($string)
{
	if (!E2DEBUG)
		return;

	echo $string;
	flush;
}

function e2_login($username, $password)
{
	_e2_debug("e2_login() Connecting...<br>");

	$fp = fsockopen ("www.everything2.com", 80, $errno, $errstr, 30);
	if (!$fp)
	{
	    echo "$errstr ($errno)<br>\n";
	    return -1;
	}
    
	_e2_debug("Connected!  Attempting to log in...<br>");

	fwrite($fp,
		 "GET /?op=login&node_id=109&lastnode_id=0"
		."&user=".urlencode($username)
		."&passwd=".urlencode($password)
		." HTTP/1.0\r\n\r\n"
	);

	while( !feof($fp) )
	{
		$buf .= fgets($fp,128);	
	}

	if ( !eregi("Set-Cookie: userpass=(.*); path=",$buf,$regs) )
	{
		echo "Unable to login!<br>";
		return -1;
	}
	$handle=$regs[1];

	_e2_debug("Login successful!<br>");

	fclose($fp);

	return $handle;
}

function _e2_writenodeshell($handle,$title)
{
	$fp = fsockopen ("www.everything2.com", 80, $errno, $errstr, 30);
	if (!$fp)
	{
	    echo "$errstr ($errno)<br>\n";
	    return -1;
	}

	$httpdata = "node=".urlencode($title)."&op=new&type=e2node";

	_e2_debug("POSTing nodeshell...<br>\n");

	fwrite($fp,
		 "POST / HTTP/1.0\r\n"
		."Cookie: userpass=".$handle."\r\n"
		."Content-length: ".strlen($httpdata)."\r\n\r\n"
		.$httpdata."\r\n"
	);

	while( !feof($fp) )
	{
		$buf .= fgets($fp,128);	
	}

	if ( !eregi("<A HREF=\"\\/index.pl\\?node_id=[0-9]+&lastnode_id=([0-9]+)\">"
		        ,$buf,$regs) )
	{
		echo "Unable to find nodeshell id!<br>";
		return -1;
	}
	$lastnode_id=$regs[1];

	_e2_debug("Nodeshell ($lastnode_id) creation successful!<br>");

	fclose($fp);

	return $lastnode_id;
}

function e2_writenode($handle,$title,$content,$type)
{

	$type=strtolower($type);

	if ( !($type == "person" || $type == "place" ||
		 $type == "thing"  || $type == "idea") )
	{
		echo "Invalide type ($type) for node \"".htmlentities($title)."\" !<br>";
		return -1;
	}

	_e2_debug("e2_writenode() Creating nodeshell...<br>");

	if ( !($node_id = _e2_writenodeshell($handle,$title)) )
		return -1;

	$fp = fsockopen ("www.everything2.com", 80, $errno, $errstr, 30);
	if (!$fp)
	{
	    echo "$errstr ($errno)<br>\n";
	    return -1;
	}

	$httpdata = "node=new+writeup"
	         . "&op=new"
			 . "&type=writeup"
			 . "&node=".$node_id
			 . "&writeup_notnew=1"
			 . "&writeup_doctext=".urlencode($content)
			 . "&writeup_parent_e2node=".$node_id
			 . "&writeuptype-".$type.".x=0"
			 . "&writeuptype-".$type.".y=0";

	fwrite($fp,
		 "POST / HTTP/1.0\r\n"
		."Cookie: userpass=".$handle."\r\n"
		."Content-length: ".strlen($httpdata)."\r\n\r\n"
		.$httpdata."\r\n"
	);

	_e2_debug("Sent:<br><pre>".htmlentities($httpdata)."</pre><br>");

	while( !feof($fp) )
	{
		$buf .= fgets($fp,128);	
	}

	_e2_debug("Node have been created...go find out!<br>");

	fclose($fp);
}

?>


File 2 of 2:
e2client.php


<?php

/*
 * Disable Magic Quotes:
 */
set_magic_quotes_runtime(0);

/*
 * Include our e2 autonoding library:
 */
include("e2auto.php.inc");

/*
 * Called to input a node; called by default.
 */
function do_getwriteup()
{
	echo "<h2><u>AP's Customizable PHP E2 Write-Up Portal:</u></h2>\n";

	echo "<form name=\"e2_ap\" action=\"index.php\" method=\"post\">\n";
	echo "<input type=\"hidden\" name=\"func\" value=\"newwriteup\">\n";

	echo "<blockquote>\n";

	echo "\t<p>\n";
	echo  "\t\t<strong>Username:</strong> "
	     ."<input type=\"text\" name=\"e2_username\" size=\"16\"><br/>\n";
	echo  "\t\t<strong>Password:</strong> "
	     ."<input type=\"password\" name=\"e2_password\" size=\"16\">\n";
	echo "\t</p>\n";

	echo "\t<p>\n";
	echo  "\t\t<strong>Title:</strong> "
	     ."\t\t<input type=\"text\" name=\"e2_title\" size=\"64\"><br/>\n";

	echo "\t<strong>Node content:<br/>\n";
	echo  "\t<textarea name=\"e2_content\""
             ."ROWS=\"30\" COLS=\"80\" wrap=virtual></textarea><br/>\n";
	echo "\t<strong>Set the type:</strong> ";
	echo "\t<select name=\"e2_type\">\n";
	echo "\t\t<option value=\"person\">person\n";
	echo "\t\t<option value=\"place\">place\n";
	echo "\t\t<option value=\"idea\">idea\n";
	echo "\t\t<option value=\"thing\">thing\n";
	echo "\t</select><br/>\n";
	echo "\t<input type=\"submit\" value=\"sumbit\">\n";
	echo "\t</p>\n";

	echo "</blockquote>\n";

	echo "</form>\n";
}

/*
 * Called to actually write the node out to e2.
 */
function do_newwriteup()
{

	global $e2_username, $e2_password;
	global $e2_title, $e2_content, $e2_type;

	if (!($e2_username) || !($e2_password) ||
		!($e2_title) || !($e2_content) || !($e2_type))
	{
		echo  "<strong>Missing some form information!"
		     ."  Please re-enter!!</strong>";
		exit();
	}

	if ( !($handle = e2_login($e2_username,$e2_password)) )
		exit();

	e2_writenode($handle,$e2_title,$e2_content,$e2_type);
}

/*
 * The Start of Execution
 * main() {
 */

if ( !isset($func) ) $func = "";
switch($func)
{
	case "newwriteup":
		do_newwriteup();
		break;
	case "getwriteup":
	default:
		do_getwriteup();
}

/*
 * }
 */

?>


Log in or registerto write something here or to contact authors.