<commit_before>package user

import (
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
)

func init() {
	config.Settings.Limits.PasswordMinLength = 8
	config.Settings.Limits.PasswordMaxLength = 128
}

func TestDefaultUser(t *testing.T) {

	user := DefaultUser()

	assert.Equal(t, uint(1), user.Id, "default user id should be 1")

	assert.False(t, user.IsAuthenticated, "default user should not be authenticated")

}

func TestSetId(t *testing.T) {

	user := DefaultUser()

	user.SetId(2)

	assert.Equal(t, uint(2), user.Id, "user id should be 2")

}

func TestSetAuthenticated(t *testing.T) {

	user := DefaultUser()

	user.SetAuthenticated()

	assert.False(t, user.IsAuthenticated, "User should be not authorized")

	user.SetId(2)

	user.SetAuthenticated()

	assert.True(t, user.IsAuthenticated, "User should be authorized")

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

}

func TestIsValid(t *testing.T) {

	user := DefaultUser()

	assert.True(t, user.IsValid(), "DefaultUser should be valid")

	user.SetId(2)

	assert.False(t, user.IsValid(), "Unauthenticated non-anon should be invalid")

	user.SetAuthenticated()

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

	user.SetId(0)

	assert.False(t, user.IsValid(), "User zero should be invalid")

	user.SetId(1)

	assert.False(t, user.IsValid(), "An authenticated anon user should be invalid")

}

func TestIsValidName(t *testing.T) {

	assert.True(t, IsValidName("cooldude2"), "Name should validate")

	assert.True(t, IsValidName("cool dude"), "Name should validate")

	assert.True(t, IsValidName("cool_dude"), "Name should validate")

	assert.True(t, IsValidName("cool-dude"), "Name should validate")

	assert.False(t, IsValidName("cool.dude"), "Name should not validate")

	assert.False(t, IsValidName("cooldude!"), "Name should not validate")

	assert.False(t, IsValidName("admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin "), "Name should not validate")

	assert.False(t, IsValidName(" Admin  "), "Name should not validate")

}

func TestPassword(t *testing.T) {

	_, err := HashPassword("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordEmpty, "Error should match")
	}

	_, err = HashPassword("heh")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordShort, "Error should match")
	}

	_, err = HashPassword("k8dyuCqJfW9v5iFUeeS4YOeiuk5Wee6Q9tZvWFHqE10ftzhaxVzxlKzx4n7CcBpRcgtaX9dZ2lBIRrsvgqXPPvmjNpIgnrums2Xtst8FsZkpZo61u3ChCs7MEO1DGy4Qa")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordLong, "Error should match")
	}

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	assert.False(t, user.ComparePassword("atestpassword"), "Password should not validate")

	user.hash = password

	assert.False(t, user.ComparePassword(""), "Password should not validate")

	assert.False(t, user.ComparePassword("wrongpassword"), "Password should not validate")

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

}

func TestCreateToken(t *testing.T) {

	Secret = ""

	user := DefaultUser()

	// secret must be set
	token, err := user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrNoSecret, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	Secret = "secret"

	// default user state should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetId(2)

	// a non authed user should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetAuthenticated()

	// a user that doesnt have a validated password should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrInvalidPassword, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.hash, err = HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, user.hash, "password should be returned")
	}

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

	token, err = user.CreateToken()
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotEmpty(t, token, "Token should not be empty")
	}

}

func TestCreateTokenAnonAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(1)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroNoAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestUserPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	err = user.Password()
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Name, "testaccount", "Name should match")
		assert.True(t, user.ComparePassword("testpassword"), "Password should validate")
	}
}

func TestUserBadPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	err = user.Password()
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Name, "testaccount", "Name should match")
		assert.False(t, user.ComparePassword("badpassword"), "Password should not validate")
	}
}

func TestFromName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(2, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	err = user.FromName("testaccount")
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Id, uint(2), "Id should match")
		assert.True(t, user.IsAuthenticated, "User should be authenticated")
		assert.True(t, user.ComparePassword("testpassword"), "Password should validate")
	}

}

func TestFromNameEmptyName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	err := user.FromName("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}

func TestFromNameBadId(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(0, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	err = user.FromName("test")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}
<commit_msg>add user password sql check<commit_after>package user

import (
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"testing"

	"github.com/eirka/eirka-libs/config"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
)

func init() {
	config.Settings.Limits.PasswordMinLength = 8
	config.Settings.Limits.PasswordMaxLength = 128
}

func TestDefaultUser(t *testing.T) {

	user := DefaultUser()

	assert.Equal(t, uint(1), user.Id, "default user id should be 1")

	assert.False(t, user.IsAuthenticated, "default user should not be authenticated")

}

func TestSetId(t *testing.T) {

	user := DefaultUser()

	user.SetId(2)

	assert.Equal(t, uint(2), user.Id, "user id should be 2")

}

func TestSetAuthenticated(t *testing.T) {

	user := DefaultUser()

	user.SetAuthenticated()

	assert.False(t, user.IsAuthenticated, "User should be not authorized")

	user.SetId(2)

	user.SetAuthenticated()

	assert.True(t, user.IsAuthenticated, "User should be authorized")

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

}

func TestIsValid(t *testing.T) {

	user := DefaultUser()

	assert.True(t, user.IsValid(), "DefaultUser should be valid")

	user.SetId(2)

	assert.False(t, user.IsValid(), "Unauthenticated non-anon should be invalid")

	user.SetAuthenticated()

	assert.True(t, user.IsValid(), "Authed non-anon user should be valid")

	user.SetId(0)

	assert.False(t, user.IsValid(), "User zero should be invalid")

	user.SetId(1)

	assert.False(t, user.IsValid(), "An authenticated anon user should be invalid")

}

func TestIsValidName(t *testing.T) {

	assert.True(t, IsValidName("cooldude2"), "Name should validate")

	assert.True(t, IsValidName("cool dude"), "Name should validate")

	assert.True(t, IsValidName("cool_dude"), "Name should validate")

	assert.True(t, IsValidName("cool-dude"), "Name should validate")

	assert.False(t, IsValidName("cool.dude"), "Name should not validate")

	assert.False(t, IsValidName("cooldude!"), "Name should not validate")

	assert.False(t, IsValidName("admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin"), "Name should not validate")

	assert.False(t, IsValidName("Admin "), "Name should not validate")

	assert.False(t, IsValidName(" Admin  "), "Name should not validate")

}

func TestPassword(t *testing.T) {

	_, err := HashPassword("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordEmpty, "Error should match")
	}

	_, err = HashPassword("heh")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordShort, "Error should match")
	}

	_, err = HashPassword("k8dyuCqJfW9v5iFUeeS4YOeiuk5Wee6Q9tZvWFHqE10ftzhaxVzxlKzx4n7CcBpRcgtaX9dZ2lBIRrsvgqXPPvmjNpIgnrums2Xtst8FsZkpZo61u3ChCs7MEO1DGy4Qa")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrPasswordLong, "Error should match")
	}

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	assert.False(t, user.ComparePassword("atestpassword"), "Password should not validate")

	user.hash = password

	assert.False(t, user.ComparePassword(""), "Password should not validate")

	assert.False(t, user.ComparePassword("wrongpassword"), "Password should not validate")

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

}

func TestCreateToken(t *testing.T) {

	Secret = ""

	user := DefaultUser()

	// secret must be set
	token, err := user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrNoSecret, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	Secret = "secret"

	// default user state should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetId(2)

	// a non authed user should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.SetAuthenticated()

	// a user that doesnt have a validated password should never get a token
	token, err = user.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrInvalidPassword, "Error should match")
		assert.Empty(t, token, "Token should be empty")
	}

	user.hash, err = HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, user.hash, "password should be returned")
	}

	assert.True(t, user.ComparePassword("testpassword"), "Password should validate")

	token, err = user.CreateToken()
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotEmpty(t, token, "Token should not be empty")
	}

}

func TestCreateTokenAnonAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(1)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)
	invalidUser.SetAuthenticated()

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestCreateTokenZeroNoAuth(t *testing.T) {

	Secret = "secret"

	invalidUser := DefaultUser()
	invalidUser.SetId(0)

	notoken, err := invalidUser.CreateToken()
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
		assert.Empty(t, notoken, "token should not be returned")
	}
}

func TestUserPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	err = user.Password()
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Name, "testaccount", "Name should match")
		assert.True(t, user.ComparePassword("testpassword"), "Password should validate")
	}
}

func TestUserBadPassword(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()
	user.SetId(2)
	user.SetAuthenticated()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"name", "password"}).AddRow("testaccount", password)

	mock.ExpectQuery("select user_name, user_password from users where user_id").WillReturnRows(rows)

	err = user.Password()
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Name, "testaccount", "Name should match")
		assert.False(t, user.ComparePassword("badpassword"), "Password should not validate")
	}
}

func TestFromName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(2, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	err = user.FromName("testaccount")
	if assert.NoError(t, err, "An error was not expected") {
		assert.Equal(t, user.Id, uint(2), "Id should match")
		assert.True(t, user.IsAuthenticated, "User should be authenticated")
		assert.True(t, user.ComparePassword("testpassword"), "Password should validate")
	}

}

func TestFromNameEmptyName(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	err := user.FromName("")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}

func TestFromNameBadId(t *testing.T) {

	Secret = "secret"

	user := DefaultUser()

	password, err := HashPassword("testpassword")
	if assert.NoError(t, err, "An error was not expected") {
		assert.NotNil(t, password, "password should be returned")
	}

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"id", "password"}).AddRow(0, password)

	mock.ExpectQuery("select user_id, user_password from users where user_name").WillReturnRows(rows)

	err = user.FromName("test")
	if assert.Error(t, err, "An error was expected") {
		assert.Equal(t, err, e.ErrUserNotValid, "Error should match")
	}

}

func TestCheckDuplicateGood(t *testing.T) {

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"count"}).AddRow(0)

	mock.ExpectQuery("select count(*) from users where user_name").WillReturnRows(rows)

	assert.False(t, CheckDuplicate(), "Should not be a duplicate")

}

func TestCheckDuplicateBad(t *testing.T) {

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	rows := sqlmock.NewRows([]string{"count"}).AddRow(1)

	mock.ExpectQuery("select count(*) from users where user_name").WillReturnRows(rows)

	assert.True(t, CheckDuplicate(), "Should be a duplicate")

}
<|endoftext|>


<commit_before>package omise

import "time"

// Receipt represents Omise's receipt object.
// See https://www.omise.co/receipts-api for more information.
type Receipt struct {
	Base
	Number                string    `json:"number"`
	Date                  time.Time `json:"date"`
	CustomerName          string    `json:"customer_name"`
	CustomerAddress       string    `json:"customer_address"`
	CustomerTaxID         string    `json:"customer_tax_id"`
	CustomerEmail         string    `json:"customer_email"`
	CustomerStatementName string    `json:"customer_statement_name"`

	CompanyName    string `json:"company_name"`
	CompanyAddress string `json:"company_address"`
	CompanyTaxID   string `json:"company_tax_id"`

	ChargeFee   int64  `json:"charge_fee"`
	VoidedFee   int64  `json:"voided_fee"`
	TransferFee int64  `json:"transfer_fee"`
	SubTotal    int64  `json:"subtotal"`
	VAT         int64  `json:"vat"`
	WHT         int64  `json:"wht"`
	Total       int64  `json:"total"`
	CreditNote  bool   `json:"credit_note"`
	Currency    string `json:"currency"`
}
<commit_msg>Fix incorrect receipt url<commit_after>package omise

import "time"

// Receipt represents Omise's receipt object.
// See https://www.omise.co/receipt-api for more information.
type Receipt struct {
	Base
	Number                string    `json:"number"`
	Date                  time.Time `json:"date"`
	CustomerName          string    `json:"customer_name"`
	CustomerAddress       string    `json:"customer_address"`
	CustomerTaxID         string    `json:"customer_tax_id"`
	CustomerEmail         string    `json:"customer_email"`
	CustomerStatementName string    `json:"customer_statement_name"`

	CompanyName    string `json:"company_name"`
	CompanyAddress string `json:"company_address"`
	CompanyTaxID   string `json:"company_tax_id"`

	ChargeFee   int64  `json:"charge_fee"`
	VoidedFee   int64  `json:"voided_fee"`
	TransferFee int64  `json:"transfer_fee"`
	SubTotal    int64  `json:"subtotal"`
	VAT         int64  `json:"vat"`
	WHT         int64  `json:"wht"`
	Total       int64  `json:"total"`
	CreditNote  bool   `json:"credit_note"`
	Currency    string `json:"currency"`
}
<|endoftext|>


<commit_before>package dynamodb_test

import (
	"os"
	"testing"

	"github.com/kyani-inc/storage/providers/dynamodb"
	"github.com/subosito/gotenv"
)

var (
	ddb       dynamodb.DynamoDB
	envLoaded = false
	access    = ""
	secret    = ""
	region    = ""
	dbtable   = ""
)

func checkEnv(t *testing.T) {
	if envLoaded == false {
		gotenv.Load(".env")

		access = os.Getenv("AWS_ACCESS")
		secret = os.Getenv("AWS_SECRET")
		region = os.Getenv("AWS_REGION")
		dbtable = os.Getenv("DYNAMO_DB_TABLE")
		envLoaded = true
	}

	if access == "" || secret == "" || region == "" || dbtable == "" {
		t.Skip("env vars not defined")
	}
}

func TestDDB(t *testing.T) {
	checkEnv(t)

	var err error
	ddb, err = dynamodb.New(access, secret, region, dbtable)

	if err != nil {
		t.Fatal("Failed to establish connection with DynamoDB!")
	} else {
		t.Log("Connected to DynamoDB server")
	}

	k, v := "test1", "hello, world!!"
	err = ddb.Put(k, []byte(v))

	if err != nil {
		t.Error("Error putting value", err.Error())
	}

	b := ddb.Get(k)

	if v != string(b) {
		t.Error("item `test1` does not contain expected values")
	}

	// ddb.Delete(k)
	//
	// b = ddb.Get(k)
	//
	// if v == string(b) {
	// 	t.Error("key test2 was not deleted!")
	// }
	//
	// k, v = "nodata", ""
	// err = ddb.Put(k, []byte(v))
	//
	// if err == nil {
	// 	t.Error("An error was expected but passed for some reason..")
	// }
	//
	// b = ddb.Get("nodata")
	//
	// if v != string(b) {
	// 	t.Error("item `nodata` should not contain data")
	// }
	//
	// k, v = "test2", "data..."
	// err = ddb.Put(k, []byte(v))
	//
	// if err != nil {
	// 	t.Error("Error putting value", err.Error())
	// }
	//
	// ddb.Flush()
	//
	// b = ddb.Get(k)
	//
	// if v == string(b) {
	// 	t.Error("Failed to flush the table..")
	// }
}
<commit_msg>uncommented other tests<commit_after>package dynamodb_test

import (
	"os"
	"testing"

	"github.com/kyani-inc/storage/providers/dynamodb"
	"github.com/subosito/gotenv"
)

var (
	ddb       dynamodb.DynamoDB
	envLoaded = false
	access    = ""
	secret    = ""
	region    = ""
	dbtable   = ""
)

func checkEnv(t *testing.T) {
	if envLoaded == false {
		gotenv.Load(".env")

		access = os.Getenv("AWS_ACCESS")
		secret = os.Getenv("AWS_SECRET")
		region = os.Getenv("AWS_REGION")
		dbtable = os.Getenv("DYNAMO_DB_TABLE")
		envLoaded = true
	}

	if access == "" || secret == "" || region == "" || dbtable == "" {
		t.Skip("env vars not defined")
	}
}

func TestDDB(t *testing.T) {
	checkEnv(t)

	var err error
	ddb, err = dynamodb.New(access, secret, region, dbtable)

	if err != nil {
		t.Fatal("Failed to establish connection with DynamoDB!")
	} else {
		t.Log("Connected to DynamoDB server")
	}

	k, v := "test1", "hello, world!!"
	err = ddb.Put(k, []byte(v))

	if err != nil {
		t.Error("Error putting value", err.Error())
	}

	b := ddb.Get(k)

	if v != string(b) {
		t.Error("item `test1` does not contain expected values")
	}

	ddb.Delete(k)

	b = ddb.Get(k)

	if v == string(b) {
		t.Error("key test2 was not deleted!")
	}

	k, v = "nodata", ""
	err = ddb.Put(k, []byte(v))

	if err == nil {
		t.Error("An error was expected but passed for some reason..")
	}

	b = ddb.Get("nodata")

	if v != string(b) {
		t.Error("item `nodata` should not contain data")
	}

	k, v = "test2", "data..."
	err = ddb.Put(k, []byte(v))

	if err != nil {
		t.Error("Error putting value", err.Error())
	}

	ddb.Flush()

	b = ddb.Get(k)

	if v == string(b) {
		t.Error("Failed to flush the table..")
	}
}
<|endoftext|>


<commit_before>package status

import (
	"encoding/json"
	"expvar"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"strings"
	"sync"
	"time"
)

type Provider interface {
	Status() (map[string]interface{}, error)
}

// Service provides HTTP status service.
type Service struct {
	addr string       // Bind address of the HTTP service.
	ln   net.Listener // Service listener

	start     time.Time           // Start up time.
	providers map[string]Provider // Registered providers
	mu        sync.Mutex

	BuildInfo map[string]interface{}

	logger *log.Logger
}

// NewService returns an initialized Service object.
func NewService(addr string) *Service {
	return &Service{
		addr:   addr,
		start:  time.Now(),
		logger: log.New(os.Stderr, "[status] ", log.LstdFlags),
	}
}

// Start starts the service.
func (s *Service) Start() error {
	server := http.Server{
		Handler: s,
	}

	ln, err := net.Listen("tcp", s.addr)
	if err != nil {
		return err
	}
	s.ln = ln

	go func() {
		err := server.Serve(s.ln)
		if err != nil {
			s.logger.Println("HTTP service Serve() returned:", err.Error())
		}
	}()
	s.logger.Println("service listening on", s.addr)

	return nil
}

// Close closes the service.
func (s *Service) Close() {
	s.ln.Close()
	return
}

// Addr returns the address on which the Service is listening
func (s *Service) Addr() net.Addr {
	return s.ln.Addr()
}

// Register registers the given provider with the given key.
func (s *Service) Register(key string, provider Provider) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.providers[key] = provider
	s.logger.Println("status provider registered for %s", key)
}

// ServeHTTP allows Service to serve HTTP requests.
func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Add version header to every response, if available.
	if v, ok := s.BuildInfo["version"].(string); ok {
		w.Header().Add("X-EKANITE-VERSION", v)
	} else {
		w.Header().Add("X-EKANITE-VERSION", "unknown")
	}

	switch {
	case strings.HasPrefix(r.URL.Path, "/status"):
		s.handleStatus(w, r)
	case r.URL.Path == "/debug/vars":
		serveExpvar(w, r)
	case strings.HasPrefix(r.URL.Path, "/debug/pprof"):
		servePprof(w, r)
	default:
		w.WriteHeader(http.StatusNotFound)
	}
}

// handleStatus returns status on the system.
func (s *Service) handleStatus(w http.ResponseWriter, r *http.Request) {
	s.mu.Lock()
	defer s.mu.Unlock()

	status := make(map[string]interface{})
	for k, p := range s.providers {
		st, err := p.Status()
		if err != nil {
			s.logger.Println("failed to retrieve status for %s:", k, err.Error())
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		status[k] = st
	}

	pretty, _ := isPretty(r)
	var b []byte
	var err error
	if pretty {
		b, err = json.MarshalIndent(status, "", "    ")
	} else {
		b, err = json.Marshal(status)
	}
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	} else {
		_, err = w.Write([]byte(b))
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
		}
	}
}

// serveExpvar serves registered expvar information over HTTP.
func serveExpvar(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	fmt.Fprintf(w, "{\n")
	first := true
	expvar.Do(func(kv expvar.KeyValue) {
		if !first {
			fmt.Fprintf(w, ",\n")
		}
		first = false
		fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
	})
	fmt.Fprintf(w, "\n}\n")
}

// servePprof serves pprof information over HTTP.
func servePprof(w http.ResponseWriter, r *http.Request) {
	switch r.URL.Path {
	case "/debug/pprof/cmdline":
		pprof.Cmdline(w, r)
	case "/debug/pprof/profile":
		pprof.Profile(w, r)
	case "/debug/pprof/symbol":
		pprof.Symbol(w, r)
	default:
		pprof.Index(w, r)
	}
}

// queryParam returns whether the given query param is set to true.
func queryParam(req *http.Request, param string) (bool, error) {
	err := req.ParseForm()
	if err != nil {
		return false, err
	}
	if _, ok := req.Form[param]; ok {
		return true, nil
	}
	return false, nil
}

// isPretty returns whether the HTTP response body should be pretty-printed.
func isPretty(req *http.Request) (bool, error) {
	return queryParam(req, "pretty")
}
<commit_msg>'go vet' fixes<commit_after>package status

import (
	"encoding/json"
	"expvar"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"strings"
	"sync"
	"time"
)

type Provider interface {
	Status() (map[string]interface{}, error)
}

// Service provides HTTP status service.
type Service struct {
	addr string       // Bind address of the HTTP service.
	ln   net.Listener // Service listener

	start     time.Time           // Start up time.
	providers map[string]Provider // Registered providers
	mu        sync.Mutex

	BuildInfo map[string]interface{}

	logger *log.Logger
}

// NewService returns an initialized Service object.
func NewService(addr string) *Service {
	return &Service{
		addr:   addr,
		start:  time.Now(),
		logger: log.New(os.Stderr, "[status] ", log.LstdFlags),
	}
}

// Start starts the service.
func (s *Service) Start() error {
	server := http.Server{
		Handler: s,
	}

	ln, err := net.Listen("tcp", s.addr)
	if err != nil {
		return err
	}
	s.ln = ln

	go func() {
		err := server.Serve(s.ln)
		if err != nil {
			s.logger.Println("HTTP service Serve() returned:", err.Error())
		}
	}()
	s.logger.Println("service listening on", s.addr)

	return nil
}

// Close closes the service.
func (s *Service) Close() {
	s.ln.Close()
	return
}

// Addr returns the address on which the Service is listening
func (s *Service) Addr() net.Addr {
	return s.ln.Addr()
}

// Register registers the given provider with the given key.
func (s *Service) Register(key string, provider Provider) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.providers[key] = provider
	s.logger.Println("status provider registered for", key)
}

// ServeHTTP allows Service to serve HTTP requests.
func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// Add version header to every response, if available.
	if v, ok := s.BuildInfo["version"].(string); ok {
		w.Header().Add("X-EKANITE-VERSION", v)
	} else {
		w.Header().Add("X-EKANITE-VERSION", "unknown")
	}

	switch {
	case strings.HasPrefix(r.URL.Path, "/status"):
		s.handleStatus(w, r)
	case r.URL.Path == "/debug/vars":
		serveExpvar(w, r)
	case strings.HasPrefix(r.URL.Path, "/debug/pprof"):
		servePprof(w, r)
	default:
		w.WriteHeader(http.StatusNotFound)
	}
}

// handleStatus returns status on the system.
func (s *Service) handleStatus(w http.ResponseWriter, r *http.Request) {
	s.mu.Lock()
	defer s.mu.Unlock()

	status := make(map[string]interface{})
	for k, p := range s.providers {
		st, err := p.Status()
		if err != nil {
			s.logger.Printf("failed to retrieve status for %s: %s", k, err.Error())
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		status[k] = st
	}

	pretty, _ := isPretty(r)
	var b []byte
	var err error
	if pretty {
		b, err = json.MarshalIndent(status, "", "    ")
	} else {
		b, err = json.Marshal(status)
	}
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	} else {
		_, err = w.Write([]byte(b))
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
		}
	}
}

// serveExpvar serves registered expvar information over HTTP.
func serveExpvar(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	fmt.Fprintf(w, "{\n")
	first := true
	expvar.Do(func(kv expvar.KeyValue) {
		if !first {
			fmt.Fprintf(w, ",\n")
		}
		first = false
		fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
	})
	fmt.Fprintf(w, "\n}\n")
}

// servePprof serves pprof information over HTTP.
func servePprof(w http.ResponseWriter, r *http.Request) {
	switch r.URL.Path {
	case "/debug/pprof/cmdline":
		pprof.Cmdline(w, r)
	case "/debug/pprof/profile":
		pprof.Profile(w, r)
	case "/debug/pprof/symbol":
		pprof.Symbol(w, r)
	default:
		pprof.Index(w, r)
	}
}

// queryParam returns whether the given query param is set to true.
func queryParam(req *http.Request, param string) (bool, error) {
	err := req.ParseForm()
	if err != nil {
		return false, err
	}
	if _, ok := req.Form[param]; ok {
		return true, nil
	}
	return false, nil
}

// isPretty returns whether the HTTP response body should be pretty-printed.
func isPretty(req *http.Request) (bool, error) {
	return queryParam(req, "pretty")
}
<|endoftext|>


<commit_before>package streams

import (
	"fmt"
	"time"

	"github.com/FederationOfFathers/dashboard/db"
	"github.com/FederationOfFathers/dashboard/messaging"
	"github.com/nicklaw5/helix"
	"go.uber.org/zap"
)

var twlog *zap.Logger
var TwitchOAuthKey string

var twitchClient *helix.Client

func Twitch(clientID string) error {
	var err error
	twitchClient, err = helix.NewClient(&helix.Options{
		ClientID: clientID,
	})
	return err

}

func MustTwitch(oauth string) {
	if err := Twitch(oauth); err != nil {
		panic(err)
	}
}

type twitchStream helix.Stream

func mindTwitch() {
	twlog = Logger.Named("twitch")
	twlog.Debug("begin minding")
	for _, stream := range Streams {
		if stream.Twitch == "" {
			twlog.Debug("not a twitch stream", zap.Int("id", stream.ID), zap.Int("member_id", stream.MemberID))
			continue
		}
		twlog.Debug("minding twitch stream", zap.String("twithc id", stream.Twitch))
		updateTwitch(stream)
	}
	twlog.Debug("end minding")
}

func updateTwitch(s *db.Stream) {
	var client = twitchClient
	var foundStream = false

	res, err := client.GetStreams(&helix.StreamsParams{
		UserIDs: []string{s.Twitch},
	})
	if err != nil {
		if err.Error() != "json: cannot unmarshal number into Go value of type string" {
			twlog.Error("error fetching stream", zap.String("key", s.Twitch), zap.Error(err))
		}
		return
	}

	switch len(res.Data.Streams) {
	case 1:
		foundStream = true
	case 0:
		twlog.Debug("No active streams", zap.String("key", s.Twitch))
	default:
		twlog.Error("Too many active streams", zap.String("key", s.Twitch))
	}

	if !foundStream {
		var save bool
		if s.TwitchStreamID != "" {
			s.TwitchStreamID = ""
			save = true
		}
		if s.TwitchStop < s.TwitchStart {
			s.TwitchStop = time.Now().Unix()
			save = true
		}
		if s.TwitchStop < s.TwitchStart {
			s.TwitchStop = s.TwitchStart + 1
			save = true
		}
		if save {
			s.Save()
		}
		return
	}

	stream := res.Data.Streams[0]

	if stream.ID == "" {
		twlog.Error("Invalid stream ID", zap.String("key", s.Twitch))
		return
	}

	var isRecent bool = time.Now().Unix()-s.TwitchStart <= 1800
	streamID := fmt.Sprintf("%d", stream.ID)
	postStreamMessage := true
	if streamID == s.TwitchStreamID && s.TwitchGame == stream.GameID {
		twlog.Debug("still streaming...", zap.String("twitch_user", s.Twitch), zap.String("game_id", stream.GameID))
		return
	} else if isRecent && s.TwitchGame == stream.GameID {
		twlog.Debug("new ID, but still streaming...", zap.String("twitch_user", s.Twitch), zap.String("game_id", stream.GameID))
		postStreamMessage = false
	}

	s.TwitchStreamID = streamID
	s.TwitchStart = time.Now().Unix()
	if s.TwitchStop > s.TwitchStart {
		s.TwitchStop = s.TwitchStart - 1
	}

	var game helix.Game
	gamesResponse, gerr := client.GetGames(&helix.GamesParams{
		IDs: []string{stream.GameID},
	})
	if gerr != nil {
		twlog.Error("could not get game data", zap.Error(err), zap.String("gameID", stream.GameID), zap.String("twitchUser", stream.UserName))
	} else {
		game = gamesResponse.Data.Games[0]

	}

	if postStreamMessage {
		sendTwitchMessage(stream, game)
	}

	s.TwitchGame = stream.GameID
	s.Save()
}

func sendTwitchMessage(stream helix.Stream, game helix.Game) {

	messaging.SendTwitchStreamMessage(messaging.StreamMessage{
		Platform:         "Twitch",
		PlatformLogo:     "https://slack-imgs.com/?c=1&o1=wi16.he16.si.ip&url=https%3A%2F%2Fwww.twitch.tv%2Ffavicon.ico",
		PlatformColor:    "#6441A4",
		PlatformColorInt: 6570404,
		Username:         stream.UserName,
		UserLogo:         stream.ThumbnailURL,
		URL:              fmt.Sprintf("https://twitch.tv/%s", stream.UserName),
		Game:             game.Name,
		Description:      stream.Title,
		Timestamp:        time.Now().Format("01/02/2006 15:04 MST"),
	})

}
<commit_msg>Fixing twitch monitoring<commit_after>package streams

import (
	"fmt"
	"time"

	"github.com/FederationOfFathers/dashboard/db"
	"github.com/FederationOfFathers/dashboard/messaging"
	"github.com/nicklaw5/helix"
	"go.uber.org/zap"
)

var twlog *zap.Logger
var TwitchOAuthKey string

var twitchClient *helix.Client

func Twitch(clientID string) error {
	var err error
	twitchClient, err = helix.NewClient(&helix.Options{
		ClientID: clientID,
	})
	return err

}

func MustTwitch(oauth string) {
	if err := Twitch(oauth); err != nil {
		panic(err)
	}
}

type twitchStream helix.Stream

func mindTwitch() {
	twlog = Logger.Named("twitch")
	twlog.Debug("begin minding")
	for _, stream := range Streams {
		if stream.Twitch == "" {
			twlog.Debug("not a twitch stream", zap.Int("id", stream.ID), zap.Int("member_id", stream.MemberID))
			continue
		}
		twlog.Debug("minding twitch stream", zap.String("Twitch id", stream.Twitch))
		updateTwitch(stream)
	}
	twlog.Debug("end minding")
}

func updateTwitch(s *db.Stream) {
	var client = twitchClient
	var foundStream = false

	res, err := client.GetStreams(&helix.StreamsParams{
		UserLogins: []string{s.Twitch},
	})
	if err != nil {
		if err.Error() != "json: cannot unmarshal number into Go value of type string" {
			twlog.Error("error fetching stream", zap.String("key", s.Twitch), zap.Error(err))
		}
		return
	}

	switch len(res.Data.Streams) {
	case 1:
		foundStream = true
	case 0:
		twlog.Debug("No active streams", zap.String("key", s.Twitch))
	default:
		twlog.Error("Too many active streams", zap.String("key", s.Twitch))
	}

	if !foundStream {
		var save bool
		if s.TwitchStreamID != "" {
			s.TwitchStreamID = ""
			save = true
		}
		if s.TwitchStop < s.TwitchStart {
			s.TwitchStop = time.Now().Unix()
			save = true
		}
		if s.TwitchStop < s.TwitchStart {
			s.TwitchStop = s.TwitchStart + 1
			save = true
		}
		if save {
			s.Save()
		}
		return
	}

	stream := res.Data.Streams[0]

	if stream.ID == "" {
		twlog.Error("Invalid stream ID", zap.String("key", s.Twitch))
		return
	}

	var isRecent bool = time.Now().Unix()-s.TwitchStart <= 1800
	streamID := fmt.Sprintf("%d", stream.ID)
	postStreamMessage := true
	if streamID == s.TwitchStreamID && s.TwitchGame == stream.GameID {
		twlog.Debug("still streaming...", zap.String("twitch_user", s.Twitch), zap.String("game_id", stream.GameID))
		return
	} else if isRecent && s.TwitchGame == stream.GameID {
		twlog.Debug("new ID, but still streaming...", zap.String("twitch_user", s.Twitch), zap.String("game_id", stream.GameID))
		postStreamMessage = false
	}

	s.TwitchStreamID = streamID
	s.TwitchStart = time.Now().Unix()
	if s.TwitchStop > s.TwitchStart {
		s.TwitchStop = s.TwitchStart - 1
	}

	var game helix.Game
	gamesResponse, gerr := client.GetGames(&helix.GamesParams{
		IDs: []string{stream.GameID},
	})
	if gerr != nil {
		twlog.Error("could not get game data", zap.Error(err), zap.String("gameID", stream.GameID), zap.String("twitchUser", stream.UserName))
	} else {
		game = gamesResponse.Data.Games[0]

	}

	if postStreamMessage {
		sendTwitchMessage(stream, game)
	}

	s.TwitchGame = stream.GameID
	s.Save()
}

func sendTwitchMessage(stream helix.Stream, game helix.Game) {

	messaging.SendTwitchStreamMessage(messaging.StreamMessage{
		Platform:         "Twitch",
		PlatformLogo:     "https://slack-imgs.com/?c=1&o1=wi16.he16.si.ip&url=https%3A%2F%2Fwww.twitch.tv%2Ffavicon.ico",
		PlatformColor:    "#6441A4",
		PlatformColorInt: 6570404,
		Username:         stream.UserName,
		UserLogo:         stream.ThumbnailURL,
		URL:              fmt.Sprintf("https://twitch.tv/%s", stream.UserName),
		Game:             game.Name,
		Description:      stream.Title,
		Timestamp:        time.Now().Format("01/02/2006 15:04 MST"),
	})

}
<|endoftext|>


<commit_before>package stripe

import (
	"net/url"
	"strconv"
)

type Coupon struct {
	Id               string `json:"id"`
	Object           string `json:"object"`
	Livemode         bool   `json:"livemode"`
	Duration         string `json:"duration"`
	AmountOff        int64  `json:"amount_off"`
	Currency         string `json:"currency"`
	DurationInMonths int64  `json:"duration_in_months"`
	MaxRedemptions   int64  `json:"max_redemptions"`
	PercentOff       int64  `json:"percent_off"`
	RedeemBy         int64  `json:"redeem_by"`
	TimesRedeemed    int64  `json:"times_redeemed"`
	Valid            bool   `json:"valid"`
}

type CouponListResponse struct {
	Object string    `json:"object"`
	Url    string    `json:"url"`
	Count  int       `json:"count"`
	Data   []*Coupon `json:"data"`
}

// Delete deletes a coupon.
//
// For more information: https://stripe.com/docs/api#delete_coupon
func (c *Coupon) Delete() (*DeleteResponse, error) {
	response := DeleteResponse{}
	err := delete("/coupons/"+c.Id, nil, &response)
	return &response, err
}

type CouponClient struct{}

// Create creates a coupon.
//
// For more information: https://stripe.com/docs/api#create_coupon
func (c *CouponClient) Create(params *CouponParams) (*Coupon, error) {
	coupon := Coupon{}
	values := url.Values{}
	parseCouponParams(params, &values)
	err := post("/coupons", values, &coupon)
	return &coupon, err
}

// Retrieve loads a coupon.
//
// For more information: https://stripe.com/docs/api#retrieve_coupon
func (c *CouponClient) Retrieve(id string) (*Coupon, error) {
	coupon := Coupon{}
	err := get("/coupons/"+id, nil, &coupon)
	return &coupon, err
}

// Delete deletes a coupon.
//
// For more information: https://stripe.com/docs/api#delete_coupon
func (c *CouponClient) Delete(id string) (*DeleteResponse, error) {
	response := DeleteResponse{}
	err := delete("/coupons/"+id, nil, &response)
	return &response, err
}

// List lists the first 10 coupons. It calls ListCount with 10 as
// the count and 0 as the offset, which are the defaults in the Stripe API.
//
// For more information: https://stripe.com/docs/api#list_coupons
func (c *CouponClient) List() (*CouponListResponse, error) {
	return c.ListCount(10, 0)
}

// ListCount lists `count` coupons starting at `offset`.
//
// For more information: https://stripe.com/docs/api#list_coupons
func (c *CouponClient) ListCount(count, offset int) (*CouponListResponse, error) {
	response := CouponListResponse{}

	params := url.Values{
		"count":  {strconv.Itoa(count)},
		"offset": {strconv.Itoa(offset)},
	}

	err := get("/coupons", params, &response)
	return &response, err
}

// parseCouponParams takes a pointer to a CouponParams and a pointer to a url.Values,
// it iterates over everything in the CouponParams struct and Adds what is there
// to the url.Values.
func parseCouponParams(params *CouponParams, values *url.Values) {
	addParamsToValues(params, values)
}
<commit_msg>updated coupons from #List and #ListCount to #All and #AllWithFilters<commit_after>package stripe

import (
	"net/url"
)

type Coupon struct {
	Id               string `json:"id"`
	Object           string `json:"object"`
	Livemode         bool   `json:"livemode"`
	Duration         string `json:"duration"`
	AmountOff        int64  `json:"amount_off"`
	Currency         string `json:"currency"`
	DurationInMonths int64  `json:"duration_in_months"`
	MaxRedemptions   int64  `json:"max_redemptions"`
	PercentOff       int64  `json:"percent_off"`
	RedeemBy         int64  `json:"redeem_by"`
	TimesRedeemed    int64  `json:"times_redeemed"`
	Valid            bool   `json:"valid"`
}

type CouponListResponse struct {
	Object string    `json:"object"`
	Url    string    `json:"url"`
	Count  int       `json:"count"`
	Data   []*Coupon `json:"data"`
}

// Delete deletes a coupon.
//
// For more information: https://stripe.com/docs/api#delete_coupon
func (c *Coupon) Delete() (*DeleteResponse, error) {
	response := DeleteResponse{}
	err := delete("/coupons/"+c.Id, nil, &response)
	return &response, err
}

type CouponClient struct{}

// Create creates a coupon.
//
// For more information: https://stripe.com/docs/api#create_coupon
func (c *CouponClient) Create(params *CouponParams) (*Coupon, error) {
	coupon := Coupon{}
	values := url.Values{}
	parseCouponParams(params, &values)
	err := post("/coupons", values, &coupon)
	return &coupon, err
}

// Retrieve loads a coupon.
//
// For more information: https://stripe.com/docs/api#retrieve_coupon
func (c *CouponClient) Retrieve(id string) (*Coupon, error) {
	coupon := Coupon{}
	err := get("/coupons/"+id, nil, &coupon)
	return &coupon, err
}

// Delete deletes a coupon.
//
// For more information: https://stripe.com/docs/api#delete_coupon
func (c *CouponClient) Delete(id string) (*DeleteResponse, error) {
	response := DeleteResponse{}
	err := delete("/coupons/"+id, nil, &response)
	return &response, err
}

// All lists the first 10 coupons. It calls AllWithFilters with a blank Filters
// so all defaults are used.
//
// For more information: https://stripe.com/docs/api#list_coupons
func (c *CouponClient) All() (*CouponListResponse, error) {
	return c.AllWithFilters(Filters{})
}

// AllWithFilters takes a Filters and applies all valid filters for the action.
//
// For more information: https://stripe.com/docs/api#list_coupons
func (c *CouponClient) AllWithFilters(filters Filters) (*CouponListResponse, error) {
	response := CouponListResponse{}
  values := url.Values{}
  addFiltersToValues([]string{"count", "offset"}, filters, &values)
	err := get("/coupons", values, &response)
	return &response, err
}

// parseCouponParams takes a pointer to a CouponParams and a pointer to a url.Values,
// it iterates over everything in the CouponParams struct and Adds what is there
// to the url.Values.
func parseCouponParams(params *CouponParams, values *url.Values) {
	addParamsToValues(params, values)
}
<|endoftext|>


<commit_before>package mercury

import (
	"sync"
	"time"

	log "github.com/cihub/seelog"
	"golang.org/x/net/context"

	"github.com/mondough/mercury/marshaling"
	tmsg "github.com/mondough/typhon/message"
)

const (
	errHeader = "Content-Error"
)

// A Request is a representation of an RPC call (inbound or outbound). It extends Typhon's Request to provide a
// Context, and also helpers for constructing a response.
type Request interface {
	tmsg.Request
	context.Context

	// Response constructs a response to this request, with the (optional) given body. The response will share
	// the request's ID, and be destined for the originator.
	Response(body interface{}) Response
	// A Context for the Request.
	Context() context.Context
	// SetContext replaces the Request's Context.
	SetContext(ctx context.Context)
}

func responseFromRequest(req Request, body interface{}) Response {
	rsp := NewResponse()
	rsp.SetId(req.Id())
	rsp.SetService(req.Service())
	rsp.SetEndpoint(req.Endpoint())
	if body != nil {
		rsp.SetBody(body)

		ct := req.Headers()[marshaling.AcceptHeader]
		marshaler := marshaling.Marshaler(ct)
		if marshaler == nil { // Fall back to proto
			marshaler = marshaling.Marshaler(marshaling.ProtoContentType)
		}
		if marshaler == nil {
			log.Errorf("[Mercury] No marshaler for response %s: %s", rsp.Id(), ct)
		} else if err := marshaler.MarshalBody(rsp); err != nil {
			log.Errorf("[Mercury] Failed to marshal response %s: %v", rsp.Id(), err)
		}
	}
	return rsp
}

type request struct {
	sync.RWMutex
	tmsg.Request
	ctx context.Context
}

func (r *request) Response(body interface{}) Response {
	return responseFromRequest(r, body)
}

func (r *request) Context() context.Context {
	r.RLock()
	defer r.RUnlock()
	return r.ctx
}

func (r *request) SetContext(ctx context.Context) {
	r.Lock()
	defer r.Unlock()
	r.ctx = ctx
}

func (r *request) Copy() tmsg.Request {
	r.RLock()
	defer r.RUnlock()
	return &request{
		Request: r.Request.Copy(),
		ctx:     r.ctx,
	}
}

// Context implementation

func (r *request) Deadline() (time.Time, bool) {
	return r.Context().Deadline()
}

func (r *request) Done() <-chan struct{} {
	return r.Context().Done()
}

func (r *request) Err() error {
	return r.Context().Err()
}

func (r *request) Value(key interface{}) interface{} {
	return r.Context().Value(key)
}

func NewRequest() Request {
	return FromTyphonRequest(tmsg.NewRequest())
}

func FromTyphonRequest(req tmsg.Request) Request {
	return &request{
		Request: req,
		ctx:     context.TODO(),
	}
}
<commit_msg>Root requests should start with a background context<commit_after>package mercury

import (
	"sync"
	"time"

	log "github.com/cihub/seelog"
	"golang.org/x/net/context"

	"github.com/mondough/mercury/marshaling"
	tmsg "github.com/mondough/typhon/message"
)

const (
	errHeader = "Content-Error"
)

// A Request is a representation of an RPC call (inbound or outbound). It extends Typhon's Request to provide a
// Context, and also helpers for constructing a response.
type Request interface {
	tmsg.Request
	context.Context

	// Response constructs a response to this request, with the (optional) given body. The response will share
	// the request's ID, and be destined for the originator.
	Response(body interface{}) Response
	// A Context for the Request.
	Context() context.Context
	// SetContext replaces the Request's Context.
	SetContext(ctx context.Context)
}

func responseFromRequest(req Request, body interface{}) Response {
	rsp := NewResponse()
	rsp.SetId(req.Id())
	rsp.SetService(req.Service())
	rsp.SetEndpoint(req.Endpoint())
	if body != nil {
		rsp.SetBody(body)

		ct := req.Headers()[marshaling.AcceptHeader]
		marshaler := marshaling.Marshaler(ct)
		if marshaler == nil { // Fall back to proto
			marshaler = marshaling.Marshaler(marshaling.ProtoContentType)
		}
		if marshaler == nil {
			log.Errorf("[Mercury] No marshaler for response %s: %s", rsp.Id(), ct)
		} else if err := marshaler.MarshalBody(rsp); err != nil {
			log.Errorf("[Mercury] Failed to marshal response %s: %v", rsp.Id(), err)
		}
	}
	return rsp
}

type request struct {
	sync.RWMutex
	tmsg.Request
	ctx context.Context
}

func (r *request) Response(body interface{}) Response {
	return responseFromRequest(r, body)
}

func (r *request) Context() context.Context {
	r.RLock()
	defer r.RUnlock()
	return r.ctx
}

func (r *request) SetContext(ctx context.Context) {
	r.Lock()
	defer r.Unlock()
	r.ctx = ctx
}

func (r *request) Copy() tmsg.Request {
	r.RLock()
	defer r.RUnlock()
	return &request{
		Request: r.Request.Copy(),
		ctx:     r.ctx,
	}
}

// Context implementation

func (r *request) Deadline() (time.Time, bool) {
	return r.Context().Deadline()
}

func (r *request) Done() <-chan struct{} {
	return r.Context().Done()
}

func (r *request) Err() error {
	return r.Context().Err()
}

func (r *request) Value(key interface{}) interface{} {
	return r.Context().Value(key)
}

func NewRequest() Request {
	return FromTyphonRequest(tmsg.NewRequest())
}

func FromTyphonRequest(req tmsg.Request) Request {
	return &request{
		Request: req,
		ctx:     context.Background(),
	}
}
<|endoftext|>


<commit_before>package oauth2

import (
	"net/http"
	"net/url"
)

type AccessTokenRequest struct {
	GrantType    GrantType
	Scope        Scope
	ClientID     string
	ClientSecret string
	Username     string
	Password     string
	RefreshToken string
	RedirectURI  string
	State        string
	Code         string
}

func ParseAccessTokenRequest(req *http.Request) (*AccessTokenRequest, error) {
	// check method
	if req.Method != "POST" {
		return nil, InvalidRequest(NoState, "Invalid HTTP method")
	}

	// parse query params and body params to form
	err := req.ParseForm()
	if err != nil {
		return nil, InvalidRequest(NoState, "Malformed query parameters or body form")
	}

	// get state
	state := req.PostForm.Get("state")

	// get grant type
	grantType := req.PostForm.Get("grant_type")
	if grantType == "" {
		return nil, InvalidRequest(state, "Missing grant type")
	}

	// get scope
	scope := ParseScope(req.PostForm.Get("scope"))

	// get client id and secret
	clientID, clientSecret, ok := req.BasicAuth()
	if !ok {
		return nil, InvalidRequest(state, "Missing or invalid HTTP authorization header")
	}

	// obtaining the client id and secret from the request body (form data)
	// is not implemented by default due to security considerations

	// get username and password
	username := req.PostForm.Get("username")
	password := req.PostForm.Get("password")

	// get refresh token
	refreshToken := req.PostForm.Get("refresh_token")

	// get redirect uri
	redirectURIString, err := url.QueryUnescape(req.Form.Get("redirect_uri"))
	if err != nil {
		return nil, InvalidRequest(state, "Invalid redirect URI")
	}

	// validate redirect uri if present
	if len(redirectURIString) > 0 {
		redirectURI, err := url.ParseRequestURI(redirectURIString)
		if err != nil || redirectURI.Fragment != "" {
			return nil, InvalidRequest(state, "Invalid redirect URI")
		}
	}

	// get code
	code := req.PostForm.Get("code")

	return &AccessTokenRequest{
		GrantType:    GrantType(grantType),
		Scope:        scope,
		ClientID:     clientID,
		ClientSecret: clientSecret,
		Username:     username,
		Password:     password,
		RefreshToken: refreshToken,
		RedirectURI:  redirectURIString,
		State:        state,
		Code:         code,
	}, nil
}

func (r *AccessTokenRequest) Confidential() bool {
	return len(r.ClientID) > 0 && len(r.ClientSecret) > 0
}

type AuthorizationRequest struct {
	ResponseType ResponseType
	Scope        Scope
	ClientID     string
	RedirectURI  string
	State        string
}

func ParseAuthorizationRequest(req *http.Request) (*AuthorizationRequest, error) {
	// check method
	if req.Method != "GET" && req.Method != "POST" {
		return nil, InvalidRequest(NoState, "Invalid HTTP method")
	}

	// parse query params and body params to form
	err := req.ParseForm()
	if err != nil {
		return nil, InvalidRequest(NoState, "Malformed query parameters or form data")
	}

	// get state
	state := req.Form.Get("state")

	// get response type
	responseType := req.Form.Get("response_type")
	if responseType == "" {
		return nil, InvalidRequest(state, "Missing response type")
	}

	// get scope
	scope := ParseScope(req.Form.Get("scope"))

	// get client id
	clientID := req.Form.Get("client_id")
	if clientID == "" {
		return nil, InvalidRequest(state, "Missing client ID")
	}

	// get redirect uri
	redirectURIString, err := url.QueryUnescape(req.Form.Get("redirect_uri"))
	if err != nil || redirectURIString == "" {
		return nil, InvalidRequest(state, "Missing redirect URI")
	}

	// parse redirect uri
	redirectURI, err := url.ParseRequestURI(redirectURIString)
	if err != nil || redirectURI.Fragment != "" {
		return nil, InvalidRequest(state, "Invalid redirect URI")
	}

	return &AuthorizationRequest{
		ResponseType: ResponseType(responseType),
		Scope:        scope,
		ClientID:     clientID,
		RedirectURI:  redirectURIString,
		State:        state,
	}, nil
}
<commit_msg>moved note<commit_after>package oauth2

import (
	"net/http"
	"net/url"
)

type AccessTokenRequest struct {
	GrantType    GrantType
	Scope        Scope
	ClientID     string
	ClientSecret string
	Username     string
	Password     string
	RefreshToken string
	RedirectURI  string
	State        string
	Code         string
}

// Note: Obtaining the client id and secret from the request body (form data)
// is not implemented by default due to security considerations.
func ParseAccessTokenRequest(req *http.Request) (*AccessTokenRequest, error) {
	// check method
	if req.Method != "POST" {
		return nil, InvalidRequest(NoState, "Invalid HTTP method")
	}

	// parse query params and body params to form
	err := req.ParseForm()
	if err != nil {
		return nil, InvalidRequest(NoState, "Malformed query parameters or body form")
	}

	// get state
	state := req.PostForm.Get("state")

	// get grant type
	grantType := req.PostForm.Get("grant_type")
	if grantType == "" {
		return nil, InvalidRequest(state, "Missing grant type")
	}

	// get scope
	scope := ParseScope(req.PostForm.Get("scope"))

	// get client id and secret
	clientID, clientSecret, ok := req.BasicAuth()
	if !ok {
		return nil, InvalidRequest(state, "Missing or invalid HTTP authorization header")
	}

	// get username and password
	username := req.PostForm.Get("username")
	password := req.PostForm.Get("password")

	// get refresh token
	refreshToken := req.PostForm.Get("refresh_token")

	// get redirect uri
	redirectURIString, err := url.QueryUnescape(req.Form.Get("redirect_uri"))
	if err != nil {
		return nil, InvalidRequest(state, "Invalid redirect URI")
	}

	// validate redirect uri if present
	if len(redirectURIString) > 0 {
		redirectURI, err := url.ParseRequestURI(redirectURIString)
		if err != nil || redirectURI.Fragment != "" {
			return nil, InvalidRequest(state, "Invalid redirect URI")
		}
	}

	// get code
	code := req.PostForm.Get("code")

	return &AccessTokenRequest{
		GrantType:    GrantType(grantType),
		Scope:        scope,
		ClientID:     clientID,
		ClientSecret: clientSecret,
		Username:     username,
		Password:     password,
		RefreshToken: refreshToken,
		RedirectURI:  redirectURIString,
		State:        state,
		Code:         code,
	}, nil
}

func (r *AccessTokenRequest) Confidential() bool {
	return len(r.ClientID) > 0 && len(r.ClientSecret) > 0
}

type AuthorizationRequest struct {
	ResponseType ResponseType
	Scope        Scope
	ClientID     string
	RedirectURI  string
	State        string
}

func ParseAuthorizationRequest(req *http.Request) (*AuthorizationRequest, error) {
	// check method
	if req.Method != "GET" && req.Method != "POST" {
		return nil, InvalidRequest(NoState, "Invalid HTTP method")
	}

	// parse query params and body params to form
	err := req.ParseForm()
	if err != nil {
		return nil, InvalidRequest(NoState, "Malformed query parameters or form data")
	}

	// get state
	state := req.Form.Get("state")

	// get response type
	responseType := req.Form.Get("response_type")
	if responseType == "" {
		return nil, InvalidRequest(state, "Missing response type")
	}

	// get scope
	scope := ParseScope(req.Form.Get("scope"))

	// get client id
	clientID := req.Form.Get("client_id")
	if clientID == "" {
		return nil, InvalidRequest(state, "Missing client ID")
	}

	// get redirect uri
	redirectURIString, err := url.QueryUnescape(req.Form.Get("redirect_uri"))
	if err != nil || redirectURIString == "" {
		return nil, InvalidRequest(state, "Missing redirect URI")
	}

	// parse redirect uri
	redirectURI, err := url.ParseRequestURI(redirectURIString)
	if err != nil || redirectURI.Fragment != "" {
		return nil, InvalidRequest(state, "Invalid redirect URI")
	}

	return &AuthorizationRequest{
		ResponseType: ResponseType(responseType),
		Scope:        scope,
		ClientID:     clientID,
		RedirectURI:  redirectURIString,
		State:        state,
	}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/url"
	"strings"
)

func init() {
	cmdRestart.Flag.StringVar(&flagApp, "a", "", "app")
}

var cmdRestart = &Command{
	Run:   runRestart,
	Usage: "restart [-a app] [type or name]",
	Short: "restart dynos",
	Long: `
Restart all app dynos, all dynos of a specific type, or a single dyno.

Examples:

  $ hk restart
  $ hk restart web
  $ hk restart web.1
`,
}

func runRestart(cmd *Command, args []string) {
	if len(args) > 1 {
		log.Fatal("Invalid usage. See 'hk help restart'")
	}

	v := make(url.Values)

	if len(args) == 1 {
		if strings.Index(args[0], ".") > 0 {
			v.Add("ps", args[0])
		} else {
			v.Add("type", args[0])
		}
	}

	must(Post(nil, "/apps/"+mustApp()+"/ps/restart", v))
}
<commit_msg>fix restart to match v3 API<commit_after>package main

import (
	"log"
)

func init() {
	cmdRestart.Flag.StringVar(&flagApp, "a", "", "app")
}

var cmdRestart = &Command{
	Run:   runRestart,
	Usage: "restart [-a app] [type or name]",
	Short: "restart dynos",
	Long: `
Restart all app dynos, all dynos of a specific type, or a single dyno.

Examples:

  $ hk restart
  $ hk restart web
  $ hk restart web.1
`,
}

func runRestart(cmd *Command, args []string) {
	if len(args) > 1 {
		log.Fatal("Invalid usage. See 'hk help restart'")
	}

	path := "/apps/"+mustApp()+"/dynos"

	if len(args) == 1 {
		path += "/" + args[0]
	}

	must(Delete(path))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"
	"container/list"
	js "encoding/json"

	"github.com/kurrik/oauth1a"
	"github.com/codingneo/twittergo"
	"github.com/kurrik/json"
	"github.com/robfig/cron"
	//"github.com/PuerkitoBio/goquery"
	"github.com/advancedlogic/GoOse"
	"github.com/codingneo/tweetsbot/ranking"
)

func LoadCredentials() (client *twittergo.Client, err error) {
	credentials, err := ioutil.ReadFile("CREDENTIALS")
	if err != nil {
		return
	}
	lines := strings.Split(string(credentials), "\n")
	config := &oauth1a.ClientConfig{
		ConsumerKey:    lines[0],
		ConsumerSecret: lines[1],
	}
	user := oauth1a.NewAuthorizedConfig(lines[2], lines[3])
	client = twittergo.NewClient(config, user, "stream.twitter.com")
	return
}

type Args struct {
	Track string
	Lang string
}

func parseArgs() *Args {
	a := &Args{}
	flag.StringVar(&a.Track, "track", "Data Science,Big Data,Machine Learning", "Keyword to look up")
	flag.StringVar(&a.Lang, "lang", "en", "Language to look up")
	flag.Parse()
	return a
}

func LoadExistingList(filename string) *list.List {
	result := list.New()

	data, err := ioutil.ReadFile(filename)
	if (err == nil) {
		// today's list exists, load existing list
		input := make(map[string][]ranking.Item)
		input["articles"] = make([]ranking.Item, 0)

		js.Unmarshal(data, &input)
		for item := range input["articles"] {
			result.PushBack(item)
		}
	}

	return result
}

type streamConn struct {
	client   *http.Client
	resp     *http.Response
	url      *url.URL
	stale    bool
	closed   bool
	mu       sync.Mutex
	// wait time before trying to reconnect, this will be
	// exponentially moved up until reaching maxWait, when
	// it will exit
	wait    int
	maxWait int
	connect func() (*http.Response, error)
}

func NewStreamConn(max int) streamConn {
	return streamConn{wait: 1, maxWait: max}
}

func (conn *streamConn) Close() {
	// Just mark the connection as stale, and let the connect() handler close after a read
	conn.mu.Lock()
	defer conn.mu.Unlock()
	conn.stale = true
	conn.closed = true
	if conn.resp != nil {
		conn.resp.Body.Close()
	}
}

func (conn *streamConn) isStale() bool {
	conn.mu.Lock()
	r := conn.stale
	conn.mu.Unlock()
	return r
}

func readStream(client *twittergo.Client, sc streamConn, path string, query url.Values,
				resp *twittergo.APIResponse, handler func([]byte), done chan bool) {

	var reader *bufio.Reader
	reader = bufio.NewReader(resp.Body)

	for {
		//we've been closed
		if sc.isStale() {
			sc.Close()
			fmt.Println("Connection closed, shutting down ")
			break
		}

		line, err := reader.ReadBytes('\n')

		if err != nil {
			if sc.isStale() {
				fmt.Println("conn stale, continue")
				continue
			}

			time.Sleep(time.Second * time.Duration(sc.wait))
			//try reconnecting, but exponentially back off until MaxWait is reached then exit?
			resp, err := Connect(client, path, query)
			if err != nil || resp == nil {
				fmt.Println(" Could not reconnect to source? sleeping and will retry ")
				if sc.wait < sc.maxWait {
					sc.wait = sc.wait * 2
				} else {
					fmt.Println("exiting, max wait reached")
					done <- true
					return
				}
				continue
			}
			if resp.StatusCode != 200 {
				fmt.Printf("resp.StatusCode = %d", resp.StatusCode)
				if sc.wait < sc.maxWait {
					sc.wait = sc.wait * 2
				}
				continue
			}

			reader = bufio.NewReader(resp.Body)
			continue
		} else if sc.wait != 1 {
			sc.wait = 1
		}
		line = bytes.TrimSpace(line)
		fmt.Println("Received a line ")

		if len(line) == 0 {
			continue
		}
		handler(line)
	}
}

func Connect(client *twittergo.Client, path string, query url.Values) (resp *twittergo.APIResponse, err error) {
	var (
		req 	*http.Request
	)

	url := fmt.Sprintf("%v?%v", path, query.Encode())
	req, err = http.NewRequest("GET", url, nil)
	if err != nil {
		err = fmt.Errorf("Could not parse request: %v\n", err)
		return
	}
	resp, err = client.SendRequest(req)
	if err != nil {
		err = fmt.Errorf("Could not send request: %v\n", err)
		return
	}

	fmt.Printf("resp.StatusCode=%d\n", resp.StatusCode)
	return
}

func filterStream(client *twittergo.Client, path string, query url.Values) (err error) {
	var (
		resp    *twittergo.APIResponse
	)

	sc := NewStreamConn(300)

	// Step 1: connect to twitter public stream endpoint
	resp, err = Connect(client, path, query)

	done := make(chan bool)
	stream := make(chan []byte, 1000)
	go func() {
		startday := time.Now().UTC().Day()
		filename := "./data/toplist-" +
			time.Now().UTC().Format("2006-01-02") +".json"

		//
		topList := LoadExistingList(filename)

		//Cron job to store toplist per hour
		c := cron.New()
		c.AddFunc("0 * * * * *",
			func() {
				fmt.Println("cron cron cron cron ............................")

				output := make(map[string]interface{})
				output["articles"] = make([]ranking.Item, 0)

				f, err := os.OpenFile(filename, os.O_RDWR, 0666)
				if (err == nil) {
					f.Close()
					err = os.Remove(filename)
				}

				f, err = os.Create(filename)
				if (err != nil) {
					fmt.Println("[Cron] File creation error")
				}

				tlist := make([]ranking.Item, 0)
				for e := topList.Front(); e != nil; e = e.Next() {
					fmt.Println("[Cron] Write url into file")
					//f.WriteString(e.Value.(ranking.Item).Url)
					//f.WriteString("\n")
					tlist = append(tlist, e.Value.(ranking.Item))
				}
				output["articles"] = tlist

				jsonstr, _ := js.Marshal(output)
				f.WriteString(string(jsonstr))
				f.Sync()
				f.Close()
			})
		c.Start()
		fmt.Println("cron job start")

		g := goose.New()
		for data := range stream {
			if (time.Now().UTC().Day() != startday) {
				// Clear the top list
				var next *list.Element
				for e := topList.Front(); e != nil; e = next {
					next = e.Next()
					topList.Remove(e)
				}

				startday = time.Now().UTC().Day()
				filename = "./data/toplist-" +
					time.Now().UTC().Format("2006-01-02") +".json"
			}

			fmt.Println(string(data))
			tweet := &twittergo.Tweet{}
			err := json.Unmarshal(data, tweet)
			if (err == nil) {
				fmt.Printf("ID:                   %v\n", tweet.Id())
				fmt.Printf("User:                 %v\n", tweet.User().ScreenName())
				fmt.Printf("Tweet:                %v\n", tweet.Text())

				rs := tweet.RetweetedStatus()
				vote := 0
				createdAt := tweet.CreatedAt()
				if (rs != nil) {
					fmt.Printf("retweet_count:        %d\n", rs.RetweetCount())
					fmt.Printf("favorite_count:        %d\n", rs.FavoriteCount())
					vote += int(rs.RetweetCount()+rs.FavoriteCount())

					createdAt = rs.CreatedAt()
				}

				if (time.Now().UTC().Sub(createdAt).Hours() < 24.0) {
					e := tweet.Entities()
					if (e != nil) {
						fmt.Printf("url:        %v\n", e.FirstUrl().ExpandedUrl())

						// Form top item
						if (e.FirstUrl().ExpandedUrl()!="") {
							item := ranking.Item{}
							item.Vote = vote
							item.Url = e.FirstUrl().ExpandedUrl()

							// article extraction
							//doc, err := goquery.NewDocument(item.Url)
							article := g.ExtractFromUrl(item.Url)

							fmt.Println("title", article.Title)
	    				fmt.Println("description", article.MetaDescription)
	    				fmt.Println("top image", article.TopImage)

	    				if (article.Title != "") &&
	    					 (article.MetaDescription != "") {
								item.Title = article.Title
	    					item.Description = article.MetaDescription
	    					item.Image = article.TopImage

	    					ranking.Insert(topList, item)
	    				}

							//if err == nil {
							//	item.Title = doc.Find("title").Text()
							//	fmt.Printf("title:        %v\n", item.Title)
							//	ranking.Insert(topList, item)
							//}

							fmt.Println("**********************************")
							for e := topList.Front(); e != nil; e = e.Next() {
								fmt.Printf("%d: %v\n",e.Value.(ranking.Item).Vote, e.Value.(ranking.Item).Url)
							}
						}
					}
				}
			}
		}
	}()

	readStream(client, sc, path, query, resp,
		func(line []byte) {
			stream <- line
		}, done)

	return
}

func main() {
	var (
		err    error
		args   *Args
		client *twittergo.Client
	)

	args = parseArgs()
	if client, err = LoadCredentials(); err != nil {
		fmt.Printf("Could not parse CREDENTIALS file: %v\n", err)
		os.Exit(1)
	}
	fmt.Println(args.Track)
	query := url.Values{}
	query.Set("track", args.Track)
	query.Set("lang", args.Lang)

	fmt.Println("Printing everything about data science, big data and machine learning:")
	fmt.Printf("=========================================================\n")
	if err = filterStream(client, "/1.1/statuses/filter.json", query); err != nil {
		fmt.Println("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

}
<commit_msg>Fixed bug in unmarshal json<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"
	"container/list"
	js "encoding/json"

	"github.com/kurrik/oauth1a"
	"github.com/codingneo/twittergo"
	"github.com/kurrik/json"
	"github.com/robfig/cron"
	//"github.com/PuerkitoBio/goquery"
	"github.com/advancedlogic/GoOse"
	"github.com/codingneo/tweetsbot/ranking"
)

func LoadCredentials() (client *twittergo.Client, err error) {
	credentials, err := ioutil.ReadFile("CREDENTIALS")
	if err != nil {
		return
	}
	lines := strings.Split(string(credentials), "\n")
	config := &oauth1a.ClientConfig{
		ConsumerKey:    lines[0],
		ConsumerSecret: lines[1],
	}
	user := oauth1a.NewAuthorizedConfig(lines[2], lines[3])
	client = twittergo.NewClient(config, user, "stream.twitter.com")
	return
}

type Args struct {
	Track string
	Lang string
}

func parseArgs() *Args {
	a := &Args{}
	flag.StringVar(&a.Track, "track", "Data Science,Big Data,Machine Learning", "Keyword to look up")
	flag.StringVar(&a.Lang, "lang", "en", "Language to look up")
	flag.Parse()
	return a
}

type TopList struct {
	Articles []ranking.Item
}

func LoadExistingList(filename string) *list.List {
	result := list.New()

	data, err := ioutil.ReadFile(filename)
	if (err == nil) {
		// today's list exists, load existing list
		var input TopList
		js.Unmarshal(data, &input)
		for i := 0; i<len(input.Articles); i++ {
			result.PushBack(input.Articles[i])
		}
	}

	return result
}

type streamConn struct {
	client   *http.Client
	resp     *http.Response
	url      *url.URL
	stale    bool
	closed   bool
	mu       sync.Mutex
	// wait time before trying to reconnect, this will be
	// exponentially moved up until reaching maxWait, when
	// it will exit
	wait    int
	maxWait int
	connect func() (*http.Response, error)
}

func NewStreamConn(max int) streamConn {
	return streamConn{wait: 1, maxWait: max}
}

func (conn *streamConn) Close() {
	// Just mark the connection as stale, and let the connect() handler close after a read
	conn.mu.Lock()
	defer conn.mu.Unlock()
	conn.stale = true
	conn.closed = true
	if conn.resp != nil {
		conn.resp.Body.Close()
	}
}

func (conn *streamConn) isStale() bool {
	conn.mu.Lock()
	r := conn.stale
	conn.mu.Unlock()
	return r
}

func readStream(client *twittergo.Client, sc streamConn, path string, query url.Values,
				resp *twittergo.APIResponse, handler func([]byte), done chan bool) {

	var reader *bufio.Reader
	reader = bufio.NewReader(resp.Body)

	for {
		//we've been closed
		if sc.isStale() {
			sc.Close()
			fmt.Println("Connection closed, shutting down ")
			break
		}

		line, err := reader.ReadBytes('\n')

		if err != nil {
			if sc.isStale() {
				fmt.Println("conn stale, continue")
				continue
			}

			time.Sleep(time.Second * time.Duration(sc.wait))
			//try reconnecting, but exponentially back off until MaxWait is reached then exit?
			resp, err := Connect(client, path, query)
			if err != nil || resp == nil {
				fmt.Println(" Could not reconnect to source? sleeping and will retry ")
				if sc.wait < sc.maxWait {
					sc.wait = sc.wait * 2
				} else {
					fmt.Println("exiting, max wait reached")
					done <- true
					return
				}
				continue
			}
			if resp.StatusCode != 200 {
				fmt.Printf("resp.StatusCode = %d", resp.StatusCode)
				if sc.wait < sc.maxWait {
					sc.wait = sc.wait * 2
				}
				continue
			}

			reader = bufio.NewReader(resp.Body)
			continue
		} else if sc.wait != 1 {
			sc.wait = 1
		}
		line = bytes.TrimSpace(line)
		fmt.Println("Received a line ")

		if len(line) == 0 {
			continue
		}
		handler(line)
	}
}

func Connect(client *twittergo.Client, path string, query url.Values) (resp *twittergo.APIResponse, err error) {
	var (
		req 	*http.Request
	)

	url := fmt.Sprintf("%v?%v", path, query.Encode())
	req, err = http.NewRequest("GET", url, nil)
	if err != nil {
		err = fmt.Errorf("Could not parse request: %v\n", err)
		return
	}
	resp, err = client.SendRequest(req)
	if err != nil {
		err = fmt.Errorf("Could not send request: %v\n", err)
		return
	}

	fmt.Printf("resp.StatusCode=%d\n", resp.StatusCode)
	return
}

func filterStream(client *twittergo.Client, path string, query url.Values) (err error) {
	var (
		resp    *twittergo.APIResponse
	)

	sc := NewStreamConn(300)

	// Step 1: connect to twitter public stream endpoint
	resp, err = Connect(client, path, query)

	done := make(chan bool)
	stream := make(chan []byte, 1000)
	go func() {
		startday := time.Now().UTC().Day()
		filename := "./data/toplist-" +
			time.Now().UTC().Format("2006-01-02") +".json"

		//
		topList := LoadExistingList(filename)

		//Cron job to store toplist per hour
		c := cron.New()
		c.AddFunc("0 * * * * *",
			func() {
				fmt.Println("cron cron cron cron ............................")

				output := make(map[string]interface{})
				output["articles"] = make([]ranking.Item, 0)

				f, err := os.OpenFile(filename, os.O_RDWR, 0666)
				if (err == nil) {
					f.Close()
					err = os.Remove(filename)
				}

				f, err = os.Create(filename)
				if (err != nil) {
					fmt.Println("[Cron] File creation error")
				}

				tlist := make([]ranking.Item, 0)
				for e := topList.Front(); e != nil; e = e.Next() {
					fmt.Println("[Cron] Write url into file")
					//f.WriteString(e.Value.(ranking.Item).Url)
					//f.WriteString("\n")
					tlist = append(tlist, e.Value.(ranking.Item))
				}
				output["articles"] = tlist

				jsonstr, _ := js.Marshal(output)
				f.WriteString(string(jsonstr))
				f.Sync()
				f.Close()
			})
		c.Start()
		fmt.Println("cron job start")

		g := goose.New()
		for data := range stream {
			if (time.Now().UTC().Day() != startday) {
				// Clear the top list
				var next *list.Element
				for e := topList.Front(); e != nil; e = next {
					next = e.Next()
					topList.Remove(e)
				}

				startday = time.Now().UTC().Day()
				filename = "./data/toplist-" +
					time.Now().UTC().Format("2006-01-02") +".json"
			}

			fmt.Println(string(data))
			tweet := &twittergo.Tweet{}
			err := json.Unmarshal(data, tweet)
			if (err == nil) {
				fmt.Printf("ID:                   %v\n", tweet.Id())
				fmt.Printf("User:                 %v\n", tweet.User().ScreenName())
				fmt.Printf("Tweet:                %v\n", tweet.Text())

				rs := tweet.RetweetedStatus()
				vote := 0
				createdAt := tweet.CreatedAt()
				if (rs != nil) {
					fmt.Printf("retweet_count:        %d\n", rs.RetweetCount())
					fmt.Printf("favorite_count:        %d\n", rs.FavoriteCount())
					vote += int(rs.RetweetCount()+rs.FavoriteCount())

					createdAt = rs.CreatedAt()
				}

				if (time.Now().UTC().Sub(createdAt).Hours() < 24.0) {
					e := tweet.Entities()
					if (e != nil) {
						fmt.Printf("url:        %v\n", e.FirstUrl().ExpandedUrl())

						// Form top item
						if (e.FirstUrl().ExpandedUrl()!="") {
							item := ranking.Item{}
							item.Vote = vote
							item.Url = e.FirstUrl().ExpandedUrl()

							// article extraction
							//doc, err := goquery.NewDocument(item.Url)
							article := g.ExtractFromUrl(item.Url)

							fmt.Println("title", article.Title)
	    				fmt.Println("description", article.MetaDescription)
	    				fmt.Println("top image", article.TopImage)

	    				if (article.Title != "") &&
	    					 (article.MetaDescription != "") {
								item.Title = article.Title
	    					item.Description = article.MetaDescription
	    					item.Image = article.TopImage

	    					ranking.Insert(topList, item)
	    				}

							//if err == nil {
							//	item.Title = doc.Find("title").Text()
							//	fmt.Printf("title:        %v\n", item.Title)
							//	ranking.Insert(topList, item)
							//}

							fmt.Println("**********************************")
							for e := topList.Front(); e != nil; e = e.Next() {
								fmt.Printf("%d: %v\n",e.Value.(ranking.Item).Vote, e.Value.(ranking.Item).Url)
							}
						}
					}
				}
			}
		}
	}()

	readStream(client, sc, path, query, resp,
		func(line []byte) {
			stream <- line
		}, done)

	return
}

func main() {
	var (
		err    error
		args   *Args
		client *twittergo.Client
	)

	args = parseArgs()
	if client, err = LoadCredentials(); err != nil {
		fmt.Printf("Could not parse CREDENTIALS file: %v\n", err)
		os.Exit(1)
	}
	fmt.Println(args.Track)
	query := url.Values{}
	query.Set("track", args.Track)
	query.Set("lang", args.Lang)

	fmt.Println("Printing everything about data science, big data and machine learning:")
	fmt.Printf("=========================================================\n")
	if err = filterStream(client, "/1.1/statuses/filter.json", query); err != nil {
		fmt.Println("Error: %v\n", err)
	}
	fmt.Printf("\n\n")

}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package state

import (
	"errors"
	"github.com/jacobsa/comeback/backup"
	"github.com/jacobsa/comeback/backup/mock"
	"github.com/jacobsa/comeback/blob"
	"github.com/jacobsa/comeback/fs"
	"github.com/jacobsa/comeback/fs/mock"
	. "github.com/jacobsa/oglematchers"
	"github.com/jacobsa/oglemock"
	. "github.com/jacobsa/ogletest"
	"testing"
	"time"
)

func TestScoreMapSaver(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

type ScoreMapSaverTest struct {
	scoreMap   ScoreMap
	fileSystem mock_fs.MockFileSystem
	wrapped    mock_backup.MockFileSaver
	now        time.Time
	nowFunc    func() time.Time

	saver backup.FileSaver

	path   string
	scores []blob.Score
	err    error
}

func init() { RegisterTestSuite(&ScoreMapSaverTest{}) }

func (t *ScoreMapSaverTest) SetUp(i *TestInfo) {
	t.scoreMap = NewScoreMap()
	t.fileSystem = mock_fs.NewMockFileSystem(i.MockController, "fileSystem")
	t.wrapped = mock_backup.NewMockFileSaver(i.MockController, "wrapped")
	t.now = time.Date(2012, time.August, 15, 22, 56, 00, 00, time.Local)
	t.nowFunc = func() time.Time { return t.now }

	t.saver = newScoreMapFileSaver(
		t.scoreMap,
		t.fileSystem,
		t.wrapped,
		t.nowFunc,
	)
}

func (t *ScoreMapSaverTest) call() {
	t.scores, t.err = t.saver.Save(t.path)
}

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ScoreMapSaverTest) CallsStat() {
	t.path = "taco"

	// File system
	ExpectCall(t.fileSystem, "Stat")("taco").
		WillOnce(oglemock.Return(fs.DirectoryEntry{}, errors.New("")))

	// Call
	t.call()
}

func (t *ScoreMapSaverTest) StatReturnsError() {
	// File system
	ExpectCall(t.fileSystem, "Stat")(Any()).
		WillOnce(oglemock.Return(fs.DirectoryEntry{}, errors.New("taco")))

	// Call
	t.call()

	ExpectThat(t.err, Error(HasSubstr("Stat")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *ScoreMapSaverTest) ScoreMapContainsEntry() {
	t.path = "taco"

	expectedKey := ScoreMapKey{
		Path:        "taco",
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       t.now.Add(-15 * time.Minute),
		Inode:       23,
		Size:        29,
	}

	// Map
	expectedScores := []blob.Score{
		blob.ComputeScore([]byte("foo")),
		blob.ComputeScore([]byte("bar")),
	}

	t.scoreMap.Set(expectedKey, expectedScores)

	// File system
	entry := fs.DirectoryEntry{
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       expectedKey.MTime,
		Inode:       23,
		Size:        29,
	}

	ExpectCall(t.fileSystem, "Stat")(Any()).
		WillOnce(oglemock.Return(entry, nil))

	// Call
	t.call()

	AssertEq(nil, t.err)
	ExpectThat(t.scores, DeepEquals(expectedScores))
}

func (t *ScoreMapSaverTest) CallsWrapped() {
	t.path = "taco"

	// File system
	ExpectCall(t.fileSystem, "Stat")(Any()).
		WillOnce(oglemock.Return(fs.DirectoryEntry{}, nil))

	// Wrapped
	ExpectCall(t.wrapped, "Save")("taco").
		WillOnce(oglemock.Return(nil, errors.New("")))

	// Call
	t.call()
}

func (t *ScoreMapSaverTest) WrappedReturnsError() {
	expectedKey := ScoreMapKey{
		Path:        "taco",
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       t.now.Add(-15 * time.Minute),
		Inode:       23,
		Size:        29,
	}

	// File system
	entry := fs.DirectoryEntry{
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       expectedKey.MTime,
		Inode:       23,
		Size:        29,
	}

	ExpectCall(t.fileSystem, "Stat")(Any()).
		WillOnce(oglemock.Return(entry, nil))

	// Wrapped
	ExpectCall(t.wrapped, "Save")(Any()).
		WillOnce(oglemock.Return(nil, errors.New("taco")))

	// Call
	t.call()

	AssertThat(t.err, Error(Equals("taco")))
	ExpectEq(nil, t.scoreMap.Get(expectedKey))
}

func (t *ScoreMapSaverTest) WrappedReturnsScores() {
	t.path = "taco"
	expectedKey := ScoreMapKey{
		Path:        "taco",
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       t.now.Add(-15 * time.Minute),
		Inode:       23,
		Size:        29,
	}

	// File system
	entry := fs.DirectoryEntry{
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       expectedKey.MTime,
		Inode:       23,
		Size:        29,
	}

	ExpectCall(t.fileSystem, "Stat")(Any()).
		WillOnce(oglemock.Return(entry, nil))

	// Wrapped
	expectedScores := []blob.Score{
		blob.ComputeScore([]byte("foo")),
		blob.ComputeScore([]byte("bar")),
	}

	ExpectCall(t.wrapped, "Save")(Any()).
		WillOnce(oglemock.Return(expectedScores, nil))

	// Call
	t.call()

	AssertEq(nil, t.err)
	ExpectThat(t.scoreMap.Get(expectedKey), DeepEquals(expectedScores))
}

func (t *ScoreMapSaverTest) MTimeInFuture() {
	t.path = "taco"
	mapKey := ScoreMapKey{
		Path:        "taco",
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       t.now.Add(time.Minute),
		Inode:       23,
		Size:        29,
	}

	// File system
	entry := fs.DirectoryEntry{
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       mapKey.MTime,
		Inode:       23,
		Size:        29,
	}

	ExpectCall(t.fileSystem, "Stat")(Any()).
		WillOnce(oglemock.Return(entry, nil))

	// Wrapped
	scores := []blob.Score{
		blob.ComputeScore([]byte("foo")),
	}

	ExpectCall(t.wrapped, "Save")(Any()).
		WillOnce(oglemock.Return(scores, nil))

	// Call
	t.call()

	AssertEq(nil, t.err)
	ExpectEq(nil, t.scoreMap.Get(mapKey))
}

func (t *ScoreMapSaverTest) MTimeInRecentPast() {
	t.path = "taco"
	mapKey := ScoreMapKey{
		Path:        "taco",
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       t.now.Add(-30 * time.Second),
		Inode:       23,
		Size:        29,
	}

	// File system
	entry := fs.DirectoryEntry{
		Permissions: 0644,
		Uid:         17,
		Gid:         19,
		MTime:       mapKey.MTime,
		Inode:       23,
		Size:        29,
	}

	ExpectCall(t.fileSystem, "Stat")(Any()).
		WillOnce(oglemock.Return(entry, nil))

	// Wrapped
	scores := []blob.Score{
		blob.ComputeScore([]byte("foo")),
	}

	ExpectCall(t.wrapped, "Save")(Any()).
		WillOnce(oglemock.Return(scores, nil))

	// Call
	t.call()

	AssertEq(nil, t.err)
	ExpectEq(nil, t.scoreMap.Get(mapKey))
}
<commit_msg>Deleted another.<commit_after><|endoftext|>


<commit_before>package main

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import (
	"net/url"

	"github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
)

func BuildQuery(v url.Values, selectStmt string, queryParamsToSQLCols map[string]string) (string, map[string]interface{}) {
	var sqlQuery string
	var criteria string
	var queryValues map[string]interface{}
	if len(v) > 0 {
		criteria, queryValues = parseCriteriaAndQueryValues(queryParamsToSQLCols, v)
		if len(queryValues) > 0 {
			sqlQuery = selectStmt + "\nWHERE " + criteria
		} else {
			sqlQuery = selectStmt
		}
	} else {
		sqlQuery = selectStmt
	}
	log.Debugln("\n--\n" + sqlQuery)
	return sqlQuery, queryValues
}

func parseCriteriaAndQueryValues(queryParamsToSQLCols map[string]string, v url.Values) (string, map[string]interface{}) {
	m := make(map[string]interface{})
	var criteria string
	queryValues := make(map[string]interface{})
	for key, val := range queryParamsToSQLCols {
		if urlValue, ok := v[key]; ok {
			m[key] = urlValue[0]
			criteria = val + "=:" + key
			queryValues[key] = urlValue[0]
			break
		}
	}
	return criteria, queryValues
}
<commit_msg>added comment to point out awareness of a single query parameter support<commit_after>package main

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import (
	"net/url"

	"github.com/apache/incubator-trafficcontrol/traffic_monitor_golang/common/log"
)

func BuildQuery(v url.Values, selectStmt string, queryParamsToSQLCols map[string]string) (string, map[string]interface{}) {
	var sqlQuery string
	var criteria string
	var queryValues map[string]interface{}
	if len(v) > 0 {
		criteria, queryValues = parseCriteriaAndQueryValues(queryParamsToSQLCols, v)
		if len(queryValues) > 0 {
			sqlQuery = selectStmt + "\nWHERE " + criteria
		} else {
			sqlQuery = selectStmt
		}
	} else {
		sqlQuery = selectStmt
	}
	log.Debugln("\n--\n" + sqlQuery)
	return sqlQuery, queryValues
}

func parseCriteriaAndQueryValues(queryParamsToSQLCols map[string]string, v url.Values) (string, map[string]interface{}) {
	m := make(map[string]interface{})
	var criteria string
	queryValues := make(map[string]interface{})
	for key, val := range queryParamsToSQLCols {
		if urlValue, ok := v[key]; ok {
			m[key] = urlValue[0]
			criteria = val + "=:" + key
			queryValues[key] = urlValue[0]
			// currently only supports a single query parameter at a time
			break
		}
	}
	return criteria, queryValues
}
<|endoftext|>


<commit_before>package ui

import "net/http"

func ServeNotFound(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Not Found", http.StatusNotFound)
}

func ServeUnauthorized(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Unauthorized", http.StatusUnauthorized)
}

func ServeBadRequest(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Bad Request", http.StatusBadRequest)
}

func ServeInternalServerError(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
<commit_msg>Implement catch func<commit_after>package ui

import "net/http"

func ServeNotFound(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Not Found", http.StatusNotFound)
}

func ServeUnauthorized(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Unauthorized", http.StatusUnauthorized)
}

func ServeBadRequest(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Bad Request", http.StatusBadRequest)
}

func ServeInternalServerError(w http.ResponseWriter, r *http.Request) {
	http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}

func catch(r *http.Request, err error) {
	if err != nil {
		panic(err)
	}
}
<|endoftext|>