FapFun

Userscript for Motherless.com. Provide direct links for pictures and video files. Download all Images on one site with DownThemAll(firefox) or Download Master(Chrome).

As of 2015-07-08. See the latest version.

// ==UserScript==
// @name       	  FapFun
// @namespace   	https://greasyfork.org/scripts/7156-fapfun/code/FapFun.user.js
// @description 	Userscript for Motherless.com. Provide direct links for pictures and video files. Download all Images on one site with DownThemAll(firefox) or Download Master(Chrome).
// @require			  https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js
// @include    	  htt*://motherless.com*
// @version			  3.6
// @grant      	  GM_xmlhttpRequest
// @grant 			  GM_setClipboard
// @grant			    GM_setValue
// @grant			    GM_getValue
// @grant			    GM_deleteValue
// @grand         UnsafeWindow
// @author        sodomgomora
// @license			  GPLv3
// ==/UserScript==
// Some of this script based on Pornifier2 script by Jesscold 
// This script is realesed under GPL v3
// Globals
var debug = false;
var images = [];
var ids = [];
var imagesUrl = [];
var siteurls = [];
var thisurl = '';
// Start the magic
main();
function fapLog(log) {
  if (debug === true) {
    console.log(log);
    return;
  }
  return;
}
function main() {
  fapLog('entered main');
  // try to become Premium
  // setTimeout(function(){
  // unsafeWindow.__is_premium = true; //really motherless?
  // }, 500);
  thisurl = window.location.href;
  var inputList = document.createElement('input');
  inputList.type = 'button';
  inputList.value = 'Images URLs';
  inputList.name = 'imagesurl';
  inputList.onclick = getImageList;
  inputList.setAttribute('style', 'font-size:18px;position:fixed;top:100px;right:20px;z-index:10000;');
  document.body.appendChild(inputList);
  addSinglePreview();
  checkForPaginationLinks(function (hasOne) {
    fapLog('main: haseOne= ' + hasOne);
    if (hasOne > 0) {
      var inputAllImages = document.createElement('input');
      inputAllImages.type = 'button';
      inputAllImages.value = 'Get all Images';
      inputAllImages.name = 'getallimages';
      inputAllImages.onclick = getAllImages;
      inputAllImages.setAttribute('style', 'font-size:18px;position:fixed;top:140px;right:20px;z-index:10000;');
      document.body.appendChild(inputAllImages);
    }
    return;
  });
  return;
}
function addResetButton() {
  var resetButton = document.createElement('input');
  resetButton.type = 'button';
  resetButton.value = 'Reset';
  resetButton.name = 'deletevalue';
  resetButton.onclick = deleteGMValue;
  resetButton.setAttribute('style', 'font-size:18px;position:fixed;top:220px;right:20px;z-index:10000;');
  document.body.appendChild(resetButton);
  return;
}
function checkForPaginationLinks(cb) {
  var ret = '';
  ret = $('.pagination_link').contents().text();
  fapLog('checkForPaginationLinks: entered!');
  fapLog('checkForPaginationLinks: ret= ' + ret);
  if (ret === '') {
    cb(0);
    return;
  } else {
    cb(1);
    return;
  }
}
//----- Button onclick functions -----

function deleteGMValue() {
  fapLog('deleteGMValue: thisurl= ' + thisurl);
  GM_deleteValue(thisurl);
  $('input[name*=\'deletevalue\']').remove();
  $('input[name*=\'stopvalue\']').remove();
}
function getAllImages() {
  var href = '';
  var lasttmp = 0;
  ids = [
  ];
  href = window.location.href;
  href = href.replace(/^(http|https):\/\//i, '');
  fapLog('getAllImages: href= ' + href);
  var url = getUrl(href);
  if (GM_getValue(url.allsites) != undefined) {
    fapLog('getAllImages: was processed earlyer!');
    addResetButton();
    displayOverlay(imagesUrl, 'lasti', url.allsites);
    thisurl = url.allsites;
    return;
  }
  thisurl = url.allsites;
  sneakyXHR(url.onesite, function (src) {
    fapLog('getAllImages: callback from sneakyXHR = ' + src);
    var urlwithoutpagenumber = url.onesite.substring(0, url.onesite.length - 1);
    $firstids = $('<div>' + src + '</div');
    $firstsite = $('<div>' + src + '</div').find('.pagination_link a');
    fapLog($firstsite);
    $firstsite.each(function () {
      var tmp = parseInt($(this).text());
      if (tmp > lasttmp) {
        lasttmp = tmp;
      }
    });
    var headers = {
      'Range': 'bytes=0-3000'
    };
    //load last paginationsite if last is realy true
    GM_xmlhttpRequest({
      method: 'get',
      'url': urlwithoutpagenumber + lasttmp,
      headers: $.extend({
      }, {
          'User-agent': 'Mozilla/4.0',
          'Accept': 'application/atom+xml,application/xml,text/xml',
          'Cookie': document.cookie
        }, headers || {
        }),
      onload: function (responseDetails) {
        var lastsitetmp = 1;
        var text = responseDetails.responseText;
        $lastsite = $('<div>' + text + '</div').find('.pagination_link a');
        fapLog($lastsite);
        $lastsite.each(function () {
          var tmp = parseInt($(this).text());
          if (tmp > lastsitetmp) {
            lastsitetmp = tmp;
          }
        });
        fapLog('getAllImages: lasttmp= ' + lasttmp + ' lastsitetmp=' + lastsitetmp);
        if (lasttmp < lastsitetmp) {
          lasttmp = lastsitetmp;
        }
        $test = $firstids.find('img[src^="http://thumbs.motherlessmedia.com/thumbs/"]');
        $test.each(function () {
          try {
            var id = $(this).attr('data-strip-src').match('thumbs/([^.]+).\\w');
          }
          catch (err) {
            return;
          }
          ids.push(id[1]);
        });
        fapLog('getAllImages: lasttmp= ' + lasttmp);
        //paginationsite shown but has no link
        if (lasttmp == 0) {
          getImages('getallimages', ids);
          return;
        }
        var urlwithoutpagenumber = url.onesite.substring(0, url.onesite.length - 1);
        for (var i = 2; i < lasttmp + 1; i++) {
          var lenght = siteurls.push(urlwithoutpagenumber + i);
        }
        fapLog('getAllImages: siteURLs= ' + siteurls);
        addStop();
        parralelizeTask(siteurls, loopGetSites, 'getallimages', function () {
          getImages('getallimages', ids);
          return;
        });
      }
    });
  }, 'get', {
      'Range': 'bytes=0-3000' //grab first 3k
    });
  return;
}
// retrun URLs for user,group,galleries and search page
function getUrl(href) {
  var url = '';
  var urlall = '';
  var parthref = '';
  var n = href.indexOf('?');
  if (n != - 1) {
    parthref = href.substring(0, n);
  } else {
    parthref = href;
  }
  fapLog('getUrl: parthref= ' + parthref);
  var casesn = parthref.indexOf('/');
  var cases = parthref.substring(casesn + 1, casesn + 2);
  fapLog('getUrl: cases= ' + cases);
  switch (cases) {
    case 'G':
      var gup = parthref.substring(casesn + 3, parthref.lenght);
      fapLog('getUrl: gup= ' + gup);
      url = 'http://motherless.com/GI' + gup + '?page=1';
      urlall = 'http://motherless.com/GI' + gup;
      break;
    case 'g':
      var g = parthref.substring(casesn + 3, parthref.lenght);
      fapLog('getUrl: g= ' + g);
      url = 'http://motherless.com/gi' + g + '?page=1';
      urlall = 'http://motherless.com/gi' + g;
      break;
    case 'u':
      var u = parthref.substring(casesn, parthref.lenght);
      fapLog('getUrl: u= ' + u);
      url = 'http://motherless.com' + u + '?t=i&page=1';
      urlall = 'http://motherless.com' + u;
      break;
    case 't':
      var t = parthref.substring(casesn, parthref.lenght);
      fapLog('getUrl: t= ' + t);
      url = 'http://motherless.com' + t + '?range=0&size=0&sort=relevance&page=1';
      urlall = 'http://motherless.com' + t;
      break;
  }
  return {
    onesite: url,
    allsites: urlall
  };
}
function getImageList() {
  fapLog('getImageList: pressed');
  thisurl = window.location.href;
  if (thisurl.indexOf('?') == - 1) {
    thisurl = thisurl + '?page=1';
  }
  if (GM_getValue(thisurl) != undefined) {
    addResetButton();
    displayOverlay(data = [], 'lasti', thisurl);
    return false;
  }
  getImages('imagesurl', images);
  return;
}
function getVideoUrl() {
  alert('not jet implemented!');
  return;
}
//-- handler for Overlay (jquery)

$(function () {
  $('body').click(function () {
    if ($('#overlay').length > 0) {
      removeOverlay();
      return;
    }
  });
  return;
});
function removeOverlay() {
  $('#overlay').remove();
  return;
}
// Get url for full image and add url under thumbnail

function addSinglePreview() {
  var data = [];
  var i = 0;
  var imgs = $('img[src^="http://thumbs.motherlessmedia.com/thumbs/"]');
  if (typeof unsafeWindow.__fileurl != "undefined"){
    fapLog('Script url found: ' + unsafeWindow.__fileurl);
    var $wrap = $('.media-action-networks');
    fapLog('TEst' + $wrap.toSource());
    var videourl = $('<strong>Video URL: </strong><a href=\'' + unsafeWindow.__fileurl + '\' class=\'pop\'>Download</a>');
    $wrap.after(videourl);
  }
  fapLog('image urls found: ' + imgs.length);
  imgs.each(function () {
    var $wrap = $(this);
    if ($wrap.data('p2-preview')) {
      return;
    }
    $wrap.data('p2-preview', 'yep');
    var $a = $wrap.closest('a');
    var vid = $wrap.attr('src').match('thumbs/([^.]+).\\w');
    // test for video preview and not an image
    var vlink = vid[1];
    var n = vlink.indexOf('-');
    vlink = vlink.substring(n, vlink.length);
    fapLog('vlink: ' + vlink);
    // is a video
    if (vlink == '-small') {
      var videoClicky = $('<a href=\'javascript;\' class=\'p2-single-preview\'>Video URL</a>');
      $a.after(videoClicky);
      var href = $a.attr('href').match(/\.com\/(\w)(\w+)/) ? [
        RegExp.$1,
        RegExp.$2
      ] : false;
      videoClicky.click(function (e, single) {
        var $this = $currentSingle = $(this);
        $this.text('loading...');
        var id = $wrap.attr('data-strip-src').match('thumbs/([^.]+).\\w');
        var vl = id[1];
        var n = vl.indexOf('-');
        id[1] = vl.substring(0, n);
        fapLog('addSinglePreview: found url for video: ' + id[1]);
        if (!id) {
          $this.text('cant load :P');
          return;
        }
        var timer = setTimeout(function () {
          $this.text('cant load :P');
        }, 8000);
        var fs = new findSrc();
        fs.findVideoSrc(id[1], function (src) {
          $this.text('Show Video');
          clearTimeout(timer);
          if (single) {
            data = [src];
          } else {
            data.unshift(src);
          }
          fapLog('addSinglePreview: video src: ' + src.toSource());
          displayOverlay(data, 'video');
        });
        return false;
      });
    }
    else {
      try {
        var id = $wrap.attr('data-strip-src').match('thumbs/([^.]+).\\w');
      }
      catch (err) {
        fapLog(err.message);
        return;
      }
      images[i] = id[1];
      i++;
      fapLog('fill images: image=' + images[i - 1] + ' index=' + i);
      var imageClicky = $('<a href=\'javascript;\' class=\'p2-single-preview\'>View full size</a>');
      $a.after(imageClicky);
      var href = $a.attr('href').match(/\.com\/(\w)(\w+)/) ? [
        RegExp.$1,
        RegExp.$2
      ] : false;
      imageClicky.click(function (e, single) {
        var $this = $currentSingle = $(this);
        $this.text('loading...');
        fapLog('found url for image: ' + id[1]);
        if (!id) {
          $this.text('cant load :P');
          return;
        }
        var timer = setTimeout(function () {
          $this.text('cant load :P');
        }, 8000);
        var fs = new findSrc();
        fs.findImgSrc(id[1], function (src) {
          $this.text('View full size');
          clearTimeout(timer);
          if (single) {
            data = [
              src
            ];
          } else {
            data.unshift(src);
          }
          fapLog('addSinglePreview: image src: ' + src.toSource());
          displayOverlay(data, 'image');
        });
        return false;
      });
    }
  });
}
function getImages(buttonname, arrimg) {
  fapLog('getImages: arrimg.length=' + arrimg.length);
  fapLog(arrimg);
  $button = $('input[name*=\'' + buttonname + '\']');
  $button.val('working...');
  if (arrimg.length > 0) {
    parralelizeTask(arrimg, loopFindImageSource, buttonname, function () {
      fapLog('getImages: iamgesUrl= ' + imagesUrl.toSource());
      arrimg = [];
      displayOverlay(imagesUrl, 'images', thisurl);
      imagesUrl = [];
      return;
    });
  }
  fapLog('getImages: last call for return');
  arrimg = [
  ];
  return;
}
function findSrc() {
  this.findVideoSrc = function (id, cb) {
    var href = 'http://motherless.com/' + id;
    sneakyXHR(href, function (d) {
      fapLog('sneaky request all: ' + d.toSource());
      var url = d.match(/"http:([^"]+).mp4"/im) ? RegExp.$1 : null;
      if (url) {
        cb({
          url: 'http:' + url + '.mp4'
        });
      }
      return;
    }, 'get', {
        'Range': 'bytes=0-3000' //grab first 3k
      });
    return;
  };
  this.findImgSrc = function (id, cb) {
    var href = 'http://motherless.com/' + id + '?full';
    sneakyXHR(href, function (d) {
      var img = d.match(/property="og:image" content="([^"]+)"/im) ? RegExp.$1 : null;
      if (img) {
        cb({
          url: img
        });
      }
      return;
    }, 'get', {
        'Range': 'bytes=0-3000' //grab first 3k
      });
    return;
  };
}
function sneakyXHR(url, cb, method, headers) {
  method = method || 'GET';
  fapLog('sneaky requesting: ' + url);
  setTimeout(function () {
    GM_xmlhttpRequest({
      method: method,
      'url': url,
      headers: $.extend({
      }, {
          'User-agent': 'Mozilla/4.0',
          'Accept': 'application/atom+xml,application/xml,text/xml',
          'Cookie': document.cookie
        }, headers || {
        }),
      onload: function (responseDetails) {
        var text = responseDetails.responseText;
        cb(text, responseDetails);
      }
    });
  }, 1);
  return;
}
// show the full image as overlay and shrink it to screen resolution

function displayOverlay(data, type, url) {
  var mywidht = window.screen.width - 50;
  var myheight = window.screen.height - 120;
  var html = '';
  fapLog('monitor resolution: ' + mywidht + ':' + myheight);
  switch (type) {
    case 'lasti':
      fapLog('displayOverlay: lasti: url= ' + url);
      html = GM_getValue(url);
      GM_setClipboard(GM_getValue(url + 'clipboard'));
      break;
    case 'image':
      html = '<table id=\'overlay\'><tbody><tr><td><img src=\'' + data[0].url + '\' style=\'width:auto; hight:100%; max-height:' + myheight + 'px; max-width:' + mywidht + 'px\'></td></tr></tbody></table>';
      break;
    case 'video':
      html = '<table id=\'overlay\'><tbody><tr><td><a href=\'' + data[0].url + '\'>Video Link</a></td></tr></tbody></table>';
      break;
    case 'images':
      var clipboard = '';
      var count = 1;
      $('input[name*=\'getallimages\']').val('Get all Images');
      $('input[name*=\'imagesurl\']').val('Images URLs');
      html = '<table id=\'overlay\'><tbody><tr><td>';
      data.forEach(function (value) {
        html += '<a class=\'changeColorLink\' href=\'' + value + '\'>link ' + count + '</a> ';
        clipboard += value + ' ';
        count++;
      });
      html += '</td></tr></tbody></table>';
      GM_setClipboard(clipboard);
      GM_setValue(url, html.toString());
      GM_setValue(url + 'clipboard', clipboard.toString());
      break;
  }
  fapLog('displayOverlay: type= ' + type + ': html=' + html.toSource());
  setTimeout(function () {
    var $el = $(html).css({
      'position': 'fixed',
      'top': 0,
      'left': 0,
      'width': '90%',
      'height': '900px',
      'background-color': 'rgba(0,0,0,.7)',
      'z-index': 10000,
      'vertical-align': 'middle',
      'text-align': 'center',
      'color': '#fff',
      'font-size': '30px',
      'font-weight': 'bold',
      'overflow': 'hidden',
      'cursor': 'auto'
    });
    $('a.changeColorLink', $el).hover(function () {
      $(this).css('color', 'blue');
    }, function () {
        $(this).css('color', 'pink');
      });
    $el.appendTo('body');
  }, 50);
  return;
}
//----- PARALELLIZISE -----
//paralellize for getting all sites within pagination 

function loopGetSites(doneTask, value) {
  sneakyXHR(value, function (src) {
    $firstids = $('<div>' + src + '</div');
    $test = $firstids.find('img[src^="http://thumbs.motherlessmedia.com/thumbs/"]');
    $test.each(function () {
      try {
        var id = $(this).attr('data-strip-src').match('thumbs/([^.]+).\\w');
      }
      catch (err) {
        fapLog(err.message);
        return;
      }
      if (id[1].lastIndexOf('-strip') != - 1) {
        fapLog('loopGetSites: Falsche parameter. Enthält -strip');
        return;
      }
      ids.push(id[1]);
      return;
    });
    doneTask();
    return;
  }, 'get', {
      'Range': 'bytes=0-3000' //grab first 3k);		
    });
}
//function to parallelize the findImageSource function

function loopFindImageSource(doneTask, value) {
  var fs = new findSrc();
  fs.findImgSrc(value, function (src) {
    var i = 0;
    data = [
      src
    ];
    imagesUrl.push(data[0].url);
    doneTask();
    return;
  });
  return;
}
//helper function for parralelize functions

function parralelizeTask(arr, fn, buttonname, done) {
  fapLog('parralelizeTask: arr= ' + arr);
  var total = arr.length;
  var maxtotal = total;
  var counttimeout = 0;
  fapLog('parralelizeTask: arr.length= ' + total);
  doneTask = function () {
    if (--total === 0) {
      done();
      return;
    }
    $('input[name*=\'' + buttonname + '\']').val('processed:' + total);
    return;
  };
  arr.forEach(function (value) {
    fn(doneTask, value);
  });
  return;
}

function addStop() {
  var stopButton = document.createElement('input');
  stopButton.type = 'button';
  stopButton.value = 'Stop';
  stopButton.name = 'stopvalue';
  stopButton.onclick = stop;
  stopButton.setAttribute('style', 'font-size:18px;position:fixed;top:260px;right:20px;z-index:10000;');
  document.body.appendChild(stopButton );
  return;
}

function stop() {
  displayOverlay(imagesUrl, 'images', thisurl);
}