Here is the source for DavidWSBot. It is licensed under the GPLv3. It uses the library sxwiki, which is also GPL. The source for bot.php:

<?php
require_once('config.php'); //configuration
require_once('SxWiki.php'); //bot framework
$success = false; //init
$wiki = new SxWiki(); //init
$wiki->verbosity = -1; //We do our own error logging :)
$editcount = 0; // Edits made this session
$opt = array();
set_time_limit(0);
$trialmode = true;
$trial = 30;

//Function declarations
function _log($what,$level = 1)
{
    global $logfile;
    $toadd = date(DATE_RFC822) . ": " . $what . "\n";
    file_put_contents($logfile,$toadd,FILE_APPEND);
    if($level == 1)
    {
        echo $toadd;
    }
    return true;
}

function error($err,$exit)
{
    $errtext = (($exit) ? "Critical error: " : "Error: ") . $err;
    _log($errtext);
    if($exit) die();
}

function getList()
{
    global $wiki;
    //global $opt;
    global $listpg;
    _log("Getting opt-in list");
    $result = array();
    $users = array();
    $wt = $wiki->getPage($listpg[0],$listpg[1]);
    preg_match_all("{{user\|(.*?)}}",$wt,$result,PREG_SET_ORDER);
    foreach($result as $r)
    {
        $users[] = $r[1];
        _log($r[1] . " has opted in",0);
    }
    _log("Finished getting opt-in list, " . count($users) . " opted in.");
    //$opt = $users;
    return $users;
}

function getRequests()
{
    global $wiki;
    
    _log("Finding users requesting to be unblocked");
    $users = $wiki->getCat("Requests for unblock");
    $params = array(
    "action" => "query",
    "list" => "blocks",
    "bklimit" => "1", // most recent block
    "bkusers" => "" // we will set this during the loop
    );
    $retval = array();
    for($i = 0; $i < count($users); $i++)
    {
        $user = $users[$i];
        if(strpos($user,"User") === 0)
        {
            //$user = str_replace("User talk:","User:",$user);
            $params["bkusers"] = $user;
            $info = $wiki->callAPI($params);
            $block = $info['query']['blocks'][0];
            if($block['by'] != "")
            {
                $temp = array($user,$block['by']);
                $retval[] = $temp;
            }
            //_log($user . " is requesting to be unblocked, originally blocked by " . $block['by'],0);
        }
    }
    _log("Finished finding users requesting to be unblocked");
    return $retval;
}

function close()
{
    global $editcount;
    _log("Session ending.  $editcount edits this session.");
}

function notify($blocked,$admin)
{
    global $wiki;
    global $editcount;
    global $trialmode;
    global $trial;
    $blocked = str_replace("User talk:","",$blocked);
    $blocked = trim($blocked);
    $utpage = "User talk: $admin";
    $current = $wiki->getPage($utpage);
    $notestring = "==Unblock Request Notification==" . "\r\n" . "{{subst:User:DavidWSBot/Unblocknotify|$blocked}}";
    $notestring .= "<!--unblocknote:($blocked," . time() . ")-->";
    preg_match("<\!--unblocknote\:\(" . preg_quote($blocked) . ",(.*?)\)-->",$current,$r);
    $timestamp = $r[1];
    $diff = time() - $timestamp;
    _log("notify($blocked,$admin) called");
    $n = $current . "\n" . $notestring;
    if($trialmode)
    {
        if($editcount >= $trial)
        {
            _log("Trial limit of $trial reached");
            die();
        }
    }
    if($timestamp == "" || $timestamp == NULL)
    {
        $diff = 21700;
    }
    if(!($diff >= 21600))
    {
        _log("$admin was already notified about $blocked within the last 6 hours.");
    }
    else
    {
        _log("Notifying $admin of the unblock request of $blocked");
        $wiki->putPage($utpage,"[[User:DavidWSBot|UB Request bot]]",$n,true,true);
        $editcount++;
        _log("$admin notified.  Total edits this session: $editcount");
    }
}
// End of function declarations

// Where are we going to run?
if($en == false)
{
    $wiki->url = $url;
}
else
{
    $wiki->wikipedia = "en";
}

// Now, here's the bot code
if($wiki->login($username,$password)) // Try logging in
{
    _log("Logged in to the wiki.");
}
else
{
    error("Could not login",true);
}
while($e != true)
{
    
    
    $opt = getList();
    $reqs = getRequests();
    foreach($reqs as $req)
    {
        _log(str_replace(" talk:",":",$req[0]) . " blocked by " . $req[1]);
        if(in_array($req[1],$opt)) //Opted in?
        {
            _log($req[1] . " is opted in, going to notify");
            notify($req[0],$req[1]);
        }
    }
    if(file_exists("./e.txt"))
    {
        $e = true;
        _log("Found e.txt, going to exit");
    }
    //notify("User talk: test","DavidWS");
    _log("Went through loop.  Sleeping ninety seconds.");
    usleep(90000000); // sleep ninety seconds
}

close();
?>

and, for config.php:

<?php
$username = "DavidWSBot";
$password = "";
$en = true;
$url = "http://test.wikipedia.org/wiki/"; //unneeded if using en
$logfile = "./log.txt";
$listpg = array("User:DavidWSBot/Optin",1); //Page,section
?>