From add6b39aece179a0e0ad425af72b8a043a0d3188 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Fri, 17 Mar 2017 19:57:12 +0100 Subject: History querying --- command.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ db.c | 43 +++++++++++++++++++++++++++++++++++++++++++ db.h | 2 +- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/command.c b/command.c index 50b9534..a691171 100644 --- a/command.c +++ b/command.c @@ -253,6 +253,54 @@ static bool cmd_send(struct conn_data *data,const char *tag,const char **args){ return closed; } +static bool cmd_history(struct conn_data *data,const char *tag,const char **args){ + char *endp; + i64 nrequested=strtoll(args[1],&endp,10); + if(args[1][0]=='\0'||*endp!='\0'||nrequested<0){ + debug("Connection fd=%d sent an invalid number for 'history': '%s'",data->fd,args[1]); + return true; + } + + if(data->userid==-1){ + send_error(data->fd,tag,"Not logged in"); + return false; + } + i64 roomid=db_find_room(args[0]); + if(roomid==-1){ + send_error(data->fd,tag,"Room not found"); + return false; + } + if(!db_is_member(roomid,data->userid)){ + send_error(data->fd,tag,"Not in that room"); + return false; + } + + struct db_message_list ml=db_get_messages(roomid,nrequested); + char *buf=NULL; + i64 len=asprintf(&buf,"%s history %" PRIi64 "\n",tag,ml.count); + assert(buf); + bool closed=send_raw_text(data->fd,buf,len); + free(buf); + + if(closed){ + db_nullify_message_list(ml); + return true; + } + + for(i64 i=ml.count-1;i>=0;i--){ + char *username=db_get_username(ml.list[i].userid); + len=asprintf(&buf,"%s history_item %" PRIi64 " %s %" PRIi64 " %s\n", + tag,ml.count-1-i,username,ml.list[i].timestamp,ml.list[i].message); + assert(buf); + closed=send_raw_text(data->fd,buf,len); + free(buf); + if(closed)break; + } + + db_nullify_message_list(ml); + return closed; +} + struct cmd_info{ const char *cmdname; @@ -269,6 +317,7 @@ static const struct cmd_info commands[]={ {"create_room",0,false,cmd_create_room}, {"invite",2,false,cmd_invite}, {"send",2,true,cmd_send}, + {"history",2,false,cmd_history}, }; #define NCOMMANDS (sizeof(commands)/sizeof(commands[0])) diff --git a/db.c b/db.c index f89e628..983080f 100644 --- a/db.c +++ b/db.c @@ -244,6 +244,41 @@ void db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message){ SQLITE(finalize,stmt); } +struct db_message_list db_get_messages(i64 roomid,i64 count){ + sqlite3_stmt *stmt; + SQLITE(prepare_v2,database, + "select user, time, message " + "from Messages " + "where room = ? " + "order by time desc " + "limit ?" + ,-1,&stmt,NULL); + SQLITE(bind_int64,stmt,1,roomid); + SQLITE(bind_int64,stmt,2,count); + + struct db_message_list ml; + i64 cap=count; + ml.count=0; + ml.list=malloc(cap,struct db_message); + + int ret; + while((ret=sqlite3_step(stmt))==SQLITE_ROW){ + if(ml.count==cap){ + die("sqlite gave too many rows while 'limit %" PRIi64 "' was present",count); + } + ml.list[ml.count].roomid=roomid; + ml.list[ml.count].userid=sqlite3_column_int64(stmt,0); + ml.list[ml.count].timestamp=sqlite3_column_int64(stmt,1); + ml.list[ml.count].message=strdup((const char*)sqlite3_column_text(stmt,2)); + ml.count++; + } + + if(ret!=SQLITE_DONE)die_sqlite("sqlite3_step"); + SQLITE(finalize,stmt); + + return ml; +} + void db_nullify_name_id(struct db_name_id ni){ if(ni.name)free(ni.name); @@ -264,3 +299,11 @@ void db_nullify_user_list(struct db_user_list ul){ if(ul.list)free(ul.list); ul.list=NULL; } + +void db_nullify_message_list(struct db_message_list ml){ + for(i64 i=0;i