From 556f1c98528c4523c4095b438b9436ade5e0d84b Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Wed, 4 Jul 2018 13:16:52 -0700 Subject: wip, simplifications --- config/config.go | 5 ++--- main.go | 54 ++++++++++++++++++++++++++++++++++++++---------------- models/db.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- web/rice-box.go | 8 ++++---- web/web.go | 2 +- 5 files changed, 98 insertions(+), 26 deletions(-) diff --git a/config/config.go b/config/config.go index 9a6df3a..91ffd87 100644 --- a/config/config.go +++ b/config/config.go @@ -7,9 +7,8 @@ import ( ) type Settings struct { - DBDriver string `json:"db_driver"` - DBServer string `json:"db"` - WebServer string `json:"web"` + DBFile string `json:"db"` + Port int `json:"web"` Username string `json:"username"` DigestPassword string `json:"password"` ProxyImages bool `json:"proxy_images"` diff --git a/main.go b/main.go index afa34e7..56b0ba7 100644 --- a/main.go +++ b/main.go @@ -12,42 +12,64 @@ import ( ) func main() { - var serve, update, verbose bool - var configFile, newFeed, export string + var help, update, verbose, proxyImages bool + var dbfile, newFeed, export, password string + var port int - flag.StringVarP(&configFile, "config", "c", "config.json", "`configuration` file") - flag.BoolVarP(&update, "update", "u", false, "fetch feeds and store them in the database") - flag.BoolVarP(&serve, "serve", "s", false, "run http server") - flag.BoolVarP(&verbose, "verbose", "v", false, "verbose output") + // dbfile + // port + // proxyImages + // username + // password + + flag.BoolVarP(&help, "help", "h", false, "print usage information") + + flag.BoolVarP(&update, "update", "u", false, "fetch feeds and store new items") flag.StringVarP(&newFeed, "add", "a", "", "add the feed at URL `http://example.com/rss.xml`") - flag.StringVarP(&export, "export", "x", "", "export feeds as `text`, json or opml") + flag.StringVarP(&export, "export", "x", "", "export feed. format required: text, json or opml") + + // flag.BoolVarP(&serve, "serve", "s", false, "run neko app by starting HTTP server") + + flag.StringVarP(&dbfile, "db", "d", "neko.db", "sqlite database file") + flag.StringVarP(&dbfile, "password", "p", "", "password to access web interface") + + flag.IntVarP(&port, "http", "s", 4994, "HTTP port to serve on") + flag.BoolVarP(&verbose, "verbose", "v", true, "verbose output") + flag.BoolVarP(&proxyImages, "imageproxy", "i", false, "rewrite and proxy all image requests for privacy (experimental)") + flag.Parse() - // no command - if !update && !serve && newFeed == "" && export == "" { + if help { flag.Usage() return } - config.Read(configFile) - models.InitDB() vlog.VERBOSE = verbose + config.Config.DBFile = dbfile + config.Config.Port = port + config.Config.ProxyImages = proxyImages + config.Config.DigestPassword = password + + models.InitDB() if update { vlog.Printf("starting crawl\n") crawler.Crawl() - } - if serve { - vlog.Printf("starting web server at %s\n", - config.Config.WebServer) - web.Serve() + return } if newFeed != "" { vlog.Printf("creating new feed\n") feed.NewFeed(newFeed) + return } if export != "" { vlog.Printf("feed export\n") exporter.ExportFeeds(export) + return } + + vlog.Printf("starting web server at 127.0.0.1:%d\n", + config.Config.Port) + web.Serve() + } diff --git a/models/db.go b/models/db.go index 31d8bdd..d5bc7dc 100644 --- a/models/db.go +++ b/models/db.go @@ -5,8 +5,8 @@ package models import ( "adammathes.com/neko/config" + "adammathes.com/neko/vlog" "database/sql" - _ "github.com/go-sql-driver/mysql" _ "github.com/mattn/go-sqlite3" "log" ) @@ -16,7 +16,9 @@ var DB *sql.DB func InitDB() { var err error // DB, err = sql.Open("mysql", dataSourceName) - DB, err = sql.Open(config.Config.DBDriver, config.Config.DBServer) + vlog.Printf("using sqlite3 db file %s\n", config.Config.DBFile) + + DB, err = sql.Open("sqlite3", config.Config.DBFile) if err != nil { log.Panic(err) } @@ -24,4 +26,53 @@ func InitDB() { if err = DB.Ping(); err != nil { log.Panic(err) } + + schema := ` +CREATE TABLE IF NOT EXISTS feed ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + url varchar(100) NOT NULL UNIQUE, + web_url varchar(255) NOT NULL DEFAULT '', + title varchar(255) NOT NULL DEFAULT '', + last_updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + category varchar(255) NOT NULL DEFAULT 'uncategorized' +); +CREATE INDEX feed_url ON feed (url); +CREATE INDEX feed_category ON feed (category); + +CREATE TABLE IF NOT EXISTS item ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + feed_id int(11) NOT NULL, + title text NOT NULL DEFAULT '', + url varchar(255) NOT NULL UNIQUE, + description text NOT NULL DEFAULT '', + publish_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + read_state tinyint(1) NOT NULL DEFAULT '0', + starred tinyint(1) NOT NULL DEFAULT '0', + full_content text NOT NULL DEFAULT '', + header_image text NOT NULL DEFAULT '', + CONSTRAINT item_ibfk_1 FOREIGN KEY (feed_id) REFERENCES feed(id) ON DELETE CASCADE +); +CREATE INDEX item_url ON item (url); +CREATE INDEX item_publish_date ON item (publish_date); +CREATE INDEX item_feed_id ON item (feed_id); +CREATE INDEX item_read_state ON item (read_state); + +CREATE VIRTUAL TABLE fts_item using fts4(content="item", title, url, description); +CREATE TRIGGER item_bu BEFORE UPDATE ON item BEGIN + DELETE FROM fts_item WHERE docid=old.rowid; +END; +CREATE TRIGGER item_bd BEFORE DELETE ON item BEGIN + DELETE FROM fts_item WHERE docid=old.rowid; +END; +CREATE TRIGGER item_au AFTER UPDATE ON item BEGIN + INSERT INTO fts_item(docid, title, url, description) VALUES(new.rowid, new.title, new.url, new.description); +END; +CREATE TRIGGER item_ai AFTER INSERT ON item BEGIN + INSERT INTO fts_item(docid, title, url, description) VALUES(new.rowid, new.title, new.url, new.description); +END; + + INSERT INTO fts_item(fts_item) VALUES('rebuild'); +` + + _, _ = DB.Exec(schema) } diff --git a/web/rice-box.go b/web/rice-box.go index d82fd72..bb8b8b5 100644 --- a/web/rice-box.go +++ b/web/rice-box.go @@ -60,8 +60,8 @@ func init() { } filec := &embedded.EmbeddedFile{ Filename: "ui.html", - FileModTime: time.Unix(1529168764, 0), - Content: string("\n\n \n neko rss mode\n \n \n \n \n \n \n \n \n \n \n \n

🐱

\n\n
\n\n
\n

Tags

\n \n \n

Feeds

\n \n
\n\n \n\n
\n
\n
\n
\n \n \n\n \n\n \n\n \n \n\n \n"), + FileModTime: time.Unix(1529169644, 0), + Content: string("\n\n \n neko rss mode\n \n \n \n \n \n \n \n \n \n \n \n

🐱

\n\n
\n\n
\n

Tags

\n \n \n

Feeds

\n \n
\n\n \n\n
\n
\n
\n
\n \n \n\n \n\n \n\n \n \n\n \n"), } filed := &embedded.EmbeddedFile{ Filename: "ui.js", @@ -82,7 +82,7 @@ func init() { // define dirs dir1 := &embedded.EmbeddedDir{ Filename: "", - DirModTime: time.Unix(1529169528, 0), + DirModTime: time.Unix(1529169644, 0), ChildFiles: []*embedded.EmbeddedFile{ file2, // ".DS_Store" file3, // "backbone-1.3.3.min.js" @@ -108,7 +108,7 @@ func init() { // register embeddedBox embedded.RegisterEmbeddedBox(`../static`, &embedded.EmbeddedBox{ Name: `../static`, - Time: time.Unix(1529169528, 0), + Time: time.Unix(1529169644, 0), Dirs: map[string]*embedded.EmbeddedDir{ "": dir1, }, diff --git a/web/web.go b/web/web.go index 1e1f628..8b3b19d 100644 --- a/web/web.go +++ b/web/web.go @@ -295,5 +295,5 @@ func Serve() { http.HandleFunc("/", AuthWrap(indexHandler)) - log.Fatal(http.ListenAndServe(config.Config.WebServer, nil)) + log.Fatal(http.ListenAndServe(":"+strconv.Itoa(config.Config.Port), nil)) } -- cgit v1.2.3