- // ==UserScript==
- // @name 跟单
- // @namespace http://tampermonkey.net/
- // @version 0.5
- // @description try to take over the world!
- // @author You
- // @include http*://q1.88666333.com/*
- // @grant GM_xmlhttpRequest
- // @grant GM.getTab
- // @grant GM.saveTab
- // @grant GM.setValue
- // @grant GM.getValue
- // @run-at document-body
- // ==/UserScript==
-
- (function() {
- 'use strict';
- const THREAD_SIZE = 10;
- var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
- function isPromise(obj) {
- return !!obj && ((typeof obj === 'object' && typeof obj.then === 'function') || (typeof obj === 'function' && typeof obj().then === 'function'));
- }
- /**
- * Wait Resource.
- *
- * @param {Function} resourceFn pred function to check resource
- * @param {Object} options
- * @returns Promise
- */
- function waitResource(resourceFn, options) {
- var optionsRes = Object.assign(
- {
- interval: 1000,
- max: 6
- },
- options
- );
- var current = 0;
- return new Promise((resolve, reject) => {
- var timer = setInterval(() => {
- if (isPromise(resourceFn)) {
- resourceFn().then(res => {
- if(res) {
- clearInterval(timer);
- resolve();
- }
- });
- } else if (resourceFn()) {
- clearInterval(timer);
- resolve();
- }
- current++;
- if (current >= optionsRes.max) {
- clearInterval(timer);
- reject('Time out');
- }
- }, optionsRes.interval);
- });
- }
-
-
- function requestAsync(data) {
- // console.log(data);
- return new Promise((resolve, reject) => {
- var reportAJAX_Error = (rspObj) => {
- console.error (`Request error: ${data}`);
- reject(`Request => Error ${data} RES ${rspObj.status}! ${rspObj.statusText}`);
- }
-
- var processJSON_Response = (rspObj) => {
- if (rspObj.status != 200 && rspObj.status != 304) {
- reportAJAX_Error (rspObj);
- } else {
- let resJSON = {};
- try{
- resJSON = JSON.parse(rspObj.responseText);
- } catch(err) {
- // ignore
- console.log(err);
- }
- resolve(resJSON);
- }
- };
- GM_xmlhttpRequest ( {
- method: "POST",
- url: document.location.origin + "/!/MemberBet",
- headers: {
- "Referer": document.location.href,
- "Content-Type": "application/x-www-form-urlencoded"
- },
- data: data,
- // responseType: "json",
- onload: processJSON_Response,
- onabort: reportAJAX_Error,
- onerror: reportAJAX_Error,
- ontimeout: reportAJAX_Error
- });
- });
- }
-
- function getOrdersAsync(account, gameType, gameCode, pageIndex) {
- return new Promise((resolve, reject) => {
- $.get(`${document.location.origin}/!/UserBets?Account=${account}&GameType=${gameType}&GameCode=${gameCode}&PageSize=100&PageIndex=${pageIndex}`).done(function(result) {
- resolve(result);
- }).fail(function(jqXHR, textStatus, errorThrown) {
- reject(`Request => Error ${errorThrown} status ${textStatus}`);
- });
- });
- }
- function resToMask(res) {
- let placeHolders = ['abcXX', 'abXcX', 'abXXc', 'aXbcX', 'aXbXc', 'aXXbc', 'XabcX', 'XabXc', 'XaXbc', 'XXabc'];
- return placeHolders.map(a => {
- let mask = 'XXXXX'.split('');
- for(let i = 0; i < 5; i++) {
- if (a[i] !== 'X') {
- mask[i] = res[i];
- }
- }
- return mask.join('');
- });
- }
-
- function signalA(pool) {
- return false;
- }
-
- async function bet(pools) {
- let count = pools.length;
- // %3D
- //const REQ_DATA = `SourceType=quick-comb&SourceData=%7B%22bet-type%22%3A%22d3%22%2C%22bet-count%22%3A${count}%2C%22dingwei-include%22%3A1%2C%22dingwei-1%22%3A%2212%22%2C%22dingwei-2%22%3A%221%22%2C%22dingwei-3%22%3A%221%22%2C%22hefeng-include%22%3A1%2C%22dan-include%22%3A1%2C%22shuang-include%22%3A1%7D&Game=${GameType}&Pools=${pools.join('%2C')}&Amount=${amount}`;
- const REQ_DATA = `SourceType=txt-import&SourceData=${count}+%E4%B8%AA%E5%8F%B7%E7%A0%81%EF%BC%88%E5%B8%A6%E9%87%91%E9%A2%9D%EF%BC%89&Game=${GameType}&Pools=${pools.join('%2C')}&Amount=`;
- console.log(REQ_DATA);
- return await requestAsync(REQ_DATA);
- }
-
- function addUI() {
- let div=document.createElement("div");
- div.setAttribute("style", "width:360px");
- let btn=document.createElement("BUTTON");
- btn.setAttribute("id", "betBtn");
- div.appendChild(btn);
- let amount = document.createElement("INPUT");
- amount.setAttribute("id", "sigAccount");
- amount.setAttribute("placeholder", "跟单信号源");
- amount.setAttribute("type", "text");
- div.appendChild(amount);
- let node = document.querySelector('#branch-info');
- let parentNode = node.parentNode;
- parentNode.insertBefore(div, node);
- }
-
- async function main() {
- if (window !== top) {
- console.log(window.location.href);
- // let summaryUsersGame = document.querySelector("a[href='summary-users-game.html']");
- if (window.location.pathname.includes("summary-users.html")) {
- while (true) {
- let summaryUsersGame = document.querySelector("a[href='summary-users-game.html']");
- if (summaryUsersGame && summaryUsersGame.classList[0] !== 'active') {
- summaryUsersGame.click();
- }
- await wait(3000);
- }
- } else {
- return;
- }
- }
-
- console.log("START...", new Date());
- if (window.location.pathname === "/") { // login
- let user = await GM.getTab();
- console.log("DEBUG ", user);
- if (!!user && !!user.name) {
- await wait(1000);
- document.querySelector('#login-id').value = user.name;
- await wait(500);
- document.querySelector('#password').value = user.password;
- await wait(500);
- document.querySelector('.btn-primary').click();
- } else {
- document.querySelector('.btn-primary').onclick = async () => {
- user.name = document.querySelector('#login-id').value;
- user.password = document.querySelector('#password').value;
- await GM.saveTab(user);
- }
- }
- return;
- }
- if (window.location.pathname === "/agreement.html") {
- await wait(500);
- document.querySelector('#lnk-agree').click();
- return;
- }
- await waitResource(async () => {
- console.log(document.querySelector('#account'));
- return typeof ENV === "object" && ENV !== null && !!ENV[GameType] && !!ENV[GameType].Resulted;
- });
- if (!!document.querySelector('#branch-info')) // member
- {
- addUI();
- while (true) {
- await GM.setValue("currentGameCode", ENV[GameType].Current.Code);
- let tabObj = await GM.getTab();
- // console.log('tabObj: ', tabObj);
- if (tabObj.started) {
- if (tabObj.gameType !== GameType) {
- document.querySelector(`#game-type-${tabObj.gameType}`).click();
- }
- document.querySelector('#betBtn').innerText = `结束`;
- document.querySelector("#sigAccount").value = await GM.getValue('sigAccount');
- document.querySelector('#betBtn').onclick = async () => {
- tabObj.started = false;
- await GM.saveTab(tabObj);
- await GM.setValue('sigGameType', null);
- await GM.setValue('sigAccount', null);
- document.querySelector('#betBtn').innerText = "...";
- }
- } else {
- document.querySelector('#betBtn').innerText = "开始";
- document.querySelector('#betBtn').onclick = async () => {
- tabObj.started = true;
- tabObj.gameType = GameType;
- tabObj.betInfo = {
- gameCode: ENV[GameType].Current.Code,
- betIdMap: {}
- };
- await GM.saveTab(tabObj);
- await GM.setValue('sigGameType', GameType);
- await GM.setValue('sigAccount', document.querySelector("#sigAccount").value);
- document.querySelector('#betBtn').innerText = "...";
- }
- }
-
- if (!tabObj.started || new Date().getTime() / 1000 > ENV[GameType].Current.Close) {
- await wait(1000);
- continue;
- }
- let sigOrders = await GM.getValue("sigOrders", {});
- if (sigOrders.gameCode !== ENV[GameType].Current.Code) {
- console.log("Game code not current");
- await wait(1000);
- continue;
- }
- if (tabObj.betInfo.gameCode !== ENV[GameType].Current.Code) {
- tabObj.betInfo.gameCode = ENV[GameType].Current.Code;
- tabObj.betInfo.betIdMap = {};
- }
- // work
- let betId = 0;
- Object.keys(sigOrders.pools).forEach((key) => {
- if (betId === 0 && !tabObj.betInfo.betIdMap[key]) {
- betId = parseInt(key);
- }
- });
- //
- if (betId > 0) {
- // if (true) {
- let res = await bet(sigOrders.pools[betId]);
- if (res.Error && res.Error !== '额度不足' && res.Error !== '账号已停用下注') {
- throw(res);
- }
- console.log(res);
- console.log("betId", betId, tabObj.betInfo);
- tabObj.betInfo.betIdMap[betId] = true;
- await GM.saveTab(tabObj);
- continue;
- }
- // end work
- await wait(1000);
- }
- } else if (!!document.querySelector('#user-link')) { // signal
- while (true) {
- // 打开报表
- if (document.querySelector('a[href="/a/summary-users.html').classList[1] !== 'selected') {
- document.querySelector('a[href="/a/summary-users.html').click();
- await wait(5000);
- continue;
- }
- let sigAccount = await GM.getValue("sigAccount");
- let sigGameType = await GM.getValue("sigGameType");
- console.log(sigAccount, sigGameType);
- if (!sigAccount || !sigGameType) {
- await wait(1000);
- continue;
- }
- let sigOrders = await GM.getValue("sigOrders", {});
- console.log("DEBUG sigOrder init", sigOrders);
- if (sigOrders.gameType !== sigGameType || sigOrders.gameCode !== ENV[sigGameType].Current.Code) {
- sigOrders.gameType = sigGameType;
- sigOrders.gameCode = ENV[sigGameType].Current.Code;
- sigOrders.pools = {};
- sigOrders.total = 0;
- }
- let res = null;
- try {
- res = await getOrdersAsync(sigAccount,sigGameType, sigOrders.gameCode, 0);
- await wait(1000);
- } catch (err) {
- console.log('ignore error:', err);
- continue;
- }
- let remainPages = Math.ceil((res.Total - sigOrders.total) / 100);
- console.log("remain pages", remainPages, res.Total, sigOrders.total);
- let idx = 0;
- let rows = [];
- let baseIdx = 0;
- while (remainPages > 0) {
- let jobSize = remainPages <= THREAD_SIZE ? remainPages : THREAD_SIZE;
- let jobReses = await Promise.all([...Array(jobSize).keys()].map((a) => getOrdersAsync(sigAccount,sigGameType, sigOrders.gameCode, a + baseIdx)));
- console.log("jobs result", jobReses);
- jobReses.forEach((res) => {
- for (let i = 0; i < res.List.length && (rows.length < res.Total - sigOrders.total); i++) {
- rows.push({
- betId: res.List[i].BetID,
- pool: res.List[i].Pool,
- amount: res.List[i].Amounts[0] / 1000
- });
- }
- });
- await wait(1000);
- remainPages -= jobSize;
- baseIdx += jobSize;
- }
-
- for (let i = rows.length - 1; i >= 0; i--) {
- let id = rows[i].betId;
- if (!Array.isArray(sigOrders.pools[id])) { // new a bet
- sigOrders.pools[id] = [];
- }
- sigOrders.pools[id].push(`${rows[i].pool}%3D${rows[i].amount}`);
- sigOrders.total++;
- }
- // console.log(sigOrders);
- await GM.setValue("sigOrders", sigOrders);
- await wait(2000);
- }
- }
- }
- main()
- .then(() => console.log("Main Done"))
- .catch((err) => {
- console.error(err, "Restart in 6 secs ...");
- setTimeout(() => location.reload(), 6 * 1000);
- });
- })();