- // ==UserScript==
- // @name 巴哈姆特勇者福利社-跳過廣告&兌換流程自動化
- // @namespace ani20168
- // @version 2.3.1
- // @description 在勇者福利社參加抽抽樂時,可以直接免費兌換抽獎卷而不用看廣告!
- // @author ani20168
- // @homepage https://home.gamer.com.tw/profile/index.php?&owner=a20280210
- // @match https://fuli.gamer.com.tw/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=gamer.com.tw
- // @grant GM_xmlhttpRequest
- // @require https://openuserjs.org/src/libs/sizzle/GM_config.js
- // ==/UserScript==
-
- (function() {
- 'use strict';
- var observer;
- var enableAutoProcessOnBuyDPage = false;
- var enableAutoSkip = false;
-
- // GM_config選單
- var GM_configStruct = {
- 'id': 'UserScriptConfig',
- 'title': '抽抽樂腳本設定',
- 'fields':
- {
- 'enableAutoProcessOnBuyDPage':
- {
- 'label': '自動送出收件資料',
- 'type': 'checkbox',
- 'default': false,
- 'title': '啟用後,在填寫收件人頁面會自動送出收件資料,開啟這項功能前請先確保收件人資訊完整,而且頁面上的"請幫我記住收件人資料"的確認框為打勾的狀態。'
- },
- 'enableAutoSkip':
- {
- 'label': '自動跳過廣告',
- 'type': 'checkbox',
- 'default': false,
- 'title': '啟用後,只要頁面是在抽抽樂的商品頁面,而且此商品目前可以透過看廣告的方式兌換抽獎機會,則會自動執行廣告跳過流程。'
- }
- },
- 'css':
- `
- #UserScriptConfig {
- font-family: 'Arial', sans-serif;
- background-color: #fff;
- color: #333;
- width: 300px;
- padding: 15px;
- margin: 0 auto;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
-
- #UserScriptConfig .config_var {
- margin-bottom: 10px;
- }
-
- #UserScriptConfig .field_label {
- margin-bottom: 5px;
- display: block;
- font-weight: bold;
- }
-
- #UserScriptConfig input[type='checkbox'] {
- margin-right: 10px;
- transform: scale(1.2);
- }
-
- #UserScriptConfig .section_header_holder {
- margin-bottom: 15px;
- }
-
- #UserScriptConfig .config_header {
- font-size: 18px;
- margin-bottom: 15px;
- text-align: center;
- }
-
- #UserScriptConfig .saveclose_buttons {
- text-align: center;
- padding: 8px 16px;
- margin:20px 40px 5px;
- border: 2px solid transparent;
- border-radius: 10px;
- transition: border-color 0.15s ease-in-out;
- }
-
-
-
- #UserScriptConfig .saveclose_buttons:hover {
- border-color: #90ee90;
- }
-
- #UserScriptConfig .reset, #UserScriptConfig .reset a {
- color: #999;
- text-decoration: none;
- padding: 8px 16px;
- display: block;
- margin: 10px auto 0;
- font-size: 12px;
- text-align: center;
- }
-
- #UserScriptConfig .reset:hover, #UserScriptConfig .reset a:hover {
- color: #666;
- }
-
- #UserScriptConfig .config_var {
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
-
- `,
- 'frameStyle':
- `
- bottom: auto; border: 2px solid #6F6F6F; display: none; height: 290px;
- left: 50%; margin: 0; max-height: 100%; max-width: 100%; opacity: 0;
- overflow: auto; padding: 0; position: fixed; right: auto; top: 50%;
- width: 330px; z-index: 9999;
- border-radius: 8px;
- box-shadow: 10px 10px 20px rgba(0,0,0,0.4);
- `
- ,
- 'events':
- {
- 'open': function() {
- console.log("配置界面已開啟");
- },
- 'save': function() {
- console.log("設定已保存");
- enableAutoProcessOnBuyDPage = GM_config.get('enableAutoProcessOnBuyDPage');
- enableAutoSkip = GM_config.get('enableAutoSkip');
- alert("保存完成!");
- },
- 'close': function() {
- console.log("配置界面已關閉");
- },
- 'init': () => {
- console.log("UI初始化");
- //獲取使用者設定
- enableAutoProcessOnBuyDPage = GM_config.get('enableAutoProcessOnBuyDPage');
- enableAutoSkip = GM_config.get('enableAutoSkip');
- }
- }
- };
-
- // 初始化GM_config
- GM_config.init(GM_configStruct);
-
- //處理驗證流程
- function handleCaptchaVerification() {
- var captchaFound = false; // 用於標記是否找到驗證器
-
- // 嘗試執行Google reCAPTCHA
- var googleRecaptcha = document.getElementById('recaptcha');
- if (googleRecaptcha && typeof grecaptcha !== 'undefined' && grecaptcha.execute) {
- grecaptcha.execute();
- captchaFound = true; // 標記找到Google reCAPTCHA
- }
-
- // 嘗試執行Cloudflare Turnstile
- if (typeof turnstile !== 'undefined' && document.querySelector('.cf-turnstile')) {
- turnstile.render('.cf-turnstile');
- captchaFound = true; // 標記找到Cloudflare Turnstile
- }
-
- // 如果沒有找到任何驗證器,則提交表單
- if (!captchaFound) {
- jQuery('#buyD').submit();
- }
- }
-
- // 檢查目前頁面是否為 message_done 頁面
- if (window.location.href.includes('https://fuli.gamer.com.tw/message_done.php')) {
- // 在 message_done 頁面上執行的操作
- var button = document.querySelector('button');
- if (button) {
- button.click();
- }
- }
-
- // 等待頁面加載完畢
- window.addEventListener('load', function() {
- // 找到TOP-my元素
- var guiTopMyElement = document.querySelector('.TOP-my ul');
-
- // 創建GUI按鈕的列表項
- var guiButtonLi = document.createElement('li');
- guiButtonLi.className = 'mobilehide';
-
- // 創建GUI按鈕的連結元素
- var guiButtonLink = document.createElement('a');
- guiButtonLink.href = 'javascript:void(0)';
- guiButtonLink.onclick = function() {
- GM_config.open();
- };
-
- // 為GUI按鈕添加圖標
- var guiButtonIcon = document.createElement('img');
- guiButtonIcon.src = 'https://i.imgur.com/uj2yF4e.png';
- guiButtonLink.appendChild(guiButtonIcon);
-
- // 將連結元素加入到列表項中,然後將列表項加入到TOP-my區塊
- guiButtonLi.appendChild(guiButtonLink);
- guiTopMyElement.insertBefore(guiButtonLi, guiTopMyElement.firstChild); // 將GUI按鈕添加到最左側
-
- // 檢查目前頁面是否為 buyD 頁面
- if (enableAutoProcessOnBuyDPage && window.location.href.includes('https://fuli.gamer.com.tw/buyD.php')) {
- document.getElementById('agree-confirm').checked = true;
- handleCaptchaVerification();
- return;
- }
-
- //如果沒有兌換欄位
- var btnList = document.getElementById('buyBtnContent');
- if (!btnList) return;
- //看一下需不需要先回答問題,如果需要,回答問題並重整
- var questionButton = btnList.querySelector('a[onclick^="showQuestion(1);"]');
- if (questionButton) {
- getCsrfToken().then(token => {
- sendAnswerQuestionRequest(token);
- setTimeout(function() {
- location.reload();
- }, 2000);
- }).catch(error => {
- console.error('獲取 CSRF token 時發生錯誤:', error);
- });
- return;
- }
- //如果沒有看廣告兌換按鈕就return
- var adButton = btnList.querySelector('a[onclick^="window.FuliAd.checkAd"]');
- if (!adButton) return;
-
- var newButton = document.createElement('a');
- newButton.className = 'btn-base c-accent-o';
- newButton.textContent = '跳過廣告';
- newButton.href = '#';
- newButton.style.marginLeft = '10px';
-
- newButton.addEventListener('click', function(event) {
- event.preventDefault();
- executeAdSkippingProcess();
- });
-
- btnList.appendChild(newButton);
-
- // 如果啟用自動跳過廣告,則自動點擊新按鈕
- if (enableAutoSkip) {
- newButton.click();
- }
- });
-
-
-
- function executeAdSkippingProcess() {
- watchAdCheck();
- getCsrfToken().then(token => {
- setTimeout(function() {
- sendPostRequest(token);
- }, 2000);
- }).catch(error => {
- console.error('獲取 CSRF token 時發生錯誤:', error);
- });
- }
-
- // 獲取CSRF token
- function getCsrfToken() {
- return new Promise((resolve, reject) => {
- GM_xmlhttpRequest({
- method: "GET",
- url: "https://fuli.gamer.com.tw/ajax/getCSRFToken.php?_=1702883537159",
- onload: function(response) {
- var token = response.responseText.trim();
- if (token) {
- resolve(token);
- } else {
- reject('Token not found in response');
- }
- },
- onerror: function(error) {
- reject('Error during request: ' + error.message);
- }
- });
- });
- }
-
- function sendAnswerQuestionRequest(csrfToken) {
- // 獲取網頁中的問題和答案
- let templateContent = document.getElementById('question-popup').innerHTML;
- let tempDiv = document.createElement('div');
- tempDiv.innerHTML = templateContent;
-
- let questions = tempDiv.querySelectorAll('.fuli-option[data-question]');
- let questionNumbers = new Set();
- questions.forEach(question => {
- questionNumbers.add(question.getAttribute('data-question'));
- });
-
- let answers = [];
- questionNumbers.forEach(questionNumber => {
- let firstOption = tempDiv.querySelector(`.fuli-option[data-question="${questionNumber}"]`);
- answers.push(firstOption.getAttribute('data-answer'));
- });
-
-
- // 獲取sn
- var urlParams = new URLSearchParams(window.location.search);
- var snValue = urlParams.get('sn');
-
- // 準備payload
- var formData = new FormData();
- formData.append('sn', snValue);
- formData.append('token', csrfToken);
- answers.forEach(answer => formData.append('answer[]', answer));
-
- // 這一段只是在看payload而已...
- var object = {};
- formData.forEach((value, key) => {
- if(!Reflect.has(object, key)){
- object[key] = value;
- return;
- }
- if(!Array.isArray(object[key])){
- object[key] = [object[key]];
- }
- object[key].push(value);
- });
- var payloadData = JSON.stringify(object);
-
- // 發送post
- GM_xmlhttpRequest({
- method: "POST",
- url: "https://fuli.gamer.com.tw/ajax/answer_question.php",
- data: formData,
- onload: function(response) {
- console.log('Payload sent:', payloadData);
- console.log('回答問題post的回應:', response.responseText);
- }
- });
- }
-
-
-
-
- // 發送已看完廣告的post請求
- function sendPostRequest(csrfToken) {
- var urlParams = new URLSearchParams(window.location.search);
- var snValue = urlParams.get('sn');
- var adButton = document.querySelector('a[onclick^="window.FuliAd.checkAd"]');
- console.log('sn:',encodeURIComponent(snValue))
-
- if (!snValue) {
- console.log('無法獲取sn參數');
- return;
- }
-
- GM_xmlhttpRequest({
- method: "POST",
- url: "https://fuli.gamer.com.tw/ajax/finish_ad.php",
- headers: {
- "Content-Type": "application/x-www-form-urlencoded"
- },
- data: "token=" + encodeURIComponent(csrfToken) + "&area=item&sn=" + encodeURIComponent(snValue),
- onload: function(response) {
- console.log('post回應:', response.responseText);
- adButton.click();
- }
- });
- }
-
- // 發送get檢查是否已經看過廣告
- function watchAdCheck() {
- var urlParams = new URLSearchParams(window.location.search);
- var snValue = urlParams.get('sn');
- var adButton = document.querySelector('a[onclick^="window.FuliAd.checkAd"]');
-
- if (!snValue) {
- console.log('無法獲取sn參數');
- return;
- }
-
- GM_xmlhttpRequest({
- method: "GET",
- url: "https://fuli.gamer.com.tw/ajax/check_ad.php?area=item&sn=" + encodeURIComponent(snValue),
- onload: function(response) {
- try {
- var responseData = JSON.parse(response.responseText);
- if (responseData.data && responseData.data.finished === 1) {
- alert('你已經看過/跳過廣告了!');
- adButton.click();
- return;
- }else{
- clickAdButton();
- }
- } catch (e) {
- console.error('解析回應時發生錯誤:', e);
- }
- }
- });
- }
-
- // 自動點擊"看廣告免費兌換"按鈕
- function clickAdButton() {
- var adButton = document.querySelector('a[onclick^="window.FuliAd.checkAd"]');
- if (adButton) {
- adButton.click();
- startObservingDialog();
- }
- }
-
- // 監視對話框
- function startObservingDialog() {
- var observerOptions = {
- childList: true,
- subtree: true
- };
-
- observer = new MutationObserver(function(mutations, obs) {
- var dialog = document.querySelector('.dialogify__content');
- if (dialog) {
- var confirmButton = dialog.querySelector('.btn-box .btn-insert.btn-primary');
- if (confirmButton) {
- confirmButton.disabled = true;
- confirmButton.style.backgroundColor = '#e5e5e5';
- }
-
- setTimeout(function() {
- handleDialogButtons(dialog);
- obs.disconnect();
- }, 500);
- }
- });
-
- observer.observe(document.body, observerOptions);
- }
-
- // 處理確認窗口的按鈕
- function handleDialogButtons(dialog) {
- var cancelButton = dialog.querySelector('.btn-box .btn-insert:not(.btn-primary)');
- var confirmButton = dialog.querySelector('.btn-box .btn-insert.btn-primary');
-
- if (cancelButton) {
- setTimeout(function() {
- cancelButton.click();
- if (confirmButton) {
- confirmButton.disabled = false;
- confirmButton.style.backgroundColor = '';
- }
- }, 1000);
- }
- }
- })();