diff options
Diffstat (limited to 'weechat')
| -rw-r--r-- | weechat/tomsg.c | 238 | 
1 files changed, 178 insertions, 60 deletions
diff --git a/weechat/tomsg.c b/weechat/tomsg.c index df6e067..bd01165 100644 --- a/weechat/tomsg.c +++ b/weechat/tomsg.c @@ -3,6 +3,7 @@  #include <stdlib.h>  #include <string.h>  #include <sys/socket.h> +#include <sys/time.h>  #include <unistd.h>  #include <errno.h>  #include <assert.h> @@ -32,6 +33,7 @@ struct roomdata{  	struct t_gui_buffer *buffer;  	struct t_gui_nick_group *buffer_nickgroup;  	int nmembers; +	int next_pending_id;  	struct conndata *conn;  // do not free  }; @@ -50,15 +52,8 @@ struct conndata{  	i64 linebuf_sz,linebuf_len;  	char *linebuf; - -	// struct t_hashtable *msgtable;  // msgid -> msgdata  }; -// struct msgdata{ -//     char *username; -//     char *message; -// }; -  static struct t_weechat_plugin *weechat_plugin; @@ -66,20 +61,27 @@ static struct t_hashtable *conntable;  // fd -> conndata  static struct t_hashtable *roomtable;  // roomname -> roomdata +static i64 gettimestamp(void) { +	struct timeval tv; +	gettimeofday(&tv,NULL); +	return (i64)tv.tv_sec*1000000+tv.tv_usec; +} + +  static void display_message(  	struct roomdata *room,  	int64_t timestamp,  	const char *username,  	const char *message,  	int64_t msgid, -	bool is_reply +	bool is_reply, +	bool is_history  ) {  	char tags[128]; -	int pos = snprintf(tags, sizeof tags, "tomsgid_%" PRIi64, msgid); -	strcpy(tags + pos, room->nmembers <= 2 ? ",notify_private" : ",notify_message"); -	if (is_reply) { -		strcat(tags, ",tomsg_reply"); -	} +	snprintf(tags, sizeof tags, "tomsgid_%" PRIi64 "%s%s", +			msgid, +			room->nmembers == 2 && !is_history ? ",notify_private" : ",notify_message", +			is_reply ? ",tomsg_reply" : "");  	weechat_printf_date_tags(  		room->buffer, timestamp / 1000000LL, @@ -88,11 +90,7 @@ static void display_message(  	);  } -static void edit_reply_message( -	struct roomdata *room, -	int64_t msgid, -	const char *new_message -) { +static struct t_gui_line_data* find_hdata_line_data_ptr(struct roomdata *room, int64_t msgid, bool must_be_reply) {  	struct t_hdata *buffer_h = weechat_hdata_get("buffer");  	struct t_hdata *lines_h = weechat_hdata_get("lines");  	struct t_hdata *line_h = weechat_hdata_get("line"); @@ -101,7 +99,7 @@ static void edit_reply_message(  	struct t_gui_lines *lines_ptr = weechat_hdata_pointer(buffer_h, room->buffer, "lines");  	if (!lines_ptr) {  		debugf("ERROR: Cannot get lines_ptr!"); -		return; +		return NULL;  	}  	struct t_gui_line *line_ptr = weechat_hdata_pointer(lines_h, lines_ptr, "last_line"); @@ -125,12 +123,56 @@ static void edit_reply_message(  			}  		} -		if (have_reply_tag && have_msgid_tag) break; +		if ((have_reply_tag || !must_be_reply) && have_msgid_tag) break;  		line_ptr = weechat_hdata_pointer(line_h, line_ptr, "prev_line");  	} -	if (line_ptr) { +	if (line_ptr) return line_data_ptr; +	else return NULL; +} + +static char *collect_line_data_tags(struct t_gui_line_data *line_data_ptr) { +	struct t_hdata *line_data_h = weechat_hdata_get("line_data"); + +	const int tags_count = weechat_hdata_integer(line_data_h, line_data_ptr, "tags_count"); + +	size_t buffer_cap = 256, buffer_len = 0; +	char *buffer = malloc(buffer_cap); +	assert(buffer); + +	for (int i = 0; i < tags_count; i++) { +		char key[32]; +		snprintf(key, sizeof key, "%d|tags_array", i); +		const char *tag = weechat_hdata_string(line_data_h, line_data_ptr, key); +		const size_t len = strlen(tag); + +		// "+ 1" for the comma, "- 1" for the final null byte +		if (buffer_len + 1 + len >= buffer_cap - 1) { +			do buffer_cap *= 2; +			while (buffer_len + 1 + len >= buffer_cap - 1); +			buffer = realloc(buffer, buffer_cap); +			assert(buffer); +		} + +		if (i > 0) buffer[buffer_len++] = ','; +		memcpy(buffer + buffer_len, tag, len); +		buffer_len += len; +	} + +	buffer[buffer_len] = '\0'; +	return buffer; +} + +static void edit_reply_message( +	struct roomdata *room, +	int64_t msgid, +	const char *new_message +) { +	struct t_hdata *line_data_h = weechat_hdata_get("line_data"); +	struct t_gui_line_data *line_data_ptr = find_hdata_line_data_ptr(room, msgid, true); + +	if (line_data_ptr) {  		debugf("edit_reply_message: found line\n");          struct t_hashtable *hashtable =  			weechat_hashtable_new( @@ -145,9 +187,72 @@ static void edit_reply_message(  	}  } +static void edit_message_msgid(struct roomdata *room, int64_t pending_id, int64_t new_msgid) { +	debugf("edit_message_msgid: looking for %" PRIi64 ", replacing with %" PRIi64 "\n", pending_id, new_msgid); + +	struct t_hdata *const line_data_h = weechat_hdata_get("line_data"); +	struct t_gui_line_data *const line_data_ptr = find_hdata_line_data_ptr(room, pending_id, false); + +	if (!line_data_ptr) { +		debugf("edit_message_msgid: not found!\n"); +		return; +	} + +	debugf("edit_message_msgid: found line\n"); + +	char *const tags_str = collect_line_data_tags(line_data_ptr); +	const size_t tags_len = strlen(tags_str); + +	size_t cursor = 0; +	char *endptr; +	size_t taglen = 0; +	while (cursor < tags_len) { +		endptr = strchr(tags_str + cursor, ','); +		taglen = endptr == NULL +					? tags_len - cursor +					: (size_t)(endptr - (tags_str + cursor)); + +		if (memcmp(tags_str + cursor, "tomsgid_", 8) == 0) { +			int64_t this_id = strtoll(tags_str + cursor + 8, NULL, 10); +			if (this_id == pending_id) break; +		} + +		cursor += taglen + 1; +	} + +	if (cursor >= tags_len) { +		debugf("edit_message_msgid: msgid not found in tags?\n"); +		return; +	} + +	// Splice the pending tag out +	tags_str[cursor] = '\0'; +	char *tags_before = tags_str; +	char *tags_after = endptr; + +	// Add the new tag at the end +	char *new_tags_str = NULL; +	asprintf(&new_tags_str, "%stomsgid_%" PRIi64 "%s", tags_before, new_msgid, tags_after); +	assert(new_tags_str); + +	free(tags_str); + +	// Persist the new tags array +	struct t_hashtable *hashtable = +		weechat_hashtable_new( +			8, WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_STRING, NULL, NULL); +	if (hashtable) { +		weechat_hashtable_set(hashtable, "tags_array", new_tags_str); +		weechat_hdata_update(line_data_h, line_data_ptr, hashtable); +		weechat_hashtable_free(hashtable); +	} + +	free(new_tags_str); +} +  static void room_update_attributes(struct roomdata *room){ -	bool private=room->nmembers<=2; +	bool private=room->nmembers==2;  	weechat_buffer_set(room->buffer,"localvar_set_type",private?"private":"channel");  	weechat_buffer_set(room->buffer,"notify",private?"3":"1");  	debugf("room_update_attributes: set private for room %s to %d\n",room->name,private); @@ -165,14 +270,25 @@ static void close_room(struct roomdata *room){  	free(room);  } +struct pending_ids { +	struct roomdata *room; +	int num;  // must be <=2 +	i64 ids[2]; +}; +  static void message_net_callback(int fd,struct net_response res,void *payload){ -	// struct msgdata *msgdata=(struct msgdata*)payload; -	debugf("message_net_callback(fd=%d,res={.type=%d})\n",fd,res.type); -	struct conndata *conn=weechat_hashtable_get(conntable,&fd); -	assert(conn); -	if(res.type==NET_ERROR){ -		weechat_printf(conn->buffer,"tomsg: send threw error: %s",res.error); -	} else if(res.type!=NET_NUMBER){ +	struct pending_ids *pending_ids = (struct pending_ids*)payload; +	debugf("message_net_callback(fd=%d,res={.type=%d})\n", fd, res.type); + +	if (res.type == NET_ERROR) { +		struct conndata *conn = weechat_hashtable_get(conntable, &fd); +		assert(conn); +		weechat_printf(conn->buffer, "tomsg: send threw error: %s", res.error); +	} else if (res.type == NET_NUMBER) { +		for (int i = 0; i < pending_ids->num; i++) { +			edit_message_msgid(pending_ids->room, -pending_ids->ids[i], res.number); +		} +	} else {  		debugf("message_net_callback: res.type=%d\n",res.type);  	}  } @@ -194,13 +310,13 @@ static int room_input_cb(const void *room_vp,void *_d,struct t_gui_buffer *buffe  		tosend=input+skipfirst;  	} -	// struct msgdata *msgdata=malloc(sizeof(msgdata)); -	// msgdata->username=strdup(conn->username); -	// msgdata->message=strdup(tosend); -	void *msgdata=NULL; - -	net_sendf(conn->fd,message_net_callback,msgdata,"send %s -1 %s",room->name,tosend); -	weechat_printf(room->buffer,"%s\t%s",conn->username,tosend); +	struct pending_ids *payload=malloc(sizeof(struct pending_ids)); +	assert(payload); +	payload->room=room; +	payload->num=1; +	payload->ids[0]=room->next_pending_id++; +	net_sendf(conn->fd,message_net_callback,payload,"send %s -1 %s",room->name,tosend); +	display_message(room,gettimestamp(),conn->username,tosend,-payload->ids[0],false,false);  	if(free_tosend){  		free((void*)tosend); @@ -340,8 +456,8 @@ static void push_net_callback(int fd,struct net_response res,void *payload){  				debugf("Found reply msgid=%" PRIi64 " replyid=%" PRIi64 "\n",res.msgid,res.replyid);  				char str[128];  				snprintf(str,sizeof str,"%s> ...",weechat_color("green")); -				display_message(room,res.timestamp,res.username,str,res.msgid,true); -				display_message(room,res.timestamp,"",res.message,res.msgid,false); +				display_message(room,res.timestamp,res.username,str,res.msgid,true,res.type==NET_HISTORY); +				display_message(room,res.timestamp,"",res.message,res.msgid,false,res.type==NET_HISTORY);  				struct room_and_msgid *payload=malloc(sizeof(struct room_and_msgid));  				assert(payload); @@ -349,13 +465,8 @@ static void push_net_callback(int fd,struct net_response res,void *payload){  				payload->msgid=res.msgid;  				net_sendf(fd,reply_get_message_net_callback,payload,"get_message %" PRIi64,res.replyid);  			} else { -				display_message(room,res.timestamp,res.username,res.message,res.msgid,false); +				display_message(room,res.timestamp,res.username,res.message,res.msgid,false,res.type==NET_HISTORY);  			} - -			// struct msgdata *msgdata=malloc(sizeof(msgdata)); -			// msgdata->username=strdup(res.username); -			// msgdata->message=strdup(res.message); -			// weechat_hashtable_set(conn->msgtable,(void*)res.msgid,msgdata);  		} else if(res.type==NET_JOIN){  			weechat_printf(room->buffer,"%sUser %s joined this room",netpfx,res.username);  			if(room->buffer_nickgroup){ @@ -416,6 +527,9 @@ static void roomlist_net_callback(int fd,struct net_response res,void *payload){  			room->name=strdup(res.items[i]);  			room->conn=conn;  			room->buffer=NULL; +			room->buffer_nickgroup=NULL; +			room->nmembers=0; +			room->next_pending_id=1;  			create_room_buffer(room);  			net_sendf(fd,history_net_callback,room,"history %s 10",room->name);  			net_sendf(fd,members_net_callback,room,"list_members %s",room->name); @@ -467,9 +581,6 @@ static void conn_destroy(struct conndata *conn){  		}  	} -	// TODO: free all items in the hashtable -	// weechat_hashtable_free(conn->msgtable); -  	for(int i=0;i<conn->nrooms;i++){  		close_room(conn->rooms[i]);  	} @@ -531,7 +642,7 @@ static int conn_input_cb(const void *conn_vp,void *_d,struct t_gui_buffer *buffe  		weechat_printf(conn->buffer,"Server protocol version not yet negotiated, please wait...");  		return WEECHAT_RC_OK;  	} -	 +  	char *input2=strdup(input);  	assert(input2);  	char *cursor=input2; @@ -645,9 +756,6 @@ static int connect_cb(const void *_p,void *hostname,int status,int _g,int fd,con  			conn->linebuf_len=0;  			conn->linebuf=malloc(conn->linebuf_sz);  			assert(conn->linebuf); -			// conn->msgtable=weechat_hashtable_new( -			//     4096, WEECHAT_HASHTABLE_INTEGER, WEECHAT_HASHTABLE_POINTER, NULL, NULL); -			// assert(conn->msgtable);  			weechat_printf(conn->buffer,"Connected!"); @@ -731,18 +839,28 @@ static int cmd_tomsg_cb(  			const char *message_body=argv_eol[3]; -			// struct msgdata *msgdata=malloc(sizeof(struct msgdata)); -			// msgdata->username=strdup(room->conn->username); -			// msgdata->message=strdup(message_body); -			void *msgdata=NULL; +			struct pending_ids *msg_payload=malloc(sizeof(struct pending_ids)); +			assert(msg_payload); +			msg_payload->room=room; +			msg_payload->num=2; +			msg_payload->ids[0]=room->next_pending_id++; +			msg_payload->ids[1]=room->next_pending_id++;  			int fd=room->conn->fd; -			net_sendf(fd,message_net_callback,msgdata,"send %s %" PRIi64 " %s",room->name,msgid,message_body); +			net_sendf(fd,message_net_callback,msg_payload,"send %s %" PRIi64 " %s",room->name,msgid,message_body); + +			char str[128]; +			snprintf(str,sizeof str,"%s> ...",weechat_color("green")); +			i64 timestamp=gettimestamp(); +			display_message(room,timestamp,room->conn->username,str,-msg_payload->ids[0],true,false); +			display_message(room,timestamp,"",message_body,-msg_payload->ids[1],false,false); -			// TODO: fix this -			weechat_printf(room->buffer,"%s\t%s> ...", -					room->conn->username,weechat_color("green")); -			weechat_printf(room->buffer,"\t%s",message_body); +			// TODO: do get_payload in message_net_callback +			// struct room_and_msgid *get_payload=malloc(sizeof(struct room_and_msgid)); +			// assert(get_payload); +			// get_payload->room=room; +			// get_payload->msgid=msgid; +			// net_sendf(fd,reply_get_message_net_callback,get_payload,"get_message %" PRIi64,msgid);  		} else {  			weechat_printf(NULL,"%stomsg: /tomsg reply on a non-tomsg buffer",errpfx);  			return WEECHAT_RC_ERROR;  | 
