← back to browse
goat command

accept

accept users

0
views
0
likes
0
installs

Aliases: acp

raw source
const moment = require("moment-timezone");

// ---- shared helper: fetch one page of pending friend requests ----
async function fetchPage(api, cursor) {
  const variables = { input: { scale: 3 } };
  if (cursor) variables.after = cursor; // pagination cursor, if the API accepts it

  const form = {
    av: api.getCurrentUserID(),
    fb_api_req_friendly_name: "FriendingCometFriendRequestsRootQueryRelayPreloader",
    fb_api_caller_class: "RelayModern",
    doc_id: "4499164963466303",
    variables: JSON.stringify(variables)
  };

  const raw = await api.httpPost("https://www.facebook.com/api/graphql/", form);
  const parsed = JSON.parse(raw);
  const connection = parsed && parsed.data && parsed.data.viewer && parsed.data.viewer.friending_possibilities;

  if (!connection || !Array.isArray(connection.edges)) {
    return { edges: [], hasNextPage: false, endCursor: null };
  }

  const pageInfo = connection.page_info || {};
  return {
    edges: connection.edges,
    hasNextPage: !!(pageInfo.has_next_page && pageInfo.end_cursor),
    endCursor: pageInfo.end_cursor || null
  };
}

function buildListText(listRequest, pageNum) {
  let msg = `📄 Page ${pageNum}\n`;
  let i = 0;
  for (const user of listRequest) {
    i++;
    msg += (`\n${i}. Name: ${user.node.name}`
      + `\nID: ${user.node.id}`
      + `\nUrl: ${user.node.url.replace("www.facebook", "fb")}`
      + `\nTime: ${moment(user.time * 1009).tz("Asia/Manila").format("DD/MM/YYYY HH:mm:ss")}\n`);
  }
  return msg;
}

// Sends a page of requests, wires up BOTH onReply (add/del) and
// onReaction (react = jump to next page) for that message.
async function sendPage({ api, event, commandName, threadID, listRequest, cursor, hasNextPage, pageNum, author }) {
  const text = buildListText(listRequest, pageNum);
  const footer = `\nReply <add: del> <number: or "all"> to take action.` +
    (hasNextPage ? `\nOr react to this message to jump to the next batch.` : `\n(This is the last batch — no more pending requests.)`);

  return new Promise((resolve) => {
    api.sendMessage(`${text}${footer}`, threadID, (err, info) => {
      if (err || !info) return resolve(null);

      const context = {
        commandName,
        messageID: info.messageID,
        listRequest,
        cursor,
        hasNextPage,
        pageNum,
        author
      };

      global.GoatBot.onReply.set(info.messageID, context);
      if (global.GoatBot.onReaction) {
        global.GoatBot.onReaction.set(info.messageID, context);
      }
      resolve(info);
    }, event.messageID);
  });
}

module.exports = {
  config: {
    name: "accept",
    aliases: ['acp'],
    version: "2.0",
    author: "JABED D KURÕ",
    countDown: 8,
    role: 2,
    shortDescription: "accept users",
    longDescription: "accept/decline friend requests, paginated — react to advance, 'add all' auto-advances, single accepts keep the list",
    category: "Utility",
  },

  onStart: async function ({ event, api, commandName }) {
    let page;
    try {
      page = await fetchPage(api, null);
    } catch (e) {
      return api.sendMessage("Failed to load pending friend requests.", event.threadID, event.messageID);
    }

    if (!page.edges || page.edges.length === 0) {
      return api.sendMessage("No pending friend requests found.", event.threadID, event.messageID);
    }

    await sendPage({
      api, event, commandName,
      threadID: event.threadID,
      listRequest: page.edges,
      cursor: page.endCursor,
      hasNextPage: page.hasNextPage,
      pageNum: 1,
      author: event.senderID
    });
  },

  // React to the list message => jump straight to the next batch,
  // no matter what (doesn't require typing "add all" first).
  onReaction: async function ({ event, Reaction, api, commandName }) {
    const ctx = Reaction;
    if (!ctx || ctx.author !== event.userID) return;

    if (!ctx.hasNextPage) {
      return api.sendMessage("এটাই শেষ ব্যাচ — আর কোনো pending request নেই।", event.threadID);
    }

    let nextPage;
    try {
      nextPage = await fetchPage(api, ctx.cursor);
    } catch (e) {
      return api.sendMessage("পরের ব্যাচ আনতে গিয়ে সমস্যা হয়েছে।", event.threadID);
    }

    if (!nextPage.edges || nextPage.edges.length === 0) {
      return api.sendMessage("এটাই শেষ ব্যাচ — আর কোনো pending request নেই।", event.threadID);
    }

    // clear old bindings so old message doesn't double-trigger
    global.GoatBot.onReply.delete(ctx.messageID);
    if (global.GoatBot.onReaction) global.GoatBot.onReaction.delete(ctx.messageID);

    await sendPage({
      api, event, commandName,
      threadID: event.threadID,
      listRequest: nextPage.edges,
      cursor: nextPage.endCursor,
      hasNextPage: nextPage.hasNextPage,
      pageNum: ctx.pageNum + 1,
      author: ctx.author
    });
  },

  onReply: async function ({ message, Reply, event, api, commandName }) {
    const ctx = Reply;
    const { author, listRequest, messageID } = ctx;
    if (author !== event.senderID) return;

    const args = event.body.replace(/ +/g, " ").toLowerCase().split(" ").filter(Boolean);

    const form = {
      av: api.getCurrentUserID(),
      fb_api_caller_class: "RelayModern",
      variables: {
        input: {
          source: "friends_tab",
          actor_id: api.getCurrentUserID(),
          client_mutation_id: Math.round(Math.random() * 19).toString()
        },
        scale: 3,
        refresh_num: 0
      }
    };

    const success = [];
    const failed = [];

    if (args[0] === "add") {
      form.fb_api_req_friendly_name = "FriendingCometFriendRequestConfirmMutation";
      form.doc_id = "3147613905362928";
    } else if (args[0] === "del") {
      form.fb_api_req_friendly_name = "FriendingCometFriendRequestDeleteMutation";
      form.doc_id = "4108254489275063";
    } else {
      return api.sendMessage('Please reply <add: del> <target number: or "all">', event.threadID, event.messageID);
    }

    const isAll = args[1] === "all";
    let targetIDs = args.slice(1);

    if (isAll) {
      targetIDs = [];
      for (let i = 1; i <= listRequest.length; i++) targetIDs.push(i);
    }

    const newTargetIDs = [];
    const promiseFriends = [];

    for (const stt of targetIDs) {
      const u = listRequest[parseInt(stt) - 1];
      if (!u) {
        failed.push(`Can't find stt ${stt} in the list`);
        continue;
      }
      form.variables.input.friend_requester_id = u.node.id;
      form.variables = JSON.stringify(form.variables);
      newTargetIDs.push(u);
      promiseFriends.push(api.httpPost("https://www.facebook.com/api/graphql/", form));
      form.variables = JSON.parse(form.variables);
    }

    for (let i = 0; i < newTargetIDs.length; i++) {
      try {
        const friendRequest = await promiseFriends[i];
        if (JSON.parse(friendRequest).errors) {
          failed.push(newTargetIDs[i].node.name);
        } else {
          success.push(newTargetIDs[i].node.name);
        }
      } catch (e) {
        failed.push(newTargetIDs[i].node.name);
      }
    }

    if (success.length === 0) {
      return api.sendMessage("Invalid response, or nothing was processed successfully.", event.threadID, event.messageID);
    }

    const resultMsg = `» The ${args[0] === 'add' ? 'friend request' : 'friend request deletion'} processed for ${success.length} people:\n\n${success.join("\n")}` +
      (failed.length > 0 ? `\n\n» The following ${failed.length} people encountered errors:\n${failed.join("\n")}` : "");

    api.sendMessage(resultMsg, event.threadID, event.messageID);

    if (isAll) {
      // "add all" / "del all" => this page is fully handled, clean it
      // up and automatically pull in the next batch if one exists.
      global.GoatBot.onReply.delete(messageID);
      if (global.GoatBot.onReaction) global.GoatBot.onReaction.delete(messageID);
      api.unsendMessage(messageID);

      if (!ctx.hasNextPage) {
        return api.sendMessage("সব pending friend request প্রসেস করা শেষ — আর কোনো ব্যাচ নেই।", event.threadID);
      }

      let nextPage;
      try {
        nextPage = await fetchPage(api, ctx.cursor);
      } catch (e) {
        return api.sendMessage("পরের ব্যাচ আনতে গিয়ে সমস্যা হয়েছে।", event.threadID);
      }

      if (!nextPage.edges || nextPage.edges.length === 0) {
        return api.sendMessage("সব pending friend request প্রসেস করা শেষ — আর কোনো ব্যাচ নেই।", event.threadID);
      }

      await sendPage({
        api, event, commandName,
        threadID: event.threadID,
        listRequest: nextPage.edges,
        cursor: nextPage.endCursor,
        hasNextPage: nextPage.hasNextPage,
        pageNum: ctx.pageNum + 1,
        author
      });
    } else {
      // Single / specific-number accept => keep the SAME list active
      // so the user can keep picking more people from it, or react
      // to move on whenever they're ready. Re-register to be safe in
      // case the dispatcher auto-clears reply bindings after one use.
      global.GoatBot.onReply.set(messageID, ctx);
      if (global.GoatBot.onReaction) global.GoatBot.onReaction.set(messageID, ctx);
    }
  }
};

View raw file