aboutsummaryrefslogtreecommitdiff
path: root/src/api.c
diff options
context:
space:
mode:
authorEmil2023-08-04 09:13:47 -0600
committerEmil2023-08-04 09:13:47 -0600
commit935243d8b4ea992c50315f0c8fcb300365a5762d (patch)
treec22d800773997b7b267d5d6cba5931f22ee2be64 /src/api.c
downloademil-probotic-master.tar.xz
emil-probotic-master.tar.zst
Initial commitHEADmaster
Diffstat (limited to 'src/api.c')
-rw-r--r--src/api.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/src/api.c b/src/api.c
new file mode 100644
index 0000000..09799a5
--- /dev/null
+++ b/src/api.c
@@ -0,0 +1,230 @@
+#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 = "<no link available>"; }
+ 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);
+}