aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command.c28
-rw-r--r--db.c35
-rw-r--r--db.h2
3 files changed, 53 insertions, 12 deletions
diff --git a/command.c b/command.c
index 3d406e1..e4d75d3 100644
--- a/command.c
+++ b/command.c
@@ -1,6 +1,7 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
+#include <limits.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
@@ -238,11 +239,14 @@ 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){
+static bool history_cmd_helper(
+ struct conn_data *data,const char *tag,const char **args,
+ const char *cmdname,i64 beforeid){
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]);
+ debug("Connection fd=%d sent an invalid number for '%s': '%s'",
+ data->fd,cmdname,args[1]);
return true;
}
@@ -261,7 +265,7 @@ static bool cmd_history(struct conn_data *data,const char *tag,const char **args
return false;
}
- struct db_message_list ml=db_get_messages(roomid,nrequested);
+ struct db_message_list ml=db_get_messages_before(roomid,nrequested,beforeid);
char *buf=NULL;
i64 len=asprintf(&buf,"%s history %" PRIi64 "\n",tag,ml.count);
bool closed=net_send_raw_text(data->fd,buf,len);
@@ -286,6 +290,23 @@ static bool cmd_history(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){
+ return history_cmd_helper(data,tag,args,"history",-1);
+}
+
+static bool cmd_history_before(struct conn_data *data,const char *tag,const char **args){
+ char *endp;
+ i64 beforeid=strtoll(args[2],&endp,10);
+ if(args[2][0]=='\0'||*endp!='\0'){
+ debug("Connection fd=%d sent an invalid id for 'history_before': '%s'",
+ data->fd,args[2]);
+ return true;
+ }
+ if(beforeid<0)beforeid=INT64_MAX;
+
+ return history_cmd_helper(data,tag,args,"history_before",beforeid);
+}
+
static bool cmd_ping(struct conn_data *data,const char *tag,const char **args){
(void)args;
return net_send_pong(data->fd,tag);
@@ -353,6 +374,7 @@ static const struct cmd_info commands[]={
{"invite",2,false,cmd_invite},
{"send",2,true,cmd_send},
{"history",2,false,cmd_history},
+ {"history_before",3,false,cmd_history_before},
{"ping",0,false,cmd_ping},
{"is_online",1,false,cmd_is_online},
{"firebase_token",1,false,cmd_firebase_token},
diff --git a/db.c b/db.c
index a193b24..f48148e 100644
--- a/db.c
+++ b/db.c
@@ -304,18 +304,35 @@ void db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message){
}
struct db_message_list db_get_messages(i64 roomid,i64 count){
+ return db_get_messages_before(roomid,count,-1);
+}
+
+struct db_message_list db_get_messages_before(i64 roomid,i64 count,i64 beforeid){
assert(count>=0);
sqlite3_stmt *stmt;
- SQLITE(prepare_v2,database,
- "select id, 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);
+ if(beforeid<0){
+ SQLITE(prepare_v2,database,
+ "select id, 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);
+ } else {
+ SQLITE(prepare_v2,database,
+ "select id, user, time, message "
+ "from Messages "
+ "where room = ? and time < (select time from Messages where id = ?) "
+ "order by time desc "
+ "limit ?"
+ ,-1,&stmt,NULL);
+ SQLITE(bind_int64,stmt,1,roomid);
+ SQLITE(bind_int64,stmt,2,beforeid);
+ SQLITE(bind_int64,stmt,3,count);
+ }
struct db_message_list ml;
i64 cap=count;
diff --git a/db.h b/db.h
index 6bc2b62..6b1d92b 100644
--- a/db.h
+++ b/db.h
@@ -60,6 +60,8 @@ bool db_delete_token(i64 userid,const char *token);
void db_create_message(i64 roomid,i64 userid,i64 timestamp,const char *message);
struct db_message_list db_get_messages(i64 roomid,i64 count); // gets latest `count` messages
+// if beforeid<0, same as db_get_messages
+struct db_message_list db_get_messages_before(i64 roomid,i64 count,i64 beforeid);
void db_nullify_name_id(struct db_name_id ni);
void db_nullify_room_list(struct db_room_list rl);