diff options
| -rw-r--r-- | protocols/Weather/res/resource.rc | 14 | ||||
| -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 | ||||
| -rw-r--r-- | protocols/Weather/weather.vcxproj | 1 | ||||
| -rw-r--r-- | protocols/Weather/weather.vcxproj.filters | 3 |
12 files changed, 184 insertions, 34 deletions
diff --git a/protocols/Weather/res/resource.rc b/protocols/Weather/res/resource.rc index d8ce1f6f3c..e2c041ad3f 100644 --- a/protocols/Weather/res/resource.rc +++ b/protocols/Weather/res/resource.rc @@ -155,6 +155,16 @@ BEGIN CONTROL "Errors",IDC_W,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,82,18,54,9 END +IDD_ACCOUNT_OPT DIALOGEX 0, 0, 309, 233 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "Enter your personel API key from Visual Crossing Weather site",IDC_STATIC,8,7,294,8 + EDITTEXT IDC_KEY,8,19,294,14,ES_AUTOHSCROLL + PUSHBUTTON "Obtain key",IDC_OBTAIN,172,38,130,14 +END + IDD_TEXTOPT DIALOGEX 0, 0, 309, 233 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD EXSTYLE WS_EX_CONTROLPARENT @@ -257,6 +267,10 @@ BEGIN BOTTOMMARGIN, 233 END + IDD_ACCOUNT_OPT, DIALOG + BEGIN + END + IDD_TEXTOPT, DIALOG BEGIN BOTTOMMARGIN, 232 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); +} diff --git a/protocols/Weather/weather.vcxproj b/protocols/Weather/weather.vcxproj index 56a2b52edd..8b18056c59 100644 --- a/protocols/Weather/weather.vcxproj +++ b/protocols/Weather/weather.vcxproj @@ -41,6 +41,7 @@ <ClCompile Include="src\weather_svcs.cpp" /> <ClCompile Include="src\weather_update.cpp" /> <ClCompile Include="src\weather_userinfo.cpp" /> + <ClCompile Include="src\weather_utils.cpp" /> <ClInclude Include="src\proto.h" /> <ClInclude Include="src\resource.h" /> <ClInclude Include="src\stdafx.h" /> diff --git a/protocols/Weather/weather.vcxproj.filters b/protocols/Weather/weather.vcxproj.filters index 92a72a4653..50c35cce0e 100644 --- a/protocols/Weather/weather.vcxproj.filters +++ b/protocols/Weather/weather.vcxproj.filters @@ -41,6 +41,9 @@ <ClCompile Include="src\weather_proto.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="src\weather_utils.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="src\resource.h"> |
