#define DBFILE "probotic_data.sqlite" #define stmt_prepare(stmt) \ sqlite3_prepare_v2(connection, stmt ## _template, -1, &stmt, NULL) VARDECL char const * db = DBFILE; VARDECL sqlite3 * connection = NULL; DECL void DBERR(const int l){ if(l != SQLITE_OK && l != SQLITE_ROW && l != SQLITE_DONE) { fprintf(stderr, "sqlite (%d): %s\n", sqlite3_errcode(connection), sqlite3_errmsg(connection)); exit(DB_ERROR); } } DECL int api_init(void) { DBERR(sqlite3_open_v2(db, &connection, SQLITE_OPEN_READWRITE, NULL)); // dont you fucking dare to remove this spacing DBERR(stmt_prepare(remind_stmt)); DBERR(stmt_prepare(set_repo_stmt)); DBERR(stmt_prepare(get_nth_id_stmt)); DBERR(stmt_prepare(new_assignment_stmt)); DBERR(stmt_prepare(purge_assignments_stmt)); DBERR(stmt_prepare(is_no_assignment_stmt)); return 0; } DECL void api_rope(void) { DBERR(sqlite3_finalize(remind_stmt)); DBERR(sqlite3_finalize(set_repo_stmt)); DBERR(sqlite3_finalize(get_nth_id_stmt)); DBERR(sqlite3_finalize(new_assignment_stmt)); DBERR(sqlite3_finalize(purge_assignments_stmt)); DBERR(sqlite3_finalize(is_no_assignment_stmt)); sqlite3_close(connection); } DECL void rope(void) { if (session) { irc_destroy_session(session); } api_rope(); } DECL char * remind(char * who) { char * r; char * title; char * desc; char * repo; DBERR(sqlite3_reset(remind_stmt)); DBERR(sqlite3_bind_text(remind_stmt, 1, who, -1, SQLITE_STATIC)); const int i = sqlite3_step(remind_stmt); DBERR(i); if (i == SQLITE_ROW) { title = (char *) sqlite3_column_text(remind_stmt, 0); title = strdup(title); desc = (char *) sqlite3_column_text(remind_stmt, 1); if (desc) { desc = strdup(desc); } else { desc = ""; } repo = (char *) sqlite3_column_text(remind_stmt, 3); if (repo) { repo = strdup(repo); } else { repo = ""; } asprintf(&r, IRC_RED "%s: " IRC_YELLOW "%s" IRC_GREEN " (@" IRC_BLUE "%s" IRC_GREEN ")" IRC_STOP, title, desc, repo); } else { r = strdup(IRC_RED "No current assignment." IRC_STOP); } return r; } DECL void set_repo(char const * const who, char const * const link) { DBERR(sqlite3_reset(set_repo_stmt)); DBERR(sqlite3_bind_text(set_repo_stmt, 1, link, -1, SQLITE_STATIC)); DBERR(sqlite3_bind_text(set_repo_stmt, 2, who, -1, SQLITE_STATIC)); DBERR(sqlite3_step(set_repo_stmt)); } DECL int rtos(void * data, int argc, char** argv, char** colname ){ (void) colname; char ** r = (char**)data; size_t data_len = 0; for(int i = 0; i < argc; i++) { if(argv[i]) { data_len += strlen(argv[i]); } else { /* strlen("NULL") == 4 */ data_len += 4; } /* strlen("|") * 2 == 2 */ data_len += 2; } ++data_len; *r = (char *)calloc(data_len, sizeof(char)); for(int i = 0; i < argc; i++){ strcat(*r, "|"); if(argv[i]){ strcat(*r, argv[i]); } else { strcat(*r, "NULL"); } } strcat(*r, "|\n"); return 0; } DECL char * dump() { char* errmsg; char* r = NULL; DBERR(sqlite3_exec(connection, dump_stmt, rtos, &r, &errmsg)); return r; } DECL char * raw(char const * const sql) { char* errmsg; char *r = NULL; sqlite3_exec(connection, sql, rtos, &r, &errmsg); if (errmsg){ free(r); r = errmsg; } else { strcat(r, "\00"); } return r; } DECL int get_project_count_callback(void* data, int argc, char** argv, char** colname) { (void)argc; (void)colname; int* count = (int*)data; *count = atoi(argv[0]); return 0; } DECL int get_project_count() { int r = 0; char const * sql = "SELECT COUNT(*) FROM project;"; DBERR(sqlite3_exec(connection, sql, get_project_count_callback, &r, NULL)); return r; } DECL int get_nth_id(const int i) { int r; DBERR(sqlite3_reset(get_nth_id_stmt)); DBERR(sqlite3_bind_int(get_nth_id_stmt, 1, i)); DBERR(sqlite3_step(get_nth_id_stmt)); r = sqlite3_column_int(get_nth_id_stmt, 0); return r; } DECL void new_assignment(char const * const who, const int project) { DBERR(sqlite3_reset(new_assignment_stmt)); DBERR(sqlite3_bind_text(new_assignment_stmt, 1, who, -1, SQLITE_STATIC)); DBERR(sqlite3_bind_int(new_assignment_stmt, 2, project)); DBERR(sqlite3_step(new_assignment_stmt)); } DECL void random_assign(char const * const who) { int i = rand() % get_project_count(); i = get_nth_id(i); new_assignment(who, i); } DECL void purge_assignments(char const * const who) { DBERR(sqlite3_reset(purge_assignments_stmt)); DBERR(sqlite3_bind_text(purge_assignments_stmt, 1, who, -1, SQLITE_STATIC)); DBERR(sqlite3_step(purge_assignments_stmt)); } DECL int is_no_assignment(char const * const who){ DBERR(sqlite3_reset(is_no_assignment_stmt)); DBERR(sqlite3_bind_text(is_no_assignment_stmt, 1, who, -1, SQLITE_STATIC)); const int e = sqlite3_step(is_no_assignment_stmt); DBERR(e); return (e == SQLITE_DONE); }