made to suck less, including:

* `make` works again, exporting correct database file path for local dev
* better formatting of durations
* refactored duration math to misc functions
* now tracks and displays score
* displays short-lifetime fp wipeouts in red
dev
Jeffrey Paul 4 years ago
parent fe1c4df4f1
commit 0d9ed8874f
  1. 2
      .gitignore
  2. 3
      Makefile
  3. 1
      go.mod
  4. 2
      go.sum
  5. 2
      hn/db.go
  6. 11
      hn/fetcher.go
  7. 58
      hn/handlers.go
  8. 20
      hn/misc.go
  9. 14
      view/index.html

2
.gitignore vendored

@ -13,4 +13,4 @@
*.out
server
storage.db
storage.sqlite

@ -1,3 +1,6 @@
# for development, db in cwd
export DATABASE_PATH := ./storage.sqlite
VERSION := $(shell git rev-parse --short HEAD)
BUILDTIME := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
BUILDTIMEFILENAME := $(shell date -u '+%Y%m%d-%H%M%SZ')

@ -6,6 +6,7 @@ require (
github.com/UnnoTed/fileb0x v1.1.4 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4
github.com/jinzhu/gorm v1.9.12
github.com/k0kubun/pp v3.0.1+incompatible
github.com/labstack/echo v3.3.10+incompatible

@ -20,6 +20,8 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclK
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4 h1:60gBOooTSmNtrqNaRvrDbi8VAne0REaek2agjnITKSw=
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=

@ -17,6 +17,7 @@ type HNFrontPage struct {
HighestRank uint // frontpage index
Rank uint // frontpage index
Title string // submission title
Score uint // updoots
URL string // duh
}
@ -27,6 +28,7 @@ type HNStoryRank struct {
Title string // submission title
URL string // duh
Rank uint // frontpage index
Score uint // updoots
FetchedAt time.Time // identical within fetchid
}

@ -88,6 +88,7 @@ func (f *Fetcher) StoreFrontPage() error {
Rank: uint(i + 1),
URL: item.URL,
Title: item.Title,
Score: item.Score,
FetchedAt: t,
}
*/
@ -109,6 +110,7 @@ func (f *Fetcher) StoreFrontPage() error {
HighestRank: uint(i + 1),
Rank: uint(i + 1),
Title: item.Title,
Score: uint(item.Score),
URL: item.URL,
}
f.db.Create(&r)
@ -116,6 +118,7 @@ func (f *Fetcher) StoreFrontPage() error {
Uint("hnid", uint(id)).
Uint("rank", uint(i+1)).
Str("title", item.Title).
Int("score", item.Score).
Str("url", item.URL).
Msg("HN new story on frontpage")
} else {
@ -129,10 +132,12 @@ func (f *Fetcher) StoreFrontPage() error {
Uint("hnid", uint(id)).
Uint("oldrank", old.Rank).
Uint("newrank", uint(i+1)).
Int("score", item.Score).
Str("title", item.Title).
Str("url", item.URL).
Msg("HN story rank changed, recording new rank")
old.Rank = uint(i + 1)
old.Score = uint(item.Score)
needSave = true
}
@ -145,6 +150,12 @@ func (f *Fetcher) StoreFrontPage() error {
old.HighestRank = uint(i + 1)
needSave = true
}
if old.Score != uint(item.Score) {
old.Score = uint(item.Score)
needSave = true
}
if needSave {
f.db.Save(&old)
}

@ -24,33 +24,41 @@ func (r *RequestHandlerSet) indexHandler(c echo.Context) error {
r.db.Where("disappeared is not ?", SQLITE_NULL_DATETIME).Order("disappeared desc").Find(&fpi)
type fprow struct {
Duration string
URL string
Title string
HighestRank uint
HNID uint
TimeGone string
Duration string
DurationSecs uint
URL string
Title string
HighestRank uint
HNID uint
Score uint
TimeGone string
TimeGoneSecs uint
}
var fprows []fprow
for _, item := range fpi {
fprows = append(fprows, fprow{
Duration: item.Disappeared.Round(time.Minute).Sub(item.Appeared.Round(time.Minute)).String(),
URL: item.URL,
HNID: item.HNID,
Title: item.Title,
HighestRank: item.HighestRank,
TimeGone: time.Now().Round(time.Minute).Sub(item.Disappeared.Round(time.Minute)).String(),
Duration: timeDiffHuman(item.Disappeared, item.Appeared),
DurationSecs: timeDiffAbsSeconds(item.Disappeared, item.Appeared),
URL: item.URL,
HNID: item.HNID,
Score: item.Score,
Title: item.Title,
HighestRank: item.HighestRank,
TimeGone: timeDiffHuman(time.Now(), item.Disappeared),
TimeGoneSecs: timeDiffAbsSeconds(time.Now(), item.Disappeared),
})
}
type rowtwo struct {
Duration string
URL string
Title string
HighestRank uint
HNID uint
Rank uint
Duration string
DurationSecs uint
URL string
Title string
Score uint
HighestRank uint
HNID uint
Rank uint
}
var currentfp []rowtwo
@ -59,12 +67,14 @@ func (r *RequestHandlerSet) indexHandler(c echo.Context) error {
for _, item := range cur {
currentfp = append(currentfp, rowtwo{
Duration: time.Now().Round(time.Minute).Sub(item.Appeared.Round(time.Minute)).String(),
URL: item.URL,
HNID: item.HNID,
Title: item.Title,
HighestRank: item.HighestRank,
Rank: item.Rank,
Duration: timeDiffHuman(time.Now(), item.Appeared),
DurationSecs: timeDiffAbsSeconds(time.Now(), item.Appeared),
URL: item.URL,
HNID: item.HNID,
Score: item.Score,
Title: item.Title,
HighestRank: item.HighestRank,
Rank: item.Rank,
})
}

@ -0,0 +1,20 @@
package hn
import (
"math"
"time"
"github.com/hako/durafmt"
)
func timeDiffHuman(first time.Time, second time.Time) string {
if first.Before(second) {
return durafmt.ParseShort(second.Sub(first)).String()
} else {
return durafmt.ParseShort(first.Sub(second)).String()
}
}
func timeDiffAbsSeconds(first time.Time, second time.Time) uint {
return uint(math.Abs(first.Sub(second).Truncate(time.Second).Seconds()))
}

@ -11,7 +11,8 @@
<th scope="col">Hang Time</th>
<th scope="col">Title</th>
<th scope="col">Highest Rank</th>
<th scope="col">Time Since Wipeout</th>
<th scope="col">Time Since <a
href="https://www.youtube.com/watch?v=p13yZAjhU0M">Wipeout</a></th>
</tr>
</thead>
<tbody>
@ -21,8 +22,13 @@
-->
<tr>
<td scope="row">{{exit.Duration}}</th>
<td><a href="{{exit.URL}}">{{exit.Title}}</a> <small>(<a
{% if exit.DurationSecs < 1800 %}
<td scope="row" class="text-danger">{{exit.Duration}}</th>
{% else %}
<td scope="row">{{exit.Duration}}</th>
{% endif %}
<td><a href="{{exit.URL}}">{{exit.Title}}</a> <small>({{exit.Score}}
points, <a
href="https://news.ycombinator.com/item?id={{exit.HNID}}">comments</a>)</small></td>
<td>{{exit.HighestRank}}</td>
<td>{{exit.TimeGone}}</td>
@ -47,7 +53,7 @@
<tr>
<td scope="row">{{i.Duration}}</th>
<td><a href="{{i.URL}}">{{i.Title}}</a> <small>(<a
<td><a href="{{i.URL}}">{{i.Title}}</a> <small>({{i.Score}} points, <a
href="https://news.ycombinator.com/item?id={{i.HNID}}">comments</a>)</small></td>
<td>{{i.HighestRank}}</td>
</tr>

Loading…
Cancel
Save