initial commit

This commit is contained in:
James Shiffer 2022-08-12 21:10:29 -07:00
commit 5d0a4d17b9
13 changed files with 323 additions and 0 deletions

90
.gitignore vendored Normal file
View File

@ -0,0 +1,90 @@
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Go template
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

17
.idea/dataSources.xml generated Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="memos" uuid="ebe1be0d-e335-44dd-879e-0f908393835a">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:C:\Users\James.Shiffer\GolandProjects\femMemos\memos.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.38.0/sqlite-jdbc-3.38.0.jar</url>
</library>
</libraries>
</data-source>
</component>
</project>

9
.idea/femMemos.iml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/femMemos.iml" filepath="$PROJECT_DIR$/.idea/femMemos.iml" />
</modules>
</component>
</project>

7
.idea/sqldialects.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/main.go" dialect="GenericSQL" />
<file url="PROJECT" dialect="SQLite" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

91
db.go Normal file
View File

@ -0,0 +1,91 @@
package main
import (
"database/sql"
"errors"
"log"
"os"
"time"
)
type Memo struct {
ID int64 `json:"id"`
Time string `json:"time"`
Message string `json:"message"`
}
func openOrCreateDb(name string) *sql.DB {
new := false
if _, err := os.Stat(name); errors.Is(err, os.ErrNotExist) {
log.Println("memos db does not exist, creating.")
new = true
}
db, err := sql.Open("sqlite3", name)
if err != nil {
log.Fatal(err)
}
if new {
_, err = db.Exec(`create table memos (
ID integer primary key autoincrement,
time text not null,
Message text not null
)`)
if err != nil {
log.Fatal(err)
}
}
return db
}
func insertMemo(db *sql.DB, message string) int64 {
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
stmt, err := tx.Prepare("insert into memos (time, Message) values (?, ?)")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
timeStr := time.Now().Format(time.RFC3339)
row, err := stmt.Exec(timeStr, message)
if err != nil {
log.Fatal(err)
}
err = tx.Commit()
if err != nil {
log.Fatal(err)
}
id, err := row.LastInsertId()
if err != nil {
log.Fatal(err)
}
return id
}
func getMemos(db *sql.DB) []Memo {
rows, err := db.Query("select * from memos order by id desc")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
var memos []Memo
for rows.Next() {
var memo Memo
err = rows.Scan(&memo.ID, &memo.Time, &memo.Message)
if err != nil {
log.Fatal(err)
}
memos = append(memos, memo)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
return memos
}

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module femMemos
go 1.19
require github.com/mattn/go-sqlite3 v1.14.14 // indirect

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=

55
http.go Normal file
View File

@ -0,0 +1,55 @@
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
type ErrorResponse struct {
Message string `json:"message"`
}
type NewMemoResponse struct {
ID int64 `json:"id"`
}
func httpGetMemos(w http.ResponseWriter, r *http.Request) {
memos := getMemos(DB)
w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(memos)
if err != nil {
log.Fatal(err)
}
}
func httpCreateMemo(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "ParseForm() err: %v", err)
return
}
message := r.FormValue("message")
if len(message) == 0 {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(422)
json.NewEncoder(w).Encode(ErrorResponse{"Memo must have a Message"})
return
}
id := insertMemo(DB, message)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(NewMemoResponse{id})
}
func endpoint(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
httpGetMemos(w, r)
case "POST":
httpCreateMemo(w, r)
default:
w.WriteHeader(405)
fmt.Fprintf(w, "HTTP method must be GET or POST")
}
}

25
main.go Normal file
View File

@ -0,0 +1,25 @@
package main
import (
"database/sql"
"errors"
_ "github.com/mattn/go-sqlite3"
"log"
"net/http"
)
var DB *sql.DB
func main() {
DB = openOrCreateDb("./memos.db")
defer DB.Close()
http.HandleFunc("/memos", endpoint)
log.Println("starting server")
err := http.ListenAndServe(":80", nil)
if errors.Is(err, http.ErrServerClosed) {
log.Println("server closed")
} else if err != nil {
log.Fatalf("error starting server: %s\n", err)
}
}

BIN
memos.db Normal file

Binary file not shown.