summaryrefslogtreecommitdiff
path: root/protocols/Teams/src/teams_avatars.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Teams/src/teams_avatars.cpp')
-rw-r--r--protocols/Teams/src/teams_avatars.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/protocols/Teams/src/teams_avatars.cpp b/protocols/Teams/src/teams_avatars.cpp
new file mode 100644
index 0000000000..a535cab005
--- /dev/null
+++ b/protocols/Teams/src/teams_avatars.cpp
@@ -0,0 +1,218 @@
+/*
+Copyright (c) 2025 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+
+void CTeamsProto::GetAvatarFileName(MCONTACT hContact, wchar_t *pszDest, size_t cbLen)
+{
+ CMStringW wszPath(GetAvatarPath());
+ wszPath += '\\';
+
+ const wchar_t *szFileType = ProtoGetAvatarExtension(getByte(hContact, "AvatarType", PA_FORMAT_JPEG));
+ CMStringA username(getId(hContact));
+ username.Replace("live:", "__live_");
+ username.Replace("facebook:", "__facebook_");
+ wszPath.AppendFormat(L"%S%s", username.c_str(), szFileType);
+
+ wcsncpy_s(pszDest, cbLen, wszPath, _TRUNCATE);
+}
+
+void CTeamsProto::ReloadAvatarInfo(MCONTACT hContact)
+{
+ if (hContact == NULL) {
+ ReportSelfAvatarChanged();
+ return;
+ }
+
+ PROTO_AVATAR_INFORMATION ai = { 0 };
+ ai.hContact = hContact;
+ SvcGetAvatarInfo(0, (LPARAM)&ai);
+}
+
+void CTeamsProto::SetAvatarUrl(MCONTACT hContact, const CMStringW &tszUrl)
+{
+ ptrW oldUrl(getWStringA(hContact, "AvatarUrl"));
+ if (oldUrl != NULL)
+ if (tszUrl == oldUrl)
+ return;
+
+ if (tszUrl.IsEmpty()) {
+ delSetting(hContact, "AvatarUrl");
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, nullptr);
+ }
+ else {
+ setWString(hContact, "AvatarUrl", tszUrl);
+ setByte(hContact, "NeedNewAvatar", 1);
+
+ PROTO_AVATAR_INFORMATION ai = {};
+ ai.hContact = hContact;
+ GetAvatarFileName(ai.hContact, ai.filename, _countof(ai.filename));
+ ai.format = ProtoGetAvatarFormat(ai.filename);
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Avatar services for Miranda
+
+INT_PTR CTeamsProto::SvcGetAvatarCaps(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam) {
+ case AF_MAXSIZE:
+ ((POINT*)lParam)->x = 98;
+ ((POINT*)lParam)->y = 98;
+ break;
+
+ case AF_MAXFILESIZE:
+ return 32000;
+
+ case AF_PROPORTION:
+ return PIP_SQUARE;
+
+ case AF_FORMATSUPPORTED:
+ case AF_ENABLED:
+ case AF_DONTNEEDDELAYS:
+ case AF_FETCHIFPROTONOTVISIBLE:
+ case AF_FETCHIFCONTACTOFFLINE:
+ return 1;
+ }
+ return 0;
+}
+
+INT_PTR CTeamsProto::SvcGetAvatarInfo(WPARAM, LPARAM lParam)
+{
+ PROTO_AVATAR_INFORMATION *pai = (PROTO_AVATAR_INFORMATION *)lParam;
+
+ pai->format = getByte(pai->hContact, "AvatarType", PA_FORMAT_JPEG);
+
+ wchar_t tszFileName[MAX_PATH];
+ GetAvatarFileName(pai->hContact, tszFileName, _countof(tszFileName));
+ wcsncpy(pai->filename, tszFileName, _countof(pai->filename));
+
+ if (::_waccess(pai->filename, 0) == 0 && !getBool(pai->hContact, "NeedNewAvatar", 0))
+ return GAIR_SUCCESS;
+
+ if (IsOnline())
+ if (ReceiveAvatar(pai->hContact))
+ return GAIR_WAITFOR;
+
+ debugLogA("No avatar");
+ return GAIR_NOAVATAR;
+}
+
+INT_PTR CTeamsProto::SvcGetMyAvatar(WPARAM wParam, LPARAM lParam)
+{
+ wchar_t path[MAX_PATH];
+ GetAvatarFileName(NULL, path, _countof(path));
+ wcsncpy((wchar_t *)wParam, path, (int)lParam);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Avatars' receiving
+
+void CTeamsProto::OnReceiveAvatar(MHttpResponse *response, AsyncHttpRequest *pRequest)
+{
+ if (response == nullptr || response->body.IsEmpty())
+ return;
+
+ MCONTACT hContact = pRequest->hContact;
+ if (response->resultCode != 200)
+ return;
+
+ PROTO_AVATAR_INFORMATION ai = { 0 };
+ ai.format = ProtoGetBufferFormat(response->body);
+ setByte(hContact, "AvatarType", ai.format);
+ GetAvatarFileName(hContact, ai.filename, _countof(ai.filename));
+
+ FILE *out = _wfopen(ai.filename, L"wb");
+ if (out == nullptr) {
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, &ai, 0);
+ return;
+ }
+
+ fwrite(response->body, 1, response->body.GetLength(), out);
+ fclose(out);
+ setByte(hContact, "NeedNewAvatar", 0);
+ ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai, 0);
+}
+
+bool CTeamsProto::ReceiveAvatar(MCONTACT hContact)
+{
+ ptrA szUrl(getStringA(hContact, "AvatarUrl"));
+ if (!mir_strlen(szUrl))
+ return false;
+
+ auto *pReq = new AsyncHttpRequest(REQUEST_GET, HOST_OTHER, szUrl, &CTeamsProto::OnReceiveAvatar);
+ pReq->hContact = hContact;
+ pReq->flags |= NLHRF_REDIRECT;
+ PushRequest(pReq);
+
+ debugLogA("Requested to read an avatar from '%s'", szUrl.get());
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Setting my own avatar
+
+void CTeamsProto::OnSentAvatar(MHttpResponse *response, AsyncHttpRequest*)
+{
+ TeamsReply root(response);
+ if (root.error())
+ return;
+}
+
+INT_PTR CTeamsProto::SvcSetMyAvatar(WPARAM, LPARAM lParam)
+{
+ wchar_t *path = (wchar_t*)lParam;
+ wchar_t avatarPath[MAX_PATH];
+ GetAvatarFileName(NULL, avatarPath, _countof(avatarPath));
+ if (path != nullptr) {
+ if (CopyFile(path, avatarPath, FALSE)) {
+ FILE *hFile = _wfopen(path, L"rb");
+ if (hFile) {
+ fseek(hFile, 0, SEEK_END);
+ size_t length = ftell(hFile);
+ if (length != -1) {
+ rewind(hFile);
+
+ mir_ptr<uint8_t> data((uint8_t*)mir_alloc(length));
+
+ if (data != NULL && fread(data, sizeof(uint8_t), length, hFile) == length) {
+ const char *szMime = FreeImage_GetFIFMimeType(FreeImage_GetFIFFromFilenameU(path));
+
+ auto *pReq = new AsyncHttpRequest(REQUEST_PUT, HOST_API, 0, &CTeamsProto::OnSentAvatar);
+ pReq->m_szUrl.AppendFormat("/users/%s/profile/avatar", m_szSkypename.MakeLower().c_str());
+ pReq->AddHeader("Content-Type", szMime);
+ pReq->m_szParam.Truncate((int)length);
+ memcpy(pReq->m_szParam.GetBuffer(), data, (int)length);
+ PushRequest(pReq);
+
+ fclose(hFile);
+ return 0;
+ }
+ }
+ fclose(hFile);
+ }
+ }
+ return -1;
+ }
+ else if (IsFileExists(avatarPath))
+ DeleteFile(avatarPath);
+
+ return 0;
+}