diff --git a/Makefile b/Makefile index 31a3e93..ccec818 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CFLAGS ?= -O2 -Wall -Wextra `pkg-config libxml-2.0 --cflags` `pkg-config libxml+ PREFIX ?= /usr/local/bin LDFLAGS ?= -lcurl -lrestbed `pkg-config libxml-2.0 --libs` `pkg-config libxml++-3.0 --libs` -PARSERS = udrevaka.o padagali.o lightofindia.o ukarla.o alcapone.o plac.o zo.o suzzies.o +PARSERS = udrevaka.o padagali.o lightofindia.o ukarla.o alcapone.o plac.o zo.o suzies.o .PHONY: default default: menuprint @@ -37,7 +37,7 @@ plac.o: restaurants/plac.cpp restaurants/restaurants.hpp network/network.hpp htm $(CXX) $(CFLAGS) -c -o $@ $< zo.o: restaurants/zo.cpp restaurants/restaurants.hpp network/network.hpp htmlparser.hpp $(CXX) $(CFLAGS) -c -o $@ $< -suzzies.o: restaurants/suzzies.cpp restaurants/restaurants.hpp network/network.hpp environment.hpp +suzies.o: restaurants/suzies.cpp restaurants/restaurants.hpp network/network.hpp environment.hpp $(CXX) $(CFLAGS) -c -o $@ $< clean: diff --git a/main.cpp b/main.cpp index 5bab0c6..b3c3560 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,7 @@ #include "environment.hpp" -#include "restaurant.hpp" -#include "menu.hpp" #include "meal.hpp" +#include "menu.hpp" +#include "restaurant.hpp" #include "restaurants/restaurants.hpp" #include @@ -14,157 +14,137 @@ std::map> restaurants; -std::string file_info_name = "data_backup"; -struct tm last_save; - -void sendResponse(const std::string &response, int status_code, const std::shared_ptr< restbed::Session > session) { - session->close(status_code, response, { { "Content-Length", std::to_string(response.length()) }, { "Access-Control-Allow-Origin", "*" } }); +void sendResponse(const std::string &response, int status_code, + const std::shared_ptr session, + const std::string &content_type = "text/plain") { + session->close(status_code, response, + { { "Content-Length", std::to_string(response.length()) }, + { "Access-Control-Allow-Origin", "*" }, + { "Content-Type", content_type } }); } -void refresh( const std::shared_ptr< restbed::Session > session ) { - for(auto &restaurant : restaurants) +void refresh(const std::shared_ptr session) { + for (auto &restaurant : restaurants) restaurant.second->parse(); std::string response = "Refreshed menus!"; - sendResponse( "Refreshed menus!", restbed::OK, session ); + sendResponse("Refreshed menus!", restbed::OK, session); } -std::string get_all_json() { +std::string get_all_json(const std::vector &days = { 0, 1, 2, 3, 4, 5, + 6 }) { std::stringstream ss{}; bool atleastonerest = false; ss << "["; - for(auto &restaurant : restaurants) { + for (auto &restaurant : restaurants) { atleastonerest = true; - ss << restaurant.second->jsonify() << ","; + ss << restaurant.second->jsonify(days) << ","; } - if(atleastonerest) + if (atleastonerest) ss.seekp(-1, ss.cur); ss << "]"; return ss.str(); } -void backupData() { - time_t now = time(NULL); - struct tm *local = localtime(&now); - if(last_save.tm_year == local->tm_year && last_save.tm_mon == local->tm_mon && last_save.tm_mday == local->tm_mday) - return; - - std::ofstream output_file; - output_file.open(file_info_name, std::ios_base::app); - auto write_buffer = get_all_json(); - write_buffer += "\n"; - output_file.write(write_buffer.c_str(), write_buffer.size()); - - last_save.tm_year = local->tm_year; - last_save.tm_mon = local->tm_mon; - last_save.tm_mday = local->tm_mday; +void get_all(const std::shared_ptr session) { + sendResponse(get_all_json(), restbed::OK, session, "application/json"); } -void get_all( const std::shared_ptr< restbed::Session > session ) { - sendResponse(get_all_json(), restbed::OK, session); -} - -void get( const std::shared_ptr< restbed::Session > session ) { +void get(const std::shared_ptr session) { // TODO better int day = -1; std::string restaurant = ""; auto request = session->get_request(); - for(const auto &query_param : request->get_query_parameters()) { - if(query_param.first == "day") { - if(query_param.second == "monday") { + for (const auto &query_param : request->get_query_parameters()) { + if (query_param.first == "day") { + if (query_param.second == "monday") { day = 0; - } else if(query_param.second == "tuesday") { + } else if (query_param.second == "tuesday") { day = 1; - } else if(query_param.second == "wednesday") { + } else if (query_param.second == "wednesday") { day = 2; - } else if(query_param.second == "thursday") { + } else if (query_param.second == "thursday") { day = 3; - } else if(query_param.second == "friday") { + } else if (query_param.second == "friday") { day = 4; - } else if(query_param.second == "saturday") { + } else if (query_param.second == "saturday") { day = 5; } else { day = 6; } } - if(query_param.first == "restaurant") + if (query_param.first == "restaurant") restaurant = query_param.second; } - if(day == -1 && restaurant == "") { - sendResponse("DIDN'T SPECIFY DAY OR RESTAURANT", restbed::BAD_REQUEST, session); + if (day == -1 && restaurant == "") { + sendResponse("DIDN'T SPECIFY DAY OR RESTAURANT", restbed::BAD_REQUEST, + session); return; } - if(restaurant != "" && restaurants.find(restaurant) == restaurants.end()) { - sendResponse("YOU DIDN'T SPECIFY A VALID RESTAURANT!", restbed::BAD_REQUEST, session); + if (restaurant != "" && restaurants.find(restaurant) == restaurants.end()) { + sendResponse("YOU DIDN'T SPECIFY A VALID RESTAURANT!", + restbed::BAD_REQUEST, session); return; } - std::stringstream ss{}; - if(day != -1 && restaurant != "") { - ss << "[" << restaurants[restaurant]->jsonify({day}) << "]"; - } else if(day != -1) { - ss << "["; - bool atleastone = false; - for(auto &restaurant : restaurants) { - atleastone = true; - ss << restaurant.second->jsonify({day}) << ","; - } - if(atleastone) - ss.seekp(-1, ss.cur); - ss << "]"; - } else if(restaurant != "") { - ss << "[" << restaurants[restaurant]->jsonify() << "]"; + std::string response{}; + if (day != -1 && restaurant != "") { + response = "[" + restaurants[restaurant]->jsonify({ day }) + "]"; + } else if (day != -1) { + response = get_all_json({ day }); + } else if (restaurant != "") { + response = "[" + restaurants[restaurant]->jsonify() + "]"; } - sendResponse(ss.str(), restbed::OK, session); + sendResponse(response, restbed::OK, session, "application/json"); } -int main(int argc, char **argv, char **env) { +int main(int /*UNUSED*/, char ** /*UNUSED*/, char **env) { setupEnv(env); restaurants["udrevaka"] = std::make_unique(); restaurants["padagali"] = std::make_unique(); - restaurants["lightofindia"] = std::make_unique(); + restaurants["lightofindia"] = + std::make_unique(); restaurants["ukarla"] = std::make_unique(); restaurants["alcapone"] = std::make_unique(); restaurants["plac"] = std::make_unique(); restaurants["zo"] = std::make_unique(); - restaurants["suzzies"] = std::make_unique(); + restaurants["suzies"] = std::make_unique(); std::cout << "Initial parsing" << std::endl; - for(auto &restaurant : restaurants) + for (auto &restaurant : restaurants) restaurant.second->parse(); std::cout << "Finished parsing" << std::endl; - last_save.tm_year = 0; - last_save.tm_mon = 0; - last_save.tm_mday = 0; - backupData(); restbed::Service service; - auto getallserv = std::make_shared< restbed::Resource >(); + auto getallserv = std::make_shared(); getallserv->set_path("/get_all"); - getallserv->set_method_handler( "GET", get_all ); + getallserv->set_method_handler("GET", get_all); service.publish(getallserv); - auto getserv = std::make_shared< restbed::Resource >(); + auto getserv = std::make_shared(); getserv->set_path("/get"); - getserv->set_method_handler( "GET", get ); + getserv->set_method_handler("GET", get); service.publish(getserv); - auto refreshserv = std::make_shared< restbed::Resource >(); + auto refreshserv = std::make_shared(); refreshserv->set_path("/refresh"); - refreshserv->set_method_handler( "GET", refresh ); + refreshserv->set_method_handler("GET", refresh); service.publish(refreshserv); - auto ssl_settings = std::make_shared(); +/* auto ssl_settings = std::make_shared(); ssl_settings->set_http_disabled(true); - ssl_settings->set_private_key(restbed::Uri("file:///home/zvon/data/programming/lunch-rest/example.key")); - ssl_settings->set_certificate(restbed::Uri("file:///home/zvon/data/programming/lunch-rest/example.crt")); - ssl_settings->set_temporary_diffie_hellman(restbed::Uri("file:///home/zvon/data/programming/lunch-rest/dhparams.pem")); - ssl_settings->set_port(1985); + ssl_settings->set_private_key(restbed::Uri( + "file:///home/zvon/data/programming/lunch-rest/example.key")); + ssl_settings->set_certificate(restbed::Uri( + "file:///home/zvon/data/programming/lunch-rest/example.crt")); + ssl_settings->set_temporary_diffie_hellman(restbed::Uri( + "file:///home/zvon/data/programming/lunch-rest/dhparams.pem")); + ssl_settings->set_port(1985);*/ - auto settings = std::make_shared< restbed::Settings >(); + auto settings = std::make_shared(); settings->set_port(1984); - settings->set_default_header( "Connection", "close" ); - settings->set_ssl_settings(ssl_settings); + settings->set_default_header("Connection", "close"); +// settings->set_ssl_settings(ssl_settings); service.start(settings); diff --git a/restaurants/restaurants.hpp b/restaurants/restaurants.hpp index 81ac1a6..fa2b2a4 100644 --- a/restaurants/restaurants.hpp +++ b/restaurants/restaurants.hpp @@ -46,10 +46,10 @@ public: virtual ~ZoRestaurant() = default; virtual void parse() override {}; }; -class SuzziesRestaurant : public Restaurant { +class SuziesRestaurant : public Restaurant { public: - SuzziesRestaurant() : Restaurant("http://suzies.cz/poledni-menu.html", "Suzzie's") {} - virtual ~SuzziesRestaurant() = default; + SuziesRestaurant() : Restaurant("https://www.suzies.cz/poledni-menu", "Suzie's") {} + virtual ~SuziesRestaurant() = default; virtual void parse() override; private: std::string api_key; diff --git a/restaurants/suzies.cpp b/restaurants/suzies.cpp new file mode 100644 index 0000000..7106aaf --- /dev/null +++ b/restaurants/suzies.cpp @@ -0,0 +1,91 @@ +#include "restaurants.hpp" +#include "../network/network.hpp" +#include "../htmlparser.hpp" +#include + +int weekDay(const std::string &date_str) { + struct tm date_tm; + strptime(date_str.c_str(), "%Y-%m-%d %H:%M:%S", &date_tm); + return (date_tm.tm_wday + 6) % 7; +} + +void LunchRest::SuziesRestaurant::parse() { + Request r; + auto html = r.get(_url); + if(html == "") + return; + clearMenus(); + HtmlParser hparse(html); + auto &root = hparse.getRoot(); + auto days = root.find("//div[@class='uk-card-body item']"); + std::cout << "IMMA TRY" << std::endl; + for(auto &day : days) { + auto daytext = nodeToText(day->find("./h2/text()")[0]); + int cur_day = 0; + switch(daytext[0]) { + case 'P': + if(daytext[1] != 'o') { + cur_day = 4; + } + break; + case "Ú"[0]: + cur_day = 1; + break; + case 'S': + cur_day = 2; + break; + case "Č"[0]: + cur_day = 3; + default: + break; + } + std::cout << "DAY: " << cur_day << std::endl; + bool working_on_meal = false; + bool working_on_soup = false; + Meal meal{}; + for(auto &child : day->get_children()) { + if(child->get_name() == "h3" && child->find("./text()").size() != 0) { + std::cout << "MEAL" << std::endl; + auto meal_type = trim(nodeToText(child->find("./text()")[0])); + std::cout << meal_type << std::endl; + meal = Meal(); + working_on_meal = true; + if(meal_type == "Polévka") { + working_on_soup = true; + meal.setSoup(); + } else { + meal.setDesc(meal_type); + } + } + if(working_on_meal && child->get_name() == "div") { + if(!working_on_soup) { + auto price_elements = child->find("./div[contains(@class, 'price')]/text()"); + if(price_elements.size() == 0) { + goto end; + } + auto price = nodeToText(price_elements[0]); + std::cout << "PRICE: " << price << std::endl; + meal.setPrice(std::stoi(price)); + auto namelen = child->find("./div[contains(@class, 'uk-width-expand')]/text()").size(); + std::string name = ""; + if(namelen == 1) { + name = trim(nodeToText(child->find("./div[contains(@class, 'uk-width-expand')]/text()")[0])); + } else { + name = trim(nodeToText(child->find("./div[contains(@class, 'uk-width-expand')]/span/text()")[0])) + " " + trim(nodeToText(child->find("./div[contains(@class, 'uk-width-expand')]/text()")[1])); + } + std::cout << name << std::endl; + meal.setName(name); + } else { + auto name = trim(nodeToText(child->find("./div[contains(@class, 'uk-width-expand')]/text()")[0])); + std::cout << name << std::endl; + meal.setName(name); + } + menus[cur_day].addMeal(meal); +end: + working_on_meal = false; + working_on_soup = false; + } + } + menus[cur_day].setInvalidMenu(false); + } +} diff --git a/restaurants/suzzies.cpp b/restaurants/suzzies.cpp deleted file mode 100644 index 04f85b7..0000000 --- a/restaurants/suzzies.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "restaurants.hpp" -#include "../network/network.hpp" -#include "../htmlparser.hpp" - -int weekDay(const std::string &date_str) { - struct tm date_tm; - strptime(date_str.c_str(), "%Y-%m-%d %H:%M:%S", &date_tm); - return (date_tm.tm_wday + 6) % 7; -} - -void LunchRest::SuzziesRestaurant::parse() { - Request r; - auto html = r.get(_url); - if(html == "") - return; - clearMenus(); - HtmlParser hparse(html); - auto &root = hparse.getRoot(); - auto days = root.find("//div[@class='day']"); - for(auto &day : days) { - auto *daynum = xmlGetProp(day->cobj(), (xmlChar*)"data-day"); - int cur_day = 0; - switch(daynum[0]) { - case '2': - cur_day = 1; - break; - case '3': - cur_day = 2; - break; - case '4': - cur_day = 3; - break; - case '5': - cur_day = 4; - default: - break; - } - for(auto &meal : day->find(".//div[@class='item']")) { - Meal meal_obj{}; - auto type = trim(nodeToText(meal->find(".//h6/text()")[0])); - auto name_nodes = meal->find(".//div[@class='title']/text()"); - auto text_nodes = meal->find(".//div[@class='text']/text()"); - auto price_nodes = meal->find(".//div[@class='price']/text()"); - if(price_nodes.size() > 0) { - // not soup - auto name = type; - if(name_nodes.size() > 0) - name += " - " + trim(nodeToText(name_nodes[0])); - meal_obj.setName(name); - if(text_nodes.size() > 0) - meal_obj.setDesc(trim(nodeToText(text_nodes[0]))); - meal_obj.setPrice(std::stoi(trim(nodeToText(price_nodes[0])))); - } else { - meal_obj.setName(trim(nodeToText(name_nodes[0]))); - meal_obj.setSoup(); - } - menus[cur_day].addMeal(meal_obj); - } - menus[cur_day].setInvalidMenu(false); - } -}