diff --git a/CMakeLists.txt b/CMakeLists.txt index e2f8f5f..94b18d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 3.7) project (whyblocked - VERSION 0.5.0 + VERSION 0.6.0 LANGUAGES CXX ) diff --git a/src/interface_text.cpp b/src/interface_text.cpp new file mode 100644 index 0000000..e739c22 --- /dev/null +++ b/src/interface_text.cpp @@ -0,0 +1,181 @@ +/* This file is part of whyblocked. + * Copyright © 2018 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "version.hpp" +#include "whyblocked.hpp" + +using std::cout; +using std::cerr; +using std::cin; + +const void whyblocked_text::print_help() +{ + cout << "Type add, remove, view or details. Or just the first letter.\n"; + cout << "Type help or h to show this help. Type quit or q to quit the program.\n"; +} + +const bool whyblocked_text::start() +{ + bool keeprunning = true; + + cout << "This is whyblocked " << global::version << ".\n"; + print_help(); + while (keeprunning) + { + string answer = ""; + cout << ": "; + cin >> answer; + switch (answer[0]) + { + case 'a': + case 'A': + { + string user, reason; + int blocked = -1; + cout << "User or instance: "; + cin >> user; + while (blocked == -1) + { + cout << "Blocked(b) or silenced(s): "; + cin >> answer; + if (answer[0] == 'b' || answer[0] == 'B') + { + blocked = 1; + } + else if (answer[0] == 's' || answer[0] == 'S') + { + blocked = 0; + } + } + cout << "Reason: "; + cin.ignore(); + std::getline(cin, reason, '\n'); + + if (add_block(user, blocked, reason)) + { + cout << user << " added.\n"; + } + + while (true) + { + cout << "Add receipt? [y/n] "; + cin >> answer; + if (answer[0] == 'y' || answer[0] == 'Y') + { + string url; + cout << "URL: "; + cin >> url; + + if (add_url(user, url)) + { + cout << "Receipt added.\n"; + } + } + else if (answer[0] == 'n' || answer[0] == 'N') + { + break; + } + else + { + continue; + } + } + break; + } + case 'r': + case 'R': + { + string user; + cout << "User or instance: "; + cin >> user; + + if (remove(user)) + { + cout << user << " removed.\n"; + } + break; + } + case 'v': + case 'V': + { + result_view result; + if (view(result)) + { + for (const std::tuple &line : result) + { + if (std::get<1>(line) == 1) + { + cout << " Blocked: "; + } + else + { + cout << "Silenced: "; + } + cout << std::get<0>(line) << " because: "; + cout << std::get<2>(line) << '\n'; + } + } + break; + } + case 'd': + case 'D': + { + cout << "User or instance: "; + cin >> answer; + { + result_details result; + if (details(answer, result)) + { + cout << answer << " is "; + if (std::get<0>(result) == 1) + { + cout << "blocked, because: "; + } + else if (std::get<0>(result) == 0) + { + cout << "silenced, because: "; + } + cout << std::get<1>(result) << '\n'; + + cout << "Receipts:\n"; + for (const string &url : std::get<2>(result)) + { + cout << " " << url << '\n'; + } + } + } + break; + } + case 'h': + case 'H': + { + print_help(); + break; + } + case 'q': + case 'Q': + { + keeprunning = false; + break; + } + default: + cout << "Response not understood.\n"; + } + } + + return true; +} diff --git a/src/whyblock.cpp b/src/whyblock.cpp deleted file mode 100644 index 0fc946e..0000000 --- a/src/whyblock.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// CC-0, tastytea - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using std::string; -using std::cout; -using std::cerr; -using std::cin; -namespace fs = std::experimental::filesystem; - -string get_filepath() -{ - string filepath; - xdgHandle xdg; - xdgInitHandle(&xdg); - filepath = xdgDataHome(&xdg); - xdgWipeHandle(&xdg); - - filepath += "/whyblocked"; - if (!fs::exists(filepath)) - { - fs::create_directory(filepath); - } - filepath += "/database.sqlite"; - if (!fs::exists(filepath)) - { - sqlite::connection con(filepath); - sqlite::execute(con, "CREATE TABLE blocks(user TEXT PRIMARY KEY, " - "blocked INTEGER, reason TEXT);", true); - sqlite::execute(con, "CREATE TABLE urls(user TEXT, url TEXT);", true); - } - - return filepath; -} - -const void print_help() -{ - cout << "Type add, remove, view or details. Or just the first letter.\n"; - cout << "Type help or h to show this help. Type quit or q to quit the program.\n"; -} - -int main(int argc, char *argv[]) -{ - try - { - sqlite::connection con(get_filepath()); - bool keeprunning = true; - - cout << "This is whyblocked " << global::version << ".\n"; - print_help(); - while (keeprunning) - { - string answer = ""; - cout << ": "; - cin >> answer; - switch (answer[0]) - { - case 'a': - case 'A': - { - string user, reason; - int blocked = -1; - cout << "User or instance: "; - cin >> user; - while (blocked == -1) - { - cout << "Blocked(b) or silenced(s): "; - cin >> answer; - if (answer[0] == 'b' || answer[0] == 'B') - { - blocked = 1; - } - else if (answer[0] == 's' || answer[0] == 'S') - { - blocked = 0; - } - } - cout << "Reason: "; - cin.ignore(); - std::getline(cin, reason, '\n'); - - sqlite::execute ins(con, "INSERT INTO blocks VALUES(?, ?, ?);"); - ins % user % blocked % reason; - ins(); - cout << user << " added.\n"; - - while (true) - { - cout << "Add receipt? [y/n] "; - cin >> answer; - if (answer[0] == 'y' || answer[0] == 'Y') - { - string url; - cout << "URL: "; - cin >> url; - - sqlite::execute ins(con, "INSERT INTO urls VALUES(?, ?);"); - ins % user % url; - ins(); - cout << "Receipt added.\n"; - } - else if (answer[0] == 'n' || answer[0] == 'N') - { - break; - } - else - { - continue; - } - } - break; - } - case 'r': - case 'R': - { - string user; - cout << "User or instance: "; - cin >> user; - - sqlite::execute rm_blocks(con, "DELETE FROM blocks WHERE user = ?;"); - sqlite::execute rm_urls(con, "DELETE FROM urls WHERE user = ?;"); - rm_blocks % user; - rm_urls % user; - rm_blocks(); - rm_urls(); - cout << user << " removed.\n"; - break; - } - case 'v': - case 'V': - { - sqlite::query q(con, "SELECT * FROM blocks;"); - boost::shared_ptr result = q.get_result(); - while(result->next_row()) - { - if (result->get_int(1) == 1) - { - cout << " Blocked: "; - } - else - { - cout << "Silenced: "; - } - cout << result->get_string(0) << " because: "; - cout << result->get_string(2) << '\n'; - } - break; - } - case 'd': - case 'D': - { - cout << "User or instance: "; - cin >> answer; - { - sqlite::query q(con, "SELECT * FROM blocks WHERE " - "user = \'" + answer + "\';"); - boost::shared_ptr result = q.get_result(); - cout << answer << " is "; - if (!result->next_row()) - { - cout << "not in the database.\n"; - break; - } - if (result->get_int(1) == 1) - { - cout << "blocked, because: "; - } - else if (result->get_int(1) == 0) - { - cout << "silenced, because: "; - } - cout << result->get_string(2) << '\n'; - } - { - cout << "Receipts:\n"; - sqlite::query q(con, "SELECT * FROM urls WHERE user = \'" + answer + "\';"); - boost::shared_ptr result = q.get_result(); - while(result->next_row()) - { - cout << " " << result->get_string(1) << '\n'; - } - } - break; - case 'h': - case 'H': - print_help(); - break; - case 'q': - case 'Q': - keeprunning = false; - break; - } - default: - cout << "Response not understood.\n"; - } - } - } - catch(const std::exception &e) - { - cerr << "An error occurred: " << e.what() << std::endl; - return 1; - } - - return 0; -} diff --git a/src/whyblocked.cpp b/src/whyblocked.cpp new file mode 100644 index 0000000..2912b80 --- /dev/null +++ b/src/whyblocked.cpp @@ -0,0 +1,184 @@ +/* This file is part of whyblocked. + * Copyright © 2018 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "whyblocked.hpp" + +using std::cerr; +namespace fs = std::experimental::filesystem; + +const string get_filepath() +{ + string filepath; + xdgHandle xdg; + xdgInitHandle(&xdg); + filepath = xdgDataHome(&xdg); + xdgWipeHandle(&xdg); + + filepath += "/whyblocked"; + if (!fs::exists(filepath)) + { + fs::create_directory(filepath); + } + filepath += "/database.sqlite"; + if (!fs::exists(filepath)) + { + sqlite::connection con(filepath); + sqlite::execute(con, "CREATE TABLE blocks(user TEXT PRIMARY KEY, " + "blocked INTEGER, reason TEXT);", true); + sqlite::execute(con, "CREATE TABLE urls(user TEXT, url TEXT);", true); + } + + return filepath; +} + +const bool add_block(const string &user, const int blocked, const string &reason) +{ + try + { + sqlite::connection con(get_filepath()); + sqlite::execute ins(con, "INSERT INTO blocks VALUES(?, ?, ?);"); + ins % user % blocked % reason; + ins(); + } + catch (const std::exception &e) + { + cerr << "An error occurred: " << e.what() << std::endl; + return false; + } + + return true; +} + +const bool add_url(const string &user, const string &url) +{ + try + { + sqlite::connection con(get_filepath()); + sqlite::execute ins(con, "INSERT INTO urls VALUES(?, ?);"); + ins % user % url; + ins(); + } + catch (const std::exception &e) + { + cerr << "An error occurred: " << e.what() << std::endl; + return false; + } + + return true; +} + +const bool remove(const string &user) +{ + try + { + sqlite::connection con(get_filepath()); + sqlite::execute rm_blocks(con, "DELETE FROM blocks WHERE user = ?;"); + sqlite::execute rm_urls(con, "DELETE FROM urls WHERE user = ?;"); + rm_blocks % user; + rm_urls % user; + rm_blocks(); + rm_urls(); + } + catch (const std::exception &e) + { + cerr << "An error occurred: " << e.what() << std::endl; + return false; + } + + return true; +} + +const bool view(result_view &result) +{ + try + { + sqlite::connection con(get_filepath()); + sqlite::query q(con, "SELECT * FROM blocks;"); + boost::shared_ptr res = q.get_result(); + while(res->next_row()) + { + result.push_back( + { + res->get_string(0), + res->get_int(1), + res->get_string(2) + }); + } + } + catch (const std::exception &e) + { + cerr << "An error occurred: " << e.what() << std::endl; + return false; + } + + return true; +} + +const bool details(const string &user, result_details &result) +{ + try + { + sqlite::connection con(get_filepath()); + sqlite::query q_blocks(con, "SELECT * FROM blocks WHERE user = \'" + user + "\';"); + boost::shared_ptr res_blocks = q_blocks.get_result(); + + sqlite::query q_urls(con, "SELECT * FROM urls WHERE user = \'" + user + "\';"); + boost::shared_ptr res_urls = q_urls.get_result(); + + if (!res_blocks->next_row()) + { + cerr << user << " is not in the database.\n"; + return false; + } + + std::vector urls; + while (res_urls->next_row()) + { + urls.push_back(res_urls->get_string(1)); + } + + result = + { + res_blocks->get_int(1), + res_blocks->get_string(2), + urls + }; + } + catch (const std::exception &e) + { + cerr << "An error occurred: " << e.what() << std::endl; + return false; + } + + return true; +} + +int main(int argc, char *argv[]) +{ + whyblocked_text::start(); + + return 0; +} diff --git a/src/whyblocked.hpp b/src/whyblocked.hpp new file mode 100644 index 0000000..c677b9b --- /dev/null +++ b/src/whyblocked.hpp @@ -0,0 +1,41 @@ +/* This file is part of whyblocked. + * Copyright © 2018 tastytea + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef WHYBLOCKED_HPP +#define WHYBLOCKED_HPP + +#include +#include +#include + +using std::string; +using result_view = std::vector>; +using result_details = std::tuple>; + +const string get_filepath(); +const bool add_block(const string &user, const int blocked, const string &reason); +const bool add_url(const string &user, const string &url); +const bool remove(const string &user); +const bool view(result_view &result); +const bool details(const string &user, result_details &result); + +namespace whyblocked_text +{ + const void print_help(); + const bool start(); +} + +#endif // WHYBLOCKED_HPP