linkbrother.c - 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 --- linkbrother.c (4118B) --- 1 // cc linkbrother.c -o linkbrother 2 // 3 // Use: ./linkbrother LINKSFILE USER MESSAGE 4 5 #define _GNU_SOURCE // sorry 6 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <ctype.h> 11 #include <sys/types.h> 12 #include <sys/stat.h> 13 #include <sys/mman.h> 14 #include <sys/time.h> 15 #include <unistd.h> 16 #include <fcntl.h> 17 #include <time.h> 18 #include <assert.h> 19 20 FILE* linksf; 21 char* links; 22 int linkslength; 23 time_t now; 24 int userlength; 25 26 void checklink(const char* user, const char* link) { 27 int l = strlen(link); 28 char* foundlink = (char*)memmem(links, linkslength, link, l); 29 if (foundlink != NULL) { 30 char* end = foundlink; 31 while (!isspace(*end) && *end != 0) { 32 end++; 33 } 34 end = 0; 35 if (*(foundlink + l) == ' ') { 36 char* nstart = foundlink + l + 1; 37 char* whostart = strstr(nstart + 1, " ") + 1; 38 char* whoend = strstr(whostart, "\n"); 39 time_t then = atoi(nstart); 40 *whoend = 0; 41 42 time_t diff = now - then; 43 char* unit; 44 int unit_number; 45 46 if (diff < 60) { 47 if (diff == 1) { 48 unit = "second"; 49 } else { 50 unit = "seconds"; 51 } 52 unit_number = diff; 53 } else if (diff < 60 * 60) { 54 unit_number = diff / 60; 55 if (unit_number == 1) { 56 unit = "minute"; 57 } else { 58 unit = "minutes"; 59 } 60 } else if (diff < 60 * 60 * 24) { 61 unit_number = diff / 60 / 60; 62 if (unit_number == 1) { 63 unit = "hour"; 64 } else { 65 unit = "hours"; 66 } 67 } else if (diff < 60 * 60 * 24 * 365) { 68 unit_number = diff / 60 / 60 / 24; 69 if (unit_number == 1) { 70 unit = "day"; 71 } else { 72 unit = "days"; 73 } 74 } else { 75 unit_number = diff / 60 / 60 / 24 / 365; 76 unit = "year"; 77 } 78 79 if (strcmp(user, whostart) == 0) { 80 switch (rand()%3) { 81 case 0: 82 printf("%s: You first posted that link %d %s ago!\n", 83 user, unit_number, unit); 84 break; 85 case 1: 86 printf("%s: We heard you the first time (%d %s ago).\n", 87 user, unit_number, unit); 88 break; 89 case 2: 90 printf("%s: %d %s ago you posted something similar. How about something new?\n", 91 user, unit_number, unit); 92 break; 93 } 94 } else { 95 switch (rand()%3) { 96 case 0: 97 printf("%s: %s already linked that %d %s ago.\n", 98 user, whostart, unit_number, unit); 99 break; 100 case 1: 101 printf("%s: Comrade! That link was first seen %d %s ago!\n", 102 user, unit_number, unit); 103 break; 104 case 2: 105 printf("%s: How nostalgic! Just like %s a whole %d %s ago!\n", 106 user, whostart, unit_number, unit); 107 break; 108 } 109 } 110 } 111 } 112 /* Always log */ 113 fprintf(linksf, "%s %ld %s\n", link, (long int)now, user); 114 } 115 116 int main(int argc, char** argv) { 117 assert(argc == 4); 118 char* dbfile = argv[1]; 119 char* user = argv[2]; 120 char* message = argv[3]; 121 122 now = time(NULL); 123 srand(now); 124 125 if (message != NULL && user != NULL) { 126 struct stat fs; 127 128 userlength = strlen(user); 129 linksf = fopen(dbfile, "a+"); 130 assert(linksf != NULL); 131 fstat(fileno(linksf), &fs); 132 linkslength = fs.st_size; 133 links = mmap(NULL, linkslength, PROT_WRITE | PROT_READ, MAP_PRIVATE, fileno(linksf), 0); 134 while (1) { 135 char* start, *end; 136 int atend; 137 138 start = strstr(message, "http://"); 139 140 if (start == NULL) { 141 start = strstr(message, "https://"); 142 } 143 144 if (start == NULL) { 145 start = strstr(message, "gopher://"); 146 } 147 148 if (start == NULL) { 149 start = strstr(message, "gophers://"); 150 } 151 152 if (start == NULL) { 153 return 0; 154 } 155 156 end = start; 157 158 while (*end != ' ' && *end != 0) { 159 end++; 160 } 161 162 atend = *end == 0; 163 *end = 0; 164 165 checklink(user, start); 166 167 if (atend) { 168 return 0; 169 } 170 171 message = end+1; 172 } 173 return 0; 174 } else { 175 return 1; 176 } 177 }