mirror of https://github.com/velour/catbase.git
bid: add some tests and tables
This commit is contained in:
parent
cdff69abdc
commit
04239ec807
|
@ -7,13 +7,31 @@ import (
|
|||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/mmcdole/gofeed"
|
||||
"github.com/rs/zerolog/log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Webshit struct {
|
||||
db *sqlx.DB
|
||||
}
|
||||
|
||||
type Weekly []string
|
||||
|
||||
type Story struct {
|
||||
Title string
|
||||
URL string
|
||||
}
|
||||
|
||||
type Bid struct {
|
||||
ID int
|
||||
User string
|
||||
Title string
|
||||
URL string
|
||||
Bid int
|
||||
}
|
||||
|
||||
func New(db *sqlx.DB) *Webshit {
|
||||
w := &Webshit{db}
|
||||
w.setup()
|
||||
|
@ -22,10 +40,26 @@ func New(db *sqlx.DB) *Webshit {
|
|||
|
||||
// setup will create any necessary SQL tables and populate them with minimal data
|
||||
func (w *Webshit) setup() {
|
||||
if _, err := w.db.Exec(`create table if not exists webshit_bids (
|
||||
id integer primary key,
|
||||
user string,
|
||||
title string,
|
||||
url string,
|
||||
bid integer
|
||||
)`); err != nil {
|
||||
log.Fatal().Err(err)
|
||||
}
|
||||
if _, err := w.db.Exec(`create table if not exists webshit_balances (
|
||||
user string primary key,
|
||||
balance int,
|
||||
score int
|
||||
)`); err != nil {
|
||||
log.Fatal().Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetHeadlines will return the current possible news headlines for bidding
|
||||
func (w *Webshit) GetHeadlines() ([]hacknews.Post, error) {
|
||||
func (w *Webshit) GetHeadlines() ([]Story, error) {
|
||||
news := hacknews.Initializer{Story: "topstories", NbPosts: 10}
|
||||
ids, err := news.GetCodesStory()
|
||||
if err != nil {
|
||||
|
@ -35,11 +69,16 @@ func (w *Webshit) GetHeadlines() ([]hacknews.Post, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return posts, nil
|
||||
var stories []Story
|
||||
for _, p := range posts {
|
||||
stories = append(stories, Story{
|
||||
Title: p.Title,
|
||||
URL: p.Url,
|
||||
})
|
||||
}
|
||||
return stories, nil
|
||||
}
|
||||
|
||||
type Weekly []string
|
||||
|
||||
// GetWeekly will return the headlines in the last webshit weekly report
|
||||
func (w *Webshit) GetWeekly() (Weekly, error) {
|
||||
fp := gofeed.NewParser()
|
||||
|
@ -67,10 +106,63 @@ func (w *Webshit) GetWeekly() (Weekly, error) {
|
|||
|
||||
// GetBalances returns the current balance for all known users
|
||||
// Any unknown user has a default balance on their first bid
|
||||
func (w *Webshit) GetBalances() {
|
||||
func (w *Webshit) GetBalance(user string) int {
|
||||
q := `select balance from webshit_balances where user=?`
|
||||
var balance int
|
||||
err := w.db.Get(&balance, q, user)
|
||||
if err != nil {
|
||||
return 100
|
||||
}
|
||||
return balance
|
||||
}
|
||||
|
||||
// Bid allows a user to place a bid on a particular story
|
||||
func (w *Webshit) Bid(user string, amount int, URL url.URL) error {
|
||||
return nil
|
||||
func (w *Webshit) Bid(user string, amount int, URL string) error {
|
||||
bal := w.GetBalance(user)
|
||||
if bal < amount {
|
||||
return fmt.Errorf("cannot bid more than balance, %d", bal)
|
||||
}
|
||||
story, err := w.getStoryByURL(URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Need a transaction here to deduct from the users balance (or create it)
|
||||
_, err = w.db.Exec(`insert into webshit_bids (user,title,url,bid) values (?,?,?,?)`,
|
||||
user, story.Title, story.URL, amount)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// getStoryByURL scrapes the URL for a title
|
||||
func (w *Webshit) getStoryByURL(URL string) (Story, error) {
|
||||
u, err := url.Parse(URL)
|
||||
if err != nil {
|
||||
return Story{}, err
|
||||
}
|
||||
if u.Host != "news.ycombinator.com" {
|
||||
return Story{}, fmt.Errorf("expected HN link")
|
||||
}
|
||||
res, err := http.Get(URL)
|
||||
if err != nil {
|
||||
return Story{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != 200 {
|
||||
return Story{}, fmt.Errorf("bad response code: %d", res.StatusCode)
|
||||
}
|
||||
|
||||
// Load the HTML document
|
||||
doc, err := goquery.NewDocumentFromReader(res.Body)
|
||||
if err != nil {
|
||||
return Story{}, err
|
||||
}
|
||||
|
||||
// Find the review items
|
||||
title := doc.Find("title").Text()
|
||||
title = strings.ReplaceAll(title, " | Hacker News", "")
|
||||
return Story{
|
||||
Title: title,
|
||||
URL: URL,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package webshit
|
|||
|
||||
import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
|
@ -10,21 +11,41 @@ import (
|
|||
func make(t *testing.T) *Webshit {
|
||||
db := sqlx.MustOpen("sqlite3", "file::memory:?mode=memory&cache=shared")
|
||||
w := New(db)
|
||||
if w.db != db {
|
||||
t.Fail()
|
||||
}
|
||||
assert.Equal(t, w.db, db)
|
||||
return w
|
||||
}
|
||||
|
||||
func TestWebshit_GetWeekly(t *testing.T) {
|
||||
w := make(t)
|
||||
weekly, err := w.GetWeekly()
|
||||
if err != nil {
|
||||
t.Errorf("Could not get weekly: %s", err)
|
||||
t.Fail()
|
||||
}
|
||||
if len(weekly) < 5 {
|
||||
t.Errorf("Weekly content:\n%+v", weekly)
|
||||
t.Fail()
|
||||
}
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, weekly)
|
||||
}
|
||||
|
||||
func TestWebshit_GetHeadlines(t *testing.T) {
|
||||
w := make(t)
|
||||
headlines, err := w.GetHeadlines()
|
||||
assert.Nil(t, err)
|
||||
assert.NotEmpty(t, headlines)
|
||||
}
|
||||
|
||||
func TestWebshit_getStoryByURL(t *testing.T) {
|
||||
w := make(t)
|
||||
expected := "Developer Tropes: “Google Does It”"
|
||||
s, err := w.getStoryByURL("https://news.ycombinator.com/item?id=20432887")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, s.Title, expected)
|
||||
}
|
||||
|
||||
func TestWebshit_getStoryByURL_BadURL(t *testing.T) {
|
||||
w := make(t)
|
||||
_, err := w.getStoryByURL("https://google.com")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestWebshit_GetBalance(t *testing.T) {
|
||||
w := make(t)
|
||||
expected := 100
|
||||
actual := w.GetBalance("foo")
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue