summaryrefslogtreecommitdiff
path: root/protocols/Weather/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Weather/src')
-rw-r--r--protocols/Weather/src/proto.h11
-rw-r--r--protocols/Weather/src/resource.h6
-rw-r--r--protocols/Weather/src/stdafx.h18
-rw-r--r--protocols/Weather/src/weather_addstn.cpp42
-rw-r--r--protocols/Weather/src/weather_data.cpp41
-rw-r--r--protocols/Weather/src/weather_opt.cpp36
-rw-r--r--protocols/Weather/src/weather_proto.cpp5
-rw-r--r--protocols/Weather/src/weather_update.cpp2
-rw-r--r--protocols/Weather/src/weather_utils.cpp39
9 files changed, 166 insertions, 34 deletions
diff --git a/protocols/Weather/src/proto.h b/protocols/Weather/src/proto.h
index 271504f665..d78ba9e4be 100644
--- a/protocols/Weather/src/proto.h
+++ b/protocols/Weather/src/proto.h
@@ -77,10 +77,10 @@ struct MYOPTIONS
class CWeatherProto : public PROTO<CWeatherProto>
{
friend class CEditDlg;
- friend class COptionsDlg;
friend class CPopupOptsDlg;
friend class CBriefInfoDlg;
friend class COptionsTextDlg;
+ friend class CGeneralOptionsDlg;
friend class WeatherUserInfoDlg;
class CProtoImpl
@@ -144,6 +144,8 @@ class CWeatherProto : public PROTO<CWeatherProto>
void GetStationID(MCONTACT hContact, wchar_t *id, int idlen);
WEATHERINFO LoadWeatherInfo(MCONTACT hContact);
+ MHttpResponse* RunQuery(const wchar_t *id, int days);
+
// menu items
void InitMenuItems();
void UpdateMenu(BOOL State);
@@ -178,8 +180,8 @@ class CWeatherProto : public PROTO<CWeatherProto>
// search
bool CheckSearch();
- int IDSearch(wchar_t *id, const int searchId);
- int NameSearch(wchar_t *name, const int searchId);
+ int IDSearch(wchar_t *id, int searchId);
+ int NameSearch(wchar_t *name, int searchId);
void __cdecl NameSearchThread(void *);
void __cdecl BasicSearchThread(void *);
@@ -217,8 +219,9 @@ public:
~CWeatherProto();
MYOPTIONS opt;
- CMOption<bool> m_bPopups;
+ CMOption<bool> m_bPopups;
+ CMOption<wchar_t *> m_szApiKey;
INT_PTR __cdecl BriefInfo(WPARAM, LPARAM);
int MapCondToStatus(MCONTACT hContact);
diff --git a/protocols/Weather/src/resource.h b/protocols/Weather/src/resource.h
index 03253f80ee..856a55a702 100644
--- a/protocols/Weather/src/resource.h
+++ b/protocols/Weather/src/resource.h
@@ -9,6 +9,7 @@
#define IDD_POPUP 204
#define IDD_OPTIONS 205
#define IDI_LOG 206
+#define IDD_ACCOUNT_OPT 207
#define IDI_UPDATE2 208
#define IDI_READ 209
#define IDI_UPDATE 210
@@ -121,7 +122,10 @@
#define IDC_SEARCHCITY 2125
#define IDC_HEADERBAR 2126
#define IDC_E1 2128
+#define IDC_EDIT1 2128
+#define IDC_KEY 2128
#define IDC_E2 2129
+#define IDC_OBTAIN 2129
#define OIC_HAND 32513
#define OIC_QUES 32514
#define OIC_BANG 32515
@@ -146,7 +150,7 @@
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 226
#define _APS_NEXT_COMMAND_VALUE 40030
-#define _APS_NEXT_CONTROL_VALUE 2128
+#define _APS_NEXT_CONTROL_VALUE 2130
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/protocols/Weather/src/stdafx.h b/protocols/Weather/src/stdafx.h
index 583e564abc..098b92f7f8 100644
--- a/protocols/Weather/src/stdafx.h
+++ b/protocols/Weather/src/stdafx.h
@@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <m_history.h>
#include <m_icolib.h>
#include <m_ignore.h>
+#include <m_json.h>
#include <m_langpack.h>
#include <m_netlib.h>
#include <m_options.h>
@@ -178,3 +179,20 @@ const wchar_t *GetDefaultText(int c);
// function from multiwin module
void UpdateMwinData(MCONTACT hContact);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// utils
+
+class JsonReply
+{
+ JSONNode *m_root = nullptr;
+ int m_errorCode = 0;
+
+public:
+ JsonReply(MHttpResponse *);
+ ~JsonReply();
+
+ __forceinline int error() const { return m_errorCode; }
+ __forceinline JSONNode &data() const { return *m_root; }
+ __forceinline operator bool() const { return m_errorCode == 200; }
+};
diff --git a/protocols/Weather/src/weather_addstn.cpp b/protocols/Weather/src/weather_addstn.cpp
index 0ad5e1bbc8..1611179dfc 100644
--- a/protocols/Weather/src/weather_addstn.cpp
+++ b/protocols/Weather/src/weather_addstn.cpp
@@ -33,7 +33,7 @@ static wchar_t name1[256];
MCONTACT CWeatherProto::AddToList(int, PROTOSEARCHRESULT *psr)
{
- if (!psr || !psr->email.w)
+ if (!psr || !psr->id.w)
return 0;
// search for existing contact
@@ -41,7 +41,7 @@ MCONTACT CWeatherProto::AddToList(int, PROTOSEARCHRESULT *psr)
DBVARIANT dbv;
// check ID to see if the contact already exist in the database
if (!getWString(hContact, "ID", &dbv)) {
- if (!mir_wstrcmpi(psr->email.w, dbv.pwszVal)) {
+ if (!mir_wstrcmpi(psr->id.w, dbv.pwszVal)) {
// remove the flag for not on list and hidden, thus make the contact visible
// and add them on the list
if (!Contact::OnList(hContact)) {
@@ -65,13 +65,11 @@ MCONTACT CWeatherProto::AddToList(int, PROTOSEARCHRESULT *psr)
// suppress online notification for the new contact
Ignore_Ignore(hContact, IGNOREEVENT_USERONLINE);
- // set contact info and settings
- wchar_t svc[256];
- wcsncpy(svc, psr->email.w, _countof(svc)); svc[_countof(svc) - 1] = 0;
-
// write the other info and settings to the database
- setWString(hContact, "ID", psr->email.w);
+ setWString(hContact, "ID", psr->id.w);
setWString(hContact, "Nick", psr->nick.w);
+ if (psr->firstName.w)
+ setWString(hContact, "FirstName", psr->firstName.w);
setWord(hContact, "Status", ID_STATUS_OFFLINE);
AvatarDownloaded(hContact);
@@ -204,21 +202,35 @@ HANDLE CWeatherProto::SearchAdvanced(MWindow hwndOwner)
return (HANDLE)sttSearchId;
}
-int CWeatherProto::IDSearch(wchar_t *sID, const int searchId)
+int CWeatherProto::IDSearch(wchar_t *sID, int searchId)
{
- // return an empty contact on "#"
PROTOSEARCHRESULT psr = { sizeof(psr) };
psr.flags = PSR_UNICODE;
- psr.nick.w = TranslateT("<Enter station name here>"); // to be entered
- psr.firstName.w = L" ";
+ psr.email.w = L" ";
psr.lastName.w = L"";
- psr.email.w = TranslateT("<Enter station ID here>"); // to be entered
- ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+
+ JsonReply reply(RunQuery(sID, 0));
+ if (!reply) {
+ psr.nick.w = TranslateT("<Enter station name here>"); // to be entered
+ psr.firstName.w = TranslateT("<Enter station ID here>"); // to be entered
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+ }
+ else {
+ auto &data = reply.data();
+ CMStringW id(FORMAT, L"%lf, %lf", data["latitude"].as_float(), data["longitude"].as_float());
+ CMStringW address1 = data["address"].as_mstring();
+ CMStringW address2 = data["resolvedAddress"].as_mstring();
+
+ psr.id.w = id.GetBuffer();
+ psr.nick.w = address1.GetBuffer();
+ psr.firstName.w = address2.GetBuffer();
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)searchId, (LPARAM)&psr);
+ }
return 0;
}
-int CWeatherProto::NameSearch(wchar_t *name, const int searchId)
+int CWeatherProto::NameSearch(wchar_t *name, int searchId)
{
- return 0;
+ return IDSearch(name, searchId);
}
diff --git a/protocols/Weather/src/weather_data.cpp b/protocols/Weather/src/weather_data.cpp
index c926787c81..ce26c27475 100644
--- a/protocols/Weather/src/weather_data.cpp
+++ b/protocols/Weather/src/weather_data.cpp
@@ -346,21 +346,16 @@ void CWeatherProto::GetDataValue(WIDATAITEM *UpdateData, wchar_t *Data, wchar_t
}
/////////////////////////////////////////////////////////////////////////////////////////
-// get single setting that is found
-// szSetting = the setting name
-// lparam = the counter
+// remove or display the weather information for a contact
+// hContact - the contact in which the info is going to be removed
-int GetWeatherDataFromDB(const char *szSetting, void *lparam)
+static int GetWeatherDataFromDB(const char *szSetting, void *lparam)
{
LIST<char> *pList = (LIST<char>*)lparam;
pList->insert(mir_strdup(szSetting));
return 0;
}
-/////////////////////////////////////////////////////////////////////////////////////////
-// remove or display the weather information for a contact
-// hContact - the contact in which the info is going to be removed
-
void DBDataManage(MCONTACT hContact, uint16_t Mode, WPARAM wParam, LPARAM)
{
// get all the settings and store them in a temporary list
@@ -398,3 +393,33 @@ void DBDataManage(MCONTACT hContact, uint16_t Mode, WPARAM wParam, LPARAM)
mir_free(str);
}
}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// data query
+
+MHttpResponse* CWeatherProto::RunQuery(const wchar_t *id, int days)
+{
+ wchar_t *pKey = m_szApiKey;
+ if (!mir_wstrlen(pKey))
+ return nullptr;
+
+ auto *pReq = new MHttpRequest(REQUEST_GET);
+ pReq->flags = NLHRF_HTTP11 | NLHRF_DUMPASTEXT;
+ pReq->m_szUrl = "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/" + mir_urlEncode(T2Utf(id).get());
+
+ if (days) {
+ time_t today = time(0);
+ struct tm *p = localtime(&today);
+ pReq->m_szUrl.AppendFormat("%04d-%02d-%02d/", p->tm_year, p->tm_mon, p->tm_mday);
+
+ today += 86400 * 7; // add one week
+ p = localtime(&today);
+ pReq->m_szUrl.AppendFormat("%04d-%02d-%02d/", p->tm_year, p->tm_mon, p->tm_mday);
+ }
+
+ pReq << CHAR_PARAM("unitGroup", "metric") << WCHAR_PARAM("key", pKey) << CHAR_PARAM("contentType", "json");
+
+ auto *ret = Netlib_HttpTransaction(m_hNetlibUser, pReq);
+ delete pReq;
+ return ret;
+}
diff --git a/protocols/Weather/src/weather_opt.cpp b/protocols/Weather/src/weather_opt.cpp
index 4fa83b1ecc..7e5f1ff1bf 100644
--- a/protocols/Weather/src/weather_opt.cpp
+++ b/protocols/Weather/src/weather_opt.cpp
@@ -181,10 +181,10 @@ void CWeatherProto::SaveOptions(void)
/////////////////////////////////////////////////////////////////////////////////////////
// weather options
-class COptionsDlg : public CWeatherDlgBase
+class CGeneralOptionsDlg : public CWeatherDlgBase
{
public:
- COptionsDlg(CWeatherProto *ppro) :
+ CGeneralOptionsDlg(CWeatherProto *ppro) :
CWeatherDlgBase(ppro, IDD_OPTIONS)
{}
@@ -442,6 +442,31 @@ public:
};
/////////////////////////////////////////////////////////////////////////////////////////
+// account options dialog
+
+class CAccountOptionsDlg : public CWeatherDlgBase
+{
+ CCtrlEdit edtKey;
+ CCtrlButton btnObtain;
+
+public:
+ CAccountOptionsDlg(CWeatherProto *ppro) :
+ CWeatherDlgBase(ppro, IDD_ACCOUNT_OPT),
+ edtKey(this, IDC_KEY),
+ btnObtain(this, IDC_OBTAIN)
+ {
+ CreateLink(edtKey, m_proto->m_szApiKey);
+
+ btnObtain.OnClick = Callback(this, &CAccountOptionsDlg::onClick_Obtain);
+ }
+
+ void onClick_Obtain(CCtrlButton *)
+ {
+ Utils_OpenUrl("https://www.visualcrossing.com/account");
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
// register the weather option pages
int CWeatherProto::OptInit(WPARAM wParam, LPARAM)
@@ -452,8 +477,13 @@ int CWeatherProto::OptInit(WPARAM wParam, LPARAM)
odp.position = 95600;
odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE;
+ // account options
+ odp.pDialog = new CAccountOptionsDlg(this);
+ odp.szTab.w = LPGENW("Account");
+ g_plugin.addOptions(wParam, &odp);
+
// plugin options
- odp.pDialog = new COptionsDlg(this);
+ odp.pDialog = new CGeneralOptionsDlg(this);
odp.szTab.w = LPGENW("General");
g_plugin.addOptions(wParam, &odp);
diff --git a/protocols/Weather/src/weather_proto.cpp b/protocols/Weather/src/weather_proto.cpp
index 6adf31846c..6df768e7ac 100644
--- a/protocols/Weather/src/weather_proto.cpp
+++ b/protocols/Weather/src/weather_proto.cpp
@@ -20,7 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
CWeatherProto::CWeatherProto(const char *protoName, const wchar_t *userName) :
PROTO<CWeatherProto>(protoName, userName),
m_impl(*this),
- m_bPopups(m_szModuleName, "UsePopup", true)
+ m_bPopups(m_szModuleName, "UsePopup", true),
+ m_szApiKey(m_szModuleName, "ApiKey", L"")
{
m_hProtoIcon = g_plugin.getIconHandle(IDI_ICON);
@@ -128,7 +129,7 @@ INT_PTR CWeatherProto::GetCaps(int type, MCONTACT)
return PF4_AVATARS | PF4_NOCUSTOMAUTH | PF4_NOAUTHDENYREASON | PF4_FORCEAUTH;
case PFLAG_UNIQUEIDTEXT:
- return (INT_PTR)TranslateT("Station ID");
+ return (INT_PTR)TranslateT("Coordinates");
}
return 0;
}
diff --git a/protocols/Weather/src/weather_update.cpp b/protocols/Weather/src/weather_update.cpp
index d0bd575629..dfab7450eb 100644
--- a/protocols/Weather/src/weather_update.cpp
+++ b/protocols/Weather/src/weather_update.cpp
@@ -26,7 +26,7 @@ menu items).
#include "stdafx.h"
-//============ RETRIEVE NEW WEATHER ============
+/////////////////////////////////////////////////////////////////////////////////////////
// retrieve weather info and display / log them
// hContact = current contact
diff --git a/protocols/Weather/src/weather_utils.cpp b/protocols/Weather/src/weather_utils.cpp
new file mode 100644
index 0000000000..b37b6bbe9a
--- /dev/null
+++ b/protocols/Weather/src/weather_utils.cpp
@@ -0,0 +1,39 @@
+/*
+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"
+
+JsonReply::JsonReply(MHttpResponse *pReply)
+{
+ if (pReply == nullptr) {
+ m_errorCode = 500;
+ return;
+ }
+
+ m_errorCode = pReply->resultCode;
+
+ m_root = json_parse(pReply->body);
+ if (m_root == nullptr)
+ m_errorCode = 500;
+
+ delete pReply;
+}
+
+JsonReply::~JsonReply()
+{
+ json_delete(m_root);
+}