twtr

Dysfunctional personal twtr software
git clone http://git.hanabi.in/repos/twtr.git
Log | Files | Refs

main.go (5359B)


      1 package main
      2 
      3 import (
      4 	"database/sql"
      5 	"fmt"
      6 	"io/ioutil"
      7 	"log"
      8 	"os"
      9 	"strconv"
     10 	"time"
     11 
     12 	"github.com/gofiber/fiber/v2"
     13 	_ "github.com/mattn/go-sqlite3"
     14 )
     15 
     16 var epoch int = 1630000000
     17 var SQLITE3 string = "sqlite3"
     18 var DB_NAME string = "./twtr.db"
     19 var MYPASS = "SOME_PASSPHRASE"
     20 
     21 type twtrDBres struct {
     22 	ID            int
     23 	TWEET         string
     24 	UNIXTIMESTAMP int
     25 }
     26 
     27 func main() {
     28 	updateSite()
     29 	app := fiber.New()
     30 
     31 	app.Get("/", getAllTwts)
     32 
     33 	app.Post("/new", postTwt)
     34 
     35 	app.Delete("/x/:id", delTwt)
     36 
     37 	log.Fatal(app.Listen(":3000"))
     38 }
     39 
     40 func getAllTwts(c *fiber.Ctx) error {
     41 	db, err := sql.Open(SQLITE3, DB_NAME)
     42 	defer db.Close()
     43 	if err != nil {
     44 		fmt.Fprintln(os.Stderr, err)
     45 		return c.Status(400).JSON(&fiber.Map{
     46 			"error": "Error occurred.",
     47 		})
     48 	}
     49 	rows, err := db.Query("SELECT * FROM twts ORDER BY ID DESC")
     50 	if err != nil {
     51 		fmt.Fprintln(os.Stderr, err)
     52 		return c.Status(400).JSON(&fiber.Map{
     53 			"error": "Error occurred.",
     54 		})
     55 	}
     56 	var res []twtrDBres
     57 	for rows.Next() {
     58 		var ID int
     59 		var TWEET string
     60 		var UNIXTIMESTAMP int
     61 		err = rows.Scan(&ID, &TWEET, &UNIXTIMESTAMP)
     62 		if err != nil {
     63 			fmt.Fprintln(os.Stderr, err)
     64 			return c.Status(400).JSON(&fiber.Map{
     65 				"error": "Error occurred.",
     66 			})
     67 		}
     68 		res = append(res, twtrDBres{ID, TWEET, (UNIXTIMESTAMP + epoch) * 1000})
     69 	}
     70 	return c.JSON(&fiber.Map{
     71 		"res": res,
     72 	})
     73 }
     74 
     75 func delTwt(c *fiber.Ctx) error {
     76 	req := map[string]string{}
     77 	c.BodyParser(&req)
     78 	passphrase := req["passphrase"]
     79 	id, err := strconv.Atoi(c.Params("id"))
     80 	if err != nil {
     81 		fmt.Fprintln(os.Stderr, err)
     82 		return c.Status(400).JSON(&fiber.Map{
     83 			"error": err,
     84 		})
     85 	}
     86 	if passphrase != MYPASS {
     87 		fmt.Fprintln(os.Stderr, "Invalid passphrase.")
     88 		return c.Status(403).JSON(&fiber.Map{
     89 			"error": "Invalid passphrase",
     90 		})
     91 	}
     92 	db, err := sql.Open(SQLITE3, DB_NAME)
     93 	defer db.Close()
     94 	if err != nil {
     95 		fmt.Fprintln(os.Stderr, err)
     96 		return c.Status(400).JSON(&fiber.Map{
     97 			"error": "Error occurred.",
     98 		})
     99 	}
    100 	stmt, err := db.Prepare("DELETE FROM twts WHERE ID = ?")
    101 	if err != nil {
    102 		fmt.Fprintln(os.Stderr, err)
    103 		return c.Status(400).JSON(&fiber.Map{
    104 			"error": "Error occurred.",
    105 		})
    106 	}
    107 	_, err = stmt.Exec(id)
    108 	if err != nil {
    109 		fmt.Fprintln(os.Stderr, err)
    110 		return c.Status(400).JSON(&fiber.Map{
    111 			"error": "Error occurred.",
    112 		})
    113 	}
    114 	updateSite()
    115 	return c.SendString("DELETE request successful.")
    116 }
    117 func postTwt(c *fiber.Ctx) error {
    118 	req := map[string]string{}
    119 	c.BodyParser(&req)
    120 	content := req["content"]
    121 	passphrase := req["passphrase"]
    122 	if content == "" {
    123 		fmt.Fprintln(os.Stderr, "Missing content in POST method.")
    124 		return c.Status(400).JSON(&fiber.Map{
    125 			"error": "Missing content in POST method.",
    126 		})
    127 	}
    128 	if passphrase != MYPASS {
    129 		fmt.Fprintln(os.Stderr, "Invalid passphrase.")
    130 		return c.Status(403).JSON(&fiber.Map{
    131 			"error": "Invalid passphrase",
    132 		})
    133 	}
    134 	right_now := int(time.Now().UnixMilli()/1000) - epoch
    135 	db, err := sql.Open(SQLITE3, DB_NAME)
    136 	defer db.Close()
    137 	if err != nil {
    138 		fmt.Fprintln(os.Stderr, err)
    139 		return c.Status(400).JSON(&fiber.Map{
    140 			"error": "Error occurred.",
    141 		})
    142 	}
    143 	stmt, err := db.Prepare("INSERT INTO twts (TWEET, UNIXTIMESTAMP) VALUES(?, ?)")
    144 	if err != nil {
    145 		fmt.Fprintln(os.Stderr, err)
    146 		return c.Status(400).JSON(&fiber.Map{
    147 			"error": "Error occurred.",
    148 		})
    149 	}
    150 	_, err = stmt.Exec(content, right_now)
    151 	if err != nil {
    152 		fmt.Fprintln(os.Stderr, err)
    153 		return c.Status(400).JSON(&fiber.Map{
    154 			"error": "Error occurred.",
    155 		})
    156 	}
    157 	updateSite()
    158 	return c.SendString("POST request successful.")
    159 }
    160 func updateSite() {
    161 	os.Remove("dst/index.html")
    162 	copyHead()
    163 	fillTwts()
    164 	copyFooter()
    165 }
    166 
    167 func copyHead() {
    168 	bytesRead, err := ioutil.ReadFile("src/_header.html")
    169 	if err != nil {
    170 		fmt.Fprintln(os.Stderr, err)
    171 		return
    172 	}
    173 	err = ioutil.WriteFile("dst/index.html", bytesRead, 0644)
    174 	if err != nil {
    175 		fmt.Fprintln(os.Stderr, err)
    176 		return
    177 	}
    178 }
    179 func copyFooter() {
    180 	bytesRead, err := ioutil.ReadFile("src/_footer.html")
    181 	if err != nil {
    182 		fmt.Fprintln(os.Stderr, err)
    183 		os.Exit(1)
    184 	}
    185 	f, err := os.OpenFile("dst/index.html", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    186 	defer f.Close()
    187 	if err != nil {
    188 		fmt.Fprintln(os.Stderr, err)
    189 		os.Exit(1)
    190 	}
    191 	f.WriteString(string(bytesRead))
    192 }
    193 func fillTwts() {
    194 	twts := getTweets()
    195 	for _, elem := range twts {
    196 		friendlyDate := time.Unix(int64(elem.UNIXTIMESTAMP/1000), 0).Format(time.UnixDate)
    197 		id := strconv.Itoa(elem.ID)
    198 		div := `
    199 			<div class="entry">
    200 			  <p>` + elem.TWEET + `</p>	
    201         <a href="#` + id + `" id="` + id + `">
    202 			    <small class="date">` + friendlyDate + `</small>
    203 			  </a>
    204 		  </div>
    205 		`
    206 		f, err := os.OpenFile("dst/index.html", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    207 		defer f.Close()
    208 		if err != nil {
    209 			fmt.Fprintln(os.Stderr, err)
    210 			os.Exit(1)
    211 		}
    212 		f.WriteString(div)
    213 	}
    214 }
    215 func getTweets() []twtrDBres {
    216 	db, err := sql.Open(SQLITE3, DB_NAME)
    217 	defer db.Close()
    218 	if err != nil {
    219 		fmt.Fprintln(os.Stderr, err)
    220 		os.Exit(1)
    221 	}
    222 	rows, err := db.Query("SELECT * FROM twts ORDER BY ID DESC")
    223 	if err != nil {
    224 		fmt.Fprintln(os.Stderr, err)
    225 		os.Exit(1)
    226 	}
    227 	var res []twtrDBres
    228 	for rows.Next() {
    229 		var ID int
    230 		var TWEET string
    231 		var UNIXTIMESTAMP int
    232 		err = rows.Scan(&ID, &TWEET, &UNIXTIMESTAMP)
    233 		if err != nil {
    234 			fmt.Fprintln(os.Stderr, err)
    235 			os.Exit(1)
    236 		}
    237 		res = append(res, twtrDBres{ID, TWEET, (UNIXTIMESTAMP + epoch) * 1000})
    238 	}
    239 	return res
    240 }