/*
Facebook plugin for Miranda Instant Messenger
_____________________________________________
Copyright � 2009-11 Michal Zelinka, 2011-17 Robert P�sel
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
class FacebookProto : public PROTO
{
public:
FacebookProto(const char *proto_name, const wchar_t *username);
~FacebookProto();
inline const char* ModuleName() const
{
return m_szModuleName;
}
inline bool isOnline()
{
return (m_iStatus != ID_STATUS_OFFLINE && m_iStatus != ID_STATUS_CONNECTING);
}
inline bool isOffline()
{
return (m_iStatus == ID_STATUS_OFFLINE);
}
inline bool isInvisible()
{
return m_invisible;
//return (m_iStatus == ID_STATUS_INVISIBLE);
}
inline int IdleSeconds()
{
if (m_iStatus == ID_STATUS_AWAY && m_awayTS)
return time(0) - m_awayTS;
return m_idleTS ? time(0) - m_idleTS : 0;
}
bool m_invisible;
bool m_enableChat;
bool m_signingOut;
time_t m_idleTS;
time_t m_awayTS;
time_t m_pingTS;
std::string m_locale;
std::string m_pagePrefix;
// DB utils missing in proto_interface
__forceinline INT_PTR getStringUtf(const char *name, DBVARIANT *result) {
return db_get_utf(NULL, m_szModuleName, name, result); }
__forceinline INT_PTR getStringUtf(MCONTACT hContact, const char *name, DBVARIANT *result) {
return db_get_utf(hContact, m_szModuleName, name, result); }
__forceinline void setStringUtf(const char *name, const char* value) { db_set_utf(NULL, m_szModuleName, name, value); }
__forceinline void setStringUtf(MCONTACT hContact, const char *name, const char* value) { db_set_utf(hContact, m_szModuleName, name, value); }
//PROTO_INTERFACE
virtual MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT* psr);
virtual int __cdecl Authorize(MEVENT hDbEvent);
virtual int __cdecl AuthDeny(MEVENT hDbEvent, const wchar_t* szReason);
virtual int __cdecl AuthRequest(MCONTACT hContact, const wchar_t* szMessage);
virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL);
virtual int __cdecl GetInfo(MCONTACT hContact, int infoType);
virtual HANDLE __cdecl SearchBasic(const wchar_t* id);
virtual HANDLE __cdecl SearchByEmail(const wchar_t* email);
virtual HANDLE __cdecl SearchByName(const wchar_t* nick, const wchar_t* firstName, const wchar_t* lastName);
virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT*);
virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg);
virtual int __cdecl SetStatus(int iNewStatus);
virtual HANDLE __cdecl GetAwayMsg(MCONTACT hContact);
virtual int __cdecl SetAwayMsg(int iStatus, const wchar_t* msg);
virtual int __cdecl UserIsTyping(MCONTACT hContact, int type);
virtual int __cdecl OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam);
////////////////////////
// Services
INT_PTR __cdecl GetMyAwayMsg(WPARAM, LPARAM);
INT_PTR __cdecl SetMyAwayMsg(WPARAM, LPARAM);
INT_PTR __cdecl SvcCreateAccMgrUI(WPARAM, LPARAM);
INT_PTR __cdecl GetMyAvatar(WPARAM, LPARAM);
INT_PTR __cdecl GetAvatarInfo(WPARAM, LPARAM);
INT_PTR __cdecl GetAvatarCaps(WPARAM, LPARAM);
INT_PTR __cdecl VisitProfile(WPARAM, LPARAM);
INT_PTR __cdecl VisitFriendship(WPARAM, LPARAM);
INT_PTR __cdecl VisitConversation(WPARAM, LPARAM);
INT_PTR __cdecl VisitNotifications(WPARAM, LPARAM);
INT_PTR __cdecl Poke(WPARAM, LPARAM);
INT_PTR __cdecl LoadHistory(WPARAM, LPARAM);
INT_PTR __cdecl CancelFriendship(WPARAM, LPARAM);
INT_PTR __cdecl RequestFriendship(WPARAM, LPARAM);
INT_PTR __cdecl ApproveFriendship(WPARAM, LPARAM);
INT_PTR __cdecl DenyFriendship(WPARAM, LPARAM);
INT_PTR __cdecl OnCancelFriendshipRequest(WPARAM, LPARAM);
INT_PTR __cdecl CheckNewsfeeds(WPARAM, LPARAM);
INT_PTR __cdecl CheckFriendRequests(WPARAM, LPARAM);
INT_PTR __cdecl CheckNotifications(WPARAM, LPARAM);
INT_PTR __cdecl CheckMemories(WPARAM, LPARAM);
INT_PTR __cdecl GetNotificationsCount(WPARAM, LPARAM);
INT_PTR __cdecl OnJoinChat(WPARAM,LPARAM);
INT_PTR __cdecl OnLeaveChat(WPARAM,LPARAM);
INT_PTR __cdecl OnMind(WPARAM,LPARAM);
// Initialization
void InitPopups();
void InitHotkeys();
void InitSounds();
void InitMenu();
// Events
int __cdecl OnModulesLoaded(WPARAM, LPARAM);
int __cdecl OnOptionsInit(WPARAM, LPARAM);
int __cdecl OnToolbarInit(WPARAM, LPARAM);
int __cdecl OnBuildStatusMenu(WPARAM,LPARAM);
int __cdecl OnContactDeleted(WPARAM,LPARAM);
int __cdecl OnPreShutdown(WPARAM,LPARAM);
int __cdecl OnPrebuildContactMenu(WPARAM,LPARAM);
int __cdecl OnIdleChanged(WPARAM,LPARAM);
int __cdecl OnGCEvent(WPARAM,LPARAM);
int __cdecl OnGCMenuHook(WPARAM,LPARAM);
int __cdecl OnDbEventRead(WPARAM, LPARAM);
int __cdecl OnProcessSrmmEvent(WPARAM, LPARAM);
int __cdecl OnPreCreateEvent(WPARAM, LPARAM);
// Loops
bool NegotiateConnection();
BYTE GetPollRate();
void __cdecl MessageLoop(void*);
void __cdecl UpdateLoop(void*);
// Processing threads
void __cdecl ProcessFriendList(void*);
void __cdecl ProcessMessages(void*);
void __cdecl ProcessUnreadMessages(void*);
void __cdecl ProcessUnreadMessage(void*);
void __cdecl ProcessFeeds(void*);
void __cdecl ProcessNotifications(void*);
void __cdecl ProcessFriendRequests(void*);
void __cdecl SearchAckThread(void*);
void __cdecl SearchIdAckThread(void*);
void __cdecl ProcessPages(void*);
void __cdecl LoadLastMessages(void*);
void __cdecl LoadHistory(void*);
void __cdecl ProcessMemories(void*);
// Worker threads
void __cdecl SignOn(void*);
void __cdecl ChangeStatus(void*);
void __cdecl SignOff(void*);
void __cdecl SetAwayMsgWorker(void*);
void __cdecl UpdateAvatarWorker(void*);
void __cdecl SendMsgWorker(void*);
void __cdecl SendChatMsgWorker(void*);
void __cdecl SendTypingWorker(void*);
void __cdecl ReadMessageWorker(void*);
void __cdecl ReadNotificationWorker(void*);
void __cdecl DeleteContactFromServer(void*);
void __cdecl AddContactToServer(void*);
void __cdecl ApproveContactToServer(void*);
void __cdecl CancelFriendsRequest(void*);
void __cdecl SendPokeWorker(void*);
void __cdecl IgnoreFriendshipRequest(void*);
void __cdecl RefreshUserInfo(void*);
// Contacts handling
bool IsMyContact(MCONTACT, bool include_chat = false);
MCONTACT ContactIDToHContact(const std::string&);
MCONTACT ChatIDToHContact(const std::string&);
std::string ThreadIDToContactID(const std::string&);
void LoadContactInfo(facebook_user* fbu);
MCONTACT AddToContactList(facebook_user*, bool force_add = false, bool add_temporarily = false);
void SetAllContactStatuses(int status);
MCONTACT HContactFromAuthEvent(MEVENT hEvent);
void StartTyping(MCONTACT hContact);
void StopTyping(MCONTACT hContact);
// Chats handling
void AddChat(const char *chat_id, const wchar_t *name);
void UpdateChat(const char *chat_id, const char *id, const char *name, const char *message, DWORD timestamp = 0, bool is_old = false);
void RenameChat(const char *chat_id, const char *name);
bool IsChatContact(const char *chat_id, const char *id);
void AddChatContact(const char *chat_id, const chatroom_participant &user, bool addToLog);
void RemoveChatContact(const char *chat_id, const char *id, const char *name);
char *GetChatUsers(const char *chat_id);
void ReceiveMessages(std::vector &messages, bool check_duplicates = false);
void LoadChatInfo(facebook_chatroom* fbc);
void LoadParticipantsNames(facebook_chatroom *fbc);
void JoinChatrooms();
bool IsSpecialChatRoom(MCONTACT hContact);
void PrepareNotificationsChatRoom();
void UpdateNotificationsChatRoom(facebook_notification *notification);
std::string FacebookProto::GenerateChatName(facebook_chatroom *fbc);
// Connection client
facebook_client facy; // TODO: Refactor to "client" and make dynamic
// Helpers
std::wstring GetAvatarFolder();
bool GetDbAvatarInfo(PROTO_AVATAR_INFORMATION &ai, std::string *url);
void CheckAvatarChange(MCONTACT hContact, const std::string &image_url);
void ToggleStatusMenuItems(bool bEnable);
void StickerAsSmiley(std::string stickerId, const std::string &url, MCONTACT hContact);
void SaveName(MCONTACT hContact, const facebook_user *fbu);
std::string PrepareUrl(std::string url);
void OpenUrl(std::string url);
void __cdecl OpenUrlThread(void*);
void MessageRead(MCONTACT hContact);
bool RunCaptchaForm(std::string imageUrl, std::string &result);
// Menu items
HGENMENU m_hMenuServicesRoot;
HGENMENU m_hStatusMind;
// Locks
HANDLE signon_lock_;
HANDLE avatar_lock_;
HANDLE log_lock_;
HANDLE update_loop_lock_;
ptrW m_tszDefaultGroup;
std::vector popupClasses;
std::string last_status_msg_;
std::vector avatar_queue;
static void CALLBACK APC_callback(ULONG_PTR p);
// Information providing
HWND NotifyEvent(wchar_t* title, wchar_t* text, MCONTACT contact, EventType type, std::string *url = NULL, std::string *notification_id = NULL, const char *icon = NULL);
void ShowNotifications();
};