summaryrefslogtreecommitdiff
path: root/protocols/Facebook
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-01-02 22:30:54 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-01-02 22:30:54 +0300
commit26d7cc8c81533ca32ec795f1035b01a23c71a06d (patch)
tree8695c3a8143cbb2fe0e0a63ccb03250c7419f0f5 /protocols/Facebook
parent7f88379698aa8a608c9a2b3f23c4e21c207f5735 (diff)
Facebook: stickers support
Diffstat (limited to 'protocols/Facebook')
-rw-r--r--protocols/Facebook/src/avatars.cpp195
-rw-r--r--protocols/Facebook/src/server.cpp64
2 files changed, 64 insertions, 195 deletions
diff --git a/protocols/Facebook/src/avatars.cpp b/protocols/Facebook/src/avatars.cpp
index 284332f32e..1823c8da4d 100644
--- a/protocols/Facebook/src/avatars.cpp
+++ b/protocols/Facebook/src/avatars.cpp
@@ -134,198 +134,3 @@ INT_PTR FacebookProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
return res;
}
-
-
-/*
-bool FacebookProto::GetDbAvatarInfo(PROTO_AVATAR_INFORMATION &pai, std::string *url)
-{
- ptrA id(getStringA(pai.hContact, FACEBOOK_KEY_ID));
- if (id == nullptr)
- return false;
-
- if (url) {
- *url = FACEBOOK_URL_PICTURE;
- utils::text::replace_first(url, "%s", std::string(id));
- }
-
- std::wstring filename = GetAvatarFolder() + L'\\' + std::wstring(_A2T(id)) + L".jpg";
-
- wcsncpy_s(pai.filename, filename.c_str(), _TRUNCATE);
- pai.format = ProtoGetAvatarFormat(pai.filename);
- return true;
-}
-
-void FacebookProto::CheckAvatarChange(MCONTACT hContact, const std::string &image_url)
-{
- std::wstring::size_type pos = image_url.rfind("/");
-
- // Facebook contacts always have some avatar - keep avatar in database even if we have loaded empty one (e.g. for 'On Mobile' contacts)
- if (image_url.empty() || pos == std::wstring::npos)
- return;
-
- // Get name of image
- std::string image_name = image_url.substr(pos + 1);
-
- // Remove eventual parameters from name
- pos = image_name.rfind("?");
- if (pos != std::wstring::npos)
- image_name = image_name.substr(0, pos);
-
- // Append our parameters to allow comparing for avatar/settings change
- if (getBool(FACEBOOK_KEY_BIG_AVATARS, DEFAULT_BIG_AVATARS))
- image_name += "?big";
-
- // Check for avatar change
- ptrA old_name(getStringA(hContact, FACEBOOK_KEY_AVATAR));
- bool update_required = (old_name == nullptr || image_name.compare(old_name) != 0);
-
- // TODO: Remove this in some newer version
- if (old_name == nullptr) {
- // Remove AvatarURL value, which was used in previous versions of plugin
- delSetting(hContact, "AvatarURL");
- }
-
- if (update_required)
- setString(hContact, FACEBOOK_KEY_AVATAR, image_name.c_str());
-
- if (!hContact) {
- PROTO_AVATAR_INFORMATION ai = { 0 };
- if (GetAvatarInfo(update_required ? GAIF_FORCE : 0, (LPARAM)&ai) != GAIR_WAITFOR)
- ReportSelfAvatarChanged();
- }
- else if (update_required) {
- db_set_b(hContact, "ContactPhoto", "NeedUpdate", 1);
- ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, nullptr);
- }
-}
-
-void FacebookProto::UpdateAvatarWorker(void *)
-{
- HNETLIBCONN nlc = nullptr;
-
- debugLogA("*** UpdateAvatarWorker");
-
- std::string params = getBool(FACEBOOK_KEY_BIG_AVATARS, DEFAULT_BIG_AVATARS) ? "?width=200&height=200" : "?width=80&height=80";
-
- for (;;) {
- std::string url;
- PROTO_AVATAR_INFORMATION ai = { 0 };
- ai.hContact = avatar_queue[0];
-
- if (Miranda_IsTerminated()) {
- debugLogA("*** Terminating avatar update early: %s", url.c_str());
- break;
- }
-
- if (GetDbAvatarInfo(ai, &url)) {
- debugLogA("*** Updating avatar: %s", url.c_str());
- bool success = facy.save_url(url + params, ai.filename, nlc);
-
- if (ai.hContact)
- ProtoBroadcastAck(ai.hContact, ACKTYPE_AVATAR, success ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)&ai);
- else if (success)
- ReportSelfAvatarChanged();
- }
-
- mir_cslock s(avatar_lock_);
- avatar_queue.erase(avatar_queue.begin());
- if (avatar_queue.empty())
- break;
- }
- Netlib_CloseHandle(nlc);
-}
-
-std::wstring FacebookProto::GetAvatarFolder()
-{
- wchar_t path[MAX_PATH];
- mir_snwprintf(path, L"%s\\%s", VARSW(L"%miranda_avatarcache%"), m_tszUserName);
- return path;
-}
-
-INT_PTR FacebookProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam)
-{
- int res = 0;
-
- switch (wParam) {
- case AF_MAXSIZE:
- ((POINT*)lParam)->x = -1;
- ((POINT*)lParam)->y = -1;
- break;
-
- case AF_FORMATSUPPORTED:
- res = (lParam == PA_FORMAT_JPEG || lParam == PA_FORMAT_GIF);
- break;
-
- case AF_DELAYAFTERFAIL:
- res = 10 * 60 * 1000;
- break;
-
- case AF_ENABLED:
- case AF_FETCHIFPROTONOTVISIBLE:
- case AF_FETCHIFCONTACTOFFLINE:
- res = 1;
- break;
- }
-
- return res;
-}
-
-INT_PTR FacebookProto::GetAvatarInfo(WPARAM wParam, LPARAM lParam)
-{
- if (!lParam)
- return GAIR_NOAVATAR;
-
- PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam;
- if (GetDbAvatarInfo(*pai, nullptr)) {
- bool fileExist = _waccess(pai->filename, 0) == 0;
-
- bool needLoad;
- if (pai->hContact)
- needLoad = (wParam & GAIF_FORCE) && (!fileExist || db_get_b(pai->hContact, "ContactPhoto", "NeedUpdate", 0));
- else
- needLoad = (wParam & GAIF_FORCE) || !fileExist;
-
- if (needLoad) {
- debugLogA("*** Starting avatar request thread for %s", _T2A(pai->filename));
- mir_cslock s(avatar_lock_);
-
- if (std::find(avatar_queue.begin(), avatar_queue.end(), pai->hContact) == avatar_queue.end()) {
- bool is_empty = avatar_queue.empty();
- avatar_queue.push_back(pai->hContact);
- if (is_empty)
- ForkThread(&FacebookProto::UpdateAvatarWorker, nullptr);
- }
- return GAIR_WAITFOR;
- }
- else if (fileExist)
- return GAIR_SUCCESS;
-
- }
- return GAIR_NOAVATAR;
-}
-
-INT_PTR FacebookProto::GetMyAvatar(WPARAM wParam, LPARAM lParam)
-{
- debugLogA("*** GetMyAvatar");
-
- if (!wParam || !lParam)
- return -3;
-
- wchar_t* buf = (wchar_t*)wParam;
- int size = (int)lParam;
-
- PROTO_AVATAR_INFORMATION ai = { 0 };
- switch (GetAvatarInfo(0, (LPARAM)&ai)) {
- case GAIR_SUCCESS:
- wcsncpy(buf, ai.filename, size);
- buf[size - 1] = 0;
- return 0;
-
- case GAIR_WAITFOR:
- return -1;
-
- default:
- return -2;
- }
-}
-*/ \ No newline at end of file
diff --git a/protocols/Facebook/src/server.cpp b/protocols/Facebook/src/server.cpp
index 257f4974d5..004633fc12 100644
--- a/protocols/Facebook/src/server.cpp
+++ b/protocols/Facebook/src/server.cpp
@@ -461,6 +461,70 @@ void FacebookProto::OnPublishPrivateMessage(const JSONNode &root)
std::string szBody(root["body"].as_string());
std::string szId(metadata["messageId"].as_string());
+ CMStringA stickerId = root["stickerId"].as_mstring();
+ if (!stickerId.IsEmpty()) {
+ if (ServiceExists(MS_SMILEYADD_LOADCONTACTSMILEYS)) {
+ CMStringW wszPath(FORMAT, L"%s\\%S\\Stickers", VARSW(L"%miranda_avatarcache%").get(), m_szModuleName);
+ CreateDirectoryTreeW(wszPath);
+
+ bool bSuccess = false;
+ CMStringW wszFileName(FORMAT, L"%s\\%S.png", wszPath.c_str(), stickerId.c_str());
+ if (GetFileAttributesW(wszFileName) == INVALID_FILE_ATTRIBUTES) {
+ auto *pReq = CreateRequestGQL(FB_API_QUERY_STICKER);
+ pReq << CHAR_PARAM("query_params", CMStringA(FORMAT, "{\"0\":[\"%s\"]}", stickerId.c_str()));
+ pReq->CalcSig();
+
+ JsonReply reply(ExecuteRequest(pReq));
+ if (!reply.error()) {
+ for (auto &sticker : reply.data()) {
+ for (auto &img : sticker["thread_image"]) {
+ CMStringA szUrl(img.as_mstring());
+
+ NETLIBHTTPREQUEST req = {};
+ req.cbSize = sizeof(req);
+ req.flags = NLHRF_NODUMP | NLHRF_SSL | NLHRF_HTTP11 | NLHRF_REDIRECT;
+ req.requestType = REQUEST_GET;
+ req.szUrl = szUrl.GetBuffer();
+
+ NETLIBHTTPREQUEST *pReply = Netlib_HttpTransaction(m_hNetlibUser, &req);
+ if (pReply != nullptr && pReply->resultCode == 200 && pReply->pData && pReply->dataLength) {
+ int iImageFormat = PA_FORMAT_UNKNOWN;
+ for (int i = 0; i < pReply->headersCount; i++)
+ if (!mir_strcmp(pReply->headers[i].szName, "Content-Type")) {
+ iImageFormat = ProtoGetAvatarFormatByMimeType(pReply->headers[i].szValue);
+ break;
+ }
+
+ if (iImageFormat != PA_FORMAT_UNKNOWN) {
+ bSuccess = true;
+ FILE *out = _wfopen(wszFileName, L"wb");
+ fwrite(pReply->pData, 1, pReply->dataLength, out);
+ fclose(out);
+ }
+ }
+ }
+ }
+ }
+ }
+ else bSuccess = true;
+
+ if (bSuccess) {
+ if (!szBody.empty())
+ szBody += "\r\n";
+ szBody += stickerId.c_str();
+
+ SMADD_CONT cont;
+ cont.cbSize = sizeof(SMADD_CONT);
+ cont.hContact = pUser->hContact;
+ cont.type = 1;
+ cont.path = wszFileName.GetBuffer();
+ CallService(MS_SMILEYADD_LOADCONTACTSMILEYS, 0, (LPARAM)&cont);
+ }
+ else szBody += TranslateU("Sticker received");
+ }
+ else szBody += TranslateU("SmileyAdd plugin required to support stickers");
+ }
+
PROTORECVEVENT pre = {};
pre.timestamp = DWORD(_wtoi64(metadata["timestamp"].as_mstring()) / 1000);
pre.szMessage = (char *)szBody.c_str();