diff --git a/api/therapist.go b/api/therapist.go index 1921ab9..fe6387a 100644 --- a/api/therapist.go +++ b/api/therapist.go @@ -1,24 +1,26 @@ package api type Therapist struct { - ID int `bun:"id,pk,autoincrement" json:"id"` - Title string `json:"title"` - Credentials string `json:"credentials"` - Verified string `json:"verified"` - Statement string `json:"statement"` - Phone string `json:"phone"` - Location string `json:"location"` - Link string `json:"link"` + ID int `bun:"id,pk,autoincrement" json:"id"` + Title string `json:"title"` + AcceptingAppointments string `json:"accepting_appointments"` + Credentials string `json:"credentials"` + Verified string `json:"verified"` + Statement string `json:"statement"` + Phone string `json:"phone"` + Location string `json:"location"` + Link string `json:"link"` } type GetTherapistParams struct { - Title *string `json:"title"` - Credentials *string `json:"credentials"` - Verified *string `json:"verified"` - Statement *string `json:"statement"` - Phone *string `json:"phone"` - Location *string `json:"location"` - Link *string `json:"link"` - Limit *int `json:"limit"` - Offset *int `json:"offset"` + Title *string `json:"title"` + Credentials *string `json:"credentials"` + AcceptingAppointments *bool `json:"accepting_appointments"` + Verified *string `json:"verified"` + Statement *string `json:"statement"` + Phone *string `json:"phone"` + Location *string `json:"location"` + Link *string `json:"link"` + Limit *int `json:"limit"` + Offset *int `json:"offset"` } diff --git a/cmd/psych/main.go b/cmd/psych/main.go index ab7185d..38f0db9 100644 --- a/cmd/psych/main.go +++ b/cmd/psych/main.go @@ -125,6 +125,12 @@ func main() { Value: "", Category: "Scraping", }, + &cli.StringFlag{ + Name: "insurance", + Usage: "Insurance to search", + Value: "premera", + Category: "Scraping", + }, ), Before: func(c *cli.Context) error { if _, err := os.Stat(c.String("config")); err != nil { @@ -150,10 +156,11 @@ func main() { }, Action: func(c *cli.Context) error { - url, err := buildURL(c.String("state"), c.String("county"), c.String("city"), c.String("zip")) - if err != nil { - return err - } + // url, err := buildURL(c.String("state"), c.String("county"), c.String("city"), c.String("zip")) + // if err != nil { + // return err + // } + url := "https://www.psychologytoday.com/us/therapists/wa/king-county?category=trauma-and-ptsd&page=2&spec=6&spec=506" config := scrape.Config{URL: url, CacheDir: filepath.Join(c.String("config"), "cache/")} diff --git a/graph/generated.go b/graph/generated.go index 1d3181c..bf834cf 100644 --- a/graph/generated.go +++ b/graph/generated.go @@ -50,14 +50,15 @@ type ComplexityRoot struct { } Therapist struct { - Credentials func(childComplexity int) int - ID func(childComplexity int) int - Link func(childComplexity int) int - Location func(childComplexity int) int - Phone func(childComplexity int) int - Statement func(childComplexity int) int - Title func(childComplexity int) int - Verified func(childComplexity int) int + AcceptingAppointments func(childComplexity int) int + Credentials func(childComplexity int) int + ID func(childComplexity int) int + Link func(childComplexity int) int + Location func(childComplexity int) int + Phone func(childComplexity int) int + Statement func(childComplexity int) int + Title func(childComplexity int) int + Verified func(childComplexity int) int } } @@ -92,6 +93,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Therapists(childComplexity, args["filter"].(*therapy.TherapistFilters)), true + case "Therapist.accepting_appointments": + if e.complexity.Therapist.AcceptingAppointments == nil { + break + } + + return e.complexity.Therapist.AcceptingAppointments(childComplexity), true + case "Therapist.credentials": if e.complexity.Therapist.Credentials == nil { break @@ -369,6 +377,8 @@ func (ec *executionContext) fieldContext_Query_therapists(ctx context.Context, f return ec.fieldContext_Therapist_id(ctx, field) case "title": return ec.fieldContext_Therapist_title(ctx, field) + case "accepting_appointments": + return ec.fieldContext_Therapist_accepting_appointments(ctx, field) case "credentials": return ec.fieldContext_Therapist_credentials(ctx, field) case "verified": @@ -616,6 +626,50 @@ func (ec *executionContext) fieldContext_Therapist_title(ctx context.Context, fi return fc, nil } +func (ec *executionContext) _Therapist_accepting_appointments(ctx context.Context, field graphql.CollectedField, obj *api.Therapist) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Therapist_accepting_appointments(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.AcceptingAppointments, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Therapist_accepting_appointments(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Therapist", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Therapist_credentials(ctx context.Context, field graphql.CollectedField, obj *api.Therapist) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Therapist_credentials(ctx, field) if err != nil { @@ -2660,7 +2714,7 @@ func (ec *executionContext) unmarshalInputTherapistFilters(ctx context.Context, asMap[k] = v } - fieldsInOrder := [...]string{"title", "credentials", "verified", "statement", "phone", "location", "link", "limit", "offset"} + fieldsInOrder := [...]string{"title", "accepting_appointments", "credentials", "verified", "statement", "phone", "location", "link", "limit", "offset"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -2676,6 +2730,15 @@ func (ec *executionContext) unmarshalInputTherapistFilters(ctx context.Context, return it, err } it.Title = data + case "accepting_appointments": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("accepting_appointments")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.AcceptingAppointments = data case "credentials": var err error @@ -2855,6 +2918,11 @@ func (ec *executionContext) _Therapist(ctx context.Context, sel ast.SelectionSet if out.Values[i] == graphql.Null { out.Invalids++ } + case "accepting_appointments": + out.Values[i] = ec._Therapist_accepting_appointments(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } case "credentials": out.Values[i] = ec._Therapist_credentials(ctx, field, obj) if out.Values[i] == graphql.Null { diff --git a/graph/schema.graphqls b/graph/schema.graphqls index c79c915..a54d9ff 100644 --- a/graph/schema.graphqls +++ b/graph/schema.graphqls @@ -5,6 +5,7 @@ type Therapist { id: ID! title: String! + accepting_appointments: String! credentials: String! verified: String! statement: String! @@ -15,6 +16,7 @@ type Therapist { input TherapistFilters { title: String + accepting_appointments: Boolean credentials: String verified: String statement: String diff --git a/models_gen.go b/models_gen.go index 5e29a53..2a70b77 100644 --- a/models_gen.go +++ b/models_gen.go @@ -3,13 +3,14 @@ package therapy type TherapistFilters struct { - Title *string `json:"title,omitempty"` - Credentials *string `json:"credentials,omitempty"` - Verified *string `json:"verified,omitempty"` - Statement *string `json:"statement,omitempty"` - Phone *string `json:"phone,omitempty"` - Location *string `json:"location,omitempty"` - Link *string `json:"link,omitempty"` - Limit *int `json:"limit,omitempty"` - Offset *int `json:"offset,omitempty"` + Title *string `json:"title,omitempty"` + AcceptingAppointments *bool `json:"accepting_appointments,omitempty"` + Credentials *string `json:"credentials,omitempty"` + Verified *string `json:"verified,omitempty"` + Statement *string `json:"statement,omitempty"` + Phone *string `json:"phone,omitempty"` + Location *string `json:"location,omitempty"` + Link *string `json:"link,omitempty"` + Limit *int `json:"limit,omitempty"` + Offset *int `json:"offset,omitempty"` } diff --git a/scrape/scrape.go b/scrape/scrape.go index f8ac3be..0da10c9 100644 --- a/scrape/scrape.go +++ b/scrape/scrape.go @@ -52,6 +52,7 @@ func (s *scraper) Scrape(config Config) []api.Therapist { c.OnHTML(".results-row", func(e *colly.HTMLElement) { var therapist api.Therapist + e.ForEach(".results-row-info", func(i int, e *colly.HTMLElement) { therapist.Title = e.ChildText(".profile-title") therapist.Credentials = e.ChildText(".profile-subtitle-credentials") @@ -60,6 +61,10 @@ func (s *scraper) Scrape(config Config) []api.Therapist { therapist.Link = e.ChildAttr("a", "href") }) + e.ForEach(".profile-features", func(i int, e *colly.HTMLElement) { + therapist.AcceptingAppointments = e.ChildText(".accepting-appointments") + }) + e.ForEach(".results-row-contact", func(i int, e *colly.HTMLElement) { therapist.Phone = e.ChildText(".results-row-mob") }) diff --git a/sqlite/therapist.go b/sqlite/therapist.go index d364c05..df82928 100644 --- a/sqlite/therapist.go +++ b/sqlite/therapist.go @@ -29,19 +29,19 @@ func (r *repository) therapistFilterQuery(query *bun.SelectQuery, params *api.Ge } if params.Verified != nil { - query.Where("? LIKE ?", bun.Ident("verified"), *params.Verified+"%") + query.Where("? LIKE ?", bun.Ident("verified"), "%"+*params.Verified+"%") } if params.Statement != nil { - query.Where("? LIKE ?", bun.Ident("statement"), *params.Statement+"%") + query.Where("? LIKE ?", bun.Ident("statement"), "%"+*params.Statement+"%") } if params.Phone != nil { - query.Where("? LIKE ?", bun.Ident("phone"), *params.Phone+"%") + query.Where("? LIKE ?", bun.Ident("phone"), "%"+*params.Phone+"%") } if params.Location != nil { - query.Where("? LIKE ?", bun.Ident("location"), *params.Location+"%") + query.Where("? LIKE ?", bun.Ident("location"), "%"+*params.Location+"%") } return query, nil