123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639 |
- /*
- * This file is the main code of Timeless
- * Copyright (C) <2019> <alkeon> [alkeon@autistici.org]
- *
- * Texdi 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, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Texdi 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 timeless. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include "datalite.h"
- #include "json.hpp"
- #include <sqlite3.h>
- #include <iostream>
- #include <fstream>
- #include <vector>
- using namespace std;
- using json = nlohmann::json;
- static int callback(void *NotUsed, int argc, char **argv, char **azColName){
- return 0;
- }
- int datalite::create(){
- sqlite3 * sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- int result = 0;
- if (!rc){
- char *zErrMsg = 0;
- string sql = "DROP TABLE IF EXISTS NEWS; \
- CREATE TABLE NEWS( \
- LINK TEXT NOT NULL, \
- TITLE TEXT NOT NULL, \
- DESCRIPTION TEXT NOT NULL, \
- MARKED INTEGER, \
- UNIQUE (LINK,TITLE,DESCRIPTION) \
- );";
- rc = sqlite3_exec(sq, sql.c_str(), callback, 0, &zErrMsg);
- if (rc == SQLITE_OK)
- result = SQLITE_OK;
- else{
- sqlite3_free(zErrMsg);
- result = rc;
- }
- } else
- result = 1;
-
- sqlite3_close(sq);
- string channel = _file + "_channel";
- rc = sqlite3_open(channel.c_str(), &sq);
- result = 0;
- if (!rc){
- char *zErrMsg = 0;
- string sql = "DROP TABLE IF EXISTS CHANNEL; \
- CREATE TABLE CHANNEL( \
- URL TEXT NOT NULL UNIQUE, \
- TITLE TEXT NOT NULL UNIQUE \
- );";
- rc = sqlite3_exec(sq, sql.c_str(), callback, 0, &zErrMsg);
- if (rc == SQLITE_OK)
- result = SQLITE_OK;
- else{
- sqlite3_free(zErrMsg);
- result = rc;
- }
- } else
- result = 1;
-
- sqlite3_close(sq);
- return result;
- }
- datalite::datalite(const string& file): _file(file){
- _position = 1;
- _last_position = 1;
- int result = create();
- if(result != 0)
- throw datalite::Invalid("Couldn't create database.\n ERROR CODE: " + to_string(result));
- }
- /*
- * Return:
- * 0 : failed
- * 1 : OK
- * 2 : inserted before
- */
- int datalite::insert_row(const string& link, const string& title,
- const string& description){
-
- sqlite3 * sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- int result = 0;
- if (!rc){
- sqlite3_stmt * res;
- string sql = "INSERT INTO NEWS VALUES ('";
- sql += link + "', '" + title + "', '" + description + "', 0);";
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- int step = sqlite3_step(res);
- if(step == SQLITE_CONSTRAINT)
- result = 2;
- else if(step == SQLITE_DONE)
- result = 1;
- else if(step == SQLITE_OK)
- result = 1;
- }else
- result = 2;
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return result;
- }
- /*
- * Return:
- * 0 : failed
- * 1 : OK
- * 2 : inserted before
- */
- int datalite::bulk_insert(const vector<string>& links, const vector<string>& titles,
- const vector<string>& descriptions){
- int result = 0;
- if(links.size() > 0){
- sqlite3 * sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- if (!rc){
- sqlite3_stmt * res;
- string sql = "INSERT OR IGNORE INTO NEWS VALUES ('";
- sql += links[0] + "', '" + titles[0] + "', '"+ descriptions[0] +"', 0)";
- for(unsigned i = 1; i < links.size(); ++i)
- sql += ",('" + links[i] + "', '" + titles[i] + "', '"+ descriptions[i] +"', 0)";
-
- sql+= ";";
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK)
- sqlite3_step(res);
- else
- result = 2;
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- }
- return result;
- }
- int datalite::delete_news(){
- sqlite3 * sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- int result = 0;
- if (!rc){
- sqlite3_stmt * res;
- string sql = "DELETE FROM NEWS WHERE MARKED=0;";
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- int step = sqlite3_step(res);
- if(step == SQLITE_CONSTRAINT)
- result = 2;
- else if(step == SQLITE_DONE)
- result = 1;
- else if(step == SQLITE_OK)
- result = 1;
- }else
- result = 2;
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return result;
- }
- void datalite::show_news(){
- string sql = "SELECT LINK, TITLE, DESCRIPTION, MARKED, rowid FROM NEWS "
- "ORDER BY rowid DESC;";
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- vector<int64_t> vector_positions;
- if (!rc){
- sqlite3_stmt *res;
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- int step = sqlite3_step(res);
- int option = 4;
- int iterations = 0;
- vector<long long> rowids;
- bool repeat = false;
- int i = 0;
- do{
- if(!repeat){
- rowids = vector<long long>();
- i = 0;
- }
- while (step == SQLITE_ROW && i < 3 && !repeat){
- const char * rowid = (char *) sqlite3_column_text(res,4);
- if(rowid != NULL){
- string rowid_s(rowid);
- rowids.push_back(stoll(rowid_s));
- }
- step = sqlite3_step(res);
- ++i;
- }
- int aux = 0;
- if(repeat) repeat = false;
- for(vector<long long>::iterator it = rowids.begin(); it != rowids.end(); ++it){
- cout << "\n" << aux << "----------------" << endl;
- cout << get_one_new(*it) << endl;
- ++aux;
- }
- if(i >= 3){
- cout << "\nUse news number to un/mark one of it" << endl;
- cout << "Do you want more news" << endl;
- cout << "3.- Yes" << endl;
- cout << "4.- No" << endl;
- cin >> option;
- cout << option << endl;
- if(option < 3 && option >= 0){
- vector_positions.push_back(rowids[option]);
- repeat = true;
- option = 3;
-
- }else if(option > 4 or option < 0){
- repeat = true;
- option = 3;
- }
-
- } else
- option = 3;
- ++iterations;
- }while(option == 3 && step == SQLITE_ROW);
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- for(unsigned i = 0; i < vector_positions.size(); ++i)
- set_mark(vector_positions[i]);
- }
- int datalite::get_mark(int64_t position){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- string link = "0";
- if (!rc){
-
- sqlite3_stmt *res;
- string sql = "SELECT MARKED FROM NEWS WHERE rowid=" + to_string(position);
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK){
- sqlite3_step(res);
- const char * marked = (char *) sqlite3_column_text(res,0);
- if(marked != NULL) link = string(marked);
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return stoi(link);
- }
- int datalite::set_mark(int64_t position){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- int result = 0;
- if (!rc){
- sqlite3_stmt *res;
- string sql = "UPDATE NEWS SET MARKED=" + to_string((get_mark(position)
- + 1) % 2) + " where rowid=" + to_string(position);
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
-
- if(rc == SQLITE_OK){
- sqlite3_step(res);
- result = SQLITE_OK;
- } else result = rc;
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return result;
- }
- /*
- * Error: line.size = 0
- * Success: line.size > 0
- *
- */
- string datalite::get_new_line(){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- string link;
- if (!rc){
-
- sqlite3_stmt *res;
- string sql = "SELECT LINK FROM NEWS WHERE rowid=" + to_string(_position);
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- sqlite3_step(res);
- const char * retri = (char *) sqlite3_column_text(res,0);
- if(retri != NULL){
-
- link = string(retri);
- ++_position;
- }
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return link;
- }
- /*
- * Error: line.size = 0
- * Success: line.size > 0
- *
- */
- string datalite::get_new_channel(){
- std::ifstream in(_file + "_channel");
- json j = json::parse(in);
- string channel = j["urls"].at(_position_channel);
- ++_position_channel;
- return channel;
- }
- /*
- * Error: line.size = 0
- * Success: line.size > 0
- *
- */
- string datalite::get_link(int64_t position){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- string link;
- if (!rc){
-
- sqlite3_stmt *res;
- string sql = "SELECT LINK FROM NEWS WHERE rowid=" + to_string(position);
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- sqlite3_step(res);
- const char * retri = (char *) sqlite3_column_text(res,0);
- if(retri != NULL) link = string(retri);
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return link;
- }
- /*
- * Error: line.size = 0
- * Success: line.size > 0
- *
- */
- string datalite::get_channel(int64_t position){
- std::ifstream in(_file + "_channel");
- json j = json::parse(in);
- return j["urls"].at(position);
- }
- bool datalite::is_valid_line(){
- bool valid = false;
- if(_position <= _last_position) valid = true;
- else {
- _last_position = get_last_position();
- if(_position <= _last_position) valid = true;
- else valid = false;
- }
- return valid;
- }
- bool datalite::is_valid_channel(){
- bool valid = false;
- if(_position_channel < _last_position_channel) valid = true;
- else {
- _last_position_channel = get_last_channel();
- if(_position_channel <= _last_position_channel) valid = true;
- else valid = false;
- }
- return valid;
- }
- /*
- * Return rowid if worked and -1 if doesn't
- *
- */
- int64_t datalite::get_last_position(){
- if(_position > _last_position){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- if (!rc){
- sqlite3_stmt *res;
- string sql = "SELECT rowid FROM NEWS WHERE rowid=(SELECT MAX(rowid)"
- " FROM NEWS)";
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- sqlite3_step(res);
- const char *retri = (char *) sqlite3_column_text(res,0);
- if(retri != NULL){
- string text(retri);
- _last_position = stoll(text);
- }
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- }
- return _last_position;
- }
- /*
- * Return rowid if worked and -1 if doesn't
- *
- */
- int64_t datalite::get_last_channel(){
- if(_position_channel > _last_position_channel){
-
- std::ifstream in(_file + "_channel");
- json j = json::parse(in);
- int i = -1;
- for(auto json_building : j["urls"]){
- ++i;
- }
-
- _last_position_channel = i;
- }
- return _last_position_channel;
- }
- void datalite::set_position(int64_t position){
- if(position <= _last_position) _position = position;
- else {
- _last_position = get_last_position();
- if(position <= _last_position) _position = position;
- else throw datalite::Invalid("Rowid greater than table rowid");
- }
- }
- datalite& datalite::operator=(datalite& src){
- if (this != &src) {
- _file = src.get_file();
- _position = src.get_position();
- _last_position = src.get_last_position();
- }
- return *this;
- }
- string datalite::get_title(const int64_t& position){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- string link;
- if (!rc){
- sqlite3_stmt *res;
- string sql = "SELECT TITLE FROM COB WHERE rowid=" + to_string(position);
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
-
- sqlite3_step(res);
- const char * title = (char *) sqlite3_column_text(res,0);
- if(title != NULL)
- link = string(title);
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return link;
- }
- string datalite::get_metainfo(const int64_t& position){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- string link;
- if (!rc){
- sqlite3_stmt *res;
- string sql = "SELECT DESCRIPTION FROM COB WHERE rowid=" + to_string(position);
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
-
- sqlite3_step(res);
- const char * description = (char *) sqlite3_column_text(res,0);
- if(description != NULL)
- link = string(description);
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return link;
- }
- void datalite::insert_datalite(datalite& db){
- int64_t position = db.get_position();
- db.set_position(1);
- cout << "Wait until insertion stop" << endl;
- while(db.is_valid_line()){
- string title = db.get_title(db.get_position());
- string metainfo = db.get_metainfo(db.get_position());
- insert_row(db.get_new_line(), title, metainfo);
- }
- cout << "Insertion finished" << endl;
- db.set_position(position);
- }
- /*
- * Return:
- * 0 : failed
- * 1 : OK
- * 2 : cancelled by user
- */
- int datalite::show_unique_database_fields(const string& sql){
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- int result = 0;
- if (!rc){
- sqlite3_stmt *res;
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- int step = sqlite3_step(res);
- int option;
- do{
- int i = 0;
- while (step == SQLITE_ROW && i < 10) {
- char * text_c = (char *) sqlite3_column_text(res, 0);
- string text(text_c);
- if(_found_links.find(text) == _found_links.end()){
- cout << text << endl;
- _found_links.insert(text);
- }
- step = sqlite3_step(res);
- ++i;
- }
- if(i > 5){
- cout << "Do you want more links?\n"
- "1.- Yes\n"
- "2.- No" << endl;
- cin >> option;
- } else
- option = 1;
-
- }while(option == 1 && step == SQLITE_ROW);
- result = option;
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return result;
- }
- string datalite::get_one_new(int64_t position){
- string result;
- sqlite3 *sq;
- int rc = sqlite3_open(_file.c_str(), &sq);
- string link;
- if (!rc){
-
- sqlite3_stmt *res;
- string sql = "SELECT TITLE, LINK, DESCRIPTION, MARKED FROM NEWS WHERE rowid=" + to_string(position);
- rc = sqlite3_prepare_v2(sq, sql.c_str(), -1, &res, 0);
- if (rc == SQLITE_OK) {
- sqlite3_step(res);
- char * retri = (char *) sqlite3_column_text(res, 3);
- string text(retri);
- if(text[0]== '1')
- cout << "\n MARKED(*)" << endl;
-
- retri = (char *) sqlite3_column_text(res, 0);
- if(retri != NULL) link = string(retri);
- result += "\n" + link + "\n\n";
- retri = (char *) sqlite3_column_text(res, 1);
- if(retri != NULL) link = string(retri);
- result += link + "\n\n";
- retri = (char *) sqlite3_column_text(res, 2);
- if(retri != NULL) link = string(retri);
- result += link;
- }
- sqlite3_finalize(res);
- }
- sqlite3_close(sq);
- return result;
- }
|