aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrumeet <yuuta@yuuta.moe>2022-11-18 17:26:25 -0800
committerTrumeet <yuuta@yuuta.moe>2022-11-18 17:26:25 -0800
commit3ebff2e47ab77a74fd9905896046ef66531b2b14 (patch)
tree97061a3f2a9f9de1022f3c63c9c7068a3dd1e7ff
downloadhitokoto-3ebff2e47ab77a74fd9905896046ef66531b2b14.tar
hitokoto-3ebff2e47ab77a74fd9905896046ef66531b2b14.tar.gz
hitokoto-3ebff2e47ab77a74fd9905896046ef66531b2b14.tar.bz2
hitokoto-3ebff2e47ab77a74fd9905896046ef66531b2b14.zip
First Commit
-rw-r--r--.gitignore6
-rw-r--r--PKGBUILD29
-rw-r--r--README.md23
-rw-r--r--init.sql28
-rw-r--r--m2.c79
-rw-r--r--types5
6 files changed, 170 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2bbb1ec
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+pkg/
+src/
+*.log
+*.zst
+*.db
+hitokoto
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 0000000..9f9338d
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,29 @@
+# Maintainer: Yuuta Liang <yuuta@yuuta.moe>
+pkgname=hitokoto
+pkgver=2.0
+pkgrel=1
+epoch=
+pkgdesc="Yuuta's Hitokoto"
+arch=(x86_64)
+url="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
+license=('custom')
+groups=()
+depends=(sqlite3 fcgi)
+source=("m2.c"
+"init.sql")
+sha256sums=('80aa15bca8361fd4430c114be633e024ee10df84e9a2d6b8939c5ab5407eeb38'
+ 'e71a00dfb9a2744f482de80e33c02341d6cae19a1f54e53a5346d972bfeff054')
+
+build() {
+ cd "$srcdir"
+ cc -Wall -O3 -lsqlite3 -lfcgi -o hitokoto m2.c
+}
+
+package() {
+ cd "$srcdir"
+ mkdir -p $pkgdir/usr/bin/
+ cp hitokoto $pkgdir/usr/bin/
+ chmod 755 $pkgdir/usr/bin/hitokoto
+ mkdir -p $pkgdir/usr/share/$pkgdir/doc/
+ cp init.sql $pkgdir/usr/share/$pkgdir/doc/
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7c5f29f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# Hitokoto
+
+Yuuta's hitokoto
+
+## Installation
+
+```shell
+makepkg
+pacman -U ./hitokoto-*.zst
+```
+
+## Usage
+
+```shell
+sqlite3 /path/to/data.db '.read /usr/share/hitokoto/doc/init.sql'
+spawn-fcgi -n -p 8080 /usr/bin/hitokoto /path/to/data.db
+```
+
+Use your favourite SQLite editor to add sources and quotes.
+
+## License
+
+WTFPL
diff --git a/init.sql b/init.sql
new file mode 100644
index 0000000..ff62b67
--- /dev/null
+++ b/init.sql
@@ -0,0 +1,28 @@
+BEGIN TRANSACTION;
+CREATE TABLE "quotes" (
+ "id" INTEGER,
+ "source" INTEGER NOT NULL,
+ "time" INTEGER NOT NULL,
+ "text" TEXT NOT NULL,
+ "text_zh" INTEGER,
+ FOREIGN KEY("source") REFERENCES "sources"("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ PRIMARY KEY("id" AUTOINCREMENT)
+);
+CREATE TABLE "sources" (
+ "id" INTEGER,
+ "type" INTEGER NOT NULL,
+ "title" TEXT NOT NULL,
+ "title_zh" TEXT,
+ PRIMARY KEY("id" AUTOINCREMENT)
+);
+CREATE VIEW "v_random_quote" AS
+SELECT
+ sources.title,
+ sources.title_zh,
+ text,
+ text_zh
+FROM quotes
+INNER JOIN sources ON sources.id = quotes.source
+ORDER BY RANDOM()
+LIMIT 1;
+COMMIT;
diff --git a/m2.c b/m2.c
new file mode 100644
index 0000000..6250e23
--- /dev/null
+++ b/m2.c
@@ -0,0 +1,79 @@
+#define _POSIX_C_SOURCE 200809L
+
+#include <fcgiapp.h>
+#include <sqlite3.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+struct fcgi_env {
+ FCGX_Stream *in;
+ FCGX_Stream *out;
+ FCGX_Stream *err;
+ FCGX_ParamArray *envp;
+};
+
+static sqlite3 *db = NULL;
+
+static void cleanup(void) {
+ if (db) {
+ sqlite3_close(db);
+ }
+}
+
+static int cb(void *dat, int count, char **data, char **columns) {
+ struct fcgi_env *env = dat;
+ if (count != 3) {
+ FCGX_FPrintF(env->out,
+ "Status: 500 Internal Server Error\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+ "The database returned %d columns.\n",
+ count);
+ }
+ FCGX_FPrintF(env->out,
+ "Content-type: application/json\r\n"
+ "\r\n"
+ "{\"title\":\"%s\",\"title_zh\":\"%s\",\"text\":\"%s\",\"text_zh\":\"%s\"\"}\n",
+ data[0],
+ data[1] == NULL ? "" : data[1],
+ data[2],
+ data[3]);
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s /path/to/data.db\n", argv[0]);
+ return 64;
+ }
+ atexit(cleanup);
+ int r;
+ if ((r = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, NULL)) != SQLITE_OK) {
+ fprintf(stderr, "Cannot open database: %s\n", sqlite3_errstr(r));
+ return r;
+ }
+ FCGX_Stream *in, *out, *err;
+ FCGX_ParamArray envp;
+ struct fcgi_env env;
+ char *errmsg;
+ while(FCGX_Accept(&in, &out, &err, &envp) >= 0) {
+ env.in = in;
+ env.out = out;
+ env.err = err;
+ env.envp = &envp;
+ if ((r = sqlite3_exec(db, "SELECT title,title_zh,text,text_zh FROM v_random_quote",
+ cb, &env, &errmsg))) {
+ FCGX_FPrintF(out,
+ "Status: 500 Internal Server Error\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+ "%s\n",
+ errmsg);
+ sqlite3_free(errmsg);
+ }
+ }
+}
diff --git a/types b/types
new file mode 100644
index 0000000..f5098dc
--- /dev/null
+++ b/types
@@ -0,0 +1,5 @@
+0 Anime
+1 Song
+2 Novel
+3 Game
+4 Friends