There are 444 previous versions of this script.
the source is over 100KB, syntax highlighting in the browser is too slow
// ==UserScript==
// @name FB Wall Manager
// @namespace FB Wall Manager
// @description Manages Wall Posts for Various FB Games
// @include http://www.facebook.com/pages/FB-Wall-Manager/*
// @include /^https?:\/\/www\.facebook\.com\/.*\/posts\/.*/
// @license http://creativecommons.org/licenses/by-nc-nd/3.0/us/
// @version 2.2.4.7
// @copyright Charlie Ewing except where noted
// @require http://userscripts.org/scripts/source/29910.user.js
// @require http://userscripts.org/scripts/source/123889.user.js
// @require http://userscripts.org/scripts/source/128747.user.js
// @require http://userscripts.org/scripts/source/129006.user.js
// @require http://userscripts.org/scripts/source/130453.user.js
// @require http://userscripts.org/scripts/source/130454.user.js
// ==/UserScript==
// Based on script built by Joe Simmons in Farmville Wall Manager
(function() {
//***************************************************************************************************************************************
//***** Globals
//***************************************************************************************************************************************
var version = "2.2.4.7";
var userID="", profile="",userAlias="";
var feeds = {
me:{url:"https://graph.facebook.com/me/home", next:"", prev:"", enabled:true, filters:{} },
wall:{url:"https://graph.facebook.com/me/feed", next:"", prev:"", enabled:true, filters:{} }
};
var rules = {};
var groups = {};
var apps = {};
var posts = {};
var history = {};
this.opts = {}; //make it global
this.quickOpts = {};
var sortFields = ["created_time","which","fromID","fromName","priority","appID","id","status","state"];
var typesPaused = [];
//***************************************************************************************************************************************
//***** Preload
//***************************************************************************************************************************************
//dont run in iframes
try {
var unsafeWindow = unsafeWindow || window.wrappedJSObject || window;
if(unsafeWindow.frameElement != null) return;
} catch(e) {log("preload: "+e);}
//***************************************************************************************************************************************
//***** Functions
//***************************************************************************************************************************************
//returns all members of an array that have a specified parameter with a specified value
//replaces same function from WM Library Script
this.matchByParam=function(o,param,value,outputType){try{
if(!exists(outputType)) outputType="array";
var inputType=(isArray(o))?"array":((typeof o) == "object")?"object":"unknown";
var ret=(outputType=="object")?{}:[]; //default to array on error
switch(inputType){
case "array": for (var i=0,e;(e=o[i]);i++){
switch(outputType){
case "array": if (e[param]==value) ret.push(e); break;
case "object": if (e[param]==value) ret[i]=e; break;
}
};break;
case "object": for (var i in o){
var e=o[i];
switch(outputType){
case "array": if (e[param]==value) ret.push(e); break;
case "object": if (e[param]==value) ret[i]=e; break;
}
};break;
}
return ret;
}catch(e){log("matchByParam: "+e);}};
//***************************************************************************************************************************************
//***** Special Use as post liker
//***************************************************************************************************************************************
//check for likeit function
function likeit(){try{
log("likeit");
var like = selectSingleNode(".//div[@id='globalContainer']//li[contains(@id,'stream_story_')]//button[@name='like']");
if (!like) like = selectSingleNode(".//div[@id='globalContainer']//li[contains(@id,'stream_story_')]//a[@class='UFILikeLink']/span");
//april 2013 version
if (!like) {
like = selectSingleNode(".//div[@id='globalContainer']//li[contains(@id,'stream_story_')]//a[@class='UFILikeLink']");
//validate not already pressed like
if (like) like = (like.getAttribute("data-ft")=="{\"tn\":\">\"}")?like:null; //detect if already liked
}
if (like) {
setTimeout(function(){
click(like);
setTimeout(function(){
sendMessage("status=1");
},500);
},500);
} else {
setTimeout(likeit,1000);
}
}catch(e){log("likeit: "+e);}};
if (location.href.startsWith("http://www.facebook.com/") && location.href.contains("/posts/")) {
if (location.hash.contains("likeit")) likeit();
return;
}
//***************************************************************************************************************************************
//***** Debug Object
//***************************************************************************************************************************************
if (debug) {
debug.init();
if (debug.initialized) log("Debug Console Initialized");
}
//***************************************************************************************************************************************
//***** Status Object
//***************************************************************************************************************************************
var doStatus = true; //always true until told otherwise after gmconfig loads
var status = {
initialized: false,
windowNode: null,
messageNode: null,
progressNode: null,
progressTextNode: null,
progressValueNode: null,
fadeInterval:null,
linger:false,
init: function(params){
params=params||{};
if (!($("WM_statusWindow"))) {
addGlobalStyle(""+
"#WM_statusWindow {padding:0px; border:1px solid #99A8C7; background-color:#E1E6EE; overflow:hidden; border-radius:3px; height:44px; width:99%;}\n"+
"#WM_statusWindow > .message {margin:3px; display:inline-block; border-right:1px solid #BFCADE; background-color:#91FF91;}\n"+
"#WM_statusWindow > .message:last-child {border-right:0px;}\n"+
"#WM_statusWindow > .message:hover {background-color:#CAD1DE;}\n"+
"#WM_statusWindow > .message > .icon {width:16px; height:16px; margin-left:2px; display:inline-block; vertical-align:top;}\n"+
"#WM_statusWindow > .message > .text {margin-left:7px; display:inline-block; width:176px; vertical-align:top; font-size:11px; text-overflow:ellipsis; color:#3B5998;}\n"+
"#WM_statusWindow > .message > .closetool {visibility:hidden; display:inline-block; width:14px; height:14px; vertical-align:top;}\n"+
"#WM_statusWindow > .message > .closetool:hover {background-color:#3B5998;}\n"+
"#WM_statusWindow > .message:hover > .closetool {visibility:visible;}\n"+
/*"#WM_statusWindow .progressBar {display:inline; position:relative; width:200px; height:14px; border:1px solid #CCDDAA; border-radius:5px; overflow:hidden;}\n"+
"#WM_statusWindow .progressBar .gfxValue {position:absolute; top:0px; left:0px; background-color:#DDFFCC; width:200px; height:14px; border-right:3px solid #CCDDAA;}\n"+
"#WM_statusWindow .progressBar .txtValue {position:absolute; top:0px; left:0px; width:200px; height:14px; text-align:center;}\n"+*/
""
,"styleStatus");
document.body.appendChild(
status.windowNode = createElement("div",{id:"WM_statusWindow"},[
//status.messageNode=createElement("div",{className:"message"}),
/*status.progressNode=createElement("div",{className:"progressBar"},[
status.progressValueNode=createElement("div",{className:"gfxValue"}),
status.progressTextNode=createElement("div",{className:"txtValue"}),
])*/
])
);
}
status.initialized = true;
},
print: function(msg, params){
if (!doStatus) return;
params=params||{};
if (!status.initialized) status.init();
if (!status.initialized) return;
//create a new message node
var id=unique();
var messageNode=createElement("div",{id:id, className:"message"},[
createElement("img",{className:"icon",src:params.icon}),
createElement("div",{className:"text",textContent:msg}),
createElement("img",{className:"closetool",src:imgs.x,onclick:function(){remove(this.parentNode);}}),
]);
/*if (status.progressNode) {//params.progress &&
status.progressNode.style.display="block";
status.progressTextNode.textContent=params.progressMsg||params.progress||msg||"";
status.progressValueNode.style.width=params.progress||"100%";
}*/
//append message to display
status.windowNode.appendChild(messageNode);
//reset fade timer
status.show();
if (status.fadeInterval) window.clearTimeout(status.fadeInterval);
if (!(params.linger||null)){
status.fadeInterval = setTimeout(status.hide,5000);
}
//destroy this message after a timer
if (!(params.linger||null)) setTimeout(function(){
remove($(id));
},5000);
//pass back the id of this message so we can delete it externally
return id;
},
show: function(){
if (!status.initialized) status.init();
if (!status.initialized) return;
if (status.windowNode) status.windowNode.style.visibility="";
},
hide: function(){
if (!status.initialized) status.init();
if (!status.initialized) return;
if (status.windowNode) status.windowNode.style.visibility="hidden";
},
};
status.init();
if (status.initialized) status.print("",{progress:"100%",progressMsg:"Status Console Initialized"});
//***************************************************************************************************************************************
//***** CSS Library and Constructors for Visual Form Elements
//***************************************************************************************************************************************
if (forms) {
forms.init();
if (debug.initialized) log("Forms Library Initialized");
}
//***************************************************************************************************************************************
//***** Visual Console Object
//***************************************************************************************************************************************
var wmConsole = {
initialized: false,
tabsNode: null, //container for tab container, left side
pagesNode: null, //container for tab pages, right side
curTab: "Feed", //remember the tab currently opened
sidekickNode: null, //remember the sidekicks list
feedNode: null, //remember where to put the feed data
dynamicTree: null, //remember where to put the dynamic grabber tests
dynamicViewer: null, //remember where to put the dynamic grabber data viewer
loading: true, //set to false after sidekicks have time to load
priorityNode: null,
priorityBuild: null,
showTab: function(){
forms.selectTabAndSection(this.id.split("_")[1],"wmMainItem","wmMainPage");
wmConsole.curTab = this.id.split("_")[1];
},
init: function(params){try{
var validateFBElements=["globalContainer","content"];
for (var e=0,elen=validateFBElements.length;e<elen;e++){
if (!($(validateFBElements[e]))) {
log("wmConsole.init: Expected element \""+validateFBElements[e]+"\" does not exist");
}
}
params=params||{};
status.print("Initializing Console");
if (!($("wmTabContainer"))) {
try{addGlobalStyle(""+
"a:hover {text-decoration: none !important;}\n"+
//"#mainContainer {background-color:#DDDDEE; padding-right:20px; padding-top:20px;}\n"+
//".hasLeftCol #mainContainer {border-right:none;}\n"+
//"#leftColContainer {float:left;}\n"+
//"#contentCol {border-radius: 5px 5px 0px 0px; padding:0px !important;}\n"+
//"#contentCurve {border-radius: 0px 0px 5px 5px; background-color:#EEEEFF; margin-right:1px;}\n"+
//"#footerContainer {border: none;}\n"+
"#content {display:none !important; }\n"+
"#wmContent {background-color:#DDDDEE; position:relative;}\n"+
"#wmLeftCol {display:table-cell; position:relative; vertical-align:top;}\n"+
"#wmRightCol {display:table-cell; position:relative; width:100%;vertical-align:top;}\n"+
"#contentCurve {display:none;}\n"+
".consoleButton {border-radius: 5px 5px 5px 5px; color: #3B5998; font-size: 11pt; padding: 10px; position: absolute; text-align: center;}\n"+
".consoleButton.left {background-color: #EEEEFF; border: 1px solid #CCCCDD; }\n"+
".consoleButton.right {background-color: #E0E8F6; border: 1px solid #DDDDEE; }\n"+
".consoleButton.icon {width:24px; height:24px; padding:5px; line-height:24px; font-weight:900; font-family:arial; font-size:20px;}\n"+
".consoleButton.icon img {width:24px; height:24px; }\n"+
".consoleButton.selected {background-color: #FFFFFF !important;}\n"+
"#wmOptions {top: 395px; left:30px; width: 105px;}\n"+
"#wmVersion {top: 440px; left:30px; width: 105px;}\n"+
"#wmPause {color: white; left: 30px; top: 30px;}\n"+
"#wmPause:hover {font-size: 26px; }\n"+
"#wmOlder {color: white; left: 70px; top: 30px;}\n"+
"#wmOlder:hover {font-size: 26px; }\n"+
"#wmNewer {color: white; left: 110px; top: 30px;}\n"+
"#wmNewer:hover {font-size: 26px; }\n"+
"#wmTabContainer {width:181px; padding-top:66px;}\n"+
".wm.sideBar {text-align:center; position:relative; border:1px solid #DDDDEE; border-radius:5px 0px 0px 5px; height:50px; display:block; left:20px; width:160px; border-right:1px solid #CCCCDD;}\n"+
".wm.sideBar.selected {background-color:#EEEEFF; border: 1px solid #CCCCDD; border-right:1px solid #EEEEFF; right:-1px; z-index:9999;}\n"+
".wm.sideBar .title {font-size:12pt; line-height:50px;}\n"+
"#wmPageContainer {position:relative; border-radius:5px; background-color:#EEEEFF; border: 1px solid #CCCCDD; overflow:hidden; height:500px;}\n"+
".wm.content {display:none; overflow:hidden;}\n"+
".wm.content.selected {display:block;}\n"+
".wm.content > .header {line-height:30px; padding-left:10px; font-size:12pt; border-bottom:1px solid #CCCCDD;}\n"+
"#wmSidekickList {position: relative; height:440px; padding:5px;}\n"+
".wmSidekickEntry {height:64px; border-bottom:1px solid #CCCCDD; position:relative;}\n"+
".wmSidekickEntry .icon {position:absolute; height:32px; width:32px; left:16px; top:16px;}\n"+
".wmSidekickEntry .title {position:absolute; line-height:32px; left:64px; top:0px; font-size:12pt;}\n"+
".wmSidekickEntry .desc {position:absolute; line-height:32px; left:64px; top:32px; font-size:8pt;}\n"+
".wmSidekickEntry .master {position:absolute; padding:5px; bottom:10px; right:10px;}\n"+
"#wmPageContainer > div {height:100%;}\n"+
"#wmMainPage_FeedSource > textarea {margin: 5px; height: 430px; font-size:11pt;}\n"+
"#wmMainPage_FeedSource > .caption {position:absolute; font-size:11pt; padding:10px;}\n"+
"#wmFeedsSave {top: 200px; right:30px; width: 105px;}\n"+
//"#wmMainPage_Dynamics > textarea {margin: 5px; height: 430px; font-size:11pt;}\n"+
//"#wmDynTutorial {top: 35px; right:165px; width: 105px;}\n"+
//"#wmDynSave {top: 35px; right:30px; width: 105px;}\n"+
//"#wmDynOpts {position:absolute; top:35px; left:35px; width:105px;}\n"+
"#wmDynamicTree {width:50%; display:inline-block; vertical-align:top;}\n"+
"#wmDynamicViewer {width:50%; display:inline-block; vertical-align:top;}\n"+
"#wmDynamicViewer input, #wmDynamicViewer select, #wmDynamicViewer textArea {border-radius:4px; border:1px solid #BDC7D8; padding:3px; margin:6px;}\n"+
"#wmPageTools {position:absolute; right:17px; z-index:2; border:1px solid black; border-radius:5px; padding:2px; background-color:#808080; color:black;}\n"+
"#wmPageTools > * {display:none; }\n"+
"#wmPageTools label {vertical-align:baseline;}\n"+
"#wmPageTools .toolIcon {width:16px; height:16px; display:block !important;}\n"+
"#wmPageTools:hover {background-color:white;}\n"+
"#wmPageTools:hover > * {display:block;}\n"+
"#wmPageTools:hover .toolIcon {display:none !important;}\n"+
"#wmPageViewSelector {font-weight:bold; color:#666666; border:none;}\n"+
".wm.post.classic {position:relative; min-height:90px; margin-left:10px; margin-right:10px; font-size:11px; color:#808080; border-bottom:1px solid #CCCCDD; padding-bottom:20px; padding-top:10px; clear:both;}\n"+
".wm.post.classic .actor {margin-top:5px; margin-bottom:10px; font-weight:700; color:#3B5998;}\n"+
".wm.post.classic .picture {float:left;padding-top:5px; padding-right:10px; }\n"+
".wm.post.classic .picture img {width:90px; height:90px; background-color:white; border:1px solid; border-radius:5px;}\n"+
".wm.post.classic .title {margin-top:5px; font-weight:700; color:#3B5998;display:block;}\n"+
".wm.post.classic .caption {display:block; }\n"+
".wm.post.classic .description {padding-top:5px; display:block;}\n"+
".wm.post.classic .postDate {}\n"+
".wm.post.classic .appName {position:relative; left:10px;}\n"+
".wm.post.classic .linkText {color:#899ADB; float:right; padding-right:32px;}\n"+
".wm.post.classic.scam {}\n"+
".wm.post.classic.noimage {min-height:1px;}\n"+
"#wmFeedNode.short {padding:20px;}\n"+
".wm.post.short {float:left; position:relative; font-size:11px; color:#808080;}\n"+
".wm.post.short .floater {overflow:hidden; display:block; background-color: white; border:0px solid; border-radius:5px; position:absolute; z-index:3; padding:0; width:0px; height:0px;}\n"+
".wm.post.short:hover .floater {-moz-transition-property: width,height,padding,border;-moz-transition-delay:1s; width:240px; height:120px; padding:5px 10px;border:1px solid;}\n"+
".wm.post.short .actor {display:block;}\n"+
".wm.post.short .picture {position:relative;}\n"+
".wm.post.short .picture img {position:relative; width:100%; height:100%; background-color:white;}\n"+
".wm.post.short .postDate {display:block;}\n"+
".wm.post.short .appName {display:block;}\n"+
".wm.post.short .linkText {display:block;}\n"+
".wm.post.short .progress {opacity:0.25; background-color:#00FF00;}\n"+
".wm.post.short.working .picture img {z-index:2;border-radius:5px; border:1px solid;}\n"+
".wm.post.short.excluded .picture img {opacity:0.25;}\n"+
".wm.post.short.timeout .picture img {opacity:0.25;}\n"+
".wm.post.short.paused .picture img {opacity:0.25;}\n"+
".wm.post.short.nodef .picture img {opacity:0.25;}\n"+
".wm.post.short.scam {}\n"+
".wm.post.short.accepted .picture img {opacity:0.25;}\n"+
".wm.post.short.failed .picture img {opacity:0.25;}\n"+
".wm.post.dev {position:relative; min-height:90px; margin-left:10px; margin-right:10px; font-size:11px; color:#808080; border-bottom:1px solid #CCCCDD; padding-bottom:20px; padding-top:10px; clear:both;}\n"+
".wm.post.dev .postid {display:block; }\n"+
".wm.post.dev .actor {display:block; padding-top:5px; font-weight:700; color:#3B5998;}\n"+
".wm.post.dev .picture {float:left;padding-top:5px; padding-right:10px; }\n"+
".wm.post.dev .picture img {width:90px; height:90px; background-color:white; border:1px solid; border-radius:5px;}\n"+
".wm.post.dev .title {padding-top:5px; font-weight:700; color:#3B5998;display:block;}\n"+
".wm.post.dev .msg {padding-top:5px; display:block; }\n"+
".wm.post.dev .caption {padding-top:5px; display:block; }\n"+
".wm.post.dev .description {padding-top:5px; display:block;}\n"+
".wm.post.dev .url {display:block; padding-top:5px; word-wrap:break-word;}\n"+
".wm.post.dev .imgsrc {display:block; padding-top:5px; word-wrap:break-word;}\n"+
".wm.post.dev .postDate {display:block; padding-top:5px;}\n"+
".wm.post.dev .appName {display:block; padding-top:5px;}\n"+
".wm.post.dev .linkText {color:#899ADB; float:right; padding-right:32px;}\n"+
".wm.post.dev .likes {display:block;}\n"+
".wm.post.dev .likeElement {display:block;}\n"+
".wm.post.dev .comments {display:block;}\n"+
".wm.post.dev .commentElement {display:block;}\n"+
".wm.post.dev .commentComment {display:block;}\n"+
".wm.post.dev.scam {}\n"+
".wm.content > div > .toolBox {display:inline;}\n"+
".wm.content > div > .toolBox > div {display:inline;}\n"+
".wm.post > .toolBox {display:inline;}\n"+
".wm.post > .toolBox > div {display:inline;}\n"+
".wm.post.classic > .toolBox {position: absolute; right: 0; top: 0;}\n"+
".toolBox.small .toolButton {height:24px;width:24px;}\n"+
".toolBox.medium .toolButton {height:32px;width:32px;}\n"+
".toolBox.large .toolButton {height:48px;width:48px;}\n"+
".toolBox.xlarge .toolButton {height:64px;width:64px;}\n"+
".toolBox.small .toolButton > a {height:22px;width:22px; top:1px; left:1px;}\n"+
".toolBox.medium .toolButton > a {height:28px;width:28px; top:2px; left:2px;}\n"+
".toolBox.large .toolButton > a {height:42px;width:42px; top:3px; left:3px;}\n"+
".toolBox.xlarge .toolButton > a {height:56px;width:56px; top:4px; left:4px;}\n"+
".toolBox.small .toolButton > a > img {height:20px;width:20px; top:1px; left:1px;}\n"+
".toolBox.medium .toolButton > a > img {height:24px;width:24px; top:2px; left:2px;}\n"+
".toolBox.large .toolButton > a > img {height:36px;width:36px; top:3px; left:3px;}\n"+
".toolBox.xlarge .toolButton > a > img {height:48px;width:48px; top:4px; left:4px;}\n"+
".toolBox.inline .toolButton {float: right;}\n"+
".toolBox.columnRight .toolButton {float: right; clear:both;}\n"+
".toolBox.columnLeft .toolButton {float: left; clear:both;}\n"+
"a.identified:after {content: url('"+imgs.identified+"'); padding-left:6px; margin-top:2px;}\n"+
"a.excluded:after {content: url('"+imgs.excluded+"'); padding-left:6px; margin-top:2px;}\n"+
"div.excluded {background-color:gray !important;}\n"+
"div.identified {}\n"+
"div.working {background-color:yellow !important;}\n"+
"div.timeout {background-color:orange !important;}\n"+
"div.paused {background-color:silver !important;}\n"+
"div.nodef {background-color:deepskyblue !important;}\n"+
"div.failed {background-color:red !important;}\n"+
"div.accepted {background-color:limegreen !important;}\n"+
"div.scam {background-color:purple !important;}\n"+
"div.scam * {color:black !important; text-decoration:none !important;}\n"+
"div.scam:after {content:url('"+imgs.warning+"'); position:absolute; right:0; top:0;}\n"+
".underline {border-bottom:1px solid #CCCCDD;}\n"+
".toolTip {display:none; border:1px solid #767676; border-radius:3px; background-color:white; color:black; position:absolute; font-size:8pt; padding:5px; line-height: 12px; z-index:9999;}\n"+
"*:hover > .toolTip {display:block;}\n"+
".menuNode {width:0px; height:0px; position:absolute; background:none; border:none;top:-5px;}\n"+
".toolTip.menuNode > ul {position:absolute; background-color: white; border: 1px solid; border-radius: 5px 5px 5px 5px; padding: 2px; min-width:100px;}\n"+
".toolTip.menuNode > ul > li {position:relative; line-height:1.28; }\n"+
".toolTip.right.menuNode {right:5px; }\n"+
".toolTip.left.menuNode {left:-5px; }\n"+
".toolTip.right.menuNode > ul {left:0px;}\n"+
".toolTip.right.menuNode > ul > li {text-align:left;}\n"+
".toolTip.left.menuNode > ul {right:0px;}\n"+
".toolTip.left.menuNode > ul > li {text-align:right;}\n"+
".toolButton { border-radius: 7px; display: block; }\n"+
".toolButton > a { border-radius: 6px; display: block; position: relative; }\n"+
".toolButton > a > img { border-radius: 5px; position: relative; display:block;}\n"+
".toolButton.oddBlue {background-image: -moz-linear-gradient(center top , #51D1EA 0%, #00758B 100%); background-color:#51D1EA;}\n"+
".toolButton.oddBlue > a {background-image: -moz-linear-gradient(center top , white 0%, #54CBE1 100%);background-color:white;}\n"+
".toolButton.oddBlue > a > img {background-image: -moz-linear-gradient(center top , #54CBE1 0%, #1FAABF 100%); background-color:#51D1EA;}\n"+
".toolButton.oddGreen {background-image: -moz-linear-gradient(center top , #B7E54F 0%, #5A8F00 100%);background-color:#B7E54F;}\n"+
".toolButton.oddGreen > a {background-image: -moz-linear-gradient(center top , white 0%, #7DBB00 100%);background-color:white;}\n"+
".toolButton.oddGreen > a > img {background-image: -moz-linear-gradient(center top , #AAE636 0%, #76AE0D 100%); background-color:#B7E54F;}\n"+
".toolButton.oddOrange {background-image: -moz-linear-gradient(center top , #FF9968 0%, #832000 100%);background-color:#FF9968;}\n"+
".toolButton.oddOrange > a {background-image: -moz-linear-gradient(center top , white 0%, #E83400 100%);background-color:white;}\n"+
".toolButton.oddOrange > a > img {background-image: -moz-linear-gradient(center top , #FA9052 0%, #D94213 100%); background-color:#FF9968;}\n"+
".toolButton.oddBlack {background-image: -moz-linear-gradient(center top , #82976E 0%, #090C05 100%);background-color:#82976E;}\n"+
".toolButton.oddBlack > a {background-image: -moz-linear-gradient(center top , white 0%, #2F3825 100%); background-color:white;}\n"+
".toolButton.oddBlack > a > img {background-image: -moz-linear-gradient(center top , #7D8F67 0%, #3F4835 100%); background-color:#82976E;}\n"+
".toolButton.separator {width:0 !important; border:1px solid silver !important; margin:0 5px !important;}\n"+
".toolDropDown {border:1px solid silver; border-radius:5px; padding:7.5px 5px; float:right; color:white; font-weight:bold; background-color:gray; box-shadow: 0 0 2px 2px white inset;}\n"+
".menuEntry, .menuList > li {position:relative; border-radius:3px; border:1px solid white; padding:3px; min-width:100px;}\n"+
".menuEntry:hover, .menuList > li:hover {border-color:#CCCCDD; background-color:#E0E8F6; }\n"+
".oldcoolPage {}\n"+
".accFailBlock {color: white; font-size: 9px; font-weight: bold; left: 0; line-height: 1.28; position: absolute; top: 0; width: 64px;}\n"+
".accFailBlock .fail {background-color: #C3463A; border-radius: 2px 2px 2px 2px; box-shadow: 1px 1px 1px rgba(0, 39, 121, 0.77); float: right; padding: 1px 2px;}\n"+
".accFailBlock .accept {background-color: #46B754; border-radius: 2px 2px 2px 2px; box-shadow: 1px 1px 1px rgba(0, 39, 121, 0.77); float: right; padding: 1px 2px;}\n"+
".priority {clear:both;}\n"+
".priority .title {border-bottom: 1px solid; border-top: 1px solid; display: block; font-size: 12px; font-weight: bold;}\n"+
//"#wmMainPage_Prioritize > textarea {margin: 5px; height: 150px; font-size:11pt; width:780px;}\n"+
"#wmPriorityBuilder {margin:5px; position: relative;}\n"+
"#wmPriorityBuilder .listItem {position:relative; border-radius: 5px; border: 1px solid #BDC7D8; padding: 5px;}\n"+
"#wmPriorityBuilder .listItem .toolBox {position: absolute; right: 0; top: 0;}\n"+
"#wmPriorityBuilder .listItem .accept {background-color: #46B754; border-radius: 2px 2px 2px 2px; box-shadow: 1px 1px 1px rgba(0, 39, 121, 0.77); padding: 5px; color: white; font-size: 9px; font-weight: bold; line-height: 1.28; postition:relative; top:-2px; margin:3px;}\n"+
"#wmPriorityBuilder select {border-radius: 4px; margin: 6px; padding: 3px;}\n"+
"#wmPriorityBuilder .selectAppID {}\n"+
"#wmPriorityBuilder .selectBonus {}\n"+
"#wmPriorityBuilder .selectPriority {}\n"+
"#wmPriorityBuilder .selectLimit {}\n"+
"#wmPriorityBuilder .selectTask {}\n"+
".unsaved {background-color:lightyellow !important;}\n"+
".whiteover:hover {background-color:#FFFFFF !important;}\n"+
".blueover:hover {background-color:#E0E8F6 !important;}\n"+
".buildMode * {background-image:url('"+imgs.grid50+"') !important;}\n"+
".red {background-color:#C3463A !important; border: 2px solid #982B2F !important; text-shadow: -1px -1px 1px #982B2F, 1px 1px 1px #982B2F, 1px -1px 1px #982B2F, -1px 1px 1px #982B2F; text-transform: none !important; font-color:white !important;}\n"+
".red:hover {background-color:#EA1515 !important;}\n"+
".green {background-color:#46B754 !important; border: 2px solid #256E46 !important; text-shadow: -1px -1px 1px #256E46, 1px 1px 1px #256E46, 1px -1px 1px #256E46, -1px 1px 1px #256E46; text-transform: none !important; font-color:white !important;}\n"+
".green:hover {background-color:#A6E11D !important;}\n"+
".blue {background-color:#51C2FB !important; border: 2px solid #057499 !important; text-shadow: -1px -1px 1px #057499, 1px 1px 1px #057499, 1px -1px 1px #057499, -1px 1px 1px #057499; text-transform: none !important; font-color:white !important;}\n"+
".blue:hover {background-color:#C2DEFF !important;}\n"+
".gray {background-color:#999999 !important; border: 2px solid #666666 !important; text-shadow: -1px -1px 1px #666666, 1px 1px 1px #666666, 1px -1px 1px #666666, -1px 1px 1px #666666; text-transform: none !important; font-color:white !important;}\n"+
".gray:hover {background-color:#C3C3C3 !important;}\n"+
".odd {background-image: -moz-linear-gradient(center top , orange, red); box-shadow: 1px 1px 1px black; -moz-transform: rotate(15deg);}\n"+
".odd:hover {-moz-transform: none;}\n"+
".post.mosquito {width:16px; height:16px;}\n"+
".post.tiny {width:24px; height:24px;}\n"+
".post.small {width:32px; height:32px;}\n"+
".post.medium {width:48px; height:48px;}\n"+
".post.large {width:64px; height:64px;}\n"+
".post.xlarge {width:96px; height:96px;}\n"+
".floater.mosquito {left:8px;top:8px;}\n"+
".floater.tiny {left:12px;top:12px;}\n"+
".floater.small {left:16px;top:16px;}\n"+
".floater.medium {left:24px;top:24px;}\n"+
".floater.large {left:32px;top:32px;}\n"+
".floater.xlarge {left:48px;top:48px;}\n"+
".post.mosquito.working .picture img {width:24px; height:24px;left:-4px;top:-4px;}\n"+
".post.tiny.working .picture img {width:32px; height:32px;left:-4px;top:-4px;}\n"+
".post.small.working .picture img {width:48px; height:48px;left:-8px;top:-8px;}\n"+
".post.medium.working .picture img {width:64px; height:64px;left:-8px;top:-8px;}\n"+
".post.large.working .picture img {width:96px; height:96px;left:-16px;top:-16px;}\n"+
".post.xlarge.working .picture img {width:128px; height:128px;left:-16px;top:-16px;}\n"+
".post.pinned {border-radius: 6px; background-color: black;}\n"+
".post.short.pinned .picture img {border-radius: 5px; height:80% !important; width:80% !important; margin-left:10%; margin-top:10%;}\n"+
""
,"styleConsole")}catch(e){log("wmConsole.init.addGlobalStyle: "+e);};
//create a new wmContent div
var baseNode=$("globalContainer");
if (baseNode) baseNode=baseNode.parentNode; else baseNode=($("body")||document.body);
baseNode.insertBefore(createElement("div",{id:"wmContent"},[
createElement("div",{id:"wmLeftCol"}),
createElement("div",{id:"wmRightCol"}),
]), $("globalContainer") );
if ($("content")) $("content").style.display="none !important";
//create the left tabs
$("wmLeftCol").appendChild(
wmConsole.tabsNode = createElement("div",{id:"wmTabContainer"},[
createElement("a",{id:"wmMainItem_Feed",href:jsVoid,className:"wm sideBar whiteover selected",onclick:wmConsole.showTab},[
createElement("span",{className:"title",href:jsVoid, textContent:"Collect"})
]),
createElement("a",{id:"wmMainItem_Sidekicks",href:jsVoid,className:"wm sideBar whiteover",onclick:wmConsole.showTab},[
createElement("span",{className:"title", textContent:"Manage Sidekicks"})
]),
createElement("a",{id:"wmMainItem_Dynamics",href:jsVoid,className:"wm sideBar whiteover",onclick:wmConsole.showTab},[
createElement("span",{className:"title", textContent:"Dynamic Grabber"})
]),
createElement("a",{id:"wmMainItem_FeedSource",href:jsVoid,className:"wm sideBar whiteover",onclick:wmConsole.showTab},[
createElement("span",{className:"title", textContent:"Manage Feeds"})
]),
createElement("a",{id:"wmMainItem_Prioritize",href:jsVoid,className:"wm sideBar whiteover",onclick:wmConsole.showTab},[
createElement("span",{className:"title", textContent:"Prioritize"})
]),
])
);
//add update/reinstall button
$("wmLeftCol").appendChild(
createElement("a",{className:"whiteover consoleButton left",id:"wmVersion",textContent:"V."+version,href:"http://userscripts.org/scripts/source/86674.user.js"},[
createElement("span",{className:"toolTip",innerHTML:"CTRL+Click to update<br/>Refresh after install"})
])
);
//add panels
$("wmRightCol").appendChild(
wmConsole.pagesNode = createElement("div",{id:"wmPageContainer"},[
//feeds panel
createElement("div",{id:"wmMainPage_Feed",href:jsVoid,className:"wm content selected"},[
//apps tab
forms.createCoolBar({tabs:[
{id:"feedAll", title:"Show ALL", selected:(quickOpts["filterApp"]=="All"),func:wmConsole.selectFilter,kids:[
wmConsole.feedNode=createElement("div",{id:"wmFeedNode",className:""}),
]},
]}),
]),
//sidekicks panel
createElement("div",{id:"wmMainPage_Sidekicks",href:jsVoid,className:"wm content"},[
createElement("div",{className:"header",textContent:"Sidekicks"}),
wmConsole.sidekickNode=createElement("div",{id:"wmSidekickList",className:"scrollY"}),
]),
//dynamics panel
createElement("div",{id:"wmMainPage_Dynamics",href:jsVoid,className:"wm content"},[
createElement("div",{className:"header",textContent:"Dynamic Grabber"}),
wmConsole.dynamicTree=createElement("div",{id:"wmDynamicTree",className:"scrollY"}),
wmConsole.dynamicViewer=createElement("div",{id:"wmDynamicViewer",className:"scrollY"}),
]),
//feeds panel
createElement("div",{id:"wmMainPage_FeedSource",href:jsVoid,className:"wm content"},[
createElement("div",{className:"header",textContent:"Feed Sources"}),
wmConsole.feedSourceNode=createElement("textarea",{textContent:getOpt("feeds_"+profile,'')||""}),
createElement("span",{className:"caption",innerHTML:"Enter the id or alias of a user or page to collect from those object's feeds.<br/>One id per line.<br/>The base feed source is your own news feed, which includes your profile wall. If you want to collect from another specific source, find that source's FB id."}),
createElement("span",{id:"wmFeedsSave",className:"whiteover consoleButton right",textContent:"Compile",onclick:main.compileFeedSources}),
]),
//rules panel
createElement("div",{id:"wmMainPage_Prioritize",href:jsVoid,className:"wm content"},[
createElement("div",{className:"header",textContent:"Priorities and Limits"}),
createElement("div",{className:"toolBox medium columnRight"},[
createElement("div",{},[
createElement("div",{className:"toolButton oddGreen"},[createElement("a",{title:"Add Rule",href:jsVoid,onclick:main.newRule},[createElement("img",{src:imgs.markasaccepted})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{title:"Reset All Limits",href:jsVoid,onclick:main.resetAllLimits},[createElement("img",{src:imgs.refresh})])]),
])
]),
wmConsole.priorityBuild=createElement("div",{id:"wmPriorityBuilder",className:"scrollY"},[]),
]),
])
);
//collection panel toolbar
wmConsole.feedNode.parentNode.className+=" scrollY selected";
wmConsole.feedNode.parentNode.parentNode.insertBefore(
createElement("div",{className:"toolBox medium inline",style:"display:inline-block;"},[
createElement("div",{},[
createElement("div",{className:"toolButton oddBlack"},[createElement("a",{title:"ReID All",href:jsVoid,onclick:main.reIDAll},[createElement("img",{src:imgs.reidentify})])]),
createElement("div",{className:"toolButton oddBlack"},[createElement("a",{title:"Clean Now",href:jsVoid,onclick:main.cleanPosts},[createElement("img",{src:imgs.trash})])]),
createElement("div",{className:"toolButton oddBlack"},[createElement("a",{title:"Reset Counters",href:jsVoid,onclick:main.resetCounters},[createElement("img",{src:imgs.refresh})])]),
createElement("div",{className:"toolButton separator"}),
(isChrome)?null:createElement("div",{className:"toolButton oddBlack"},[createElement("a",{title:"Sort Descending",href:jsVoid,onclick:function(){main.sortPosts({direction:"desc"});main.redrawPosts();} },[createElement("img",{src:"http://i1181.photobucket.com/albums/x430/merricksdad/sortdesc.png"})])]),
(isChrome)?null:createElement("div",{className:"toolButton oddBlack"},[createElement("a",{title:"Sort Ascending",href:jsVoid,onclick:function(){main.sortPosts({direction:"asc"});main.redrawPosts();} },[createElement("img",{src:"http://i1181.photobucket.com/albums/x430/merricksdad/sortasc.png"})])]),
(isChrome)?null:createElement("select",{id:"wmSortBy",className:"toolDropDown", title:"Sort By:", onchange:function(){main.sortPosts({by:this.value});main.redrawPosts();} },optionsFromArray(sortFields)),
(isChrome)?null:createElement("div",{className:"toolButton separator"}),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{name:"2",title:"Developer View",href:jsVoid,onclick:main.setDisplay},[createElement("img",{src:imgs.dev})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{name:"1",title:"Short View",href:jsVoid,onclick:main.setDisplay},[createElement("img",{src:imgs.short})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{name:"0",title:"Classic View",href:jsVoid,onclick:main.setDisplay},[createElement("img",{src:imgs.classic})])]),
createElement("div",{className:"toolButton separator"}),
createElement("div",{className:"toolButton oddOrange"},[createElement("a",{id:"wmpausecollect",title:"Pause Automatic Collection",href:jsVoid,onclick:main.pauseCollecting},[createElement("img",{src:imgs.stop})])]),
createElement("div",{className:"toolButton oddOrange"},[createElement("a",{id:"wmpausefetch",title:"Pause Automatic Fetching",href:jsVoid,onclick:main.pauseFetching},[createElement("img",{src:imgs.expand2})])]),
createElement("div",{className:"toolButton oddBlack"},[createElement("a",{title:"Fetch Older Posts Now",href:jsVoid,onclick:function(){main.fetch({next:true,bypassPause:true});} },[createElement("img",{src:imgs.feeds})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{title:"Fetch Newer Posts Now",href:jsVoid,onclick:function(){main.fetch({prev:true,bypassPause:true});} },[createElement("img",{src:imgs.feeds})])]),
])
])
, wmConsole.feedNode.parentNode);
//restore saved sort order
if (!isChrome) selectDropDownElement($("wmSortBy"),quickOpts.sortBy);
//$("wmPageViewSelector").selectedIndex = (quickOpts.displayMode||0);
var cn = wmConsole.feedNode.className;
wmConsole.feedNode.className = (quickOpts.displayMode=="1" || quickOpts.displayMode=="3")?cn.addWord("short"):cn.removeWord("short");
}
wmConsole.initialized = true;
//give sidekicks time to dock
if (params["callback"]||null) {
var fx = params["callback"];
delete params["callback"];
doAction(fx);
}
}catch(e){log("wmConsole.init: "+e);}},
selectFilter: function(){
if (this.className.containsWord("selected") ) return;
var tabs=this.parentNode.childNodes;
if (tabs.length) for (var t=0,tab;(tab=tabs[t]);t++) tab.className=tab.className.removeWord("selected");
this.className=this.className.addWord("selected");
quickOpts["filterApp"]=this.id.split("_feed")[1];
main.saveQuickOpts();
main.redrawPosts();
}
};
//***************************************************************************************************************************************
//***** Sidekick Docking Object
//***************************************************************************************************************************************
var Dock = {
//restructure menu to append appID before every object
fixMenu: function(menu,app){try{
var ret={};
//for each object in menu
for (var o in menu){
//main.message(o);
ret[app+o]=menu[o];
//fix button functions and arrays to be prepended by the appID of that sidekick
var t=menu[o]["type"];
switch(t){
case "button_highlight":
case "button_selectmulti":
case "button_selectprefix":
//fix elements in the clearfirst array
if (menu[o]["clearfirst"]){
for (var i=0,len=ret[app+o]["clearfirst"].length;i<len;i++){
ret[app+o]["clearfirst"][i] = app+ret[app+o]["clearfirst"][i];
}
}
//fix elements in the options array
if (menu[o]["options"]){
for (var i=0,len=ret[app+o]["options"].length;i<len;i++){
ret[app+o]["options"][i] = app+ret[app+o]["options"][i];
}
}
if (menu[o]["clearPrefix"]){
ret[app+o]["clearPrefix"]=app+ret[app+o]["clearPrefix"];
}
if (menu[o]["prefix"]){
ret[app+o]["prefix"]=app+ret[app+o]["prefix"];
}
}
//fix kids
if (menu[o]["kids"]){
//rebuild kids object
ret[app+o]["kids"]=Dock.fixMenu(menu[o]["kids"],app);
}
}
return ret;
} catch(e) {log("Dock.fixMenu: "+e);}},
//restructure tests to append appID before every object's return
fixTests: function(arr,app){try{
//for each test in array
for (var t=0,len=arr.length;t<len;t++) {
var ret=arr[t].ret, kids=arr[t].kids;
//replace return value
if (ret) {
if (ret!="exclude" && ret!="none") {
arr[t].ret=app.appID+ret;
}
}
//process subtests
if (kids) Dock.fixTests(kids,app);
}
} catch(e) {log("Dock.fixTests: "+e);}},
fixAcceptTexts:function(app){try{
var newAccText={};
for (var s in app.accText) {
newAccText[app.appID+s]=app.accText[s];
}
app.accText=newAccText;
} catch(e) {log("Dock.fixAcceptTexts: "+e);}},
addMenuElements:function(app){try{
//add various WM based options for this app
GM_config.settings["section_dynamicopts"]["kids"]["enableDynamic"]["kids"]["dynamic"+app.appID]=checkBox(app.name+" ("+app.appID+")",true);
GM_config.settings["section_filters"]["kids"]["dontstealBlock"]["kids"][app.appID+"dontsteal"]=checkBox(app.name);
GM_config.settings["section_filters"]["kids"]["filterapps"]["kids"]["hide"+app.appID]=checkBox(app.name);
GM_config.settings["section_basicopts"]["kids"]["blockautolikebygame"]["kids"]["nolike"+app.appID]=checkBox(app.name);
var testms=quickOpts["masterSwitch"][app.appID];
quickOpts.masterSwitch[app.appID]=(testms==null||testms=="undefined")?true:testms;
} catch(e) {log("Dock.addMenuElements: "+e);}},
addSidekickElement:function(app){try{
//create an entry for the sidekick on the wmConsole
var sidekickNode = wmConsole.sidekickNode || $("wmSidekickList");
if (sidekickNode) {
sidekickNode.appendChild(
createElement("div",{className:"wmSidekickEntry"+((quickOpts.masterSwitch[app.appID]||false)?"":" disabled")},[
createElement("img",{className:"icon crisp",src:(app.icon||imgs.plugin)}),
createElement("span",{className:"title",textContent:app.name}),
createElement("span",{className:"desc",textContent:(app.desc||"no description")}),
createElement("a",{id:"master_"+app.appID,className:"master consoleButton right",href:jsVoid,textContent:((quickOpts.masterSwitch[app.appID]||false)?"Disable":"Enable"),onclick:main.toggleSidekick}),
])
);
} else {
log("wmconsole sidekicknode is null");
}
} catch(e) {log("Dock.addSidekickElement: "+e);}},
addConsoleElement:function(app){try{
//create game filter buttons on the wmConsole
var coolBar = $("wmCoolItem_feedAll").parentNode;
if (coolBar) {
var title=(app.name||"");
var icon=(app.icon||null);
var node = coolBar.appendChild(
forms.createCoolBarButton({id:"feed"+app.appID,title:title,icon:icon,func:wmConsole.selectFilter,selected:(quickOpts.filterApp==app.appID)})
);
//add accept/fail counters
app.failCount=0;
app.acceptCount=0;
if (node) node.appendChild(
createElement("div",{className:"accFailBlock"},[
createElement("span",{className:"fail",textContent:"0"}),
createElement("span",{className:"accept",textContent:"0"}),
])
);
var btnCount = coolBar.childNodes.length;
coolBar.style.width=(btnCount*64)+"px";
coolBar.parentNode.className = coolBar.parentNode.className.addWord("scrollX");
}
} catch(e) {log("Dock.addConsoleElement: "+e);}},
answerDockingDoor: function(){try {
log("Sidekick requesting to dock");
//get all sidekicks that left info on the dock;
forNodes(".//div[@id='wmDock']/div[(@data-ft) and not(@data-ft='')]",{},function(newNote){
if (newNote){
var val = newNote.getAttribute('data-ft');
var newset = JSON.parse(val);
//save it into the NEW format for games
var game=(apps[newset.appID]=new App(newset));
//append the appID in front of every menu and test element id
game.menu=Dock.fixMenu(game.menu,game.appID);
Dock.fixTests(game.tests,game);
Dock.fixAcceptTexts(game);
Dock.addMenuElements(game);
Dock.addSidekickElement(game);
Dock.addConsoleElement(game);
//add similar options for grouped apps
var filters=(newset.addFilters||[]);
for (var f=0,filt;(filt=filters[f]);f++) {
Dock.addMenuElements(filt);
Dock.addSidekickElement(filt);
Dock.addConsoleElement(filt);
//create a new App for each sub-app and link parent and child pointers
filt.parent=game; //point to parent game
(game.kids=(game.kids||[])).push(apps[filt.appID]=new App(filt));
}
//add synonym appID's for side games, avoiding already created filters
var synID=newset["synAppID"]||null;
if (synID) for (var s=0;s<synID.length;s++) if (!apps[synID[s]]) {
(game.kids=(game.kids||[])).push(apps[synID[s]]=new App({appID:synID[s],parent:game}));
}
//add menu items
GM_config.append(game.menu);
main.updateSettingsValues();
//detach the menu from the newset to reduce duplication
delete game.menu;
//erase the door note so we dont add it again later
newNote.setAttribute('data-ft','');
return;
}
});
} catch(e) {log("Dock.answerDockingDoor: "+e);}},
};
log("Script: WM initialized",{level:0});
//***************************************************************************************************************************************
//***** Sidekick Object
//***************************************************************************************************************************************
var Collector = {
tabs : {}, //container for window objects
recycle : [], //container for reusable window objects
queue : [], //container for urls to do in order
count : 0,
//requires id, url and callback
open : function(params) {try{
params.msg=status.print("Collecting...",{});
//log("Collector.open()",{level:0});
//check for tab queueing
if (opts.queuetabs && Collector.count) {
//toss the next action in the queue while we wait for the current one to finish
Collector.queue.push(params);
//log("Collector.open: request queued",{level:1});
return;
}
var url = params.url;
var id = params.id;
//create a window or use a recycled one
var tabHwnd;
if (Collector.recycle.length) {
tabHwnd = Collector.recycle.shift();
tabHwnd.location.href=url;
//log("Collector.open: window reused",{level:1});
} else {
tabHwnd = open(url,"_blank");
//log("Collector.open: new window created",{level:1});
}
//window opening
if (tabHwnd) {
Collector.count++;
params.hwnd=tabHwnd; //store the window handle
params.openTime=timeStamp();
Collector.tabs[id]=params; //add the tab and all its data to the array
var callback = params.callback;
if (callback) {
delete params.callback;
//log("Collector.open: callback fired",{level:3});
doAction(function(){
remove($(params.msg));
callback(params);
});
}
} else {
log("Collector: Tab or Window is not opening or your browser does not support controlling tabs and windows via scripts.",{level:5});
}
}catch(e){log("Collector.open: "+e);}},
doNext : function(){try{Collector.open(Collector.queue.shift());}catch(e){log("Collector.doNext: "+e);}},
close : function(tab) {try{
//recycle or close the passed tab
try{
if (opts.recycletabsall || opts.queuetabs || (Collector.recycle.length < opts.recycletabs)) {
//wipe it and put it away
tab.hwnd.location.hash="";
tab.hwnd.location.href="about:blank";
Collector.recycle.push(tab.hwnd);
} else {
if (tab.hwnd) tab.hwnd.close();
}
tab.hwnd=null;
} catch (e){log("Collector.close: close or recycle: "+e);}
delete tab;
Collector.count--
//check for items in queue to do next
if (Collector.queue.length) {
//check that queueing is still in practice
if (opts.queuetabs) {
setTimeout(Collector.doNext,1000); //just do one
} else {
//options have changed since queueing was enacted, release all the queue into windows right now
var offset=1000;
while (Collector.queue.length && (Collector.count < opts.maxrequests)) {
setTimeout(Collector.doNext,offset); //open all, up to the limit set in options
offset+=100;
}
}
}
} catch (e){log("Collector.close: "+e);}},
closeAll : function() {try{
//first delete the queue so close fx doesnt pick them up
Collector.queue=[]; //empty but dont destroy
//then close the active windows, moving any to the recycler if that is enabled
for (var t in Collector.tabs) {
Collector.close(Collector.tabs[t]);
}
//then close any recycled windows
if (Collector.recycle.length) {
for (var r=0, hwnd; r < Collector.recycle.length; r++) {
if (hwnd=Collector.recycle[r]) {
hwnd.close();
}
}
Collector.recycle=[];
}
} catch (e){log("Collector.closeAll: "+e);}},
};
//***************************************************************************************************************************************
//***** New Prioritizer Object
//***************************************************************************************************************************************
//enums
var PRIORITY_DESTROY_RULE = 0;
var PRIORITY_PAUSE_TYPE = 1;
var PRIORITY_UNCHECK_TYPE = 2;
var PRIORITY_PAUSE_APPID = 3;
var PRIORITY_REFRESH_BROWSER = 4;
var PRIORITY_PAUSE_ALL = 5;
var Priority = {
opts:{},
init:function(params){
params=(params||{});
Priority.opts = getOptJSON("priorityOpts_"+profile)||{};
//import rules
rules={};
var rulesIn=getOptJSON("priority_"+profile)||{};
for (var r in rulesIn){
var rule=new Rule(rulesIn[r]);
rules[rule.id]=rule;
}
},
};
//***************************************************************************************************************************************
//***** New Dynamic Grabber Object
//***************************************************************************************************************************************
var Grabber = {
treeview:null, //container for treeview object
tests:[],
opts:{},
methods:["msg","fromID","fromName","url","body","html","targetID","targetName","caption","title","desc","comments",
"commentorID","commentorName","likeName","likeID","link","either","img","canvas"],
init:function(params){try{
params=(params||{});
Grabber.opts=getOptJSON("dynamicOpts_"+profile)||{};
//get current tests or try to upgrade from older WM
var testString=(getOpt("dynamics_"+profile)||""), failed;
if (testString=="") {//never used dynamics before
log("Grabber.init: Dynamics never used before");
setOpt("dynamics_"+profile, "[{}]");
}
else if (testString.startsWith("[")) { //already stored in an array
if (testString.startsWith("[{")) {//should be ok from here
try{
var test=JSON.parse(testString);
failed=((test==null) || ((typeof test)!="object"));
} catch (e) {
failed=true;
}
}
else if (testString=="[]"){ //no tests exist, add a default test
log("Grabber.init: No initial dynamic test...add one");
setOpt("dynamics_"+profile, "[{}]");
}
else failed=true; //format not correct
}
else if (testString.startsWith("{")) { //already stored in an object
try{
var test=JSON.parse("["+testString+"]");
failed=((test==null) || ((typeof test)!="object"));
if (!failed) {
log("Grabber.init: Upgraded");
setOptJSON("dynamics_"+profile, test); //upgrade
}
} catch (e) {
failed=true;
}
}
else failed=true; //format not correct
if (failed) {
if (confirm("I Cannot convert your dynamic tests to objects. I need to discard your tests to procede.")) {
} else {
alert("OK, but I cannot run your current tests. I will store them for you in the about:config under \".dynamicBackup\" and give you a fresh grabber console.");
setOpt("dynamicBackup_"+profile, testString);
}
setOpt("dynamics_"+profile, "[{}]");
}
Grabber.tests = getOptJSON("dynamics_"+profile) || [{}];
}catch(e){log("Grabber.init: "+e);}},
save:function(){try{
setOptJSON("dynamics_"+profile,Grabber.tests);
setOptJSON("dynamicOpts_"+profile,Grabber.opts);
}catch(e){log("Grabber.save: "+e);}},
add:function(){try{
var test={enabled:true};
Grabber.tests.push(test);
Grabber.save();
return test;
}catch(e){log("Grabber.add: "+e);}},
//get the test object with id starting at optional node or at top level
//may return null
getTest:function(id,node){try{
var nodes=(node||Grabber.tests);
for (var i=0,len=nodes.length;i<len;i++){
if (nodes[i]["id"]==id) {
return nodes[i];
} else if (nodes[i]["kids"]) {
var ret = Grabber.getTest(id,nodes[i]["kids"]);
if (ret) return ret;
}
}
}catch(e){log("Grabber.getTest: "+e);}},
};
//***************************************************************************************************************************************
//***** Feed Object
//***************************************************************************************************************************************
//feed object type
var Feed = function(){try{
params=params||{};
//set defaults
this.enabled=true;
//use passed params
for (var p in params) this[p]=params[p];
this.enable=function(){try{this.enabled=true;}catch(e){log("Feed.enable: "+e);}};
this.disable=function(){try{this.enabled=false;}catch(e){log("Feed.disable: "+e);}};
this.toggle=function(){try{if(this.enabled)this.disable(); else this.enable();}catch(e){log("Feed.toggle: "+e);}};
}catch(e){log("Feed.init: "+e);}};
//***************************************************************************************************************************************
//***** Priority/Rule Object
//***************************************************************************************************************************************
//priority onLimit actions
var priorityActions = new Enum("DESTROY_RULE","PAUSE_TYPE","UNCHECK_TYPE","PAUSE_APPID","REFRESH_BROWSER","PAUSE_ALL");
//priority object type
var Rule = function(params){try{
params=params||{};
//set defaults
this.enabled=true;
this.limitCount=0; this.limit=0;
this.level=50; this.appID=null; this.bonus=null;
//use passed params
for (var p in params) this[p]=params[p];
this.id=this.id||unique();
this.enable=function(){try{
this.enabled=true;
this.node.className=this.node.className.removeWord("disabled");
main.saverules();
}catch(e){log("Rule.enable: "+e);}};
this.disable=function(){try{
this.enabled=false;
this.node.className=this.node.className.addWord("disabled");
main.saveRules();
}catch(e){log("Rule.disable: "+e);}};
this.toggle=function(){try{
if(this.enabled)this.disable(); else this.enable();
}catch(e){log("Rule.toggle: "+e);}};
this.resetLimit=function(){try{
this.limitCount=0;
this.limitCounterNode.textContent=this.limitCount;
main.saveRules();
}catch(e){log("Feed.resetLimit: "+e);}};
this.incrementLimitCounter=function(){try{
this.limitCount++;
this.limitCounterNode.textContent=this.limitCount;
main.saveRules();
}catch(e){log("Feed.incrementLimitCounter: "+e);}};
this.remove=function(){try{
remove(this.node);
delete rules[this.id];
main.saveRules();
}catch(e){log("Feed.remove: "+e);}};
this.populateBonusList=function(){try{
var node=this.bonusDropDown;
var bonuses=[];
//get the list of accept texts for this app
if (this.appID!="") bonuses = apps[this.appID].accText;
bonuses["dynamic"]="* Dynamic: Just Grab It";
bonuses["none"]="* None: Break Identification Circuit";
bonuses["wishlist"]="* Flag as Wishlist";
bonuses["exclude"]="* Exclude: Prevent Collection";
bonuses["send"]="* Send Unknown";
bonuses["doUnknown"]="* Get Unknown";
//add each element to the dropdown
var elem;
node.innerHTML=""; //wipe previous list
for (var i in bonuses) {
var showI=i.removePrefix(this.appID);
node.appendChild(elem=createElement("option",{textContent:((bonuses[i].substring(0,1)=="*")?"":((showI.startsWith("send"))?"Send ":"Get "))+bonuses[i], value:showI}));
if (this.bonus== showI) elem.selected = true;
}
}catch(e){log("Rule.populateBonusList: "+e);}};
//draw to priority/rule manager
var rule=this;
try{$("wmPriorityBuilder").insertBefore(
this.node=createElement("div",{className:"listItem"+((!this.enabled)?" disabled":"")},[
createElement("label",{textContent:"appID:"}),
this.appDropDown=createElement("select",{className:"selectAppID",onchange:function(){rule.appID=this.value; rule.populateBonusList(); main.saveRules();}},main.getAppDropDownList(this.appID)),
createElement("label",{textContent:"Bonus:"}),
this.bonusDropDown=createElement("select",{className:"selectBonus",onchange:function(){rule.bonus=this.value; main.saveRules();}},main.getBonusDropDownList({appID:params.appID,selected:params.bonus,dropID:true})),
createElement("br"),
createElement("label",{textContent:"Priority:"}),
this.levelDropDown=createElement("select",{className:"selectPriority",onchange:function(){rule.level=parseInt(this.value); main.saveRules();}},(function(){
var optsret=[];
//create option values and names;
var ddopts = {};
for (var i=0;i<100;i++) {ddopts[i.toString()]=i.toString();}
ddopts["0"]="Top"; ddopts["50"]="Default"; ddopts["99"]="Bottom";
//add option values to list
for (var i in ddopts) {
var elem = createElement("option",{textContent:ddopts[i],value:i});
if ((this.level||null) == i) elem.selected=true;
optsret.push(elem);
}
return optsret;
})()),
createElement("label",{textContent:"Limit:"}),
this.limitCounterNode=createElement("span",{className:"accept",textContent:this.limitCount,title:"Current Counter"}),
this.limitDropDown=createElement("select",{className:"selectLimit",onchange:function(){rule.limit=this.value; main.saveRules();}},(function(){
var optsret=[];
//create option values and names;
var ddopts = {}; var lims=[-1,1,2,3,4,5,10,15,20,30,50];
for (var i=0;i<lims.length;i++) {ddopts[lims[i].toString()]=lims[i].toString();}
ddopts["-1"]="No Limit";
//add option values to list
for (var i in ddopts) {
var elem = createElement("option",{textContent:ddopts[i],value:i});
if ((this.limit||null) == i) elem.selected=true;
optsret.push(elem);
}
return optsret;
})()),
createElement("label",{textContent:"onLimit:"}),
this.taskDropDown=createElement("select",{className:"selectTask",onchange:function(){rule.onLimit=this.value; main.saveRules();}},(function(){
var optsret=[];
//create option values and names;
var ddopts = {"0":"Destroy Rule","1":"Pause Bonus","2":"Uncheck Bonus","3":"Pause AppID",
"4":"Refresh Browser","5":"Pause All"};
//add option values to list
for (var i in ddopts) {
var elem = createElement("option",{textContent:ddopts[i],value:i});
if ((this.onLimit||null) == i) elem.selected=true;
optsret.push(elem);
}
return optsret;
})()),
createElement("div",{className:"toolBox medium inline"},[
createElement("div",{},[
createElement("div",{className:"toolButton oddOrange"},[createElement("a",{title:"Delete Rule",href:jsVoid,onclick:function(){rule.remove();}},[createElement("img",{src:imgs.trash})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{title:"Reset Limit",href:jsVoid,onclick:function(){rule.resetLimit();}},[createElement("img",{src:imgs.refresh})])]),
createElement("div",{className:"toolButton oddBlack"},[createElement("a",{title:"Toggle",href:jsVoid,onclick:function(){rule.toggle();}},[createElement("img",{src:imgs.check})])]),
])
])
])
, $("wmPriorityBuilder").firstChild);}catch(e){log("Rule.init.drawRule: "+e);}
}catch(e){log("Rule.init: "+e);}};
//***************************************************************************************************************************************
//***** Group Object
//***************************************************************************************************************************************
//bonus group object type
var BonusGroup = function(){try{
params=params||{};
for (var p in params) this[p]=params[p];
}catch(e){log("BonusGroup.init: "+e);}};
//***************************************************************************************************************************************
//***** App Object
//***************************************************************************************************************************************
//app object type
var App = function(params){try{
//expected: id, name, namespace, icon
params=params||{};
//set defaults
this.enabled=true; this.failCount=0; this.acceptCount=0;
this.paused=false;
this.tests={};
//use passed params
for (var p in params) this[p]=params[p];
this.enable=function(){try{this.enabled=true;}catch(e){log("App.enable: "+e);}};
this.disable=function(){try{this.enabled=false;}catch(e){log("App.disable: "+e);}};
this.toggle=function(){try{if(this.enabled)this.disable(); else this.enable();}catch(e){log("App.toggle: "+e);}};
this.resetCounter=function(){try{
this.acceptCount=0; this.failCount=0;
this.updateCounters();
}catch(e){log("App.resetCounter: "+e);}};
this.updateCounters=function(){try{
var node = selectSingleNode(".//*[contains(@class,'accFailBlock')]/*[contains(@class,'fail')]",{node:$("wmCoolItem_feed"+this.appID)});
if (node) node.textContent=this.failCount;
node = selectSingleNode(".//*[contains(@class,'accFailBlock')]/*[contains(@class,'accept')]",{node:$("wmCoolItem_feed"+this.appID)});
if (node) node.textContent=this.acceptCount;
}catch(e){log("App.updateCounters: "+e);}}
this.fetchPosts=function(){try{
//request posts from facebook
}catch(e){log("App.fetchPosts: "+e);}}
this.pause=function(){try{this.paused=true;}catch(e){log("App.pause: "+e);}}
this.unPause=function(){try{this.paused=false;}catch(e){log("App.unPause: "+e);}}
//get a list of posts for this app from the global posts list
this.getPosts=function(){try{
return matchByParam(posts,"app",this,"object");
}catch(e){log("App.getPosts: "+e);}}
}catch(e){log("App.init: "+e);}};
//***************************************************************************************************************************************
//***** Post Object
//***************************************************************************************************************************************
//post binary flags
var postFlags = new EnumFlags("COLLECT","SCAM","FAILED","ACCEPTED","EXCLUDED","PAUSED","PINNED","LIKED","MYPOST","STALE","NODEF","WISHLIST","WORKING","TIMEOUT");
//post object type
var Post = function(params){try{
params=params||{};
//set defaults
this.status=0; this.state=""; this.flags=0;
this.node=null; //collector panel node
//use passed params
for (var p in params) this[p]=params[p];
//link to our application array of objects
var app=(this.app=apps[this.application.id]);
var synApp=app.parent||app;
//set another appID param specifically for sorting purposes
this.appID=app.appID;
this.appName=app.name;
//update the namespace parameter if it does not exist
if (!exists(app.namespace)) app.namespace=this.application.namespace;
//validate the application namespace for sidekicks that provide namespace checking
if (exists(app.namespace)) if (app.namespace!=this.application.namespace) {
this.flags=this.flags|postFlags.SCAM; //Graph API namespace does not match sidekick known namespace, flag as scam
}
//now drop the application object we got from FB
if (exists(this.application)) delete this.application;
//add some functions
this.identify=function(){try{
//set a timer on the post for delayed deletion
this.drawTime=timeStamp();
//set/reset priority, state, status & flags
this.priority=50;
this.status=0;
this.state="";
this.flags=0;
this.removeAllClasses();
if (this.node||null) this.node=null; //detach the node object
//avoid posts that belong to a disabled sidekick
if(!quickOpts.masterSwitch[app.appID]) {
//master switch is off
this.exclude();
return true;
}
//hide posts by apps that we specifically told to hide
if (opts["hide"+app.appID]) {this.remove(); return false;}
var whoPosted = (this.fromID=this.from.id);
var whoName = (this.fromName=this.from.name);
//convert a unix date to a readable date
this.realtime=(new Date((this.date()||0)*1000).toLocaleString());
//avoid potential scam posts
if (opts.scamblock) {
if ( !this.linkHref.startsWith("http://apps.facebook.com/"+app.namespace) && !this.linkHref.startsWith("https://apps.facebook.com/"+app.namespace) ){
this.flags |= (postFlags.SCAM | postFlags.EXCLUDED);
if (opts.hidescams) {this.remove(); return false;}
return true;
}
}
//avoid posts by self
if (whoPosted==userID){
this.exclude();
if (opts.hidemyposts) {this.remove(); return false;}
return true;
}
//avoid W2W posts not for me
var isForMe = this.getTargets().inArray(userID);
var isW2W = this.getTargets().length>0;
if (opts[app.appID+"dontsteal"] && isW2W && !isForMe){
this.exclude();
if (opts.hidenotforme) {this.remove(); return false;}
return true;
}
//avoid posts older than olderLimit
if (olderLimit!=0) {
if (this.isStale(olderLimit) && opts.skipstale) {
this.exclude();
if (opts.hidestale) {this.remove(); return false;}
return true;
}
}
//get bonus type
var w=(this.which = main.which(this));
//check for pause
if(typesPaused.inArray(w)) this.pause();
//check for excluded or unknown posts
if (w=="none" || w=="exclude") {
if (w=="exclude") {
this.exclude();
if (opts.hideexcluded) {this.remove(); return false;}
} else if (w=="none") {
this.flags |= postFlags.NODEF;
if (opts.pinundefined) this.pin();
}
return true;
} else {
//set identified text
this.idText=main.getAccText(synApp.appID,w);
if (w==synApp.appID+"doUnknown" || w==synApp.appID+"send") {
this.flags |= postFlags.NODEF;
if (opts.pinundefined) this.pin();
}
//check for priority
for (r in rules) {
var rule = rules[r];
if (rule.enabled && (rule.appID+rule.bonus) == w) {
//affected by this rule
this.priority=rule.level;
}
}
}
//avoid liked posts
if (this.getLikes().inArray(userID) && opts.skipliked){
if (opts.markliked) this.status=1; //mark liked as accepted
this.exclude();
if (opts.hideliked) {this.remove(); return false;}
return true;
}
//Check history
this.status=this.status||0;
if (exists(history[this.id])) {
//post previously processed
this.status=(history[this.id].status||0);
var gotItem=((this.status>0) || (this.status==-6) || (this.status==-4) || (this.status==-15 && opts.accepton15));
if (gotItem) this.flags |= postFlags.ACCEPTED;
else if (this.status<0) this.flags |= postFlags.FAILED;
if (opts.hideaccepted && gotItem) {this.remove(); return false;}
if (opts.hidefailed && this.status<0) {this.remove(); return false;}
return true;
}
//check if wanted
if ((w=="dynamic") || opts[w] || (w.startsWith((this.app.parent||this.app).appID+"send") && opts[(this.app.parent||this.app).appID+"sendall"]) ) {
//bonus type is wanted
this.collect();
return true;
}
//bonus type is unwanted
if (w.find("wishlist")) {
this.flags |= postFlags.WISHLIST;
if (opts.hideunwanted && !opts.donthidewishlists) {this.remove(); return false;}
}
if (opts.hideunwanted) {this.remove(); return false;}
return true;
}catch(e){log("Post.identify: "+e);}};
this.open=function(){try{
var post = this;
var id = post.id;
var app = this.app;
var synApp = app.parent||app;
//fix the link based on sidekick alterlink information
var alterLink=(synApp.alterLink||null);
var targetHref = post.linkHref();
var doAlterLink=(synApp.flags.alterLink||false);
if (doAlterLink && alterLink) {
//note that only find and replace functionality is available right now, no wildcards or array inserts will work
var find = (alterLink.find||"");
//check if user is wanting a regex or string replacement
if (alterLink.isRegex||false) find=new RegExp(find,"");
targetHref = targetHref.replace(find,(alterLink.replace||""));
//check for word specific changes
if ((alterLink.words||null) && (alterLink.conversionChart||null)){
var either = post.either().toLowerCase();
for (var w=0,len=alterLink.words.length; w<len; w++) {
var word=(alterLink.words[w]).toLowerCase();
if (either.contains(word)) {
//replace the word
targetHref=targetHref.replace("{%1}",alterLink.conversionChart[word.noSpaces()]);
break;
}
}
}
}
//fix the link, removing https and switching to http only
targetHref = targetHref.replace('https://','http://');
//open the bonus page in a new tab or the previously opened tab object to save memory
post.flags = ((post.flags | postFlags.WORKING) & (~postFlags.COLLECT));
post.fixClasses();
post.state="working";
main.requestsOpen++;
doAction(function(){Collector.open({url:targetHref,id:id,callback:main.onFrameLoad,post:post});});
}catch(e){log("Post.open: "+e);}};
this.forceOpen=function(){try{
var post=this;
post.flags |= postFlags.COLLECT;
post.flags &= ~(postFlags.FAILED | postFlags.TIMEOUT | postFlags.ACCEPTED);
post.fixClasses();
post.open();
}catch(e){log("Post.forceOpen: "+e);}};
this.like=function(){try{
var url=this.actionLink("Like");
setTimeout(function(){Collector.open({url:url+"#likeit",id:url,callback:main.onLikePost});},100);
}catch(e){log("Post.like: "+e);}};
this.draw=function(redraw){try{
var post=this;
var app=post.app, synApp=app.parent||app;
//if a filter exists check against filter
var filter=(quickOpts.filterApp||"All");
if (filter!="All" && filter!=app.appID) return; //dont show this post in this filter
//prefetch css words
var tags = " " + post.state;
for (var f in postFlags) if (post.flags & postFlags[f]) tags=tags.addWord(f.toLowerCase());
//disallow certain combinations
if (tags.containsWord("accepted") || tags.containsWord("failed")) tags=tags.removeWord("collect");
//create the layout
var layout=function(){
switch (quickOpts.displayMode||"0"){
case "0": //classic mode
var hideimage = (opts.hideimages || (opts.hideimagesunwanted && (post.which==="none" || post.which==="exclude") ) );
var placeholder=createElement("div");
return createElement("div",{id:"post_"+post.id,className:"wm post classic"+tags+((hideimage)?" noimage":""),title:((post.flags & postFlags.SCAM)?"Post is possible scam":"")},[
createElement("a",{className:"actor",textContent:post.from.name,href:"http://www.facebook.com/profile.php?id="+post.from.id}),
createElement("div",{className:"toolBox small inline"}),
(!hideimage)?createElement("a",{href:post.link,className:"picture"},[
createElement("img",{src:(post.picture||imgs.noimage)})
]):placeholder.cloneNode(true),
(!opts.hidebody)?createElement("div",{},(function(){
var ret = [];
ret.push(createElement("a",{className:"title",textContent:post.name,href:post.link}));
if (post.caption||null)ret.push(createElement("span",{className:"caption",textContent:post.caption}) );
if (post.description||null)ret.push(createElement("span",{className:"description",textContent:post.description}) );
return ret;
})() ):placeholder.cloneNode(true),
createElement("div",{style:"position:absolute; bottom:5px; left:100px; width:660px;"},[
(!opts.hidedate)?createElement("span",{className:"postDate",textContent:post.realtime}):placeholder.cloneNode(true),
(!opts.hidevia)?createElement("a",{className:"appName",textContent:" via "+app.name,href:"http://apps.facebook.com/"+app.namespace+"/",title:app.appID}):placeholder.cloneNode(true),
createElement("a",{className:"linkText"+((post.flags & postFlags.EXCLUDED)?" excluded":"")+(post.idText?" identified":""),textContent:((post.idText||null) && opts.debugrecog)?post.idText:post.linkText(),href:post.linkHref(),title:post.linkText()}),
]),
]);
placeholder=null;
break;
case "1": case "3": //short mode and priority mode
return createElement("div",{id:"post_"+post.id,className:"wm post short "+opts.thumbsize+tags,title:((post.flags & postFlags.SCAM)?"Post is possible scam":"")},[
createElement("a",{href:jsVoid,className:"picture",onclick:function(){post.forceOpen();}},[
createElement("img",{src:post.picture||imgs.noimage,onmousemove:main.moveFloater})
]),
createElement("div",{id:"floater_"+post.id,className:"floater "+opts.thumbsize},[
createElement("div",{className:"toolBox small inline"}),
createElement("a",{className:"actor",textContent:"From: "+post.from.name,href:"http://www.facebook.com/profile.php?id="+post.from.id}),
createElement("span",{className:"postDate",textContent:"Date: "+post.realtime}),
createElement("a",{className:"appName",textContent:"App: "+app.name,href:"http://apps.facebook.com/"+app.namespace+"/",title:app.appID}),
createElement("a",{className:"linkText"+((post.flags & postFlags.EXCLUDED)?" excluded":"")+(post.idText?" identified":""),textContent:"Action: "+(((post.idText||null) && opts.debugrecog)?post.idText:post.linkText()), href:post.linkHref(), title:post.linkText()}),
createElement("span",{className:"status",textContent:"Status: "+(post.status||"0")+ " " + (main.statusText[post.status||"0"])}),
]),
]);
break;
case "2": //dev mode
return createElement("div",{id:"post_"+post.id,className:"wm post dev"+tags,title:((post.flags & postFlags.SCAM)?"Post is possible scam":"")},[
createElement("a",{className:"postid",textContent:"postID: "+post.id, href:post.actionLink("Like"), target:"_blank"}),
createElement("span",{className:"actor",textContent:"fromName(fromID): "+post.from.name+"("+post.from.id+")"}),
createElement("div",{className:"toolBox small inline"}),
createElement("a",{href:post.link,className:"picture"},[
createElement("img",{src:post.picture||imgs.noimage})
]),
createElement("div",{},(function(){
var ret = [];
ret.push(createElement("span",{className:"title",textContent:"title: "+post.name}));
if (post.message||null)ret.push(createElement("span",{className:"msg",textContent:"msg: "+post.message}) );
if (post.caption||null)ret.push(createElement("span",{className:"caption",textContent:"caption: "+post.caption}) );
if (post.description||null)ret.push(createElement("span",{className:"description",textContent:"desc: "+post.description}) );
ret.push(createElement("span",{className:"imgsrc",textContent:"img: "+(post.picture||"")}));
ret.push(createElement("span",{className:"postDate",textContent:post.realtime}));
ret.push(createElement("span",{className:"appName",textContent:" via appName: "+app.name+"(appID: "+app.appID+", canvas: "+app.namespace+")"}));
ret.push(createElement("a",{className:"url",textContent:"url: "+post.link,href:post.link}) );
//show likes
if (post.likes||null){
if (post.likes.data||null){
ret.push(createElement("div",{className:"likes"},(function(){
var data=post.likes.data;
var retData=[];
for(var d=0,lenL=data.length; d<lenL; d++){
retData.push(createElement("span",{className:"likeElement",textContent:"likeName(likeID):"+data[d].name+"("+data[d].id+")"}));
}
return retData;
})()));
}
}
//show comments
if (post.comments||null){
if (post.comments.data||null){
ret.push(createElement("div",{className:"comments"},(function(){
var data=post.comments.data;
var retData=[];
for(var d=0,lenC=data.length; d<lenC; d++){
retData.push(createElement("span",{className:"commentElement",textContent:"commentorName(commentorID): "+data[d].from.name+"("+data[d].from.id+")"}));
retData.push(createElement("span",{className:"commentComment",textContent:"comments: "+data[d].message}));
}
return retData;
})()));
}
}
return ret;
})() ),
createElement("div",{style:"position:absolute; bottom:5px; left:100px; width:660px;"},[
createElement("a",{className:"linkText",textContent:("identified linkText: "+post.idText+" (which: "+post.which+")")+" || "+("original linkText: "+post.linkText()), href:post.linkHref(),title:post.linkText()}),
]),
]);
break;
}
}();
//store the DOM object
post.node=layout;
//determine draw location
var sibling=(redraw)?null:post.nextSibling();
if (sibling||null) wmConsole.feedNode.insertBefore(layout, sibling.node);
else wmConsole.feedNode.appendChild(layout);
main.addToolBox(post);
}catch(e){log("Post.draw: "+e);}};
this.openSource=function(){try{
var url=this.actionLink("Like");
open(url,"_blank");
}catch(e){log("Post.openSource: "+e);}};
this.addClass=function(s){try{
if (this.node){
this.node.className=this.node.className.addWord(s);
}
}catch(e){log("Post.addWord: "+e);}};
this.removeAllClasses=function(){try{
for (var c in postFlags) this.removeClass(c);
}catch(e){log("Post.removeAllClasses: "+e);}};
this.removeClass=function(s){try{
if (this.node){
this.node.className=this.node.className.removeWord(s);
}
}catch(e){log("Post.removeWord: "+e);}};
this.pause=function(){try{
this.flags |= postFlags.PAUSED;
this.addClass("paused");
}catch(e){log("Post.pause: "+e);}};
this.unPause=function(){try{
this.flags &= ~postFlags.PAUSED;
this.removeClass("paused");
}catch(e){log("Post.unPause: "+e);}};
this.exclude=function(){try{
this.flags |= postFlags.EXCLUDED;
this.addClass("excluded");
}catch(e){log("Post.exclude: "+e);}};
this.collect=function(){try{
this.flags |= postFlags.COLLECT;
this.addClass("collect");
}catch(e){log("Post.collect: "+e);}};
this.stopCollect=function(){try{
this.flags &= ~postFlags.COLLECT;
this.removeClass("collect");
}catch(e){log("Post.collect: "+e);}};
this.togglePin=function(){try{
if (this.flags & postFlags.PINNED) this.unPin(); else this.pin();
}catch(e){log("Post.togglePin: "+e);}};
this.pin=function(){try{
this.flags |= postFlags.PINNED;
this.addClass("pinned");
if (this.node||null) {
var btn=selectSingleNode(".//div[contains(@class,'toolButton')]//a[contains(@title,'Pin')]/img",{node:this.node});
if (btn) btn.className=btn.className.addWord("rotateRight");
}
}catch(e){log("Post.pin: "+e);}};
this.unPin=function(){try{
this.flags &= ~postFlags.PINNED;
this.removeClass("pinned");
if (this.node||null) {
var btn=selectSingleNode(".//div[contains(@class,'toolButton')]//a[contains(@title,'Pin')]/img",{node:this.node});
if (btn) btn.className=btn.className.removeWord("rotateRight");
}
}catch(e){log("Post.unPin: "+e);}};
this.fixClasses=function(){try{
//"COLLECT","SCAM","FAILED","ACCEPTED","EXCLUDED","PAUSED","PINNED","LIKED","MYPOST","STALE","NODEF","WISHLIST","WORKING","TIMEOUT"
for (var f in postFlags) if (postFlags[f] & this.flags) this.addClass(f.toLowerCase()); else this.removeClass(f.toLowerCase());
}catch(e){log("Post.fixClasses: "+e);}};
this.accept=function(mark){try{
this.flags |= postFlags.ACCEPTED;
this.flags &= ~(postFlags.FAILED | postFlags.WORKING | postFlags.COLLECT | postFlags.TIMEOUT);
this.fixClasses();
if (mark) main.setAsAccepted(null, 3,this);
}catch(e){log("Post.accept: "+e);}};
this.fail=function(mark){try{
this.flags |= postFlags.FAILED;
this.flags &= ~(postFlags.ACCEPTED | postFlags.WORKING | postFlags.COLLECT | postFlags.TIMEOUT);
this.fixClasses();
if (mark) main.setAsFailed(null, -18,this);
}catch(e){log("Post.fail: "+e);}};
this.timeout=function(){try{
this.flags |= postFlags.TIMEOUT;
this.flags &= ~(postFlags.FAILED | postFlags.WORKING | postFlags.ACCEPTED);
this.fixClasses();
}catch(e){log("Post.timeout: "+e);}};
this.remove=function(){try{
var node=(this.node||$("post_"+this.id));
if (node) if (node.parentNode||null) remove(node);
this.node=null;
delete posts[this.id];
}catch(e){log("Post.remove: "+e);}};
this.linkText=function(){try{
if (this.actions.length >=3) return this.actions.last().name||"";
else return "";
}catch(e){log("Post.linkText: "+e);}};
this.linkHref=function(){try{
return this.link||((this.actions.length>=3)?(this.actions.last().link||""):"")||"";
if (this.actions.length >=3) return this.actions.last().link||"";
else return this.link||"";
}catch(e){log("Post.linkHref: "+e);}};
this.actionLink=function(action){try{
for (var a=0,act;(act=this.actions[a]);a++) if (act.name.toLowerCase()==action.toLowerCase()) {return act.link; break;}
}catch(e){log("Post.actionLink: "+e);}};
this.body=function(){try{
return (this.title||"")+" "+(this.caption||"")+" "+(this.description||"");
}catch(e){log("Post.body: "+e);}};
this.either=function(){try{
return this.linkText()+" "+this.body();
}catch(e){log("Post.either: "+e);}};
this.date=function(){try{
return this["created_time"];
}catch(e){log("Post.date: "+e);}};
this.isStale=function(timeOverride) {try{
if (exists(timeOverride)) if(timeOverride==0) return false;
var now = timeStamp();
var pubTime = this.date()+"000";
var aDay = (1000 * 60 * 60 * 24);
return (now-pubTime)>(timeOverride||aDay);
}catch(e){log("Post.isStale: "+e);}};
//req must equal "id" or "name"
this.getTargets=function(req){try{
req = req||"id";
var ret = [];
if (exists(this.to)) {
for (var i=0,target; (target=this.to.data[i]);i++) ret.push(target[req]);
}
return ret;
}catch(e){log("Post.getTargets: "+e);}};
//ret must equal "id" or "message" or "name" or "count"
this.getComments=function(req){try{
var ret = [];
if (exists(this.comments)) if (this.comments.count) {
switch(req){
case "message": for (var i=0,comment; (comment=this.comments.data[i]);i++) ret.push(comment[req]); break;
case "id":case "name": for (var i=0,comment; (comment=this.comments.data[i]);i++) ret.push(comment.from[req]); break;
case "count": return this.comments.count; break;
}
}
return ret;
}catch(e){log("Post.getComments: "+e);}};
//ret must equal "id" or "name" or "count"
this.getLikes=function(req){try{
req = req||"id";
var ret = [];
if (exists(this.likes)) if (this.likes.count) {
switch(req){
case "id":case "name": for (var i=0,like; (like=this.likes.data[i]); i++) ret.push(like[req]); break;
case "count": return this.likes.count; break;
}
}
return ret;
}catch(e){log("Post.getLikes: "+e);}};
this.moveToTop = function(){try{
if (this.node||null) this.node.parentNode.insertBefore(this.node,this.node.parentNode.childNodes[0]);
}catch(e){log("Post.moveToTop: "+e);}};
this.moveToBottom = function(){try{
if (this.node||null) this.node.parentNode.appendChild(this.node);
}catch(e){log("Post.moveToBottom: "+e);}};
this.reID = function(){try{
if (this.node||null) {
//remember its location
var sibling=this.node.nextSibling; // else its on the bottom of the list
//drop from display
remove(this.node);
}
//reidentify and redraw
if (this.identify()) this.draw();
//if it redraws, its still good
if (this.node) {
//move it to where it was before
if (sibling) sibling.parentNode.insertBefore(this.node,sibling);
else this.node.parentNode.appendChild(this.node);
}
}catch(e){log("Post.reID: "+e);}};
//return the next visible sibling post
this.nextSibling = function(){try{
//determine if there is a filter
var filter=(quickOpts.filterApp||"All");
//get visible posts
var visiblePosts=(filter=="All")?posts:matchByParam(posts,"appID",filter);
//search for the current post
var found=false, sibling=null;
for (var p in visiblePosts) {
if (found) {sibling=visiblePosts[p]; break}
else if (visiblePosts[p]==this) found=true;
}
//return what is found
return sibling;
}catch(e){log("Post.nextSibling: "+e);}};
//return the previous visible sibling post
this.previousSibling = function(){try{
//determine if there is a filter
var filter=(quickOpts.filterApp||"All");
//get visible posts
var visiblePosts=(filter=="All")?posts:matchByParam(posts,"appID",filter);
//search for the current post
var sibling=null;
for (var p in visiblePosts) {
if (visiblePosts[p]==this) break;
else sibling=visiblePosts[p];
}
//return what is found
return sibling;
}catch(e){log("Post.previousSibling: "+e);}};
}catch(e){log("Post.init: "+e);}};
//***************************************************************************************************************************************
//***** Main Object
//***************************************************************************************************************************************
var main = {
paused : false,
fetchPaused : false,
requestsOpen : 0,
reqTO : 30000,
accDefaultText : "Got this!",
failText : "Oh no! Sorry pardner!",
overLimitText : "Limit reached!",
statusText : {
"20":"Sidekick returned force accept",
"3":"Marked as accepted by user",
"2":"Responseless Collection",
"1":"Accepted",
"0":"Unknown",
"-1":"Failed",
"-2":"None Left",
"-3":"Over Limit",
"-4":"Over Limit, Sent One Anyway",
"-5":"Server Error",
"-6":"Already Got",
"-7":"Server Down For Repairs",
"-8":"Problem Getting Passback Link",
"-9":"Final Request Returned Null Page",
"-10":"Final Request Failure",
"-11":"Expired",
"-12":"Not a Neighbor",
"-13":"Requirements not met",
"-14":"Timeout",
"-15":"Unrecognized Response",
"-16":"Passback Link is missing",
"-17":"Window Missing",
"-18":"Marked as failed by user",
"-20":"Sidekick returned force fail",
},
pauseCollecting : function(){
var isPaused=(main.paused = !main.paused);
var btn=$("wmpausecollect");
btn.parentNode.className = (isPaused)?btn.parentNode.className.replaceWord("oddOrange","oddGreen"):btn.parentNode.className.replaceWord("oddGreen","oddOrange");
btn.childNodes[0].src = (isPaused)?imgs.play:imgs.stop;
btn.title = (isPaused)?"Collect":"Pause Automatic Collection";
},
pauseFetching : function(){
var isPaused=(main.fetchPaused = !main.fetchPaused);
var btn=$("wmpausefetch");
btn.parentNode.className = (isPaused)?btn.parentNode.className.replaceWord("oddOrange","oddGreen"):btn.parentNode.className.replaceWord("oddGreen","oddOrange");
btn.title = (isPaused)?"Fetch":"Pause Automatic Fetching";
},
sortPosts : function(params){
params=params||{};
params.direction=(quickOpts.sortDirection=(params.direction||quickOpts.sortDirection||"desc")); //default descending to keep time ordered posts in order newest to oldest
params.by=(quickOpts.sortBy=(params.by||quickOpts.sortBy||"created_time")); //default by date
main.saveQuickOpts();
//convert to array
var postsArray=methodsToArray(posts);
//sort
postsArray.sort(function(a,b){
if (["ascending","asc"].inArray(params.direction.toLowerCase())) return a[params.by]>b[params.by];
if (["descending","desc"].inArray(params.direction.toLowerCase())) return a[params.by]<b[params.by];
});
//convert back to object
posts=arrayToMethods(postsArray);
},
doWhichTestTree : function(post, testList, testData, custom) {try{
//match post to an app
var app=post.app;
var synApp=(app.parent||app), w=null;
for (var i=0,test;((test=testList[i]) && (w===null));i++) {
//finish constructing dynamic collection tests
var ret = test.ret;
if (custom) {
if (!ret) ret = "dynamic"; //default to dynamic
if (ret!="dynamic" && ret!="none" && ret!="exclude") ret=synApp.appID+ret; //add appID except to magic words
}
//part to make dynamic collection tests work only if they are the correct appID
//also do not process disabled tests
if (!test.disabled && (!custom || (custom && (!test.appID || (app.appID==test.appID))))){
//if the test is not a dynamic grabber test
//OR if the test IS a dynamic test and the appID matches
//OR if the test IS a dynamic test and no appID was supplied
//then run the test
//detect test type
var testType=(test.search||null);
var types=Grabber.methods;
if (!testType) for (var tt=0,len=types.length; tt<len; tt++) {if (test[types[tt]]||"") {testType=types[tt];break;}}
//select the type of data to use
var src;
if (isArray(testType)){ //new search array format
for (var t=0,tlen=testType.length;t<tlen;t++) src+=(testData[testType[t]]||"");
}
else src = (testData[testType]||""); //old test method like testType:text
if (src){
//begin processing this test
var subTests=test.subTests, kids=test.kids, allowNone=false, subNumRange=test.subNumRange,text=(test.find||test[testType]||"");
//process subtests array
if (subTests && text) {
for (var i2=0,subTest,found=false;((subTest=subTests[i2]) && (!found));i2++) {
var testX = text.replace('{%1}',subTest).toLowerCase();
//do a standard test with the replaced search string
found=src.find(testX);
//return a found value, replacing %1 with a lowercase no-space text equal to the subtest string
w=(found)?ret.replace('{%1}',subTest.noSpaces().toLowerCase()):w;
testX=null;
}
//process number array
} else if (subNumRange && text){
var start=parseInt(subNumRange.split(",")[0]), end=parseInt(subNumRange.split(",")[1]);
for (var i2=start,found=false;((!found) && i2<=end);i2++) {
var testX = text.replace('{%1}',i2).toLowerCase();
//do a standard test with the replaced search string
found=src.find(testX);
//return a found value, replacing %1 with a lowercase no-space text equal to the subtest string
w=(found)?ret.replace('{%1}',i2):w;
testX=null;
}
//process text array, process similar to subtests
} else if (text && (isArray(text))) {
for (var i2=0,subTest,found=false;((subTest=text[i2]) && (!found));i2++) {
var testX = subTest.toLowerCase();
//do a standard test with the replaced search string
found=src.find(testX);
//return the same value no matter which element from the array is found
w=(found)?ret:w;
testX=null;
}
//process regex
} else if (text && (test.regex||test.isRegex||null) ) {
var mods = (test.mods||"gi");
var testRegex = new RegExp(text,mods);
var match=src.match(testRegex);
if (match) match=match[0]; //always take the first match
w=ret||match||w;
//process single text
} else if (text) {
try{
w=(src.find(text.toLowerCase() ))?ret:w;
} catch(e){
log("main.doWhichTestTree:"+e);
log("--app:"+app.appID);
log("--test:"+JSON.stringify(test));
}
}
}//end src exists
//see if test has type 2 subtests (child node tests based on parent test)
w = ((kids && w)?main.doWhichTestTree(post, kids, testData, custom):w) || w; //if kids return null, default to key found above
//if this test tree returned "none", start over with next tree by replacing "none" with null
//true "none" is handled in the which() function below
if (w==="none") w=null;
}//end custom checker
}
return w;
}catch(e){log("main.doWhichTestTree: "+e);}},
which : function(post) {try{
//match post to an app
var w, app=post.app, synApp=(app.parent||app);
//create various data for the tests to use
var testData = {
title: (post.name||"").toLowerCase(),
msg: (post.message||"").toLowerCase(),
caption: (post.caption||"").toLowerCase(),
desc: (post.description||"").toLowerCase(),
link: post.linkText().toLowerCase(),
url: Url.decode(post.linkHref()).toLowerCase(),
img: (post.picture||"").toLowerCase(),
fromName: post.from.name.toLowerCase(),
fromID: post.from.id.toLowerCase(),
targetName: ","+post.getTargets("name").join(",").toLowerCase(),
targetID: ","+post.getTargets("id").join(",").toLowerCase(),
canvas: app.namespace.toLowerCase(),
likeName: ","+post.getLikes("name").join(",").toLowerCase(),
likeID: ","+post.getLikes("id").join(",").toLowerCase(),
comments: post.getComments("message").join(" \n").toLowerCase(),
commentorName: ","+post.getComments("name").join(",").toLowerCase(),
commentorID: ","+post.getComments("id").join(",").toLowerCase(),
};
//replacement for old options like body, either and html
testData.body = testData.title+testData.caption+testData.desc;
testData.either = testData.link+testData.body;
testData.html = testData.fromID + testData.fromName + testData.targetID + testData.targetName + testData.message
+ testData.href + testData.either + testData.img + testData.canvas + testData.likeID + testData.likeName
+ testData.commentorID + testData.commentorName + testData.comments;
var dynamicTests = Grabber.tests;
//check user built dynamic tests first if enabled and told to run first
if (opts["dynamic"+app.appID] && opts.dynamicFirst && dynamicTests) {
w=main.doWhichTestTree(post,dynamicTests, testData, true)||"none";
}
//process this game's tests if dynamic didn't already get one
if (w=="none" || !w || w=="") {
w=((tests=synApp.tests)?main.doWhichTestTree(post,tests, testData):"none")||"none";
}
//check user built dynamic tests last if enabled and not told to run first
if (w=="none" || !w || w=="") {
if (opts["dynamic"+app.appID] && !opts.dynamicFirst && dynamicTests) {
w=main.doWhichTestTree(post,dynamicTests,testData, true)||"none";
}
}
//switch to undefined collection if enabled
w=(w==="none" && opts[synApp.appID+"doUnknown"])?synApp.appID+"doUnknown":w;
return w;
}catch(e){log("main.which: "+e);}},
resetAccepted : function() {
if(confirm("Really clear all history?")) doAction(function(){
history={};
setOpt('history_'+profile,'{}');
});
},
onWindowResize : function(){
w=window.innerWidth;
if ($('wmCoolItem_feedAll')) $('wmCoolItem_feedAll').parentNode.parentNode.parentNode.style.width=(w-200+"px"); //181 for sidebar, 17 for slider, 2 for borders
},
onSave : function() {
//recopy the settings array from GM_Config
main.updateSettingsValues();
//update those settings we use as global variables
debug.doDebug = opts.debug;
debug.debugLevel = opts.debugLevel;
debug.debugMaxComments = opts.debugmaxcomments;
//hide or show counters
if (opts.showcounters) main.showCounters(); else main.hideCounters();
//update intervals
main.setIntervals();
//set console heights
main.resizeConsole();
//set new user colors
main.setColors();
},
getSettingsTree : function(i,settings,tempopts) {
var field = settings[i];
var value=GM_config.get(i), kids=field.kids;
switch(field.type) {
case "checkbox":
tempopts[i] = value; break;
default: tempopts[i] = value;
}
if(kids && typeof kids=="object") for(var kid in kids) {
tempopts=main.getSettingsTree(kid,kids,tempopts);
}
value=null; kids=null; field=null;
return tempopts;
},
updateSettingsValues : function(){try{
//log("main.updateSettingsValues()");
var tempopts={}, settings=GM_config.settings;
for(var i in settings) tempopts=main.getSettingsTree(i,settings,tempopts);
opts = tempopts; tempopts=null; settings=null;
}catch(e){"main.updateSettingsValues: "+e}},
getAccText: function(appID,w,past){
var app=apps[appID]; if (app.parent) app=app.parent;
return (w=="dynamic")?"Dynamic Grab"+((past)?"bed":""):(((w.find("send")?"Sen"+((past)?"t":"d")+" ":w.find("wishlist")?"":"G"+((past?"o":"e"))+"t ") + app.accText[w]) || ((past)?main.accDefaultText:"Get Unknown") || ((w.startsWith(app.appID+"doUnknown"))?"Unknown":"") );
},
stopCollectionOf : function(w){
for (var p in posts) if (posts[p].which==w) posts[p].stopCollect();
},
pauseByType : function(w){
//mark as paused all those posts not yet done
for (var p in posts) if (posts[p].which==w) posts[p].pause();
//store the paused type but dont save it
typesPaused.push(w);
},
unPauseByType : function(w){
//unpause all those posts not yet done
for (var p in posts) if (posts[p].which==w) posts[p].unPause();
//remove paused type from list but dont save it
typesPaused.removeByValue(w);
},
setAsAccepted : function(comment,status, post) {try{
var app=post.app;
var synApp=app.parent||app;
post.state="accepted";
post.status=status;
post.accept();
history[post.id]={status:status, date:timeStamp(), which:(post.which||"undefined").removePrefix(app.appID), appID:app.appID};
setOptJSON('history_'+profile,history);
var postNode=post.node||$("post_"+post.id);
if (postNode){
var link=selectSingleNode(".//a[contains(@class,'linkText')]",{node:postNode});
var text=main.getAccText(synApp.appID,post.which,true);
link.textContent = (comment || text || main.statusText[status] || main.accDefaultText);
main.updatePostStatus(post.id);
}
app.acceptCount++; app.updateCounters();
//check if any limit rule affects this bonus type
for (r in rules) {
var rule = rules[r];
if ((rule.appID+rule.bonus) == post.which) {
if (rule.limit!="-1") {
//tick this rule up one
rule.incrementLimitCounter();
//check the limit value
if (rule.limitCount>=rule.limit) {
//limit reached
switch(rule.onLimit){
case "0": //destroy rule
rule.remove();
break;
case "1": //pause collection of this bonus type
//select all bonuses of this type prepped to run
main.pauseByType(post.which);
break;
case "2": //uncheck bonus type in options menu
main.disableOpt(post.which);
//now mark those that are already set for collection to NOT collect
main.stopCollectionOf(post.which);
break;
}
}
}
}
}
//try autolike
try{
if (opts.autolikeall || opts.autolikeaccepted || (opts.autolikesent && (post.which||"undefined").startsWith(synApp.appID+"send")) ) {
if (!opts["nolike"+app.appID]){
setTimeout(function(){post.like();},100+(opts.autolikedelay*1000));
}
}
} catch(e){log("setAsAccepted: autolike failed: "+e,{level:3});}
}catch(e){log("main.setAsAccepted: "+e);}},
disableOpt : function(w){
opts[w]=false;
GM_config.set(w,false);
GM_config.save();
},
enableOpt : function(w){
opts[w]=true;
GM_config.set(w,true);
GM_config.save();
},
resetCounters : function(){try{
for (var a in apps) apps[a].resetCounter();
}catch(e){log("main.resetCounters: "+e);}},
setAsFailed : function(comment, status, post){try{
var app=post.app;
var synApp=app.parent||app;
var postNode=post.node||$("post_"+post.id);
if (!opts.failontimeout && status==-14) {
post.state="timeout";
post.timeout();
} else {
post.state="failed";
post.fail();
history[post.id]={status:status, date:timeStamp(), which:(post.which||"undefined").removePrefix(app.appID), appID:app.appID};
setOptJSON('history_'+profile,history);
}
post.status=status;
if (postNode) {
var link=selectSingleNode(".//a[contains(@class,'linkText')]",{node:postNode});
link.textContent = (comment || main.statusText[status] || main.failText);
main.updatePostStatus(post.id);
}
app.failCount++; app.updateCounters();
//try autolike
try{
if (opts.autolikeall) {
if (!opts["nolike"+app.appID]){
setTimeout(function(){post.like();},100+(opts.autolikedelay*1000));
}
}
} catch(e){log("setAsFailed: autolike failed: "+e,{level:3});}
}catch(e){log("main.setAsFailed: "+e);}},
setPriority : function(){
var postNode=selectSingleNode(".//ancestor::*[starts-with(@id,'post_')]",{node:this});
var id=postNode.id.replace("post_","");
posts[id]["priority"]=this.getAttribute("name");
remove(postNode);
posts[id].draw();
},
clearURL : function(tab){
Collector.close(tab);
main.requestsOpen--;
},
onFrameLoad : function(tab,noDebug){try{
//tab object contains {id,post,url}
if (!noDebug) log("onFrameLoad()",{level:0});
var id=tab.id; var post=tab.post||posts[id];
if (!(post||null)) {
//resource deleted while post was out
main.clearURL(tab);
return;
}
var app=post.app;
var synApp=app.parent||app;
var httpsTrouble=synApp.flags.httpsTrouble;
var responseLess=synApp.flags.skipResponse;
var postNode=post.node||$("post_"+post.id);
var link=selectSingleNode(".//a[contains(@class,'linkText')]",{node:postNode});
var w=post.which||"undefined";
tab.tries=(tab.tries||0)+1;
if (tab.tries>opts.reqtimeout) {
log("onFrameLoad: request timeout",{level:3});
main.setAsFailed(null, -14, post);
main.clearURL(tab);
return;
}
var retry=function(){setTimeout(function(e){main.onFrameLoad(tab, true);}, 1000);};
var failedItem=false, gotItem=false, nopopLink;
//check if window object is missing
if (!(tab.hwnd)) {main.setAsFailed(null,-17,post); main.clearURL(tab); return;}
//check if window document does not yet exist
//if (!(tab.hwnd.document||null)) {retry(); return;}
//get sidekick return value
var hashMsg="",hashStatus=0;
try{
//if error encountered, reload the page
if (tab.hwnd.document.title==="Problem loading page"){
log("processPosts: problem loading page",{level:1});
tab.hwnd.location.reload();
retry();
return;
}
var temphash = tab.hwnd.location.hash; //capture a hash if we can
hashMsg = ((temphash)?temphash.removePrefix("#"):null) || tab.hwnd.location.href.split("#")[1];
hashStatus=(responseLess)?2:(hashMsg||null)?parseInt(hashMsg.split('status=')[1].split("&")[0]):0;
gotItem=((hashStatus>0) || (hashStatus==-6) || (hashStatus==-4) || (hashStatus==-15 && opts.accepton15));
failedItem=(hashStatus<0);
if (!gotItem && !failedItem) {retry(); return;}
} catch(e){
var errText=""+e;
if (errText.contains("hashMsg is undefined")) {
//this known issue occurs when a page is not yet fully loaded and the
//WM script tries to read the page content
retry();
return;
}
else if (errText.contains("Permission denied to access property")) {
//we've reached some known cross domain issue
if (responseLess) {
//if the sidekick creator has chosen to use responseless collection
//simply assume the page has loaded and mark the item as collected
gotItem=true;failedItem=false;hashStatus=2;
} else {
//log("onFrameLoad: "+e,{level:2});
retry();
return;
}
}
else if (errText.contains("NS_ERROR_INVALID_POINTER")
|| errText.contains("tab.hwnd.document is null") ) {
main.setAsFailed(null,-17,post);
main.clearURL(tab);
return;
}
else {
log("onFrameLoad: "+e,{level:3});
retry();
return;
}
}
//if gotItem then we have been offered the item so far
if (gotItem){
//build debug block
switch(hashStatus){
case -6: case -4: case 1:
// this bonus is available or we still have the ability to send something for no return
if (synApp.flags.requiresTwo){
try{
nopopLink=hashMsg.split("&link=[")[1].split("]")[0];
}catch(e){
//known rare issue where no link is passed back by pioneer trail
}
}
//dont break before next
case -15: case 2:
if (!synApp.flags.requiresTwo){
main.setAsAccepted(null, hashStatus,post);
}
break;
default:
//should not have come here for any reason, but if we did assume its a status code I didnt script for
main.setAsFailed(null, hashStatus,post);
log("onFrameLoad: unexpected status code: "+hashStatus,{level:2});
break;
}
} else {
main.setAsFailed(null,hashStatus,post);
}
// click "yes" to accept it, if we got this far we actually found an accept button
if(synApp.flags.requiresTwo && gotItem) {
if (nopopLink) {
var req; req=GM_xmlhttpRequest({
method: "GET",
url: nopopLink,
onload: function(response) {
//search for error messages
var test=response.responseText;
if (test==""){
//no text was found at requested href
log("onFrameLoad: final stage: null response",{level:2});
main.setAsFailed(null, -9,post);
} else {
//if no errors then we got it
main.setAsAccepted(null, hashStatus,post);
}
main.clearURL(tab);
if(req)req=null;
},
onerror: function(response) {
log("onFrameLoad: final stage: error returned",{level:2});
//if final request fails, drop the request for now
main.setAsFailed(null, -10,post);
main.clearURL(tab);
if(req)req=null;
},
onabort: function(response) {
log("onFrameLoad: final stage: request aborted",{level:2});
main.setAsFailed(null, -10,post);
main.clearURL(tab);
if(req)req=null;
},
});setTimeout(function(){if(req)req.abort(); if(req)req=null;},opts.reqtimeout*1000);
} else {
log("onFrameLoad: nopopLink is null and a string was expected",{level:3});
main.setAsFailed(null, -16,post);
main.clearURL(tab);
return;
}
} else main.clearURL(tab);
}catch(e){log("main.onFrameLoad: "+e);}},
toggle : function(opt){
if (opts[opt]){
GM_config.set(opt, false);
opts[opt] = false;
} else {
GM_config.set(opt, true);
opts[opt] = true;
}
GM_config.save();
},
getAppDropDownList : function(selectedIndex,allowBlank){
var retApps=[];
//add the fake initial option
retApps.push(createElement("option",{textContent:"select an app",value:""}));
retApps.push(createElement("option",{textContent:"* All",value:""}));
if (allowBlank) retApps.push(createElement("option",{textContent:"all apps",value:""}));
for(var i in apps){
if (!apps[i].parent) {
var elem = createElement("option",{textContent:apps[i].name,value:i});
if ((selectedIndex||null) == i) elem.selected = true;
retApps.push(elem);
}
}
return retApps;
},
saveRules : function(){try{
setOptJSON("priority_"+profile,rules); //functions are omitted
setOptJSON("priorityOpts_"+profile,Priority.opts);
}catch(e){log("main.saveRules: "+e);}},
newRule : function(){try{
var rule=new Rule();
rules[rule.id]=rule;
main.saveRules();
}catch(e){log("main.newRule: "+e);}},
getBonusDropDownList : function(params){
params=params||{};
var selected = params.selected||"";
var appID = params.appID||null;
var dropID = params.dropID||false; //force the element value to drop its appID prefix
var optsret=[], bonuses={};
if (appID) bonuses = apps[appID].accText;
bonuses["dynamic"]="* Dynamic: Just Grab It";
bonuses["none"]="* None: Break Identification Circuit";
bonuses["wishlist"]="* Flag as Wishlist";
bonuses["exclude"]="* Exclude: Prevent Collection";
bonuses["send"]="* Send Unknown";
bonuses["doUnknown"]="* Get Unknown";
//create option values and names;
for (var i in bonuses) {
var elem
if (appID) elem = createElement("option",{textContent:((i.startsWith(appID+"send"))?"Send ":((bonuses[i].substring(0,1)=="*")?"":"Get "))+bonuses[i],value:((dropID)?i.removePrefix(appID):i)});
else elem = createElement("option",{textContent:bonuses[i],value:i});
if (appID) {if (selected==((dropID)?i.removePrefix(appID):i) ) elem.selected = true;}
else {if (selected==i) elem.selected=true;}
optsret.push(elem);
}
return optsret;
},
resetAllLimits : function(){
for (var r in rules) {
rules[r].resetLimit();
}
main.saveRules();
},
reIDAll : function(){
for (var p in posts) posts[p].identify();
main.sortPosts();
main.redrawPosts();
},
addToolBox : function(post){
if (!opts.showtoolbox) return;
var toolNode = selectSingleNode(".//div[contains(@class,'toolBox')]",{node:$("post_"+post.id)});
if (toolNode) toolNode.appendChild(
createElement("div",{},[
createElement("div",{className:"toolButton oddBlue"+((!opts.showpostsrc)?" hidden":"")},[createElement("a",{title:"Show Post Source",href:post.actionLink("Like"),target:"_blank"},[createElement("img",{src:imgs.newwindow})])]),
createElement("div",{className:"toolButton oddBlack"+((!opts.showclean)?" hidden":"")},[createElement("a",{title:"Clean",href:jsVoid,onclick:function(){post.remove();}},[createElement("img",{src:imgs.trash})])]),
createElement("div",{className:"toolButton oddBlack"+((!opts.showpin)?" hidden":"")},[createElement("a",{title:"Pin",href:jsVoid,onclick:function(){post.togglePin();}},[createElement("img",{src:imgs.pin})])]),
createElement("div",{className:"toolButton oddOrange"+((!opts.showmovebottom)?" hidden":"")},[createElement("a",{title:"Move to Bottom",href:jsVoid,onclick:function(){post.moveToBottom();}},[createElement("img",{src:imgs.movetobottom})])]),
createElement("div",{className:"toolButton oddGreen"+((!opts.showmovetop)?" hidden":"")},[createElement("a",{title:"Move to Top",href:jsVoid,onclick:function(){post.moveToTop();}},[createElement("img",{src:imgs.movetotop})])]),
createElement("div",{className:"toolButton oddBlack"+((!opts.showreid)?" hidden":"")},[createElement("a",{title:"ReID Post",href:jsVoid,onclick:function(){post.reID();}},[createElement("img",{src:imgs.reidentify})])]),
createElement("div",{className:"toolButton oddBlue"+((!opts.showlike)?" hidden":"")},[createElement("a",{title:"Like Post",href:jsVoid,onclick:function(){post.like();}},[createElement("img",{src:imgs.likepost})])]),
createElement("div",{className:"toolButton oddOrange"+((!opts.showmarkfailed)?" hidden":"")},[createElement("a",{title:"Mark as Failed",href:jsVoid,onclick:function(){post.fail(true);}},[createElement("img",{src:imgs.markasfailed})])]),
createElement("div",{className:"toolButton oddGreen"+((!opts.showmarkaccepted)?" hidden":"")},[createElement("a",{title:"Mark as Accepted",href:jsVoid,onclick:function(){post.accept(true);}},[createElement("img",{src:imgs.markasaccepted})])]),
createElement("div",{className:"toolButton oddBlue"+((!opts.showopen)?" hidden":"")},[createElement("a",{title:"Open Post",href:jsVoid,onclick:function(){post.forceOpen();}},[createElement("img",{src:imgs.do})])]),
])
);
},
updatePostStatus : function(id){
var status = posts[id].status;
var statusNode = selectSingleNode(".//*[contains(@class,'status')]",{node:$("post_"+id)});
if (statusNode) statusNode.textContent="Status: "+(status||"0") + " " + (main.statusText[status||"0"]);
status=null; statusNode=null;
},
onLikePost : function(tab){
try{
var like=tab.hwnd.location.hash.removePrefix("#").getUrlParam("status")=="1";
if (like) {
Collector.close(tab);
return;
}
} catch (e){
//log(""+e);
}
tab.tries=(tab.tries||0)+1;
if (tab.tries<opts.autoliketimeout) setTimeout(function(){main.onLikePost(tab);}, 1000);
else {
log("onLikePost: unable to finish auto-like",{level:3});
doAction(function(){Collector.close(tab);});
}
},
toggleSidekick : function(){
var appID = this.id.split("master_")[1];
var opt = !(quickOpts["masterSwitch"][appID]||false); //toggle
quickOpts["masterSwitch"][appID]=opt;
var className = this.parentNode.className;
this.parentNode.className = ((opt)?className.removeWord("disabled"):className.addWord("disabled"));
this.textContent=((opt)?"Disable":"Enable");
main.saveQuickOpts();
},
saveQuickOpts : function(){
setOptJSON('quickopts_'+profile, quickOpts);
},
setDisplay : function(){
var x=this.getAttribute("name");
quickOpts.displayMode=x;
main.saveQuickOpts();
main.redrawPosts();
},
redrawPosts : function(){
status.print("Redrawing Posts");
//clear the feed
wmConsole.feedNode.innerHTML="";
wmConsole.feedNode.className=(quickOpts.displayMode=="1" || quickOpts.displayMode=="3")?"short":"";
for (var p in posts) posts[p].draw(true);
},
moveFloater : function(ev){
if (isChrome) return;
var img=this, offset=trueOffset(img), scrolled=trueScrollOffset(img),
post=selectSingleNode(".//ancestor::div[starts-with(@id,'post')]",{node:img}),
floater=$(post.id.replace("post","floater")), special={};
//log( (scrolled.left) +","+ (scrolled.top) );
special.x=(ev.clientX > (document.documentElement.clientWidth/2))?-(240+4+22):0; //width+overshot+BorderAndPadding
special.y=(ev.clientY > (document.documentElement.clientHeight/2))?-(120+4+12):0;
floater.style.left=(ev.clientX-(offset.left-scrolled.left))+(2+special.x)+"px";
floater.style.top=(ev.clientY-(offset.top-scrolled.top))+(2+special.y)+"px";
},
processPosts : function(){
//dont run if menu is open or if requests are still out or if the console is paused
if($("GM_config") || (main.requestsOpen >= opts.maxrequests) || main.paused) return;
var postNode=selectSingleNode(".//div[starts-with(@id,'post_') and contains(@class,'collect') and not(contains(@class,'paused'))]",{node:wmConsole.feedNode});
if (postNode) {
var post = posts[postNode.id.replace('post_','')];
if (post) post.open();
}
},
olderPosts : function () {
main.fetch({next:true});
},
newerPosts : function () {
main.fetch({prev:true});
},
cleanPosts : function () {try{
for (var p in posts) {
var post = posts[p];
if (!(
(post.flags & (postFlags.PINNED | postFlags.COLLECT | postFlags.WORKING)) ||
((post.flags & postFlags.TIMEOUT) && !opts.cleanTimedOut)
)) post.remove();
}
}catch(e){log("main.cleanPosts(): "+e);}},
calcTime : function (timer) {
var t=2;
switch(GM_config.get(timer+"interval")) {
case "tenth": t = 0.1; break; // 6 seconds
case "sixth": t = 0.1666667; break; // 10 seconds
case "third": t = 0.3333333; break; // 20 seconds
case "half": t = 0.5; break; // 30 seconds
case "one": t = 1; break; // 1 minute
case "two": t = 2; break; // 2 minutes
case "three": t = 3; break; // 3 minutes
case "four": t = 4; break; // 4 minutes
case "five": t = 5; break; // 5 minutes
case "ten": t = 10; break; // 10 minutes
case "fifteen": t = 15; break; // 15 minutes
case "thirty": t = 30; break; // 30 minutes
case "hour": t = 60; break; // 1 hour
case "2hour": t = 60*2; break; // 2 hours
case "3hour": t = 60*3; break; // 3 hours
case "4hour": t = 60*4; break; // 4 hours
case "8hour": t = 60*8; break; // 8 hours
case "12hour": t = 60*12; break; // 12 hours
case "18hour": t = 60*18; break; // 18 hours
case "24hour": t = 60*24; break; // 1 day
case "36hour": t = 60*36; break; // 1.5 days
case "48hour": t = 60*48; break; // 2 days
case "30s2m": t = (Math.random() * 1.5) + 0.5; break; // random between 30s and 2m
case "2m5m": t = (Math.random() * 3) + 2; break; // random between 2m and 5m
case "5m10m": t = (Math.random() * 5) + 5; break; // random between 5m and 10m
}
return Math.round((t*60000)+(Math.random()*(t*100)));
},
dynamicTestAllowUpdate : true,
dynamicTestUpdate : function(){
//if (!main.dynamicTestAllowUpdate) return;
var tabs=$("wmTabPage_wmDynamicData").parentNode;
var id=selectSingleNode(".//input[@name='id']",{node:tabs}).value;
var retList=selectSingleNode(".//select[contains(@class,'retList')]",{node:tabs});
var name=this.name;
var test=Grabber.getTest(id);
switch(name){
case "label":case "appID":case "ret": case "action":
test[name]=this.value;
if (name=="appID") {
//update the bonus list
retList.innerHTML="";
appendChildren(retList,main.getBonusDropDownList({appID:test.appID,selected:test.ret,dropID:true}));
}
else if (name=="label") {
//update the treeview branch title
var branch=selectSingleNode(".//div[@id='"+test.id+"']/div[contains(@class,'title')]",{node:$("wmDynamicTree")});
if (branch) branch.textContent=test.label;
}
break;
case "regex":
test.regex = this.checked;
if (test.regex) {
test.find = this.previousSibling.previousSibling.value.split(/\r?\n|\r/g)[0];
delete test.subNumRange; delete test.subTests;
}
else test.find = this.previousSibling.previousSibling.value.split(/\r?\n|\r/g);
break;
case "find": case "search":
test[name]=this.value.split(/\r?\n|\r/g);
if ((name=="find") && (test.regex || test.subTests || test.subNumRange)) test.find=test.find[0]; //if regex is used then only take the first entry
break;
case "sub":
if (this.nextSibling.nextSibling.checked) {test.subNumRange=this.value; delete test.subTests;}
else {
test.subTests=this.value.split(/\r?\n|\r/g);
delete test.subNumRange;
//can only use first text entry
if (isArray(test.find)) test.find=test.find[0];
}
break;
case "searchDD":
this.previousSibling.value+=("\n"+this.value);
break;
case "retDD":
this.previousSibling.value=this.value;
test.ret=this.value;
break;
case "note":
test[name]=this.value;
break;
case "disabled":
test[name]=this.checked;
break;
case "numRange":
var subTest=this.previousSibling.previousSibling;
if (this.checked) { test.subNumRange=subTest.value; delete test.subTests; }
else { test.subTests=this.value.split(/\r?\n|\r/g); delete test.subNumRange; }
break;
default:
test[name]=this.value;
break;
}
//validate and show warnings
Grabber.save();
},
validateDynamics : function(test){
Grabber.save();
},
showDynamicBranch : function(treeNode){try{
//prevent loading of data to register as an edit
main.dynamicTestAllowUpdate=false;
var test=treeNode.data;
var id=test.id;
//draw the data
var appID,search,find,retID,note,regex,subTest,numRange,title,retList,action;
wmConsole.dynamicViewer.innerHTML=""; //clear it out
wmConsole.dynamicViewer.appendChild(
forms.createTabs({height:"400", subType:"fat", tabs:[
{id:"wmDynamicData",caption:"Data",selected:true,kids:[
createElement("div",{className:"toolBox medium inline"},[
createElement("div",{},[
createElement("div",{className:"toolButton oddGreen"},[createElement("a",{title:"New Test",href:jsVoid,onclick:function(){treeNode.addChild();},name:"new"},[createElement("img",{src:imgs.plus})])]),
createElement("div",{className:"toolButton oddOrange"},[createElement("a",{title:"Delete Test",href:jsVoid,onclick:function(){treeNode.remove(); $("wmDynamicViewer").innerHTML="";},name:"delete"},[createElement("img",{src:imgs.trash})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{title:"Move Up",href:jsVoid,onclick:function(){treeNode.moveUp();},name:"moveup"},[createElement("img",{src:imgs.arrowup})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{title:"Move Down",href:jsVoid,onclick:function(){treeNode.moveDown();},name:"movedown"},[createElement("img",{src:imgs.arrowdown})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{title:"Move Up One Level",href:jsVoid,onclick:function(){treeNode.moveUpLevel();},name:"uplevel"},[createElement("img",{src:imgs.uplevel})])]),
createElement("div",{className:"toolButton oddBlue"},[createElement("a",{title:"Move To Top Level",href:jsVoid,onclick:function(){treeNode.moveToTop();},name:"uptop"},[createElement("img",{src:imgs.movetotop})])]),
])
]),
testID=createElement("input",{name:"id",type:"hidden",className:"id",title:"This test's internal id."}),
createElement("label",{textContent:"Title:"}),
title=createElement("input",{name:"label",type:"text",className:"label",title:"Give your test an identifying title.",onchange:main.dynamicTestUpdate}),
createElement("br"),
createElement("label",{textContent:"appID:"}),
appID=createElement("select",{name:"appID",className:"appID",title:"What game are you testing against?",onchange:main.dynamicTestUpdate},main.getAppDropDownList(test.appID)),
createElement("label",{textContent:"Disable:"}),
disable=createElement("input",{name:"disabled",type:"checkbox",className:"checkbox",title:"Disable this test and its kids.",onchange:main.dynamicTestUpdate}),
createElement("br"),
function(){
try{
return forms.createSelectionList({
id:"wmDynamicSelectSearch",
subType:"fat",
onChange:function(list){test.search=list.toArray(); main.validateDynamics(test);},
allowSelect:true,
allowMove:true,
title:"Search",
name:"search",
data:Grabber.methods,
selected:(isArray(test.search))?test.search:((test.search)?[].push(test.search):[]),
moveUpImage:imgs.arrowup,
moveDownImage:imgs.arrowdown,
moveTopImage:imgs.movetotop,
moveBottomImage:imgs.movetobottom,
width:"75%",
});
}catch(e){log("showDynamicBranch()[search]:"+e); return null;}
}(),
createElement("br"),
createElement("input",{type:"button", name:"mode", value:"Standard", className:"mode", value:"Standard", disabled:(!test.regex && !test.subTests && !test.subNumRange), onclick: function(){
if (this.disabled) return;
delete test.regex;
delete test.subNumRange;
delete test.subTests;
if (!isArray(test.find)) test.find=[].push(test.find);
main.showDynamicBranch(treeNode);
} }),
createElement("input",{type:"button", name:"mode", className:"mode", value:"Sub Tests", disabled:(test.subTests), onclick:function(){
if (this.disabled) return;
delete test.regex;
delete test.subNumRange;
if (isArray(test.find)) test.find=test.find[0];
test.subTests=test.subTests||[];
main.showDynamicBranch(treeNode);
}}),
createElement("input",{type:"button", name:"mode", className:"mode", value:"Sub Number Range", disabled:(test.subNumRange), onclick:function(){
if (this.disabled) return;
delete test.regex;
delete test.subTests;
if (isArray(test.find)) test.find=test.find[0];
test.subNumRange=test.subNumRange||"0,0";
main.showDynamicBranch(treeNode);
}}),
createElement("input",{type:"button", name:"mode", className:"mode", value:"RegExp", disabled:(test.regex), onclick:function(){
if (this.disabled) return;
delete test.subTests;
delete test.subNumRange;
if (isArray(test.find)) test.find=test.find[0];
test.regex=true;
main.showDynamicBranch(treeNode);
}}),
//draw the finding methods
function(){
try{
if (!test.regex && !test.subTests && !test.subNumRange){
return createElement("div",{id:"wmDynamicMode"},[
forms.createSelectionList({
id:"wmDynamicSelectFind",
subType:"fat",
onChange:function(list){test.find=list.toArray(true); main.validateDynamics(test);},
allowMove:true,
allowAdd:true,
allowRemove:true,
requireUnique:true,
title:"Find",
name:"findMulti",
data:(isArray(test.find))?test.find:((test.find)?[].push(test.find):[]),
moveUpImage:imgs.arrowup,
moveDownImage:imgs.arrowdown,
moveTopImage:imgs.movetotop,
moveBottomImage:imgs.movetobottom,
removeImage:imgs.x,
addImage:imgs.plus,
width:"75%",
})
])
} else {
return createElement("div",{id:"wmDynamicMode"},[
(opts.showdynamictips)?createElement("p",{textContent:"Enter a find string below. If you are using the RegExp mode, your find string will be converted to a registered expression, and the return value will be equal to what is found, or you can override it with a return value below. If you are instead using SubTests or a Number Range, include a {%1} in your string as an insertion point for the range of data."}):null,
createElement("label",{textContent:"Find:"}),
createElement("input",{type:"test",name:"find",value:((isArray(test.find))?test.find[0]:test.find),onchange:function(){
test.find=this.value;
main.validateDynamics(test);
} }),
(test.subTests)?(
forms.createSelectionList({
id:"wmDynamicSelectSubtests",
subType:"fat",
onChange:function(list){test.subTests=list.toArray(true); main.validateDynamics(test);},
allowMove:true,
allowAdd:true,
allowRemove:true,
requireUnique:true,
title:"SubTests",
name:"subTests",
data:(isArray(test.subTests))?test.subTests:((test.subTests)?[].push(test.subTests):[]),
moveUpImage:imgs.arrowup,
moveDownImage:imgs.arrowdown,
moveTopImage:imgs.movetotop,
moveBottomImage:imgs.movetobottom,
removeImage:imgs.x,
addImage:imgs.plus,
width:"75%",
})
):null,
(test.subNumRange)?(
createElement("div",{},[
(opts.showdynamictips)?createElement("p",{textContent:"Enter a number range below, which will be mechanically entered into your find string."}):null,
createElement("label",{textContent:"Number Range (start, end):"}),
createElement("input",{type:"text",value:(test.subNumRange.split(",")[0]||"0"), onchange:function(){
var start = parseInt(this.value) || "0";
var end = parseInt(this.nextSibling.value) || "0";
test.subNumRange=start+","+end;
main.validateDynamics(test);
} }),
createElement("input",{type:"text",value:(test.subNumRange.split(",")[1]||"0"), onchange:function(){
var start = parseInt(this.previousSibling.value) || "0";
var end = parseInt(this.value) || "0";
test.subNumRange=start+","+end;
main.validateDynamics(test);
} }),
])
):null,
])
}
}catch(e){log("showDynamicBranch()[find modes]:"+e); return null;}
}(),
createElement("br"),
(opts.showdynamictips)?createElement("p",{textContent:"Select a predefined identification from the dropdown. You may leave this field blank to use the default identifier 'dynamic'."}):null,
//createElement("br"),
createElement("label",{textContent:"Return ID:"}),
retID=createElement("input",{name:"ret",type:"text",className:"ret",title:"Give your test a return value.",onchange:main.dynamicTestUpdate}),
createElement("select",{name:"retDD",className:"retList",title:"Select a predefined return value from the list.",onchange:main.dynamicTestUpdate},main.getBonusDropDownList({appID:test.appID,dropID:true,selected:test.ret})),
createElement("br"),
/*
(opts.showdynamictips)?createElement("p",{textContent:"This new feature allows you to make dynamically identified posts behave differently."}):null,
//createElement("br"),
createElement("label",{textContent:"Action:"}),
action=createElement("select",{name:"action",className:"action",title:"Select an action from the list.",onchange:main.dynamicTestUpdate},optionsFromArray(["normal","open","hide","fail","accept","pin"],test.action||"normal")),
createElement("br"),
*/
]},
{id:"wmDynamicNote",caption:"Notes",kids:[
createElement("label",{textContent:"Note:"}),
createElement("br"),
note=createElement("textArea",{name:"note",className:"note",title:"Attach a note to your test.",onchange:main.dynamicTestUpdate}),
]},
{id:"wmDynamicOther",caption:"Other",kids:[
(opts.showdynamictips)?createElement("p",{textContent:"This panel contains other parameters found on the test entry. Many of these parameters are probably vestigial parameters replaced by more currently supported parameters found on the data panel. You may continue using these parameters or delete them and start using the newer parameters."}):null,
]},
]})
);
//fill in the standard data
testID.value=test.id;
title.value = test.label || "<no title>";
appID.value = test.appID || "";
//search.value = (isArray(test.search))?test.search.join("\n"):test.search;
//find.value = (isArray(test.find))?test.find.join("\n"):test.find;
//regex.checked = test.regex;
//subTest.value = ((test.subTests)?test.subTests.join("\n"):null) || test.subNumRange || ""; //remembering that subTests is an array
//numRange.checked = test.subNumRange;
retID.value = test.ret || "";
note.value = test.note || "";
//draw anything not matching the above parameters to the "Other" tab
var standard=["label","appID","search","find","regex","subTest","subNumRange","ret","note","kids","id","do"];
for (p in test){
if (!(standard.inArray(p))) {
$("wmTabPage_wmDynamicOther").appendChild(
createElement("div",{},[
createElement("label",{textContent:p+":"}),
createElement("input",{name:p,type:"text",className:"other", value:test[p],onchange:main.dynamicTestUpdate}),
])
);
}
}
//let edits take place again
main.dynamicTestAllowUpdate=true;
}catch(e){log("main.showDynamicBranch: "+e);}},
setIntervals : function() {try{
//setup the timer to get new posts
if (procIntv) window.clearInterval(procIntv);
procIntv=window.setInterval(main.processPosts, 2000);
//setup the timer to get new posts
if (newIntv) window.clearInterval(newIntv);
if(opts.newinterval != "off") newIntv=window.setInterval(main.newerPosts, main.calcTime("new"));
//setup the timer to get new posts
if (oldIntv) window.clearInterval(oldIntv);
if(opts.oldinterval != "off") oldIntv=window.setInterval(main.olderPosts, main.calcTime("old")+2000);
if(opts.maxinterval == "off") olderLimit=0; else olderLimit=(main.calcTime("max")||olderLimit);
//setup the timer to clean up old posts from the feed
if (cleanIntv) window.clearInterval(cleanIntv);
if(opts.cleaninterval != "off") cleanIntv=window.setInterval(main.cleanPosts, main.calcTime("clean")+250);
}catch(e){log("main.setIntervals: "+e);}},
hideCounters : function(){try{
hideNodes("//*[contains(@class,'accFailBlock')]");
}catch(e){log("main.hideCounters: "+e);}},
showCounters : function(){try{
showNodes("//*[contains(@class,'accFailBlock')]");
}catch(e){log("main.showCounters: "+e);}},
validatePost : function(fbPost){try{
//validate required post fields
if (!( exists(fbPost.application) && exists(fbPost.link) && fbPost.type=="link")) {
return;
}
//accept only posts we have sidekicks for
var app;
if (!exists(app=apps[fbPost.application.id])) return;
//accept only posts for which a sidekick is enabled
if (!quickOpts.masterSwitch[app.appID]) return;
//create a Post object from the post data
var post=(posts[fbPost]=new Post(fbPost));
var hasID=post.identify();
main.sortPosts(); //make sure new posts fit the current sort order and direction
if (hasID) post.draw();
}catch(e){log("main.validatePost: "+e);}},
fetch : function(params) {try{
if (main.fetchPaused && !params.bypassPause) return;
params=params||{};
//for each feed source
for (var f in feeds) { var feed=feeds[f]; if (feed.enabled) {
//for each app under that feed source, as long as its not a neighbor wall
if (feed.url.contains("/me/home")) for (var a in apps) {
//dont request posts for a game who's masterswitch is off
if (quickOpts.masterSwitch[a]){
var app=apps[a];
Graph.fetchPosts({
callback:main.validatePost,
next:(params.next||null),
prev:(params.prev||null),
limit:olderLimit,
fetchQty:(opts.fetchQty||25),
feed:feed,
appName:app.name,
filter:"app_"+a //run once for each app filter
});
}
/* the option to NOT use app filters is no longer available
} else if (feed.url.contains("/me/home")){
Graph.fetchPosts({
callback:main.validatePost,
next:(params.next||null),
prev:(params.prev||null),
limit:olderLimit,
fetchQty:(opts.fetchQty||25),
feed:feed,
filter:"cg" //default to only games feed
});
*/
} else {
Graph.fetchPosts({
callback:main.validatePost,
next:(params.next||null),
prev:(params.prev||null),
limit:olderLimit,
fetchQty:(opts.fetchQty||25),
appName:"feed:"+feed,
feed:feed,
//filter:null //cannot be used with profile walls
});
}
}}
}catch(e){log("main.fetch: "+e);}},
firstFetch : function(){try{
main.fetch();
if (opts.showcounters) main.showCounters(); else main.hideCounters();
main.setIntervals();
if (opts.autopausecollect) main.pauseCollecting();
if (opts.autopausefetch) main.pauseFetching();
}catch(e){log("main.firstFetch: "+e);}},
afterSidekicksDock : function(){try{
//set up the priorities and limits object
Priority.init();
//decipher the dynamic tests
Grabber.init();
//draw the dynamic grabber console's tree base
var visTreeView = createElement("div",{className:"forms wrapper fat"});
wmConsole.dynamicTree.appendChild(visTreeView); //it must be bound to the document first
//create the behind the scenes tree structure and start jamming branches on
Grabber.treeview = new forms.TREEVIEW({
data:Grabber.tests,
onSelect:main.showDynamicBranch,
node:visTreeView,
collapsedImage:imgs.down,
expandedImage:imgs.up,
onNodeAdded:Grabber.save,
onNodeRemoved:Grabber.save,
onNodeMoved:Grabber.save,
});
//start fetching posts
main.firstFetch();
}catch(e){log("main.afterSidekicksDock: "+e);}},
compileFeedSources : function(){try{
var feedsInput = wmConsole.feedSourceNode.value
setOpt('feeds_'+profile,wmConsole.feedSourceNode.value);
//add feeds entries to graph list
var newFeeds = {me:feeds.me, wall:feeds.wall}; //always put our own feed in there first
//for each new feed, check if that feed already exists in the list so we can preserve next/prev location
for (var f=0,feedsToAdd=feedsInput.split("\n"),toAdd; (toAdd=feedsToAdd[f]); f++) if (toAdd.trim()!="") {
var feed = "https://graph.facebook.com/"+toAdd+"/feed", found=false;
//check current feeds to see if it exists
if (feeds[toAdd]||null){
//found, copy the old version to preserve next/prev location
newFeeds[toAdd]=feeds[toAdd]; found=true;
}
//if not found, add it new
if (!found) newFeeds[toAdd]={url:feed, next:"",prev:"",enabled:true,filters:{} };
}
//overwrite the old feeds list
feeds=newFeeds;
}catch(e){log("main.compileFeedSources: "+e);}},
resizeConsole : function(){try{
var ht=opts.windowstdheight;
$("wmPageContainer").style.height=ht+"px";
$("wmCoolPage_feedAll").style.height=ht-81-36+"px"; //coolbar is 81px with slider, toolbar is 34 + border 1
$("wmSidekickList").style.height=ht-40+"px"; //header is 30px + padding 5
$("wmPriorityBuilder").style.height=ht-40+"px"; //header is 30px + padding 5
$("wmDynamicTree").style.height=ht-30+"px"; //header is 30px
$("wmDynamicViewer").style.height=ht-30+"px"; //header is 30px
//wmConsole.dynamicNode.style.height=ht+"px";
//wmConsole.feedSourceNode.style.height=ht+"px";
}catch(e){log("main.resizeConsole: "+e);}},
setColors : function(){try{
var colors=["pinned","excluded","paused","scam","nodef","timeout","working","failed","accepted"];
var css="";
for (var c=0, color; (color=colors[c]); c++) {
css+=("div."+color+"{background-color:"+opts["colors"+color]+" !important;}\n");
}
//set the new transition delay timer
css+=(".wm.post.short:hover .floater {-moz-transition-property: padding,border,width,height;-moz-transition-delay:"+opts["transitiondelay"]+"s; width:240px; height:120px; padding:5px 10px;border:1px solid;}\n");
remove($("user_colors_css"));
addGlobalStyle(css,"user_colors_css");
}catch(e){log("main.setColors: "+e);}},
initConsole : function(){try{
wmConsole.loading=false;
if (wmConsole.initialized) log("WM Console Initialized");
//add an entrypoint for sidekicks since we know FB gave us access
document.body.appendChild(createElement('div',{id:'wmDock',style:'display:none;',onclick:Dock.answerDockingDoor}));
//add the options opener now that options exist
$("wmLeftCol").appendChild(
createElement("span",{className:"whiteover consoleButton left",id:"wmOptions",textContent:"WM Options",onclick:GM_config.open},[
createElement("span",{className:"toolTip",innerHTML:"Click to view options menu"})
])
);
//set console heights
main.resizeConsole();
//compile the feed sources before first run
main.compileFeedSources();
//wait some time before fetching posts to make sure all sidekicks are docked
setTimeout(main.afterSidekicksDock,(opts.waitDocking*1000));
//jam the status object inside the "mainContainer"
$('wmContent').insertBefore(status.windowNode,$('wmLeftCol'));
//initialize user colors
main.setColors();
}catch(e){log("main.initConsole: "+e);}},
cleanHistory : function(){try{
//history = getOptJSON("history_"+profile)||{};
var ageDays=parseInt(opts.itemage);
var timeNow=timeStamp();
for(var i in history) {
if( ( (timeNow-history[i].date) /day) > ageDays) {
delete history[i];
}
}
setOptJSON("history_"+profile, history);
}catch(e){log("main.cleanHistory: "+e);}},
optionsSetup : function(){try{
GM_config.storage="settings_"+profile;
GM_config.init("<img class='logo' src='"+imgs.logo+"'> v"+version, {
import:button("Import Settings",GM_config.importSettings),
export:button("Export Settings",GM_config.exportSettings),
section_main:section("Wall Manager Info",{
MainMessageCenter:separator("Documentation - Messages - Help",null,{
Mainupdate:anchor("Update Script","http://userscripts.org/scripts/source/86674.user.js"),
donateWM:{type:"link",label:"Donate for FBWM via Paypal",href:"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=merricksdad%40gmail%2ecom&lc=US&item_name=Charlie%20Ewing&item_number=FBWM¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted"},
Mainwikipage:anchor("Wiki Support Page","http://fbwm.wikia.com/wiki/Known_Issues"),
Mainsetupinfo:anchor("Setup Info","http://fbwm.wikia.com/wiki/New_User_Setup"),
Maindiscuss:anchor("Known Bugs","http://fbwm.wikia.com/wiki/Known_Issues"),
Mainrevisionlog:anchor("Revision Log","http://fbwm.wikia.com/wiki/Revisions"),
},true),
}),
section_dev:section("Dev/Debug Options",{
styling:optionBlock("Styling",{
pinundefined:checkBox("Pin Undefined Bonus Types"),
},true),
debugOpts:optionBlock("Debug",{
debug:checkBox("Enable Debug",true),
debugLevel:{
label:"Debug Sensitivity",
title:"Sets the level of errors and warnings to report. 0 is all, 5 shows only the worst.",
type:"select",
options:{
"0":"Function calls",
"1":"Function subsections & messages",
"2":"Captured expected errors",
"3":"Known unfixed errors",
"4":"Unexpected errors",
"5":"Fatal errors",
},
"default":"0"
},
debugmaxcomments:inputBox("Max debug lines (0 for no limit)",100),
},true),
advDebugOpts:optionBlock("Advanced Debug",{
devDebugFunctionSubsections:checkBox("Debug Function Subsections",false),
devDebugGraphData:checkBox("Debug Graph Packets (not available for Chrome)",false),
},true),
}),
section_history:section("History Options",{
itemage:inputBox("How long to keep tried items in memory (days)",2),
reset:button("Clear History",main.resetAccepted),
}),
section_access:section("Accessibility Options",{
shortmodeopts:optionBlock("Short Mode",{
thumbsize:{
label:"Thumbnail Size",
type:"select",
title:"Size of bonus thumbnails in display mode: short and .",
options:{
"mosquito":"16px",
"tiny":"24px",
"small":"32px",
"medium":"48px",
"large":"64px",
"xlarge":"96px",
},
"default":"medium"
},
},true),
styling:optionBlock("Styling",{
debugrecog:checkBox("Show Identified Text (instead of original link text)",true),
showcounters:checkBox("Show Accept/Fail Counts",true),
windowstdheight:inputBox("Adjust Console Height (px)",500),
showdynamictips:checkBox("Show Dynamic Console Tips",true),
transitiondelay:inputBox("Hover Box Delay (short mode only)",1),
},true),
toolboxopts:optionBlock("Customize Post Toolbox",{
showtoolbox:checkBox("Enable ToolBox", true),
showopen:checkBox("Open Post",true),
showmarkfailed:checkBox("Mark As Failed",true),
showmarkaccepted:checkBox("Mark As Accepted",true),
showlike:checkBox("Like Post",true),
showreid:checkBox("Re-ID Post",true),
showmovetop:checkBox("Move to Top",true),
showmovebottom:checkBox("Move to Bottom",true),
showpin:checkBox("Pin Post",true),
showclean:checkBox("Clean Post",true),
showpostsrc:checkBox("Show Post Source",true),
},true),
}),
section_colors:section("Display Colors (as words or #values)",{
colorsaccepted:inputBox("Accepted","limegreen"),
colorsfailed:inputBox("Failed","red"),
colorsworking:inputBox("Working","yellow"),
colorsexcluded:inputBox("Excluded","gray"),
colorspaused:inputBox("Paused","silver"),
colorsnodef:inputBox("No Definition","deepskyblue"),
colorsscam:inputBox("Potential Scam","purple"),
colorspinned:inputBox("Pinned","black"),
colorstimeout:inputBox("Timeout","orange"),
}),
section_filters:section("Feed Filter Options",{
displayfilters:optionBlock("Remove Feed Parts (Classic Mode Only)",{
hideimages:checkBox("Images (All)"),
hideimagesunwanted:checkBox("Images (Unwanted Posts)"),
hidebody:checkBox("Post Body Text"),
hidevia:checkBox("Via App"),
hidedate:checkBox("Date/Time"),
},true),
filters:optionBlock("Hide By Type",{
hidemyposts:checkBox("My Posts"),
hideunwanted:checkBox("Unwanted"),
hideaccepted:checkBox("Accepted"),
hidefailed:checkBox("Failed"),
hidescams:checkBox("Scams"),
hidestale:checkBox("Stale Posts"),
hideexcluded:checkBox("Excluded"),
hideliked:checkBox("Liked By Me"),
hideunsupported:checkBox("Unsupported Apps"),
donthidewishlists:checkBox("Don't Hide Known Wish Lists"),
}),
//allow hiding all posts by particular games
filterapps:optionBlock("Hide By App",{}),
//now added dynamically as appID+"dontsteal"
dontstealBlock:optionBlock("Don't take W2W posts not for me",{}),
skipopts:optionBlock("Skip By Type",{
skipliked:checkBox("Liked By Me"),
skipstale:checkBox("Day-Old Posts"),
}),
rules:optionBlock("Styling Rules",{
accepton15:checkBox("Mark 'Unrecognized Response' As Accepted"),
markliked:checkBox("Mark Liked As Accepted (must check Skip Liked)"),
},true),
cleanupblock:optionBlock("Cleanup",{
cleaninterval:{
label:"Cleanup Interval",
type:"select",
title:"Remove unwanted posts from collection console after a set time.",
options:{
"off":"Off",
"one":"1 minute",
"two":"2 minutes",
"five":"5 minutes",
"ten":"10 minutes",
"fifteen":"15 minutes",
"thirty":"30 minutes",
"hour":"1 hour",
},
"default":"off"
},
cleanTimedOut:checkBox("Clean timed out posts",true),
},true),
}),
section_basicopts:section("Basic Tech Options",{
intervals:optionBlock("Post Fetching",{
newinterval:{
label:"Get Newer Posts Interval",
type:"select",
title:"Fetch new posts from facebook after a set time.",
options:{
"off":"Off",
"tenth":"6 seconds",
"sixth":"10 seconds",
"half":"30 seconds",
"one":"1 minute",
"two":"2 minutes",
"three":"3 minutes",
"four":"4 minutes",
"five":"5 minutes",
"ten":"10 minutes",
},
"default":"half"
},
fetchQty:{
label:"Fetch how many?",
type:"select",
title:"Posts fetched per request. Higher numbers affect speed of fetching.",
options:{
"5":"5",
"10":"10",
"25":"25",
"50":"50",
"100":"100",
},
"default":"25"
},
oldinterval:{
label:"Get Older Posts Interval",
type:"select",
title:"Fetch previous posts from facebook after a set time.",
options:{
"off":"Off",
"tenth":"6 seconds",
"sixth":"10 seconds",
"half":"30 seconds",
"one":"1 minute",
"two":"2 minutes",
"three":"3 minutes",
"four":"4 minutes",
"five":"5 minutes",
"ten":"10 minutes",
},
"default":"off"
},
maxinterval:{
label:"How old is too old? (hours)",
type:"select",
title:"Tell WM what you think is a good max post age to fetch. Also affects which posts are considered 'stale'.",
options:{
"off":"Off/Infinite",
"hour":"1",
"2hour":"2",
"3hour":"3",
"4hour":"4",
"8hour":"8",
"12hour":"12",
"18hour":"18",
"24hour":"24",
"32hour":"32",
"48hour":"48",
},
"default":"24hour"
},
},true),
restrictors:optionBlock("Fetching/Collecting Autopause",{
autopausefetch:checkBox("Pause Fetching after First Fetch"),
autopausecollect:checkBox("Pause Collection on Startup"),
},true),
autoLikeBlock:optionBlock("Auto-Like (overrides max requests)",{
autolikeall:checkBox("All Posts"),
autolikeaccepted:checkBox("Accepted Posts"),
autolikesent:checkBox("Sent Posts"),
autoliketimeout:inputBox("Auto-Like Timeout (seconds)",30),
autolikedelay:inputBox("Auto-Like Ban-Prevention Delay (seconds)",3),
},true),
blockautolikebygame:optionBlock("Block Auto-like by Game",{},false),
docking:optionBlock("Sidekick Docking",{
waitDocking:inputBox("Sidekick Docking Wait (seconds)",15),
},true),
multitask:optionBlock("Multi-task",{
maxrequests:inputBox("Max requests simultaneously",1),
recycletabs:inputBox("Recycle Windows/Tabs",1),
recycletabsall:checkBox("Recycle All",true),
},true),
queueing:optionBlock("Task-Queue",{
queuetabs:checkBox("Force all posts and autolikes through one tab using a queue (overrides multi-task)",true),
},true),
timeouts:optionBlock("Time-outs",{
reqtimeout:inputBox("Item Acceptance Page Timeout (seconds)",30),
failontimeout:checkBox("Mark Timeout as Failure (default: retry indefinitely)"),
},true),
}),
section_dynamicopts:section("Dynamic Grabber Options",{
dynamicopts:optionBlock("Dynamic Collection",{
dynamicFirst:checkBox("Run Dynamics BEFORE Sidekicks",true),
},true),
enableDynamic:optionBlock("Enable Dynamics by Game",{}),
}),
},
"", //forms.css // Custom styling for the options interface
{"save":main.onSave});
// add options shortcut to user script commands
GM_registerMenuCommand("Wall Manager "+version+" Options", GM_config.open);
}catch(e){log("main.optionsSetup: "+e);}},
init : function(){try{
//capture user id/alias/name and make it global
userID = Graph.userID;
userAlias = Graph.userAlias;
profile = userAlias||userID;
debug.print("UserID:"+userID+"; UserAlias:"+userAlias+"; WM is Using:"+profile);
//create the options menu
main.optionsSetup();
//duplicate the options saved in gm_config
main.updateSettingsValues();
//setup debug beyond its defaults
debug.doDebug = opts.debug;
debug.debugLevel = opts.debugLevel;
debug.debugMaxComments = opts.debugmaxcomments;
// clean history
history = getOptJSON('history_'+profile)||{};
main.cleanHistory();
//get quickopts
quickOpts = getOptJSON('quickopts_'+profile)||{};
quickOpts["filterApp"]=(quickOpts["filterApp"]||"All");
quickOpts["displayMode"]=(quickOpts["displayMode"]||"0");
quickOpts["masterSwitch"]=(quickOpts["masterSwitch"]||{});
//prep the console now that we have an id and/or alias
wmConsole.init({callback:main.initConsole});
}catch(e){log("main.init: "+e);}},
run : function() {try{
// pre-load console images
for(var img in imgs) try{new Image().src = imgs[img];}catch(e){log("preload: "+e);}
//special about:config entry for disabling storage of fb auth token
//should help multi account users
if (true||getOpt("disableSaveAuthToken")) Graph.authToken=null;
Graph.fetchUser({callback:main.init});
}catch(e){log("main.run: "+e);}}
}; //end of main
//*****short text versions for GM_config menu options*****
var checkBox=function(l,d,c,n){return ({type:"checkbox",label:l,"default":d||false,kids:c,newitem:n});}
var hidden=function(l,d,c){return ({type:"hidden",label:l,"default":d,kids:c});}
var optionBlock=function(l,c,hideSelectAll,n){hideSelectAll=hideSelectAll||false;return ({type:"optionblock",label:l,kids:c,hideSelectAll:hideSelectAll,newitem:n});}
var separator=function(l,s,c,hideSelectAll){hideSelectAll=hideSelectAll||false; return ({type:"separator",label:l,section:s,kids:c}); }
var section=function(l,c){return ({type:"section",label:l,kids:c});}
var inputBox=function(l,d,n){return ({type:"float",label:l,"default":(d||0),newitem:n});}
var button=function(l,s){return ({type:"button",label:l,script:s});}
var anchor=function(l,u,t){return ({type:"link",label:l,href:u,title:(t||'')});}
//***************************************************************************************************************************************
//***** Immediate
//***************************************************************************************************************************************
status.print("Starting Script");
log("Script: main initialized",{level:0});
// section for reclaiming memory and stopping memory leaks
var newIntv=null; //refresh interval
var oldIntv=null; //refresh interval
var procIntv=null; //process interval
var cleanIntv=null; //post removal interval
var olderLimit=day; //default 1 day
var cleanup=function() {try{
//destroy intervals
if (newIntv) window.clearInterval(newIntv);
if (oldIntv) window.clearInterval(oldIntv);
if (procIntv) window.clearInterval(procIntv);
if (cleanIntv) window.clearInterval(cleanIntv);
oldIntv = newIntv = procIntv = cleanIntv = null;
//close the sidekick tabs
Collector.closeAll();
//remove this event listener
window.removeEventListener("beforeunload", cleanup, false);
window.removeEventListener("resize", main.onWindowResize, false);
//clean up memory
main=null; wmConsole=null; Dock=null; Graph=null; Collector=null;
olderLimit=null;
checkBox=null; hidden=null; optionBlock=null; separator=null; section=null; inputBox=null; button=null; anchor=null;
history = feeds = rules = groups = apps = posts = null;
}catch(e){log("cleanup: "+e);}}
window.addEventListener("beforeunload", cleanup, false);
window.addEventListener("resize", main.onWindowResize, false);
//start it up
main.run();
})(); // anonymous function wrapper end
/* to do
-dynamics
--add button to define a dynamic test to the post toolbar
--allow editing of dynamics in text mode for advanced users
--show custom dynamic return values in the dropdown
-priorities
--add button to define a priority to the post toolbar
--allow priorities to use wildcards
-console
--allow the user to choose the data shown per post via a dropdown with checkboxes
--stop drawing all the content for hover boxes ahead of time. They should be created on the fly when needed only
--rebuild the options menu into some tabs
--fix it so an initial tab is open
--give tabs a set height and y scolling
--section headers are automatically closed by default, not open
-data
--dynamics: id:{} not {id:}
--dynamics: show dynamic options in options menu
--history: ability to clear by appID or which
--settings: much better tree structure, not just values
--settings: never delete values or structure just because a sidekick didn't dock
--settings: store settings separately by appID?
-forms
--treeview: refine, add root and branch images as well as show roots and branches options
-group by [appid, author, priority, day, hour]
--expand/collapse groups
-dev tools
--ability to dump a post's data
-fixes and requests
--problem splitting request urls if first fetch didn't return yet
--re-id all after priority/dynamic menu change (as option)
-recent fixes
*/