]> Nishi Git Mirror - okuu.git/commitdiff
adding stuff
authorNishi <nishi@nishi.boats>
Tue, 10 Sep 2024 19:21:48 +0000 (19:21 +0000)
committerNishi <nishi@nishi.boats>
Tue, 10 Sep 2024 19:21:48 +0000 (19:21 +0000)
git-svn-id: file:///raid/svn-personal/okuu/trunk@3 7d206d2a-66c2-044b-96de-ba755a9b3ba8

Bot/Makefile
Bot/bot.c [new file with mode: 0644]
Bot/main.c
Bot/news.c [new file with mode: 0644]
Bot/ok_bot.h [new file with mode: 0644]
Bot/ok_news.h [new file with mode: 0644]
Bot/ok_util.h [new file with mode: 0644]
Bot/util.c [new file with mode: 0644]
launch.sh [new file with mode: 0755]

index 039c1d11259b0c18a5a02aa35b030195294ba80a..d742ea1b1cec296eca49bb91927c2dd04190f174 100644 (file)
@@ -5,7 +5,7 @@ include $(PWD)/Platform/$(PLATFORM).mk
 .PHONY: all clean
 .SUFFIXES: .c .o
 
-OBJS = main.o ircfw.o
+OBJS = main.o ircfw.o bot.o util.o news.o
 
 all: okuu$(EXEC)
 
diff --git a/Bot/bot.c b/Bot/bot.c
new file mode 100644 (file)
index 0000000..6fa9df3
--- /dev/null
+++ b/Bot/bot.c
@@ -0,0 +1,246 @@
+/* $Id$ */
+
+#include "ok_bot.h"
+
+#include "ok_util.h"
+#include "ok_news.h"
+
+#include "ircfw.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <strings.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <dirent.h>
+#include <poll.h>
+
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+
+#ifdef __FreeBSD__
+#include <netinet/in.h>
+#endif
+
+#define OKUU_VERSION "1.00"
+
+extern char* nntpserver;
+extern char* nntpuser;
+extern char* nntppass;
+extern char* nntppath;
+extern char* nntpcount;
+extern int nntpport;
+
+extern char* ircserver;
+extern char* ircchan;
+extern char* ircpass;
+extern char* ircuser;
+extern char* ircnick;
+extern char* ircreal;
+extern int ircport;
+
+int ok_sock;
+struct sockaddr_in ok_addr;
+
+void ok_close(int sock){
+       close(sock);
+}
+
+void ok_bot_kill(int sig){
+       fprintf(stderr, "Shutdown\n");
+       ircfw_socket_send_cmd(ok_sock, NULL, "QUIT :Shutdown (Signal)");
+       exit(1);
+}
+
+bool ok_is_number(const char* str) {
+       int i;
+       for(i = 0; str[i] != 0; i++) {
+               if(!('0' <= str[i] && str[i] <= '9')) return false;
+       }
+       return true;
+}
+
+char* ok_null(const char* str){
+       return str == NULL ? "(null)" : (char*)str;
+}
+
+int namesort(const struct dirent** a_, const struct dirent** b_){
+       const struct dirent* a = *a_;
+       const struct dirent* b = *b_;
+       return atoi(a->d_name) - atoi(b->d_name);
+}
+
+int nodots(const struct dirent* d){
+       return (strcmp(d->d_name, "..") == 0 || strcmp(d->d_name, ".") == 0) ? 0 : 1;
+}
+
+void ok_bot(void){
+       if((ok_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0){
+               fprintf(stderr, "Socket creation failure\n");
+               return;
+       }
+
+       bzero((char*)&ok_addr, sizeof(ok_addr));
+       ok_addr.sin_family = PF_INET;
+       ok_addr.sin_addr.s_addr = inet_addr(ircserver);
+       ok_addr.sin_port = htons(ircport);
+       
+       if(connect(ok_sock, (struct sockaddr*)&ok_addr, sizeof(ok_addr)) < 0){
+               fprintf(stderr, "Connection failure\n");
+               ok_close(ok_sock);
+               return;
+       }
+
+       signal(SIGINT, ok_bot_kill);
+       signal(SIGTERM, ok_bot_kill);
+
+       char* construct = malloc(1025);
+
+       if(ircpass != NULL && strlen(ircpass) > 0){
+               sprintf(construct, "PASS :%s", ircpass);
+               ircfw_socket_send_cmd(ok_sock, NULL, construct);
+       }
+
+       sprintf(construct, "USER %s %s %s :%s", ircuser, ircuser, ircuser, ircreal);
+       ircfw_socket_send_cmd(ok_sock, NULL, construct);
+
+       sprintf(construct, "NICK :%s", ircnick);
+       ircfw_socket_send_cmd(ok_sock, NULL, construct);
+
+       bool is_in = false;
+
+       struct pollfd pollfds[1];
+       pollfds[0].fd = ok_sock;
+       pollfds[0].events = POLLIN | POLLPRI;
+
+       while(1){
+               int r = poll(pollfds, 1, 100);
+               if(!(r > 0 && pollfds[0].revents & POLLIN)){
+                       /* 100ms sleep, technically */
+                       uint64_t count = 0;
+                       FILE* f = fopen(nntpcount, "rb");
+                       if(f != NULL){
+                               fread(&count, sizeof(count), 1, f);
+                               fclose(f);
+                       }
+                       struct dirent** list;
+                       int n = scandir(nntppath, &list, nodots, namesort);
+                       if(n >= 0){
+                               int i;
+                               for(i = 0; i < n; i++){
+                                       if(count <= atoi(list[i]->d_name)){
+                                               sprintf(construct, "%s/%s", nntppath, list[i]->d_name);
+                                               if(ok_news_read(construct) == 0){
+                                                       char* tmp = ok_strcat3("PRIVMSG ", ircchan, " :\x03" "07[USENET] ~ ");
+                                                       char* temp = ok_strcat3(tmp, news_entry.from, "\x03 ");
+                                                       free(tmp);
+                                                       int j;
+                                                       int incr = 0;
+                                                       for(j = 0;; j++){
+                                                               if(news_entry.content[j] == 0 || news_entry.content[j] == '\n'){
+                                                                       char* line = malloc(j - incr + 1);
+                                                                       line[j - incr] = 0;
+                                                                       memcpy(line, news_entry.content + incr, j - incr);
+
+                                                                       if(strlen(line) > 0){
+                                                                               char* msg = ok_strcat(temp, line);
+                                                                               ircfw_socket_send_cmd(ok_sock, NULL, msg);
+                                                                               free(msg);
+                                                                       }
+
+                                                                       free(line);
+                                                                       incr = j + 1;
+                                                                       if(news_entry.content[j] == 0) break;
+                                                               }
+                                                       }
+                                                       free(temp);
+                                               }else{
+                                                       fprintf(stderr, "Could not read %s\n", construct);
+                                               }
+                                       }
+                                       free(list[i]);
+                               }
+                               count = atoi(list[i - 1]->d_name) + 1;
+                               free(list);
+                       }
+                       f = fopen(nntpcount, "wb");
+                       if(f != NULL){
+                               fwrite(&count, sizeof(count), 1, f);
+                               fclose(f);
+                       }
+                       continue;
+               }
+               int st = ircfw_socket_read_cmd(ok_sock);
+               if(st != 0){
+                       fprintf(stderr, "Bad response\n");
+                       return;
+               }
+               if(strlen(ircfw_message.command) == 3 && ok_is_number(ircfw_message.command)){
+                       int res = atoi(ircfw_message.command);
+                       if(!is_in && 400 <= res && res <= 599){
+                               fprintf(stderr, "Bad response\n");
+                               return;
+                       }else if(400 <= res && res <= 599){
+                               fprintf(stderr, "Ignored error: %d\n", res);
+                               continue;
+                       }
+                       if(res == 376){
+                               is_in = true;
+                               fprintf(stderr, "Login successful\n");
+                               sprintf(construct, "JOIN :%s", ircchan);
+                               ircfw_socket_send_cmd(ok_sock, NULL, construct);
+                       }
+               }else{
+                       if(strcasecmp(ircfw_message.command, "PING") == 0){
+                               fprintf(stderr, "Ping request\n");
+                               sprintf(construct, "PONG :%s", ok_null(ircfw_message.prefix));
+                               ircfw_socket_send_cmd(ok_sock, NULL, construct);
+                       }else if(strcasecmp(ircfw_message.command, "PRIVMSG") == 0){
+                               char* prefix = ircfw_message.prefix;
+                               char** params = ircfw_message.params;
+
+                               int len = 0;
+                               if(params != NULL) {
+                                       int i;
+                                       for(i = 0; params[i] != NULL; i++);
+                                       len = i;
+                               }
+                               if(prefix != NULL && len == 2) {
+                                       char* sentin = params[0];
+                                       char* msg = params[1];
+                                       char* nick = ok_strdup(prefix);
+                                       int i;
+                                       for(i = 0; nick[i] != 0; i++) {
+                                               if(nick[i] == '!') {
+                                                       nick[i] = 0;
+                                                       break;
+                                               }
+                                       }
+                                       if(msg[0] == 1 && msg[strlen(msg) - 1] == 1){
+                                               /* CTCP */
+                                               if(strcasecmp(msg, "\x01VERSION\x01") == 0){
+                                                       sprintf(construct, "NOTICE %s :\x01VERSION Okuu %s / IRC Frameworks %s: http://nishi.boats/okuu\x01", nick, OKUU_VERSION, IRCFW_VERSION);
+                                                       ircfw_socket_send_cmd(ok_sock, NULL, construct);
+                                               }
+                                       }else if(sentin[0] == '#'){
+                                               /* This was sent in channel */
+                                       }
+
+                                       free(nick);
+                               }
+                       }else if(strcasecmp(ircfw_message.command, "ERROR") == 0){
+                               if(ircfw_message.params != NULL){
+                                       int i;
+                                       for(i = 0; ircfw_message.params[i] != NULL; i++) fprintf(stderr, "ERROR: %s\n", ircfw_message.params[i]);
+                               }
+                       }
+               }
+       }
+
+       ircfw_socket_send_cmd(ok_sock, NULL, "QUIT :Shutdown");
+
+       free(construct);
+}
index b1eefe9ce21d5017d8eb8d0a592f99371c5bf081..9ff8e1e93b2b9d1d61edcf9f859014f1deb0974e 100644 (file)
@@ -1,5 +1,9 @@
 /* $Id$ */
 
+#include "ok_bot.h"
+
+#include "ok_news.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
 char* nntpserver;
 char* nntpuser;
 char* nntppass;
+char* nntppath;
+char* nntpcount;
 int nntpport = 119;
 
 char* ircserver;
-int ircport = 6669;
+char* ircchan;
+char* ircuser;
+char* ircnick;
+char* ircreal;
+char* ircpass;
+int ircport = 6667;
 
 int main(){
        printf("Okuu starting up\n");
@@ -18,7 +29,14 @@ int main(){
        nntpserver = getenv("NNTPSERVER");
        nntpuser = getenv("NNTPUSER");
        nntppass = getenv("NNTPPASS");
+       nntppath = getenv("NNTPPATH");
+       nntpcount = getenv("NNTPCOUNT");
        ircserver = getenv("IRCSERVER");
+       ircchan = getenv("IRCCHAN");
+       ircuser = getenv("IRCUSER");
+       ircnick = getenv("IRCNICK");
+       ircreal = getenv("IRCREAL");
+       ircpass = getenv("IRCPASS");
        if(getenv("NNTPPORT") != NULL){
                nntpport = atoi(getenv("NNTPPORT"));
        }
@@ -30,11 +48,31 @@ int main(){
                fprintf(stderr, "Set NNTPSERVER\n");
                bad = true;
        }
+       if(nntppath == NULL){
+               fprintf(stderr, "Set NNTPPATH\n");
+               bad = true;
+       }
+       if(nntpcount == NULL){
+               fprintf(stderr, "Set NNTPCOUNT\n");
+               bad = true;
+       }
        if(ircserver == NULL){
                fprintf(stderr, "Set IRCSERVER\n");
                bad = true;
        }
+       if(ircchan == NULL){
+               fprintf(stderr, "Set IRCCHAN\n");
+               bad = true;
+       }
+       if(ircuser == NULL){
+               fprintf(stderr, "Set IRCUSER\n");
+               bad = true;
+       }
+       if(ircnick == NULL) ircnick = ircuser;
+       if(ircreal == NULL) ircreal = ircuser;
        if(bad){
                return 1;
        }
+       ok_news_init();
+       ok_bot();
 }
diff --git a/Bot/news.c b/Bot/news.c
new file mode 100644 (file)
index 0000000..f5c018f
--- /dev/null
@@ -0,0 +1,205 @@
+/* $Id$ */
+
+#define OK_NEWS_SRC
+#include "ok_news.h"
+
+#include "ok_util.h"
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/stat.h>
+
+struct news_entry news_entry;
+
+void ok_news_init(void){
+       news_entry.from = NULL;
+       news_entry.content = NULL;
+}
+
+int ok_news_read(const char* path){
+
+       if(news_entry.from != NULL){
+               free(news_entry.from);
+               news_entry.from = NULL;
+       }
+       if(news_entry.content != NULL){
+               free(news_entry.content);
+               news_entry.content = NULL;
+       }
+
+       struct stat s;
+       if(stat(path, &s) == 0){
+               char* boundary = NULL;
+               char* buffer = malloc(s.st_size + 1);
+               buffer[s.st_size] = 0;
+               FILE* f = fopen(path, "r");
+               fread(buffer, s.st_size, 1, f);
+
+               uint64_t i;
+               bool newline = false;
+               int incr = 0;
+               char* l = malloc(1);
+               l[0] = 0;
+               bool header = true;
+               bool ignore = false;
+               bool bheader = false;
+               for(i = 0; i < s.st_size; i++){
+                       if(buffer[i] == '\r'){
+                               if(buffer[i + 1] == '\n'){
+                                       /* newline */
+                                       i++;
+                                       if(!header){
+                                               char* line = malloc(i - 1 - incr + 1);
+                                               line[i - 1 - incr] = 0;
+                                               memcpy(line, buffer + incr, i - 1 - incr);
+
+                                               if(strcmp(line, ".") == 0){
+                                                       free(line);
+                                                       break;
+                                               }else{
+                                                       char* ln = line;
+                                                       if(line[0] == '.'){
+                                                               ln++;
+                                                       }
+
+                                                       if(news_entry.content == NULL){
+                                                               news_entry.content = malloc(1);
+                                                               news_entry.content[0] = 0;
+                                                       }
+
+                                                       if(boundary != NULL && strcmp(ln, boundary) == 0){
+                                                               bheader = true;
+                                                               ignore = true;
+                                                       }else if(boundary != NULL && bheader && strlen(ln) == 0){
+                                                               bheader = false;
+                                                               free(line);
+                                                               incr = i + 1;
+                                                               newline = true;
+                                                               continue;
+                                                       }else if(boundary != NULL && bheader){
+                                                               int j;
+                                                               for(j = 0; j < strlen(ln); j++){
+                                                                       if(ln[j] == ':'){
+                                                                               ln[j] = 0;
+                                                                               if(strcasecmp(ln, "Content-Type") == 0){
+                                                                                       ignore = false;
+                                                                                       j++;
+                                                                                       for(; ln[j] != 0 && (ln[j] == ' ' || ln[j] == '\t'); j++);
+                                                                                       if(ln[j] != 0){
+                                                                                               char* v = ln + j;
+                                                                                               int k;
+                                                                                               for(k = 0; v[k] != 0; k++){
+                                                                                                       if(v[k] == ';'){
+                                                                                                               v[k] = 0;
+                                                                                                               break;
+                                                                                                       }
+                                                                                               }
+                                                                                               if(strcasecmp(v, "text/plain") == 0){
+                                                                                               }else{
+                                                                                                       ignore = true;
+                                                                                               }
+                                                                                       }
+                                                                               }
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+
+                                                       if(!ignore && !bheader){
+                                                               char* tmp = news_entry.content;
+                                                               news_entry.content = ok_strcat3(tmp, ln, "\n");
+                                                               free(tmp);
+                                                       }
+                                               }
+
+                                               free(line);
+                                       }else if(newline){
+                                               header = false;
+                                       }else{
+                                               char* line = malloc(i - 1 - incr + 1);
+                                               line[i - 1 - incr] = 0;
+                                               memcpy(line, buffer + incr, i - 1 - incr);
+
+                                               char* last = ok_strdup(l);
+                                               char* tmp = l;
+                                               l = ok_strcat(tmp, line);
+                                               free(tmp);
+                                               bool al = false;
+                                               if(('a' <= line[0] && line[0] <= 'z') || ('A' <= line[0] && line[0] <= 'Z')){
+                                                       free(l);
+                                                       l = ok_strdup(line);
+                                                       al = true;
+                                               }
+                                               if(al){
+                                                       char* ln = ok_strdup(l);
+                                                       int j;
+                                                       for(j = 0; ln[j] != 0; j++){
+                                                               if(ln[j] == ':'){
+                                                                       char* key = ln;
+                                                                       char* value = "";
+                                                                       ln[j] = 0;
+                                                                       j++;
+                                                                       for(; ln[j] != 0 && (ln[j] == '\t' || ln[j] == ' '); j++);
+                                                                       if(ln[j] != 0) value = ln + j;
+                                                                       if(strcasecmp(key, "From") == 0){
+                                                                               if(news_entry.from != NULL) free(news_entry.from);
+                                                                               news_entry.from = ok_strdup(value);
+                                                                       }else if(strcasecmp(key, "Content-Type") == 0){
+                                                                               int k = 0;
+                                                                               int incr2 = 0;
+                                                                               for(k = 0; k <= strlen(value); k++){
+                                                                                       if(value[k] == ';' || value[k] == 0){
+                                                                                               char* attr = malloc(k - incr2 + 1);
+                                                                                               attr[k - incr2] = 0;
+                                                                                               memcpy(attr, value + incr2, k - incr2);
+
+                                                                                               int in;
+                                                                                               for(in = 0; attr[in] != 0; in++){
+                                                                                                       if(attr[in] == '='){
+                                                                                                               attr[in] = 0;
+
+                                                                                                               if(strcasecmp(attr, "boundary") == 0){
+                                                                                                                       boundary = ok_strcat("--", attr + in + 1 + 1);
+                                                                                                                       boundary[strlen(attr + in + 1 + 1) - 1 + 2] = 0;
+                                                                                                                       ignore = true;
+                                                                                                               }
+
+                                                                                                               break;
+                                                                                                       }
+                                                                                               }
+
+                                                                                               free(attr);
+                                                                                               k++;
+                                                                                               for(; value[k] != 0 && (value[k] == ' ' || value[k] == '\t'); k++);
+                                                                                               incr2 = k;
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                                       free(ln);
+                                               }
+                                               free(last);
+                                               free(line);
+                                       }
+                                       incr = i + 1;
+                                       newline = true;
+                               }else{
+                                       newline = false;
+                               }
+                       }else{
+                               newline = false;
+                       }
+               }
+               free(l);
+
+               free(buffer);
+               if(boundary != NULL) free(boundary);
+               return 0;
+       }else{
+               return 1;
+       }
+}
diff --git a/Bot/ok_bot.h b/Bot/ok_bot.h
new file mode 100644 (file)
index 0000000..66bbf35
--- /dev/null
@@ -0,0 +1,8 @@
+/* $Id$ */
+
+#ifndef __OK_BOT_H__
+#define __OK_BOT_H__
+
+void ok_bot(void);
+
+#endif
diff --git a/Bot/ok_news.h b/Bot/ok_news.h
new file mode 100644 (file)
index 0000000..a3ed195
--- /dev/null
@@ -0,0 +1,18 @@
+/* $Id$ */
+
+#ifndef __OK_NEWS_H__
+#define __OK_NEWS_H__
+
+struct news_entry {
+       char* from;
+       char* content;
+};
+
+void ok_news_init(void);
+int ok_news_read(const char* path);
+
+#ifndef OK_NEWS_SRC
+extern struct news_entry news_entry;
+#endif
+
+#endif
diff --git a/Bot/ok_util.h b/Bot/ok_util.h
new file mode 100644 (file)
index 0000000..6bee40b
--- /dev/null
@@ -0,0 +1,10 @@
+/* $Id$ */
+
+#ifndef __OK_UTIL_H__
+#define __OK_UTIL_H__
+
+char* ok_strcat(const char* a, const char* b);
+char* ok_strcat3(const char* a, const char* b, const char* c);
+char* ok_strdup(const char* a);
+
+#endif
diff --git a/Bot/util.c b/Bot/util.c
new file mode 100644 (file)
index 0000000..7cf29fb
--- /dev/null
@@ -0,0 +1,25 @@
+/* $Id$ */
+
+#include "ok_util.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+char* ok_strcat(const char* a, const char* b){
+       char* str = malloc(strlen(a) + strlen(b) + 1);
+       memcpy(str, a, strlen(a));
+       memcpy(str + strlen(a), b, strlen(b));
+       str[strlen(a) + strlen(b)] = 0;
+       return str;
+}
+
+char* ok_strcat3(const char* a, const char* b, const char* c){
+       char* tmp = ok_strcat(a, b);
+       char* str = ok_strcat(tmp, c);
+       free(tmp);
+       return str;
+}
+
+char* ok_strdup(const char* a){
+       return ok_strcat(a, "");
+}
diff --git a/launch.sh b/launch.sh
new file mode 100755 (executable)
index 0000000..97f6c0e
--- /dev/null
+++ b/launch.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+export NNTPSERVER=127.0.0.1
+export NNTPPATH=/var/news/spool/articles/comp/os/netbsd
+export NNTPCOUNT=netbsd-count
+export IRCSERVER=192.168.0.161
+export IRCCHAN=#test
+export IRCUSER=okuu
+export IRCNICK=Okuu
+export IRCREAL="Utsuho Reiuji"
+./Bot/okuu