Compare commits

..

8 Commits

Author SHA1 Message Date
c35608476f nuke/rebuild module
All checks were successful
continuous-integration/drone/push Build is passing
2020-03-25 09:15:31 -07:00
67f317ed98 update ci config to always build
Some checks failed
continuous-integration/drone/push Build is failing
* hopefully
2020-03-25 09:13:48 -07:00
cccddb3172 bugfixes, i think
All checks were successful
continuous-integration/drone/push Build is passing
2020-03-25 09:11:31 -07:00
0d9ed8874f made to suck less, including:
All checks were successful
continuous-integration/drone/push Build is passing
* `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
2020-03-25 07:50:10 -07:00
fe1c4df4f1 broke the build, this fixes it.
All checks were successful
continuous-integration/drone/push Build is passing
2020-03-24 21:21:09 -07:00
5d7ecfa2cc update readme
Some checks failed
continuous-integration/drone/push Build is failing
2020-03-24 21:18:48 -07:00
b48a464536 fix typo, add link to @dang thread for /about
Some checks failed
continuous-integration/drone/push Build is failing
2020-03-24 21:16:02 -07:00
ffe6670ec8 will no longer grow db unbounded 2020-03-24 21:15:40 -07:00
19 changed files with 186 additions and 150 deletions

View File

@@ -6,13 +6,12 @@ steps:
image: plugins/docker
network_mode: bridge
settings:
repo: sneak/hntransparency
repo: sneak/orangesite
dry_run: true
username:
from_secret: docker_username
password:
from_secret: docker_password
auto_tag: true
tags:
- ${DRONE_COMMIT_SHA}
- ${DRONE_BRANCH}

2
.gitignore vendored
View File

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

View File

@@ -1,6 +1,6 @@
FROM golang:1.14 as builder
WORKDIR /go/src/git.eeqj.de/sneak/hntransparencylog
WORKDIR /go/src/git.eeqj.de/sneak/orangesite
COPY . .
#RUN make lint && make build
@@ -16,9 +16,9 @@ FROM alpine
RUN mkdir -p /app/bin
COPY --from=builder /go/src/git.eeqj.de/sneak/hntransparencylog/server /app/bin/server
COPY --from=builder /go/src/git.eeqj.de/sneak/orangesite/server /app/bin/server
# FIXME figure out how to embed these stupid templates
COPY --from=builder /go/src/git.eeqj.de/sneak/hntransparencylog/view /app/view
COPY --from=builder /go/src/git.eeqj.de/sneak/orangesite/view /app/view
# put the source in there too for safekeeping
COPY --from=builder /go/go-src.tgz /usr/local/src/go-src.tgz

View File

@@ -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')
@@ -7,7 +10,7 @@ BUILDHOST := $(shell hostname -s)
BUILDARCH := $(shell uname -m)
FN := server
IMAGENAME := sneak/hntransparencylog
IMAGENAME := sneak/orangesite
UNAME_S := $(shell uname -s)

View File

@@ -1,7 +1,17 @@
# hntransparencylog
# Orangesite Transparency Log
Hacker News Transparency Log
Live: https://orangesite.sneak.cloud
Shows stories that were on the HN front page within the last 48 hours, but
aren't any more. Sorted by the amount of time they remained on the front
page, smallest first.
Shows stories that were on the orangesite front page within the last 48
hours, but aren't any more. Sorted by the amount of time they remained on
the front page, smallest first.
# TODO
* make that part about sorting not be a lie
* make that part about 48 hours not be a lie
* continue to resist the urge to use the orange
# Author
* [sneak@sneak.berlin](mailto:sneak@sneak.berlin)

View File

@@ -4,7 +4,7 @@ package main
import (
"os"
"git.eeqj.de/sneak/hntransparencylog/hn"
"git.eeqj.de/sneak/orangesite/hn"
)
var Version string

9
go.mod
View File

@@ -1,21 +1,16 @@
module git.eeqj.de/sneak/hntransparencylog
module git.eeqj.de/sneak/orangesite
go 1.14
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
github.com/labstack/echo/v4 v4.1.15
github.com/labstack/gommon v0.3.0
github.com/mattn/go-isatty v0.0.12
github.com/mayowa/echo-pongo2 v0.0.0-20170410154925-661ce95e1767
github.com/nathan-osman/pongo2-fileb0x v0.0.0-20180406192709-b069fe2eec68
github.com/peterhellberg/hn v0.0.0-20160106115829-a27cdd2ca854
github.com/rs/zerolog v1.18.0
github.com/ziflex/lecho/v2 v2.0.0
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
)

62
go.sum
View File

@@ -1,25 +1,17 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/UnnoTed/fileb0x v1.1.4 h1:IUgFzgBipF/ujNx9wZgkrKOF3oltUuXMSoaejrBws+A=
github.com/UnnoTed/fileb0x v1.1.4/go.mod h1:X59xXT18tdNk/D6j+KZySratBsuKJauMtVuJ9cgOiZs=
github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v1.0.2 h1:KPldsxuKGsS2FPWsNeg9ZO18aCrGKujPoWXn2yo+KQM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4 h1:GY1+t5Dr9OKADM64SYnQjw/w99HMYvQ0A8/JoUkxVmc=
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc=
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
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=
@@ -29,53 +21,30 @@ github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5 h1:rhqTjzJlm7EbkELJDKM
github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/k0kubun/pp v1.3.0 h1:r9td75hcmetrcVbmsZRjnxcIbI9mhm+/N6iWyG4TWe0=
github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/karrick/godirwalk v1.7.8 h1:VfG72pyIxgtC7+3X9CMHI0AOl4LwyRAg98WAgsvffi8=
github.com/karrick/godirwalk v1.7.8/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo v1.4.4 h1:1bEiBNeGSUKxcPDGfZ/7IgdhJJZx8wV/pICJh4W2NJI=
github.com/labstack/echo v3.2.1+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/echo/v4 v4.1.10 h1:/yhIpO50CBInUbE/nHJtGIyhBv0dJe2cDAYxc3V3uMo=
github.com/labstack/echo/v4 v4.1.10/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/echo/v4 v4.1.15 h1:4aE6KfJC+wCnMjODwcpeEGWGsRfszxZMwB3QVTECj2I=
github.com/labstack/echo/v4 v4.1.15/go.mod h1:GWO5IBVzI371K8XJe50CSvHjQCafK6cw8R/moLhEU6o=
github.com/labstack/gommon v0.2.7/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw=
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/mayowa/echo-pongo2 v0.0.0-20170410154925-661ce95e1767 h1:T8fARjLT0o9OkyYmCAm3UuPVWm6/8yTAt4rmmWVTORI=
github.com/mayowa/echo-pongo2 v0.0.0-20170410154925-661ce95e1767/go.mod h1:JCIHkkBgcmXEr/rc3YhaxQ9MgZ4GJe7wjEV/is2uuag=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/nathan-osman/pongo2-fileb0x v0.0.0-20180406192709-b069fe2eec68 h1:h11XoSnZets0sfHYNDJTfN25OnC5u7YwVfqt2tEjTTc=
github.com/nathan-osman/pongo2-fileb0x v0.0.0-20180406192709-b069fe2eec68/go.mod h1:RQeQ4BP2ZHGo+QjbNu3b3C+ogX6fbX+dVz+5nuC3fE0=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/peterhellberg/hn v0.0.0-20160106115829-a27cdd2ca854 h1:K6zV6rLnXlmq8H7gqclq/K8ZANQyqpvhrzSkq70qoZw=
github.com/peterhellberg/hn v0.0.0-20160106115829-a27cdd2ca854/go.mod h1:4NUrlv14rntJHyfqrF46i63j+7lUU8yIx/y6ORuO32M=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
@@ -83,45 +52,34 @@ github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThC
github.com/rs/zerolog v1.18.0 h1:CbAm3kP2Tptby1i9sYy2MGRg0uxIN9cyDb59Ys7W8z8=
github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.1.0 h1:RZqt0yGBsps8NGvLSGW804QQqCUYYLsaOjTVHy1Ocw4=
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
github.com/ziflex/lecho v1.2.0 h1:/ykfd7V/aTsWUYNFimgbdhUiEMnWzvNaCxtbM/LX5F8=
github.com/ziflex/lecho/v2 v2.0.0 h1:ggrWF5LaGAC+Y+WX71jFK7uYR7cUFbHjIgGqCyrYC5Q=
github.com/ziflex/lecho/v2 v2.0.0/go.mod h1:s7dy9Fynjx6z+/7xE2BsK13vXIS3oQoo4ZaKXYG5xUs=
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180921000356-2f5d2388922f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20181019160139-8e24a49d80f8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -129,6 +87,4 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -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
}

View File

@@ -12,8 +12,6 @@ import (
"github.com/rs/zerolog"
)
const SQLITE_NULL_DATETIME = "0001-01-01 00:00:00+00:00"
func NewFetcher(db *gorm.DB) *Fetcher {
f := new(Fetcher)
f.db = db
@@ -82,29 +80,39 @@ func (f *Fetcher) StoreFrontPage() error {
if err != nil {
return (err)
}
s := HNStoryRank{
HNID: uint(id),
Rank: uint(i + 1),
URL: item.URL,
Title: item.Title,
FetchedAt: t,
}
/*
s := HNStoryRank{
HNID: uint(id),
Rank: uint(i + 1),
URL: item.URL,
Title: item.Title,
Score: item.Score,
FetchedAt: t,
}
*/
//f.log.Debug().Msgf("storing story with rank %d in db", (i + 1))
// FIXME this will grow unbounded and make the file too big if
// I don't clean this up or otherwise limit the data in here
f.db.Create(&s)
// disabled for now
//f.db.Create(&s)
//FIXME check to see if the same HNID was already on the frontpage
//or not so we don't spam the db
// check to see if the item was on the frontpage already or not
var c int
f.db.Model(&HNFrontPage{}).Where("hn_id = ? and disappeared is ?", id, SQLITE_NULL_DATETIME).Count(&c)
f.db.Model(&HNFrontPage{}).Where("hn_id = ?", id).Count(&c)
if c == 0 {
// first appearance on frontpage
r := HNFrontPage{
HNID: uint(id),
Appeared: t,
Disappeared: time.Time{},
HighestRank: uint(i + 1),
Rank: uint(i + 1),
Title: item.Title,
Score: uint(item.Score),
URL: item.URL,
}
f.db.Create(&r)
@@ -112,24 +120,25 @@ 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 {
// it's still here, compare its ranking
// it's still here, (or back)
var old HNFrontPage
f.db.Model(&HNFrontPage{}).Where("hn_id = ? and disappeared is ?", id, SQLITE_NULL_DATETIME).First(&old)
// FIXME update highestrank if new is lower
needSave := false
f.db.Model(&HNFrontPage{}).Where("hn_id = ?", id).First(&old)
if old.Rank != uint(i+1) {
f.log.Info().
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)
needSave = true
old.Score = uint(item.Score)
}
if old.HighestRank > uint(i+1) {
@@ -139,18 +148,22 @@ func (f *Fetcher) StoreFrontPage() error {
Uint("newrecord", uint(i+1)).
Msg("recording new record high rank for story")
old.HighestRank = uint(i + 1)
needSave = true
}
if needSave {
f.db.Save(&old)
if old.Score != uint(item.Score) {
old.Score = uint(item.Score)
}
// in any case it's here now
old.Disappeared = time.Time{}
f.db.Save(&old)
}
}
// FIXME iterate over frontpage items still active in DB and note any
// that are no longer on the scrape
fpitems, err := f.db.Model(&HNFrontPage{}).Where("disappeared is ?", SQLITE_NULL_DATETIME).Rows()
fpitems, err := f.db.Model(&HNFrontPage{}).Where("disappeared is ?", time.Time{}).Rows()
if err != nil {
f.log.Error().
Err(err)
@@ -181,8 +194,8 @@ func (f *Fetcher) StoreFrontPage() error {
}
}
fpitems.Close() // close tx before we do the update
f.db.Model(&HNFrontPage{}).Where("disappeared is ? and hn_id in (?)", SQLITE_NULL_DATETIME, toupdate).Update("Disappeared", t)
fpitems.Close() // close result before we do the update
f.db.Model(&HNFrontPage{}).Where("disappeared is ? and hn_id in (?)", time.Time{}, toupdate).Update("Disappeared", t)
return nil
}

View File

@@ -10,61 +10,73 @@ import (
)
type RequestHandlerSet struct {
db *gorm.DB
db *gorm.DB
version string
}
func NewRequestHandlerSet(db *gorm.DB) *RequestHandlerSet {
func NewRequestHandlerSet(version string, db *gorm.DB) *RequestHandlerSet {
rhs := new(RequestHandlerSet)
rhs.db = db
rhs.version = version
return rhs
}
func (r *RequestHandlerSet) indexHandler(c echo.Context) error {
var fpi []HNFrontPage
r.db.Where("disappeared is not ?", SQLITE_NULL_DATETIME).Order("disappeared desc").Find(&fpi)
r.db.Where("disappeared is not ?", time.Time{}).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
var cur []HNFrontPage
r.db.Where("disappeared is ?", SQLITE_NULL_DATETIME).Order("rank asc").Find(&cur)
r.db.Where("disappeared is ?", time.Time{}).Order("rank asc").Find(&cur)
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,
})
}
@@ -72,13 +84,15 @@ func (r *RequestHandlerSet) indexHandler(c echo.Context) error {
"time": time.Now().UTC().Format(time.RFC3339Nano),
"exits": fprows,
"current": currentfp,
"gitrev": r.version,
}
return c.Render(http.StatusOK, "index.html", tc)
}
func (r *RequestHandlerSet) aboutHandler(c echo.Context) error {
tc := pongo2.Context{
"time": time.Now().UTC().Format(time.RFC3339Nano),
"time": time.Now().UTC().Format(time.RFC3339Nano),
"gitrev": r.version,
}
return c.Render(http.StatusOK, "about.html", tc)
}

20
hn/misc.go Normal file
View File

@@ -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()))
}

View File

@@ -122,7 +122,7 @@ func (a *App) runForever() int {
}
a.e.Renderer = r
rhs := NewRequestHandlerSet(a.db)
rhs := NewRequestHandlerSet(a.version, a.db)
// Routes
a.e.GET("/", rhs.indexHandler)

View File

@@ -5,13 +5,15 @@
<div class="col-lg-12">
<h1>About This Site</h1>
<h2>IMPORTANT</h2>
<h2>⚠️ Important!</h2>
<p>This is a third-party site, not affiliated with HN, provided for
informational purposes only. <b>Do not</b> contact or hassle HN
administrators about any information you learn here. Their site,
their rules. I repeat: <b>Do not hassle or interrogate the HN admins.</b>
</p>
<p>This is a third-party site, not affiliated in any way with HN,
provided for informational purposes only. <b>Do not</b> contact or
hassle HN administrators about any information you learn here.
Their site, their rules. I repeat: <b>Do not hassle or interrogate
the HN admins about their front page.</b> <small>(<a
href="https://news.ycombinator.com/item?id=22643777">more
info</a>)</small> </p>
<h2>Why?</h2>
@@ -22,12 +24,9 @@
<h2>How?</h2>
<p><a href="https://git.eeqj.de/sneak/hntransparencylog">Go</a> and the
<p>Go and the
graciously provided <a href="https://github.com/HackerNews/API">HN
API</a>.</p>
<h2>Who</h2>
<p><a href="mailto:sneak@sneak.berlin">@sneak</a>.</p>
</div>
{% endblock %}

View File

@@ -13,14 +13,7 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<style>
body {
background: #f6f6ef;
}
#pagebody {
margin-top: 4em;
}
{% include "style.css" %}
</style>
</head>

10
view/bodyfooter.html Normal file
View File

@@ -0,0 +1,10 @@
<footer>
<small>
A project by <a href="https://sneak.berlin">@sneak</a>.
&nbsp;&nbsp;&nbsp;&nbsp;
<code>{{gitrev}}</code>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="http://git.eeqj.de/sneak/orangesite">source</a> (<a
href="https://en.wikipedia.org/wiki/WTFPL">WTFPL</a>)
</small>
</footer>

View File

@@ -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>
@@ -55,8 +61,5 @@
</tbody>
</table>
<small>{{ time }}</small>
</div>
{% endblock %}

View File

@@ -12,4 +12,5 @@
{% endblock %}
</div>
</div>
{% include "bodyfooter.html" %}
{% endblock %}

18
view/style.css Normal file
View File

@@ -0,0 +1,18 @@
body {
background: #f6f6ef;
}
#pagebody {
margin-top: 4em;
}
footer {
padding-left: 1em;
padding-top: 2em;
padding-bottom: 0.5em;
}
h1,h2,h3,h4 {
padding-top: 1em;
padding-bottom: 0.25em;
}