<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net/url"
	"os"
	"strings"

	log "github.com/avabot/ava/Godeps/_workspace/src/github.com/Sirupsen/logrus"
	"github.com/avabot/ava/Godeps/_workspace/src/github.com/garyburd/go-oauth/oauth"
	"github.com/avabot/ava/Godeps/_workspace/src/github.com/jmoiron/sqlx"
	"github.com/avabot/ava/shared/datatypes"
	"github.com/avabot/ava/shared/knowledge"
	"github.com/avabot/ava/shared/language"
	"github.com/avabot/ava/shared/pkg"
)

type Yelp string

type client struct {
	client oauth.Client
	token  oauth.Credentials
}

type yelpResp struct {
	Businesses []struct {
		Name         string
		ImageURL     string `json:"image_url"`
		MobileURL    string `json:"mobile_url"`
		DisplayPhone string `json:"display_phone"`
		Distance     int
		Rating       float64
		Location     struct {
			City           string
			DisplayAddress []string `json:"display_address"`
		}
	}
}

var port = flag.Int("port", 0, "Port used to communicate with Ava.")
var ErrNoBusinesses = errors.New("no businesses")

var c client
var db *sqlx.DB
var p *pkg.Pkg
var l *log.Entry

func main() {
	flag.Parse()
	l = log.WithFields(log.Fields{
		"pkg": "yelp",
	})
	c.client.Credentials.Token = os.Getenv("YELP_CONSUMER_KEY")
	c.client.Credentials.Secret = os.Getenv("YELP_CONSUMER_SECRET")
	c.token.Token = os.Getenv("YELP_TOKEN")
	c.token.Secret = os.Getenv("YELP_TOKEN_SECRET")
	var err error
	db, err = pkg.ConnectDB()
	if err != nil {
		l.Fatalln(err)
	}
	trigger := &dt.StructuredInput{
		Commands: []string{
			"find",
			"where",
			"show",
			"recommend",
			"recommendation",
			"recommendations",
		},
		Objects: language.Foods(),
	}
	p, err = pkg.NewPackage("yelp", *port, trigger)
	if err != nil {
		l.Fatalln("building", err)
	}
	yelp := new(Yelp)
	if err := p.Register(yelp); err != nil {
		l.Fatalln("registering", err)
	}
}

func (t *Yelp) Run(m *dt.Msg, respMsg *dt.RespMsg) error {
	// NOTE optional: get state before this package was run, enabling
	// chaining. For instance, allow passing context from a FourSquare
	// result into this. See the opening lines of FollowUp() for an example
	resp := m.NewResponse()
	resp.State = map[string]interface{}{
		"query":      "",
		"location":   "",
		"offset":     float64(0),
		"businesses": []interface{}{},
	}
	si := m.Input.StructuredInput
	query := ""
	for _, o := range si.Objects {
		query += o + " "
	}
	for _, p := range si.Places {
		query += p + " "
	}
	resp.State["query"] = query
	if len(si.Places) == 0 {
		l.Infoln("no place entered, getting location")
		loc, question, err := knowledge.GetLocation(db, m.User)
		if err != nil {
			return err
		}
		if len(question) > 0 {
			if loc != nil && len(loc.Name) > 0 {
				resp.State["location"] = loc.Name
			}
			resp.Sentence = question
			return p.SaveResponse(respMsg, resp)
		}
		resp.State["location"] = loc.Name
	}
	// Occurs in the case of "nearby" or other contextual place terms, where
	// no previous context was available to expand it.
	if len(resp.State["location"].(string)) == 0 {
		loc, question, err := knowledge.GetLocation(db, m.User)
		if err != nil {
			return err
		}
		if len(question) > 0 {
			if loc != nil && len(loc.Name) > 0 {
				resp.State["location"] = loc.Name
			}
			resp.Sentence = question
			return p.SaveResponse(respMsg, resp)
		}
		resp.State["location"] = loc.Name
	}
	if err := t.searchYelp(resp); err != nil {
		l.WithField("fn", "searchYelp").Errorln(err)
	}
	return p.SaveResponse(respMsg, resp)
}

// FollowUp handles dialog question/answers and additional user queries
func (t *Yelp) FollowUp(m *dt.Msg,
	respMsg *dt.RespMsg) error {
	// Retrieve the conversation's context
	if err := m.GetLastResponse(db); err != nil {
		l.WithField("fn", "GetLastResponse").Errorln(err)
		return err
	}
	resp := m.NewResponse()

	// First we handle dialog. If we asked for a location, use the response
	if resp.State["location"] == "" {
		loc := m.Input.StructuredInput.All()
		resp.State["location"] = loc
		if err := t.searchYelp(resp); err != nil {
			l.WithField("fn", "searchYelp").Fatalln(err)
		}
		return p.SaveResponse(respMsg, resp)
	}

	// If no businesses are returned inform the user now
	if resp.State["businesses"] != nil &&
		len(resp.State["businesses"].([]interface{})) == 0 {
		resp.Sentence = "I couldn't find anything like that"
		return p.SaveResponse(respMsg, resp)
	}

	// Responses were returned, and the user has asked this package an
	// additional query. Handle the query by keyword
	words := strings.Fields(m.Input.Sentence)
	offI := int(resp.State["offset"].(float64))
	var s string
	for _, w := range words {
		w = strings.TrimRight(w, ").,;?!:")
		switch strings.ToLower(w) {
		case "rated", "rating", "review", "recommend", "recommended":
			s = fmt.Sprintf("It has a %s star review on Yelp",<commit_msg>Convert fatal err to simply log<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net/url"
	"os"
	"strings"

	log "github.com/avabot/ava/Godeps/_workspace/src/github.com/Sirupsen/logrus"
	"github.com/avabot/ava/Godeps/_workspace/src/github.com/garyburd/go-oauth/oauth"
	"github.com/avabot/ava/Godeps/_workspace/src/github.com/jmoiron/sqlx"
	"github.com/avabot/ava/shared/datatypes"
	"github.com/avabot/ava/shared/knowledge"
	"github.com/avabot/ava/shared/language"
	"github.com/avabot/ava/shared/pkg"
)

type Yelp string

type client struct {
	client oauth.Client
	token  oauth.Credentials
}

type yelpResp struct {
	Businesses []struct {
		Name         string
		ImageURL     string `json:"image_url"`
		MobileURL    string `json:"mobile_url"`
		DisplayPhone string `json:"display_phone"`
		Distance     int
		Rating       float64
		Location     struct {
			City           string
			DisplayAddress []string `json:"display_address"`
		}
	}
}

var port = flag.Int("port", 0, "Port used to communicate with Ava.")
var ErrNoBusinesses = errors.New("no businesses")

var c client
var db *sqlx.DB
var p *pkg.Pkg
var l *log.Entry

func main() {
	flag.Parse()
	l = log.WithFields(log.Fields{
		"pkg": "yelp",
	})
	c.client.Credentials.Token = os.Getenv("YELP_CONSUMER_KEY")
	c.client.Credentials.Secret = os.Getenv("YELP_CONSUMER_SECRET")
	c.token.Token = os.Getenv("YELP_TOKEN")
	c.token.Secret = os.Getenv("YELP_TOKEN_SECRET")
	var err error
	db, err = pkg.ConnectDB()
	if err != nil {
		l.Fatalln(err)
	}
	trigger := &dt.StructuredInput{
		Commands: []string{
			"find",
			"where",
			"show",
			"recommend",
			"recommendation",
			"recommendations",
		},
		Objects: language.Foods(),
	}
	p, err = pkg.NewPackage("yelp", *port, trigger)
	if err != nil {
		l.Fatalln("building", err)
	}
	yelp := new(Yelp)
	if err := p.Register(yelp); err != nil {
		l.Fatalln("registering", err)
	}
}

func (t *Yelp) Run(m *dt.Msg, respMsg *dt.RespMsg) error {
	// NOTE optional: get state before this package was run, enabling
	// chaining. For instance, allow passing context from a FourSquare
	// result into this. See the opening lines of FollowUp() for an example
	resp := m.NewResponse()
	resp.State = map[string]interface{}{
		"query":      "",
		"location":   "",
		"offset":     float64(0),
		"businesses": []interface{}{},
	}
	si := m.Input.StructuredInput
	query := ""
	for _, o := range si.Objects {
		query += o + " "
	}
	for _, p := range si.Places {
		query += p + " "
	}
	resp.State["query"] = query
	if len(si.Places) == 0 {
		l.Infoln("no place entered, getting location")
		loc, question, err := knowledge.GetLocation(db, m.User)
		if err != nil {
			return err
		}
		if len(question) > 0 {
			if loc != nil && len(loc.Name) > 0 {
				resp.State["location"] = loc.Name
			}
			resp.Sentence = question
			return p.SaveResponse(respMsg, resp)
		}
		resp.State["location"] = loc.Name
	}
	// Occurs in the case of "nearby" or other contextual place terms, where
	// no previous context was available to expand it.
	if len(resp.State["location"].(string)) == 0 {
		loc, question, err := knowledge.GetLocation(db, m.User)
		if err != nil {
			return err
		}
		if len(question) > 0 {
			if loc != nil && len(loc.Name) > 0 {
				resp.State["location"] = loc.Name
			}
			resp.Sentence = question
			return p.SaveResponse(respMsg, resp)
		}
		resp.State["location"] = loc.Name
	}
	if err := t.searchYelp(resp); err != nil {
		l.WithField("fn", "searchYelp").Errorln(err)
	}
	return p.SaveResponse(respMsg, resp)
}

// FollowUp handles dialog question/answers and additional user queries
func (t *Yelp) FollowUp(m *dt.Msg,
	respMsg *dt.RespMsg) error {
	// Retrieve the conversation's context
	if err := m.GetLastResponse(db); err != nil {
		l.WithField("fn", "GetLastResponse").Errorln(err)
		return err
	}
	resp := m.NewResponse()

	// First we handle dialog. If we asked for a location, use the response
	if resp.State["location"] == "" {
		loc := m.Input.StructuredInput.All()
		resp.State["location"] = loc
		if err := t.searchYelp(resp); err != nil {
			l.WithField("fn", "searchYelp").Errorln(err)
		}
		return p.SaveResponse(respMsg, resp)
	}

	// If no businesses are returned inform the user now
	if resp.State["businesses"] != nil &&
		len(resp.State["businesses"].([]interface{})) == 0 {
		resp.Sentence = "I couldn't find anything like that"
		return p.SaveResponse(respMsg, resp)
	}

	// Responses were returned, and the user has asked this package an
	// additional query. Handle the query by keyword
	words := strings.Fields(m.Input.Sentence)
	offI := int(resp.State["offset"].(float64))
	var s string
	for _, w := range words {
		w = strings.TrimRight(w, ").,;?!:")
		switch strings.ToLower(w) {
		case "rated", "rating", "review", "recommend", "recommended":
			s = fmt.Sprintf("It has a %s star review on Yelp",
{'fraction_non_alphanumeric': 0.15410039248089238, 'fraction_numerical': 0.0030985333608758523, 'mean_word_length': 3.5674528301886794, 'pattern_counts': {'":': 12, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6573640', 'n_tokens_mistral': 3779, 'n_tokens_neox': 3492, 'n_words': 864}