Frustrated by a minor detail
Yes, a minor detail, because I'm sure it's incredibly simple, but it's not working.
My bot correctly sends all the votes to a list, then sorts the posts by tag.
I'm properly logged into the keychain with the correct account, but when I click "vote," nothing happens. It only gives me errors: either "broken post" or "post doesn't exist." So it's not a keychain detection issue.

If any coders happen to stumble across this ^^, here's the current code.
<?php
$file = 'votes-log.json';
// CLEAR
if (isset($_GET['clear'])) {
file_put_contents($file, json_encode([]));
echo "cleared";
exit;
}
// SAVE
$input = file_get_contents("php://input");
$data = json_decode($input, true);
if ($data) {
$existing = file_exists($file)
? json_decode(file_get_contents($file), true)
: [];
if (!is_array($existing)) $existing = [];
$seen = [];
foreach ($existing as $v) {
$seen[$v['author'].'/'.$v['permlink']] = true;
}
$list = isset($data[0]) ? $data : [$data];
foreach ($list as $v) {
$key = $v['author'].'/'.$v['permlink'];
if (!isset($seen[$key])) {
$existing[] = $v;
$seen[$key] = true;
}
}
file_put_contents($file, json_encode($existing, JSON_PRETTY_PRINT));
echo json_encode(["ok" => true]);
exit;
}
// LOAD
$votes = file_exists($file)
? json_decode(file_get_contents($file), true)
: [];
if (!is_array($votes)) $votes = [];
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>π Hive Voting Bot</title>
<style>
* { box-sizing: border-box; }
body {
background: #0a0a0f;
color: #fff;
font-family: Arial;
margin: 0;
padding: 0;
padding-top: 120px;
}
h1 {
text-align: center;
color: #00f7ff;
margin: 0;
padding: 15px 0 5px 0;
}
h2 {
color: #00f7ff99;
padding-left: 20px;
}
/* ββ TOPBAR ββ */
#topbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
background: #0d0d1a;
border-bottom: 1px solid #00f7ff33;
z-index: 9999;
padding: 10px 20px;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px;
}
#topbar input {
padding: 8px;
border-radius: 6px;
border: none;
background: #222;
color: #fff;
width: 180px;
}
#topbar button {
padding: 8px 12px;
border-radius: 6px;
border: none;
background: #00f7ff;
color: #000;
cursor: pointer;
font-weight: bold;
}
#accountStatus {
color: #00ff88;
font-size: 13px;
}
#searchInput {
width: 200px;
}
/* ββ CARDS ββ */
.container {
display: flex;
flex-wrap: wrap;
gap: 20px;
padding: 20px;
}
.card {
background: #111;
border: 1px solid #00f7ff33;
border-radius: 10px;
padding: 15px;
width: 300px;
box-shadow: 0 0 10px #00f7ff22;
}
.priority {
border: 1px solid #00ff88;
box-shadow: 0 0 15px #00ff8844;
}
.card h3 {
margin-top: 0;
color: #00f7ff;
}
.card button {
background: #00f7ff;
border: none;
padding: 8px 12px;
cursor: pointer;
border-radius: 5px;
font-weight: bold;
color: #000;
}
.card input {
width: 55px;
padding: 4px;
border-radius: 4px;
border: none;
background: #222;
color: #fff;
text-align: center;
}
.small {
font-size: 12px;
color: #aaa;
}
.progress {
font-size: 12px;
margin-top: 8px;
color: #ccc;
max-height: 120px;
overflow-y: auto;
}
</style>
</head>
<body>
<!-- ββ TOPBAR ββ -->
<div id="topbar">
<span style="color:#00f7ff; font-weight:bold;">π Hive Bot</span>
<!-- Compte -->
<input id="hiveAccount" placeholder="Votre compte Hive">
<button onclick="saveAccount()">β
Connecter</button>
<span id="accountStatus">non connectΓ©</span>
<!-- Search -->
<input id="searchInput" placeholder="π Tag (ex: cent)" onkeydown="if(event.key==='Enter') searchTag()">
<button onclick="searchTag()">Chercher</button>
<!-- Reset -->
<button onclick="clearVotes()" style="background:#ff4444; color:#fff;">π§Ή Reset</button>
</div>
<h1>π Hive Voting Bot</h1>
<h2>β Tags prioritaires</h2>
<div id="priority" class="container"></div>
<h2>π¦ Autres tags</h2>
<div id="others" class="container"></div>
<script>
// ββ DATA ββ
const votes = <?php echo json_encode($votes); ?>;
// ββ TAG β COMPTE VOTEUR ββ
const tagMap = {
cent: "benef.cent",
alive: "benef.alive",
archon: "benef.archon",
heartbeat: "benef.alive",
neoxian: "benef.neoxian",
bbh: "benef.bbho",
tribes: "token-thx",
sportstalk: "commentators"
};
// ββ GROUPE PAR TAG ββ
const grouped = {};
votes.forEach(v => {
if (!v || !v.author || !v.permlink) return;
const key = v.author + "/" + v.permlink;
let tags = [];
if (Array.isArray(v.tags)) {
tags = v.tags.slice(0, 10);
} else if (v.tag) {
tags = [v.tag];
} else {
tags = ["unknown"];
}
tags.forEach(tag => {
tag = (tag || "unknown").toLowerCase().trim();
if (!grouped[tag]) grouped[tag] = {};
grouped[tag][key] = v;
});
});
// ββ COMPTE COURANT ββ
let currentAccount = localStorage.getItem("hive_account") || null;
if (currentAccount) {
document.addEventListener("DOMContentLoaded", () => {
document.getElementById("accountStatus").innerText = "β
@" + currentAccount;
document.getElementById("hiveAccount").value = currentAccount;
});
}
function saveAccount() {
const val = document.getElementById("hiveAccount").value.trim();
if (!val) return;
currentAccount = val;
localStorage.setItem("hive_account", val);
document.getElementById("accountStatus").innerText = "β
@" + val;
}
// ββ CRΓER UNE CARD ββ
function createCard(tag, posts, isPriority) {
const div = document.createElement("div");
div.className = "card" + (isPriority ? " priority" : "");
div.setAttribute("data-tag", tag);
const compte = tagMap[tag] ? `<div class="small">Compte: @${tagMap[tag]}</div>` : "";
div.innerHTML = `
<h3>#${tag}</h3>
${compte}
<div style="margin:8px 0;">
Puissance: <input id="power_${tag}" value="5" type="number" min="1" max="100"> %
</div>
<button onclick="voteTag('${tag}')">β‘ Voter</button>
<div class="progress" id="progress_${tag}"></div>
<hr style="border-color:#ffffff11;">
<div class="small">${posts.length} posts</div>
`;
return div;
}
// ββ BUILD UI ββ
const priorityDiv = document.getElementById("priority");
const otherDiv = document.getElementById("others");
Object.keys(tagMap).forEach(tag => {
if (grouped[tag]) {
priorityDiv.appendChild(
createCard(tag, Object.values(grouped[tag]), true)
);
}
});
Object.keys(grouped)
.filter(tag => !tagMap[tag])
.sort()
.forEach(tag => {
otherDiv.appendChild(
createCard(tag, Object.values(grouped[tag]), false)
);
});
// ββ VOTE ββ
function voteTag(tag) {
if (!window.hive_keychain) {
alert("β Keychain non installΓ©");
return;
}
if (!currentAccount) {
alert("β οΈ Entre ton compte Hive en haut !");
return;
}
const power = Math.min(100, Math.max(1,
parseInt(document.getElementById("power_" + tag).value) || 5
));
const posts = Object.values(grouped[tag] || {});
const box = document.getElementById("progress_" + tag);
if (posts.length === 0) {
box.innerHTML = "β οΈ Aucun post";
return;
}
box.innerHTML = `β³ ${posts.length} posts Γ voter...`;
let i = 0;
function next() {
if (i >= posts.length) {
box.innerHTML += "<br><br>β
β
TERMINE";
return;
}
const v = posts[i];
let author = (v.author || "").replace("@", "").trim();
let permlink = (v.permlink || "").trim();
// β
nettoyage permlink (FIX CRUCIAL)
if (permlink.includes("/")) {
const parts = permlink.split("/");
permlink = parts[parts.length - 1];
}
permlink = permlink.substring(0, 255);
// β
validation
if (!author || !permlink) {
box.innerHTML += `<br>β οΈ skip (vide)`;
i++;
return next();
}
if (permlink.length > 255) {
box.innerHTML += `<br>β οΈ skip (trop long)`;
i++;
return next();
}
box.innerHTML = `
Vote ${i+1}/${posts.length}<br>
π @${author}
`;
console.log("VOTE β", {
voter: currentAccount,
author,
permlink,
weight: power * 100
});
window.hive_keychain.requestVote(
currentAccount,
author,
permlink,
power * 100,
function(res) {
console.log("KEYCHAIN:", res);
if (!res) {
box.innerHTML += "<br>β aucune rΓ©ponse";
}
else if (!res.success) {
box.innerHTML += `<br>β ${res.message || "erreur"}`;
}
else {
box.innerHTML += "<br>β
OK";
}
i++;
// β
dΓ©lai safe (IMPORTANT)
setTimeout(next, 5000);
}
);
}
next();
}
// ββ CLEAR ββ
function clearVotes() {
fetch("4.php?clear=1").then(() => location.reload());
}
// ββ SEARCH ββ
function searchTag() {
const value = document.getElementById("searchInput").value.toLowerCase().trim();
if (!value) return;
const cards = document.querySelectorAll(".card");
for (let card of cards) {
const t = card.getAttribute("data-tag");
if (t === value) {
card.scrollIntoView({ behavior: "smooth", block: "center" });
card.style.boxShadow = "0 0 25px #00f7ff";
setTimeout(() => card.style.boxShadow = "", 2000);
return;
}
}
alert("Tag non trouvΓ© : " + value);
}
</script>
</body>
</html>