linkbrother.c - annna - Annna the nice friendly bot. | |
git clone git://bitreich.org/annna/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws6… | |
Log | |
Files | |
Refs | |
Tags | |
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… | |
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,… | |
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 } |