Keep track of posted links. - annna - Annna the nice friendly bot. HTML git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/annna/ DIR Log DIR Files DIR Refs DIR Tags DIR README --- DIR commit 484cc7bd51ceaaed82b650154cff6bb7e14a878d DIR parent 87850ff5e5fe1150688b7c725974d5383a3e496f HTML Author: Troels Henriksen <athas@sigkill.dk> Date: Mon, 7 Aug 2023 21:51:25 +0200 Keep track of posted links. Signed-off-by: Annna Robert-Houdin <annna@bitreich.org> Diffstat: M annna-message-common | 5 +++++ A modules/linkbrother/linkbrother.c | 177 +++++++++++++++++++++++++++++++ A modules/linkbrother/linkbrother.sh | 12 ++++++++++++ 3 files changed, 194 insertions(+), 0 deletions(-) --- DIR diff --git a/annna-message-common b/annna-message-common @@ -240,6 +240,11 @@ case "${text}" in ;; esac +critique=$($modbase/linkbrother/linkbrother.sh "$modbase/linkbrother/db" "$user" "$text") +if [ "$critique" ]; then + annna-say -s "${server}" -c "${channel}" "$critique" +fi + case "${text}" in "${ircuser}"?) exclamation="$(printf "%s\n" "${text}" | sed "s,${ircuser}\(.\),\1,g")" DIR diff --git a/modules/linkbrother/linkbrother.c b/modules/linkbrother/linkbrother.c @@ -0,0 +1,177 @@ +// cc linkbrother.c -o linkbrother +// +// Use: ./linkbrother LINKSFILE USER MESSAGE + +#define _GNU_SOURCE // sorry + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <assert.h> + +FILE* linksf; +char* links; +int linkslength; +time_t now; +int userlength; + +void checklink(const char* user, const char* link) { + int l = strlen(link); + char* foundlink = (char*)memmem(links, linkslength, link, l); + if (foundlink != NULL) { + char* end = foundlink; + while (!isspace(*end) && *end != 0) { + end++; + } + end = 0; + if (*(foundlink + l) == ' ') { + char* nstart = foundlink + l + 1; + char* whostart = strstr(nstart + 1, " ") + 1; + char* whoend = strstr(whostart, "\n"); + time_t then = atoi(nstart); + *whoend = 0; + + time_t diff = now - then; + char* unit; + int unit_number; + + if (diff < 60) { + if (diff == 1) { + unit = "second"; + } else { + unit = "seconds"; + } + unit_number = diff; + } else if (diff < 60 * 60) { + unit_number = diff / 60; + if (unit_number == 1) { + unit = "minute"; + } else { + unit = "minutes"; + } + } else if (diff < 60 * 60 * 24) { + unit_number = diff / 60 / 60; + if (unit_number == 1) { + unit = "hour"; + } else { + unit = "hours"; + } + } else if (diff < 60 * 60 * 24 * 365) { + unit_number = diff / 60 / 60 / 24; + if (unit_number == 1) { + unit = "day"; + } else { + unit = "days"; + } + } else { + unit_number = diff / 60 / 60 / 24 / 365; + unit = "year"; + } + + if (strcmp(user, whostart) == 0) { + switch (rand()%3) { + case 0: + printf("%s: You first posted that link %d %s ago!\n", + user, unit_number, unit); + break; + case 1: + printf("%s: We heard you the first time (%d %s ago).\n", + user, unit_number, unit); + break; + case 2: + printf("%s: %d %s ago you posted something similar. How about something new?\n", + user, unit_number, unit); + break; + } + } else { + switch (rand()%3) { + case 0: + printf("%s: %s already linked that %d %s ago.\n", + user, whostart, unit_number, unit); + break; + case 1: + printf("%s: Comrade! That link was first seen %d %s ago!\n", + user, unit_number, unit); + break; + case 2: + printf("%s: How nostalgic! Just like %s a whole %d %s ago!\n", + user, whostart, unit_number, unit); + break; + } + } + } + } + /* Always log */ + fprintf(linksf, "%s %ld %s\n", link, (long int)now, user); +} + +int main(int argc, char** argv) { + assert(argc == 4); + char* dbfile = argv[1]; + char* user = argv[2]; + char* message = argv[3]; + + now = time(NULL); + srand(now); + + if (message != NULL && user != NULL) { + struct stat fs; + + userlength = strlen(user); + linksf = fopen(dbfile, "a+"); + assert(linksf != NULL); + fstat(fileno(linksf), &fs); + linkslength = fs.st_size; + links = mmap(NULL, linkslength, PROT_WRITE | PROT_READ, MAP_PRIVATE, fileno(linksf), 0); + while (1) { + char* start, *end; + int atend; + + start = strstr(message, "http://"); + + if (start == NULL) { + start = strstr(message, "https://"); + } + + if (start == NULL) { + start = strstr(message, "gopher://"); + } + + if (start == NULL) { + start = strstr(message, "gophers://"); + } + + if (start == NULL) { + return 0; + } + + end = start; + + while (*end != ' ' && *end != 0) { + end++; + } + + atend = *end == 0; + *end = 0; + + checklink(user, start); + + if (atend) { + return 0; + } + + message = end+1; + } + return 0; + } else { + return 1; + } +} DIR diff --git a/modules/linkbrother/linkbrother.sh b/modules/linkbrother/linkbrother.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# State-of-the-art JIT compilation of linkbrother. + +set -e + +dir=$(dirname $0) +if ! [ -x "$dir/linkbrother" -a "$dir/linkbrother" -nt "$dir/linkbrother.c" ]; then + cc "$dir/linkbrother.c" -o "$dir/linkbrother" +fi + +"$dir/linkbrother" "$@"