gpt4 book ai didi

javascript - 脚本从头到尾顺利运行,但没有出现预期的结果

转载 作者:行者123 更新时间:2023-12-05 00:35:20 25 4
gpt4 key购买 nike

该项目旨在研究一种新的社交媒体:
https://booyah.live/
我的需求是:
1 - 从遵循特定配置文件的配置文件中收集数据。
2 - 我的帐户使用此数据来跟踪收集的配置文件。
3 - 在其他可能的选项中,也取消关注我关注的配置文件。
当前脚本中发现的问题:
理论上正在收集配置文件数据,脚本完美运行直到结束,但由于某种原因我无法指定,而不是遵循所有收集的配置文件,它只遵循基本配置文件。
例如:
我想关注 ID 为 123456 的所有 250 个配置文件
我激活 booyahGetAccounts(123456); 脚本
理论上,最终结果将是我的帐户关注 250 个配置文件
但最终结果我只关注 123456 配置文件,所以我关注的人数是 1
完整的项目脚本:

const csrf = 'MY_CSRF_TOKEN';
async function booyahGetAccounts(uid, type = 'followers', follow = 1) {
if (typeof uid !== 'undefined' && !isNaN(uid)) {
const loggedInUserID = window.localStorage?.loggedUID;
if (uid === 0) uid = loggedInUserID;
const unfollow = follow === -1;
if (unfollow) follow = 1;
if (loggedInUserID) {
if (csrf) {
async function getUserData(uid) {
const response = await fetch(`https://booyah.live/api/v3/users/${uid}`),
data = await response.json();
return data.user;
}
const loggedInUserData = await getUserData(loggedInUserID),
targetUserData = await getUserData(uid),
followUser = uid => fetch(`https://booyah.live/api/v3/users/${loggedInUserID}/followings`, { method: (unfollow ? 'DELETE' : 'POST'), headers: { 'X-CSRF-Token': csrf }, body: JSON.stringify({ followee_uid: uid, source: 43 }) }),
logSep = (data = '', usePad = 0) => typeof data === 'string' && usePad ? console.log((data ? data + ' ' : '').padEnd(50, '━')) : console.log('━'.repeat(50),data,'━'.repeat(50));
async function getList(uid, type, follow) {
const isLoggedInUser = uid === loggedInUserID;
if (isLoggedInUser && follow && !unfollow && type === 'followings') {
follow = 0;
console.warn('You alredy follow your followings. `follow` mode switched to `false`. Followings will be retrieved instead of followed.');
}
const userData = await getUserData(uid),
totalCount = userData[type.slice(0,-1)+'_count'] || 0,
totalCountStrLength = totalCount.toString().length;
if (totalCount) {
let userIDsLength = 0;
const userIDs = [],
nickname = userData.nickname,
nicknameStr = `${nickname ? ` of ${nickname}'s ${type}` : ''}`,
alreadyFollowedStr = uid => `User ID ${uid} already followed by ${loggedInUserData.nickname} (Account #${loggedInUserID})`;
async function followerFetch(cursor = 0) {
const fetched = [];
await fetch(`https://booyah.live/api/v3/users/${uid}/${type}?cursor=${cursor}&count=100`).then(res => res.json()).then(data => {
const list = data[type.slice(0,-1)+'_list'];
if (list?.length) fetched.push(...list.map(e => e.uid));
if (fetched.length) {
userIDs.push(...fetched);
userIDsLength += fetched.length;
if (follow) followUser(uid);
console.log(`${userIDsLength.toString().padStart(totalCountStrLength)} (${(userIDsLength / totalCount * 100).toFixed(4)}%)${nicknameStr} ${follow ? 'followed' : 'retrieved'}`);
if (fetched.length === 100) {
followerFetch(data.cursor);
} else {
console.log(`END REACHED. ${userIDsLength} accounts ${follow ? 'followed' : 'retrieved'}.`);
if (!follow) logSep(targetList);
}
}
});
}
await followerFetch();
return userIDs;
} else {
console.log(`This account has no ${type}.`);
}
}
logSep(`${follow ? 'Following' : 'Retrieving'} ${targetUserData.nickname}'s ${type}`, 1);
const targetList = await getList(uid, type, follow);
} else {
console.error('Missing CSRF token. Retrieve your CSRF token from the Network tab in your inspector by clicking into the Network tab item named "bug-report-claims" and then scrolling down in the associated details window to where you see "x-csrf-token". Copy its value and store it into a variable named "csrf" which this function will reference when you execute it.');
}
} else {
console.error('You do not appear to be logged in. Please log in and try again.');
}
} else {
console.error('UID not passed. Pass the UID of the profile you are targeting to this function.');
}
}
当前的问题是链接中该答案的延续:
Collect the full list of buttons to follow without having to scroll the page (DevTools Google Chrome)
由于我无法在该问题上提供更多赏金,因此我创建了这个问题,以向任何可以修复错误并使脚本正常工作的人提供新的赏金。

Access account on Booyah website to use for tests:

Access by google:

User: teststackoverflowbooyah@gmail.com

Password: quartodemilha

最佳答案

我不得不承认阅读你的代码真的很难,我花了更少的时间从头开始重写所有内容。
说我们需要在能够存储一些数据的 Web 浏览器的 JavaScript 控制台中剪切/粘贴一段代码(即关注的到期和永久关注),我们需要一些考虑。
我们可以将以下内容的过期视为 volatile 数据:如果丢失,可以将其重置为我们丢失此数据后的 1 天。 window.localStorage 是存储此类数据的完美候选者。如果我们更改网络浏览器,唯一的缺点是我们会取消关注的过期时间,并且我们可以容忍将它们重置为从我们更改浏览器开始的 1 天后。
虽然要存储永久关注者列表,但即使我们更改 Web 浏览器,我们也需要永久存储。我想到的最好的想法是创建一个替代帐户来关注我们永远不想停止关注的用户。在我的代码中,我使用了 uid 3186068(随机用户),一旦您创建了自己的替代帐户,只需将代码块的第一行替换为其 uid 即可。
我们需要注意的另一件事是错误处理:API 可能总是有错误。我选择的方法是编写 myFetch,如果出现错误,会重试两次相同的调用;如果错误仍然存​​在,我们可能正面临暂时的 booyah.live 中断。可能我们只需要稍后重试。
为了尝试提供舒适的界面,代码块从 window.location 收集 uid :要关注用户的关注者,只需在其个人资料上打开的选项卡上剪切/粘贴代码块。例如,我从 https://booyah.live/studio/123456?source=44 打开的选项卡运行代码。
最后,要取消关注用户,在 5 分钟后调用 clean 函数,我们粘贴代码(以免与关注关注者的调用冲突),然后在一小时后执行它完成它的工作。它被编写为以原子方式访问 localStorage ,因此您可以让它们中的许多同时在同一浏览器的不同选项卡上运行,您不必关心它。唯一需要注意的是,当 window.location 更改时,选项卡中的所有 JavaScript 事件都会重置;所以我建议在主页上保持一个标签打开,将代码块粘贴在上面,然后忘记这个标签;它将是负责取消关注用户的选项卡。然后打开其他标签来做你需要的事情,当你点击一个你想要关注关注者的用户时,将 block 粘贴在上面,等待工作完成并继续正常使用标签。

// The account we use to store followings
const followingsUID = 3186068;
// Gather the loggedUID from window.localStorage
const { loggedUID } = window.localStorage;
// Gather the CSRF-Token from the cookies
const csrf = document.cookie.split("; ").reduce((ret, _) => (_.startsWith("session_key=") ? _.substr(12) : ret), null);

// APIs could have errors, let's do some retries
async function myFetch(url, options, attempt = 0) {
try {
const res = await fetch("https://booyah.live/api/v3/" + url, options);
const ret = await res.json();

return ret;
} catch(e) {
// After too many consecutive errors, let's abort: we need to retry later
if(attempt === 3) throw e;

return myFetch(url, option, attempt + 1);
}
}

function expire(uid, add = true) {
const { followingsExpire } = window.localStorage;
let expires = {};

try {
// Get and parse followingsExpire from localStorage
expires = JSON.parse(followingsExpire);
} catch(e) {
// In case of error (ex. new browsers) simply init to empty
window.localStorage.followingsExpire = "{}";
}

if(! uid) return expires;

// Set expire after 1 day
if(add) expires[uid] = new Date().getTime() + 3600 * 24 * 1000;
else delete expires[uid];

window.localStorage.followingsExpire = JSON.stringify(expires);
}

async function clean() {
try {
const expires = expire();
const now = new Date().getTime();

for(const uid in expires) {
if(expires[uid] < now) {
await followUser(parseInt(uid), false);
expire(uid, false);
}
}
} catch(e) {}

// Repeat clean in an hour
window.setTimeout(clean, 3600 * 1000);
}

async function fetchFollow(uid, type = "followers", from = 0) {
const { cursor, follower_list, following_list } = await myFetch(`users/${uid}/${type}?cursor=${from}&count=50`);
const got = (type === "followers" ? follower_list : following_list).map(_ => _.uid);
const others = cursor ? await fetchFollow(uid, type, cursor) : [];

return [...got, ...others];
}

async function followUser(uid, follow = true) {
console.log(`${follow ? "F" : "Unf"}ollowing ${uid}...`);
return myFetch(`users/${loggedUID}/followings`, {
method: follow ? "POST" : "DELETE",
headers: { "X-CSRF-Token": csrf },
body: JSON.stringify({ followee_uid: uid, source: 43 })
});
}

async function doAll() {
if(! loggedUID) throw new Error("Can't get 'loggedUID' from localStorage: try to login again");
if(! csrf) throw new Error("Can't get session token from cookies: try to login again");

console.log("Fetching current followings...");
const currentFollowings = await fetchFollow(loggedUID, "followings");

console.log("Fetching permanent followings...");
const permanentFollowings = await fetchFollow(followingsUID, "followings");

console.log("Syncing permanent followings...");
for(const uid of permanentFollowings) {
expire(uid, false);

if(currentFollowings.indexOf(uid) === -1) {
await followUser(uid);
currentFollowings.push(uid);
}
}

// Sync followingsExpire in localStorage
for(const uid of currentFollowings) if(permanentFollowings.indexOf(uid) === -1) expire(uid);
// Call first clean task in 5 minutes
window.setTimeout(clean, 300 * 1000);

// Gather uid from window.location
const match = /\/studio\/(\d+)/.exec(window.location.pathname);

if(match) {
console.log("Fetching this user followers...");
const followings = await fetchFollow(parseInt(match[1]));

for(const uid of followings) {
if(currentFollowings.indexOf(uid) === -1) {
await followUser(uid);
expire(uid);
}
}
}

return "Done";
}

await doAll();
问题:我强烈怀疑 booyah.live API 错误
为了测试我的代码,我从 https://booyah.live/studio/123456?source=44 运行它。
如果我多次运行它,我将继续获得以下输出:
Fetching current followings...
Fetching permanent followings...
Syncing permanent followings...
Following 1801775...
Following 143823...
Following 137017...
Fetching this user followers...
Following 16884042...
Following 16166724...
某处有bug! 在同一选项卡中后续执行的预期输出将是:
Fetching current followings...
Fetching permanent followings...
Syncing permanent followings...
Fetching this user followers...
在我的代码中寻找错误但没有成功后,我检查了 booyah.live API:如果我导航以下 URL( uid 是代码在后续执行中继续遵循的那些)
https://booyah.live/studio/1801775
https://booyah.live/studio/143823
https://booyah.live/studio/137017
https://booyah.live/studio/16884042
https://booyah.live/studio/16166724
我可以清楚地看到我关注了他们,但是如果我浏览 https://booyah.live/following(我关注的用户列表)我找不到他们,如果我滚动页面直到最后也找不到。
由于我执行与网站完全相同的调用,我强烈怀疑该错误存在于 booyah.live API 中,与它们处理 cursor 参数的方式完全相同。
我建议您向 booyah.live 支持团队开一张支持票。您可以使用您提供给我们的测试帐户:我已经向您提供了执行此操作的详细信息。 ;)

关于javascript - 脚本从头到尾顺利运行,但没有出现预期的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69076135/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com