Skip to content

Commit

Permalink
feat: re-colourize chat history on load
Browse files Browse the repository at this point in the history
This is only a partial implementation. We only colourize normal messages
at present. In order to do other types of messages (actions, connection
status, mod events etc.) we'll need to change the log format to give
us more hints

This commit also removes seconds from the default log timestamp for
consistency witht he UI default, and adds the missing config example
field for custom log timestamp formats.
  • Loading branch information
JFreegman committed Feb 17, 2024
1 parent 6b415fa commit 5ae055a
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 19 deletions.
6 changes: 3 additions & 3 deletions doc/toxic.conf.5
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: toxic.conf
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
.\" Date: 2024-02-07
.\" Date: 2024-02-17
.\" Manual: Toxic Manual
.\" Source: toxic __VERSION__
.\" Language: English
.\"
.TH "TOXIC\&.CONF" "5" "2024\-02\-07" "toxic __VERSION__" "Toxic Manual"
.TH "TOXIC\&.CONF" "5" "2024\-02\-17" "toxic __VERSION__" "Toxic Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand Down Expand Up @@ -79,7 +79,7 @@ Time format string for the interface enclosed by double quotes\&. See
.PP
\fBlog_timestamp_format\fR
.RS 4
Time format string for logging enclosed by double quotes\&. See
Time format string for logging enclosed by double quotes\&. (Note: the time portion of the format string must be enclosed by square brackets in order to be parsed by toxic)\&. See
\fBdate\fR(1)
.RE
.PP
Expand Down
2 changes: 1 addition & 1 deletion doc/toxic.conf.5.asc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ OPTIONS
See *date*(1)

*log_timestamp_format*;;
Time format string for logging enclosed by double quotes.
Time format string for logging enclosed by double quotes. (Note: the time portion of the format string must be enclosed by square brackets in order to be parsed by toxic).
See *date*(1)

*alerts*;;
Expand Down
4 changes: 4 additions & 0 deletions misc/toxic.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ ui = {
// Timestamp format string according to date/strftime format. Overrides time_format setting
timestamp_format="%H:%M";

// Timestamp format string for raw logs according to date/strftime format. (Note: the time
// of the format string must be enclosed in square brackets in order to be parsed by toxic).
log_timestamp_format="%Y/%m/%d [%H:%M]"

// true to show you when others are typing a message in 1-on-1 chats
show_typing_other=true;

Expand Down
14 changes: 11 additions & 3 deletions src/chat.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/

#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* needed for wcswidth() */
#define _GNU_SOURCE /* needed for strcasestr() and wcswidth() */
#endif

#include "chat.h"
Expand Down Expand Up @@ -1647,18 +1647,26 @@ static void chat_onDraw(ToxWindow *self, Toxic *toxic)

static void chat_init_log(ToxWindow *self, Toxic *toxic, const char *self_nick)
{
Tox *tox = toxic->tox;

ChatContext *ctx = self->chatwin;
const Client_Config *c_config = toxic->c_config;

char myid[TOX_ADDRESS_SIZE];
tox_self_get_address(toxic->tox, (uint8_t *) myid);
tox_self_get_address(tox, (uint8_t *) myid);

char self_name[TOX_MAX_NAME_LENGTH + 1];
tox_self_get_name(tox, (uint8_t *) self_name);

const size_t len = tox_self_get_name_size(tox);
self_name[len] = '\0';

if (log_init(ctx->log, c_config, self_nick, myid, Friends.list[self->num].pub_key, LOG_TYPE_CHAT) != 0) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to initialize chat log.");
return;
}

if (load_chat_history(ctx->log, self, c_config) != 0) {
if (load_chat_history(ctx->log, self, c_config, self_name) != 0) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to load chat history.");
}

Expand Down
8 changes: 7 additions & 1 deletion src/conference.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ static void init_conference_logging(ToxWindow *self, Toxic *toxic, uint32_t conf
char my_id[TOX_ADDRESS_SIZE];
tox_self_get_address(tox, (uint8_t *) my_id);

char self_name[TOX_MAX_NAME_LENGTH + 1];
tox_self_get_name(tox, (uint8_t *) self_name);

const size_t len = tox_self_get_name_size(tox);
self_name[len] = '\0';

char conference_id[TOX_CONFERENCE_ID_SIZE];
tox_conference_get_id(tox, conferencenum, (uint8_t *) conference_id);

Expand All @@ -187,7 +193,7 @@ static void init_conference_logging(ToxWindow *self, Toxic *toxic, uint32_t conf
return;
}

if (load_chat_history(ctx->log, self, c_config) != 0) {
if (load_chat_history(ctx->log, self, c_config, self_name) != 0) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to load chat history.");
}

Expand Down
5 changes: 4 additions & 1 deletion src/groupchats.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ static void init_groupchat_log(ToxWindow *self, Toxic *toxic, uint32_t groupnumb
char my_id[TOX_ADDRESS_SIZE];
tox_self_get_address(tox, (uint8_t *) my_id);

char self_nick[TOX_MAX_NAME_LENGTH + 1];
get_group_self_nick_truncate(tox, self_nick, groupnumber);

char chat_id[TOX_GROUP_CHAT_ID_SIZE];

Tox_Err_Group_State_Queries err;
Expand All @@ -353,7 +356,7 @@ static void init_groupchat_log(ToxWindow *self, Toxic *toxic, uint32_t groupnumb
return;
}

if (load_chat_history(ctx->log, self, c_config) != 0) {
if (load_chat_history(ctx->log, self, c_config, self_nick) != 0) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to load chat history.");
}

Expand Down
53 changes: 52 additions & 1 deletion src/line_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,58 @@ int line_info_add(ToxWindow *self, const Client_Config *c_config, bool show_time

line_info_init_line(self, new_line);

hst->queue[hst->queue_size++] = new_line;
hst->queue[hst->queue_size] = new_line;
++hst->queue_size;

return new_line->id;
}

int line_info_load_history(ToxWindow *self, const Client_Config *c_config, const char *timestamp,
const char *name, int colour, const char *message)
{
if (self == NULL) {
return -1;
}

struct history *hst = self->chatwin->hst;

if (hst->queue_size >= MAX_LINE_INFO_QUEUE) {
return -1;
}

struct line_info *new_line = calloc(1, sizeof(struct line_info));

if (new_line == NULL) {
return -1;
}

int len = 1 + strlen(c_config->line_normal) + 3;

const uint16_t msg_width = line_info_add_msg(new_line->msg, sizeof(new_line->msg) / sizeof(wchar_t), message);
len += msg_width;

if (c_config->timestamps == TIMESTAMPS_ON) {
snprintf(new_line->timestr, sizeof(new_line->timestr), "%s", timestamp);
}

len += strlen(new_line->timestr) + 1;

snprintf(new_line->name1, sizeof(new_line->name1), "%s", name);
len += strlen(new_line->name1);

new_line->id = (hst->line_end->id + 1 + hst->queue_size) % INT_MAX;
new_line->len = len;
new_line->msg_width = msg_width;
new_line->type = IN_MSG;
new_line->bold = false;
new_line->colour = colour;
new_line->noread_flag = false;
new_line->timestamp = get_unix_time();

line_info_init_line(self, new_line);

hst->queue[hst->queue_size] = new_line;
++hst->queue_size;

return new_line->id;
}
Expand Down
11 changes: 10 additions & 1 deletion src/line_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,22 @@ struct history {

/* creates new line_info line and puts it in the queue.
*
* Returns the id of the new line.
* Returns the ID of the new line on success.
* Returns -1 on failure.
*/
__attribute__((format(printf, 9, 10)))
int line_info_add(ToxWindow *self, const Client_Config *c_config, bool show_timestamp, const char *name1,
const char *name2, LINE_TYPE type, uint8_t bold, uint8_t colour, const char *msg, ...);

/*
* Similar to line_info_add() but uses lines from history.
*
* Returns the ID of the new line on success.
* Returns -1 on failure.
*/
int line_info_load_history(ToxWindow *self, const Client_Config *c_config, const char *timestamp,
const char *name, int colour, const char *message);

/* Prints a section of history starting at line_start */
void line_info_print(ToxWindow *self, const Client_Config *c_config);

Expand Down
54 changes: 51 additions & 3 deletions src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ void write_to_log(struct chatlog *log, const Client_Config *c_config, const char

const char *t = c_config->log_timestamp_format;
char s[MAX_STR_SIZE];
format_time_str(s, MAX_STR_SIZE, t, get_time());
get_time_str(s, sizeof(s), t);
fprintf(log->file, "%s %s %s\n", s, name_frmt, msg);

if (timed_out(log->lastwrite, LOG_FLUSH_LIMIT)) {
Expand Down Expand Up @@ -231,12 +231,60 @@ int log_init(struct chatlog *log, const Client_Config *c_config, const char *nam
return 0;
}

static void load_line(ToxWindow *self, const Client_Config *c_config, const char *line, const char *self_name)
{
const size_t line_length = strlen(line);
const int start_ts = char_find(0, line, '[') + 1;
const int end_ts = char_find(0, line, ']');
const int ts_len = end_ts - start_ts;
const int start_idx = (line_length > start_ts) ? start_ts - 1 : 0;

char timestamp[TIME_STR_SIZE];

// sanity check
if (ts_len <= 0 || ts_len >= sizeof(timestamp) || start_ts < 0 || start_ts + ts_len >= line_length
|| start_ts >= line_length || end_ts <= 0 || end_ts >= line_length) {
return;
}

memcpy(timestamp, &line[start_ts], ts_len);
timestamp[ts_len] = '\0';

const int end_name = char_find(end_ts, line, ':');

if (end_name + 2 >= line_length || end_name <= 0) {
goto on_error;
}

char name[TOXIC_MAX_NAME_LENGTH + 1];
const char *message = &line[end_name + 2];

const int start_name = end_ts + 1;
const int name_len = end_name - start_name - 1;

if (start_name + 1 >= line_length || name_len >= sizeof(name) || start_name + 1 + name_len >= line_length
|| name_len <= 0) {
goto on_error;
}

memcpy(name, &line[start_name + 1], name_len);
name[name_len] = '\0';

const int colour = strcmp(self_name, name) != 0 ? CYAN : GREEN;

line_info_load_history(self, c_config, timestamp, name, colour, message);
return;

on_error:
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "%s", &line[start_idx]);
}

/* Loads chat log history and prints it to `self` window.
*
* Return 0 on success or if log file doesn't exist.
* Return -1 on failure.
*/
int load_chat_history(struct chatlog *log, ToxWindow *self, const Client_Config *c_config)
int load_chat_history(struct chatlog *log, ToxWindow *self, const Client_Config *c_config, const char *self_name)
{
if (log == NULL) {
return -1;
Expand Down Expand Up @@ -303,7 +351,7 @@ int load_chat_history(struct chatlog *log, ToxWindow *self, const Client_Config
}

while (line != NULL && count--) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "%s", line);
load_line(self, c_config, line, self_name);
line = strtok_r(NULL, "\n", &tmp);
}

Expand Down
2 changes: 1 addition & 1 deletion src/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void log_disable(struct chatlog *log);
* Return 0 on success or if log file doesn't exist.
* Return -1 on failure.
*/
int load_chat_history(struct chatlog *log, ToxWindow *self, const Client_Config *c_config);
int load_chat_history(struct chatlog *log, ToxWindow *self, const Client_Config *c_config, const char *self_name);

/* Renames chatlog file `src` to `dest`.
*
Expand Down
4 changes: 2 additions & 2 deletions src/message_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ void cqueue_remove(ToxWindow *self, Toxic *toxic, uint32_t receipt)
}

if (log->log_on) {
char selfname[TOX_MAX_NAME_LENGTH];
char selfname[TOX_MAX_NAME_LENGTH + 1];
tox_self_get_name(tox, (uint8_t *) selfname);

size_t len = tox_self_get_name_size(tox);
const size_t len = tox_self_get_name_size(tox);
selfname[len] = 0;

write_to_log(log, c_config, msg->message, selfname, msg->type == OUT_ACTION);
Expand Down
2 changes: 1 addition & 1 deletion src/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ int settings_load_main(Client_Config *s, const Run_Options *run_opts)
if (config_setting_lookup_int(setting, ui_strings.time_format, &time)) {
if (time == 12) {
snprintf(s->timestamp_format, sizeof(s->timestamp_format), "%s", "%I:%M %p");
snprintf(s->log_timestamp_format, sizeof(s->log_timestamp_format), "%s", "%Y/%m/%d [%I:%M:%S %p]");
snprintf(s->log_timestamp_format, sizeof(s->log_timestamp_format), "%s", "%Y/%m/%d [%I:%M %p]");
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ enum settings_values {
#define LINE_NORMAL "-"
#define LINE_SPECIAL ">"
#define TIMESTAMP_DEFAULT "%H:%M"
#define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]"
#define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M]"
#define MPLEX_AWAY_NOTE "Away from keyboard, be back soon!"

typedef struct Windows Windows;
Expand Down

0 comments on commit 5ae055a

Please sign in to comment.