diff options
Diffstat (limited to 'protocols/Weather/src')
| -rw-r--r-- | protocols/Weather/src/proto.h | 11 | ||||
| -rw-r--r-- | protocols/Weather/src/resource.h | 6 | ||||
| -rw-r--r-- | protocols/Weather/src/stdafx.h | 18 | ||||
| -rw-r--r-- | protocols/Weather/src/weather_addstn.cpp | 42 | ||||
| -rw-r--r-- | protocols/Weather/src/weather_data.cpp | 41 | ||||
| -rw-r--r-- | protocols/Weather/src/weather_opt.cpp | 36 | ||||
| -rw-r--r-- | protocols/Weather/src/weather_proto.cpp | 5 | ||||
| -rw-r--r-- | protocols/Weather/src/weather_update.cpp | 2 | ||||
| -rw-r--r-- | protocols/Weather/src/weather_utils.cpp | 39 |
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); +} |
