Initial commit

Main structure is mostly figured out.  Only a noun phrase is currently
generated.
This commit is contained in:
Zorchenhimer 2021-02-13 11:39:05 -05:00
commit 3d6c1a444f
19 changed files with 1464 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
bin/
settings.json
*.sqlite
*.txt

16
Makefile Normal file
View File

@ -0,0 +1,16 @@
#SOURCES= *.go \
# api/*.go \
# business/*.go \
# cmd/*.go \
# database/*.go \
# frontend/*.go \
# models/*.go
SOURCES=$(shell find . -type f -name "*.go")
bin/server: bin/ $(SOURCES)
go build -o bin/server cmd/server.go
bin/:
mkdir -p bin

2
api/api.go Normal file
View File

@ -0,0 +1,2 @@
package api

29
business/business.go Normal file
View File

@ -0,0 +1,29 @@
package business
import (
"github.com/zorchenhimer/hacker-quotes/models"
//"github.com/zorchenhimer/hacker-quotes/database"
)
type HackerQuotes interface {
// Random returns a completely randomized quote.
Random() (string, error)
// Format returns a quote in the given format.
Format(format string) (string, error)
// InitData populates the underlying database with data from the given json file.
InitData(filename string) error
}
type Admin interface {
AddNoun(word models.Noun) error
AddVerb(word models.Verb) error
RemoveNoun(word string) error
// Word is the indefinite form.
RemoveVerb(word string) error
GetNouns() ([]models.Noun, error)
GetVerbs() ([]models.Verb, error)
}

241
business/generic.go Normal file
View File

@ -0,0 +1,241 @@
package business
import (
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"strings"
"github.com/zorchenhimer/hacker-quotes/database"
"github.com/zorchenhimer/hacker-quotes/models"
)
type generic struct {
db database.DB
}
func NewGeneric(db database.DB) (HackerQuotes, error) {
return &generic{db: db}, nil
}
func (g *generic) Random() (string, error) {
definite := rand.Int() % 2 == 0
hasAdj := rand.Int() % 2 == 0
plural := rand.Int() % 2 == 0
np, err := g.nounPhrase(definite, hasAdj, plural)
if err != nil {
return "", err
}
//fmt.Printf("(%s) definite: %t; hasAdj: %t; plural: %t\n", np, definite, hasAdj, plural)
sb := strings.Builder{}
sb.WriteString(np)
return sb.String(), nil
}
func (g *generic) Format(format string) (string, error) {
return "", fmt.Errorf("Not implemented")
}
func (g *generic) nounPhrase(definite, hasAdj, plural bool) (string, error){
adj := ""
var err error
if hasAdj {
adj, err = g.randomAdjective()
if err != nil {
return "", err
}
}
noun, err := g.randomNoun(plural)
if err != nil {
return "", err
}
phrase := adj
if phrase != "" {
phrase += " " + noun
} else {
phrase = noun
}
if definite && !plural {
//fmt.Println("[nounPhrase] definite && !plural")
return "the " + phrase, nil
}
if !plural {
//fmt.Println("[nounPhrase] !plural")
return ana(phrase), nil
}
return phrase, nil
}
func (g *generic) randomAdjective() (string, error) {
ids, err := g.db.GetAdjectiveIds()
if err != nil {
return "", fmt.Errorf("[adj] get IDs error: %v", err)
}
if len(ids) <= 0 {
return "", fmt.Errorf("No adjective IDs returned from database")
}
rid := int(rand.Int63n(int64(len(ids))))
//fmt.Printf("[adj] len(ids): %d; rid: %d; %d\n", len(ids), rid, ids[rid])
adj, err := g.db.GetAdjective(ids[rid])
if err != nil {
return "", fmt.Errorf("[adj] ID: %d; %v", ids[rid], err)
}
return adj.Word, nil
}
func (g *generic) randomNoun(plural bool) (string, error) {
ids, err := g.db.GetNounIds()
if err != nil {
return "", fmt.Errorf("[noun] get IDs error: %v", err)
}
if len(ids) <= 0 {
return "", fmt.Errorf("No noun IDs returned from database")
}
rid := int(rand.Int63n(int64(len(ids))))
//fmt.Printf("[noun] len(ids): %d; rid: %d; ID: %d\n", len(ids), rid, ids[rid])
noun, err := g.db.GetNoun(ids[rid])
if err != nil {
return "", fmt.Errorf("[noun] ID: %d; %v", ids[rid], err)
}
if plural {
return noun.Plural(), nil
}
return noun.Word, nil
}
func (g *generic) randomVerb() (string, error) {
ids, err := g.db.GetVerbIds()
if err != nil {
return "", fmt.Errorf("[verb] get IDs error: %v", err)
}
if len(ids) <= 0 {
return "", fmt.Errorf("No verb IDs returned from database")
}
rid := int(rand.Int63n(int64(len(ids))))
verb, err := g.db.GetVerb(ids[rid])
if err != nil {
return "", fmt.Errorf("[verb] ID: %d; %v", ids[rid], err)
}
return verb.Word, nil
}
func (g *generic) InitData(filename string) error {
fmt.Printf("Initializing database with data in %q\n", filename)
if g.db == nil {
return fmt.Errorf("databse is nil!")
}
raw, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
data := map[string][][]string{}
if err = json.Unmarshal(raw, &data); err != nil {
return err
}
rawadj, ok := data["adjectives"]
if !ok {
return fmt.Errorf("Missing adjectives key in data")
}
adjectives := []models.Adjective{}
for _, adj := range rawadj {
t, word := adj[0], adj[1]
a := models.Adjective{Word: word}
if strings.Contains(t, "a") {
a.Absolute = true
}
if strings.Contains(t, "e") {
a.AppendEst = true
}
if strings.Contains(t, "m") {
a.AppendMore = true
}
adjectives = append(adjectives, a)
}
rawnoun, ok := data["nouns"]
if !ok {
return fmt.Errorf("Missing nouns key in data")
}
nouns := []models.Noun{}
for _, noun := range rawnoun {
t, word := noun[0], noun[1]
n := models.Noun{Word: word}
if strings.Contains(t, "m") {
n.Multiple = true
}
if strings.Contains(t, "b") {
n.Begin = true
}
if strings.Contains(t, "e") {
n.End = true
}
if strings.Contains(t, "a") {
n.Alone = true
}
if strings.Contains(t, "r") {
n.Regular = true
}
nouns = append(nouns, n)
}
rawverbs, ok := data["verbs"]
if !ok {
return fmt.Errorf("Missing verbs key in data")
}
verbs := []models.Verb{}
for _, word := range rawverbs {
v := models.Verb{Word: word[1]}
if strings.Contains(word[0], "r") {
v.Regular = true
}
verbs = append(verbs, v)
}
return g.db.InitData(adjectives, nouns, verbs, nil)
}
// Prepend "a", "an" or nothing to a phrase
func ana(phrase string) string {
//fmt.Printf("[ana] phrase[0]: %s; %q\n", string(phrase[0]), phrase)
if strings.ContainsAny(string(phrase[0]), "aeiou") {
return "an " + phrase
}
return "a " + phrase
}

56
cmd/generate.go Normal file
View File

@ -0,0 +1,56 @@
package main
import (
"os"
"fmt"
"github.com/zorchenhimer/hacker-quotes/business"
"github.com/zorchenhimer/hacker-quotes/database"
)
func main() {
fmt.Println("len(os.Args):", len(os.Args))
var count int = 1
if len(os.Args) == 2 {
fmt.Sscanf(os.Args[1], "%d", &count)
}
db, err := database.New("sqlite", "file:db.sqlite?mode=memory")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
hq, err := business.NewGeneric(db)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = hq.InitData("word_lists.json")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if count == 1 {
sentence, err := hq.Random()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("\n>>", sentence, "<<\n")
} else {
fmt.Println("")
for i := 0; i < count; i++ {
sentence, err := hq.Random()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(">>", sentence, "<<")
}
}
}

18
cmd/server.go Normal file
View File

@ -0,0 +1,18 @@
package main
import (
"fmt"
"os"
"github.com/zorchenhimer/hacker-quotes"
)
func main() {
server, err := hacker.New("settings.json")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
server.Hack()
}

76
database/database.go Normal file
View File

@ -0,0 +1,76 @@
package database
import (
"fmt"
"os"
"github.com/zorchenhimer/hacker-quotes/models"
)
type DbType string
const (
DB_Json DbType = "json"
DB_PostgresSQL DbType = "pgsql"
DB_SQLite DbType = "sqlite"
)
type DB interface {
// Sentence returns a format string for a sentence with the given ID.
//Sentence(id int) (string, error)
AddAdjective(word models.Adjective) error
AddNoun(word models.Noun) error
AddVerb(word models.Verb) error
RemoveAdjective(id int) error
RemoveNoun(id int) error
RemoveVerb(id int) error
GetAdjectiveIds() ([]int, error)
GetNounIds() ([]int, error)
GetVerbIds() ([]int, error)
GetAdjective(id int) (*models.Adjective, error)
GetNoun(id int) (*models.Noun, error)
GetVerb(id int) (*models.Verb, error)
InitData([]models.Adjective, []models.Noun, []models.Verb, []string) error
IsNew() bool
Close()
}
type dbInit func(connectionString string) (DB, error)
var registered map[DbType]dbInit
func New(databaseType DbType, connectionString string) (DB, error) {
f, ok := registered[databaseType]
if !ok {
return nil, fmt.Errorf("Unregistered database type: %s", databaseType)
}
return f(connectionString)
}
func register(databaseType DbType, initFunc dbInit) {
if registered == nil {
registered = make(map[DbType]dbInit)
}
if _, exists := registered[databaseType]; exists {
panic(fmt.Sprintf("Unable to register database with type %s: already exists.", databaseType))
}
registered[databaseType] = initFunc
}
// fileExists returns whether the given file or directory exists or not.
// Taken from https://stackoverflow.com/a/10510783
func fileExists(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
if os.IsNotExist(err) {
return false
}
return true
}

325
database/sqlite.go Normal file
View File

@ -0,0 +1,325 @@
package database
import (
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
"github.com/zorchenhimer/hacker-quotes/models"
)
func init() {
register(DB_SQLite, sqliteInit)
}
type sqliteDb struct {
db *sql.DB
isNew bool
}
func sqliteInit(connectionString string) (DB, error) {
fmt.Println("[sqlite] DB file:", connectionString)
newDb := false
if !fileExists(connectionString) {
newDb = true
}
db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s", connectionString))
if err != nil {
fmt.Println("[sqlite] Open error:", err)
return nil, err
}
if newDb {
stmt := `
create table Adjectives (id integer not null primary key, absolute bool, appendMore bool, appendEst bool, word text);
create table Nouns (id integer not null primary key, multiple bool, begin bool, end bool, alone bool, regular bool, word text);
create table Verbs (id integer not null primary key, regular bool, word text);
`
//create table Sentences (id integer not null primary key, sentence text)
if _, err := db.Exec(stmt); err != nil {
fmt.Println("[sqlite], DB table creation error:", err)
return nil, err
}
}
fmt.Println("[sqlite] no errors")
return &sqliteDb{db: db, isNew: newDb}, nil
}
func (s *sqliteDb) prep(query string) (*sql.Tx, *sql.Stmt, error) {
tx, err := s.db.Begin()
if err != nil {
return nil, nil, err
}
stmt, err := tx.Prepare(query)
if err != nil {
tx.Rollback()
return nil, nil, err
}
return tx, stmt, nil
}
func (s *sqliteDb) Sentence(id int) (string, error) {
stmt, err := s.db.Prepare("select from sentences where id = ?")
if err != nil {
return "", err
}
defer stmt.Close()
var sentence string
if err = stmt.QueryRow(id).Scan(&sentence); err != nil {
return "", err
}
return sentence, nil
}
func (s *sqliteDb) AddAdjective(word models.Adjective) error {
tx, stmt, err := s.prep("insert into Adjectives (Absolute, AppendMore, AppendEst, Word) values (?, ?, ?, ?)")
if err != nil {
return err
}
defer stmt.Close()
if _, err := stmt.Exec(word.Absolute, word.AppendMore, word.AppendEst, word.Word); err != nil {
txerr := tx.Rollback()
if txerr != nil {
return fmt.Errorf("rollback error: %v; exec error: %v", txerr, err)
}
return err
}
return tx.Commit()
}
func (s *sqliteDb) AddNoun(word models.Noun) error {
tx, stmt, err := s.prep("insert into nouns (Multiple, Begin, End, Alone, Regular, Word) values (?, ?, ?, ?, ?, ?)")
if err != nil {
return err
}
defer stmt.Close()
if _, err := stmt.Exec(word.Multiple, word.Begin, word.End, word.Alone, word.Regular, word.Word); err != nil {
txerr := tx.Rollback()
if txerr != nil {
return fmt.Errorf("rollback error: %v; exec error: %v", txerr, err)
}
return err
}
return tx.Commit()
}
func (s *sqliteDb) AddVerb(word models.Verb) error {
tx, stmt, err := s.prep("insert into verbs (Regular, Word) values (?, ?)")
if err != nil {
return err
}
defer stmt.Close()
if _, err := stmt.Exec(word.Regular, word.Word); err != nil {
txerr := tx.Rollback()
if txerr != nil {
return fmt.Errorf("rollback error: %v; exec error: %v", txerr, err)
}
return err
}
return tx.Commit()
}
func (s *sqliteDb) removeWord(query string, id int) error {
stmt, err := s.db.Prepare(query)
if err != nil {
return err
}
defer stmt.Close()
_, err = stmt.Exec(id)
return err
}
func (s *sqliteDb) RemoveAdjective(id int) error {
return s.removeWord("delete from adjectives where id = ?", id)
}
func (s *sqliteDb) RemoveNoun(id int) error {
return s.removeWord("delete from nouns where id = ?", id)
}
func (s *sqliteDb) RemoveVerb(id int) error {
return s.removeWord("delete from verbs where id = ?", id)
}
func (s *sqliteDb) readIds(query string) ([]int, error) {
rows, err := s.db.Query("select id from adjectives")
if err != nil {
return nil, err
}
defer rows.Close()
ids := []int{}
for rows.Next() {
var id int
if err = rows.Scan(&id); err != nil {
return nil, err
}
ids = append(ids, id)
}
return ids, rows.Err()
}
func (s *sqliteDb) GetAdjectiveIds() ([]int, error) {
return s.readIds("select id from adjectives")
}
func (s *sqliteDb) GetNounIds() ([]int, error) {
return s.readIds("select id from nouns")
}
func (s *sqliteDb) GetVerbIds() ([]int, error) {
return s.readIds("select id from verbs")
}
func (s *sqliteDb) GetAdjective(id int) (*models.Adjective, error) {
stmt, err := s.db.Prepare("select Id, Absolute, AppendMore, AppendEst, Word from Adjectives where id = ?")
if err != nil {
return nil, err
}
defer stmt.Close()
adj := &models.Adjective{}
if err = stmt.QueryRow(id).Scan(&adj.Id, &adj.Absolute, &adj.AppendMore, &adj.AppendEst, &adj.Word); err != nil {
return nil, err
}
return adj, nil
}
func (s *sqliteDb) GetNoun(id int) (*models.Noun, error) {
stmt, err := s.db.Prepare("select Id, Multiple, Begin, End, Alone, Regular, Word from Nouns where id = ?")
if err != nil {
return nil, err
}
defer stmt.Close()
noun := &models.Noun{}
if err = stmt.QueryRow(id).Scan(&noun.Id, &noun.Multiple, &noun.Begin, &noun.End, &noun.Alone, &noun.Regular, &noun.Word); err != nil {
return nil, err
}
return noun, nil
}
func (s *sqliteDb) GetVerb(id int) (*models.Verb, error) {
stmt, err := s.db.Prepare("select Id, Regular, Word from Verbs where id = ?")
if err != nil {
return nil, err
}
defer stmt.Close()
verb := &models.Verb{}
if err = stmt.QueryRow(id).Scan(&verb.Id, &verb.Regular, &verb.Word); err != nil {
return nil, err
}
return verb, nil
}
func (s *sqliteDb) InitData(adjectives []models.Adjective, nouns []models.Noun, verbs []models.Verb, sentences []string) error {
tx, err := s.db.Begin()
if err != nil {
return err
}
astmt_txt := "insert into adjectives (Absolute, AppendMore, AppendEst, Word) values (?, ?, ?, ?)"
fmt.Println(astmt_txt)
astmt, err := tx.Prepare(astmt_txt)
if err != nil {
tx.Rollback()
return err
}
for _, adj := range adjectives {
_, err = astmt.Exec(adj.Absolute, adj.AppendMore, adj.AppendEst, adj.Word)
if err != nil {
tx.Rollback()
return err
}
}
astmt.Close()
nstmt_txt := "insert into nouns (Multiple, Begin, End, Alone, Regular, Word) values (?, ?, ?, ?, ?, ?)"
fmt.Println(nstmt_txt)
nstmt, err := tx.Prepare(nstmt_txt)
if err != nil {
tx.Rollback()
return err
}
for _, noun := range nouns {
if _, err = nstmt.Exec(noun.Multiple, noun.Begin, noun.End, noun.Alone, noun.Regular, noun.Word); err != nil {
tx.Rollback()
return err
}
}
nstmt.Close()
vstmt_txt := "insert into verbs (Regular, Word) values (?, ?)"
fmt.Println(vstmt_txt)
vstmt, err := tx.Prepare(vstmt_txt)
if err != nil {
tx.Rollback()
return err
}
for _, verb := range verbs {
_, err = vstmt.Exec(verb.Regular, verb.Word)
if err != nil {
tx.Rollback()
return err
}
}
vstmt.Close()
//sstmt, err := tx.Prepare("insert into sentences (Sentence) values (?)")
//if err != nil {
// tx.Rollback()
// return err
//}
//for _, sentence := range sentences {
// _, err = sstmt.Exec(sentence)
// if err != nil {
// tx.Rollback()
// return err
// }
//}
//sstmt.Close()
err = tx.Commit()
if err != nil {
return err
}
s.isNew = false
return nil
}
func (s *sqliteDb) IsNew() bool {
return s.isNew
}
func (s *sqliteDb) Close() {
s.db.Close()
}

45
frontend/frontend.go Normal file
View File

@ -0,0 +1,45 @@
package frontend
import (
"net/http"
"html/template"
//"github.com/gorilla/sessions"
//"github.com/zorchenhimer/hacker-quotes/models"
//"github.com/zorchenhimer/hacker-quotes/database"
"github.com/zorchenhimer/hacker-quotes/business"
)
type Frontend struct {
//db database.DB
bs business.HackerQuotes
//cookies *sessions.CookieStore
templates map[string]*template.Template
}
func New(bs business.HackerQuotes) (*Frontend, error) {
f := &Frontend{
bs: bs,
//cookies: sessions.NewCookieStore([]byte("some auth key"), []byte("some encrypt key")),
}
return f, nil
}
func (f *Frontend) ServeHTTP(w http.ResponseWriter, r *http.Request) {
//parts := strings.Split(r.URL.Path, "/")
switch r.URL.Path {
case "/":
f.home(w, r)
//case "/admin":
// f.admin(w, r)
default:
f.notFound(w, r)
}
}
func (f *Frontend) notFound(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
}

14
frontend/home.go Normal file
View File

@ -0,0 +1,14 @@
package frontend
import (
"net/http"
)
func (f *Frontend) home(w http.ResponseWriter, r *http.Request) {
words, err := f.bs.Random()
if err != nil {
w.Write([]byte(err.Error()))
return
}
w.Write([]byte(words))
}

8
go.mod Normal file
View File

@ -0,0 +1,8 @@
module github.com/zorchenhimer/hacker-quotes
go 1.15
require (
github.com/gorilla/sessions v1.2.1
github.com/mattn/go-sqlite3 v1.14.6
)

6
go.sum Normal file
View File

@ -0,0 +1,6 @@
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=

11
models/adjective.go Normal file
View File

@ -0,0 +1,11 @@
package models
type Adjective struct {
Id int
Absolute bool
AppendMore bool
AppendEst bool
Word string
}

42
models/noun.go Normal file
View File

@ -0,0 +1,42 @@
package models
import (
"strings"
)
type Noun struct {
Id int
Multiple bool
Begin bool
End bool
Alone bool
Regular bool
Word string
}
func (n Noun) Plural() string {
suffixes := []string{
"s",
"x",
"sh",
"ch",
"ss",
}
for _, sfx := range suffixes {
if strings.HasSuffix(n.Word, sfx) {
return n.Word + "es"
}
}
if strings.HasSuffix(n.Word, "y") && !strings.ContainsAny(string(n.Word[len(n.Word)-2]), "aeiou") {
return n.Word[:len(n.Word)-1] + "ies"
}
return n.Word + "s"
}

28
models/verb.go Normal file
View File

@ -0,0 +1,28 @@
package models
type Verb struct {
Id int
Regular bool
// Indefinite form
Word string
ConjugationsPast []Conjugate
ConjugationsPresent []Conjugate
ConjugationsFuture []Conjugate
}
type ConjugateType int
const (
CT_I ConjugateType = iota
CT_You
CT_It
CT_We
CT_They
)
type Conjugate struct {
Type ConjugateType
Form string
}

87
server.go Normal file
View File

@ -0,0 +1,87 @@
package hacker
import (
"net/http"
"fmt"
//"github.com/zorchenhimer/hacker-quotes/api"
"github.com/zorchenhimer/hacker-quotes/business"
"github.com/zorchenhimer/hacker-quotes/database"
"github.com/zorchenhimer/hacker-quotes/frontend"
//"github.com/zorchenhimer/hacker-quotes/models"
)
type Server struct {
db database.DB
hs *http.Server
bs business.HackerQuotes
settings *settings
}
// New returns a new Server object with the settings from configFile.
// If no file is specified, a default "settings.config" will be
// created with default settings in the current working directory.
func New(configFile string) (*Server, error) {
s := &Server{}
if settings, err := loadSettings(configFile); err != nil {
return nil, fmt.Errorf("Unable to load settings: %s", err)
} else {
s.settings = settings
}
db, err := database.New(s.settings.DatabaseType, s.settings.ConnectionString)
if err != nil {
return nil, fmt.Errorf("Unable to load database type %s: %s", s.settings.DatabaseType, err)
}
s.db = db
bs, err := business.NewGeneric(db)
if err != nil {
return nil, err
}
s.bs = bs
if s.db.IsNew() {
fmt.Println("database is new")
err = bs.InitData("word_lists.json")
if err != nil {
return nil, err
}
} else {
fmt.Println("database isn't new")
}
web, err := frontend.New(s.bs)
if err != nil {
return nil, fmt.Errorf("Unable to load frontend: %s", err)
}
mux := http.NewServeMux()
//mux.Handle("/api", api)
mux.Handle("/", web)
hs := &http.Server{
Addr: ":8080",
Handler: mux,
}
s.hs = hs
return s, nil
}
func (s *Server) Hack() error {
if err := s.hs.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Println("Error running HTTP server:", err)
}
return nil
}
func (s *Server) Shutdown() error {
return fmt.Errorf("Not implemented")
}

51
settings.go Normal file
View File

@ -0,0 +1,51 @@
package hacker
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"github.com/zorchenhimer/hacker-quotes/database"
)
type settings struct {
DatabaseType database.DbType
ConnectionString string
HttpAddr string
}
func loadSettings(filename string) (*settings, error) {
if !fileExists(filename) {
return nil, fmt.Errorf("%q doesn't exist", filename)
//return &settings{
// HttpAddr: ":8080",
//}, nil
}
raw, err := ioutil.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("Error reading file: %s", err)
}
s := &settings{}
if err = json.Unmarshal(raw, s); err != nil {
return nil, fmt.Errorf("Error unmarshaling: %s", err)
}
return s, nil
}
// fileExists returns whether the given file or directory exists or not.
// Taken from https://stackoverflow.com/a/10510783
func fileExists(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
if os.IsNotExist(err) {
return false
}
return true
}

405
word_lists.json Normal file
View File

@ -0,0 +1,405 @@
{
"adjectives": [
["tm", "quantum"],
["tm", "virtual"],
["ta", "shortened"],
["tm", "common"],
["te", "raw"],
["tm", "random"],
["ta", "audio"],
["tm", "industrial"],
["tm", "3D-printed"],
["tm", "proprietary"],
["tm", "forbidden"],
["ta", "patented"],
["tm", "neural"],
["tm", "wireless"],
["tm", "online"],
["tm", "offline"],
["tm", "primary"],
["ta", "8-bit"],
["tm", "open"],
["ta", "live"],
["tm", "flexible"],
["tm", "adaptive"],
["tm", "artificial"],
["tm", "mobile"],
["tm", "meta"],
["tm", "regular"],
["tm", "variable"],
["tm", "global"],
["tm", "automatic"],
["tm", "geometric"],
["tm", "inductive"],
["tm", "default"],
["tm", "constant"],
["tm", "asymmetric"],
["tm", "symmetric"],
["tm", "robust"],
["tm", "analog"],
["tm", "digital"],
["tm", "micro"],
["tm", "standardized"],
["tm", "hidden"],
["tm", "biometric"],
["tm", "safety"],
["tm", "emulated"],
["ta", "root"],
["ta", "generic"],
["ta", "bricked"],
["ta", "miscellaneous"],
["ta", "haptic"],
["tm", "logical"],
["ta", "physical"],
["ta", "relative"],
["ta", "lasered"],
["ta", "licensed"],
["ta", "robotic"],
["tm", "immersive"],
["ta", "customized"],
["ta", "malfunctioning"],
["tm", "granular"],
["ta", "quality"],
["ta", "open source"],
["tm", "sophisticated"],
["tm", "statistical"],
["tm", "DIY"],
["ta", "remote"],
["ta", "handheld"],
["tm", "bleeding edge"],
["tm", "modern"],
["tm", "outdated"],
["ta", "legacy"],
["ta", "visual"],
["ta", "guidance"],
["tm", "private"],
["tm", "public"],
["tm", "cyber"],
["ta", "numeric"],
["ta", "mathematical"],
["ta", "linguistic"],
["ta", "platform-specific"],
["ta", "normalized"],
["ta", "bitwise"],
["ta", "hexadecimal"],
["ta", "octal"],
["ta", "binary"],
["ta", "decimal"],
["te", "large"],
["te", "small"],
["tm", "normal"],
["ta", "infected"],
["ta", "internal"],
["tm", "synchron"],
["tm", "asynchron"],
["ta", "biometric"],
["ta", "idle"],
["ta", "external"],
["ta", "reserved"],
["ta", "explicit"],
["ta", "implicit"],
["tm", "decentralized"],
["tm", "interactive"],
["ta", "lambda"],
["tm", "recursive"],
["te", "weak"],
["ta", "matching"],
["tm", "similar"],
["te", "strong"],
["ta", "partial"],
["ta", "performance"],
["ta", "build in"]
],
"nouns":[
["sar", "git"],
["sar", "github"],
["sar", "gitlab"],
["sar", "gitea"],
["sar", "bitbucket"],
["smer", "branch"],
["smer", "commit"],
["smber", "log"],
["smar", "pull request"],
["smar", "merge request"],
["smber", "stash"],
["sber", "status"],
["smber", "tag"],
["smber", "origin"],
["smber", "master"],
["smber", "lemur"],
["sber", "spacehuhn"],
["smber", "laser"],
["smber", "signal"],
["smber", "network"],
["smber", "analyzer"],
["smber", "application"],
["smber", "firewall"],
["smber", "cybernuke"],
["sber", "IRC"],
["smber", "mainframe"],
["smber", "server"],
["smber", "cloud"],
["smbr", "reality"],
["smer", "request"],
["sber", "WiFi"],
["sber", "Bluetooth"],
["smber", "cable"],
["sber", "ethernet"],
["sber", "LAN"],
["sber", "WAN"],
["smber", "antenna"],
["sber", "NAS"],
["smar", "power supply"],
["smber", "grid"],
["smber", "display"],
["smber", "monitor"],
["smber", "microcontroller"],
["smber", "controller"],
["ser", "SoC"],
["sbr", "SBC"],
["sbr", "ATX"],
["sbr", "ITX"],
["sbr", "USB"],
["ser", "HDD"],
["ser", "SSD"],
["smber", "keyboard"],
["smer", "transition"],
["smber", "tree"],
["ser", "SD"],
["ser", "LED"],
["ser", "IDE"],
["smer", "editor"],
["smer", "frame"],
["ser", "PoC"],
["smber", "bucket"],
["sber", "VM"],
["smer", "identifier"],
["sber", "middleware"],
["sber", "bottleneck"],
["ser", "UI"],
["ser", "GUI"],
["smber", "observer"],
["smber", "singleton"],
["smber", "array"],
["smber", "transmitter"],
["smber", "DVD"],
["ber", "logic"],
["smber", "emulation"],
["smer", "reader"],
["smer", "writer"],
["smer", "label"],
["smber", "clock"],
["smber", "MCU"],
["smber", "phone"],
["smber", "space"],
["sber", "data"],
["sber", "analysis"],
["smber", "sample"],
["sber", "intelligence"],
["smber", "sensor"],
["smber", "camera"],
["smber", "battery"],
["smber", "process"],
["smber", "website"],
["smber", "homepage"],
["smber", "app"],
["smber", "error"],
["smber", "warning"],
["smber", "sequence"],
["smber", "information"],
["sbr", "ASCII"],
["smber", "pattern"],
["smber", "simulation"],
["smber", "simulator"],
["sber", "indicator"],
["smber", "troll"],
["smber", "regulator"],
["smber", "container"],
["smber", "breadboard"],
["sber", "IC"],
["smber", "controller"],
["smber", "drone"],
["smber", "deauther"],
["smar", "if loop"],
["sar", "GTFO"],
["sber", "fax"],
["smar", "garbage collector"],
["smer", "collector"],
["smber", "thread"],
["smber", "model"],
["smber", "switch"],
["smber", "dimension"],
["sber", "foo"],
["sber", "bar"],
["smber", "key"],
["smber", "java"],
["smber", "coffee"],
["sbr", "null"],
["sbr", "NaN"],
["sbr", "undefined"],
["smber", "integer"],
["smber", "double"],
["smber", "string"],
["sar", "bare metal"],
["smber", "adapter"],
["smber", "framework"],
["smber", "system"],
["smber", "algorithm"],
["sbr", "spacetime"],
["smbr", "LCD"],
["sber", "bandwidth"],
["smber", "virus"],
["sbr", "UTF-8"],
["sber", "web"],
["sbr", "handler"],
["smber", "exeption"],
["smber", "path"],
["smber", "reference"],
["smber", "template"],
["smber", "wildcard"],
["smber", "interface"],
["sber", "syntax"],
["smber", "loop"],
["smber", "demon"],
["smber", "core"],
["sber", "interpreter"],
["smber", "string"],
["smber", "document"],
["smber", "cookie"],
["smber", "codec"],
["smber", "e-mail"],
["sber", "OS"],
["smber", "service"],
["sber", "provider"],
["smber", "cache"],
["smber", "database"],
["smber", "object"],
["smbers", "dictionary"],
["sber", "driver"],
["smber", "index"],
["sber", "encoder"],
["smber", "list"],
["smber", "tuple"],
["smber", "range"],
["smber", "stream"],
["sber", "internet"],
["smber", "component"],
["smber", "module"],
["smber", "library"],
["smber", "limit"],
["smber", "function"],
["smer", "token"],
["smber", "code"],
["smber", "wave"],
["sber", "IoT"],
["smber", "blockchain"],
["smber", "repository"],
["smber", "northbridge"],
["smber", "southbridge"]
],
"verbs": [
["r", "init"],
["r", "pull"],
["r", "push"],
["r", "clone"],
["r", "fetch"],
["r", "commit"],
["r", "rebase"],
["r", "merge"],
["r", "fork"],
["r", "stash"],
["r", "tag"],
["r", "cherry-pick"],
["r", "checkout"],
["r", "wrap"],
["r", "iterate"],
["r", "loop"],
["r", "port"],
["r", "infect"],
["r", "append"],
["r", "change"],
["r", "normalize"],
["r", "average"],
["r", "decrypt"],
["r", "encrypt"],
["r", "convert"],
["r", "access"],
["r", "coordinate"],
["r", "power"],
["r", "monitor"],
["r", "regulate"],
["r", "detect"],
["r", "block"],
["r", "debug"],
["r", "observe"],
["r", "bypass"],
["r", "input"],
["r", "synthesize"],
["r", "connect"],
["r", "parse"],
["r", "generate"],
["r", "copy"],
["r", "analyze"],
["r", "control"],
["r", "benchmark"],
["r", "request"],
["r", "enter"],
["r", "call"],
["r", "detect"],
["r", "print"],
["r", "simulate"],
["r", "emulate"],
["r", "intercept"],
["r", "sequence"],
["r", "synchronize"],
["r", "test"],
["r", "tokenize"],
["r", "format"],
["r", "constrain"],
["r", "import"],
["r", "export"],
["r", "develop"],
["r", "invert"],
["r", "slice"],
["r", "index"],
["r", "join"],
["r", "shorten"],
["r", "partition"],
["r", "decompile"],
["r", "split"],
["r", "swap"],
["r", "cast"],
["r", "clear"],
["r", "stream"],
["r", "remove"],
["r", "add"],
["r", "signal"],
["r", "process"],
["r", "disconnect"],
["r", "start"],
["r", "interpret"],
["r", "yield"],
["r", "match"],
["r", "inspect"],
["r", "collect"],
["r", "restrict"],
["r", "display"],
["r", "address"],
["r", "identify"],
["r", "load"],
["r", "define"],
["r", "decentralize"],
["r", "update"],
["r", "encode"],
["r", "virtualize"],
["r", "transmit"],
["r", "compile"],
["r", "randomize"],
["r", "deauth"],
["r", "alter"],
["r", "mute"],
["r", "hash"]
]
}