RE: Update Bot auto curation

You are viewing a single comment's thread:

part 3

...
(html comment removed: ========== PATCH 2: Account Switcher ========== )


🔐 Voting Account

    <div style="display: flex; gap: 10px; align-items: center; margin-bottom: 10px;">
        <input 
            type="text" 
            id="account-input" 
            placeholder="Enter Hive username"
            style="flex: 1; padding: 10px; background: rgba(18, 18, 48, 0.8); border: 1px solid rgba(178, 0, 255, 0.3); border-radius: 8px; color: var(--text-primary); font-size: 1rem;"
        />
        <button 
            id="connect-btn" 
            onclick="connectAccount()"
            style="padding: 10px 20px; white-space: nowrap;">
            🔗 Connect & Validate
        </button>
    </div>
    
    <div id="account-status" style="display: none; padding: 10px; border-radius: 6px; margin-top: 10px; font-size: 0.9rem;"></div>
</div>

    <p><strong>Eligible Posts:</strong> <span style="color: var(--neon-green);"><?php echo count($eligible_posts); ?></span>/<?php echo count($posts); ?></p>
    
    (html comment removed:  ========== AFFICHAGE DES RÈGLES DE VOTE ========== )
    <div style="margin-top: 20px; padding: 15px; background: rgba(0, 212, 255, 0.05); border-radius: 8px; border: 1px solid rgba(0, 212, 255, 0.2);">
        <h3 style="color: var(--neon-blue); margin-bottom: 10px; font-size: 1.1rem;">⚙️ Vote Rules</h3>
        <?php foreach ($VOTE_RULES as $min_words => $weight): ?>
            <p style="margin: 5px 0; font-size: 0.95rem;">
                <span style="color: var(--neon-yellow);">≥ <?php echo $min_words; ?> words</span> 
                → 
                <span style="color: var(--neon-green); font-weight: bold;"><?php echo $weight / 100; ?>%</span>
            </p>
        <?php endforeach; ?>
    </div>
</div>

<?php if (count($eligible_posts) > 0): ?>
<div class="card">
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
        <h2 style="margin: 0;">✅ Eligible Posts (<?php echo count($eligible_posts); ?>)</h2>
        <button onclick="voteAll()" style="padding: 10px 20px;">🚀 Vote All</button>
    </div>

    <table>
        <thead>
            <tr>
                <th>Author</th>
                <th>Title</th>
                <th>Words</th>
                <th>Weight</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($eligible_posts as $p): 
                $words = count_words($p['body']);
                $vote_weight = get_vote_weight($words);
            ?>
            <tr>
                <td>
                    <a href="https://peakd.com/@<?php echo $p['author']; ?>" 
                       target="_blank" 
                       style="color: var(--neon-blue); text-decoration: none;">
                        @<?php echo $p['author']; ?>
                    </a>
                </td>
                <td>
                    <a href="https://peakd.com/@<?php echo $p['author']; ?>/<?php echo $p['permlink']; ?>" 
                       target="_blank"
                       style="color: var(--text-primary); text-decoration: none;">
                        <?php echo htmlspecialchars(mb_substr($p['title'], 0, 60)) . (mb_strlen($p['title']) > 60 ? '...' : ''); ?>
                    </a>
                </td>
                <td><?php echo $words; ?></td>
                <td>
                    <span style="
                        color: <?php 
                            echo $vote_weight >= 600 ? 'var(--neon-green)' : 
                                 ($vote_weight >= 500 ? 'var(--neon-yellow)' : 'var(--neon-blue)'); 
                        ?>;
                        font-weight: bold;
                    ">
                        <?php echo $vote_weight / 100; ?>%
                    </span>
                </td>
                <td>
                    <button
                        class="vote-btn"
                        onclick="votePost(
                            '<?php echo addslashes($p['author']); ?>',
                            '<?php echo addslashes($p['permlink']); ?>',
                            this,
                            <?php echo $words; ?>
                        )">
                        Vote <?php echo $vote_weight / 100; ?>%
                    </button>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>
<?php else: ?>
<div class="card">
    <h2>⚠️ No Eligible Posts</h2>
    <p style="color: var(--text-secondary);">All posts have already been voted on or don't meet criteria.</p>
</div>
<?php endif; ?>

(html comment removed:  ========== PATCH 1: Vote History (AMÉLIORÉ) ========== )
<div id="vote-history" style="
    margin-top: 40px;
    padding: 30px;
    background: linear-gradient(135deg, rgba(18, 18, 48, 0.95), rgba(30, 30, 70, 0.85));
    border-radius: 15px;
    border: 2px solid var(--neon-purple);
    box-shadow: 0 8px 32px rgba(178, 0, 255, 0.3);
">
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
        <h2 style="
            font-family: 'Orbitron', sans-serif;
            color: var(--neon-purple);
            text-shadow: 0 0 10px var(--neon-purple);
            margin: 0;
        ">📊 Vote Session History</h2>
        <button onclick="clearVoteHistory()" style="
            background: linear-gradient(45deg, #ff0040, #ff6b9d);
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 8px;
            cursor: pointer;
            font-weight: bold;
            transition: all 0.3s;
            font-family: 'Orbitron', sans-serif;
        " onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
            🗑️ Clear History
        </button>
    </div>
    <div id="history-list" style="
        display: grid;
        gap: 15px;
        max-height: 500px;
        overflow-y: auto;
    "></div>
</div>



<script>
    // ========== CONFIGURATION ==========
    const VOTE_STORAGE_KEY = 'hiveVoteHistory';
    const ACCOUNT_STORAGE_KEY = 'hiveVoterAccount';
    const VOTE_DELAY = 5000;
    const AUTO_REFRESH_DELAY = 900000;
    
    // ========== AUTO-VOTE CONFIG (FROM PHP) ==========
    const AUTO_VOTE_ENABLED = <?php echo AUTO_VOTE_ENABLED ? 'true' : 'false'; ?>;
    const AUTO_VOTE_DELAY = <?php echo AUTO_VOTE_DELAY; ?>;
    const AUTO_REFRESH_AFTER_VOTE = <?php echo AUTO_REFRESH_AFTER_VOTE ? 'true' : 'false'; ?>;

    // ========== VOTE RULES (SYNCHRONIZED WITH PHP) ==========
    const VOTE_RULES = <?php echo json_encode($VOTE_RULES); ?>;

    function calculateVoteWeight(wordCount) {
        // Trie les seuils par ordre décroissant
        const sortedThresholds = Object.keys(VOTE_RULES)
            .map(Number)
            .sort((a, b) => b - a);
        
        for (const minWords of sortedThresholds) {
            if (wordCount >= minWords) {
                return VOTE_RULES[minWords];
            }
        }
        return 0;
    }

    // ========== VOTE SESSION ==========
    let voteSession = {
        history: [],
        votedPosts: []
    };

    let autoRefreshTimer = null;

    // ========== CONNECT ACCOUNT ==========
    function connectAccount() {
        const accountInput = document.getElementById('account-input');
        const statusDiv = document.getElementById('account-status');
        const username = accountInput.value.trim().replace('@', '');
        
        if (!username) {
            alert('⚠️ Please enter a username');
            return;
        }

        statusDiv.style.display = 'block';
        statusDiv.className = 'status-badge status-loading';
        statusDiv.textContent = '⏳ Validating account...';

        fetch('https://api.hive.blog', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                jsonrpc: '2.0',
                method: 'condenser_api.get_accounts',
                params: [[username]],
                id: 1
            })
        })
        .then(res => res.json())
        .then(data => {
            if (data.result && data.result.length > 0) {
                localStorage.setItem(ACCOUNT_STORAGE_KEY, username);
                document.getElementById('current-account-display').textContent = `@${username}`;
                statusDiv.className = 'status-badge status-success';
                statusDiv.textContent = `✅ Connected as @${username}`;
                console.log(`✅ Account validated: @${username}`);
            } else {
                statusDiv.className = 'status-badge status-failed';
                statusDiv.textContent = '❌ Account not found';
            }
        })
        .catch(err => {
            statusDiv.className = 'status-badge status-failed';
            statusDiv.textContent = '❌ Connection error';
            console.error(err);
        });
    }

    // ========== VOTE FUNCTION ==========
    function votePost(author, permlink, button, wordCount) {
        const savedAccount = localStorage.getItem(ACCOUNT_STORAGE_KEY) || '<?php echo VOTER_ACCOUNT; ?>';
        
        if (button.disabled) return;
        
        button.disabled = true;
        button.textContent = "⏳ Voting...";

        // Calculate weight using centralized function
        let weight = calculateVoteWeight(wordCount);

        console.log(`🗳️ Voting for @${author}/${permlink} with ${weight/100}% (${wordCount} words)`);

        hive_keychain.requestVote(
            savedAccount,
            permlink,
            author,
            weight,
            response => {
                if (response.success) {
                    button.textContent = "✅ Voted";
                    button.classList.add("voted");
                    addVoteToSession(author, permlink, weight, true);
                    updateHistoryDisplay();
                    console.log(`✅ Successfully voted for @${author}/${permlink}`);
                } else {
                    button.textContent = "❌ Failed";
                    button.style.background = "linear-gradient(90deg, var(--neon-red), #ff7a18)";
                    console.error("Vote error:", response.message);
                    alert(`❌ Vote failed: ${response.message}`);
                }
            }
        );
    }

    // ========== ADD VOTE TO SESSION ==========
    function addVoteToSession(author, permlink, weight, success) {
        const voteData = {
            author: author,
            permlink: permlink,
            weight: weight,
            success: success,
            timestamp: Date.now()
        };
        
        voteSession.history.unshift(voteData);
        voteSession.votedPosts.push(`${author}/${permlink}`);
        
        localStorage.setItem(VOTE_STORAGE_KEY, JSON.stringify(voteSession));
    }

    // ========== LOAD VOTE SESSION ==========
    function loadVoteSession() {
        const stored = localStorage.getItem(VOTE_STORAGE_KEY);
        if (stored) {
            voteSession = JSON.parse(stored);
            updateHistoryDisplay();
        }
    }

    // ========== CLEAR VOTE HISTORY ==========
    function clearVoteHistory() {
        if (confirm('🗑️ Clear all vote history?')) {
            voteSession = { history: [], votedPosts: [] };
            localStorage.removeItem(VOTE_STORAGE_KEY);
            updateHistoryDisplay();
            console.log('✅ Vote history cleared');
        }
    }

    // ========== UPDATE HISTORY DISPLAY ==========
    function updateHistoryDisplay() {
        const historyList = document.getElementById('history-list');
        
        if (voteSession.history.length === 0) {
            historyList.innerHTML = '<p style="text-align: center; color: var(--text-secondary); padding: 20px;">No votes yet in this session</p>';
            return;
        }

        historyList.innerHTML = voteSession.history.map(vote => {
            const authorName = `@${vote.author}`;
            const postUrl = `https://peakd.com/@${vote.author}/${vote.permlink}`;
            const profileUrl = `https://peakd.com/@${vote.author}`;
            const avatarUrl = `https://images.hive.blog/u/${vote.author}/avatar`;
            const timeAgo = getTimeAgo(vote.timestamp);
            
            return `
                <div class="history-item">
                    <a href="${profileUrl}" target="_blank">
                        <img src="${avatarUrl}" alt="${authorName}" class="history-avatar" 
                             onerror="this.src='https://images.hive.blog/u/hive.blog/avatar'">
                    </a>
                    
                    <div class="history-content">
                        <a href="${profileUrl}" target="_blank" class="history-author">
                            ${authorName}
                        </a>
                        <a href="${postUrl}" target="_blank" class="history-post-link">
                            🔗 View post on PeakD
                        </a>
                    </div>
                    
                    <div class="history-meta">
                        <span class="history-weight">💎 ${vote.weight / 100}%</span>
                        <span class="history-time">${timeAgo}</span>
                    </div>
                </div>
            `;
        }).join('');
    }

    function getTimeAgo(timestamp) {
        const now = Date.now();
        const diffMs = now - timestamp;
        const diffMins = Math.floor(diffMs / 60000);
        
        if (diffMins < 1) return 'Just now';
        if (diffMins < 60) return `${diffMins}m ago`;
        
        const diffHours = Math.floor(diffMins / 60);
        if (diffHours < 24) return `${diffHours}h ago`;
        
        const diffDays = Math.floor(diffHours / 24);
        return `${diffDays}d ago`;
    }

// ========== AUTO-VOTE FUNCTION ==========
async function startAutoVote() {

const username = localStorage.getItem(ACCOUNT_STORAGE_KEY)
    || '<?php echo VOTER_ACCOUNT; ?>';

// ✅ CHECK VP LIVE AU DÉMARRAGE
const res = await fetch('https://api.hive.blog', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        jsonrpc: '2.0',
        method: 'condenser_api.get_accounts',
        params: [[username]],
        id: 1
    })
});

const data = await res.json();
const liveVP = data?.result?.[0]
    ? Math.round(data.result[0].voting_power / 100)
    : 0;

console.log(`🔋 VP au démarrage : ${liveVP}%`);

if (liveVP < <?php echo MIN_VP_THRESHOLD; ?>) {
    console.log("⛔ VP insuffisant, auto-vote annulé");
    return;
}

// ✅ TON CODE AUTO-VOTE EXISTANT
const buttons = document.querySelectorAll("button.vote-btn:not([disabled])");

if (buttons.length === 0) {
    console.log("✅ No posts to vote");
    if (AUTO_REFRESH_AFTER_VOTE) scheduleAutoRefresh();
    return;
}

console.log(`🤖 AUTO-VOTE: Starting for ${buttons.length} posts`);
showAutoVoteIndicator(buttons.length);

let index = 0;
function voteNext() {
    if (index >= buttons.length) {
        console.log("✅ AUTO-VOTE: Complete");
        hideAutoVoteIndicator();
        if (AUTO_REFRESH_AFTER_VOTE) scheduleAutoRefresh();
        return;
    }

    updateAutoVoteIndicator(index + 1, buttons.length);
    buttons[index].click();
    index++;
    setTimeout(voteNext, AUTO_VOTE_DELAY);
}

voteNext();

}

    // ========== VOTE ALL FUNCTION (MANUAL) ==========
    function voteAll() {
        const buttons = document.querySelectorAll("button.vote-btn:not([disabled])");
        
        if (buttons.length === 0) {
            console.log("✅ No eligible posts - refreshing in 5 seconds");
            scheduleAutoRefresh();
            return;
        }

        let index = 0;
        function voteNext() {
            if (index >= buttons.length) {
                console.log("✅ Voting complete - refreshing in 5 seconds");
                scheduleAutoRefresh();
                return;
            }
            buttons[index].click();
            index++;
            setTimeout(voteNext, 3000);
        }

        voteNext();
    }

...



0
0
0.000
0 comments