/*
Facebook plugin for Miranda Instant Messenger
_____________________________________________
Copyright © 2009-11 Michal Zelinka, 2011-17 Robert Pösel, 2017-18 Miranda NG team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "constants.h"
#pragma once
#define FORCE_DISCONNECT 1
#define FORCE_QUIT 2
class facebook_client
{
public:
////////////////////////////////////////////////////////////
// Client definition
facebook_client()
{
}
// Random generator value for this client
unsigned int random_ = 0;
// Parent handle
FacebookProto *parent = nullptr;
// User data
facebook_user self_;
std::string username_;
std::string password_;
std::string dtsg_;
std::string ttstamp_;
std::string logout_hash_;
std::string chat_channel_;
std::string chat_channel_host_;
std::string chat_channel_partition_;
std::string chat_sequence_num_;
std::string chat_reconnect_reason_;
std::string chat_sticky_num_;
std::string chat_sticky_pool_;
std::string chat_conn_num_;
std::string chat_clientid_;
std::string chat_traceid_;
time_t last_feeds_update_ = 0;
time_t last_notification_time_ = 0;
volatile unsigned int msgid_ = 0;
int chat_msgs_recv_ = 0;
volatile unsigned int chat_req_ = 0;
bool mbasicWorks = true;
////////////////////////////////////////////////////////////
// Client vs protocol communication
void client_notify(wchar_t* message);
void info_notify(wchar_t* message);
////////////////////////////////////////////////////////////
// Cookies, Data storage
mir_cs cookies_lock_;
std::map cookies;
std::map pages;
std::map chat_rooms;
std::map notifications;
// Contact/thread id caches
std::map thread_id_to_user_id;
std::map chat_id_to_hcontact;
std::map user_id_to_hcontact;
std::string get_server_type();
std::string get_privacy_type();
std::set ignore_read;
std::set typers; // store info about typing contacts, because Facebook doesn't send "stopped typing" event when there is actual message being sent
std::map readers;
char* load_cookies();
void store_headers(http::response* resp, NETLIBHTTPHEADER* headers, int headers_count);
void clear_cookies();
void clear_notifications();
void clear_chatrooms();
void clear_readers();
void insert_reader(MCONTACT, time_t, const std::string &readerId = "");
void erase_reader(MCONTACT);
////////////////////////////////////////////////////////////
// Connection handling
unsigned int error_count_ = 0;
bool handle_entry(const std::string &method);
bool handle_success(const std::string &method);
bool handle_error(const std::string &method, int force_disconnect = 0);
void __inline increment_error() { this->error_count_++; }
void __inline decrement_error() { if (error_count_ > 0) error_count_--; }
void __inline reset_error() { error_count_ = 0; }
////////////////////////////////////////////////////////////
// Helpers for data
__inline const char *__dyn() const {
return "7AzkXxaA4ojgDxyLqzGomzEbHGbGey8WhLFwgoqwWhE98nwgUaoepovHyodEbbxW4E4u3ucDBwJx62i2PxOcG4K1Zxa2m4oqyUf8oCK251G6XDwnU567oeo5m4pHxC326U6OfBwHx";
// FIXME: What's this value and where it come from? Looks like it is the same through all requests.
}
__inline CMStringA __req() {
// Increment request number and convert it to string with radix 36 (whole numbers + whole alphabet)
char buffer[10];
itoa(InterlockedIncrement(&this->chat_req_), buffer, 36);
return CMStringA(buffer);
}
__inline const char *__rev() const {
return "3553943";
}
////////////////////////////////////////////////////////////
// Login handling
bool login(const char *username, const char *password);
bool logout();
bool sms_code(const char *fb_dtsg);
////////////////////////////////////////////////////////////
// Session handling
bool home();
bool reconnect();
bool chat_state(bool online = true);
////////////////////////////////////////////////////////////
// Updates handling
mir_cs send_message_lock_;
mir_cs notifications_lock_;
////////////////////////////////////////////////////////////
// Messages handling
std::map messages_ignore;
std::map messages_timestamp;
bool loading_history = false;
mir_cs loading_history_lock_;
bool channel();
bool activity_ping();
int send_message(int seqid, MCONTACT, const std::string &message_text, std::string *error_text, const std::string &captchaPersistData = "", const std::string &captcha = "");
////////////////////////////////////////////////////////////
// Status handling
bool post_status(status_data *data);
////////////////////////////////////////////////////////////
// HTTP communication
http::response sendRequest(class HttpRequest *request);
bool save_url(const std::string &url, const std::wstring &filename, HNETLIBCONN &nlc);
// channel.cpp
enum Type { PULL, PING };
HttpRequest* channelRequest(Type type);
// contacts.cpp
HttpRequest* addFriendRequest(const char *userId);
HttpRequest* deleteFriendRequest(const char *userId);
HttpRequest* getFriendshipsRequest();
HttpRequest* answerFriendshipRequest(const char *userId, bool bConfirm);
HttpRequest* cancelFriendshipRequest(const char *userId);
HttpRequest* userInfoRequest(const LIST &userIds);
HttpRequest* userInfoAllRequest();
// feeds.cpp
HttpRequest* newsfeedRequest();
HttpRequest* memoriesRequest();
// history.cpp
HttpRequest* threadInfoRequest(bool isChat, const char *id, const char* timestamp = nullptr, int limit = -1, bool loadMessages = false);
HttpRequest* threadInfoRequest(const LIST &ids, int limit);
HttpRequest* unreadThreadsRequest();
// login.cpp
HttpRequest* loginRequest();
HttpRequest* loginRequest(const char *username, const char *password, const char *urlData, const char *bodyData);
HttpRequest* logoutRequest();
HttpRequest* loginSmsRequest(const char *dtsg);
HttpRequest* setupMachineRequest();
HttpRequest* setupMachineRequest(const char *dtsg, const char *nh, const char *submit);
// messages.cpp
HttpRequest* sendMessageRequest(const char *userId, const char *threadId, const char *messageId, const char *messageText, bool isChat, const char *captcha, const char *captchaPersistData);
HttpRequest* sendTypingRequest(const char *userId, bool isChat, bool isTyping);
HttpRequest* markMessageReadRequest(const LIST &ids);
HttpRequest* destroyThreadRequest(facebook_chatroom *fbc);
HttpRequest* exitThreadRequest(facebook_chatroom *fbc);
// notifications.cpp
HttpRequest* getNotificationsRequest(int count);
HttpRequest* markNotificationReadRequest(const char *id);
// profile.cpp
HttpRequest* homeRequest();
HttpRequest* dtsgRequest();
HttpRequest* profileRequest(const char *data);
HttpRequest* profileInfoRequest(const char *userId);
HttpRequest* profilePictureRequest(const char *userId);
// search.cpp
HttpRequest* searchRequest(const char *query, int s, int pn, const char *ssid);
// status.cpp
HttpRequest* reconnectRequest();
HttpRequest* setVisibilityRequest(bool online);
// utils.cpp
HttpRequest* linkScraperRequest(status_data *status);
HttpRequest* refreshCaptchaRequest(const char *captchaPersistData);
HttpRequest* getPagesRequest();
HttpRequest* switchIdentityRequest(const char *userId);
HttpRequest* sharePostRequest(status_data *status, const char *linkData);
HttpRequest* sendPokeRequest(const char *userId);
////////////////////////////////////////////////////////////
// Netlib handle
HNETLIBUSER handle_ = nullptr;
void set_handle(HNETLIBUSER h)
{
handle_ = h;
}
};