summaryrefslogtreecommitdiff
path: root/protocols/Steam/src/steam_bbcodes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Steam/src/steam_bbcodes.cpp')
-rw-r--r--protocols/Steam/src/steam_bbcodes.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/protocols/Steam/src/steam_bbcodes.cpp b/protocols/Steam/src/steam_bbcodes.cpp
new file mode 100644
index 0000000000..98c8d0c4b1
--- /dev/null
+++ b/protocols/Steam/src/steam_bbcodes.cpp
@@ -0,0 +1,166 @@
+/*
+Copyright (C) 2012-25 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 EncodeBbcodes(SESSION_INFO *si, CMStringW &wszText)
+{
+ int idx = wszText.Find(':');
+ if (idx != -1) {
+ CMStringW wszNick(wszText.Left(idx));
+ for (auto &it : si->getUserList()) {
+ if (wszNick == it->pszNick) {
+ wszText.Delete(0, idx + 1);
+
+ CMStringW wszReplace(FORMAT, L"[mention=%lld]@%s[/mention]", SteamIdToAccountId(_wtoi64(it->pszUID)), it->pszNick);
+ wszText = wszReplace + wszText;
+ break;
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct BBCode
+{
+ CMStringA szTag, szValue, szBody;
+ std::map<CMStringA, CMStringA> attrs;
+};
+
+static bool p2str(CMStringA &str, const char *&text, const char *subStr)
+{
+ if (auto *p = strpbrk(text, subStr)) {
+ str.Append(text, p - text);
+ text = p;
+ return true;
+ }
+
+ return false;
+}
+
+int parseBbcode(const char *p, BBCode &ret)
+{
+ auto *pSave = p;
+
+ while (isalpha(*p))
+ ret.szTag.AppendChar(*p++);
+
+ // [tag=value][/tag]
+ if (*p == '=') {
+ if (!p2str(ret.szValue, p, "]"))
+ return -1;
+ }
+ // [tag attr=value][/tag]
+ else if (*p == ' ') {
+ p++;
+ while (*p != ']') {
+ CMStringA szName, szValue;
+ if (!p2str(szName, p, "="))
+ return -1;
+
+ if (*++p == '\"') {
+ auto *p1 = strchr(++p, '\"');
+ if (p1 == nullptr)
+ return -1;
+
+ szValue.Append(p, p1 - p);
+ p = p1 + 1;
+ }
+ else {
+ if (!p2str(szValue, p, " ]"))
+ return -1;
+ }
+
+ ret.attrs[szName] = szValue;
+ if (*p == ' ')
+ p++;
+ }
+ }
+ // [tag][/tag]
+ else if (*p != ']')
+ return -1;
+
+ p++; // skip first ]
+
+ CMStringA szClose = "[/" + ret.szTag + "]";
+ auto *pEnd = strstr(p, szClose);
+ if (pEnd == nullptr)
+ return -1;
+
+ if (pEnd != p)
+ ret.szValue.Append(p, pEnd - p);
+
+ return pEnd + szClose.GetLength() - pSave;
+}
+
+void CSteamProto::DecodeBbcodes(SESSION_INFO *si, CMStringA &szText)
+{
+ for (int idx = szText.Find('['); idx != -1; idx = szText.Find('[', idx + 1)) {
+ BBCode code;
+ int iLength = parseBbcode(szText.c_str() + idx + 1, code) + 1;
+ if (iLength == 0)
+ continue;
+
+ bool bPlaceFirst = false;
+ CMStringA szReplace;
+ if (code.szTag == "emoticon")
+ szReplace.Format(":%s:", code.szValue.c_str());
+ else if (code.szTag == "sticker")
+ szReplace.Format(":%s:", code.attrs["type"].c_str());
+ else if (code.szTag == "mention") {
+ CMStringW wszId(FORMAT, L"%lld", AccountIdToSteamId(_atoi64(code.szValue)));
+ if (auto *pUser = g_chatApi.UM_FindUser(si, wszId)) {
+ szReplace.Format("%s:", T2Utf(pUser->pszNick).get());
+ bPlaceFirst = true;
+ }
+ }
+ else if (code.szTag == "lobbyinvite") {
+ szReplace = TranslateU("You were invited to play a game");
+ }
+ else if (code.szTag == "img") {
+ auto szUrl = code.attrs["src"];
+ if (szUrl.IsEmpty())
+ szUrl = code.attrs["thumbnail_src"];
+
+ if (!szUrl.IsEmpty())
+ szReplace = "[url]" + szUrl + "[/url]";
+
+ szUrl = code.attrs["associated_app"];
+ if (!szUrl.IsEmpty()) {
+ CMStringA szSetting = "AppInfo_" + szUrl;
+ ptrA szName(g_plugin.getUStringA(szSetting));
+ if (szName)
+ szReplace.AppendFormat("\r\n%s: %s", TranslateU("Associated application"), szName.get());
+ else
+ SendAppInfoRequest(atoi(szUrl));
+ }
+ }
+ else if (code.szTag == "spoiler") {
+ szReplace = code.szValue;
+ }
+ else continue;
+
+ szText.Delete(idx, iLength);
+ if (!szReplace.IsEmpty()) {
+ if (bPlaceFirst)
+ szText = szReplace + szText;
+ else
+ szText.Insert(idx, szReplace);
+ }
+ }
+}