Enable adding and removing ingredients from recipes.

This commit is contained in:
Nicolás A. Ortega Froysa 2024-10-21 13:54:07 +02:00
parent 03b1250006
commit 5bcc598880
6 changed files with 87 additions and 5 deletions

View File

@ -28,6 +28,8 @@ enum cmd_id {
CMD_LIST, CMD_LIST,
CMD_DEL, CMD_DEL,
CMD_INFO, CMD_INFO,
CMD_ADD_INGR,
CMD_RM_INGR,
CMD_HELP, CMD_HELP,
CMD_VERSION, CMD_VERSION,
}; };
@ -37,6 +39,8 @@ static const std::map<enum cmd_id, std::vector<std::string>> commands = {
{ CMD_LIST, {"list", "ls"} }, { CMD_LIST, {"list", "ls"} },
{ CMD_DEL, {"del", "rm"} }, { CMD_DEL, {"del", "rm"} },
{ CMD_INFO, {"info", "i"} }, { CMD_INFO, {"info", "i"} },
{ CMD_ADD_INGR, {"add-ingr"} },
{ CMD_RM_INGR, {"rm-ingr"} },
{ CMD_HELP, {"help", "-h", "--help"} }, { CMD_HELP, {"help", "-h", "--help"} },
{ CMD_VERSION, {"version", "-v", "--version"} }, { CMD_VERSION, {"version", "-v", "--version"} },
}; };
@ -58,6 +62,8 @@ static inline void print_help(void) {
"\tlist, ls List recipes with filters.\n" "\tlist, ls List recipes with filters.\n"
"\tdel, rm Delete recipe by ID.\n" "\tdel, rm Delete recipe by ID.\n"
"\tinfo Show recipe information.\n" "\tinfo Show recipe information.\n"
"\tadd-ingr Add ingredient to a recipe.\n"
"\trm-ingr Remove ingredient from a recipe.\n"
"\thelp, -h, --help Show this help information.\n" "\thelp, -h, --help Show this help information.\n"
"\tversion, -v, --version Show version information.\n" "\tversion, -v, --version Show version information.\n"
<< std::endl; << std::endl;

View File

@ -167,3 +167,60 @@ int cmd_info(const int id) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
int cmd_add_ingr(const int recipe_id, const char *ingredients) {
db db;
std::vector<std::string> ingr_list = split(ingredients, ",");
db.open();
if(not db.recipe_exists(recipe_id)) {
std::cerr << "Recipe with ID " << recipe_id << " does not exist." << std::endl;
db.close();
return EXIT_FAILURE;
}
for(auto &i : ingr_list) {
int ingr_id;
trim(i);
if(not db.ingredient_exists(i))
ingr_id = db.add_ingredient(i);
else
ingr_id = db.get_ingredient_id(i);
db.conn_recipe_ingredient(recipe_id, ingr_id);
}
db.close();
return EXIT_SUCCESS;
}
int cmd_rm_ingr(const int recipe_id, const char *ingredients) {
db db;
std::vector<std::string> ingr_list = split(ingredients, ",");
db.open();
if(not db.recipe_exists(recipe_id)) {
std::cerr << "Recipe with ID " << recipe_id << " does not exist." << std::endl;
db.close();
return EXIT_FAILURE;
}
for(auto &i : ingr_list) {
int ingr_id;
trim(i);
if(not db.ingredient_exists(i)) {
std::cerr << "Could not find ingredient '" << i << "'. Skipping!" << std::endl;
continue;
}
ingr_id = db.get_ingredient_id(i);
db.disconn_recipe_ingredient(recipe_id, ingr_id);
}
db.close();
return EXIT_SUCCESS;
}

View File

@ -21,3 +21,5 @@ int cmd_add(void);
int cmd_list(int argc, char *argv[]); int cmd_list(int argc, char *argv[]);
int cmd_delete(int argc, char *argv[]); int cmd_delete(int argc, char *argv[]);
int cmd_info(const int id); int cmd_info(const int id);
int cmd_add_ingr(const int recipe_id, const char *ingredients);
int cmd_rm_ingr(const int recipe_id, const char *ingredients);

View File

@ -101,7 +101,7 @@ int db::add_recipe(const std::string &name, const std::string &description) {
if(not sqlite_db) if(not sqlite_db)
throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__)); throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__));
if(sqlite3_exec(sqlite_db, std::format("INSERT INTO recipes(name,description) VALUES('{}','{}');", name, description).c_str(), if(sqlite3_exec(sqlite_db, std::format("INSERT OR IGNORE INTO recipes(name,description) VALUES('{}','{}');", name, description).c_str(),
nullptr, nullptr, nullptr) not_eq SQLITE_OK) { nullptr, nullptr, nullptr) not_eq SQLITE_OK) {
throw std::runtime_error("Failed to insert new recipe into database."); throw std::runtime_error("Failed to insert new recipe into database.");
} }
@ -251,7 +251,7 @@ int db::add_ingredient(const std::string &name) {
if(not sqlite_db) if(not sqlite_db)
throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__)); throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__));
if(sqlite3_exec(sqlite_db, std::format("INSERT INTO ingredients(name) VALUES(lower('{}'));", name).c_str(), if(sqlite3_exec(sqlite_db, std::format("INSERT OR IGNORE INTO ingredients(name) VALUES(lower('{}'));", name).c_str(),
nullptr, nullptr, nullptr) not_eq SQLITE_OK) { nullptr, nullptr, nullptr) not_eq SQLITE_OK) {
throw std::runtime_error(std::format("Failed to instert ingredient '{}'.", name)); throw std::runtime_error(std::format("Failed to instert ingredient '{}'.", name));
} }
@ -280,7 +280,7 @@ int db::add_tag(const std::string &name) {
if(not sqlite_db) if(not sqlite_db)
throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__)); throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__));
if(sqlite3_exec(sqlite_db, std::format("INSERT INTO tags(name) VALUES('{}');", name).c_str(), if(sqlite3_exec(sqlite_db, std::format("INSERT OR IGNORE INTO tags(name) VALUES('{}');", name).c_str(),
nullptr, nullptr, nullptr) not_eq SQLITE_OK) { nullptr, nullptr, nullptr) not_eq SQLITE_OK) {
throw std::runtime_error(std::format("Failed to insert tag '{}'", name)); throw std::runtime_error(std::format("Failed to insert tag '{}'", name));
} }
@ -309,18 +309,28 @@ void db::conn_recipe_ingredient(int recipe_id, int ingredient_id) {
if(not sqlite_db) if(not sqlite_db)
throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__)); throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__));
if(sqlite3_exec(sqlite_db, std::format("INSERT INTO recipe_ingredient(recipe_id, ingredient_id) VALUES({},{});", recipe_id, ingredient_id).c_str(), if(sqlite3_exec(sqlite_db, std::format("INSERT OR IGNORE INTO recipe_ingredient(recipe_id, ingredient_id) VALUES({},{});", recipe_id, ingredient_id).c_str(),
nullptr, nullptr, nullptr) not_eq SQLITE_OK) { nullptr, nullptr, nullptr) not_eq SQLITE_OK) {
throw std::runtime_error(std::format("Failed to connect recipe with ID {} to ingredient with ID {}", throw std::runtime_error(std::format("Failed to connect recipe with ID {} to ingredient with ID {}",
recipe_id, ingredient_id)); recipe_id, ingredient_id));
} }
} }
void db::disconn_recipe_ingredient(int recipe_id, int ingredient_id) {
if(not sqlite_db)
throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__));
if(sqlite3_exec(sqlite_db, std::format("DELETE FROM recipe_ingredient WHERE recipe_id={} AND ingredient_id={};", recipe_id, ingredient_id).c_str(),
nullptr, nullptr, nullptr) not_eq SQLITE_OK) {
throw std::runtime_error(std::format("Failed to disconnect recipe with ID {} from ingredient with ID {}.", recipe_id, ingredient_id));
}
}
void db::conn_recipe_tag(int recipe_id, int tag_id) { void db::conn_recipe_tag(int recipe_id, int tag_id) {
if(not sqlite_db) if(not sqlite_db)
throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__)); throw std::runtime_error(std::format("{}: Database not open! Please contact a developer.", __PRETTY_FUNCTION__));
if(sqlite3_exec(sqlite_db, std::format("INSERT INTO recipe_tag(recipe_id, tag_id) VALUES({},{});", recipe_id, tag_id).c_str(), if(sqlite3_exec(sqlite_db, std::format("INSERT OR IGNORE INTO recipe_tag(recipe_id, tag_id) VALUES({},{});", recipe_id, tag_id).c_str(),
nullptr, nullptr, nullptr) not_eq SQLITE_OK) { nullptr, nullptr, nullptr) not_eq SQLITE_OK) {
throw std::runtime_error(std::format("Failed to connect recipe with ID {} to tag with ID {}", throw std::runtime_error(std::format("Failed to connect recipe with ID {} to tag with ID {}",
recipe_id, tag_id)); recipe_id, tag_id));

View File

@ -95,5 +95,6 @@ public:
} }
void conn_recipe_ingredient(int recipe_id, int ingredient_id); void conn_recipe_ingredient(int recipe_id, int ingredient_id);
void disconn_recipe_ingredient(int recipe_id, int ingredient_id);
void conn_recipe_tag(int recipe_id, int tag_id); void conn_recipe_tag(int recipe_id, int tag_id);
}; };

View File

@ -50,6 +50,12 @@ int main(int argc, char *argv[]) {
case CMD_INFO: case CMD_INFO:
ret = cmd_info(std::stoi(argv[2])); ret = cmd_info(std::stoi(argv[2]));
break; break;
case CMD_ADD_INGR:
ret = cmd_add_ingr(std::stoi(argv[2]), argv[3]);
break;
case CMD_RM_INGR:
ret = cmd_rm_ingr(std::stoi(argv[2]), argv[3]);
break;
case CMD_HELP: case CMD_HELP:
print_help(); print_help();
break; break;