mirror of https://github.com/nealey/irc-bot
Add a slack.com CGI front-end
This commit is contained in:
parent
506ff13ee6
commit
d07c27135d
4
Makefile
4
Makefile
|
@ -1,5 +1,5 @@
|
||||||
CFLAGS = -Wall -Werror
|
CFLAGS = -Wall -Werror
|
||||||
TARGETS = bot factoids
|
TARGETS = bot factoids slack.cgi
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ all: $(TARGETS)
|
||||||
src/bot:
|
src/bot:
|
||||||
src/factoids: src/factoids.o src/cdb.o src/cdbmake.o
|
src/factoids: src/factoids.o src/cdb.o src/cdbmake.o
|
||||||
|
|
||||||
|
src/slack.cgi: src/slack.cgi.o src/cgi.o
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGETS) $(addprefix src/, $(TARGETS)) src/*.o
|
rm -f $(TARGETS) $(addprefix src/, $(TARGETS)) src/*.o
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* This software has been authored by an employee or employees of Los
|
||||||
|
* Alamos National Security, LLC, operator of the Los Alamos National
|
||||||
|
* Laboratory (LANL) under Contract No. DE-AC52-06NA25396 with the U.S.
|
||||||
|
* Department of Energy. The U.S. Government has rights to use,
|
||||||
|
* reproduce, and distribute this software. The public may copy,
|
||||||
|
* distribute, prepare derivative works and publicly display this
|
||||||
|
* software without charge, provided that this Notice and any statement
|
||||||
|
* of authorship are reproduced on all copies. Neither the Government
|
||||||
|
* nor LANS makes any warranty, express or implied, or assumes any
|
||||||
|
* liability or responsibility for the use of this software. If
|
||||||
|
* software is modified to produce derivative works, such modified
|
||||||
|
* software should be clearly marked, so as not to confuse it with the
|
||||||
|
* version available from LANL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "cgi.h"
|
||||||
|
|
||||||
|
#define POST_MAX 4000
|
||||||
|
|
||||||
|
static int is_cgi = 0;
|
||||||
|
static char **argv = NULL;
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_char_argv()
|
||||||
|
{
|
||||||
|
static int arg = 0;
|
||||||
|
static char *p;
|
||||||
|
|
||||||
|
if (NULL == argv) {
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == arg) {
|
||||||
|
arg = 1;
|
||||||
|
p = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! p) {
|
||||||
|
return EOF;
|
||||||
|
} else if (! *p) {
|
||||||
|
arg += 1;
|
||||||
|
p = argv[arg];
|
||||||
|
return '&';
|
||||||
|
}
|
||||||
|
|
||||||
|
return *(p++);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_char_stdin()
|
||||||
|
{
|
||||||
|
static long inlen = -1;
|
||||||
|
|
||||||
|
if (-1 == inlen) {
|
||||||
|
char *p = getenv("CONTENT_LENGTH");
|
||||||
|
if (p) {
|
||||||
|
inlen = atoi(p);
|
||||||
|
if (inlen > POST_MAX) {
|
||||||
|
inlen = POST_MAX;
|
||||||
|
}
|
||||||
|
if (inlen < 0) {
|
||||||
|
inlen = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
inlen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inlen) {
|
||||||
|
inlen -= 1;
|
||||||
|
return getchar();
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_char_query_string()
|
||||||
|
{
|
||||||
|
static char *p = (char *)-1;
|
||||||
|
|
||||||
|
if ((char *)-1 == p) {
|
||||||
|
p = getenv("QUERY_STRING");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! p) {
|
||||||
|
return EOF;
|
||||||
|
} else if (! *p) {
|
||||||
|
return EOF;
|
||||||
|
} else {
|
||||||
|
return *(p++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int (* read_char)() = read_char_argv;
|
||||||
|
|
||||||
|
int
|
||||||
|
cgi_init(char *global_argv[])
|
||||||
|
{
|
||||||
|
char *rm = getenv("REQUEST_METHOD");
|
||||||
|
|
||||||
|
if (! rm) {
|
||||||
|
read_char = read_char_argv;
|
||||||
|
argv = global_argv;
|
||||||
|
} else if (0 == strcmp(rm, "POST")) {
|
||||||
|
read_char = read_char_stdin;
|
||||||
|
is_cgi = 1;
|
||||||
|
} else if (0 == strcmp(rm, "GET")) {
|
||||||
|
read_char = read_char_query_string;
|
||||||
|
is_cgi = 1;
|
||||||
|
} else {
|
||||||
|
printf(("405 Method not allowed\r\n"
|
||||||
|
"Allow: GET, POST\r\n"
|
||||||
|
"Content-type: text/plain\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"%s is not allowed.\n"),
|
||||||
|
rm);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char
|
||||||
|
tonum(int c)
|
||||||
|
{
|
||||||
|
if ((c >= '0') && (c <= '9')) {
|
||||||
|
return c - '0';
|
||||||
|
}
|
||||||
|
if ((c >= 'a') && (c <= 'f')) {
|
||||||
|
return 10 + c - 'a';
|
||||||
|
}
|
||||||
|
if ((c >= 'A') && (c <= 'F')) {
|
||||||
|
return 10 + c - 'A';
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char
|
||||||
|
read_hex()
|
||||||
|
{
|
||||||
|
int a = read_char();
|
||||||
|
int b = read_char();
|
||||||
|
|
||||||
|
return tonum(a)*16 + tonum(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a key or a value. Since & and = aren't supposed to appear
|
||||||
|
outside of boundaries, we can use the same function for both.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
cgi_item(char *str, size_t maxlen)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
c = read_char();
|
||||||
|
switch (c) {
|
||||||
|
case EOF:
|
||||||
|
case '=':
|
||||||
|
case '&':
|
||||||
|
str[pos] = '\0';
|
||||||
|
return pos;
|
||||||
|
case '%':
|
||||||
|
c = read_hex();
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
c = ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pos < maxlen - 1) {
|
||||||
|
str[pos] = c;
|
||||||
|
pos += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cgi_header(char *content_type)
|
||||||
|
{
|
||||||
|
if (is_cgi) {
|
||||||
|
printf("Content-type: %s\r\n\r\n", content_type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef __CGI_H_
|
||||||
|
#define __CGI_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int cgi_init(char *global_argv[]);
|
||||||
|
size_t cgi_item(char *str, size_t maxlen);
|
||||||
|
void cgi_header(char *content_type);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,95 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h> // only for chdir
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "cgi.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
jputchar(char c)
|
||||||
|
{
|
||||||
|
if (c == '\n') {
|
||||||
|
printf("\\n");
|
||||||
|
} else if (c < 0x20) {
|
||||||
|
printf("\%04x", c);
|
||||||
|
} else if ((c == '\\') || (c == '"')) {
|
||||||
|
putchar('\\');
|
||||||
|
putchar(c);
|
||||||
|
} else {
|
||||||
|
putchar(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char key[80];
|
||||||
|
char val[2000];
|
||||||
|
|
||||||
|
bool its_me = false;
|
||||||
|
|
||||||
|
cgi_init(argv);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = cgi_item(key, sizeof(key));
|
||||||
|
len = cgi_item(val, sizeof(val));
|
||||||
|
|
||||||
|
if (0 == len) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == strcmp(key, "user_id")) {
|
||||||
|
if (0 == strcmp(val, "USLACKBOT")) {
|
||||||
|
its_me = true;
|
||||||
|
}
|
||||||
|
} else if (0 == strcmp(key, "channel_name")) {
|
||||||
|
char chan[40];
|
||||||
|
|
||||||
|
snprintf(chan, sizeof(chan), "#%s", val);
|
||||||
|
setenv("forum", chan, true);
|
||||||
|
} else if (0 == strcmp(key, "user_name")) {
|
||||||
|
setenv("sender", val, true);
|
||||||
|
} else if (0 == strcmp(key, "text")) {
|
||||||
|
setenv("text", val, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cgi_header("text/json");
|
||||||
|
|
||||||
|
if (its_me) {
|
||||||
|
printf("{}");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setenv("command", "PRIVMSG", true);
|
||||||
|
|
||||||
|
chdir("/home/neale/bot/zinc");
|
||||||
|
{
|
||||||
|
FILE *p = popen("./handler", "r");
|
||||||
|
int newlines = 0;
|
||||||
|
|
||||||
|
printf("{\"text\": \"");
|
||||||
|
for (;;) {
|
||||||
|
int c = fgetc(p);
|
||||||
|
|
||||||
|
if (EOF == c) {
|
||||||
|
break;
|
||||||
|
} else if ('\n' == c) {
|
||||||
|
newlines += 1;
|
||||||
|
} else {
|
||||||
|
for (; newlines > 0; newlines -= 1) {
|
||||||
|
jputchar('\n');
|
||||||
|
}
|
||||||
|
jputchar(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\"}\n");
|
||||||
|
|
||||||
|
pclose(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue