summaryrefslogtreecommitdiff
path: root/protocols/Steam/src/steam_contacts.cpp
diff options
context:
space:
mode:
authoraunsane <aunsane@gmail.com>2018-01-14 22:02:44 +0300
committeraunsane <aunsane@gmail.com>2018-01-14 22:03:16 +0300
commit7cb1539b0dbcf585472dd2341129adf174bb0bb5 (patch)
tree6879adfdd3ebf5f64557525df118e0753969fd95 /protocols/Steam/src/steam_contacts.cpp
parenta6b0d0df4854ffda2577e2b61844467253eb9e0f (diff)
Steam: refactoring pt.2
Diffstat (limited to 'protocols/Steam/src/steam_contacts.cpp')
-rw-r--r--protocols/Steam/src/steam_contacts.cpp573
1 files changed, 294 insertions, 279 deletions
diff --git a/protocols/Steam/src/steam_contacts.cpp b/protocols/Steam/src/steam_contacts.cpp
index 98f06662de..894853f46b 100644
--- a/protocols/Steam/src/steam_contacts.cpp
+++ b/protocols/Steam/src/steam_contacts.cpp
@@ -2,6 +2,9 @@
void CSteamProto::SetContactStatus(MCONTACT hContact, WORD status)
{
+ if (!hContact)
+ return;
+
WORD oldStatus = getWord(hContact, "Status", ID_STATUS_OFFLINE);
if (oldStatus != status)
{
@@ -11,19 +14,13 @@ void CSteamProto::SetContactStatus(MCONTACT hContact, WORD status)
switch (status)
{
case ID_STATUS_FREECHAT:
- {
- // Contact is looking to play, save it to as status message
- if (hContact)
- db_set_ws(hContact, "CList", "StatusMsg", TranslateT("Looking to play"));
- }
+ // Contact is looking to play, save it to as status message
+ db_set_ws(hContact, "CList", "StatusMsg", TranslateT("Looking to play"));
break;
case ID_STATUS_OUTTOLUNCH:
- {
- // Contact is looking to trade, save it to as status message
- if (hContact)
- db_set_ws(hContact, "CList", "StatusMsg", TranslateT("Looking to trade"));
- }
+ // Contact is looking to trade, save it to as status message
+ db_set_ws(hContact, "CList", "StatusMsg", TranslateT("Looking to trade"));
break;
case ID_STATUS_OFFLINE:
@@ -33,16 +30,12 @@ void CSteamProto::SetContactStatus(MCONTACT hContact, WORD status)
delSetting(hContact, "XStatusName");
delSetting(hContact, "XStatusMsg");
- if (hContact)
- SetContactExtraIcon(hContact, NULL);
+ SetContactExtraIcon(hContact, NULL);
}
// no break intentionally
default:
- {
- if (hContact)
- db_unset(hContact, "CList", "StatusMsg");
- }
+ db_unset(hContact, "CList", "StatusMsg");
break;
}
}
@@ -67,20 +60,14 @@ MCONTACT CSteamProto::GetContactFromAuthEvent(MEVENT hEvent)
return DbGetAuthEventContact(&dbei);
}
-MCONTACT CSteamProto::FindContact(const char *steamId)
+MCONTACT CSteamProto::GetContact(const char *steamId)
{
- MCONTACT hContact = NULL;
-
- mir_cslock lck(this->contact_search_lock);
-
- for (hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName))
- {
- ptrA cSteamId(db_get_sa(hContact, this->m_szModuleName, "SteamID"));
- if (!lstrcmpA(cSteamId, steamId))
- break;
+ for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
+ ptrA cSteamId(getStringA(hContact, "SteamID"));
+ if (!mir_strcmp(cSteamId, steamId))
+ return hContact;
}
-
- return hContact;
+ return NULL;
}
void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
@@ -97,26 +84,21 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
// set name
JSONNode node = data["realname"];
- if (!node.isnull())
- {
+ if (!node.isnull()) {
CMStringW realName = node.as_mstring();
- if (!realName.IsEmpty())
- {
+ if (!realName.IsEmpty()) {
int pos = realName.Find(L' ', 1);
- if (pos != -1)
- {
+ if (pos != -1) {
setWString(hContact, "FirstName", realName.Mid(0, pos));
setWString(hContact, "LastName", realName.Mid(pos + 1));
}
- else
- {
+ else {
setWString(hContact, "FirstName", realName);
delSetting(hContact, "LastName");
}
}
}
- else
- {
+ else {
delSetting(hContact, "FirstName");
delSetting(hContact, "LastName");
}
@@ -128,8 +110,7 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
// set country
node = data["loccountrycode"];
- if (!node.isnull())
- {
+ if (!node.isnull()) {
json_string countryCode = node.as_string();
char *country = (char *)CallService(MS_UTILS_GETCOUNTRYBYISOCODE, (WPARAM)countryCode.c_str(), 0);
setString(hContact, "Country", country);
@@ -138,17 +119,25 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
delSetting(hContact, "Country");
// state code
- node = data["locstatecode"];
- if (!node.isnull())
- setDword(hContact, "StateCode", node.as_int());
- else
+ // note: it seems that steam sends "incorrect" state code
+ //node = data["locstatecode"];
+ //if (!node.isnull())
+ //{
+ // json_string stateCode = node.as_string();
+ // setString(hContact, "State", stateCode.c_str());
+ //}
+ //else
+ //{
+ // delSetting(hContact, "State");
delSetting(hContact, "StateCode");
+ //}
// city id
- node = data["loccityid"];
- if (!node.isnull())
- setDword(hContact, "CityID", node.as_int());
- else
+ // note: steam no longer sends state city id
+ //node = data["loccityid"];
+ //if (!node.isnull())
+ // setDword(hContact, "CityID", node.as_int());
+ //else
delSetting(hContact, "CityID");
// account created
@@ -160,34 +149,38 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
setDword(hContact, "LogoffTS", node.as_int());
// status
- // NOTE: this here is wrong info, probably depending on publicity of steam profile, but we don't need this at all, we get status updates by polling
- /*node = json_get(data, "personastate");
- status = SteamToMirandaStatus(json_as_int(node));
- SetContactStatus(hContact, status);
- */
+ node = data["lastlogoff"];
+ // note: this here is often wrong info, probably depending on publicity of steam profile
+ // but sometimes polling does not get status at all
+ WORD oldStatus = getWord(hContact, "Status", ID_STATUS_OFFLINE);
+ // so, set status only if contact offline
+ if (oldStatus == ID_STATUS_OFFLINE) {
+ WORD status = SteamToMirandaStatus((PersonaState)node.as_int());
+ SetContactStatus(hContact, status);
+ }
// client
node = data["personastateflags"];
- int stateflags = !node.isnull() ? node.as_int() : -1;
+ long stateflags = !node.isnull() ? node.as_int() : -1;
if (stateflags == 0) {
// nothing special, either standard client or in different status (only online, I want to play, I want to trade statuses support this flags)
WORD status = getWord(hContact, "Status", ID_STATUS_OFFLINE);
if (status == ID_STATUS_ONLINE || status == ID_STATUS_OUTTOLUNCH || status == ID_STATUS_FREECHAT)
setWString(hContact, "MirVer", L"Steam");
}
- else if (stateflags & 2) {
+ else if (stateflags & PersonaStateFlag::InJoinableGame) {
// game
setWString(hContact, "MirVer", L"Steam (in game)");
}
- else if (stateflags & 256) {
+ else if (stateflags & PersonaStateFlag::OnlineUsingWeb) {
// on website
setWString(hContact, "MirVer", L"Steam (website)");
}
- else if (stateflags & 512) {
+ else if (stateflags & PersonaStateFlag::OnlineUsingMobile) {
// on mobile
setWString(hContact, "MirVer", L"Steam (mobile)");
}
- else if (stateflags & 1024) {
+ else if (stateflags & PersonaStateFlag::OnlineUsingBigPicture) {
// big picture mode
setWString(hContact, "MirVer", L"Steam (Big Picture)");
}
@@ -199,8 +192,7 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
// playing game
json_string appId = data["gameid"].as_string();
CMStringW gameInfo = data["gameextrainfo"].as_mstring();
- if (!appId.empty() || !gameInfo.IsEmpty())
- {
+ if (!appId.empty() || !gameInfo.IsEmpty()) {
DWORD gameId = atol(appId.c_str());
json_string serverIP = data["gameserverip"].as_string();
json_string serverID = data["gameserversteamid"].as_string();
@@ -210,16 +202,14 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
setString(hContact, "ServerID", serverID.c_str());
CMStringW message(gameInfo);
- if (gameId && message.IsEmpty())
- {
+ if (gameId && message.IsEmpty()) {
ptrA token(getStringA("TokenSecret"));
PushRequest(
new GetAppInfoRequest(token, appId.c_str()),
&CSteamProto::OnGotAppInfo,
(void*)hContact);
}
- else
- {
+ else {
if (!gameId)
message.Append(TranslateT(" (Non-Steam)"));
if (!serverIP.empty())
@@ -232,8 +222,7 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
SetContactExtraIcon(hContact, gameId);
}
- else
- {
+ else {
delSetting(hContact, "GameID");
delSetting(hContact, "ServerIP");
delSetting(hContact, "ServerID");
@@ -246,136 +235,125 @@ void CSteamProto::UpdateContactDetails(MCONTACT hContact, const JSONNode &data)
}
}
-void CSteamProto::ContactIsRemoved(MCONTACT hContact)
+void CSteamProto::ContactIsFriend(MCONTACT hContact)
{
delSetting(hContact, "AuthAsked");
+ delSetting(hContact, "Auth");
+ delSetting(hContact, "Grant");
+ db_unset(hContact, "CList", "NotOnList");
- // If this contact was authorized and now is not (and isn't filled time of deletion), notify it
- if (!getDword(hContact, "DeletedTS", 0) && getByte(hContact, "Auth", 0) == 0)
- {
- setDword(hContact, "DeletedTS", ::time(nullptr));
+ // Check if this contact was removed someday and if so, notify he's back
+ if (getDword(hContact, "DeletedTS", 0) && !getByte(hContact, "Auth", 0)) {
+ delSetting(hContact, "DeletedTS");
ptrW nick(getWStringA(hContact, "Nick"));
wchar_t message[MAX_PATH];
- mir_snwprintf(message, MAX_PATH, TranslateT("%s has been removed from your contact list"), nick);
+ mir_snwprintf(message, MAX_PATH, TranslateT("%s is back in your contact list"), nick);
- ShowNotification(L"Steam", message);
+ ShowNotification(message);
}
+}
- if (getByte(hContact, "Auth", 0) != 1)
- {
- setByte(hContact, "Auth", 1);
- }
+void CSteamProto::ContactIsBlocked(MCONTACT hContact)
+{
+ // todo
+ setByte(hContact, "Block", 1);
+}
- SetContactStatus(hContact, ID_STATUS_OFFLINE);
+void CSteamProto::ContactIsUnblocked(MCONTACT hContact)
+{
+ delSetting(hContact, "Block");
}
-void CSteamProto::ContactIsFriend(MCONTACT hContact)
+void CSteamProto::ContactIsRemoved(MCONTACT hContact)
{
delSetting(hContact, "AuthAsked");
- // Check if this contact was removed someday and if so, notify he's back
- if (getDword(hContact, "DeletedTS", 0) && getByte(hContact, "Auth", 0) != 0)
- {
- delSetting(hContact, "DeletedTS");
+ // If this contact was authorized and now is not (and isn't filled time of deletion), notify it
+ if (!getDword(hContact, "DeletedTS", 0) && !getByte(hContact, "Auth", 0)) {
+ setDword(hContact, "DeletedTS", now());
ptrW nick(getWStringA(hContact, "Nick"));
wchar_t message[MAX_PATH];
- mir_snwprintf(message, MAX_PATH, TranslateT("%s is back in your contact list"), nick);
-
- ShowNotification(L"Steam", message);
- }
+ mir_snwprintf(message, MAX_PATH, TranslateT("%s has been removed from your contact list"), nick);
- if (getByte(hContact, "Auth", 0) != 0 || getByte(hContact, "Grant", 0) != 0)
- {
- delSetting(hContact, "Auth");
- delSetting(hContact, "Grant");
+ ShowNotification(message);
}
-}
-void CSteamProto::ContactIsIgnored(MCONTACT hContact)
-{
- // todo
- setByte(hContact, "Block", 1);
+ setByte(hContact, "Auth", 1);
+ SetContactStatus(hContact, ID_STATUS_OFFLINE);
}
void CSteamProto::ContactIsAskingAuth(MCONTACT hContact)
{
- if (getByte(hContact, "AuthAsked", 0) != 0) {
+ //if (getByte(hContact, "AuthAsked", 0))
// auth request was already showed, do nothing here
- return;
- }
+ //return;
- if (getByte(hContact, "Auth", 0) == 0) {
+ /*if (getByte(hContact, "Auth", 0) == 0) {
// user was just added or he already has authorization, but because we've just got auth request, he was probably deleted and requested again
ContactIsRemoved(hContact);
- }
+ }*/
// create auth request event
ptrA steamId(getStringA(hContact, "SteamID"));
ptrA nickName(getStringA(hContact, "Nick"));
+ if (nickName == nullptr)
+ nickName = mir_strdup(steamId);
ptrA firstName(getStringA(hContact, "FirstName"));
- if (firstName == NULL)
+ if (firstName == nullptr)
firstName = mir_strdup("");
ptrA lastName(getStringA(hContact, "LastName"));
- if (lastName == NULL)
+ if (lastName == nullptr)
lastName = mir_strdup("");
char reason[MAX_PATH];
- mir_snprintf(reason, Translate("%s has added you to his or her Friend List"), nickName);
+ mir_snprintf(reason, Translate("%s has added you to contact list"), nickName);
DB_AUTH_BLOB blob(hContact, nickName, firstName, lastName, steamId, reason);
PROTORECVEVENT recv = { 0 };
- recv.timestamp = time(nullptr);
+ recv.timestamp = now();
recv.szMessage = blob;
recv.lParam = blob.size();
ProtoChainRecv(hContact, PSR_AUTH, 0, (LPARAM)&recv);
-
- // remember to not create this event again, unless authorization status changes again
- setByte(hContact, "AuthAsked", 1);
}
-MCONTACT CSteamProto::AddContact(const char *steamId, bool isTemporary)
+MCONTACT CSteamProto::AddContact(const char *steamId, const wchar_t *nick, bool isTemporary)
{
- MCONTACT hContact = NULL;
-
- mir_cslock lck(this->contact_search_lock);
+ mir_cslock lock(m_addContactLock);
- for (hContact = db_find_first(this->m_szModuleName); hContact; hContact = db_find_next(hContact, this->m_szModuleName))
- {
- ptrA cSteamId(db_get_sa(hContact, this->m_szModuleName, "SteamID"));
- if (!lstrcmpA(cSteamId, steamId))
- break;
+ if (!steamId || !mir_strlen(steamId)) {
+ debugLogA(__FUNCTION__ ": empty steam id");
+ return NULL;
}
- if (!hContact)
- {
- // create contact
- hContact = db_add_contact();
- Proto_AddToContact(hContact, this->m_szModuleName);
+ MCONTACT hContact = GetContact(steamId);
+ if (hContact)
+ return hContact;
- setString(hContact, "SteamID", steamId);
+ // create contact
+ hContact = db_add_contact();
+ Proto_AddToContact(hContact, m_szModuleName);
- // update info
- //UpdateContact(hContact, contact);
+ setString(hContact, "SteamID", steamId);
+ if (mir_wstrlen(nick)) {
+ setWString(hContact, "Nick", nick);
+ db_set_ws(hContact, "CList", "MyHandle", nick);
+ }
- if (isTemporary)
- {
- setByte(hContact, "Auth", 1);
- //setByte(hContact, "Grant", 1);
- db_set_b(hContact, "CList", "NotOnList", 1);
- }
+ // update info
+ //UpdateContact(hContact, contact);
- // move to default group
- DBVARIANT dbv;
- if (!getWString("DefaultGroup", &dbv))
- {
- if(Clist_GroupExists(dbv.ptszVal))
- db_set_ws(hContact, "CList", "Group", dbv.ptszVal);
- db_free(&dbv);
- }
- }
+ if (isTemporary)
+ db_set_b(hContact, "CList", "NotOnList", 1);
+
+ setByte(hContact, "Auth", 1);
+ //setByte(hContact, "Grant", 1);
+
+ // move to default group
+ if (m_defaultGroup)
+ db_set_ws(hContact, "CList", "Group", m_defaultGroup);
return hContact;
}
@@ -391,11 +369,11 @@ void CSteamProto::UpdateContactRelationship(MCONTACT hContact, const JSONNode &d
return;
json_string relationship = node.as_string();
- if (!lstrcmpiA(relationship.c_str(), "friend"))
+ if (!mir_strcmp(relationship.c_str(), "friend"))
ContactIsFriend(hContact);
- else if (!lstrcmpiA(relationship.c_str(), "ignoredfriend"))
- ContactIsIgnored(hContact);
- else if (!lstrcmpiA(relationship.c_str(), "requestrecipient"))
+ else if (!mir_strcmp(relationship.c_str(), "ignoredfriend"))
+ ContactIsBlocked(hContact);
+ else if (!mir_strcmp(relationship.c_str(), "requestrecipient"))
ContactIsAskingAuth(hContact);
}
@@ -404,8 +382,7 @@ void CSteamProto::OnGotAppInfo(const JSONNode &root, void *arg)
MCONTACT hContact = (UINT_PTR)arg;
JSONNode apps = root["apps"].as_array();
- for (const JSONNode &app : apps)
- {
+ for (const JSONNode &app : apps) {
DWORD gameId = app["appid"].as_int();
CMStringW message = app["name"].as_mstring();
@@ -424,67 +401,69 @@ void CSteamProto::OnGotFriendList(const JSONNode &root, void*)
std::string steamIds = (char*)ptrA(getStringA("SteamID"));
// Remember contacts on server
- std::map<json_string, JSONNode*> friendsMap;
+ std::map<json_string, JSONNode*> friendsMap;
JSONNode friends = root["friends"].as_array();
- for (const JSONNode &_friend : friends)
- {
+ for (const JSONNode &_friend : friends) {
json_string steamId = _friend["steamid"].as_string();
friendsMap.insert(std::make_pair(steamId, json_copy(&_friend)));
}
- { // Check and update contacts in database
- mir_cslock lck(this->contact_search_lock);
-
- for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName))
- {
- ptrA steamId(getStringA(hContact, "SteamID"));
- if (steamId == nullptr)
- continue;
+ // Check and update contacts in database
+ for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) {
+ ptrA steamId(getStringA(hContact, "SteamID"));
+ if (steamId == nullptr)
+ continue;
- auto it = friendsMap.find((char*)steamId);
- if (it != friendsMap.end())
- {
- // Contact is on server-list, update (and eventually notify) it
- UpdateContactRelationship(hContact, *it->second);
- steamIds.append(",").append(it->first);
- json_delete(it->second);
- friendsMap.erase(it);
- }
- else
- {
- // Contact was removed from server-list, notify it
- ContactIsRemoved(hContact);
- }
+ auto it = friendsMap.find((char*)steamId);
+ if (it == friendsMap.end()) {
+ // Contact was removed from server-list, notify it
+ ContactIsRemoved(hContact);
+ continue;
}
+
+ JSONNode _friend = *it->second;
+
+ // Contact is on server-list, update (and eventually notify) it
+ UpdateContactRelationship(hContact, _friend);
+
+ // Do not update summary for non friends
+ json_string relationship = _friend["relationship"].as_string();
+ if (relationship == "friend")
+ steamIds.append(",").append(it->first);
+
+ json_delete(it->second);
+ friendsMap.erase(it);
}
// Check remaining contacts in map and add them to contact list
- for (auto it : friendsMap)
- {
+ for (auto it : friendsMap) {
// Contact is on server-list, but not in database, add (but not notify) it
- MCONTACT hContact = AddContact(it.first.c_str());
- UpdateContactRelationship(hContact, *it.second);
-
- steamIds.append(",").append(it.first);
+ JSONNode _friend = *it.second;
+
+ json_string relationship = _friend["relationship"].as_string();
+
+ MCONTACT hContact = AddContact(it.first.c_str(), nullptr, relationship != "friend");
+ UpdateContactRelationship(hContact, _friend);
+
+ if (relationship == "friend")
+ steamIds.append(",").append(it.first);
+
json_delete(it.second);
}
friendsMap.clear();
- // We need to delete nroot here at the end, because we had references to JSONNode objects stored in friends map
- // json_delete(nroot);
-
ptrA token(getStringA("TokenSecret"));
if (!steamIds.empty())
{
- //steamIds.pop_back();
+ steamIds.pop_back();
PushRequest(
new GetUserSummariesRequest(token, steamIds.c_str()),
&CSteamProto::OnGotUserSummaries);
}
- // Download last messages
+ // Load last conversations
PushRequest(
new GetConversationsRequest(token),
&CSteamProto::OnGotConversations);
@@ -501,11 +480,9 @@ void CSteamProto::OnGotBlockList(const JSONNode &root, void*)
if (friends.isnull())
return;
- for (size_t i = 0; i < friends.size(); i++)
+ for (const JSONNode &_friend: friends)
{
- JSONNode node = friends[i].as_node();
-
- json_string steamId = node["steamid"].as_string();
+ json_string steamId = _friend["steamid"].as_string();
/*MCONTACT hContact = FindContact(steamId);
if (!hContact)
@@ -514,8 +491,8 @@ void CSteamProto::OnGotBlockList(const JSONNode &root, void*)
steamIds.append(steamId).append(",");
}*/
- json_string relationship = node["relationship"].as_string();
- if (!lstrcmpiA(relationship.c_str(), "ignoredfriend"))
+ json_string relationship = _friend["relationship"].as_string();
+ if (!mir_strcmp(relationship.c_str(), "ignoredfriend"))
{
// todo: open block list
}
@@ -529,15 +506,12 @@ void CSteamProto::OnGotUserSummaries(const JSONNode &root, void*)
if (players.isnull())
return;
- for (size_t i = 0; i < players.size(); i++)
- {
- JSONNode player = players[i];
+ for (const JSONNode &player : players) {
json_string steamId = player["steamid"].as_string();
-
- MCONTACT hContact = NULL;
- if (!IsMe(steamId.c_str()))
- hContact = AddContact(steamId.c_str());
-
+ CMStringW nick = player["personaname"].as_mstring();
+ MCONTACT hContact = !IsMe(steamId.c_str())
+ ? hContact = AddContact(steamId.c_str(), nick)
+ : NULL;
UpdateContactDetails(hContact, player);
}
}
@@ -548,8 +522,7 @@ void CSteamProto::OnGotAvatar(const HttpResponse &response, void *arg)
ai.hContact = (UINT_PTR)arg;
GetDbAvatarInfo(ai);
- if (!response.IsSuccess())
- {
+ if (!response.IsSuccess()) {
ptrA steamId(getStringA(ai.hContact, "SteamID"));
debugLogA(__FUNCTION__ ": failed to get avatar %s", steamId);
@@ -558,11 +531,10 @@ void CSteamProto::OnGotAvatar(const HttpResponse &response, void *arg)
return;
}
- FILE *fp = _wfopen(ai.filename, L"wb");
- if (fp)
- {
- fwrite(response.Content, sizeof(char), response.Content.GetSize(), fp);
- fclose(fp);
+ FILE *file = _wfopen(ai.filename, L"wb");
+ if (file) {
+ fwrite(response.Content, sizeof(char), response.Content.GetSize(), file);
+ fclose(file);
if (ai.hContact)
ProtoBroadcastAck(ai.hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&ai, 0);
@@ -575,21 +547,63 @@ void CSteamProto::OnFriendAdded(const HttpResponse &response, void *arg)
{
SendAuthParam *param = (SendAuthParam*)arg;
- if (!response.IsSuccess() || lstrcmpiA(response.Content, "true"))
- {
- ptrA steamId(getStringA(param->hContact, "SteamID"));
- debugLogA(__FUNCTION__ ": failed to add friend %s", steamId);
+ if (!response.IsSuccess() || mir_strcmp(response.Content, "true")) {
+
+ ptrW steamId(getWStringA(param->hContact, "SteamID"));
+ ptrW who(getWStringA(param->hContact, "Nick"));
+ if (!who)
+ who = mir_wstrdup(steamId);
- ProtoBroadcastAck(param->hContact, ACKTYPE_AUTHREQ, ACKRESULT_FAILED, param->hAuth, 0);
+ wchar_t message[MAX_PATH];
+ mir_snwprintf(message, L"Error adding friend %s", who);
+
+ JSONNode root = JSONNode::parse(response.Content);
+ if (root) {
+ int success = root["success"].as_int();
+ if (success == 1) {
+ JSONNode invited = root["invited"].as_array();
+ if (invited.empty()) {
+ JSONNode errors = root["failed_invites_result"].as_array();
+ if (!errors.empty()) {
+ int first = 0;
+ int errorCode = errors[first].as_int();
+ switch (errorCode)
+ {
+ case 11:
+ mir_snwprintf(message, L"All communication with %s is blocked. Communication is only possible if you have lifted the blocking. To do this, visit the user's Steam Community page.", who);
+ break;
+ case 15:
+ mir_snwprintf(message, L"Request to %s can not be sent. His/her friends list is full.", who);
+ break;
+ case 24:
+ mir_wstrcpy(message, L"Your account does not meet the requirements to use this feature. Visit Steam Support to get more information.");
+ break;
+ case 25:
+ mir_snwprintf(message, L"Request to %s can not be sent. Your friends list is full.", who);
+ break;
+ case 40:
+ mir_snwprintf(message, L"Error adding friend %s. The communication between you and the other Steam member is blocked.", who);
+ break;
+ case 84:
+ mir_wstrcpy(message, L"You've been sending too many invitations lately. Please try again in a day or two.");
+ break;
+ }
+ }
+ }
+ else {
+ ContactIsFriend(param->hContact);
+ ProtoBroadcastAck(param->hContact, ACKTYPE_AUTHREQ, ACKRESULT_SUCCESS, param->hAuth, 0);
+ return;
+ }
+ }
+ }
+ ShowNotification(message, MB_ICONERROR);
+ ProtoBroadcastAck(param->hContact, ACKTYPE_AUTHREQ, ACKRESULT_FAILED, param->hAuth, 0);
return;
}
- delSetting(param->hContact, "Auth");
- delSetting(param->hContact, "Grant");
- delSetting(param->hContact, "DeletedTS");
- db_unset(param->hContact, "CList", "NotOnList");
-
+ ContactIsFriend(param->hContact);
ProtoBroadcastAck(param->hContact, ACKTYPE_AUTHREQ, ACKRESULT_SUCCESS, param->hAuth, 0);
}
@@ -597,27 +611,42 @@ void CSteamProto::OnFriendBlocked(const HttpResponse &response, void *arg)
{
ptrA steamId((char*)arg);
- if (!response.IsSuccess() || lstrcmpiA(response.Content, "true"))
- {
- debugLogA(__FUNCTION__ ": failed to ignore friend %s", (char*)arg);
+ if (!response.IsSuccess() || mir_strcmp(response.Content, "true")) {
+ debugLogA(__FUNCTION__ ": failed to ignore friend %s", (char*)steamId);
return;
}
+
+ MCONTACT hContact = GetContact(steamId);
+ if (hContact)
+ ContactIsBlocked(hContact);
}
-void CSteamProto::OnFriendRemoved(const HttpResponse &response, void *arg)
+void CSteamProto::OnFriendUnblocked(const HttpResponse &response, void *arg)
{
- MCONTACT hContact = (UINT_PTR)arg;
+ ptrA steamId((char*)arg);
- if (!response.IsSuccess() || lstrcmpiA(response.Content, "true"))
- {
- ptrA who(getStringA(hContact, "SteamID"));
+ if (!response.IsSuccess() || mir_strcmp(response.Content, "true")) {
+ debugLogA(__FUNCTION__ ": failed to unignore friend %s", (char*)steamId);
+ return;
+ }
+
+ MCONTACT hContact = GetContact(steamId);
+ if (hContact)
+ ContactIsUnblocked(hContact);
+}
- debugLogA(__FUNCTION__ ": failed to remove friend %s", who);
+void CSteamProto::OnFriendRemoved(const HttpResponse &response, void *arg)
+{
+ ptrA steamId((char*)arg);
+
+ if (!response.IsSuccess() || mir_strcmp(response.Content, "true")) {
+ debugLogA(__FUNCTION__ ": failed to remove friend %s", (char*)steamId);
return;
}
- setByte(hContact, "Auth", 1);
- setDword(hContact, "DeletedTS", ::time(nullptr));
+ MCONTACT hContact = GetContact(steamId);
+ if (hContact)
+ ContactIsRemoved(hContact);
}
void CSteamProto::OnAuthRequested(const JSONNode &root, void*)
@@ -628,13 +657,14 @@ void CSteamProto::OnAuthRequested(const JSONNode &root, void*)
int first = 0;
JSONNode players = root["players"].as_array();
JSONNode player = players[first];
- if (!player.isnull())
- {
- json_string steamId = player["steamid"].as_string();
- MCONTACT hContact = AddContact(steamId.c_str());
- UpdateContactDetails(hContact, player);
- ContactIsAskingAuth(hContact);
- }
+ if (player.isnull())
+ return;
+
+ json_string steamId = player["steamid"].as_string();
+ CMStringW nick = player["personaname"].as_mstring();
+ MCONTACT hContact = AddContact(steamId.c_str(), nick);
+ UpdateContactDetails(hContact, player);
+ ContactIsAskingAuth(hContact);
}
void CSteamProto::OnPendingApproved(const JSONNode &root, void *arg)
@@ -645,8 +675,7 @@ void CSteamProto::OnPendingApproved(const JSONNode &root, void *arg)
return;
int success = root["success"].as_int();
- if (success == 0)
- {
+ if (success == 0) {
json_string error = root["error_text"].as_string();
debugLogA(__FUNCTION__ ": failed to approve pending from %s (%s)", steamId, ptrA(mir_utf8decodeA(error.c_str())));
}
@@ -660,8 +689,7 @@ void CSteamProto::OnPendingIgnoreded(const JSONNode &root, void *arg)
return;
int success = root["success"].as_int();
- if (success == 0)
- {
+ if (success == 0) {
json_string error = root["error_text"].as_string();
debugLogA(__FUNCTION__ ": failed to ignore pending from %s (%s)", steamId, ptrA(mir_utf8decodeA(error.c_str())));
}
@@ -671,54 +699,47 @@ void CSteamProto::OnSearchResults(const HttpResponse &response, void *arg)
{
HANDLE searchType = (HANDLE)arg;
- if (!response.IsSuccess())
- {
+ if (!response.IsSuccess()) {
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, searchType, 0);
debugLogA(__FUNCTION__ ": failed to get summaries");
return;
}
JSONNode root = JSONNode::parse(response.Content);
- if (root.isnull())
- {
+ if (root.isnull()) {
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, searchType, 0);
+ debugLogA(__FUNCTION__ ": no data");
return;
}
JSONNode players = root["players"].as_array();
- for (size_t i = 0; i < players.size(); i++)
- {
- JSONNode player = players[i];
-
+ for (const JSONNode &player : players) {
STEAM_SEARCH_RESULT ssr = { 0 };
- ssr.hdr.cbSize = sizeof(STEAM_SEARCH_RESULT);
- ssr.hdr.flags = PSR_UNICODE;
+ ssr.psr.cbSize = sizeof(STEAM_SEARCH_RESULT);
+ ssr.psr.flags = PSR_UNICODE;
CMStringW steamId = player["steamid"].as_mstring();
- ssr.hdr.id.w = steamId.Detach();
+ ssr.psr.id.w = steamId.Detach();
CMStringW nick = player["personaname"].as_mstring();
- ssr.hdr.nick.w = nick.Detach();
+ ssr.psr.nick.w = nick.Detach();
JSONNode node = player["realname"];
- if (!node.isnull())
- {
+ if (!node.isnull()) {
CMStringW realName = node.as_mstring();
- if (!realName.IsEmpty())
- {
+ if (!realName.IsEmpty()) {
int pos = realName.Find(' ', 1);
- if (pos != -1)
- {
- ssr.hdr.firstName.w = realName.Mid(0, pos).Detach();
- ssr.hdr.lastName.w = realName.Mid(pos + 1).Detach();
+ if (pos != -1) {
+ ssr.psr.firstName.w = realName.Mid(0, pos).Detach();
+ ssr.psr.lastName.w = realName.Mid(pos + 1).Detach();
}
else
- ssr.hdr.firstName.w = realName.Detach();
+ ssr.psr.firstName.w = realName.Detach();
}
}
- //ssr.contact = contact;
- ssr.data = json_copy(&player); // FIXME: is this needed and safe (no memleak) to be here?
+ // todo: is this needed and safe (no memleak) to be here?
+ ssr.data = json_copy(&player);
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, searchType, (LPARAM)&ssr);
}
@@ -728,17 +749,16 @@ void CSteamProto::OnSearchResults(const HttpResponse &response, void *arg)
void CSteamProto::OnSearchByNameStarted(const HttpResponse &response, void *arg)
{
- if (!response.IsSuccess())
- {
+ if (!response.IsSuccess()) {
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE)arg, 0);
debugLogA(__FUNCTION__ ": failed to get results");
return;
}
JSONNode root = JSONNode::parse(response.Content);
- if (root.isnull())
- {
+ if (root.isnull()) {
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE)arg, 0);
+ debugLogA(__FUNCTION__ ": no data");
return;
}
@@ -749,27 +769,22 @@ void CSteamProto::OnSearchByNameStarted(const HttpResponse &response, void *arg)
std::string steamIds;
JSONNode results = root["results"].as_array();
- for (size_t i = 0; i < results.size(); i++)
- {
- JSONNode result = results[i];
+ for (const JSONNode &result : results) {
json_string steamId = result["steamid"].as_string();
steamIds.append(steamId).append(",");
}
- if (!steamIds.empty())
- {
- // remove trailing ","
- steamIds.pop_back();
-
- ptrA token(getStringA("TokenSecret"));
-
- PushRequest(
- new GetUserSummariesRequest(token, steamIds.c_str()),
- &CSteamProto::OnSearchResults,
- (HANDLE)arg);
- }
- else
- {
+ if (steamIds.empty()) {
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)arg, 0);
+ return;
}
+
+ // remove trailing ","
+ steamIds.pop_back();
+
+ ptrA token(getStringA("TokenSecret"));
+ PushRequest(
+ new GetUserSummariesRequest(token, steamIds.c_str()),
+ &CSteamProto::OnSearchResults,
+ (HANDLE)arg);
}