/*
Copyright (c) 2015-23 Miranda NG team (https://miranda-ng.org)
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 version 2
of the License.
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 .
*/
#ifndef _SKYPE_PROTO_H_
#define _SKYPE_PROTO_H_
struct CSkypeProto : public PROTO
{
friend class CSkypeOptionsMain;
friend class CSkypeGCCreateDlg;
friend class CSkypeInviteDlg;
class CSkypeProtoImpl
{
friend struct CSkypeProto;
CSkypeProto &m_proto;
CTimer m_heartBeat;
void OnHeartBeat(CTimer *)
{
m_proto.ProcessTimer();
}
CSkypeProtoImpl(CSkypeProto &pro) :
m_proto(pro),
m_heartBeat(Miranda_GetSystemWindow(), UINT_PTR(this) + 1)
{
m_heartBeat.OnEvent = Callback(this, &CSkypeProtoImpl::OnHeartBeat);
}
} m_impl;
public:
CSkypeProto(const char *protoName, const wchar_t *userName);
~CSkypeProto();
//////////////////////////////////////////////////////////////////////////////////////
// Virtual functions
MCONTACT AddToList(int flags, PROTOSEARCHRESULT* psr) override;
MCONTACT AddToListByEvent(int flags, int iContact, MEVENT hDbEvent) override;
int AuthRequest(MCONTACT hContact, const wchar_t* szMessage) override;
int Authorize(MEVENT hDbEvent) override;
int AuthDeny(MEVENT hDbEvent, const wchar_t* szReason) override;
int AuthRecv(MCONTACT hContact, PROTORECVEVENT*) override;
INT_PTR GetCaps(int type, MCONTACT hContact = NULL) override;
int GetInfo(MCONTACT hContact, int infoType) override;
HANDLE SearchBasic(const wchar_t* id) override;
int SendMsg(MCONTACT hContact, const char* msg) override;
int SetStatus(int iNewStatus) override;
int UserIsTyping(MCONTACT hContact, int type) override;
int RecvContacts(MCONTACT hContact, PROTORECVEVENT*) override;
HANDLE SendFile(MCONTACT hContact, const wchar_t *szDescription, wchar_t **ppszFiles) override;
HANDLE GetAwayMsg(MCONTACT hContact) override;
int SetAwayMsg(int m_iStatus, const wchar_t *msg) override;
void OnBuildProtoMenu(void) override;
void OnContactDeleted(MCONTACT) override;
MWindow OnCreateAccMgrUI(MWindow) override;
void OnMarkRead(MCONTACT, MEVENT) override;
void OnModulesLoaded() override;
void OnShutdown() override;
// icons
static void InitIcons();
// menus
static void InitMenus();
// popups
void InitPopups();
void UninitPopups();
// languages
static void InitLanguages();
// search
void __cdecl SearchBasicThread(void* id);
//////////////////////////////////////////////////////////////////////////////////////
// services
static INT_PTR EventGetIcon(WPARAM wParam, LPARAM lParam);
static INT_PTR GetEventText(WPARAM, LPARAM lParam);
//////////////////////////////////////////////////////////////////////////////////////
// settings
CMOption bAutoHistorySync;
CMOption bMarkAllAsUnread;
CMOption bUseBBCodes;
CMOption bUseServerTime; // hidden setting!
CMOption bUseHostnameAsPlace;
CMOption wstrPlace;
CMOption wstrCListGroup;
//////////////////////////////////////////////////////////////////////////////////////
// other data
int m_iPollingId;
ptrA m_szApiToken, m_szToken, m_szId;
CMStringA m_szSkypename, m_szMyname;
__forceinline CMStringA getId(MCONTACT hContact) {
return getMStringA(hContact, SKYPE_SETTINGS_ID);
}
void OnReceiveAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnSentAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnSearch(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
// login
void OnLoginOAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnSubscriptionsCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnCapabilitiesSended(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnReceiveStatus(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnStatusChanged(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnEndpointCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnEndpointDeleted(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
// oauth
void OnOAuthStart(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnOAuthConfirm(NETLIBHTTPREQUEST* response, AsyncHttpRequest* pRequest);
void OnOAuthAuthorize(NETLIBHTTPREQUEST* response, AsyncHttpRequest* pRequest);
void OnOAuthEnd(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnASMObjectCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnASMObjectUploaded(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void LoadContactsAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void LoadContactList(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnBlockContact(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnUnblockContact(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnMessageSent(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnGetServerHistory(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnSyncHistory(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnLoadChats(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnGetChatInfo(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void OnReceiveAwayMsg(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
void CheckConvert(void);
bool CheckOauth(const char *szResponse);
void LoadProfile(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest);
static INT_PTR __cdecl GlobalParseSkypeUriService(WPARAM, LPARAM lParam);
private:
bool m_bHistorySynced;
std::map cookies;
static std::map languages;
HANDLE m_hPollingThread;
LIST m_PopupClasses;
LIST m_OutMessages;
// locks
mir_cs m_lckOutMessagesList;
mir_cs messageSyncLock;
mir_cs m_StatusLock;
mir_cs m_AppendMessageLock;
bool m_bThreadsTerminated;
EventHandle m_hPollingEvent;
EventHandle m_hTrouterEvent;
EventHandle m_hTrouterHealthEvent;
INT_PTR __cdecl SvcGetAvatarInfo(WPARAM, LPARAM);
INT_PTR __cdecl SvcGetAvatarCaps(WPARAM, LPARAM);
INT_PTR __cdecl SvcGetMyAvatar(WPARAM, LPARAM);
INT_PTR __cdecl SvcSetMyAvatar(WPARAM, LPARAM);
// requests
bool m_isTerminated = true;
mir_cs m_requestQueueLock;
LIST m_requests;
EventHandle m_hRequestQueueEvent;
HANDLE m_hRequestQueueThread;
void __cdecl WorkerThread(void *);
void StartQueue();
void StopQueue();
NETLIBHTTPREQUEST* DoSend(AsyncHttpRequest *request);
void Execute(AsyncHttpRequest *request);
void PushRequest(AsyncHttpRequest *request);
// menus
static HGENMENU ContactMenuItems[CMI_MAX];
int OnPrebuildContactMenu(WPARAM hContact, LPARAM);
static int PrebuildContactMenu(WPARAM hContact, LPARAM lParam);
// options
int __cdecl OnOptionsInit(WPARAM wParam, LPARAM lParam);
// login
void Login();
void OnLoginSuccess();
void SendPresence();
// profile
void UpdateProfileFirstName(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileLastName(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileDisplayName(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileGender(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileBirthday(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileCountry(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileState(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileCity(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileLanguage(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileHomepage(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileAbout(const JSONNode &node, MCONTACT hContact = NULL);
void UpdateProfileEmails(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfilePhoneMobile(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfilePhoneHome(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfilePhoneOffice(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileXStatusMessage(const JSONNode &root, MCONTACT hContact = NULL);
void UpdateProfileAvatar(const JSONNode &root, MCONTACT hContact = NULL);
void __cdecl CSkypeProto::SendFileThread(void *p);
// contacts
uint16_t GetContactStatus(MCONTACT hContact);
void SetContactStatus(MCONTACT hContact, uint16_t status);
void SetAvatarUrl(MCONTACT hContact, CMStringW &tszUrl);
void ReloadAvatarInfo(MCONTACT hContact);
void GetAvatarFileName(MCONTACT hContact, wchar_t* pszDest, size_t cbLen);
MCONTACT FindContact(const char *skypeId);
MCONTACT FindContact(const wchar_t *skypeId);
MCONTACT AddContact(const char *skypename, const char *nick, bool isTemporary = false);
MCONTACT GetContactFromAuthEvent(MEVENT hEvent);
// messages
std::map m_mpOutMessagesIds;
MEVENT GetMessageFromDb(const char *messageId);
MEVENT AddDbEvent(uint16_t type, MCONTACT hContact, uint32_t timestamp, uint32_t flags, const CMStringW &content, const CMStringA &msgId);
void EditEvent(MEVENT hEvent, const CMStringW &content, time_t edit_time);
int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam);
void MarkMessagesRead(MCONTACT hContact, MEVENT hDbEvent);
void OnPrivateMessageEvent(const JSONNode &node);
void ProcessContactRecv(MCONTACT hContact, time_t timestamp, const char *szContent, const char *szMessageId);
// chats
void InitGroupChatModule();
int __cdecl OnGroupChatEventHook(WPARAM, LPARAM lParam);
int __cdecl OnGroupChatMenuHook(WPARAM, LPARAM lParam);
INT_PTR __cdecl OnJoinChatRoom(WPARAM hContact, LPARAM);
INT_PTR __cdecl OnLeaveChatRoom(WPARAM hContact, LPARAM);
SESSION_INFO* StartChatRoom(const wchar_t *tid, const wchar_t *tname);
void OnChatEvent(const JSONNode &node);
wchar_t* GetChatContactNick(MCONTACT hContact, const wchar_t *id, const wchar_t *name = nullptr);
void AddMessageToChat(SESSION_INFO *si, const wchar_t *from, const wchar_t *content, bool isAction, int emoteOffset, time_t timestamp, bool isLoading = false);
void AddChatContact(SESSION_INFO *si, const wchar_t *id, const wchar_t *role, bool isChange = false);
void RemoveChatContact(SESSION_INFO *si, const wchar_t *id, bool isKick = false, const wchar_t *initiator = L"");
void SendChatMessage(SESSION_INFO *si, const wchar_t *tszMessage);
void SetChatStatus(MCONTACT hContact, int iStatus);
// polling
void __cdecl PollingThread(void*);
void ParsePollData(const char*);
void ProcessNewMessage(const JSONNode &node);
void ProcessUserPresence(const JSONNode &node);
void ProcessThreadUpdate(const JSONNode &node);
void ProcessEndpointPresence(const JSONNode &node);
void ProcessConversationUpdate(const JSONNode &node);
void RefreshStatuses(void);
void ReadHistoryRest(const char *url);
// utils
template
__inline static void FreeList(const LIST &lst)
{
for (auto &it : lst)
mir_free(it);
}
__forceinline bool IsOnline() const
{ return (m_iStatus > ID_STATUS_OFFLINE);
}
__forceinline bool IsMe(const wchar_t *str)
{ return (!mir_wstrcmpi(str, Utf2T(m_szMyname)) || !mir_wstrcmp(str, getMStringW("SelfEndpointName")));
}
__forceinline bool IsMe(const char *str)
{ return (!mir_strcmpi(str, m_szMyname) || !mir_strcmp(str, ptrA(getUStringA("SelfEndpointName"))));
}
static time_t IsoToUnixTime(const std::string &stamp);
static int SkypeToMirandaStatus(const char *status);
static const char *MirandaToSkypeStatus(int status);
void ShowNotification(const wchar_t *message, MCONTACT hContact = NULL);
void ShowNotification(const wchar_t *caption, const wchar_t *message, MCONTACT hContact = NULL, int type = 0);
static bool IsFileExists(std::wstring path);
static LRESULT CALLBACK PopupDlgProcCall(HWND hPopup, UINT uMsg, WPARAM wParam, LPARAM lParam);
void ProcessTimer();
CMStringW RunConfirmationCode();
CMStringW ChangeTopicForm();
//events
void InitDBEvents();
//services
INT_PTR __cdecl BlockContact(WPARAM hContact, LPARAM);
INT_PTR __cdecl UnblockContact(WPARAM hContact, LPARAM);
INT_PTR __cdecl OnRequestAuth(WPARAM hContact, LPARAM lParam);
INT_PTR __cdecl OnGrantAuth(WPARAM hContact, LPARAM);
INT_PTR __cdecl GetContactHistory(WPARAM hContact, LPARAM lParam);
INT_PTR __cdecl SvcCreateChat(WPARAM, LPARAM);
INT_PTR __cdecl ParseSkypeUriService(WPARAM, LPARAM lParam);
template
static INT_PTR __cdecl GlobalService(WPARAM wParam, LPARAM lParam)
{
CSkypeProto *proto = CMPlugin::getInstance((MCONTACT)wParam);
return proto ? (proto->*Service)(wParam, lParam) : 0;
}
};
typedef CProtoDlgBase CSkypeDlgBase;
#endif //_SKYPE_PROTO_H_