File size: 4,483 Bytes
e192d16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
Output:
"use strict";

var utils = require("../utils");
var log = require("npmlog");
var bluebird = require("bluebird");

module.exports = function (defaultFuncs, api, ctx) {
  function getGUID() {
    let _0x161e32 = Date.now(),
      _0x4ec135 = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
        /[xy]/g,
        function (_0x32f946) {
          let _0x141041 = Math.floor((_0x161e32 + Math.random() * 16) % 16);
          _0x161e32 = Math.floor(_0x161e32 / 16);
          let _0x31fcdd = (
            _0x32f946 == "x" ? _0x141041 : (_0x141041 & 0x3) | 0x8
          ).toString(16);
          return _0x31fcdd;
        },
      );
    return _0x4ec135;
  }

  function uploadAttachment(attachment, callback) {
    var uploads = [];

    // create an array of promises
    if (!utils.isReadableStream(attachment)) {
      throw {
        error:
          "Attachment should be a readable stream and not " +
          utils.getType(attachment) +
          ".",
      };
    }

    var form = {
      file: attachment,
      av: api.getCurrentUserID(),
      profile_id: api.getCurrentUserID(),
      source: "19",
      target_id: api.getCurrentUserID(),
      __user: api.getCurrentUserID(),
      __a: "1",
    };

    uploads.push(
      defaultFuncs
        .postFormData(
          "https://www.facebook.com/ajax/ufi/upload",
          ctx.jar,
          form,
          {},
        )
        .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
        .then(function (resData) {
          if (resData.error) {
            throw resData;
          }
          return resData.payload;
        }),
    );

    // resolve all promises
    bluebird
      .all(uploads)
      .then(function (resData) {
        callback(null, resData);
      })
      .catch(function (err) {
        log.error("uploadAttachment", err);
        return callback(err);
      });
  }

  async function sendCommentToFb(postId, text, fileID) {
    const feedback_id = Buffer.from("feedback:" + postId).toString("base64");

    const ss1 = getGUID();
    const ss2 = getGUID();

    const form = {
      av: api.getCurrentUserID(),
      fb_api_req_friendly_name: "CometUFICreateCommentMutation",
      fb_api_caller_class: "RelayModern",
      doc_id: "4744517358977326",
      variables: JSON.stringify({
        displayCommentsFeedbackContext: null,
        displayCommentsContextEnableComment: null,
        displayCommentsContextIsAdPreview: null,
        displayCommentsContextIsAggregatedShare: null,
        displayCommentsContextIsStorySet: null,
        feedLocation: "TIMELINE",
        feedbackSource: 0,
        focusCommentID: null,
        includeNestedComments: false,
        input: {
          attachments: fileID ? [{ media: { id: fileID } }] : null,
          feedback_id: feedback_id,
          formatting_style: null,
          message: {
            ranges: [],
            text: text,
          },
          is_tracking_encrypted: true,
          tracking: [],
          feedback_source: "PROFILE",
          idempotence_token: "client:" + ss1,
          session_id: ss2,
          actor_id: api.getCurrentUserID(),
          client_mutation_id: Math.round(Math.random() * 19),
        },
        scale: 3,
        useDefaultActor: false,
        UFI2CommentsProvider_commentsKey: "ProfileCometTimelineRoute",
      }),
    };

    const res = JSON.parse(
      await api.httpPost("https://www.facebook.com/api/graphql/", form),
    );
    return res;
  }

  return async function sendComment(content, postId, callback) {
    if (typeof content === "object") {
      var text = content.body || "";
      if (content.attachment) {
        if (!utils.isReadableStream(content.attachment)) {
          throw new Error("Attachment must be a ReadableStream");
        }

        uploadAttachment(content.attachment, async function (err, files) {
          if (err) {
            return callback(err);
          }

          await sendCommentToFb(postId, text, files[0].fbid)
            .then((res) => {
              return callback(null, res);
            })
            .catch((err) => {
              return callback(err);
            });
        });
      }
    } else if (typeof content === "string") {
      var text = content;
      await sendCommentToFb(postId, text, null)
        .then((res) => {
          return callback(null, res);
        })
        .catch((_) => {
          return;
        });
    } else throw new Error("Invalid content");
  };
};
// example usage