summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-01-10 22:47:42 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-01-10 22:47:42 +0300
commit4e69c635f238cc951265e036ef74cef75b9a65c8 (patch)
tree4a8af2c5d841a0551b0c034339fc44ad202eca28
parent8cad7d3baec2de5e117f115f89482b47ad124a18 (diff)
Facebook: added custom reactions' icons to popups
-rw-r--r--protocols/FacebookRM/src/entities.h21
-rw-r--r--protocols/FacebookRM/src/events.cpp17
-rw-r--r--protocols/FacebookRM/src/json.cpp87
-rw-r--r--protocols/FacebookRM/src/proto.cpp4
-rw-r--r--protocols/FacebookRM/src/proto.h5
-rw-r--r--protocols/FacebookRM/src/version.h4
6 files changed, 103 insertions, 35 deletions
diff --git a/protocols/FacebookRM/src/entities.h b/protocols/FacebookRM/src/entities.h
index e1f9b69faa..57fe178249 100644
--- a/protocols/FacebookRM/src/entities.h
+++ b/protocols/FacebookRM/src/entities.h
@@ -129,23 +129,10 @@ struct facebook_notification
std::string text;
std::string link;
std::string id;
- const char *icon;
- time_t time;
- bool seen;
- HWND hWndPopup;
-
- facebook_notification()
- {
- this->time = 0;
- this->seen = false;
- this->hWndPopup = nullptr;
- this->icon = nullptr;
- }
-
- void setIcon(const std::string& /*iconUrl*/)
- {
- icon = nullptr;
- }
+ const char *icon = nullptr;
+ time_t time = 0;
+ bool seen = false;
+ HWND hWndPopup = nullptr;
};
struct facebook_newsfeed
diff --git a/protocols/FacebookRM/src/events.cpp b/protocols/FacebookRM/src/events.cpp
index c6fae5dfee..f0f2d6abbb 100644
--- a/protocols/FacebookRM/src/events.cpp
+++ b/protocols/FacebookRM/src/events.cpp
@@ -28,7 +28,11 @@ HWND FacebookProto::NotifyEvent(wchar_t* title, wchar_t* text, MCONTACT contact,
return nullptr;
char name[256];
-
+ if (icon != nullptr) {
+ strncpy_s(name, icon, _TRUNCATE);
+ Skin_PlaySound("Notification");
+ }
+ else
switch (type) {
case EVENT_CLIENT:
mir_snprintf(name, "%s_%s", m_szModuleName, "Client");
@@ -65,22 +69,11 @@ HWND FacebookProto::NotifyEvent(wchar_t* title, wchar_t* text, MCONTACT contact,
if (!getByte(FACEBOOK_KEY_SYSTRAY_NOTIFY, DEFAULT_SYSTRAY_NOTIFY)) {
if (ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
-
- // TODO: if popup with particular ID is already showed, just update his content
- // ... but f***ed up Popup Classes won't allow it now - they need to return hPopupWindow somehow
- /* if (popup exists) {
- if (PUChangeTextT(hWndPopup, info) > 0) // success
- return;
- }*/
-
POPUPDATACLASS pd = { sizeof(pd) };
pd.pwszTitle = title;
pd.pwszText = text;
pd.pszClassName = name;
pd.hContact = contact;
- if (icon != nullptr) {
- // pd.hIcon = IcoLib_GetIconByHandle(GetIconHandle(icon)); // FIXME: Uncomment when implemented in Popup+ and YAPP correctly
- }
if (url != nullptr || notification_id != nullptr) {
popup_data *data = new popup_data(this);
diff --git a/protocols/FacebookRM/src/json.cpp b/protocols/FacebookRM/src/json.cpp
index ee743ec2f4..af232b9bd6 100644
--- a/protocols/FacebookRM/src/json.cpp
+++ b/protocols/FacebookRM/src/json.cpp
@@ -22,6 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
+LRESULT CALLBACK PopupDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
void parseUser(const JSONNode &it, facebook_user *fbu)
{
fbu->user_id = it.name();
@@ -236,7 +238,7 @@ int FacebookProto::ParseNotifications(std::string *data, std::map< std::string,
notification->link = url_.as_string();
notification->text = utils::text::html_entities_decode(utils::text::slashu_to_utf8(text_.as_string()));
notification->time = utils::time::from_string(time_.as_string());
- notification->setIcon(icon_.as_string());
+ notification->icon = ParseIcon(icon_.as_string());
// Write notification to chatroom
UpdateNotificationsChatRoom(notification);
@@ -431,6 +433,81 @@ bool FacebookProto::ProcessSpecialMessage(std::vector<facebook_message>* message
return true;
}
+const char* FacebookProto::ParseIcon(const std::string &url)
+{
+ if (url.empty())
+ return nullptr;
+
+ auto itr = reactions.find(url);
+ if (itr == reactions.end()) {
+ UCHAR hash[MIR_SHA256_HASH_SIZE];
+ mir_sha256_hash(url.c_str(), url.length(), hash);
+
+ wchar_t wszHash[MIR_SHA256_HASH_SIZE * 2 + 10];
+ bin2hexW(hash, sizeof(hash), wszHash);
+
+ wchar_t wszFileName[MAX_PATH];
+ mir_snwprintf(wszFileName, L"%s\\%s", VARSW(L"%miranda_avatarcache%"), m_tszUserName);
+ if (_waccess(wszFileName, 0))
+ CreateDirectoryTreeW(wszFileName);
+
+ wcscat_s(wszFileName, L"\\");
+ wcscat_s(wszFileName, wszHash);
+ wcscat_s(wszFileName, L".ico");
+ if (_waccess(wszFileName, 0)) {
+ NETLIBHTTPREQUEST req = { sizeof(req) };
+ req.requestType = REQUEST_GET;
+ req.szUrl = (char*)url.c_str();
+ req.flags = NLHRF_NODUMPHEADERS;
+
+ NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(facy.handle_, &req);
+ if (reply != nullptr && reply->resultCode == HTTP_CODE_OK) {
+ IMGSRVC_MEMIO memio = { 0 };
+ memio.iLen = reply->dataLength;
+ memio.pBuf = reply->pData;
+ memio.fif = FIF_UNKNOWN; /* detect */
+
+ HBITMAP hBmp = (HBITMAP)CallService(MS_IMG_LOADFROMMEM, (WPARAM)&memio);
+ if (hBmp != nullptr) {
+ IMGSRVC_INFO info = { sizeof(info) };
+ info.wszName = wszFileName;
+ info.fif = FIF_ICO;
+ info.dwMask = IMGI_HBITMAP;
+ info.hbm = hBmp;
+ CallService(MS_IMG_SAVE, (WPARAM)&info, IMGL_WCHAR);
+ }
+ }
+ }
+
+ HICON hIcon;
+ if (ExtractIconEx(wszFileName, 0, nullptr, &hIcon, 1) == 1) {
+ int idx = (int)reactions.size() + 1;
+ wchar_t desc[256];
+ char name[256];
+ mir_snwprintf(desc, L"%s/%s%d", m_tszUserName, TranslateT("Reaction"), idx);
+ mir_snprintf(name, "%s_%s%d", m_szModuleName, "Reaction", idx);
+
+ POPUPCLASS ppc = { sizeof(ppc) };
+ ppc.flags = PCF_TCHAR;
+ ppc.PluginWindowProc = PopupDlgProc;
+ ppc.lParam = APF_RETURN_HWND;
+ ppc.pwszDescription = desc;
+ ppc.pszName = name;
+ ppc.hIcon = hIcon;
+ ppc.colorBack = RGB(59, 89, 152); // Facebook's blue
+ ppc.colorText = RGB(255, 255, 255); // white
+ ppc.iSeconds = 0;
+ popupClasses.push_back(Popup_RegisterClass(&ppc));
+
+ mir_cslock lck(csReactions);
+ reactions.insert(std::make_pair(url, name));
+ }
+
+ itr = reactions.find(url);
+ }
+
+ return (itr == reactions.end()) ? nullptr : itr->second.c_str();
+}
int FacebookProto::ParseMessages(std::string *pData, std::vector<facebook_message>* messages, std::map< std::string, facebook_notification* >* notifications)
{
@@ -684,7 +761,7 @@ int FacebookProto::ParseMessages(std::string *pData, std::vector<facebook_messag
notification->link = url.as_string();
notification->id = alert_id.as_string();
notification->time = timestamp;
- notification->setIcon(icon_.as_string());
+ notification->icon = ParseIcon(icon_.as_string());
// Fix notification ID
std::string::size_type pos = notification->id.find(":");
@@ -738,6 +815,12 @@ int FacebookProto::ParseMessages(std::string *pData, std::vector<facebook_messag
notification->id = alert_id;
notification->time = utils::time::from_string(data["time"].as_string());
+ const JSONNode &app_icon_ = data["app_icon"]["__html"];
+ if (app_icon_) {
+ std::string url = app_icon_.as_string();
+ notification->icon = ParseIcon(utils::text::source_get_value(&url, 3, "img class=\"img\"", "src=\"", "\""));
+ }
+
// Write notification to chatroom
UpdateNotificationsChatRoom(notification);
diff --git a/protocols/FacebookRM/src/proto.cpp b/protocols/FacebookRM/src/proto.cpp
index d64100165b..be0f917120 100644
--- a/protocols/FacebookRM/src/proto.cpp
+++ b/protocols/FacebookRM/src/proto.cpp
@@ -108,8 +108,8 @@ FacebookProto::FacebookProto(const char* proto_name, const wchar_t* username) :
FacebookProto::~FacebookProto()
{
// Uninit popup classes
- for (std::vector<HANDLE>::size_type i = 0; i < popupClasses.size(); i++)
- Popup_UnregisterClass(popupClasses[i]);
+ for (auto &it : popupClasses)
+ Popup_UnregisterClass(it);
popupClasses.clear();
Netlib_CloseHandle(m_hNetlibUser);
diff --git a/protocols/FacebookRM/src/proto.h b/protocols/FacebookRM/src/proto.h
index 7a004640e8..d5e3617546 100644
--- a/protocols/FacebookRM/src/proto.h
+++ b/protocols/FacebookRM/src/proto.h
@@ -45,6 +45,8 @@ class FacebookProto : public PROTO<FacebookProto>
int ParseUnreadThreads(std::string*, std::vector< std::string >*);
int ParseUserInfo(std::string* data, facebook_user* fbu);
+ const char* ParseIcon(const std::string &url);
+
public:
FacebookProto(const char *proto_name, const wchar_t *username);
~FacebookProto();
@@ -276,6 +278,9 @@ public:
std::string last_status_msg_;
std::vector<MCONTACT> avatar_queue;
+ mir_cs csReactions;
+ std::map<std::string, std::string> reactions;
+
// Information providing
HWND NotifyEvent(wchar_t* title, wchar_t* text, MCONTACT contact, EventType type, std::string *url = nullptr, std::string *notification_id = nullptr, const char *icon = nullptr);
void ShowNotifications();
diff --git a/protocols/FacebookRM/src/version.h b/protocols/FacebookRM/src/version.h
index 070b2bc311..130684e559 100644
--- a/protocols/FacebookRM/src/version.h
+++ b/protocols/FacebookRM/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 4
-#define __RELEASE_NUM 0
-#define __BUILD_NUM 3
+#define __RELEASE_NUM 1
+#define __BUILD_NUM 1
#include <stdver.h>