summaryrefslogtreecommitdiff
path: root/protocols/CurrencyRates/src/CurrencyRatesProviderCurrencyConverter.cpp
blob: 46924e4e6dafcb932bf7c80e2ee05d56afe0302a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "stdafx.h"

static CMStringW build_url(const CMStringW &rsURL, const CMStringW &from, const CMStringW &to)
{
	CMStringW res = rsURL + L"?q=" + from + L"_" + to + L"&compact=ultra";
	if (mir_wstrlen(g_plugin.wszApiKey))
		res.AppendFormat(L"&apiKey=%S", (wchar_t*)g_plugin.wszApiKey);
	return res;
}

static CMStringW build_url(MCONTACT hContact, const CMStringW &rsURL)
{
	CMStringW sFrom = g_plugin.getMStringW(hContact, DB_STR_FROM_ID);
	CMStringW sTo = g_plugin.getMStringW(hContact, DB_STR_TO_ID);
	return build_url(rsURL, sFrom, sTo);
}

static bool parse_response(const CMStringW &rsJSON, double &dRate)
{
	JSONNode root = JSONNode::parse(_T2A(rsJSON));
	if (!root)
		return false;

	dRate = root.at(json_index_t(0)).as_float();
	return true;
}

/////////////////////////////////////////////////////////////////////////////////////////
// CCurrencyRatesProviderCurrencyConverter implementation

struct CCurrencyRatesProviderCurrencyConverter : public CCurrencyRatesProviderBase
{
	CCurrencyRatesProviderCurrencyConverter()
	{}

	double Convert(double dAmount, const CCurrencyRate &from, const CCurrencyRate &to) const override
	{
		CMStringW sFullURL = build_url(GetURL(), from.GetID(), to.GetID());

		CHTTPSession http;
		if ((true == http.OpenURL(sFullURL))) {
			CMStringW sHTML;
			if ((true == http.ReadResponce(sHTML))) {
				double dResult = 0.0;
				if ((true == parse_response(sHTML, dResult)))
					return dResult * dAmount;

				throw std::runtime_error(Translate("Error occurred during HTML parsing."));
			}
			else throw std::runtime_error(Translate("Error occurred during site access."));
		}
		else throw std::runtime_error(Translate("Error occurred during site access."));

		return 0.0;
	}

private:
	void RefreshCurrencyRates(TContacts &anContacts) override
	{
		CHTTPSession http;
		CMStringW sURL = GetURL();

		for (TContacts::const_iterator i = anContacts.begin(); i != anContacts.end(); ++i) {
			MCONTACT hContact = *i;

			CMStringW sFullURL = build_url(hContact, sURL);
			if (true == http.OpenURL(sFullURL)) {
				CMStringW sHTML;
				if (true == http.ReadResponce(sHTML)) {
					double dRate = 0.0;
					if (true == parse_response(sHTML, dRate)) {
						WriteContactRate(hContact, dRate);
						continue;
					}
				}
			}

			SetContactStatus(hContact, ID_STATUS_NA);
		}
	}

	wchar_t *GetXmlFilename() const override
	{
		return L"CC.xml";
	}
};

/////////////////////////////////////////////////////////////////////////////////////////
// Module entry point

void InitCC()
{
	g_apProviders.push(new CCurrencyRatesProviderCurrencyConverter());
}