summaryrefslogtreecommitdiff
path: root/replay.c
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-05-11 19:03:57 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-05-11 19:03:57 +0100
commit0559bff00a6be2054194632c3543bf62af1fb56f (patch)
treef007a35d1d7af9a7fa1166831b982c84111baad7 /replay.c
parentc46d01b5afd2da4779efb2700469037eca6122be (diff)
Add the ability to replay messages from a replay log file. (No replay log file writing yet.)
Diffstat (limited to 'replay.c')
-rw-r--r--replay.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/replay.c b/replay.c
new file mode 100644
index 0000000..8c37d4c
--- /dev/null
+++ b/replay.c
@@ -0,0 +1,231 @@
+#include "replay.h"
+
+// Return the unixtime timestamp at the start of a line,
+// or -1 if a timestamp couldn't be extracted
+int gettimestamp(char *str) {
+ int timestamp;
+ char timestr[TIMELEN];
+ int count = 0;
+
+ // Make sure we're starting with a digit
+ if (!isdigit(str[0])) {
+ return -1;
+ }
+
+ // Extract each digit until we encounter a non-digit
+ for (int i = 0; i < TIMELEN; i++) {
+ if (isdigit(str[i])) {
+ timestr[count] = str[i];
+ count++;
+ }
+ }
+
+ timestr[count] = '\0'; // Null terminate
+
+ timestamp = strtol(timestr, NULL, 10); // Convert resulting string to an integer, base 10
+
+ return timestamp;
+}
+
+// Set 'str' to a string with the leading unixtime timestamp removed.
+// Returns 1 on success, 0 on failure
+int striptimestamp(char *str) {
+ char line[MAXCHAR];
+ int count = 0;
+
+ // Make sure we're starting with a digit
+ if (!isdigit(str[0])) {
+ return 0;
+ }
+
+ // Skip over each digit until we encounter a non-digit, record the position
+ for (int i = 0; i < TIMELEN; i++) {
+ if (isdigit(str[i])) {
+ count++;
+ }
+ }
+
+ // Skip over the space
+ count++;
+
+ int count2 = 0;
+
+ // Copy from the end of the digits (and the space) until the end of the string
+ for (size_t i = count; i < strlen(str); i++) {
+ line[count2] = str[i];
+ count2++;
+ }
+
+ strncpy(str, line, count2);
+ str[count2] = '\0';
+
+ return 1;
+}
+
+// Take a string like:
+// 1557592901 :foo!bar@baz PRIVMSG foo :hello world
+// And convert it to:
+// :foo!bar@baz PRIVMSG foo :[17:41:41] hello world
+// Only inserts the formatted time for PRIVMSGs at the moment (and maybe only needs to!).
+void formattime(char *str) {
+ // Extract the timestamp for conversion into [HH:MM:SS]
+ char timestr[TIMELEN];
+ sprintf(timestr, "%d", gettimestamp(str)); // Convert int time to string time
+ struct tm tm;
+ strptime(timestr, "%s", &tm);
+ char timestampf[TIMELEN]; // Formatted timestamp
+ // Convert into [HH:MM:SS]
+ strftime(timestampf, TIMELEN, "[%H:%M:%S]", &tm);
+ printf("Formatted time string: '%s'.\n", timestampf);
+
+ // Strip the original unixtimestamp
+ striptimestamp(str);
+ printf("Now got '%s' and '%s'.\n", timestampf, str);
+
+ // Take note of the length
+ int len = strlen(str);
+
+ // Find the start of the message if it's a PRIVMSG
+ char *ret;
+ int pos1;
+ if ((ret = strstr(str, "PRIVMSG")) != NULL) {
+ // Position within str of "PRIVMSG"
+ pos1 = ret - str;
+ printf("Found 'PRIVMSG' at position '%d' of '%s'.\n", pos1, str);
+ } else {
+ // If it's not a PRIVMSG, stop here
+ return;
+ }
+
+ char *ret2;
+ int pos2;
+ // Find the start of the actual message within the PRIVMSG
+ if ((ret2 = strstr(ret, ":")) != NULL) {
+ // Position within ret of ":"
+ pos2 = ret2 - ret;
+ printf("Found ':' at position '%d' of '%s'.\n", pos2, ret);
+ } else {
+ // Didn't find the real message, weird.
+ return;
+ }
+
+ // Position of start of PRIVMSG colon in original string
+ int realpos = pos1 + pos2 + 1;
+
+ // Build the new formatted string
+ char newline[MAXCHAR];
+
+ // First bit (:foo!bar@baz PRIVMSG foo :)
+ for (int i = 0; i < realpos; i++) {
+ newline[i] = str[i];
+ }
+
+ // Second bit (:foo!bar@baz PRIVMSG foo :[HH:MM:SS])
+ int j = 0;
+ for (int i = realpos; i < TIMELEN + realpos - 1; i++) { // -1 to avoid the null char from timestampf
+ newline[i] = timestampf[j];
+ j++;
+ }
+
+ // Insert a space after the formatted timestamp
+ newline[TIMELEN + realpos - 1] = ' ';
+
+ // Final bit (the original PRIVMSG contents)
+ for (int i = TIMELEN + realpos; i < len + TIMELEN; i++) {
+ newline[i] = str[i - TIMELEN];
+ }
+
+ // Copy the whole thing back to str and null terminate
+ strncpy(str, newline, len + TIMELEN);
+ str[len + TIMELEN] = '\0';
+
+ printf("Ended up with relay string of: '%s'.\n", str);
+}
+
+// Return the number of lines in the replay log since 'seconds' seconds ago, or -1 if there a problem.
+int relaylines(int seconds) {
+ FILE *fp;
+ char str[MAXCHAR];
+ char* filename = "replay.log";
+
+ int numlines = 0;
+
+ fp = fopen(filename, "r");
+
+ if (fp == NULL) {
+ printf("error: could not open replay log '%s'.\n", filename);
+ exit(1);
+ }
+
+ // Get the current time for comparison later
+ int timenow = (int)time(NULL);
+
+ while (fgets(str, MAXCHAR, fp) != NULL) {
+ // Read the timestamp from each line
+ int timestamp = gettimestamp(str);
+ if (timestamp < 1) {
+ printf("Error reading timestamp from replay log file.\n");
+ return -1;
+ }
+
+ printf("Timestamp is: '%d'.\n", timestamp);
+
+ // If the line is within range of the requested time, count it
+ if (timestamp > timenow - seconds) {
+ numlines++;
+ }
+ }
+
+ fclose(fp);
+ return numlines;
+}
+
+// Set 'str' to the line in the log with a timestamp of greater than 'seconds'
+// seconds ago, plus however many lines 'linenum' is set to.
+// Also modify the line to include a timestamp in the form "[HH:MM:SS]".
+// Returns 1 on success, or 0 on failure.
+// TODO - This is horribly inefficient since it re-reads the entire file each call, rewrite this!
+int readrelayline(int seconds, int linenum, char *str) {
+ FILE *fp;
+ char line[MAXCHAR];
+ char* filename = "replay.log";
+
+ int count = 0;
+
+ fp = fopen(filename, "r");
+
+ if (fp == NULL) {
+ printf("error: could not open replay log '%s'.\n", filename);
+ return 1;
+ }
+
+ // Get the current time for comparison later
+ int timenow = (int)time(NULL);
+
+ while (fgets(line, MAXCHAR, fp) != NULL) {
+ printf("Read: '%s'.\n", line);
+ // Read the timestamp from each line
+ int timestamp = gettimestamp(line);
+ if (timestamp < 1) {
+ printf("Error reading timestamp from replay log file.\n");
+ exit(1);
+ }
+
+ // If the line is within range of the requested time...
+ if (timestamp > timenow - seconds) {
+ // ...and it is the current requested line then return it
+ if (count == linenum) {
+ // Insert our formatted [HH:MM:SS] timestamp into the message
+ formattime(line);
+
+ strncpy(str, line, strlen(line));
+ str[strlen(line)] = '\0';
+ return 1;
+ }
+ count++;
+ }
+ }
+
+ // If we got here something went wrong
+ return 0;
+}