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/PuerkitoBio/goquery"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/mmcdole/gofeed"
|
"github.com/mmcdole/gofeed"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Webshit struct {
|
type Webshit struct {
|
||||||
db *sqlx.DB
|
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 {
|
func New(db *sqlx.DB) *Webshit {
|
||||||
w := &Webshit{db}
|
w := &Webshit{db}
|
||||||
w.setup()
|
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
|
// setup will create any necessary SQL tables and populate them with minimal data
|
||||||
func (w *Webshit) setup() {
|
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
|
// 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}
|
news := hacknews.Initializer{Story: "topstories", NbPosts: 10}
|
||||||
ids, err := news.GetCodesStory()
|
ids, err := news.GetCodesStory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -35,11 +69,16 @@ func (w *Webshit) GetHeadlines() ([]hacknews.Post, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// GetWeekly will return the headlines in the last webshit weekly report
|
||||||
func (w *Webshit) GetWeekly() (Weekly, error) {
|
func (w *Webshit) GetWeekly() (Weekly, error) {
|
||||||
fp := gofeed.NewParser()
|
fp := gofeed.NewParser()
|
||||||
|
@ -67,10 +106,63 @@ func (w *Webshit) GetWeekly() (Weekly, error) {
|
||||||
|
|
||||||
// GetBalances returns the current balance for all known users
|
// GetBalances returns the current balance for all known users
|
||||||
// Any unknown user has a default balance on their first bid
|
// 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
|
// Bid allows a user to place a bid on a particular story
|
||||||
func (w *Webshit) Bid(user string, amount int, URL url.URL) error {
|
func (w *Webshit) Bid(user string, amount int, URL string) error {
|
||||||
return nil
|
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 (
|
import (
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
@ -10,21 +11,41 @@ import (
|
||||||
func make(t *testing.T) *Webshit {
|
func make(t *testing.T) *Webshit {
|
||||||
db := sqlx.MustOpen("sqlite3", "file::memory:?mode=memory&cache=shared")
|
db := sqlx.MustOpen("sqlite3", "file::memory:?mode=memory&cache=shared")
|
||||||
w := New(db)
|
w := New(db)
|
||||||
if w.db != db {
|
assert.Equal(t, w.db, db)
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebshit_GetWeekly(t *testing.T) {
|
func TestWebshit_GetWeekly(t *testing.T) {
|
||||||
w := make(t)
|
w := make(t)
|
||||||
weekly, err := w.GetWeekly()
|
weekly, err := w.GetWeekly()
|
||||||
if err != nil {
|
assert.Nil(t, err)
|
||||||
t.Errorf("Could not get weekly: %s", err)
|
assert.NotEmpty(t, weekly)
|
||||||
t.Fail()
|
}
|
||||||
}
|
|
||||||
if len(weekly) < 5 {
|
func TestWebshit_GetHeadlines(t *testing.T) {
|
||||||
t.Errorf("Weekly content:\n%+v", weekly)
|
w := make(t)
|
||||||
t.Fail()
|
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