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 }); }
/// <summary> /// Fetches`Message` object from the message id /// </summary> /// <param name="thread">Thread containing this message</param> /// <param name="mid">Message ID to fetch from</param> /// <returns>`FB_Message` object</returns> public static async Task <FB_Message> _from_fetch(FB_Thread thread, string mid) { /* * Fetches`Message` object from the message id * :param thread: Thread containing this message * :param mid: Message ID to fetch from * :return: `Message` object * :rtype: Message * :raises: FBchatException if request failed * */ var message_info = ((JToken)await thread._forcedFetch(mid))?.get("message"); return(FB_Message._from_graphql(message_info, thread)); }
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 }); }
internal static FB_Message _from_pull(JToken data, FB_Thread thread, string author = null, string timestamp = null) { var metadata = data?.get("messageMetadata"); var tags = metadata?.get("tags")?.ToObject <List <string> >(); var rtn = new FB_Message( session: thread.session, text: data.get("body")?.Value <string>()); rtn.uid = metadata?.get("messageId")?.Value <string>(); rtn.session = thread.session; rtn.thread_id = thread.uid; rtn.author = author; rtn.timestamp = timestamp; rtn.mentions = JToken.Parse(data.get("data")?.get("prng")?.Value <string>() ?? "{}")?.Select((m) => FB_Mention._from_prng(m) ).ToList(); if (data.get("attachments") != null) { try { foreach (var a in data.get("attachments")) { var mercury = a.get("mercury"); if (mercury.get("blob_attachment") != null) { var image_metadata = a.get("imageMetadata"); var attach_type = mercury.get("blob_attachment")?.get("__typename")?.Value <string>(); var attachment = FB_Attachment.graphql_to_attachment( mercury.get("blob_attachment") ); if (new string[] { "MessageFile", "MessageVideo", "MessageAudio" }.Contains(attach_type)) { // TODO: Add more data here for audio files if (attachment is FB_FileAttachment) { ((FB_FileAttachment)attachment).size = a?.get("fileSize")?.Value <int>() ?? 0; } if (attachment is FB_VideoAttachment) { ((FB_VideoAttachment)attachment).size = a?.get("fileSize")?.Value <int>() ?? 0; } } rtn.attachments.Add(attachment); } else if (mercury.get("sticker_attachment") != null) { rtn.sticker = FB_Sticker._from_graphql( mercury.get("sticker_attachment") ); } else if (mercury.get("extensible_attachment") != null) { var attachment = FB_Attachment.graphql_to_extensible_attachment( mercury.get("extensible_attachment") ); if (attachment is FB_UnsentMessage) { rtn.unsent = true; } else if (attachment != null) { rtn.attachments.Add(attachment); } } } } catch { Debug.WriteLine(string.Format("An exception occured while reading attachments: {0}", data.get("attachments"))); } } rtn.emoji_size = EmojiSizeMethods._from_tags(tags); rtn.forwarded = FB_Message._get_forwarded_from_tags(tags); return(rtn); }
internal static FB_Message _from_reply(JToken data, FB_Thread thread) { var tags = data.get("messageMetadata")?.get("tags")?.ToObject <List <string> >(); var rtn = new FB_Message( session: thread.session, text: data.get("body")?.Value <string>(), mentions: JToken.Parse(data.get("data")?.get("prng")?.Value <string>() ?? "{}")?.Select((m) => FB_Mention._from_prng(m) ).ToList(), emoji_size: EmojiSizeMethods._from_tags(tags)); var metadata = data.get("messageMetadata"); rtn.forwarded = FB_Message._get_forwarded_from_tags(tags); rtn.uid = metadata?.get("messageId")?.Value <string>(); rtn.thread_id = thread.uid; // Added rtn.author = metadata?.get("actorFbId")?.Value <string>(); rtn.timestamp = metadata?.get("timestamp")?.Value <string>(); rtn.reply_to_id = data?.get("messageReply")?.get("replyToMessageId")?.get("id")?.Value <string>(); rtn.unsent = false; if (data.get("data")?.get("platform_xmd") != null) { var quick_replies = JToken.Parse(data.get("data")?.get("platform_xmd").Value <string>()).get("quick_replies"); if (quick_replies.Type == JTokenType.Array) { rtn.quick_replies = quick_replies.Select((q) => FB_QuickReply.graphql_to_quick_reply(q)).ToList(); } else { rtn.quick_replies = new List <FB_QuickReply>() { FB_QuickReply.graphql_to_quick_reply(quick_replies) } }; } foreach (var atc in data.get("attachments") ?? Enumerable.Empty <JToken>()) { var attachment = JToken.Parse(atc.get("mercuryJSON")?.Value <string>()); if (attachment.get("blob_attachment") != null) { rtn.attachments.Add( FB_Attachment.graphql_to_attachment(attachment.get("blob_attachment")) ); } if (attachment.get("extensible_attachment") != null) { var ext_attachment = FB_Attachment.graphql_to_extensible_attachment(attachment.get("extensible_attachment")); if (ext_attachment is FB_UnsentMessage) { rtn.unsent = true; } else if (ext_attachment != null) { rtn.attachments.Add(ext_attachment); } } } return(rtn); }
internal static FB_Message _from_graphql(JToken data, FB_Thread thread, JToken read_receipts = null) { if (data["message_sender"] == null) { data["message_sender"] = new JObject(new JProperty("id", 0)); } if (data["message"] == null) { data["message"] = new JObject(new JProperty("text", "")); } var tags = data.get("tags_list")?.ToObject <List <string> >(); var rtn = new FB_Message( session: thread.session, text: data.get("message")?.get("text")?.Value <string>(), mentions: data.get("message")?.get("ranges")?.Select((m) => FB_Mention._from_range(m) ).ToList(), emoji_size: EmojiSizeMethods._from_tags(tags), sticker: FB_Sticker._from_graphql(data.get("sticker"))); rtn.forwarded = FB_Message._get_forwarded_from_tags(tags); rtn.uid = data.get("message_id")?.Value <string>(); rtn.thread_id = thread.uid; // Added rtn.author = data.get("message_sender")?.get("id")?.Value <string>(); rtn.timestamp = data.get("timestamp_precise")?.Value <string>(); rtn.unsent = false; if (data.get("unread") != null) { rtn.is_read = !data.get("unread").Value <bool>(); } rtn.reactions = new Dictionary <string, string>(); foreach (var r in data.get("message_reactions")) { rtn.reactions.Add(r.get("user")?.get("id")?.Value <string>(), r.get("reaction").Value <string>()); } if (data.get("blob_attachments") != null) { rtn.attachments = new List <FB_Attachment>(); foreach (var attachment in data.get("blob_attachments")) { rtn.attachments.Add(FB_Attachment.graphql_to_attachment(attachment)); } } if (data.get("platform_xmd_encoded") != null) { var quick_replies = JToken.Parse(data.get("platform_xmd_encoded")?.Value <string>()).get("quick_replies"); if (quick_replies != null) { if (quick_replies.Type == JTokenType.Array) { rtn.quick_replies = quick_replies.Select((q) => FB_QuickReply.graphql_to_quick_reply(q)).ToList(); } else { rtn.quick_replies = new List <FB_QuickReply>() { FB_QuickReply.graphql_to_quick_reply(quick_replies) } }; } } if (data.get("extensible_attachment") != null) { var attachment = FB_Attachment.graphql_to_extensible_attachment(data.get("extensible_attachment")); if (attachment is FB_UnsentMessage) { rtn.unsent = true; } else if (attachment != null) { rtn.attachments.Add(attachment); } } if (data.get("replied_to_message") != null && data.get("replied_to_message").get("message") != null) { // data["replied_to_message"]["message"] is None if the message is deleted rtn.replied_to = FB_Message._from_graphql(data.get("replied_to_message").get("message"), thread); rtn.reply_to_id = rtn.replied_to.uid; } if (read_receipts != null) { rtn.read_by = read_receipts.Where(r => long.Parse(r.get("watermark")?.Value <string>()) >= long.Parse(rtn.timestamp)) .Select(r => r.get("actor")?.get("id")?.Value <string>()).ToList(); } return(rtn); }
/// <summary> /// Searches for messages in all threads /// Intended to be used alongside `FB_Thread.searchMessages` /// </summary> /// <param name="query">Text to search for</param> /// <param name="offset">Number of messages to skip</param> /// <param name="limit">Max. number of threads to retrieve</param> /// <returns>Iterable with tuples of threads, and the total amount of matching messages in each</returns> public async Task <List <(FB_Thread thread, int count)> > searchMessages(string query, int offset = 0, int limit = 5) { /* * Search for messages in all threads. * Intended to be used alongside `FB_Thread.searchMessages` * Warning! If someone send a message to a thread that matches the query, while * we're searching, some snippets will get returned twice. * Not sure if we should handle it, Facebook's implementation doesn't... * Args: * query: Text to search for * limit: Max. number of threads to retrieve. If ``None``, all threads will be * retrieved. * Returns: * Iterable with tuples of threads, and the total amount of matching messages in each. */ var data = new Dictionary <string, object>() { { "query", query }, { "offset", offset.ToString() }, { "limit", limit.ToString() } }; var j = await this._session._payload_post("/ajax/mercury/search_snippets.php?dpr=1", data); var total_snippets = j?.get("search_snippets")?.get(query); var rtn = new List <(FB_Thread, int)>(); foreach (var node in j?.get("graphql_payload")?.get("message_threads")) { FB_Thread thread = null; var type_ = node?.get("thread_type")?.Value <string>(); if (type_ == "GROUP") { thread = new FB_Group( session: _session, uid: node?.get("thread_key")?.get("thread_fbid")?.Value <string>() ); } else if (type_ == "ONE_TO_ONE") { thread = new FB_Thread( session: _session, uid: node?.get("thread_key")?.get("other_user_id")?.Value <string>() ); } //if True: // TODO: This check! // thread = UserData._from_graphql(self.session, node) //else: // thread = PageData._from_graphql(self.session, node) else { throw new FBchatException(string.Format("Unknown thread type: {0}", type_)); } if (thread != null) { rtn.Add((thread, total_snippets?.get(thread.uid)?.get("num_total_snippets")?.Value <int>() ?? 0)); } else { rtn.Add((null, 0)); } } return(rtn); }