-
Notifications
You must be signed in to change notification settings - Fork 21
/
youlikehitsbot.user.js
189 lines (181 loc) · 11.7 KB
/
youlikehitsbot.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// ==UserScript==
// @name YouLikeHits Bot
// @namespace https://github.com/gekkedev/youlikehitsbot
// @version 0.5.1
// @description Interacts with YLH automatically whereever possible.
// @author gekkedev
// @updateURL https://raw.githubusercontent.com/gekkedev/youlikehitsbot/master/youlikehitsbot.user.js
// @downloadURL https://raw.githubusercontent.com/gekkedev/youlikehitsbot/master/youlikehitsbot.user.js
// @match *://*.youlikehits.com/login.php
// @match *://*.youlikehits.com/soundcloudplays.php*
// @match *://*.youlikehits.com/websites.php*
// @match *://*.youlikehits.com/viewwebsite.php*
// @match *://*.youlikehits.com/youtubenew2.php*
// @match *://*.youlikehits.com/bonuspoints.php*
// @grant GM.getValue
// @grant GM.setValue
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @require https://cdn.jsdelivr.net/gh/naptha/tesseract.js/dist/tesseract.min.js
// ==/UserScript==
(() => {
const J = jQuery.noConflict(true);
/** how many miliseconds to wait between launching another loop */
const globalInterval = 2000;
solveCaptcha = (imageEl, outputEl, captchaIdentifier, callback = () => {}) => {
if (window[captchaIdentifier] == undefined) {
window[captchaIdentifier] = true; //solving takes some time, so we'll lock a duplicate solver instance out
let note = attachNotification(imageEl, "Please wait while your captcha is being solved. Don't worry if the code does not seem to match; that's because a new captcha image has been generated!");
Tesseract.recognize(J(imageEl).attr("src")).then(equation => {
var formula = equation.text;
if (formula.length = 3) {//the exact length of the fomula
if (formula.substr(1, 1) == 7) { //2-1 gets recognized as 271
formula = formula.substr(0, 1) + "-" + formula.substr(2);
}
formula = formula.replace(/x/g, "*"); //x is just the human version of *
formula = formula.replace(/[} ]/g, ""); //a random char being the result of misinterpretation; occasionally happening on the login form
//console.log(formula); //re-enable this to debug how the captchasolving is doing so far
outputEl.val(eval(formula));
window[captchaIdentifier] = false; //not really necessary IF directly triggering a classic non-ajax post request
removeNotification(note);
callback()
}
});
}
}
const attachNotification = (identifier, notification) => {
//IDEA: turn it into a nice(r) GUI with an ID to check more efficiently for duplicates
const el = "<p style='color: red;'>Bot says: <i>" + notification + "</i></p>";
const prevEl = J(identifier).prev()[0];
if (prevEl == undefined || !prevEl.innerText.includes(notification))
return J(el).insertBefore(identifier);
}
const removeNotification = (el) => {
if (el != undefined)
el.remove()
}
/** input seconds, receive milliseconds */
const randomSeconds = (from, to) => {
return Math.floor(Math.random() * (to - from + 1) + from) * 1000
}
const alertOnce = (message, identifier) => {
localIdentifier = (identifier != undefined) ? identifier : message;
if (shownWarnings.indexOf(localIdentifier) == -1) {
shownWarnings.push(localIdentifier);
alert(message)
}
}
//runtime vars
let previousVideo = "";
/** indicates if a warning/message has already been shown. Happens once per window. Use alertOnce() */
let shownWarnings = [];
//loop over the website to find out which subpage we are on and take the appropriate actions IDEA: refactor the loop into a singleton
const mainLoop = setInterval(() => {
if (J("*:contains('503 Service Unavailable')").length) {
console.log("Server Error! reloading...");
location.reload();
} else if (J("*:contains('not logged in!')").length) {
window.location.href = "login.php"
} else if (J("*:contains('Failed. You did not successfully solve the problem.')").length) {
J("a:contains('Try Again')")[0].click()
} else {
switch (document.location.pathname) {
case "/login.php":
if (!J("#password").val().length) attachNotification("#username", "Consider storing your login data in your browser.")
const captcha = J("img[alt='Enter The Numbers']");
if (captcha.length)
solveCaptcha(captcha[0], J("input[name='postcaptcha']"), "ylh_login_captchasolving");
break;
case "/bonuspoints.php":
if (J("body:contains('You have made ')").length && J("body:contains(' Hits out of ')").length) {
const reloadDelay = randomSeconds(60, 60 * 5);
attachNotification(".maintable", "Not enough points. Reloading the website in " + Math.round(reloadDelay / 1000 / 60) + " minutes to check again...");
setTimeout(() => location.reload(), reloadDelay);
clearInterval(mainLoop); //no further checks since we gotta reload anyway
} else if (J(".buybutton").length) J(".buybutton")[0].click()
break;
case "/soundcloudplays.php":
//no timer visible / no song currently playing?
if (!J(".maintable span[id*='count']").attr("style").includes("display:none;")) return attachNotification(".maintable", "Music already playing..."); //TODO: detect timers that do not update
if (J(".followbutton").length) {
J(".followbutton").first().click();
} else alert("no followbutton, fix this pls");
case "/youtubenew2.php":
if (J('body:contains("failed")').length) location.reload(); //captcha failed?
if (J(".followbutton").length) { //if false, there is likely a captcha waiting to be solved
let vidID = () => { return J(".followbutton").first().parent().children("span[id*='count']").attr("id") };
let patienceKiller = (prev) => { setTimeout( () => { if (vidID() == prev) { J(".followbutton").parent().children("a:contains('Skip')").click(); newWin.close(); }}, 1000 * 135)}; //max time: 120s + 15s grace time (max length: http://prntscr.com/q4o75o)
//console.log(previousVideo + " " + vidID() + (previousVideo != vidID() ? " true": " false"));
if (vidID() != previousVideo) { //has a new video has been provided yet? This will overcome slow network connections causing the same video to be played over and over
previousVideo = vidID();
if (window.eval("typeof(window.newWin) !== 'undefined'")) {
if (newWin.closed) {
console.log("Watching one Video!");
J(".followbutton")[0].click();
patienceKiller(previousVideo)
}
} else {
console.log("Watching one Video!");
J(".followbutton")[0].click();
patienceKiller(previousVideo)
}
} //else do nothing and wait (until the video gets replaced or our patience thread tears)
} else {
captcha = J("img[src*='captchayt']");
if (captcha.length) //captcha? no problemo, amigo.
solveCaptcha(captcha[0], J("input[name='answer']"), "ylh_yt_traffic_captchasolving", () => J("input[value='Submit']").first().click());
}
break;
}
GM.getValue("ylh_traffic_tab_open", false).then(state => {
switch (document.location.pathname) {
case "/websites.php":
if (J("*:contains('There are no Websites currently visitable for Points')").length) {
alertOnce("All websites were visited. Revisit/reload the page to start surfing again.")
} else {
if (!state && window.eval("typeof(window.childWindow) !== 'undefined'")) {
if (!childWindow.closed)
childWindow.close();
} else if (state && window.eval("typeof(window.childWindow) == 'undefined'")) {
console.log("no child window is actually open. let's create a new tab as if we came here for the very first time!");
state = false;
}
var buttons = J(".followbutton:visible");
if (buttons.length) {
if (!state) {
console.log("setting the tabstate to true...");
GM.setValue('ylh_traffic_tab_open', true).then(() => {
console.log("Visiting a new page...");
buttons[0].onclick();
});
} else {
}
} else {
console.log("We ran out of buttons! requesting more...");
//GM.getValue("ylh_traffic_reloadlimit", false).then(rlimit => {
if (window.eval("typeof(window.childWindow) !== 'undefined'") && childWindow.closed) //without this we would not wait for the last link of the page to be visited successfully
location.reload();
//J("a[title='Refresh']")[0].click();
}
}
break;
case "/viewwebsite.php":
if (!J("*:contains('been logged out of YouLikeHits')").length) {
if (
J(".alert:visible:contains('You got'):contains('Points')").length
|| J('body:contains("We couldn\'t locate the website you\'re attempting to visit.")').length
|| J('body:contains("You have successfully reported")').length
) {
console.log("setting the tabstate to false...");
GM.setValue('ylh_traffic_tab_open', false).then(() => { //free the way for a new tab
/*window.close(); //might not always work in FF
setTimeout (window.close, 1000);*/
});
} else if (J("*:contains('viewing websites too quickly! Please wait')").length) location.reload();
} else alert("Please reload the website list, and make sure you are still logged in.");
break;
}
});
}
}, globalInterval);
})();