[partners_api] cian api

This commit is contained in:
Arsentiy Milchakov 2017-07-11 11:28:41 +03:00 committed by Roman Kuznetsov
parent c3e46e0896
commit 0cfb088c53
10 changed files with 417 additions and 0 deletions

View file

@ -11,6 +11,8 @@ set(
banner.hpp
booking_api.cpp
booking_api.hpp
cian_api.cpp
cian_api.hpp
facebook_ads.cpp
facebook_ads.hpp
mopub_ads.cpp

133
partners_api/cian_api.cpp Normal file
View file

@ -0,0 +1,133 @@
#include "partners_api/cian_api.hpp"
#include "platform/http_client.hpp"
#include "platform/platform.hpp"
#include "geometry/rect2d.hpp"
#include "base/logging.hpp"
#include <utility>
#include "3party/jansson/myjansson.hpp"
using namespace platform;
namespace
{
bool RunSimpleHttpRequest(string const & url, string & result)
{
HttpClient request(url);
if (request.RunHttpRequest() && !request.WasRedirected() && request.ErrorCode() == 200)
{
result = request.ServerResponse();
return true;
}
return false;
}
void MakeResult(std::string const & src, std::vector<cian::RentPlace> & result)
{
my::Json root(src.c_str());
if (!json_is_object(root.get()))
MYTHROW(my::Json::Exception, ("The answer must contain a json object."));
json_t * clusters = json_object_get(root.get(), "clusters");
if (clusters == nullptr)
return;
size_t const clustersSize = json_array_size(clusters);
if (clustersSize == 0)
return;
for (size_t i = 0; i < clustersSize; ++i)
{
auto cluster = json_array_get(clusters, i);
cian::RentPlace place;
FromJSONObject(cluster, "lat", place.m_latlon.lat);
FromJSONObject(cluster, "lng", place.m_latlon.lon);
json_t * offers = json_object_get(cluster, "offers");
if (offers == nullptr)
return;
size_t const offersSize = json_array_size(offers);
if (offersSize == 0)
return;
for (size_t i = 0; i < offersSize; ++i)
{
auto offer = json_array_get(offers, i);
cian::RentOffer rentOffer;
FromJSONObject(offer, "flatType", rentOffer.m_flatType);
FromJSONObject(offer, "roomsCount", rentOffer.m_roomsCount);
FromJSONObject(offer, "priceRur", rentOffer.m_priceRur);
FromJSONObject(offer, "floorNumber", rentOffer.m_floorNumber);
FromJSONObject(offer, "floorsCount", rentOffer.m_floorsCount);
FromJSONObject(offer, "url", rentOffer.m_url);
FromJSONObject(offer, "address", rentOffer.m_address);
place.m_offers.push_back(std::move(rentOffer));
}
result.push_back(std::move(place));
}
}
} // namespace
namespace cian
{
// static
bool RawApi::GetRentNearby(m2::RectD const & rect, std::string & result,
std::string const & baseUrl /* = kBaseUrl */)
{
ostringstream url;
url << baseUrl << "/get-offers-in-bbox/?bbox=" << rect.minX() << ',' << rect.maxY() << '~'
<< rect.maxX() << ',' << rect.minY();
return RunSimpleHttpRequest(url.str(), result);
}
Api::Api(std::string const & baseUrl /* = kBaseUrl */) : m_baseUrl(baseUrl) {}
Api::~Api()
{
m_worker.Shutdown(base::WorkerThread::Exit::SkipPending);
}
uint64_t Api::GetRentNearby(m2::RectD const & rect, RentNearbyCallback const & cb)
{
auto const reqId = ++m_requestId;
auto const baseUrl = m_baseUrl;
m_worker.Push([reqId, rect, cb, baseUrl]() {
std::string rawResult;
std::vector<RentPlace> result;
if (!RawApi::GetRentNearby(rect, rawResult, baseUrl))
{
GetPlatform().RunOnGuiThread([cb, result, reqId]() { cb(result, reqId); });
return;
}
try
{
MakeResult(rawResult, result);
}
catch (my::Json::Exception const & e)
{
LOG(LERROR, (e.Msg()));
result.clear();
}
GetPlatform().RunOnGuiThread([cb, result, reqId]() { cb(result, reqId); });
});
return reqId;
}
} // namespace cian

57
partners_api/cian_api.hpp Normal file
View file

@ -0,0 +1,57 @@
#pragma once
#include "geometry/latlon.hpp"
#include "geometry/rect2d.hpp"
#include "base/worker_thread.hpp"
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
namespace cian
{
std::string const kBaseUrl = "https://api.cian.ru/rent-nearby/v1";
class RawApi
{
public:
static bool GetRentNearby(m2::RectD const & rect, std::string & result,
std::string const & url = kBaseUrl);
};
struct RentOffer
{
std::string m_flatType;
uint8_t m_roomsCount = 0;
uint32_t m_priceRur = 0;
uint8_t m_floorNumber = 0;
uint8_t m_floorsCount = 0;
std::string m_url;
std::string m_address;
};
struct RentPlace
{
ms::LatLon m_latlon;
std::vector<RentOffer> m_offers;
};
using RentNearbyCallback =
std::function<void(std::vector<RentPlace> const & places, uint64_t const requestId)>;
class Api
{
public:
explicit Api(std::string const & baseUrl = kBaseUrl);
virtual ~Api();
uint64_t GetRentNearby(m2::RectD const & rect, RentNearbyCallback const & cb);
private:
uint64_t m_requestId = 0;
std::string m_baseUrl;
base::WorkerThread m_worker;
};
} // namespace cian

View file

@ -12,6 +12,7 @@ SOURCES += \
ads_base.cpp \
ads_engine.cpp \
booking_api.cpp \
cian_api.cpp \
facebook_ads.cpp \
mopub_ads.cpp \
opentable_api.cpp \
@ -28,6 +29,7 @@ HEADERS += \
ads_engine.hpp \
banner.hpp \
booking_api.hpp \
cian_api.hpp \
facebook_ads.hpp \
mopub_ads.hpp \
opentable_api.hpp \

View file

@ -6,6 +6,7 @@ set(
SRC
ads_engine_tests.cpp
booking_tests.cpp
cian_tests.cpp
facebook_tests.cpp
mopub_tests.cpp
rb_tests.cpp

View file

@ -0,0 +1,38 @@
#include "testing/testing.hpp"
#include "partners_api/cian_api.hpp"
#include "3party/jansson/myjansson.hpp"
namespace
{
UNIT_TEST(Cian_GetRentNearbyRaw)
{
string result;
cian::RawApi::GetRentNearby({37.402891, 55.656318, 37.840971, 55.859980}, result);
TEST(!result.empty(), ());
my::Json root(result.c_str());
TEST(json_is_object(root.get()), ());
}
UNIT_TEST(Cian_GetRentNearby)
{
cian::Api api("http://localhost:34568/partners");
m2::RectD rect(37.501365, 55.805666, 37.509873, 55.809183);
std::vector<cian::RentPlace> result;
uint64_t reqId = 0;
reqId = api.GetRentNearby(rect, [&reqId, &result](std::vector<cian::RentPlace> const & places,
uint64_t const requestId) {
TEST_EQUAL(reqId, requestId, ());
result = places;
testing::StopEventLoop();
});
testing::RunEventLoop();
TEST(!result.empty(), ());
}
} // namespace

View file

@ -28,6 +28,7 @@ SOURCES += \
$$ROOT_DIR/testing/testingmain.cpp \
ads_engine_tests.cpp \
booking_tests.cpp \
cian_tests.cpp \
facebook_tests.cpp \
mopub_tests.cpp \
rb_tests.cpp \

View file

@ -144,6 +144,7 @@ class ResponseProvider:
"/booking/min_price": self.partners_minprice,
"/booking/min_price.getHotelAvailability": self.partners_minprice,
"/partners/taxi_info": self.partners_yandex_taxi_info,
"/partners/get-offers-in-bbox/": self.partners_rent_nearby,
}[url]()
except:
return self.test_404()
@ -225,6 +226,9 @@ class ResponseProvider:
def partners_yandex_taxi_info(self):
return Payload(jsons.PARTNERS_TAXI_INFO)
def partners_rent_nearby(self):
return Payload(jsons.PARTNERS_RENT_NEARBY)
def kill(self):
logging.debug("Kill called in ResponseProvider")
self.delegate.kill()

View file

@ -1,3 +1,5 @@
# coding=utf-8
PARTNERS_PRICE = """
{
"prices": [
@ -248,3 +250,168 @@ PARTNERS_TAXI_INFO = """
"time": 1057.7440430297368
}
"""
PARTNERS_RENT_NEARBY = """
{
"clusters": [
{
"lat": 55.80529,
"lng": 37.508274,
"offers": [
{
"flatType": "rooms",
"roomsCount": 2,
"priceRur": 50000,
"floorNumber": 8,
"floorsCount": 9,
"photosCount": 11,
"url": "https://cian.ru/rent/flat/159026341",
"address": "Ленинградский просп., 77К2"
},
{
"flatType": "rooms",
"roomsCount": 1,
"priceRur": 39999,
"floorNumber": 1,
"floorsCount": 12,
"photosCount": 13,
"url": "https://cian.ru/rent/flat/157827964",
"address": "Ленинградский просп., 77К2"
},
{
"flatType": "rooms",
"roomsCount": 2,
"priceRur": 58000,
"floorNumber": 6,
"floorsCount": 9,
"photosCount": 9,
"url": "https://cian.ru/rent/flat/159523671",
"address": "Ленинградский просп., 77К2"
}
],
"count": 3,
"url": "https://cian.ru/cat.php?deal_type=rent&offer_type=flat&engine_version=2&house%5B0%5D=26696"
},
{
"lat": 55.805776,
"lng": 37.50946,
"offers": [
{
"flatType": "rooms",
"roomsCount": 1,
"priceRur": 39000,
"floorNumber": 2,
"floorsCount": 9,
"photosCount": 9,
"url": "https://cian.ru/rent/flat/158786442",
"address": "Ленинградский просп., 77А"
}
],
"count": 1,
"url": "https://cian.ru/cat.php?deal_type=rent&offer_type=flat&engine_version=2&house%5B0%5D=2009028"
},
{
"lat": 55.808306,
"lng": 37.5008,
"offers": [
{
"flatType": "rooms",
"roomsCount": 2,
"priceRur": 50000,
"floorNumber": 6,
"floorsCount": 10,
"photosCount": 9,
"url": "https://cian.ru/rent/flat/155419837",
"address": "Волоколамское ш., 6"
}
],
"count": 1,
"url": "https://cian.ru/cat.php?deal_type=rent&offer_type=flat&engine_version=2&house%5B0%5D=1692086"
},
{
"lat": 55.805999,
"lng": 37.503738,
"offers": [
{
"flatType": "rooms",
"roomsCount": 2,
"priceRur": 70000,
"floorNumber": 4,
"floorsCount": 9,
"photosCount": 0,
"url": "https://cian.ru/rent/flat/159765700",
"address": "Волоколамское ш., 1кА"
}
],
"count": 1,
"url": "https://cian.ru/cat.php?deal_type=rent&offer_type=flat&engine_version=2&house%5B0%5D=1009214"
},
{
"lat": 55.805361,
"lng": 37.507124,
"offers": [
{
"flatType": "rooms",
"roomsCount": 1,
"priceRur": 45000,
"floorNumber": 1,
"floorsCount": 9,
"photosCount": 6,
"url": "https://cian.ru/rent/flat/158673214",
"address": "Ленинградский просп., 77К3"
},
{
"flatType": "rooms",
"roomsCount": 2,
"priceRur": 48000,
"floorNumber": 5,
"floorsCount": 9,
"photosCount": 15,
"url": "https://cian.ru/rent/flat/158613232",
"address": "Ленинградский просп., 77К3"
},
{
"flatType": "rooms",
"roomsCount": 1,
"priceRur": 45000,
"floorNumber": 1,
"floorsCount": 9,
"photosCount": 7,
"url": "https://cian.ru/rent/flat/159035369",
"address": "Ленинградский просп., 77К3"
}
],
"count": 3,
"url": "https://cian.ru/cat.php?deal_type=rent&offer_type=flat&engine_version=2&house%5B0%5D=26698"
},
{
"lat": 55.809226,
"lng": 37.504978,
"offers": [
{
"flatType": "rooms",
"roomsCount": 2,
"priceRur": 60000,
"floorNumber": 5,
"floorsCount": 8,
"photosCount": 37,
"url": "https://cian.ru/rent/flat/157212858",
"address": "Ленинградское ш., 3С1"
},
{
"flatType": "rooms",
"roomsCount": 2,
"priceRur": 35000,
"floorNumber": 6,
"floorsCount": 8,
"photosCount": 5,
"url": "https://cian.ru/rent/flat/158689565",
"address": "Ленинградское ш., 3С1"
}
],
"count": 2,
"url": "https://cian.ru/cat.php?deal_type=rent&offer_type=flat&engine_version=2&house%5B0%5D=583624"
}
]
}
"""

View file

@ -24,6 +24,9 @@
3D47B29B1F054C89000828D2 /* taxi_countries.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D47B2971F054C89000828D2 /* taxi_countries.cpp */; };
3D47B29C1F054C89000828D2 /* taxi_countries.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D47B2981F054C89000828D2 /* taxi_countries.hpp */; };
3D47B29D1F054C89000828D2 /* taxi_places.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D47B2991F054C89000828D2 /* taxi_places.hpp */; };
3D47B2AC1F14BE89000828D2 /* cian_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D47B2AA1F14BE89000828D2 /* cian_api.cpp */; };
3D47B2AD1F14BE89000828D2 /* cian_api.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D47B2AB1F14BE89000828D2 /* cian_api.hpp */; };
3D47B2AF1F14BE94000828D2 /* cian_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D47B2AE1F14BE94000828D2 /* cian_tests.cpp */; };
3DBC1C541E4B14920016897F /* facebook_ads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DBC1C521E4B14920016897F /* facebook_ads.cpp */; };
3DBC1C551E4B14920016897F /* facebook_ads.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3DBC1C531E4B14920016897F /* facebook_ads.hpp */; };
3DFEBF851EF82BEA00317D5C /* viator_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3DFEBF831EF82BEA00317D5C /* viator_api.cpp */; };
@ -75,6 +78,9 @@
3D47B2971F054C89000828D2 /* taxi_countries.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = taxi_countries.cpp; sourceTree = "<group>"; };
3D47B2981F054C89000828D2 /* taxi_countries.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = taxi_countries.hpp; sourceTree = "<group>"; };
3D47B2991F054C89000828D2 /* taxi_places.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = taxi_places.hpp; sourceTree = "<group>"; };
3D47B2AA1F14BE89000828D2 /* cian_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cian_api.cpp; sourceTree = "<group>"; };
3D47B2AB1F14BE89000828D2 /* cian_api.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cian_api.hpp; sourceTree = "<group>"; };
3D47B2AE1F14BE94000828D2 /* cian_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cian_tests.cpp; sourceTree = "<group>"; };
3DBC1C501E4B14810016897F /* facebook_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = facebook_tests.cpp; sourceTree = "<group>"; };
3DBC1C521E4B14920016897F /* facebook_ads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = facebook_ads.cpp; sourceTree = "<group>"; };
3DBC1C531E4B14920016897F /* facebook_ads.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = facebook_ads.hpp; sourceTree = "<group>"; };
@ -160,6 +166,8 @@
F6B5363B1DA520B20067EEA5 /* partners_api */ = {
isa = PBXGroup;
children = (
3D47B2AA1F14BE89000828D2 /* cian_api.cpp */,
3D47B2AB1F14BE89000828D2 /* cian_api.hpp */,
3D47B2961F054C89000828D2 /* taxi_base.cpp */,
3D47B2971F054C89000828D2 /* taxi_countries.cpp */,
3D47B2981F054C89000828D2 /* taxi_countries.hpp */,
@ -197,6 +205,7 @@
F6B536441DA521060067EEA5 /* partners_api_tests */ = {
isa = PBXGroup;
children = (
3D47B2AE1F14BE94000828D2 /* cian_tests.cpp */,
3D47B2801F00F94D000828D2 /* mopub_tests.cpp */,
3DFEBF871EF82C1300317D5C /* viator_tests.cpp */,
3DFEBFA01EFBFC2300317D5C /* taxi_engine_tests.cpp */,
@ -250,6 +259,7 @@
3DFEBF861EF82BEA00317D5C /* viator_api.hpp in Headers */,
346E889C1E9D087400D4CE9B /* rb_ads.hpp in Headers */,
3DFEBF9A1EFBFC1500317D5C /* taxi_base.hpp in Headers */,
3D47B2AD1F14BE89000828D2 /* cian_api.hpp in Headers */,
346E889A1E9D087400D4CE9B /* banner.hpp in Headers */,
3DFEBF9F1EFBFC1500317D5C /* yandex_api.hpp in Headers */,
3DFEBF9D1EFBFC1500317D5C /* taxi_provider.hpp in Headers */,
@ -360,6 +370,7 @@
3DFEBF9B1EFBFC1500317D5C /* taxi_engine.cpp in Sources */,
346E889B1E9D087400D4CE9B /* rb_ads.cpp in Sources */,
3DBC1C541E4B14920016897F /* facebook_ads.cpp in Sources */,
3D47B2AF1F14BE94000828D2 /* cian_tests.cpp in Sources */,
346E88981E9D087400D4CE9B /* ads_engine.cpp in Sources */,
3D47B29B1F054C89000828D2 /* taxi_countries.cpp in Sources */,
F67E75251DB8F06F00D6741F /* opentable_api.cpp in Sources */,
@ -367,6 +378,7 @@
F6B536401DA520E40067EEA5 /* booking_api.cpp in Sources */,
3D47B29A1F054C89000828D2 /* taxi_base.cpp in Sources */,
3DFEBF9E1EFBFC1500317D5C /* yandex_api.cpp in Sources */,
3D47B2AC1F14BE89000828D2 /* cian_api.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};