Beispiel #1
0
        internal static (FB_User author, long at) _parse_fetch(Session session, JToken data)
        {
            var author = new FB_User(session: session, uid: data?.get("message_sender")?.get("id")?.Value <string>());
            var at     = long.Parse(data?.get("timestamp_precise")?.Value <string>());

            return(author, at);
        }
Beispiel #2
0
        internal static FB_FriendRequest _parse(Session session, JToken data)
        {
            var author = new FB_User(session: session, uid: data?.get("from")?.Value <string>());

            return(new FB_FriendRequest()
            {
                author = author
            });
        }
Beispiel #3
0
        internal static (FB_User author, FB_Thread thread, long at) _parse_metadata(Session session, JToken data)
        {
            var metadata = data?.get("messageMetadata");
            var author   = new FB_User(session: session, uid: metadata?.get("actorFbId")?.Value <string>());
            var thread   = FB_ThreadEvent._get_thread(session, metadata);
            var at       = long.Parse(metadata?.get("timestamp")?.Value <string>());

            return(author, thread, at);
        }
Beispiel #4
0
        public static FB_User _from_thread_fetch(JToken data)
        {
            var c_info                 = FB_User._parse_customization_info(data);
            var participants           = data.get("all_participants")?.get("nodes")?.Select(node => node.get("messaging_actor"));
            var user                   = participants.Where((p) => p.get("id")?.Value <string>() == data.get("thread_key")?.get("other_user_id")?.Value <string>())?.FirstOrDefault();
            var last_message_timestamp = data.get("last_message")?.get("nodes")?.FirstOrDefault()?.get("timestamp_precise")?.Value <string>();

            var name       = user.get("name")?.Value <string>();
            var first_name = user.get("first_name")?.Value <string>() ?? user.get("short_name")?.Value <string>();
            var last_name  = first_name != null?name?.Replace(first_name, "")?.Trim() : null;

            var gender = GENDER.graphql_GENDERS["UNKNOWN"];

            if (data.get("gender")?.Type == JTokenType.Integer)
            {
                gender = GENDER.standard_GENDERS[data.get("gender")?.Value <int>() ?? 0];
            }
            else
            {
                int gender_int = 0;
                if (int.TryParse(data.get("gender")?.Value <string>(), out gender_int))
                {
                    gender = GENDER.standard_GENDERS[gender_int];
                }
                else
                {
                    gender = GENDER.graphql_GENDERS[data.get("gender")?.Value <string>() ?? "UNKNOWN"];
                }
            };

            if (user.get("big_image_src") == null)
            {
                user["big_image_src"] = new JObject(new JProperty("uri", ""));
            }

            var plan = data.get("event_reminders")?.get("nodes")?.FirstOrDefault() != null?FB_Plan._from_graphql(data.get("event_reminders")?.get("nodes")?.FirstOrDefault()) : null;

            return(new FB_User(
                       uid: user.get("id")?.Value <string>(),
                       url: user.get("url")?.Value <string>(),
                       name: name,
                       first_name: first_name,
                       last_name: last_name,
                       is_friend: user.get("is_viewer_friend")?.Value <bool>() ?? false,
                       gender: gender,
                       affinity: user.get("viewer_affinity")?.Value <float>() ?? 0,
                       nickname: (string)c_info.GetValueOrDefault("nickname"),
                       color: (string)c_info.GetValueOrDefault("color"),
                       emoji: (JToken)c_info.GetValueOrDefault("emoji"),
                       own_nickname: (string)c_info.GetValueOrDefault("own_nickname"),
                       photo: user.get("big_image_src")?.get("uri")?.Value <string>(),
                       message_count: data.get("messages_count")?.Value <int>() ?? 0,
                       last_message_timestamp: last_message_timestamp,
                       plan: plan));
        }
Beispiel #5
0
        /// <summary>
        /// Get thread list of your facebook account
        /// </summary>
        /// <param name="limit">Max.number of threads to retrieve. Capped at 20</param>
        /// <param name="thread_location">models.ThreadLocation: INBOX, PENDING, ARCHIVED or OTHER</param>
        /// <param name="before">A unix timestamp, indicating from which point to retrieve messages</param>
        public async Task <List <FB_Thread> > fetchThreadList(int limit = 20, string thread_location = ThreadLocation.INBOX, string before = null)
        {
            /*
             * Get thread list of your facebook account
             * :param limit: Max.number of threads to retrieve.Capped at 20
             * :param thread_location: models.ThreadLocation: INBOX, PENDING, ARCHIVED or OTHER
             * :param before: A timestamp (in milliseconds), indicating from which point to retrieve threads
             * :type limit: int
             * :return: `models.Thread` objects
             * :rtype: list
             * :raises: Exception if request failed
             */

            if (limit > 20 || limit < 1)
            {
                throw new FBchatUserError("`limit` should be between 1 and 20");
            }

            var dict = new Dictionary <string, object>()
            {
                { "limit", limit },
                { "tags", new string[] { thread_location } },
                { "before", before },
                { "includeDeliveryReceipts", true },
                { "includeSeqID", false }
            };

            var j = await this._session.graphql_request(GraphQL.from_doc_id(doc_id: "1349387578499440", param: dict));

            var rtn = new List <FB_Thread>();

            foreach (var node in j.get("viewer")?.get("message_threads")?.get("nodes"))
            {
                var _type = node.get("thread_type")?.Value <string>();
                if (_type == "GROUP")
                {
                    rtn.Add(FB_Group._from_graphql(_session, node));
                }
                else if (_type == "ONE_TO_ONE")
                {
                    rtn.Add(FB_User._from_thread_fetch(_session, node));
                }
                else if (_type == "MARKETPLACE")
                {
                    rtn.Add(FB_Marketplace._from_graphql(_session, node));
                }
                else
                {
                    throw new FBchatException(string.Format("Unknown thread type: {0}", _type));
                }
            }
            return(rtn);
        }
Beispiel #6
0
        internal static FB_TypingStatus _from_orca(Session session, JToken data)
        {
            var author = new FB_User(session: session, uid: data?.get("sender_fbid")?.Value <string>());
            var status = data?.get("state")?.Value <int>() == 1;

            return(new FB_TypingStatus()
            {
                author = author,
                thread = author,
                status = status
            });
        }
Beispiel #7
0
        internal static FB_ParticipantRemoved _from_fetch(FB_Thread thread, JToken data)
        {
            (FB_User author, long at) = FB_ParticipantRemoved._parse_fetch(thread.session, data);
            var removed = new FB_User(data?.get("participants_removed")?.FirstOrDefault()?.get("id")?.Value <string>(), thread.session);

            return(new FB_ParticipantRemoved()
            {
                author = author,
                thread = thread as FB_Group,
                removed = removed,
                at = at
            });
        }
Beispiel #8
0
        /// TODO: This!

        internal static FB_LiveLocationEvent _parse(Session session, JToken data)
        {
            var thread = FB_LiveLocationEvent._get_thread(session, data);

            foreach (var location_data in data?.get("messageLiveLocations") ?? Enumerable.Empty <JToken>())
            {
                var message  = new FB_Message(session: session, thread_id: thread.uid, uid: data?.get("messageId")?.Value <string>());
                var author   = new FB_User(session: session, uid: location_data?.get("senderId")?.Value <string>());
                var location = FB_LiveLocationAttachment._from_pull(location_data);
            }

            return(null);
        }
Beispiel #9
0
        internal static FB_ParticipantRemoved _parse(Session session, JToken data)
        {
            (FB_User author, FB_Thread thread, long at) = FB_ParticipantRemoved._parse_metadata(session, data);
            var removed = new FB_User(data?.get("leftParticipantFbId")?.Value <string>(), session);

            return(new FB_ParticipantRemoved()
            {
                author = author,
                thread = thread as FB_Group,
                removed = removed,
                at = at
            });
        }
Beispiel #10
0
        public static FB_User _from_graphql(JToken data)
        {
            if (data.get("profile_picture") == null)
            {
                data["profile_picture"] = new JObject(new JProperty("uri", ""));
            }
            var c_info = FB_User._parse_customization_info(data);
            var plan   = data.get("event_reminders")?.get("nodes")?.FirstOrDefault() != null?FB_Plan._from_graphql(data.get("event_reminders")?.get("nodes")?.FirstOrDefault()) : null;

            var name       = data.get("name")?.Value <string>();
            var first_name = data.get("first_name")?.Value <string>() ?? data.get("short_name")?.Value <string>();
            var last_name  = first_name != null?name?.Replace(first_name, "")?.Trim() : null;

            var gender = GENDER.graphql_GENDERS["UNKNOWN"];

            if (data.get("gender")?.Type == JTokenType.Integer)
            {
                gender = GENDER.standard_GENDERS[data.get("gender")?.Value <int>() ?? 0];
            }
            else
            {
                int gender_int = 0;
                if (int.TryParse(data.get("gender")?.Value <string>(), out gender_int))
                {
                    gender = GENDER.standard_GENDERS[gender_int];
                }
                else
                {
                    gender = GENDER.graphql_GENDERS[data.get("gender")?.Value <string>() ?? "UNKNOWN"];
                }
            };

            return(new FB_User(
                       uid: data.get("id")?.Value <string>(),
                       url: data.get("url")?.Value <string>(),
                       name: name,
                       first_name: first_name,
                       last_name: last_name,
                       is_friend: data.get("is_viewer_friend")?.Value <bool>() ?? false,
                       gender: gender,
                       affinity: data.get("viewer_affinity")?.Value <float>() ?? 0,
                       nickname: (string)c_info.GetValueOrDefault("nickname"),
                       color: (string)c_info.GetValueOrDefault("color"),
                       emoji: (JToken)c_info.GetValueOrDefault("emoji"),
                       own_nickname: (string)c_info.GetValueOrDefault("own_nickname"),
                       photo: data.get("profile_picture")?.get("uri")?.Value <string>(),
                       message_count: data.get("messages_count")?.Value <int>() ?? 0,
                       plan: plan));
        }
Beispiel #11
0
        internal static FB_NicknameSet _parse(Session session, JToken data)
        {
            (FB_User author, FB_Thread thread, long at) = FB_NicknameSet._parse_metadata(session, data);
            var subject  = new FB_User(data?.get("untypedData")?.get("participant_id")?.Value <string>(), session);
            var nickname = data?.get("untypedData")?.get("nickname")?.Value <string>();

            return(new FB_NicknameSet()
            {
                author = author,
                thread = thread,
                subject = subject,
                nickname = nickname,
                at = at
            });
        }
Beispiel #12
0
        internal static FB_ThreadsRead _parse_read_receipt(Session session, JToken data)
        {
            var author = new FB_User(session: session, uid: data?.get("actorFbId")?.Value <string>());
            var thread = FB_ThreadEvent._get_thread(session, data);
            var at     = long.Parse(data.get("actionTimestampMs")?.Value <string>());

            return(new FB_ThreadsRead()
            {
                author = author,
                threads = new List <FB_Thread>()
                {
                    thread
                },
                at = at
            });
        }
Beispiel #13
0
        internal static FB_ThreadsRead _parse(Session session, JToken data)
        {
            var author  = new FB_User(session.user.uid, session);
            var threads = data?.get("threadKeys")?.Select(x => FB_ThreadEvent._get_thread(session, new JObject()
            {
                { "threadKey", x }
            }));
            var at = long.Parse(data?.get("actionTimestamp")?.Value <string>());

            return(new FB_ThreadsRead()
            {
                author = author,
                threads = threads.ToList(),
                at = at
            });
        }
Beispiel #14
0
        internal static FB_AdminsRemoved _parse(Session session, JToken data)
        {
            (FB_User author, FB_Thread thread, long at) = FB_AdminsRemoved._parse_metadata(session, data);
            var target = new FB_User(data?.get("untypedData")?.get("TARGET_ID")?.Value <string>(), session);

            return(new FB_AdminsRemoved()
            {
                author = author,
                thread = thread,
                removed = new List <FB_User>()
                {
                    target
                },
                at = at
            });
        }
Beispiel #15
0
        internal static FB_NicknameSet _from_fetch(FB_Thread thread, JToken data)
        {
            (FB_User author, long at) = FB_NicknameSet._parse_fetch(thread.session, data);
            var extra    = data?.get("extensible_message_admin_text");
            var subject  = new FB_User(extra?.get("participant_id")?.Value <string>(), thread.session);
            var nickname = extra?.get("nickname")?.Value <string>();

            return(new FB_NicknameSet()
            {
                author = author,
                thread = thread,
                subject = subject,
                nickname = nickname,
                at = at
            });
        }
Beispiel #16
0
        /// <summary>
        /// Find and get a thread by its name
        /// </summary>
        /// <param name="name">Name of the thread</param>
        /// <param name="limit">The max. amount of threads to fetch</param>
        /// <returns>`FB_User`, `FB_Group` and `FB_Page` objects, ordered by relevance</returns>
        public async Task <List <FB_Thread> > searchThreads(string name, int limit = 1)
        {
            /*
             * Find and get a thread by its name
             * :param name: Name of the thread
             * :param limit: The max. amount of groups to fetch
             * : return: `User`, `Group` and `Page` objects, ordered by relevance
             * :rtype: list
             * :raises: FBchatException if request failed
             * */

            var param = new Dictionary <string, object>()
            {
                { "search", name }, { "limit", limit.ToString() }
            };
            var j = await this._session.graphql_request(GraphQL.from_query(GraphQL.SEARCH_THREAD, param));

            List <FB_Thread> rtn = new List <FB_Thread>();

            foreach (var node in j[name]?.get("threads")?.get("nodes"))
            {
                if (node.get("__typename").Value <string>().Equals("User"))
                {
                    rtn.Add(FB_User._from_graphql(_session, node));
                }
                else if (node.get("__typename").Value <string>().Equals("MessageThread"))
                {
                    // MessageThread => Group thread
                    rtn.Add(FB_Group._from_graphql(_session, node));
                }
                else if (node.get("__typename").Value <string>().Equals("Page"))
                {
                    rtn.Add(FB_Page._from_graphql(_session, node));
                }
                else if (node.get("__typename").Value <string>().Equals("Group"))
                {
                    // We don"t handle Facebook "Groups"
                    continue;
                }
                else
                {
                    Debug.WriteLine(string.Format("Unknown __typename: {0} in {1}", node.get("__typename").Value <string>(), node));
                }
            }

            return(rtn);
        }
Beispiel #17
0
        /// <summary>
        /// Find and get user by his/her name
        /// </summary>
        /// <param name="name">Name of the user</param>
        /// <param name="limit">The max. amount of users to fetch</param>
        /// <returns>`FB_User` objects, ordered by relevance</returns>
        public async Task <List <FB_User> > searchUsers(string name, int limit = 10)
        {
            /*
             * Find and get user by his/ her name
             * : param name: Name of the user
             * :param limit: The max. amount of users to fetch
             * : return: `User` objects, ordered by relevance
             * :rtype: list
             * :raises: FBchatException if request failed
             * */

            var param = new Dictionary <string, object>()
            {
                { "search", name }, { "limit", limit.ToString() }
            };
            var j = await this._session.graphql_request(GraphQL.from_query(GraphQL.SEARCH_USER, param));

            return(j[name]?.get("users")?.get("nodes").Select(node => FB_User._from_graphql(_session, node)).ToList());
        }
Beispiel #18
0
        internal static FB_MessagesDelivered _parse(Session session, JToken data)
        {
            var thread = FB_MessagesDelivered._get_thread(session, data);
            var author = thread;

            if (data?.get("actorFbId")?.Value <string>() != null)
            {
                author = new FB_User(data?.get("actorFbId")?.Value <string>(), session);
            }
            var messages = data?.get("messageIds")?.Select(x => new FB_Message(session, thread_id: thread.uid, uid: x?.Value <string>()));
            var at       = long.Parse(data?.get("deliveredWatermarkTimestampMs")?.Value <string>());

            return(new FB_MessagesDelivered()
            {
                author = author as FB_User,
                thread = thread,
                messages = messages.ToList(),
                at = at
            });
        }
Beispiel #19
0
        /// <summary>
        /// Fetch users the client is currently chatting with
        /// </summary>
        /// <returns>`FB_User` objects</returns>
        public async Task <List <FB_User> > fetchUsers()
        {
            /*
             * Fetch users the client is currently chatting with
             * This is very close to your friend list, with the follow differences:
             * It differs by including users that you're not friends with, but have chatted
             * with before, and by including accounts that are "Messenger Only".
             * But does not include deactivated, deleted or memorialized users (logically,
             * since you can't chat with those).
             * : return: `User` objects
             * :rtype: list
             * :raises: FBchatException if request failed
             * */

            var data = new Dictionary <string, object>()
            {
                { "viewer", this._session.user.uid },
            };
            var j = await this._session._payload_post("/chat/user_info_all", data : data);

            var users = new List <FB_User>();

            foreach (var u in j.Value <JObject>().Properties())
            {
                var k = u.Value;
                if (!new[] { "user", "friend" }.Contains(k?.get("type")?.Value <string>()) ||
                    new[] { "0", "\0" }.Contains(k.get("id").Value <string>()))
                {
                    // Skip invalid users
                    continue;
                }
                users.Add(FB_User._from_all_fetch(_session, k));
            }

            return(users);
        }
Beispiel #20
0
        /// <summary>
        /// Get threads' info from IDs, unordered
        /// </summary>
        /// <param name="thread_ids">One or more thread ID(s) to query</param>
        /// <returns>A dictionary of FB_Thread objects, labeled by their ID</returns>
        public async Task <Dictionary <string, FB_Thread> > fetchThreadInfo(List <string> thread_ids)
        {
            /*
             * Get threads" info from IDs, unordered
             * ..warning::
             * Sends two requests if users or pages are present, to fetch all available info!
             * :param thread_ids: One or more thread ID(s) to query
             * :return: `models.Thread` objects, labeled by their ID
             * :rtype: dict
             * :raises: Exception if request failed
             */

            var queries = new List <GraphQL>();

            foreach (var thread_id in thread_ids)
            {
                queries.Add(GraphQL.from_doc_id(doc_id: "2147762685294928", param: new Dictionary <string, object>()
                {
                    { "id", thread_id },
                    { "message_limit", 0.ToString() },
                    { "load_messages", false.ToString() },
                    { "load_read_receipts", false.ToString() },
                    { "before", null }
                }));
            }

            var j = await this._session.graphql_requests(queries);

            foreach (var obj in j.Select((x, index) => new { entry = x, i = index }))
            {
                if (obj.entry.get("message_thread") == null)
                {
                    // If you don't have an existing thread with this person, attempt to retrieve user data anyways
                    j[obj.i]["message_thread"] = new JObject(
                        new JProperty("thread_key",
                                      new JObject(
                                          new JProperty("other_user_id", thread_ids[obj.i]))),
                        new JProperty("thread_type", "ONE_TO_ONE"));
                }
            }

            var pages_and_user_ids = j.Where(k => k.get("message_thread")?.get("thread_type")?.Value <string>()?.Equals("ONE_TO_ONE") ?? false)
                                     .Select(k => k.get("message_thread")?.get("thread_key")?.get("other_user_id")?.Value <string>());
            JObject pages_and_users = null;

            if (pages_and_user_ids.Count() != 0)
            {
                pages_and_users = await this._fetchInfo(pages_and_user_ids.ToList());
            }

            var rtn = new Dictionary <string, FB_Thread>();

            foreach (var obj in j.Select((x, index) => new { entry = x, i = index }))
            {
                var entry = obj.entry.get("message_thread");
                if (entry.get("thread_type")?.Value <string>()?.Equals("GROUP") ?? false)
                {
                    var _id = entry.get("thread_key")?.get("thread_fbid").Value <string>();
                    rtn[_id] = FB_Group._from_graphql(_session, entry);
                }
                if (entry.get("thread_type")?.Value <string>()?.Equals("MARKETPLACE") ?? false)
                {
                    var _id = entry.get("thread_key")?.get("thread_fbid").Value <string>();
                    rtn[_id] = FB_Marketplace._from_graphql(_session, entry);
                }
                else if (entry.get("thread_type")?.Value <string>()?.Equals("ONE_TO_ONE") ?? false)
                {
                    var _id = entry.get("thread_key")?.get("other_user_id")?.Value <string>();
                    if (pages_and_users[_id] == null)
                    {
                        throw new FBchatException(string.Format("Could not fetch thread {0}", _id));
                    }
                    foreach (var elem in pages_and_users[_id])
                    {
                        entry[((JProperty)elem).Name] = ((JProperty)elem).Value;
                    }
                    if (entry.get("first_name") != null)
                    {
                        rtn[_id] = FB_User._from_graphql(_session, entry);
                    }
                    else
                    {
                        rtn[_id] = FB_Page._from_graphql(_session, entry);
                    }
                }
                else
                {
                    throw new FBchatException(string.Format("{0} had an unknown thread type: {1}", thread_ids[obj.i], entry));
                }
            }

            return(rtn);
        }