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 }