From 71c88bacb5dcca077690381f89c86042019d428e Mon Sep 17 00:00:00 2001 From: Maciej Gibowicz Date: Mon, 17 Feb 2025 10:39:32 +0100 Subject: [PATCH] [BH-2097] Adding and deleting a single custom quote Adding and removing custom quotes in the database sent by Center --- module-services/service-db/DBServiceAPI.cpp | 33 +++ .../include/service-db/DBServiceAPI.hpp | 10 + .../include/service-db/QuotesMessages.hpp | 49 +++- .../include/endpoints/JsonKeyNames.hpp | 19 +- .../presenters/HomeScreenPresenter.cpp | 3 +- .../services/db/agents/QuotesAgent.cpp | 75 ++++++ .../services/db/agents/QuotesAgent.hpp | 3 + .../services/db/agents/QuotesQueries.hpp | 7 + .../desktop/endpoints/quotes/QuotesHelper.cpp | 86 +++++- test/custom_quotes.py | 255 ++++++++++++++++++ 10 files changed, 518 insertions(+), 22 deletions(-) create mode 100644 test/custom_quotes.py diff --git a/module-services/service-db/DBServiceAPI.cpp b/module-services/service-db/DBServiceAPI.cpp index 5322994486768723a643913b477f55fcbecbc635..38dbc1d6d2fc7e467c63bc5e237f0a59be8ee9e2 100644 --- a/module-services/service-db/DBServiceAPI.cpp +++ b/module-services/service-db/DBServiceAPI.cpp @@ -317,6 +317,39 @@ void DBServiceAPI::InformDateChanged(sys::Service *serv) DBServiceAPI::GetQuery(serv, db::Interface::Name::Quotes, std::move(query)); } +bool DBServiceAPI::QuotesAddNewEntry(sys::Service *serv, + const std::string "e, + const std::string &author, + std::unique_ptr &&listener) +{ + auto query = std::make_unique(quote, author); + query->setQueryListener(std::move(listener)); + const auto [result, _] = DBServiceAPI::GetQuery(serv, db::Interface::Name::Quotes, std::move(query)); + return result; +} + +bool DBServiceAPI::QuotesEditEntry(sys::Service *serv, + std::uint32_t id, + const std::string "e, + const std::string &author, + std::unique_ptr &&listener) +{ + auto query = std::make_unique(id, quote, author); + query->setQueryListener(std::move(listener)); + const auto [result, _] = DBServiceAPI::GetQuery(serv, db::Interface::Name::Quotes, std::move(query)); + return result; +} + +bool DBServiceAPI::QuotesDeleteEntry(sys::Service *serv, + std::uint32_t id, + std::unique_ptr &&listener) +{ + auto query = std::make_unique(id); + query->setQueryListener(std::move(listener)); + const auto [result, _] = DBServiceAPI::GetQuery(serv, db::Interface::Name::Quotes, std::move(query)); + return result; +} + void DBServiceAPI::QuotesGroupChanged(sys::Service *serv, const std::string &group) { auto query = std::make_unique(group); diff --git a/module-services/service-db/include/service-db/DBServiceAPI.hpp b/module-services/service-db/include/service-db/DBServiceAPI.hpp index d9069b961e4fa27ebe11db8cf6f32cc6730fa7c8..00fbe0d3172d864502106e671975c99c1febc995 100644 --- a/module-services/service-db/include/service-db/DBServiceAPI.hpp +++ b/module-services/service-db/include/service-db/DBServiceAPI.hpp @@ -128,5 +128,15 @@ class DBServiceAPI static void InformLanguageChanged(sys::Service *serv); static void InformDateChanged(sys::Service *serv); + static bool QuotesAddNewEntry(sys::Service *serv, + const std::string "e, + const std::string &author, + std::unique_ptr &&listener); + static bool QuotesEditEntry(sys::Service *serv, + std::uint32_t id, + const std::string "e, + const std::string &author, + std::unique_ptr &&listener); + static bool QuotesDeleteEntry(sys::Service *serv, std::uint32_t id, std::unique_ptr &&listener); static void QuotesGroupChanged(sys::Service *serv, const std::string &group); }; diff --git a/module-services/service-db/include/service-db/QuotesMessages.hpp b/module-services/service-db/include/service-db/QuotesMessages.hpp index f9fa8b02b6c5db70dc079d7a44f9dba19ddccd3a..dbbcd5e7e74436a6ece2442b96af9b315e75ae0a 100644 --- a/module-services/service-db/include/service-db/QuotesMessages.hpp +++ b/module-services/service-db/include/service-db/QuotesMessages.hpp @@ -298,7 +298,8 @@ namespace Quotes class AddQuoteResponse : public db::QueryResult { public: - explicit AddQuoteResponse(bool success, unsigned int quoteId) : success(success), quoteId(quoteId) + explicit AddQuoteResponse(bool success = false, unsigned int quoteId = 0) + : success(success), quoteId(quoteId) {} const bool success; const unsigned int quoteId; @@ -374,6 +375,50 @@ namespace Quotes } }; + class AddNewEntry : public db::Query + { + public: + explicit AddNewEntry(const std::string "e, const std::string &author) + : Query(Query::Type::Create), quote(quote), author(author) + {} + const std::string quote; + const std::string author; + + auto debugInfo() const -> std::string + { + return "AddNewEntry"; + } + }; + + class EditEntry : public db::Query + { + public: + explicit EditEntry(std::uint32_t id, const std::string "e, const std::string &author) + : Query(Query::Type::Update), id(id), quote(quote), author(author) + {} + const std::uint32_t id; + const std::string quote; + const std::string author; + + auto debugInfo() const -> std::string + { + return "EditEntry"; + } + }; + + class EditEntryResponse : public db::QueryResult + { + public: + explicit EditEntryResponse(bool success = false) : success(success) + {} + const bool success; + + auto debugInfo() const -> std::string + { + return "EditEntryResponse"; + } + }; + class InformGroupChanged : public db::Query { public: @@ -434,7 +479,7 @@ namespace Quotes class DeleteQuoteResponse : public db::QueryResult { public: - explicit DeleteQuoteResponse(bool success) : success(success) + explicit DeleteQuoteResponse(bool success = false) : success(success) {} const bool success; diff --git a/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp b/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp index e887094b6ce085ef34f3bd3bab3ca86ac34ac37c..5947e191352e3d979f72cc329de529d899e18ff7 100644 --- a/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp +++ b/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp @@ -126,18 +126,11 @@ namespace sdesktop::endpoints::json namespace quotes { - namespace settings - { - inline constexpr auto group = "group"; - inline constexpr auto interval = "interval"; - } // namespace settings - - inline constexpr auto quotation = "quotation"; - namespace quotations - { - inline constexpr auto text = "text"; - inline constexpr auto author = "author"; - } // namespace quotations - } // namespace quotes + inline constexpr auto quote = "quote"; + inline constexpr auto author = "author"; + inline constexpr auto group = "group"; + inline constexpr auto interval = "interval"; + inline constexpr auto quoteID = "quoteID"; + } // namespace quotes } // namespace sdesktop::endpoints::json diff --git a/products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp b/products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp index 15b2345154167bd85562abdcc4c725315ef45fed..c0856c8b9c5c956954bc728c4d5a4bba15590078 100644 --- a/products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp +++ b/products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2025, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md #include "application-bell-main/presenters/HomeScreenPresenter.hpp" @@ -288,6 +288,7 @@ namespace app::home_screen const auto batteryState = batteryModel.getLevelState().state; const bool isUsbConnected = usbStatusModel.isUsbConnected(batteryState); getView()->updateUsbStatus(isUsbConnected); + requestQuote(); } bool HomeScreenPresenter::isLowBatteryWarningNeeded() diff --git a/products/BellHybrid/services/db/agents/QuotesAgent.cpp b/products/BellHybrid/services/db/agents/QuotesAgent.cpp index af01b8b019ccd8156b3b4a376887b8cf120dd230..77074b8738c967e1ec89adb57c757786b9b137b1 100644 --- a/products/BellHybrid/services/db/agents/QuotesAgent.cpp +++ b/products/BellHybrid/services/db/agents/QuotesAgent.cpp @@ -24,6 +24,15 @@ namespace Quotes shuffleQuoteModel.updateList(ListUpdateMode::Forced); return std::make_unique(true); } + else if (typeid(*query) == typeid(Messages::AddNewEntry)) { + return handleAddNewEntry(query); + } + else if (typeid(*query) == typeid(Messages::EditEntry)) { + return handleEditEntry(query); + } + else if (typeid(*query) == typeid(Messages::DeleteQuoteRequest)) { + return handleDeleteEntry(query); + } else if (typeid(*query) == typeid(Messages::InformGroupChanged)) { return handleGroupChanged(query); } @@ -51,6 +60,72 @@ namespace Quotes return nullptr; } + auto QuotesAgent::handleAddNewEntry(std::shared_ptr query) -> std::unique_ptr + { + const auto request = std::dynamic_pointer_cast(query); + if (request == nullptr) { + auto response = std::make_unique(); + response->setRequestQuery(query); + return response; + } + + const auto quotesGroup = settings->getValue(settings::Quotes::selectedGroup, settings::SettingsScope::Global); + const auto executeResult = + quotesDB->execute(Queries::addCustomQuote, request->quote.c_str(), request->author.c_str()); + + if (executeResult && quotesGroup == customGroup) { + shuffleQuoteModel.updateList(ListUpdateMode::Forced); + } + + const auto quoteId = quotesDB->getLastInsertRowId(); + auto response = std::make_unique(executeResult, quoteId); + response->setRequestQuery(query); + return response; + } + + auto QuotesAgent::handleEditEntry(std::shared_ptr query) -> std::unique_ptr + { + const auto request = std::dynamic_pointer_cast(query); + if (request == nullptr) { + auto response = std::make_unique(); + response->setRequestQuery(query); + return response; + } + + const auto quotesGroup = settings->getValue(settings::Quotes::selectedGroup, settings::SettingsScope::Global); + const auto executeResult = + quotesDB->execute(Queries::editCustomQuote, request->quote.c_str(), request->author.c_str(), request->id); + + if (executeResult && quotesGroup == customGroup) { + shuffleQuoteModel.updateList(ListUpdateMode::Forced); + } + + auto response = std::make_unique(executeResult); + response->setRequestQuery(query); + return response; + } + + auto QuotesAgent::handleDeleteEntry(std::shared_ptr query) -> std::unique_ptr + { + const auto request = std::dynamic_pointer_cast(query); + if (request == nullptr) { + auto response = std::make_unique(); + response->setRequestQuery(query); + return response; + } + + const auto quotesGroup = settings->getValue(settings::Quotes::selectedGroup, settings::SettingsScope::Global); + const auto executeResult = quotesDB->execute(Queries::deleteCustomQuote, request->quoteId); + + if (executeResult && quotesGroup == customGroup) { + shuffleQuoteModel.updateList(ListUpdateMode::Forced); + } + + auto response = std::make_unique(executeResult); + response->setRequestQuery(query); + return response; + } + auto QuotesAgent::handleGroupChanged(std::shared_ptr query) -> std::unique_ptr { const auto request = std::dynamic_pointer_cast(query); diff --git a/products/BellHybrid/services/db/agents/QuotesAgent.hpp b/products/BellHybrid/services/db/agents/QuotesAgent.hpp index 139c7bf66bcea5a667b6d1ec5b4913aaa6d57bae..754f596726a92256157ef5d6ad296bd525cf9687 100644 --- a/products/BellHybrid/services/db/agents/QuotesAgent.hpp +++ b/products/BellHybrid/services/db/agents/QuotesAgent.hpp @@ -30,6 +30,9 @@ namespace Quotes Database *quotesDB; ShuffleQuoteModel shuffleQuoteModel; + auto handleAddNewEntry(std::shared_ptr query) -> std::unique_ptr; + auto handleEditEntry(std::shared_ptr query) -> std::unique_ptr; + auto handleDeleteEntry(std::shared_ptr query) -> std::unique_ptr; auto handleGroupChanged(std::shared_ptr query) -> std::unique_ptr; }; } // namespace Quotes diff --git a/products/BellHybrid/services/db/agents/QuotesQueries.hpp b/products/BellHybrid/services/db/agents/QuotesQueries.hpp index d72171906e8d40411a577475140a9cf90e30332c..945a0cb9f848940c2e3faa5904b7572022db776a 100644 --- a/products/BellHybrid/services/db/agents/QuotesQueries.hpp +++ b/products/BellHybrid/services/db/agents/QuotesQueries.hpp @@ -20,4 +20,11 @@ namespace Quotes::Queries "SELECT quote_id, quote, author FROM custom_quote_table WHERE quote_id=" u32_ ";"; inline constexpr auto getCustomQuotesCount = "SELECT COUNT(quote_id) FROM custom_quote_table;"; + + inline constexpr auto addCustomQuote = "INSERT INTO custom_quote_table (quote, author) VALUES (" str_c str_ ");"; + + inline constexpr auto deleteCustomQuote = "DELETE FROM custom_quote_table WHERE quote_id=" u32_ ";"; + + inline constexpr auto editCustomQuote = + "UPDATE custom_quote_table SET quote=" str_c "author=" str_ " WHERE quote_id=" u32_ ";"; } // namespace Quotes::Queries diff --git a/products/BellHybrid/services/desktop/endpoints/quotes/QuotesHelper.cpp b/products/BellHybrid/services/desktop/endpoints/quotes/QuotesHelper.cpp index 79e286d335f26b0fa83f9eb68bd9bc8d8da131c9..bd574afe0aa0422a09c540f00d2fc3fdfb9b3d99 100644 --- a/products/BellHybrid/services/desktop/endpoints/quotes/QuotesHelper.cpp +++ b/products/BellHybrid/services/desktop/endpoints/quotes/QuotesHelper.cpp @@ -4,8 +4,10 @@ #include #include #include +#include #include #include +#include #include namespace sdesktop::endpoints @@ -18,17 +20,68 @@ namespace sdesktop::endpoints auto QuotesHelper::processPost(Context &context) -> ProcessResult { - // TODO: https://appnroll.atlassian.net/browse/BH-2097 - return {Sent::No, ResponseContext{.status = http::Code::InternalServerError}}; + const auto &body = context.getBody(); + if (const auto "e = body[json::quotes::quote].string_value(); !quote.empty()) { + const auto &author = body[json::quotes::author].string_value(); + + auto listener = std::make_unique( + [=](db::QueryResult *result, Context &context) { + const auto addQuoteResult = dynamic_cast(result); + if (addQuoteResult == nullptr || !addQuoteResult->success) { + context.setResponseStatus(http::Code::InternalServerError); + sender::putToSendQueue(context.createSimpleResponse()); + return false; + } + + context.setResponseBody( + json11::Json::object{{json::quotes::quoteID, static_cast(addQuoteResult->quoteId)}}); + context.setResponseStatus(http::Code::OK); + sender::putToSendQueue(context.createSimpleResponse()); + return true; + }, + context); + + DBServiceAPI::QuotesAddNewEntry(owner, quote.c_str(), author.c_str(), std::move(listener)); + return {Sent::Yes, std::nullopt}; + } + + LOG_ERROR("Bad request! New quote is incorrect or missing!"); + return {Sent::No, ResponseContext{.status = http::Code::BadRequest}}; } auto QuotesHelper::processPut(Context &context) -> ProcessResult { const auto &body = context.getBody(); - if (const auto group = body[json::quotes::settings::group].string_value(); !group.empty()) { + if (const auto "e = body[json::quotes::quote].string_value(); !quote.empty()) { + const auto &author = body[json::quotes::author].string_value(); + const auto id = body[json::quotes::quoteID]; + + if (!id.is_number()) { + return {Sent::No, ResponseContext{.status = http::Code::BadRequest}}; + } + + auto listener = std::make_unique( + [=](db::QueryResult *result, Context &context) { + const auto editQuoteResult = dynamic_cast(result); + if (editQuoteResult == nullptr || !editQuoteResult->success) { + context.setResponseStatus(http::Code::InternalServerError); + sender::putToSendQueue(context.createSimpleResponse()); + return false; + } + + context.setResponseStatus(http::Code::OK); + sender::putToSendQueue(context.createSimpleResponse()); + return true; + }, + context); + + DBServiceAPI::QuotesEditEntry(owner, id.int_value(), quote.c_str(), author.c_str(), std::move(listener)); + return {Sent::Yes, std::nullopt}; + } + else if (const auto group = body[json::quotes::group].string_value(); !group.empty()) { DBServiceAPI::QuotesGroupChanged(owner, group.c_str()); } - else if (const auto interval = body[json::quotes::settings::interval].string_value(); !interval.empty()) { + else if (const auto &interval = body[json::quotes::interval].string_value(); !interval.empty()) { // TODO: https://appnroll.atlassian.net/browse/BH-2095 } else { @@ -40,8 +93,29 @@ namespace sdesktop::endpoints auto QuotesHelper::processDelete(Context &context) -> ProcessResult { - // TODO: https://appnroll.atlassian.net/browse/BH-2097 - return {Sent::No, ResponseContext{.status = http::Code::InternalServerError}}; + const auto &body = context.getBody(); + if (const auto quoteID = body[json::quotes::quoteID]; quoteID.is_number()) { + auto listener = std::make_unique( + [=](db::QueryResult *result, Context context) { + const auto deleteResult = dynamic_cast(result); + if (deleteResult == nullptr || !deleteResult->success) { + context.setResponseStatus(http::Code::InternalServerError); + sender::putToSendQueue(context.createSimpleResponse()); + return false; + } + + context.setResponseStatus(http::Code::NoContent); + sender::putToSendQueue(context.createSimpleResponse()); + return true; + }, + context); + + DBServiceAPI::QuotesDeleteEntry(owner, quoteID.int_value(), std::move(listener)); + return {Sent::Yes, std::nullopt}; + } + + LOG_ERROR("Bad request! Quote ID is incorrect or missing!"); + return {Sent::No, ResponseContext{.status = http::Code::BadRequest}}; } } // namespace sdesktop::endpoints diff --git a/test/custom_quotes.py b/test/custom_quotes.py new file mode 100644 index 0000000000000000000000000000000000000000..ceede7fb668809d8a3f291c53201ff01036719b1 --- /dev/null +++ b/test/custom_quotes.py @@ -0,0 +1,255 @@ +import base64 +import os.path +import serial +import random +import json +import zlib +import argparse +import time +from tqdm import tqdm + +http_methods = { + 'GET': 1, + 'POST': 2, + 'PUT': 3, + 'DELETE': 4 +} + +endpoint_types = { + 'Invalid': 0, + 'DeviceInfo': 1, + 'Update': 2, + 'FilesystemUpload': 3, + 'Backup': 4, + 'Restore': 5, + 'Factory': 6, + 'Contacts': 7, + 'Messages': 8, + 'Calllog': 9, + 'CalendarEventsPlaceholder': 10, + 'DeveloperMode': 11, + 'Bluetooth': 12, + 'UsbSecurity': 13, + 'Outbox': 14, + 'Reboot': 15, + 'TimeSync': 16, + 'Quotes': 17 +} + +payload_marker = '#' +payload_size_len = 9 +port_timeout_short_s = 1 +port_timeout_long_s = 5 +port_baudrate = 115200 + + +def get_new_uuid() -> int: + return random.randint(1, 10000) + +def add_quote(port_path: str, quote_str: str, author_str: str) -> bool: + uuid = get_new_uuid() + + payload = { + 'endpoint': endpoint_types['Quotes'], + 'method': http_methods['POST'], + 'uuid': uuid, + 'body': { + 'quote': quote_str, + 'author': author_str + } + } + + payload_str = json.dumps(payload) + payload_len_str = str(len(payload_str)).rjust(payload_size_len, '0') + request_str = payload_marker + payload_len_str + payload_str + + with serial.Serial(port_path, port_baudrate, timeout=port_timeout_short_s) as port: + port.write(request_str.encode('ascii')) + response = port.read(2048) + resp_json = json.loads(response[10:]) + status = resp_json['status'] + if status == 200: + print(f'Request success {resp_json["body"]}') + return True + print(f'Request failed, status {status}') + return False + +def edit_quote(port_path: str, quote_id: int, quote_str: str, author_str: str) -> bool: + uuid = get_new_uuid() + + payload = { + 'endpoint': endpoint_types['Quotes'], + 'method': http_methods['PUT'], + 'uuid': uuid, + 'body': { + 'quoteID': quote_id, + 'quote': quote_str, + 'author': author_str + } + } + + payload_str = json.dumps(payload) + payload_len_str = str(len(payload_str)).rjust(payload_size_len, '0') + request_str = payload_marker + payload_len_str + payload_str + + with serial.Serial(port_path, port_baudrate, timeout=port_timeout_short_s) as port: + port.write(request_str.encode('ascii')) + response = port.read(2048) + resp_json = json.loads(response[10:]) + status = resp_json['status'] + if status == 200: + print(f'Request success') + return True + print(f'Request failed, status {status}') + return False + +def delete_quote(port_path: str, quote_id: int) -> bool: + uuid = get_new_uuid() + + payload = { + 'endpoint': endpoint_types['Quotes'], + 'method': http_methods['DELETE'], + 'uuid': uuid, + 'body': { + 'quoteID': quote_id + } + } + + payload_str = json.dumps(payload) + payload_len_str = str(len(payload_str)).rjust(payload_size_len, '0') + request_str = payload_marker + payload_len_str + payload_str + + with serial.Serial(port_path, port_baudrate, timeout=port_timeout_short_s) as port: + port.write(request_str.encode('ascii')) + response = port.read(2048) + resp_json = json.loads(response[10:]) + status = resp_json['status'] + if status == 204: + print(f'Request success') + return True + print(f'Request failed, status {status}') + return False + +def change_group(port_path: str, quote_group: str) -> bool: + uuid = get_new_uuid() + + payload = { + 'endpoint': endpoint_types['Quotes'], + 'method': http_methods['PUT'], + 'uuid': uuid, + 'body': { + 'group': quote_group + } + } + + payload_str = json.dumps(payload) + payload_len_str = str(len(payload_str)).rjust(payload_size_len, '0') + request_str = payload_marker + payload_len_str + payload_str + + with serial.Serial(port_path, port_baudrate, timeout=port_timeout_short_s) as port: + port.write(request_str.encode('ascii')) + response = port.read(2048) + resp_json = json.loads(response[10:]) + status = resp_json['status'] + if status == 200: + print(f'Request success') + return True + print(f'Request failed, status {status}') + return False + +def change_interval(port_path: str, quote_interval: str) -> bool: + uuid = get_new_uuid() + + payload = { + 'endpoint': endpoint_types['Quotes'], + 'method': http_methods['PUT'], + 'uuid': uuid, + 'body': { + 'interval': quote_interval + } + } + + payload_str = json.dumps(payload) + payload_len_str = str(len(payload_str)).rjust(payload_size_len, '0') + request_str = payload_marker + payload_len_str + payload_str + + with serial.Serial(port_path, port_baudrate, timeout=port_timeout_short_s) as port: + port.write(request_str.encode('ascii')) + response = port.read(2048) + resp_json = json.loads(response[10:]) + status = resp_json['status'] + if status == 200: + print(f'Request success') + return True + print(f'Request failed, status {status}') + return False + +def main(): + parser = argparse.ArgumentParser( + prog='custom_quotes', + description='Script used to test functionality of custom quotes endpoint in Harmony project' + ) + parser.add_argument('-p', '--port', + metavar='path_to_com_port', + help='path to COM port of the device (e.g. /dev/ttyACM0)') + parser.add_argument('-a', '--add', + action='store_true', + help='add new custom quote') + parser.add_argument('-d', '--delete', + metavar='quote_id_to_delete', + type=int, + help='delete custom quote') + parser.add_argument('-e', '--edit', + metavar='quote_id_to_edit', + type=int, + help='edit custom quote') + parser.add_argument('-q', '--quote', + metavar='string_with_quote', + help='string with new quote') + parser.add_argument('-t', '--author', + metavar='string_with_author', + help='string with author') + parser.add_argument('-g', '--group', + metavar='string_with_group_type', + help='string with type of group of displayed quotes [Predefined or Custom]') + parser.add_argument('-i', '--interval', + metavar='quotes_display_interval', + help='quotes display interval [\'x\' minutes or \'at midnight\']') + + args = parser.parse_args() + if not args.port: + print('Invalid usage: please specify device port') + print('Run with -h to see help') + return + if not args.add and not args.delete and not args.edit and not args.group and not args.interval: + print('Invalid usage: please specify add, delete, edit, group or interval argument') + print('Run with -h to see help') + return + if args.add: + if not args.quote: + print('Invalid usage: please add quote') + print('Run with -h to see help') + return + else: + print("adding new quotes: " + args.quote) + status = add_quote(args.port, args.quote, args.author) + elif args.delete: + print("deleting quotes nr: " + str(args.delete)) + status = delete_quote(args.port, args.delete) + elif args.edit: + if not args.quote: + print('Invalid usage: please add quote') + print('Run with -h to see help') + return + else: + print("editing quotes nr: " + str(args.edit)) + status = edit_quote(args.port, args.edit, args.quote, args.author) + elif args.group: + print("quotes group: " + args.group) + status = change_group(args.port, args.group) + elif args.interval: + print("quotes interval: " + args.interval) + status = change_interval(args.port, args.interval) + +if __name__ == '__main__': + main()