// ==UserScript==
// @name FarmRPG - Quick Farm Tasks
// @namespace duck.wowow
// @version 0.1
// @description Adds buttons outside of the relevant page to allow the user to do daily tasks quickly. Visit farm supply to allow the script to confirm you own the perks for chickens, cows and pigs in order to unlock their pet/feed buttons
// @author Odung
// @match https://farmrpg.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=farmrpg.com
// @grant GM.getValue
// @grant GM.setValue
// @require https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.min.js
// @license MIT
// ==/UserScript==
(async function() {
'use strict';
const now = luxon.DateTime.now().setZone("America/Chicago").startOf("day");
const current = now.day;
const farmData = await GM.getValue('farm', {chicken: 0, cow: 0, pig: 0, storehouse: 0, farmhouse: 0, raptor: 0});
let perks = await GM.getValue('perks', {});
function observePage(element) {
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'data-page') {
const page = mutation.target.getAttribute('data-page');
if (page === 'xfarm') farm();
else if (page === 'supply') supply();
}
}
});
observer.observe(element, { attributes: true });
}
function farm() {
const id = getFarmId();
if (!id) return;
const observer = new MutationObserver(() => {
const elements = [
{ selector: 'div.page:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(7) > div:nth-child(1) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(1) > a:nth-child(1) > div:nth-child(1) > div:nth-child(1)', title: "Pet", url: "https://farmrpg.com/worker.php?go=petallchickens", id: 'chicken' },
{ selector: 'div.page:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(7) > div:nth-child(1) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(2) > a:nth-child(1) > div:nth-child(1) > div:nth-child(1)', title: "Pet", url: "https://farmrpg.com/worker.php?go=petallcows", id: 'cow' },
{ selector: 'div.page:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(7) > div:nth-child(1) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(3) > a:nth-child(1) > div:nth-child(1) > div:nth-child(1)', title: "Feed", url: "https://farmrpg.com/worker.php?go=feedallpigs", id: 'pig' },
{ selector: 'div.page:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(7) > div:nth-child(1) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(4) > a:nth-child(1) > div:nth-child(1) > div:nth-child(1)', title: "Work", url: `https://farmrpg.com/worker.php?go=work&id=${id}`, id: 'storehouse' },
{ selector: 'div.page:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(7) > div:nth-child(1) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(5) > a:nth-child(1) > div:nth-child(1) > div:nth-child(1)', title: "Rest", url: `https://farmrpg.com/worker.php?go=rest&id=${id}`, id: 'farmhouse' },
{ selector: 'div.page:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(7) > div:nth-child(1) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(6) > a:nth-child(1) > div:nth-child(1) > div:nth-child(1)', title: "Pet", url: "https://farmrpg.com/worker.php?go=incuallraptors", id: 'raptor' }
];
let found = false;
elements.forEach(({ selector, title, url, id }) => {
const element = document.querySelector(selector);
if (element) {
found = true;
if (!element.querySelector("button") && farmData[id] !== current) {
if (id === 'chicken' && !perks['Pet-o-Matic I']) return;
else if (id === 'cow' && !perks['Pet-o-Matic II']) return;
else if (id === 'pig' && !perks['Feed-o-Matic I']) return;
element.appendChild(createButton(title, url, id, selector));
}
}
});
if (found) observer.disconnect();
});
observer.observe(document.body, { childList: true, subtree: true });
}
function createButton(title, url, id, selector) {
const button = document.createElement("button");
button.textContent = title;
button.id = id;
button.style.cssText = `display: flex; width: 50px; align-items: center; justify-content: center; padding: 8px 12px; margin-left: 10px; font-size: 14px; font-weight: bold; border: none; border-radius: 5px; background: #333; color: #fff; cursor: pointer; transition: background 0.2s ease, transform 0.1s ease;`;
button.addEventListener("mouseenter", () => {
button.style.background = "#444";
button.style.transform = "scale(1.05)";
});
button.addEventListener("mouseleave", () => {
button.style.background = "#333";
button.style.transform = "scale(1)";
});
button.addEventListener("click", async () => {
event.preventDefault();
event.stopPropagation();
try {
const response = await fetch(url, { method: "POST" });
console.log(response);
if (response.ok) {
farmData[id] = current;
await GM.setValue('farm', farmData);
button.remove();
const calendar = document.querySelector(selector)?.parentElement.querySelector('.f7-icons')?.parentElement;
if (calendar) calendar.remove();
} else {
button.textContent = 'Error';
setTimeout(() => {
button.textContent = title;
}, 1000);
}
} catch (error) {
console.error(error);
}
});
return button;
}
function getFarmId() {
const match = window.location.href.match(/id=(\d+)/);
return match ? match[1] : null;
}
async function supply() {
const playerPerks = {};
const requiredPerks = ['Pet-o-Matic I', 'Pet-o-Matic II', 'Feed-o-Matic I'];
if (!Array.from(document.querySelectorAll(".item-title strong")).find(el => el.textContent.trim() === 'Pet-o-Matic I')) return;
requiredPerks.forEach(perk => {
if (Array.from(document.querySelectorAll(".item-title strong")).find(el => el.textContent.trim() === perk).parentElement.nextElementSibling.firstElementChild.classList.contains('btnblue')) playerPerks[perk] = true;
});
perks = playerPerks;
await GM.setValue('perks', playerPerks);
}
const observer = new MutationObserver(mutations => {
const element = document.querySelector('#fireworks');
if (element) {
observePage(element);
observer.disconnect();
}
});
observer.observe(document.body, { childList: true, subtree: true });
})();