-
-
Notifications
You must be signed in to change notification settings - Fork 86
Expand file tree
/
Copy pathalgorithmBuilder.js
More file actions
145 lines (127 loc) · 6.07 KB
/
Copy pathalgorithmBuilder.js
File metadata and controls
145 lines (127 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright (c) 2024-2026 nich (@nichxbt). Licensed under the Apache License, Version 2.0.
// scripts/algorithmBuilder.js
// Browser console script for training X's algorithm by engaging with niche content
// Paste in DevTools console on x.com/home or x.com/search
// by nichxbt
(() => {
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
// =============================================
// CONFIGURATION
// =============================================
const CONFIG = {
topics: ['AI', 'startups', 'web3'], // Niches to train on
scrollRounds: 6, // Rounds per topic
scrollDelay: 2000, // ms between scrolls
likeRatio: 0.5, // Like 50% of relevant tweets
followRatio: 0.2, // Follow 20% of relevant users
maxLikes: 30, // Max likes per session
maxFollows: 10, // Max follows per session
actionDelay: 2500, // ms between actions
dryRun: true, // SET FALSE TO EXECUTE
};
// =============================================
const download = (data, filename) => {
const a = document.createElement('a');
a.href = URL.createObjectURL(new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }));
a.download = filename;
document.body.appendChild(a);
a.click();
a.remove();
console.log(`📥 Downloaded: ${filename}`);
};
let totalLikes = 0;
let totalFollows = 0;
const engaged = [];
const scrapeTweets = async () => {
const tweets = [];
const seen = new Set();
for (let round = 0; round < CONFIG.scrollRounds; round++) {
const articles = document.querySelectorAll('article[data-testid="tweet"]');
for (const article of articles) {
const textEl = article.querySelector('[data-testid="tweetText"]');
if (!textEl) continue;
const text = textEl.textContent.trim();
const fp = text.slice(0, 80);
if (seen.has(fp)) continue;
seen.add(fp);
const likeBtn = article.querySelector('[data-testid="like"]');
const isLiked = !!article.querySelector('[data-testid="unlike"]');
const authorLink = article.querySelector('a[href^="/"][role="link"]');
const authorMatch = authorLink ? (authorLink.getAttribute('href') || '').match(/^\/([A-Za-z0-9_]+)/) : null;
const author = authorMatch ? authorMatch[1] : 'unknown';
const followBtn = article.querySelector('[data-testid$="-follow"]');
tweets.push({ text, author, likeBtn, isLiked, followBtn, article });
}
console.log(` 📜 Round ${round + 1}: ${tweets.length} tweets`);
window.scrollTo(0, document.body.scrollHeight);
await sleep(CONFIG.scrollDelay);
}
return tweets;
};
const engageTopic = async (topic) => {
console.log(`\n🔍 Searching: "${topic}"...`);
window.location.href = `https://x.com/search?q=${encodeURIComponent(topic)}&src=typed_query&f=live`;
await sleep(4000);
const tweets = await scrapeTweets();
console.log(`📊 Found ${tweets.length} tweets for "${topic}"`);
for (const tweet of tweets) {
if (totalLikes >= CONFIG.maxLikes && totalFollows >= CONFIG.maxFollows) break;
// Like
if (!tweet.isLiked && tweet.likeBtn && totalLikes < CONFIG.maxLikes && Math.random() < CONFIG.likeRatio) {
if (CONFIG.dryRun) {
console.log(` 🏃 [DRY] Would like @${tweet.author}: "${tweet.text.slice(0, 50)}..."`);
} else {
tweet.likeBtn.click();
console.log(` ❤️ Liked @${tweet.author}: "${tweet.text.slice(0, 50)}..."`);
}
totalLikes++;
engaged.push({ action: 'like', author: tweet.author, topic, text: tweet.text.slice(0, 100) });
await sleep(CONFIG.actionDelay);
}
// Follow
if (tweet.followBtn && totalFollows < CONFIG.maxFollows && Math.random() < CONFIG.followRatio) {
if (CONFIG.dryRun) {
console.log(` 🏃 [DRY] Would follow @${tweet.author}`);
} else {
tweet.followBtn.click();
console.log(` ➕ Followed @${tweet.author}`);
}
totalFollows++;
engaged.push({ action: 'follow', author: tweet.author, topic });
await sleep(CONFIG.actionDelay);
}
}
};
const run = async () => {
console.log('╔════════════════════════════════════════════════╗');
console.log('║ 🧠 ALGORITHM BUILDER ║');
console.log('║ by nichxbt — v1.0 ║');
console.log('╚════════════════════════════════════════════════╝');
if (CONFIG.dryRun) console.log('\n🏃 DRY RUN — no actions will be taken.');
console.log(`📋 Topics: ${CONFIG.topics.join(', ')}`);
console.log(`🎯 Limits: ${CONFIG.maxLikes} likes, ${CONFIG.maxFollows} follows\n`);
for (const topic of CONFIG.topics) {
if (totalLikes >= CONFIG.maxLikes && totalFollows >= CONFIG.maxFollows) break;
await engageTopic(topic);
}
console.log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(' 📊 SESSION SUMMARY');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log(` ❤️ Likes: ${totalLikes}`);
console.log(` ➕ Follows: ${totalFollows}`);
console.log(` 📝 Topics: ${CONFIG.topics.length}`);
if (CONFIG.dryRun) console.log(' 🏃 (Dry run — nothing executed)');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (engaged.length > 0) {
download({
topics: CONFIG.topics,
totalLikes,
totalFollows,
engaged,
dryRun: CONFIG.dryRun,
timestamp: new Date().toISOString(),
}, `xactions-algorithm-builder-${Date.now()}.json`);
}
};
run();
})();