From bff2c4242d0d0895547d1b54dc0d26cc4230aaeb Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Wed, 8 Oct 2025 02:09:22 +0200 Subject: [PATCH 01/26] feat: linkedin --- .cursor/rules/tee-types_update_plan.mdc | 48 -- args/args.go | 7 +- args/linkedin.go | 97 --- args/linkedin/profile/profile.go | 132 +++ args/linkedin/profile/profile_suite_test.go | 13 + args/linkedin/profile/profile_test.go | 221 +++++ args/twitter.go | 18 +- args/unmarshaller.go | 43 +- types/jobs.go | 8 +- types/linkedin.go | 52 -- types/linkedin/experiences/experiences.go | 23 + types/linkedin/functions/functions.go | 63 ++ types/linkedin/industries/industries.go | 869 ++++++++++++++++++++ types/linkedin/profile/profile.go | 188 +++++ types/linkedin/seniorities/seniorities.go | 33 + 15 files changed, 1584 insertions(+), 231 deletions(-) delete mode 100644 .cursor/rules/tee-types_update_plan.mdc delete mode 100644 args/linkedin.go create mode 100644 args/linkedin/profile/profile.go create mode 100644 args/linkedin/profile/profile_suite_test.go create mode 100644 args/linkedin/profile/profile_test.go delete mode 100644 types/linkedin.go create mode 100644 types/linkedin/experiences/experiences.go create mode 100644 types/linkedin/functions/functions.go create mode 100644 types/linkedin/industries/industries.go create mode 100644 types/linkedin/profile/profile.go create mode 100644 types/linkedin/seniorities/seniorities.go diff --git a/.cursor/rules/tee-types_update_plan.mdc b/.cursor/rules/tee-types_update_plan.mdc deleted file mode 100644 index 741eea6..0000000 --- a/.cursor/rules/tee-types_update_plan.mdc +++ /dev/null @@ -1,48 +0,0 @@ ---- -description: -globs: -alwaysApply: false ---- -# tee-types: LinkedIn Data Structures Extension - -## Overview -This plan details the required changes for the `github.com/masa-finance/tee-types` repository. These changes are a prerequisite for integrating the new LinkedIn profile fetching functionality into the `tee-worker`. The goal is to extend the existing data structures to support both profile search and full profile fetching jobs. - -## ⚠️ CRITICAL REQUIREMENTS -- **BACKWARD COMPATIBILITY**: The changes must not break existing `tee-worker` functionality that relies on `searchbyquery`. -- **CONSISTENCY**: The new data structures should align with the output of the `linkedin-scraper` SDK (`v1.0.0`). -- **CLARITY**: Use clear and descriptive naming for new structs and fields. - -## Implementation Steps - -### Phase 1: Argument Structure Update - -#### Step 1.1: Extend and Rename Job Arguments -**Objective**: Create a unified argument struct that supports both search and profile fetching. -**Files**: `args/linkedin.go` -**Action**: -- Rename the existing `LinkedInSearchArguments` struct to `LinkedInArguments`. This provides a more generic name for future extensions. -- Add a new field `PublicIdentifier string `json:"public_identifier,omitempty"` to the renamed `LinkedInArguments` struct. This will be used to specify the target profile for fetching. -**Verification**: The new `LinkedInArguments` struct contains fields for both search (`Query`, `MaxResults`, etc.) and profile fetching (`PublicIdentifier`). -**Commit**: `feat(args): extend and rename linkedin arguments for profile fetching` - -### Phase 2: Result Structure Extension - -#### Step 2.1: Define Comprehensive Profile Result -**Objective**: Create a new struct to hold the rich data from a full profile fetch. -**Files**: `types/linkedin.go` -**Action**: -- Create a new struct `LinkedInFullProfileResult`. -- This struct should include fields for all the data provided by the scraper's `GetProfile` method, such as: - - `PublicIdentifier`, `URN`, `FullName`, `Headline`, `Location`, `Summary` - - Slices for `[]Experience`, `[]Education`, `[]Skill` - - `ProfilePictureURL` -- Define helper structs for `Experience`, `Education`, and `Skill` with relevant fields (e.g., `Title`, `CompanyName` for experience; `SchoolName`, `DegreeName` for education). -**Verification**: The `LinkedInFullProfileResult` and its nested structs are defined and compile correctly. The structure matches the expected output from the `linkedin-scraper`. -**Commit**: `feat(types): add LinkedInFullProfileResult for detailed profiles` - -## Success Criteria -- ✅ `args/linkedin.go` contains the updated `LinkedInArguments` struct. -- ✅ `types/linkedin.go` contains the new `LinkedInFullProfileResult` and its associated substructures. -- ✅ The changes are non-breaking for code that uses the old `LinkedInSearchArguments` (after a name update). -- ✅ The new structures are ready to be consumed by the `tee-worker`. diff --git a/args/args.go b/args/args.go index ab7abe4..5504844 100644 --- a/args/args.go +++ b/args/args.go @@ -3,13 +3,14 @@ package args import ( "encoding/json" "fmt" - "strings" + + teetypes "github.com/masa-finance/tee-types/types" ) // QueryTypeArgument provides a minimal structure to extract the QueryType (json "type") // This is used across different job types to determine the specific capability being requested type QueryTypeArgument struct { - QueryType string `json:"type"` + QueryType teetypes.Capability `json:"type"` } // UnmarshalJSON implements custom JSON unmarshaling with normalization @@ -20,6 +21,6 @@ func (q *QueryTypeArgument) UnmarshalJSON(data []byte) error { if err := json.Unmarshal(data, aux); err != nil { return fmt.Errorf("failed to unmarshal QueryType arguments: %w", err) } - q.QueryType = strings.ToLower(aux.QueryType) + q.QueryType = aux.QueryType return nil } diff --git a/args/linkedin.go b/args/linkedin.go deleted file mode 100644 index dc3ba93..0000000 --- a/args/linkedin.go +++ /dev/null @@ -1,97 +0,0 @@ -package args - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/masa-finance/tee-types/pkg/util" - teetypes "github.com/masa-finance/tee-types/types" -) - -// LinkedInArguments defines args for LinkedIn operations -type LinkedInArguments struct { - QueryType string `json:"type"` // "searchbyquery", "getprofile" - Query string `json:"query"` // Keywords for search or username for profile - PublicIdentifier string `json:"public_identifier,omitempty"` - NetworkFilters []string `json:"network_filters,omitempty"` // ["F", "S", "O"] - First, Second, Other (default: all) - MaxResults int `json:"max_results"` // Maximum number of results to return - Start int `json:"start"` // Pagination start offset -} - -// UnmarshalJSON implements custom JSON unmarshaling with validation -func (l *LinkedInArguments) UnmarshalJSON(data []byte) error { - // Prevent infinite recursion (you call json.Unmarshal which then calls `UnmarshalJSON`, which then calls `json.Unmarshal`...) - type Alias LinkedInArguments - aux := &struct { - *Alias - }{ - Alias: (*Alias)(l), - } - - if err := json.Unmarshal(data, aux); err != nil { - return fmt.Errorf("failed to unmarshal LinkedIn arguments: %w", err) - } - - // Normalize QueryType to lowercase - l.QueryType = strings.ToLower(l.QueryType) - - return l.Validate() -} - -// Validate validates the LinkedIn arguments (general validation) -func (l *LinkedInArguments) Validate() error { - // Note: QueryType is not required for all capabilities, similar to Twitter pattern - // Query is also not required for all capabilities - - if l.MaxResults < 0 { - return fmt.Errorf("max_results must be non-negative, got: %d", l.MaxResults) - } - - if l.Start < 0 { - return fmt.Errorf("start must be non-negative, got: %d", l.Start) - } - - return nil -} - -// ValidateForJobType validates LinkedIn arguments for a specific job type -func (l *LinkedInArguments) ValidateForJobType(jobType teetypes.JobType) error { - if err := l.Validate(); err != nil { - return err - } - - // Validate QueryType against job-specific capabilities - return jobType.ValidateCapability(teetypes.Capability(l.QueryType)) -} - -// GetCapability returns the QueryType as a typed Capability -func (l *LinkedInArguments) GetCapability() teetypes.Capability { - return teetypes.Capability(l.QueryType) -} - -// IsSearchOperation returns true if this is a search operation -func (l *LinkedInArguments) IsSearchOperation() bool { - capability := l.GetCapability() - return capability == teetypes.CapSearchByQuery -} - -// IsProfileOperation returns true if this is a profile operation -func (l *LinkedInArguments) IsProfileOperation() bool { - capability := l.GetCapability() - return capability == teetypes.CapGetProfile -} - -// HasNetworkFilters returns true if network filters are specified -func (l *LinkedInArguments) HasNetworkFilters() bool { - return len(l.NetworkFilters) > 0 -} - -// GetEffectiveMaxResults returns the effective maximum results, defaulting to a reasonable limit -func (l *LinkedInArguments) GetEffectiveMaxResults() int { - return util.Max(l.MaxResults, 10) -} - -// LinkedInSearchArguments is an alias for LinkedInArguments for backward compatibility. -// Deprecated: use LinkedInArguments instead. -type LinkedInSearchArguments = LinkedInArguments diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go new file mode 100644 index 0000000..67443ad --- /dev/null +++ b/args/linkedin/profile/profile.go @@ -0,0 +1,132 @@ +package profile + +import ( + "encoding/json" + "errors" + "fmt" + + teetypes "github.com/masa-finance/tee-types/types" + "github.com/masa-finance/tee-types/types/linkedin/experiences" + "github.com/masa-finance/tee-types/types/linkedin/functions" + "github.com/masa-finance/tee-types/types/linkedin/industries" + "github.com/masa-finance/tee-types/types/linkedin/profile" + "github.com/masa-finance/tee-types/types/linkedin/seniorities" +) + +var ( + ErrScraperModeNotSupported = errors.New("scraper mode not supported") + ErrMaxItemsTooLarge = errors.New("max items must be less than or equal to 100") + ErrYearsOfExperienceNotSupported = errors.New("years of experience not supported") + ErrSeniorityLevelNotSupported = errors.New("seniority level not supported") + ErrFunctionNotSupported = errors.New("function not supported") + ErrIndustryNotSupported = errors.New("industry not supported") +) + +const ( + DefaultMaxItems = 10 + DefaultScraperMode = profile.ScraperModeShort + MaxItems = 100 +) + +// Arguments defines args for LinkedIn profile operations +type Arguments struct { + QueryType teetypes.Capability `json:"type"` + ScraperMode profile.ScraperMode `json:"scraperMode"` + Query string `json:"searchQuery"` + MaxItems uint `json:"maxItems"` + Locations []string `json:"locations"` + CurrentComanies []string `json:"currentCompanies"` + PastCompanies []string `json:"pastCompanies"` + CurrentJobTitles []string `json:"currentJobTitles"` + PastJobTitles []string `json:"pastJobTitles"` + Schools []string `json:"schools"` + YearsOfExperience []experiences.Id `json:"yearsOfExperienceIds"` + YearsAtCurrentCompany []experiences.Id `json:"yearsAtCurrentCompanyIds"` + SeniorityLevels []seniorities.Id `json:"seniorityLevelIds"` + Functions []functions.Id `json:"functionIds"` + Industries []industries.Id `json:"industryIds"` + FirstNames []string `json:"firstNames"` + LastNames []string `json:"lastNames"` + RecentlyChangedJobs bool `json:"recentlyChangedJobs"` + StartPage uint `json:"startPage"` +} + +func (a *Arguments) UnmarshalJSON(data []byte) error { + type Alias Arguments + aux := &struct { + *Alias + }{ + Alias: (*Alias)(a), + } + + if err := json.Unmarshal(data, aux); err != nil { + return fmt.Errorf("failed to unmarshal LinkedIn profile arguments: %w", err) + } + + a.setDefaultValues() + + return a.Validate() +} + +func (a *Arguments) setDefaultValues() { + if a.MaxItems == 0 { + a.MaxItems = DefaultMaxItems + } + if a.ScraperMode == "" { + a.ScraperMode = DefaultScraperMode + } +} + +func (a *Arguments) Validate() error { + var errs []error + + if a.MaxItems > MaxItems { + errs = append(errs, ErrMaxItemsTooLarge) + } + if !profile.AllScraperModes.Contains(a.ScraperMode) { + errs = append(errs, ErrScraperModeNotSupported) + } + for _, yoe := range a.YearsOfExperience { + if !experiences.All.Contains(yoe) { + errs = append(errs, fmt.Errorf("%w: %v", ErrYearsOfExperienceNotSupported, yoe)) + } + } + for _, yac := range a.YearsAtCurrentCompany { + if !experiences.All.Contains(yac) { + errs = append(errs, fmt.Errorf("%w: %v", ErrYearsOfExperienceNotSupported, yac)) + } + } + for _, sl := range a.SeniorityLevels { + if !seniorities.All.Contains(sl) { + errs = append(errs, fmt.Errorf("%w: %v", ErrSeniorityLevelNotSupported, sl)) + } + } + for _, f := range a.Functions { + if !functions.All.Contains(f) { + errs = append(errs, fmt.Errorf("%w: %v", ErrFunctionNotSupported, f)) + } + } + for _, i := range a.Industries { + if !industries.All.Contains(i) { + errs = append(errs, fmt.Errorf("%w: %v", ErrIndustryNotSupported, i)) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + + return nil +} + +func (a *Arguments) GetCapability() teetypes.Capability { + return a.QueryType +} + +func (a *Arguments) ValidateForJobType(jobType teetypes.JobType) error { + if err := a.Validate(); err != nil { + return err + } + + return jobType.ValidateCapability(a.QueryType) +} diff --git a/args/linkedin/profile/profile_suite_test.go b/args/linkedin/profile/profile_suite_test.go new file mode 100644 index 0000000..713e96d --- /dev/null +++ b/args/linkedin/profile/profile_suite_test.go @@ -0,0 +1,13 @@ +package profile_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestArgs(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Args Suite") +} diff --git a/args/linkedin/profile/profile_test.go b/args/linkedin/profile/profile_test.go new file mode 100644 index 0000000..d11a78f --- /dev/null +++ b/args/linkedin/profile/profile_test.go @@ -0,0 +1,221 @@ +package profile_test + +import ( + "encoding/json" + "errors" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/masa-finance/tee-types/args/linkedin/profile" + "github.com/masa-finance/tee-types/types" + "github.com/masa-finance/tee-types/types/linkedin/experiences" + "github.com/masa-finance/tee-types/types/linkedin/functions" + "github.com/masa-finance/tee-types/types/linkedin/industries" + profiletypes "github.com/masa-finance/tee-types/types/linkedin/profile" + "github.com/masa-finance/tee-types/types/linkedin/seniorities" +) + +var _ = Describe("LinkedIn Profile Arguments", func() { + Describe("Marshalling and unmarshalling", func() { + It("should set default values", func() { + args := profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + } + jsonData, err := json.Marshal(args) + Expect(err).ToNot(HaveOccurred()) + err = json.Unmarshal([]byte(jsonData), &args) + Expect(err).ToNot(HaveOccurred()) + Expect(args.MaxItems).To(Equal(uint(10))) + Expect(args.ScraperMode).To(Equal(profiletypes.ScraperModeShort)) + }) + + It("should override default values", func() { + args := profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + MaxItems: 50, + ScraperMode: profiletypes.ScraperModeFull, + } + jsonData, err := json.Marshal(args) + Expect(err).ToNot(HaveOccurred()) + err = json.Unmarshal([]byte(jsonData), &args) + Expect(err).ToNot(HaveOccurred()) + Expect(args.MaxItems).To(Equal(uint(50))) + Expect(args.ScraperMode).To(Equal(profiletypes.ScraperModeFull)) + }) + }) + + Describe("Validation", func() { + It("should succeed with valid arguments", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + YearsOfExperience: []experiences.Id{experiences.ThreeToFiveYears}, + SeniorityLevels: []seniorities.Id{seniorities.Senior}, + Functions: []functions.Id{functions.Engineering}, + Industries: []industries.Id{industries.AccommodationServices}, + } + err := args.Validate() + Expect(err).ToNot(HaveOccurred()) + }) + + It("should fail with max items too large", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 150, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + Expect(errors.Is(err, profile.ErrMaxItemsTooLarge)).To(BeTrue()) + }) + + It("should fail with invalid scraper mode", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: "InvalidMode", + MaxItems: 10, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + Expect(errors.Is(err, profile.ErrScraperModeNotSupported)).To(BeTrue()) + }) + + It("should fail with invalid years of experience", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + YearsOfExperience: []experiences.Id{"invalid"}, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + Expect(errors.Is(err, profile.ErrYearsOfExperienceNotSupported)).To(BeTrue()) + + }) + + It("should fail with invalid years at current company", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + YearsAtCurrentCompany: []experiences.Id{"invalid"}, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + Expect(errors.Is(err, profile.ErrYearsOfExperienceNotSupported)).To(BeTrue()) + + }) + + It("should fail with invalid seniority level", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + SeniorityLevels: []seniorities.Id{"invalid"}, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + Expect(errors.Is(err, profile.ErrSeniorityLevelNotSupported)).To(BeTrue()) + }) + + It("should fail with invalid function", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + Functions: []functions.Id{"invalid"}, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + Expect(errors.Is(err, profile.ErrFunctionNotSupported)).To(BeTrue()) + + }) + + It("should fail with invalid industry", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + Industries: []industries.Id{"invalid"}, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + Expect(errors.Is(err, profile.ErrIndustryNotSupported)).To(BeTrue()) + + }) + + It("should handle multiple validation errors", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: "InvalidMode", + MaxItems: 150, + YearsOfExperience: []experiences.Id{"invalid"}, + SeniorityLevels: []seniorities.Id{"invalid"}, + } + err := args.Validate() + Expect(err).To(HaveOccurred()) + // Should contain multiple error messages + Expect(err.Error()).To(ContainSubstring("max items must be less than or equal to 100")) + Expect(err.Error()).To(ContainSubstring("scraper mode not supported")) + Expect(err.Error()).To(ContainSubstring("years of experience not supported")) + Expect(err.Error()).To(ContainSubstring("seniority level not supported")) + }) + }) + + Describe("GetCapability", func() { + It("should return the query type", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + } + Expect(args.GetCapability()).To(Equal(types.CapSearchByProfile)) + }) + }) + + Describe("ValidateForJobType", func() { + It("should succeed with valid job type and capability", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + } + err := args.ValidateForJobType(types.LinkedInJob) + Expect(err).ToNot(HaveOccurred()) + }) + + It("should fail with invalid job type", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: profiletypes.ScraperModeShort, + MaxItems: 10, + } + err := args.ValidateForJobType(types.TwitterJob) + Expect(err).To(HaveOccurred()) + }) + + It("should fail if base validation fails", func() { + args := &profile.Arguments{ + QueryType: types.CapSearchByProfile, + Query: "software engineer", + ScraperMode: "InvalidMode", + MaxItems: 10, + } + err := args.ValidateForJobType(types.LinkedInJob) + Expect(err).To(HaveOccurred()) + }) + }) +}) diff --git a/args/twitter.go b/args/twitter.go index abee6d4..6c08f65 100644 --- a/args/twitter.go +++ b/args/twitter.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "strings" teetypes "github.com/masa-finance/tee-types/types" ) @@ -22,13 +21,13 @@ const ( // TwitterSearchArguments defines args for Twitter searches type TwitterSearchArguments struct { - QueryType string `json:"type"` // Optional, type of search - Query string `json:"query"` // Username or search query - Count int `json:"count"` - StartTime string `json:"start_time"` // Optional ISO timestamp - EndTime string `json:"end_time"` // Optional ISO timestamp - MaxResults int `json:"max_results"` // Optional, max number of results - NextCursor string `json:"next_cursor"` + QueryType teetypes.Capability `json:"type"` // Optional, type of search + Query string `json:"query"` // Username or search query + Count int `json:"count"` + StartTime string `json:"start_time"` // Optional ISO timestamp + EndTime string `json:"end_time"` // Optional ISO timestamp + MaxResults int `json:"max_results"` // Optional, max number of results + NextCursor string `json:"next_cursor"` } // UnmarshalJSON implements custom JSON unmarshaling with validation @@ -45,9 +44,6 @@ func (t *TwitterSearchArguments) UnmarshalJSON(data []byte) error { return fmt.Errorf("failed to unmarshal Twitter arguments: %w", err) } - // Normalize QueryType to lowercase - t.QueryType = strings.ToLower(t.QueryType) - return t.Validate() } diff --git a/args/unmarshaller.go b/args/unmarshaller.go index 1d3c26d..3a68a11 100644 --- a/args/unmarshaller.go +++ b/args/unmarshaller.go @@ -3,8 +3,8 @@ package args import ( "encoding/json" "fmt" - "strings" + linkedinProfile "github.com/masa-finance/tee-types/args/linkedin/profile" "github.com/masa-finance/tee-types/types" ) @@ -55,16 +55,15 @@ func unmarshalTikTokArguments(args map[string]any) (JobArguments, error) { if err := unmarshalToStruct(args, minimal); err != nil { return nil, fmt.Errorf("failed to unmarshal TikTok arguments: %w", err) } - capability := types.Capability(strings.ToLower(minimal.QueryType)) - if capability == types.CapEmpty { + if minimal.QueryType == types.CapEmpty { defaultCap, exists := types.JobDefaultCapabilityMap[types.TiktokJob] if !exists { return nil, fmt.Errorf("no default capability configured for job type: %s", types.TiktokJob) } - capability = defaultCap + minimal.QueryType = defaultCap } - switch capability { + switch minimal.QueryType { case types.CapSearchByQuery: searchArgs := &TikTokSearchByQueryArguments{} if err := unmarshalToStruct(args, searchArgs); err != nil { @@ -93,7 +92,7 @@ func unmarshalTikTokArguments(args map[string]any) (JobArguments, error) { } return transcriptionArgs, nil default: - return nil, fmt.Errorf("unknown tiktok type: %s", capability) + return nil, fmt.Errorf("unknown tiktok type: %s", minimal.QueryType) } } @@ -106,7 +105,7 @@ func unmarshalTwitterArguments(jobType types.JobType, args map[string]any) (*Twi // If no QueryType is specified, use the default capability for this job type if twitterArgs.QueryType == "" { if defaultCap, exists := types.JobDefaultCapabilityMap[jobType]; exists { - twitterArgs.QueryType = string(defaultCap) + twitterArgs.QueryType = defaultCap } } @@ -118,25 +117,31 @@ func unmarshalTwitterArguments(jobType types.JobType, args map[string]any) (*Twi return twitterArgs, nil } -func unmarshalLinkedInArguments(jobType types.JobType, args map[string]any) (*LinkedInArguments, error) { - linkedInArgs := &LinkedInArguments{} - if err := unmarshalToStruct(args, linkedInArgs); err != nil { - return nil, fmt.Errorf("failed to unmarshal LinkedIn job arguments: %w", err) +func unmarshalLinkedInArguments(jobType types.JobType, args map[string]any) (JobArguments, error) { + minimal := &QueryTypeArgument{} + if err := unmarshalToStruct(args, minimal); err != nil { + return nil, fmt.Errorf("failed to unmarshal LinkedIn arguments: %w", err) } - // If no QueryType is specified, use the default capability for this job type - if linkedInArgs.QueryType == "" { + if minimal.QueryType == types.CapEmpty { if defaultCap, exists := types.JobDefaultCapabilityMap[jobType]; exists { - linkedInArgs.QueryType = string(defaultCap) + minimal.QueryType = defaultCap } } - // Perform job-type-specific validation for LinkedIn - if err := linkedInArgs.ValidateForJobType(jobType); err != nil { - return nil, fmt.Errorf("linkedin job validation failed: %w", err) + switch minimal.QueryType { + case types.CapSearchByProfile: + linkedInArgs := &linkedinProfile.Arguments{} + if err := unmarshalToStruct(args, linkedInArgs); err != nil { + return nil, fmt.Errorf("failed to unmarshal LinkedIn job arguments: %w", err) + } + if err := linkedInArgs.ValidateForJobType(jobType); err != nil { + return nil, fmt.Errorf("linkedin job validation failed: %w", err) + } + return linkedInArgs, nil + default: + return nil, fmt.Errorf("unknown linkedin type: %s", minimal.QueryType) } - - return linkedInArgs, nil } func unmarshalRedditArguments(jobType types.JobType, args map[string]any) (*RedditArguments, error) { diff --git a/types/jobs.go b/types/jobs.go index 753a970..628cb46 100644 --- a/types/jobs.go +++ b/types/jobs.go @@ -111,7 +111,6 @@ const ( var ( AlwaysAvailableTelemetryCaps = []Capability{CapTelemetry, CapEmpty} AlwaysAvailableTiktokCaps = []Capability{CapTranscription, CapEmpty} - AlwaysAvailableLinkedInCaps = []Capability{CapSearchByQuery, CapGetProfile, CapEmpty} // AlwaysAvailableCapabilities defines the job capabilities that are always available regardless of configuration AlwaysAvailableCapabilities = WorkerCapabilities{ @@ -142,6 +141,9 @@ var ( // WebCaps are all the Web capabilities (only available with Apify) WebCaps = []Capability{CapScraper, CapEmpty} + + // LinkedInCaps are all the LinkedIn capabilities (only available with Apify) + LinkedInCaps = []Capability{CapSearchByProfile} ) // JobCapabilityMap defines which capabilities are valid for each job type @@ -163,6 +165,9 @@ var JobCapabilityMap = map[JobType][]Capability{ // Web job capabilities WebJob: WebCaps, + // LinkedIn job capabilities + LinkedInJob: LinkedInCaps, + // TikTok job capabilities TiktokJob: combineCapabilities( AlwaysAvailableTiktokCaps, @@ -186,4 +191,5 @@ var JobDefaultCapabilityMap = map[JobType]Capability{ TiktokJob: CapTranscription, RedditJob: CapScrapeUrls, TelemetryJob: CapTelemetry, + LinkedInJob: CapSearchByProfile, } diff --git a/types/linkedin.go b/types/linkedin.go deleted file mode 100644 index b5c050a..0000000 --- a/types/linkedin.go +++ /dev/null @@ -1,52 +0,0 @@ -// Package types provides shared types between tee-worker and tee-indexer -package types - -// LinkedInProfileResult defines the structure of a LinkedIn profile search result -type LinkedInProfileResult struct { - PublicIdentifier string `json:"public_identifier"` // Username/slug in profile URL - URN string `json:"urn"` // LinkedIn's unique resource name - FullName string `json:"full_name"` // Person's full name - Headline string `json:"headline"` // Professional headline/title - Location string `json:"location"` // Geographic location - ProfileURL string `json:"profile_url"` // Full LinkedIn profile URL - Degree string `json:"degree,omitempty"` // Connection degree (1st, 2nd, etc.) -} - -// Experience defines the structure for a single entry in a user's work experience -type Experience struct { - Title string `json:"title"` - CompanyName string `json:"company_name"` - Location string `json:"location,omitempty"` - StartDate string `json:"start_date,omitempty"` - EndDate string `json:"end_date,omitempty"` - Description string `json:"description,omitempty"` -} - -// Education defines the structure for a single entry in a user's education history -type Education struct { - SchoolName string `json:"school_name"` - DegreeName string `json:"degree_name,omitempty"` - FieldOfStudy string `json:"field_of_study,omitempty"` - StartDate string `json:"start_date,omitempty"` - EndDate string `json:"end_date,omitempty"` - Description string `json:"description,omitempty"` -} - -// Skill defines the structure for a single skill entry -type Skill struct { - Name string `json:"name"` -} - -// LinkedInFullProfileResult defines the structure for a detailed LinkedIn profile -type LinkedInFullProfileResult struct { - PublicIdentifier string `json:"public_identifier"` - URN string `json:"urn"` - FullName string `json:"full_name"` - Headline string `json:"headline"` - Location string `json:"location"` - Summary string `json:"summary,omitempty"` - ProfilePictureURL string `json:"profile_picture_url,omitempty"` - Experiences []Experience `json:"experiences,omitempty"` - Education []Education `json:"education,omitempty"` - Skills []Skill `json:"skills,omitempty"` -} diff --git a/types/linkedin/experiences/experiences.go b/types/linkedin/experiences/experiences.go new file mode 100644 index 0000000..bd844f7 --- /dev/null +++ b/types/linkedin/experiences/experiences.go @@ -0,0 +1,23 @@ +package experiences + +import "github.com/masa-finance/tee-types/pkg/util" + +// id represents a LinkedIn experience level identifier +type Id string + +// Experience level constants +const ( + LessThanAYear Id = "1" + OneToTwoYears Id = "2" + ThreeToFiveYears Id = "3" + SixToTenYears Id = "4" + MoreThanTenYears Id = "5" +) + +var All = util.NewSet( + LessThanAYear, + OneToTwoYears, + ThreeToFiveYears, + SixToTenYears, + MoreThanTenYears, +) diff --git a/types/linkedin/functions/functions.go b/types/linkedin/functions/functions.go new file mode 100644 index 0000000..19af25c --- /dev/null +++ b/types/linkedin/functions/functions.go @@ -0,0 +1,63 @@ +package functions + +import "github.com/masa-finance/tee-types/pkg/util" + +// id represents a LinkedIn function identifier +type Id string + +// Function constants +const ( + Accounting Id = "1" + Administrative Id = "2" + ArtsAndDesign Id = "3" + BusinessDevelopment Id = "4" + CommunityAndSocialServices Id = "5" + Consulting Id = "6" + Education Id = "7" + Engineering Id = "8" + Entrepreneurship Id = "9" + Finance Id = "10" + HealthcareServices Id = "11" + HumanResources Id = "12" + InformationTechnology Id = "13" + Legal Id = "14" + Marketing Id = "15" + MediaAndCommunication Id = "16" + MilitaryAndProtectiveServices Id = "17" + Operations Id = "18" + ProductManagement Id = "19" + ProgramAndProjectManagement Id = "20" + Purchasing Id = "21" + QualityAssurance Id = "22" + RealEstate Id = "23" + Research Id = "24" + Sales Id = "25" +) + +var All = util.NewSet( + Accounting, + Administrative, + ArtsAndDesign, + BusinessDevelopment, + CommunityAndSocialServices, + Consulting, + Education, + Engineering, + Entrepreneurship, + Finance, + HealthcareServices, + HumanResources, + InformationTechnology, + Legal, + Marketing, + MediaAndCommunication, + MilitaryAndProtectiveServices, + Operations, + ProductManagement, + ProgramAndProjectManagement, + Purchasing, + QualityAssurance, + RealEstate, + Research, + Sales, +) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go new file mode 100644 index 0000000..fa53dbc --- /dev/null +++ b/types/linkedin/industries/industries.go @@ -0,0 +1,869 @@ +package industries + +import "github.com/masa-finance/tee-types/pkg/util" + +// IndustryId represents a LinkedIn industry identifier +type Id string + +// Industry constants +const ( + AccommodationServices Id = "2190" + FoodAndBeverageServices Id = "34" + BarsTavernsAndNightclubs Id = "2217" + Caterers Id = "2212" + MobileFoodServices Id = "2214" + Restaurants Id = "32" + Hospitality Id = "31" + BedAndBreakfastsHostelsHomestays Id = "2197" + HotelsAndMotels Id = "2194" + AdministrativeAndSupportServices Id = "1912" + CollectionAgencies Id = "1938" + EventsServices Id = "110" + FacilitiesServices Id = "122" + JanitorialServices Id = "1965" + LandscapingServices Id = "2934" + Fundraising Id = "101" + OfficeAdministration Id = "1916" + SecurityAndInvestigations Id = "121" + SecurityGuardsAndPatrolServices Id = "1956" + SecuritySystemsServices Id = "1958" + StaffingAndRecruiting Id = "104" + ExecutiveSearchServices Id = "1923" + TemporaryHelpServices Id = "1925" + TelephoneCallCenters Id = "1931" + TranslationAndLocalization Id = "108" + TravelArrangements Id = "30" + WritingAndEditing Id = "103" + Construction Id = "48" + BuildingConstruction Id = "406" + NonresIdentialBuildingConstruction Id = "413" + ResIdentialBuildingConstruction Id = "408" + CivilEngineering Id = "51" + HighwayStreetAndBrIdgeConstruction Id = "431" + SubdivisionOfLand Id = "428" + UtilitySystemConstruction Id = "419" + SpecialtyTradeContractors Id = "435" + BuildingEquipmentContractors Id = "453" + BuildingFinishingContractors Id = "460" + BuildingStructureAndExteriorContractors Id = "436" + ConsumerServices Id = "91" + CivicAndSocialOrganizations Id = "90" + Associations Id = "1909" + PoliticalOrganizations Id = "107" + ProfessionalOrganizations Id = "1911" + HouseholdServices Id = "2318" + NonProfitOrganizations Id = "100" + PersonalAndLaundryServices Id = "2258" + LaundryAndDrycleaningServices Id = "2272" + PersonalCareServices Id = "2259" + PetServices Id = "2282" + PhilanthropicFundraisingServices Id = "131" + ReligiousInstitutions Id = "89" + RepairAndMaintenance Id = "2225" + CommercialAndIndustrialMachineryMaintenance Id = "2247" + ElectronicAndPrecisionEquipmentMaintenance Id = "2240" + FootwearAndLeatherGoodsRepair Id = "2255" + ReupholsteryAndFurnitureRepair Id = "2253" + VehicleRepairAndMaintenance Id = "2226" + Education Id = "1999" + ELearningProvIders Id = "132" + HigherEducation Id = "68" + PrimaryAndSecondaryEducation Id = "67" + ProfessionalTrainingAndCoaching Id = "105" + TechnicalAndVocationalTraining Id = "2018" + CosmetologyAndBarberSchools Id = "2019" + FineArtsSchools Id = "2025" + FlightTraining Id = "2020" + LanguageSchools Id = "2029" + SecretarialSchools Id = "2012" + SportsAndRecreationInstruction Id = "2027" + EntertainmentProvIders Id = "28" + ArtistsAndWriters Id = "38" + MuseumsHistoricalSitesAndZoos Id = "37" + HistoricalSites Id = "2161" + Museums Id = "2159" + ZoosAndBotanicalGardens Id = "2163" + Musicians Id = "115" + PerformingArtsAndSpectatorSports Id = "2130" + CircusesAndMagicShows Id = "2139" + DanceCompanies Id = "2135" + PerformingArts Id = "39" + SpectatorSports Id = "33" + Racetracks Id = "2143" + SportsTeamsAndClubs Id = "2142" + TheaterCompanies Id = "2133" + RecreationalFacilities Id = "40" + AmusementParksAndArcades Id = "2167" + GamblingFacilitiesAndCasinos Id = "29" + GolfCoursesAndCountryClubs Id = "2179" + SkiingFacilities Id = "2181" + WellnessAndFitnessServices Id = "124" + FarmingRanchingForestry Id = "201" + Farming Id = "63" + Horticulture Id = "150" + ForestryAndLogging Id = "298" + RanchingAndFisheries Id = "256" + Fisheries Id = "66" + Ranching Id = "64" + FinancialServices Id = "43" + CapitalMarkets Id = "129" + InvestmentAdvice Id = "1720" + InvestmentBanking Id = "45" + InvestmentManagement Id = "46" + SecuritiesAndCommodityExchanges Id = "1713" + VentureCapitalAndPrivateEquityPrincipals Id = "106" + CreditIntermediation Id = "1673" + Banking Id = "41" + InternationalTradeAndDevelopment Id = "141" + LoanBrokers Id = "1696" + SavingsInstitutions Id = "1678" + FundsAndTrusts Id = "1742" + InsuranceAndEmployeeBenefitFunds Id = "1743" + PensionFunds Id = "1745" + TrustsAndEstates Id = "1750" + Insurance Id = "42" + ClaimsAdjustingActuarialServices Id = "1738" + InsuranceAgenciesAndBrokerages Id = "1737" + InsuranceCarriers Id = "1725" + GovernmentAdministration Id = "75" + AdministrationOfJustice Id = "73" + CorrectionalInstitutions Id = "3068" + CourtsOfLaw Id = "3065" + FireProtection Id = "3070" + LawEnforcement Id = "77" + PublicSafety Id = "78" + EconomicPrograms Id = "2375" + TransportationPrograms Id = "3085" + UtilitiesAdministration Id = "3086" + EnvironmentalQualityPrograms Id = "388" + AirWaterAndWasteProgramManagement Id = "2366" + ConservationPrograms Id = "2368" + HealthAndHumanServices Id = "2353" + EducationAdministrationPrograms Id = "69" + PublicAssistancePrograms Id = "2360" + PublicHealth Id = "2358" + HousingAndCommunityDevelopment Id = "2369" + CommunityDevelopmentAndUrbanPlanning Id = "2374" + HousingPrograms Id = "3081" + MilitaryAndInternationalAffairs Id = "2391" + ArmedForces Id = "71" + InternationalAffairs Id = "74" + PublicPolicyOffices Id = "79" + ExecutiveOffices Id = "76" + LegislativeOffices Id = "72" + SpaceResearchAndTechnology Id = "3089" + HoldingCompanies Id = "1905" + HospitalsAndHealthCare Id = "14" + CommunityServices Id = "2115" + ServicesForTheElderlyAndDisabled Id = "2112" + Hospitals Id = "2081" + IndivIdualAndFamilyServices Id = "88" + ChildDayCareServices Id = "2128" + EmergencyAndReliefServices Id = "2122" + VocationalRehabilitationServices Id = "2125" + MedicalPractices Id = "13" + AlternativeMedicine Id = "125" + AmbulanceServices Id = "2077" + Chiropractors Id = "2048" + Dentists Id = "2045" + FamilyPlanningCenters Id = "2060" + HomeHealthCareServices Id = "2074" + MedicalAndDiagnosticLaboratories Id = "2069" + MentalHealthCare Id = "139" + Optometrists Id = "2050" + OutpatientCareCenters Id = "2063" + PhysicalOccupationalAndSpeechTherapists Id = "2054" + Physicians Id = "2040" + NursingHomesAndResIdentialCareFacilities Id = "2091" + Manufacturing Id = "25" + ApparelManufacturing Id = "598" + FashionAccessoriesManufacturing Id = "615" + AppliancesElectricalAndElectronicsManufacturing Id = "112" + ElectricLightingEquipmentManufacturing Id = "998" + ElectricalEquipmentManufacturing Id = "2468" + FuelCellManufacturing Id = "3255" + HouseholdApplianceManufacturing Id = "1005" + ChemicalManufacturing Id = "54" + AgriculturalChemicalManufacturing Id = "709" + ArtificialRubberAndSyntheticFiberManufacturing Id = "703" + ChemicalRawMaterialsManufacturing Id = "690" + PaintCoatingAndAdhesiveManufacturing Id = "722" + PersonalCareProductManufacturing Id = "18" + PharmaceuticalManufacturing Id = "15" + SoapAndCleaningProductManufacturing Id = "727" + ClimateTechnologyProductManufacturing Id = "3251" + ComputersAndElectronicsManufacturing Id = "24" + AudioAndVIdeoEquipmentManufacturing Id = "973" + CommunicationsEquipmentManufacturing Id = "964" + ComputerHardwareManufacturing Id = "3" + AccessibleHardwareManufacturing Id = "3245" + MagneticAndOpticalMediaManufacturing Id = "994" + MeasuringAndControlInstrumentManufacturing Id = "983" + SmartMeterManufacturing Id = "3254" + SemiconductorManufacturing Id = "7" + RenewableEnergySemiconductorManufacturing Id = "144" + FabricatedMetalProducts Id = "840" + ArchitecturalAndStructuralMetalManufacturing Id = "852" + BoilersTanksAndShippingContainerManufacturing Id = "861" + ConstructionHardwareManufacturing Id = "871" + CutleryAndHandtoolManufacturing Id = "849" + MetalTreatments Id = "883" + MetalValveBallAndRollerManufacturing Id = "887" + SpringAndWireProductManufacturing Id = "873" + TurnedProductsAndFastenerManufacturing Id = "876" + FoodAndBeverageManufacturing Id = "23" + Breweries Id = "562" + Distilleries Id = "564" + Wineries Id = "2500" + AnimalFeedManufacturing Id = "481" + BakedGoodsManufacturing Id = "529" + BeverageManufacturing Id = "142" + DairyProductManufacturing Id = "65" + FruitAndVegetablePreservesManufacturing Id = "504" + MeatProductsManufacturing Id = "521" + SeafoodProductManufacturing Id = "528" + SugarAndConfectioneryProductManufacturing Id = "495" + FurnitureAndHomeFurnishingsManufacturing Id = "26" + HouseholdAndInstitutionalFurnitureManufacturing Id = "1080" + MattressAndBlindsManufacturing Id = "1095" + OfficeFurnitureAndFixturesManufacturing Id = "1090" + GlassCeramicsAndConcreteManufacturing Id = "145" + AbrasivesAndNonmetallicMineralsManufacturing Id = "799" + ClayAndRefractoryProductsManufacturing Id = "773" + GlassProductManufacturing Id = "779" + LimeAndGypsumProductsManufacturing Id = "794" + LeatherProductManufacturing Id = "616" + FootwearManufacturing Id = "622" + WomensHandbagManufacturing Id = "625" + MachineryManufacturing Id = "55" + AgricultureConstructionMiningMachineryManufacturing Id = "901" + AutomationMachineryManufacturing Id = "147" + RobotManufacturing Id = "3247" + CommercialAndServiceIndustryMachineryManufacturing Id = "918" + EnginesAndPowerTransmissionEquipmentManufacturing Id = "935" + RenewableEnergyEquipmentManufacturing Id = "3241" + HvacAndRefrigerationEquipmentManufacturing Id = "923" + IndustrialMachineryManufacturing Id = "135" + MetalworkingMachineryManufacturing Id = "928" + MedicalEquipmentManufacturing Id = "17" + OilAndCoalProductManufacturing Id = "679" + PaperAndForestProductManufacturing Id = "61" + PlasticsAndRubberProductManufacturing Id = "743" + PackagingAndContainersManufacturing Id = "146" + PlasticsManufacturing Id = "117" + RubberProductsManufacturing Id = "763" + PrimaryMetalManufacturing Id = "807" + PrintingServices Id = "83" + SportingGoodsManufacturing Id = "20" + TextileManufacturing Id = "60" + TobaccoManufacturing Id = "21" + TransportationEquipmentManufacturing Id = "1029" + AviationAndAerospaceComponentManufacturing Id = "52" + DefenseAndSpaceManufacturing Id = "1" + MotorVehicleManufacturing Id = "53" + AlternativeFuelVehicleManufacturing Id = "3253" + MotorVehiclePartsManufacturing Id = "1042" + RailroadEquipmentManufacturing Id = "62" + Shipbuilding Id = "58" + WoodProductManufacturing Id = "784" + OilGasAndMining Id = "332" + Mining Id = "56" + CoalMining Id = "341" + MetalOreMining Id = "345" + NonmetallicMineralMining Id = "356" + OilAndGas Id = "57" + NaturalGasExtraction Id = "3096" + OilExtraction Id = "3095" + ProfessionalServices Id = "1810" + Accounting Id = "47" + AdvertisingServices Id = "80" + GovernmentRelationsServices Id = "148" + PublicRelationsAndCommunicationsServices Id = "98" + MarketResearch Id = "97" + ArchitectureAndPlanning Id = "50" + AccessibleArchitectureAndDesign Id = "3246" + BusinessConsultingAndServices Id = "11" + EnvironmentalServices Id = "86" + HumanResourcesServices Id = "137" + MarketingServices Id = "1862" + OperationsConsulting Id = "2401" + OutsourcingAndOffshoringConsulting Id = "123" + StrategicManagementServices Id = "102" + DesignServices Id = "99" + GraphicDesign Id = "140" + RegenerativeDesign Id = "3256" + InteriorDesign Id = "3126" + EngineeringServices Id = "3242" + RoboticsEngineering Id = "3248" + SurveyingAndMappingServices Id = "3249" + ItServicesAndItConsulting Id = "96" + ComputerAndNetworkSecurity Id = "118" + DigitalAccessibilityServices Id = "3244" + ItSystemCustomSoftwareDevelopment Id = "3102" + ItSystemDataServices Id = "3106" + ItSystemDesignServices Id = "1855" + ItSystemInstallationAndDisposal Id = "3104" + ItSystemOperationsAndMaintenance Id = "3103" + ItSystemTestingAndEvaluation Id = "3107" + ItSystemTrainingAndSupport Id = "3105" + LegalServices Id = "10" + AlternativeDisputeResolution Id = "120" + LawPractice Id = "9" + Photography Id = "136" + ResearchServices Id = "70" + BiotechnologyResearch Id = "12" + NanotechnologyResearch Id = "114" + ThinkTanks Id = "130" + ServicesForRenewableEnergy Id = "3243" + VeterinaryServices Id = "16" + RealEstateAndEquipmentRentalServices Id = "1757" + EquipmentRentalServices Id = "1779" + CommercialAndIndustrialEquipmentRental Id = "1798" + ConsumerGoodsRental Id = "1786" + RealEstate Id = "44" + LeasingNonResIdentialRealEstate Id = "128" + LeasingResIdentialRealEstate Id = "1759" + RealEstateAgentsAndBrokers Id = "1770" + Retail Id = "27" + FoodAndBeverageRetail Id = "1339" + RetailGroceries Id = "22" + OnlineAndMailOrderRetail Id = "1445" + RetailApparelAndFashion Id = "19" + RetailAppliancesElectricalAndElectronicEquipment Id = "1319" + RetailArtDealers Id = "3186" + RetailArtSupplies Id = "111" + RetailBooksAndPrintedNews Id = "1409" + RetailBuildingMaterialsAndGardenEquipment Id = "1324" + RetailFlorists Id = "1423" + RetailFurnitureAndHomeFurnishings Id = "1309" + RetailGasoline Id = "1370" + RetailHealthAndPersonalCareProducts Id = "1359" + RetailPharmacies Id = "3250" + RetailLuxuryGoodsAndJewelry Id = "143" + RetailMotorVehicles Id = "1292" + RetailMusicalInstruments Id = "1407" + RetailOfficeEquipment Id = "138" + RetailOfficeSuppliesAndGifts Id = "1424" + RetailRecyclableMaterialsUsedMerchandise Id = "1431" + TechnologyInformationAndMedia Id = "1594" + MediaTelecommunications Id = "3133" + BookAndPeriodicalPublishing Id = "82" + BookPublishing Id = "1602" + NewspaperPublishing Id = "81" + PeriodicalPublishing Id = "1600" + BroadcastMediaProductionAndDistribution Id = "36" + CableAndSatelliteProgramming Id = "1641" + RadioAndTelevisionBroadcasting Id = "1633" + MoviesVIdeosAndSound Id = "35" + AnimationAndPostProduction Id = "127" + MediaProduction Id = "126" + MoviesAndSoundRecording Id = "1611" + SoundRecording Id = "1623" + SheetMusicPublishing Id = "1625" + Telecommunications Id = "8" + SatelliteTelecommunications Id = "1649" + TelecommunicationsCarriers Id = "1644" + WirelessServices Id = "119" + TechnologyInformationAndInternet Id = "6" + DataInfrastructureAndAnalytics Id = "2458" + BlockchainServices Id = "3134" + BusinessIntelligencePlatforms Id = "3128" + ClimateDataAndAnalytics Id = "3252" + InformationServices Id = "84" + InternetPublishing Id = "3132" + BusinessContent Id = "3129" + OnlineAudioAndVIdeoMedia Id = "113" + InternetNews Id = "3124" + Libraries Id = "85" + Blogs Id = "3125" + InternetMarketplacePlatforms Id = "1285" + SocialNetworkingPlatforms Id = "3127" + SoftwareDevelopment Id = "4" + ComputerGames Id = "109" + MobileGamingApps Id = "3131" + ComputerNetworkingProducts Id = "5" + DataSecuritySoftwareProducts Id = "3130" + DesktopComputingSoftwareProducts Id = "3101" + EmbeddedSoftwareProducts Id = "3099" + MobileComputingSoftwareProducts Id = "3100" + TransportationLogisticsSupplyChainAndStorage Id = "116" + AirlinesAndAviation Id = "94" + FreightAndPackageTransportation Id = "87" + GroundPassengerTransportation Id = "1495" + InterurbanAndRuralBusServices Id = "1504" + SchoolAndEmployeeBusServices Id = "1512" + ShuttlesAndSpecialNeedsTransportationServices Id = "1517" + SightseeingTransportation Id = "1532" + TaxiAndLimousineServices Id = "1505" + UrbanTransitServices Id = "1497" + MaritimeTransportation Id = "95" + PipelineTransportation Id = "1520" + PostalServices Id = "1573" + RailTransportation Id = "1481" + TruckTransportation Id = "92" + WarehousingAndStorage Id = "93" + Utilities Id = "59" + ElectricPowerGeneration Id = "383" + FossilFuelElectricPowerGeneration Id = "385" + NuclearElectricPowerGeneration Id = "386" + RenewableEnergyPowerGeneration Id = "3240" + BiomassElectricPowerGeneration Id = "390" + GeothermalElectricPowerGeneration Id = "389" + HydroelectricPowerGeneration Id = "384" + SolarElectricPowerGeneration Id = "387" + WindElectricPowerGeneration Id = "2489" + ElectricPowerTransmissionControlAndDistribution Id = "382" + NaturalGasDistribution Id = "397" + WaterWasteSteamAndAirConditioningServices Id = "398" + SteamAndAirConditioningSupply Id = "404" + WasteCollection Id = "1981" + WasteTreatmentAndDisposal Id = "1986" + WaterSupplyAndIrrigationSystems Id = "400" + Wholesale Id = "133" + WholesaleAlcoholicBeverages Id = "1267" + WholesaleApparelAndSewingSupplies Id = "1222" + WholesaleAppliancesElectricalAndElectronics Id = "1171" + WholesaleBuildingMaterials Id = "49" + WholesaleChemicalAndAlliedProducts Id = "1257" + WholesaleComputerEquipment Id = "1157" + WholesaleDrugsAndSundries Id = "1221" + WholesaleFoodAndBeverage Id = "1231" + WholesaleFootwear Id = "1230" + WholesaleFurnitureAndHomeFurnishings Id = "1137" + WholesaleHardwarePlumbingHeatingEquipment Id = "1178" + WholesaleImportAndExport Id = "134" + WholesaleLuxuryGoodsAndJewelry Id = "1208" + WholesaleMachinery Id = "1187" + WholesaleMetalsAndMinerals Id = "1166" + WholesaleMotorVehiclesAndParts Id = "1128" + WholesalePaperProducts Id = "1212" + WholesalePetroleumAndPetroleumProducts Id = "1262" + WholesalePhotographyEquipmentAndSupplies Id = "1153" + WholesaleRawFarmProducts Id = "1250" + WholesaleRecyclableMaterials Id = "1206" +) + +var All = util.NewSet( + AccommodationServices, + FoodAndBeverageServices, + BarsTavernsAndNightclubs, + Caterers, + MobileFoodServices, + Restaurants, + Hospitality, + BedAndBreakfastsHostelsHomestays, + HotelsAndMotels, + AdministrativeAndSupportServices, + CollectionAgencies, + EventsServices, + FacilitiesServices, + JanitorialServices, + LandscapingServices, + Fundraising, + OfficeAdministration, + SecurityAndInvestigations, + SecurityGuardsAndPatrolServices, + SecuritySystemsServices, + StaffingAndRecruiting, + ExecutiveSearchServices, + TemporaryHelpServices, + TelephoneCallCenters, + TranslationAndLocalization, + TravelArrangements, + WritingAndEditing, + Construction, + BuildingConstruction, + CivilEngineering, + SubdivisionOfLand, + UtilitySystemConstruction, + SpecialtyTradeContractors, + BuildingEquipmentContractors, + BuildingFinishingContractors, + BuildingStructureAndExteriorContractors, + ConsumerServices, + CivicAndSocialOrganizations, + Associations, + PoliticalOrganizations, + ProfessionalOrganizations, + HouseholdServices, + NonProfitOrganizations, + PersonalAndLaundryServices, + LaundryAndDrycleaningServices, + PersonalCareServices, + PetServices, + PhilanthropicFundraisingServices, + ReligiousInstitutions, + RepairAndMaintenance, + CommercialAndIndustrialMachineryMaintenance, + ElectronicAndPrecisionEquipmentMaintenance, + FootwearAndLeatherGoodsRepair, + ReupholsteryAndFurnitureRepair, + VehicleRepairAndMaintenance, + Education, + HigherEducation, + PrimaryAndSecondaryEducation, + ProfessionalTrainingAndCoaching, + TechnicalAndVocationalTraining, + CosmetologyAndBarberSchools, + FineArtsSchools, + FlightTraining, + LanguageSchools, + SecretarialSchools, + SportsAndRecreationInstruction, + ArtistsAndWriters, + MuseumsHistoricalSitesAndZoos, + HistoricalSites, + Museums, + ZoosAndBotanicalGardens, + Musicians, + PerformingArtsAndSpectatorSports, + CircusesAndMagicShows, + DanceCompanies, + PerformingArts, + SpectatorSports, + Racetracks, + SportsTeamsAndClubs, + TheaterCompanies, + RecreationalFacilities, + AmusementParksAndArcades, + GamblingFacilitiesAndCasinos, + GolfCoursesAndCountryClubs, + SkiingFacilities, + WellnessAndFitnessServices, + FarmingRanchingForestry, + Farming, + Horticulture, + ForestryAndLogging, + RanchingAndFisheries, + Fisheries, + Ranching, + FinancialServices, + CapitalMarkets, + InvestmentAdvice, + InvestmentBanking, + InvestmentManagement, + SecuritiesAndCommodityExchanges, + VentureCapitalAndPrivateEquityPrincipals, + CreditIntermediation, + Banking, + InternationalTradeAndDevelopment, + LoanBrokers, + SavingsInstitutions, + FundsAndTrusts, + InsuranceAndEmployeeBenefitFunds, + PensionFunds, + TrustsAndEstates, + Insurance, + ClaimsAdjustingActuarialServices, + InsuranceAgenciesAndBrokerages, + InsuranceCarriers, + GovernmentAdministration, + AdministrationOfJustice, + CorrectionalInstitutions, + CourtsOfLaw, + FireProtection, + LawEnforcement, + PublicSafety, + EconomicPrograms, + TransportationPrograms, + UtilitiesAdministration, + EnvironmentalQualityPrograms, + AirWaterAndWasteProgramManagement, + ConservationPrograms, + HealthAndHumanServices, + EducationAdministrationPrograms, + PublicAssistancePrograms, + PublicHealth, + HousingAndCommunityDevelopment, + CommunityDevelopmentAndUrbanPlanning, + HousingPrograms, + MilitaryAndInternationalAffairs, + ArmedForces, + InternationalAffairs, + PublicPolicyOffices, + ExecutiveOffices, + LegislativeOffices, + SpaceResearchAndTechnology, + HoldingCompanies, + HospitalsAndHealthCare, + CommunityServices, + ServicesForTheElderlyAndDisabled, + Hospitals, + ChildDayCareServices, + EmergencyAndReliefServices, + VocationalRehabilitationServices, + MedicalPractices, + AlternativeMedicine, + AmbulanceServices, + Chiropractors, + Dentists, + FamilyPlanningCenters, + HomeHealthCareServices, + MedicalAndDiagnosticLaboratories, + MentalHealthCare, + Optometrists, + OutpatientCareCenters, + PhysicalOccupationalAndSpeechTherapists, + Physicians, + Manufacturing, + ApparelManufacturing, + FashionAccessoriesManufacturing, + AppliancesElectricalAndElectronicsManufacturing, + ElectricLightingEquipmentManufacturing, + ElectricalEquipmentManufacturing, + FuelCellManufacturing, + HouseholdApplianceManufacturing, + ChemicalManufacturing, + AgriculturalChemicalManufacturing, + ArtificialRubberAndSyntheticFiberManufacturing, + ChemicalRawMaterialsManufacturing, + PaintCoatingAndAdhesiveManufacturing, + PersonalCareProductManufacturing, + PharmaceuticalManufacturing, + SoapAndCleaningProductManufacturing, + ClimateTechnologyProductManufacturing, + ComputersAndElectronicsManufacturing, + CommunicationsEquipmentManufacturing, + ComputerHardwareManufacturing, + AccessibleHardwareManufacturing, + MagneticAndOpticalMediaManufacturing, + MeasuringAndControlInstrumentManufacturing, + SmartMeterManufacturing, + SemiconductorManufacturing, + RenewableEnergySemiconductorManufacturing, + FabricatedMetalProducts, + ArchitecturalAndStructuralMetalManufacturing, + BoilersTanksAndShippingContainerManufacturing, + ConstructionHardwareManufacturing, + CutleryAndHandtoolManufacturing, + MetalTreatments, + MetalValveBallAndRollerManufacturing, + SpringAndWireProductManufacturing, + TurnedProductsAndFastenerManufacturing, + FoodAndBeverageManufacturing, + Breweries, + Distilleries, + Wineries, + AnimalFeedManufacturing, + BakedGoodsManufacturing, + BeverageManufacturing, + DairyProductManufacturing, + FruitAndVegetablePreservesManufacturing, + MeatProductsManufacturing, + SeafoodProductManufacturing, + SugarAndConfectioneryProductManufacturing, + FurnitureAndHomeFurnishingsManufacturing, + HouseholdAndInstitutionalFurnitureManufacturing, + MattressAndBlindsManufacturing, + OfficeFurnitureAndFixturesManufacturing, + GlassCeramicsAndConcreteManufacturing, + AbrasivesAndNonmetallicMineralsManufacturing, + ClayAndRefractoryProductsManufacturing, + GlassProductManufacturing, + LimeAndGypsumProductsManufacturing, + LeatherProductManufacturing, + FootwearManufacturing, + WomensHandbagManufacturing, + MachineryManufacturing, + AgricultureConstructionMiningMachineryManufacturing, + AutomationMachineryManufacturing, + RobotManufacturing, + CommercialAndServiceIndustryMachineryManufacturing, + EnginesAndPowerTransmissionEquipmentManufacturing, + RenewableEnergyEquipmentManufacturing, + HvacAndRefrigerationEquipmentManufacturing, + IndustrialMachineryManufacturing, + MetalworkingMachineryManufacturing, + MedicalEquipmentManufacturing, + OilAndCoalProductManufacturing, + PaperAndForestProductManufacturing, + PlasticsAndRubberProductManufacturing, + PackagingAndContainersManufacturing, + PlasticsManufacturing, + RubberProductsManufacturing, + PrimaryMetalManufacturing, + PrintingServices, + SportingGoodsManufacturing, + TextileManufacturing, + TobaccoManufacturing, + TransportationEquipmentManufacturing, + AviationAndAerospaceComponentManufacturing, + DefenseAndSpaceManufacturing, + MotorVehicleManufacturing, + AlternativeFuelVehicleManufacturing, + MotorVehiclePartsManufacturing, + RailroadEquipmentManufacturing, + Shipbuilding, + WoodProductManufacturing, + OilGasAndMining, + Mining, + CoalMining, + MetalOreMining, + NonmetallicMineralMining, + OilAndGas, + NaturalGasExtraction, + OilExtraction, + ProfessionalServices, + Accounting, + AdvertisingServices, + GovernmentRelationsServices, + PublicRelationsAndCommunicationsServices, + MarketResearch, + ArchitectureAndPlanning, + AccessibleArchitectureAndDesign, + BusinessConsultingAndServices, + EnvironmentalServices, + HumanResourcesServices, + MarketingServices, + OperationsConsulting, + OutsourcingAndOffshoringConsulting, + StrategicManagementServices, + DesignServices, + GraphicDesign, + RegenerativeDesign, + InteriorDesign, + EngineeringServices, + RoboticsEngineering, + SurveyingAndMappingServices, + ItServicesAndItConsulting, + ComputerAndNetworkSecurity, + DigitalAccessibilityServices, + ItSystemCustomSoftwareDevelopment, + ItSystemDataServices, + ItSystemDesignServices, + ItSystemInstallationAndDisposal, + ItSystemOperationsAndMaintenance, + ItSystemTestingAndEvaluation, + ItSystemTrainingAndSupport, + LegalServices, + AlternativeDisputeResolution, + LawPractice, + Photography, + ResearchServices, + BiotechnologyResearch, + NanotechnologyResearch, + ThinkTanks, + ServicesForRenewableEnergy, + VeterinaryServices, + RealEstateAndEquipmentRentalServices, + EquipmentRentalServices, + CommercialAndIndustrialEquipmentRental, + ConsumerGoodsRental, + RealEstate, + RealEstateAgentsAndBrokers, + Retail, + FoodAndBeverageRetail, + RetailGroceries, + OnlineAndMailOrderRetail, + RetailApparelAndFashion, + RetailAppliancesElectricalAndElectronicEquipment, + RetailArtDealers, + RetailArtSupplies, + RetailBooksAndPrintedNews, + RetailBuildingMaterialsAndGardenEquipment, + RetailFlorists, + RetailFurnitureAndHomeFurnishings, + RetailGasoline, + RetailHealthAndPersonalCareProducts, + RetailPharmacies, + RetailLuxuryGoodsAndJewelry, + RetailMotorVehicles, + RetailMusicalInstruments, + RetailOfficeEquipment, + RetailOfficeSuppliesAndGifts, + RetailRecyclableMaterialsUsedMerchandise, + TechnologyInformationAndMedia, + MediaTelecommunications, + BookAndPeriodicalPublishing, + BookPublishing, + NewspaperPublishing, + PeriodicalPublishing, + BroadcastMediaProductionAndDistribution, + CableAndSatelliteProgramming, + RadioAndTelevisionBroadcasting, + AnimationAndPostProduction, + MediaProduction, + MoviesAndSoundRecording, + SoundRecording, + SheetMusicPublishing, + Telecommunications, + SatelliteTelecommunications, + TelecommunicationsCarriers, + WirelessServices, + TechnologyInformationAndInternet, + DataInfrastructureAndAnalytics, + BlockchainServices, + BusinessIntelligencePlatforms, + ClimateDataAndAnalytics, + InformationServices, + InternetPublishing, + BusinessContent, + InternetNews, + Libraries, + Blogs, + InternetMarketplacePlatforms, + SocialNetworkingPlatforms, + SoftwareDevelopment, + ComputerGames, + MobileGamingApps, + ComputerNetworkingProducts, + DataSecuritySoftwareProducts, + DesktopComputingSoftwareProducts, + EmbeddedSoftwareProducts, + MobileComputingSoftwareProducts, + TransportationLogisticsSupplyChainAndStorage, + AirlinesAndAviation, + FreightAndPackageTransportation, + GroundPassengerTransportation, + InterurbanAndRuralBusServices, + SchoolAndEmployeeBusServices, + ShuttlesAndSpecialNeedsTransportationServices, + SightseeingTransportation, + TaxiAndLimousineServices, + UrbanTransitServices, + MaritimeTransportation, + PipelineTransportation, + PostalServices, + RailTransportation, + TruckTransportation, + WarehousingAndStorage, + Utilities, + ElectricPowerGeneration, + FossilFuelElectricPowerGeneration, + NuclearElectricPowerGeneration, + RenewableEnergyPowerGeneration, + BiomassElectricPowerGeneration, + GeothermalElectricPowerGeneration, + HydroelectricPowerGeneration, + SolarElectricPowerGeneration, + WindElectricPowerGeneration, + ElectricPowerTransmissionControlAndDistribution, + NaturalGasDistribution, + WaterWasteSteamAndAirConditioningServices, + SteamAndAirConditioningSupply, + WasteCollection, + WasteTreatmentAndDisposal, + WaterSupplyAndIrrigationSystems, + Wholesale, + WholesaleAlcoholicBeverages, + WholesaleApparelAndSewingSupplies, + WholesaleAppliancesElectricalAndElectronics, + WholesaleBuildingMaterials, + WholesaleChemicalAndAlliedProducts, + WholesaleComputerEquipment, + WholesaleDrugsAndSundries, + WholesaleFoodAndBeverage, + WholesaleFootwear, + WholesaleFurnitureAndHomeFurnishings, + WholesaleHardwarePlumbingHeatingEquipment, + WholesaleImportAndExport, + WholesaleLuxuryGoodsAndJewelry, + WholesaleMachinery, + WholesaleMetalsAndMinerals, + WholesaleMotorVehiclesAndParts, + WholesalePaperProducts, + WholesalePetroleumAndPetroleumProducts, + WholesalePhotographyEquipmentAndSupplies, + WholesaleRawFarmProducts, + WholesaleRecyclableMaterials, +) diff --git a/types/linkedin/profile/profile.go b/types/linkedin/profile/profile.go new file mode 100644 index 0000000..a7257ad --- /dev/null +++ b/types/linkedin/profile/profile.go @@ -0,0 +1,188 @@ +package profile + +import ( + "time" + + "github.com/masa-finance/tee-types/pkg/util" +) + +type ScraperMode string + +const ( + ScraperModeShort ScraperMode = "Short" + ScraperModeFull ScraperMode = "Full" + ScraperModeFullEmail ScraperMode = "Full + email search" +) + +var AllScraperModes = util.NewSet(ScraperModeShort, ScraperModeFull, ScraperModeFullEmail) + +// Profile represents a complete profile response +type Profile struct { + ID string `json:"id"` + PublicIdentifier string `json:"publicIdentifier"` + URL string `json:"Url"` + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + Headline string `json:"headline"` + About string `json:"about"` + OpenToWork bool `json:"openToWork"` + Hiring bool `json:"hiring"` + Photo string `json:"photo"` + Premium bool `json:"premium"` + Influencer bool `json:"influencer"` + Location Location `json:"location"` + Verified bool `json:"verified"` + RegisteredAt time.Time `json:"registeredAt"` + TopSkills string `json:"topSkills"` + ConnectionsCount int `json:"connectionsCount"` + FollowerCount int `json:"followerCount"` + CurrentPosition []CurrentPosition `json:"currentPosition"` + Experience []Experience `json:"experience"` + Education []Education `json:"education"` + Certifications []Certification `json:"certifications"` + Projects []Project `json:"projects"` + Volunteering []Volunteering `json:"volunteering"` + ReceivedRecommendations []any `json:"receivedRecommendations"` // we don't have examples of this data yet... + Skills []Skill `json:"skills"` + Courses []Course `json:"courses"` + Publications []Publication `json:"publications"` + Patents []any `json:"patents"` // we don't have examples of this data yet... + HonorsAndAwards []HonorAndAward `json:"honorsAndAwards"` + Languages []Language `json:"languages"` + Featured any `json:"featured"` // we don't have examples of this data yet... + MoreProfiles []MoreProfile `json:"moreProfiles"` +} + +// Location represents the location information +type Location struct { + Text string `json:"Text"` + CountryCode string `json:"countryCode"` + Parsed ParsedLocation `json:"parsed"` +} + +// ParsedLocation represents the parsed location details +type ParsedLocation struct { + Text string `json:"text"` + CountryCode string `json:"countryCode"` + RegionCode *string `json:"regionCode"` + Country string `json:"country"` + CountryFull string `json:"countryFull"` + State string `json:"state"` + City string `json:"city"` +} + +// CurrentPosition represents current position information +type CurrentPosition struct { + CompanyName string `json:"companyName"` +} + +// Experience represents work experience +type Experience struct { + Position string `json:"position"` + Location string `json:"location"` + EmploymentType string `json:"employmentType"` + WorkplaceType *string `json:"workplaceType"` + CompanyName string `json:"companyName"` + CompanyURL string `json:"companyUrl"` + CompanyID string `json:"companyId"` + CompanyUniversalName string `json:"companyUniversalName"` + Duration string `json:"duration"` + Description string `json:"description"` + Skills []string `json:"skills"` + StartDate DateRange `json:"startDate"` + EndDate DateRange `json:"endDate"` +} + +// DateRange represents a date range with month, year, and text +type DateRange struct { + Month *string `json:"month,omitempty"` + Year *int `json:"year,omitempty"` + Text string `json:"text"` +} + +// Education represents educational background +type Education struct { + SchoolName string `json:"schoolName"` + SchoolURL string `json:"schoolUrl"` + Degree string `json:"degree"` + FieldOfStudy *string `json:"fieldOfStudy"` + Skills []string `json:"skills"` + StartDate DateRange `json:"startDate"` + EndDate DateRange `json:"endDate"` + Period string `json:"period"` +} + +// Certification represents a certification +type Certification struct { + Title string `json:"title"` + IssuedAt string `json:"issuedAt"` + IssuedBy string `json:"issuedBy"` + IssuedByLink string `json:"issuedByLink"` +} + +// Project represents a project +type Project struct { + Title string `json:"title"` + Description string `json:"description"` + Duration string `json:"duration"` + StartDate DateRange `json:"startDate"` + EndDate DateRange `json:"endDate"` +} + +// Volunteering represents volunteer experience +type Volunteering struct { + Role string `json:"role"` + Duration string `json:"duration"` + StartDate *DateRange `json:"startDate"` + EndDate *DateRange `json:"endDate"` + OrganizationName string `json:"organizationName"` + OrganizationURL *string `json:"organizationUrl"` + Cause string `json:"cause"` +} + +// Skill represents a skill with optional positions and endorsements +type Skill struct { + Name string `json:"name"` + Positions []string `json:"positions,omitempty"` + Endorsements string `json:"endorsements,omitempty"` +} + +// Course represents a course +type Course struct { + Title string `json:"title"` + AssociatedWith string `json:"associatedWith"` + AssociatedWithLink string `json:"associatedWithLink"` +} + +// Publication represents a publication +type Publication struct { + Title string `json:"title"` + PublishedAt string `json:"publishedAt"` + Link string `json:"link"` +} + +// HonorAndAward represents an honor or award +type HonorAndAward struct { + Title string `json:"title"` + IssuedBy string `json:"issuedBy"` + IssuedAt string `json:"issuedAt"` + Description string `json:"description"` + AssociatedWith string `json:"associatedWith"` + AssociatedWithLink string `json:"associatedWithLink"` +} + +// Language represents a language with proficiency level +type Language struct { + Name string `json:"name"` + Proficiency string `json:"proficiency"` +} + +// MoreProfile represents a related profile +type MoreProfile struct { + ID string `json:"id"` + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + Position *string `json:"position,omitempty"` + PublicIdentifier string `json:"publicIdentifier"` + URL string `json:"Url"` +} diff --git a/types/linkedin/seniorities/seniorities.go b/types/linkedin/seniorities/seniorities.go new file mode 100644 index 0000000..7685c99 --- /dev/null +++ b/types/linkedin/seniorities/seniorities.go @@ -0,0 +1,33 @@ +package seniorities + +import "github.com/masa-finance/tee-types/pkg/util" + +// id represents a LinkedIn seniority level identifier +type Id string + +// Seniority level constants +const ( + InTraining Id = "100" + EntryLevel Id = "110" + Senior Id = "120" + Strategic Id = "130" + EntryLevelManager Id = "200" + ExperiencedManager Id = "210" + Director Id = "220" + VicePresident Id = "300" + CXO Id = "310" + Partner Id = "320" +) + +var All = util.NewSet( + InTraining, + EntryLevel, + Senior, + Strategic, + EntryLevelManager, + ExperiencedManager, + Director, + VicePresident, + CXO, + Partner, +) From ee0d46384cbd0013dee2f17f052470c67cc47cae Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Wed, 8 Oct 2025 02:38:07 +0200 Subject: [PATCH 02/26] fix: validation tests --- args/linkedin/profile/profile_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/args/linkedin/profile/profile_test.go b/args/linkedin/profile/profile_test.go index d11a78f..65650bb 100644 --- a/args/linkedin/profile/profile_test.go +++ b/args/linkedin/profile/profile_test.go @@ -198,12 +198,12 @@ var _ = Describe("LinkedIn Profile Arguments", func() { It("should fail with invalid job type", func() { args := &profile.Arguments{ - QueryType: types.CapSearchByProfile, + QueryType: types.CapSearchByQuery, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, MaxItems: 10, } - err := args.ValidateForJobType(types.TwitterJob) + err := args.ValidateForJobType(types.LinkedInJob) Expect(err).To(HaveOccurred()) }) From ed6515a4c2e7ee692037c4c355498b55137dc4e7 Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Wed, 8 Oct 2025 19:41:43 +0200 Subject: [PATCH 03/26] chore: fix unmarshalling tests --- args/unmarshaller_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/args/unmarshaller_test.go b/args/unmarshaller_test.go index 4231cbd..03baaca 100644 --- a/args/unmarshaller_test.go +++ b/args/unmarshaller_test.go @@ -51,7 +51,7 @@ var _ = Describe("Unmarshaller", func() { Expect(err).ToNot(HaveOccurred()) twitterArgs, ok := jobArgs.(*args.TwitterSearchArguments) Expect(ok).To(BeTrue()) - Expect(twitterArgs.QueryType).To(Equal("searchbyquery")) + Expect(twitterArgs.QueryType).To(Equal(types.CapSearchByQuery)) Expect(twitterArgs.Query).To(Equal("golang")) Expect(twitterArgs.Count).To(Equal(10)) }) From 9bed6c8af730ac4451d896adadfc28676f727b09 Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Wed, 8 Oct 2025 20:56:55 +0200 Subject: [PATCH 04/26] chore: adds basic linkedin type tests --- args/args.go | 4 + args/linkedin/linkedin.go | 13 + args/linkedin/profile/profile_test.go | 2 +- types/linkedin/experiences/experiences.go | 18 + types/linkedin/functions/functions.go | 58 + types/linkedin/industries/industries.go | 1476 +++++++++------------ types/linkedin/linkedin.go | 25 + types/linkedin/linkedin_suite_test.go | 13 + types/linkedin/linkedin_test.go | 208 +++ types/linkedin/seniorities/seniorities.go | 28 + types/types.go | 7 + 11 files changed, 1037 insertions(+), 815 deletions(-) create mode 100644 args/linkedin/linkedin.go create mode 100644 types/linkedin/linkedin.go create mode 100644 types/linkedin/linkedin_suite_test.go create mode 100644 types/linkedin/linkedin_test.go create mode 100644 types/types.go diff --git a/args/args.go b/args/args.go index 5504844..c90cb19 100644 --- a/args/args.go +++ b/args/args.go @@ -4,9 +4,13 @@ import ( "encoding/json" "fmt" + linkedin "github.com/masa-finance/tee-types/args/linkedin" teetypes "github.com/masa-finance/tee-types/types" ) +// LinkedIn is the LinkedIn arguments by type +var LinkedIn = linkedin.LinkedIn + // QueryTypeArgument provides a minimal structure to extract the QueryType (json "type") // This is used across different job types to determine the specific capability being requested type QueryTypeArgument struct { diff --git a/args/linkedin/linkedin.go b/args/linkedin/linkedin.go new file mode 100644 index 0000000..a213807 --- /dev/null +++ b/args/linkedin/linkedin.go @@ -0,0 +1,13 @@ +package linkedin + +import ( + "github.com/masa-finance/tee-types/args/linkedin/profile" +) + +type linkedin struct { + Profile *profile.Arguments +} + +var LinkedIn = linkedin{ + Profile: &profile.Arguments{}, +} diff --git a/args/linkedin/profile/profile_test.go b/args/linkedin/profile/profile_test.go index 65650bb..3294523 100644 --- a/args/linkedin/profile/profile_test.go +++ b/args/linkedin/profile/profile_test.go @@ -57,7 +57,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { YearsOfExperience: []experiences.Id{experiences.ThreeToFiveYears}, SeniorityLevels: []seniorities.Id{seniorities.Senior}, Functions: []functions.Id{functions.Engineering}, - Industries: []industries.Id{industries.AccommodationServices}, + Industries: []industries.Id{industries.SoftwareDevelopment}, } err := args.Validate() Expect(err).ToNot(HaveOccurred()) diff --git a/types/linkedin/experiences/experiences.go b/types/linkedin/experiences/experiences.go index bd844f7..e714b58 100644 --- a/types/linkedin/experiences/experiences.go +++ b/types/linkedin/experiences/experiences.go @@ -21,3 +21,21 @@ var All = util.NewSet( SixToTenYears, MoreThanTenYears, ) + +type ExperiencesConfig struct { + All util.Set[Id] + LessThanAYear Id + OneToTwoYears Id + ThreeToFiveYears Id + SixToTenYears Id + MoreThanTenYears Id +} + +var Experiences = ExperiencesConfig{ + All: *All, + LessThanAYear: LessThanAYear, + OneToTwoYears: OneToTwoYears, + ThreeToFiveYears: ThreeToFiveYears, + SixToTenYears: SixToTenYears, + MoreThanTenYears: MoreThanTenYears, +} diff --git a/types/linkedin/functions/functions.go b/types/linkedin/functions/functions.go index 19af25c..cd08f33 100644 --- a/types/linkedin/functions/functions.go +++ b/types/linkedin/functions/functions.go @@ -61,3 +61,61 @@ var All = util.NewSet( Research, Sales, ) + +type FunctionsConfig struct { + All util.Set[Id] + Accounting Id + Administrative Id + ArtsAndDesign Id + BusinessDevelopment Id + CommunityAndSocialServices Id + Consulting Id + Education Id + Engineering Id + Entrepreneurship Id + Finance Id + HealthcareServices Id + HumanResources Id + InformationTechnology Id + Legal Id + Marketing Id + MediaAndCommunication Id + MilitaryAndProtectiveServices Id + Operations Id + ProductManagement Id + ProgramAndProjectManagement Id + Purchasing Id + QualityAssurance Id + RealEstate Id + Research Id + Sales Id +} + +var Functions = FunctionsConfig{ + All: *All, + Accounting: Accounting, + Administrative: Administrative, + ArtsAndDesign: ArtsAndDesign, + BusinessDevelopment: BusinessDevelopment, + CommunityAndSocialServices: CommunityAndSocialServices, + Consulting: Consulting, + Education: Education, + Engineering: Engineering, + Entrepreneurship: Entrepreneurship, + Finance: Finance, + HealthcareServices: HealthcareServices, + HumanResources: HumanResources, + InformationTechnology: InformationTechnology, + Legal: Legal, + Marketing: Marketing, + MediaAndCommunication: MediaAndCommunication, + MilitaryAndProtectiveServices: MilitaryAndProtectiveServices, + Operations: Operations, + ProductManagement: ProductManagement, + ProgramAndProjectManagement: ProgramAndProjectManagement, + Purchasing: Purchasing, + QualityAssurance: QualityAssurance, + RealEstate: RealEstate, + Research: Research, + Sales: Sales, +} diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index fa53dbc..1d74529 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -2,868 +2,716 @@ package industries import "github.com/masa-finance/tee-types/pkg/util" -// IndustryId represents a LinkedIn industry identifier +// Id represents a LinkedIn industry identifier type Id string // Industry constants const ( - AccommodationServices Id = "2190" - FoodAndBeverageServices Id = "34" - BarsTavernsAndNightclubs Id = "2217" - Caterers Id = "2212" - MobileFoodServices Id = "2214" - Restaurants Id = "32" - Hospitality Id = "31" - BedAndBreakfastsHostelsHomestays Id = "2197" - HotelsAndMotels Id = "2194" - AdministrativeAndSupportServices Id = "1912" - CollectionAgencies Id = "1938" - EventsServices Id = "110" - FacilitiesServices Id = "122" - JanitorialServices Id = "1965" - LandscapingServices Id = "2934" - Fundraising Id = "101" - OfficeAdministration Id = "1916" - SecurityAndInvestigations Id = "121" - SecurityGuardsAndPatrolServices Id = "1956" - SecuritySystemsServices Id = "1958" - StaffingAndRecruiting Id = "104" - ExecutiveSearchServices Id = "1923" - TemporaryHelpServices Id = "1925" - TelephoneCallCenters Id = "1931" - TranslationAndLocalization Id = "108" - TravelArrangements Id = "30" - WritingAndEditing Id = "103" - Construction Id = "48" - BuildingConstruction Id = "406" - NonresIdentialBuildingConstruction Id = "413" - ResIdentialBuildingConstruction Id = "408" - CivilEngineering Id = "51" - HighwayStreetAndBrIdgeConstruction Id = "431" - SubdivisionOfLand Id = "428" - UtilitySystemConstruction Id = "419" - SpecialtyTradeContractors Id = "435" - BuildingEquipmentContractors Id = "453" - BuildingFinishingContractors Id = "460" - BuildingStructureAndExteriorContractors Id = "436" - ConsumerServices Id = "91" - CivicAndSocialOrganizations Id = "90" - Associations Id = "1909" - PoliticalOrganizations Id = "107" - ProfessionalOrganizations Id = "1911" - HouseholdServices Id = "2318" - NonProfitOrganizations Id = "100" - PersonalAndLaundryServices Id = "2258" - LaundryAndDrycleaningServices Id = "2272" - PersonalCareServices Id = "2259" - PetServices Id = "2282" - PhilanthropicFundraisingServices Id = "131" - ReligiousInstitutions Id = "89" - RepairAndMaintenance Id = "2225" - CommercialAndIndustrialMachineryMaintenance Id = "2247" - ElectronicAndPrecisionEquipmentMaintenance Id = "2240" - FootwearAndLeatherGoodsRepair Id = "2255" - ReupholsteryAndFurnitureRepair Id = "2253" - VehicleRepairAndMaintenance Id = "2226" - Education Id = "1999" - ELearningProvIders Id = "132" - HigherEducation Id = "68" - PrimaryAndSecondaryEducation Id = "67" - ProfessionalTrainingAndCoaching Id = "105" - TechnicalAndVocationalTraining Id = "2018" - CosmetologyAndBarberSchools Id = "2019" - FineArtsSchools Id = "2025" - FlightTraining Id = "2020" - LanguageSchools Id = "2029" - SecretarialSchools Id = "2012" - SportsAndRecreationInstruction Id = "2027" - EntertainmentProvIders Id = "28" - ArtistsAndWriters Id = "38" - MuseumsHistoricalSitesAndZoos Id = "37" - HistoricalSites Id = "2161" - Museums Id = "2159" - ZoosAndBotanicalGardens Id = "2163" - Musicians Id = "115" - PerformingArtsAndSpectatorSports Id = "2130" - CircusesAndMagicShows Id = "2139" - DanceCompanies Id = "2135" - PerformingArts Id = "39" - SpectatorSports Id = "33" - Racetracks Id = "2143" - SportsTeamsAndClubs Id = "2142" - TheaterCompanies Id = "2133" - RecreationalFacilities Id = "40" - AmusementParksAndArcades Id = "2167" - GamblingFacilitiesAndCasinos Id = "29" - GolfCoursesAndCountryClubs Id = "2179" - SkiingFacilities Id = "2181" - WellnessAndFitnessServices Id = "124" - FarmingRanchingForestry Id = "201" - Farming Id = "63" - Horticulture Id = "150" - ForestryAndLogging Id = "298" - RanchingAndFisheries Id = "256" - Fisheries Id = "66" - Ranching Id = "64" - FinancialServices Id = "43" - CapitalMarkets Id = "129" - InvestmentAdvice Id = "1720" - InvestmentBanking Id = "45" - InvestmentManagement Id = "46" - SecuritiesAndCommodityExchanges Id = "1713" - VentureCapitalAndPrivateEquityPrincipals Id = "106" - CreditIntermediation Id = "1673" - Banking Id = "41" - InternationalTradeAndDevelopment Id = "141" - LoanBrokers Id = "1696" - SavingsInstitutions Id = "1678" - FundsAndTrusts Id = "1742" - InsuranceAndEmployeeBenefitFunds Id = "1743" - PensionFunds Id = "1745" - TrustsAndEstates Id = "1750" - Insurance Id = "42" - ClaimsAdjustingActuarialServices Id = "1738" - InsuranceAgenciesAndBrokerages Id = "1737" - InsuranceCarriers Id = "1725" - GovernmentAdministration Id = "75" - AdministrationOfJustice Id = "73" - CorrectionalInstitutions Id = "3068" - CourtsOfLaw Id = "3065" - FireProtection Id = "3070" - LawEnforcement Id = "77" - PublicSafety Id = "78" - EconomicPrograms Id = "2375" - TransportationPrograms Id = "3085" - UtilitiesAdministration Id = "3086" - EnvironmentalQualityPrograms Id = "388" - AirWaterAndWasteProgramManagement Id = "2366" - ConservationPrograms Id = "2368" - HealthAndHumanServices Id = "2353" - EducationAdministrationPrograms Id = "69" - PublicAssistancePrograms Id = "2360" - PublicHealth Id = "2358" - HousingAndCommunityDevelopment Id = "2369" - CommunityDevelopmentAndUrbanPlanning Id = "2374" - HousingPrograms Id = "3081" - MilitaryAndInternationalAffairs Id = "2391" - ArmedForces Id = "71" - InternationalAffairs Id = "74" - PublicPolicyOffices Id = "79" - ExecutiveOffices Id = "76" - LegislativeOffices Id = "72" - SpaceResearchAndTechnology Id = "3089" - HoldingCompanies Id = "1905" - HospitalsAndHealthCare Id = "14" - CommunityServices Id = "2115" - ServicesForTheElderlyAndDisabled Id = "2112" - Hospitals Id = "2081" - IndivIdualAndFamilyServices Id = "88" - ChildDayCareServices Id = "2128" - EmergencyAndReliefServices Id = "2122" - VocationalRehabilitationServices Id = "2125" - MedicalPractices Id = "13" - AlternativeMedicine Id = "125" - AmbulanceServices Id = "2077" - Chiropractors Id = "2048" - Dentists Id = "2045" - FamilyPlanningCenters Id = "2060" - HomeHealthCareServices Id = "2074" - MedicalAndDiagnosticLaboratories Id = "2069" - MentalHealthCare Id = "139" - Optometrists Id = "2050" - OutpatientCareCenters Id = "2063" - PhysicalOccupationalAndSpeechTherapists Id = "2054" - Physicians Id = "2040" - NursingHomesAndResIdentialCareFacilities Id = "2091" - Manufacturing Id = "25" - ApparelManufacturing Id = "598" - FashionAccessoriesManufacturing Id = "615" - AppliancesElectricalAndElectronicsManufacturing Id = "112" - ElectricLightingEquipmentManufacturing Id = "998" - ElectricalEquipmentManufacturing Id = "2468" - FuelCellManufacturing Id = "3255" - HouseholdApplianceManufacturing Id = "1005" - ChemicalManufacturing Id = "54" - AgriculturalChemicalManufacturing Id = "709" - ArtificialRubberAndSyntheticFiberManufacturing Id = "703" - ChemicalRawMaterialsManufacturing Id = "690" - PaintCoatingAndAdhesiveManufacturing Id = "722" - PersonalCareProductManufacturing Id = "18" - PharmaceuticalManufacturing Id = "15" - SoapAndCleaningProductManufacturing Id = "727" - ClimateTechnologyProductManufacturing Id = "3251" - ComputersAndElectronicsManufacturing Id = "24" - AudioAndVIdeoEquipmentManufacturing Id = "973" - CommunicationsEquipmentManufacturing Id = "964" - ComputerHardwareManufacturing Id = "3" - AccessibleHardwareManufacturing Id = "3245" - MagneticAndOpticalMediaManufacturing Id = "994" - MeasuringAndControlInstrumentManufacturing Id = "983" - SmartMeterManufacturing Id = "3254" - SemiconductorManufacturing Id = "7" - RenewableEnergySemiconductorManufacturing Id = "144" - FabricatedMetalProducts Id = "840" - ArchitecturalAndStructuralMetalManufacturing Id = "852" - BoilersTanksAndShippingContainerManufacturing Id = "861" - ConstructionHardwareManufacturing Id = "871" - CutleryAndHandtoolManufacturing Id = "849" - MetalTreatments Id = "883" - MetalValveBallAndRollerManufacturing Id = "887" - SpringAndWireProductManufacturing Id = "873" - TurnedProductsAndFastenerManufacturing Id = "876" - FoodAndBeverageManufacturing Id = "23" - Breweries Id = "562" - Distilleries Id = "564" - Wineries Id = "2500" - AnimalFeedManufacturing Id = "481" - BakedGoodsManufacturing Id = "529" - BeverageManufacturing Id = "142" - DairyProductManufacturing Id = "65" - FruitAndVegetablePreservesManufacturing Id = "504" - MeatProductsManufacturing Id = "521" - SeafoodProductManufacturing Id = "528" - SugarAndConfectioneryProductManufacturing Id = "495" - FurnitureAndHomeFurnishingsManufacturing Id = "26" - HouseholdAndInstitutionalFurnitureManufacturing Id = "1080" - MattressAndBlindsManufacturing Id = "1095" - OfficeFurnitureAndFixturesManufacturing Id = "1090" - GlassCeramicsAndConcreteManufacturing Id = "145" - AbrasivesAndNonmetallicMineralsManufacturing Id = "799" - ClayAndRefractoryProductsManufacturing Id = "773" - GlassProductManufacturing Id = "779" - LimeAndGypsumProductsManufacturing Id = "794" - LeatherProductManufacturing Id = "616" - FootwearManufacturing Id = "622" - WomensHandbagManufacturing Id = "625" - MachineryManufacturing Id = "55" - AgricultureConstructionMiningMachineryManufacturing Id = "901" - AutomationMachineryManufacturing Id = "147" - RobotManufacturing Id = "3247" - CommercialAndServiceIndustryMachineryManufacturing Id = "918" - EnginesAndPowerTransmissionEquipmentManufacturing Id = "935" - RenewableEnergyEquipmentManufacturing Id = "3241" - HvacAndRefrigerationEquipmentManufacturing Id = "923" - IndustrialMachineryManufacturing Id = "135" - MetalworkingMachineryManufacturing Id = "928" - MedicalEquipmentManufacturing Id = "17" - OilAndCoalProductManufacturing Id = "679" - PaperAndForestProductManufacturing Id = "61" - PlasticsAndRubberProductManufacturing Id = "743" - PackagingAndContainersManufacturing Id = "146" - PlasticsManufacturing Id = "117" - RubberProductsManufacturing Id = "763" - PrimaryMetalManufacturing Id = "807" - PrintingServices Id = "83" - SportingGoodsManufacturing Id = "20" - TextileManufacturing Id = "60" - TobaccoManufacturing Id = "21" - TransportationEquipmentManufacturing Id = "1029" - AviationAndAerospaceComponentManufacturing Id = "52" - DefenseAndSpaceManufacturing Id = "1" - MotorVehicleManufacturing Id = "53" - AlternativeFuelVehicleManufacturing Id = "3253" - MotorVehiclePartsManufacturing Id = "1042" - RailroadEquipmentManufacturing Id = "62" - Shipbuilding Id = "58" - WoodProductManufacturing Id = "784" - OilGasAndMining Id = "332" - Mining Id = "56" - CoalMining Id = "341" - MetalOreMining Id = "345" - NonmetallicMineralMining Id = "356" - OilAndGas Id = "57" - NaturalGasExtraction Id = "3096" - OilExtraction Id = "3095" - ProfessionalServices Id = "1810" - Accounting Id = "47" - AdvertisingServices Id = "80" - GovernmentRelationsServices Id = "148" - PublicRelationsAndCommunicationsServices Id = "98" - MarketResearch Id = "97" - ArchitectureAndPlanning Id = "50" - AccessibleArchitectureAndDesign Id = "3246" - BusinessConsultingAndServices Id = "11" - EnvironmentalServices Id = "86" - HumanResourcesServices Id = "137" - MarketingServices Id = "1862" - OperationsConsulting Id = "2401" - OutsourcingAndOffshoringConsulting Id = "123" - StrategicManagementServices Id = "102" - DesignServices Id = "99" - GraphicDesign Id = "140" - RegenerativeDesign Id = "3256" - InteriorDesign Id = "3126" - EngineeringServices Id = "3242" - RoboticsEngineering Id = "3248" - SurveyingAndMappingServices Id = "3249" - ItServicesAndItConsulting Id = "96" - ComputerAndNetworkSecurity Id = "118" - DigitalAccessibilityServices Id = "3244" - ItSystemCustomSoftwareDevelopment Id = "3102" - ItSystemDataServices Id = "3106" - ItSystemDesignServices Id = "1855" - ItSystemInstallationAndDisposal Id = "3104" - ItSystemOperationsAndMaintenance Id = "3103" - ItSystemTestingAndEvaluation Id = "3107" - ItSystemTrainingAndSupport Id = "3105" - LegalServices Id = "10" - AlternativeDisputeResolution Id = "120" - LawPractice Id = "9" - Photography Id = "136" - ResearchServices Id = "70" - BiotechnologyResearch Id = "12" - NanotechnologyResearch Id = "114" - ThinkTanks Id = "130" - ServicesForRenewableEnergy Id = "3243" - VeterinaryServices Id = "16" - RealEstateAndEquipmentRentalServices Id = "1757" - EquipmentRentalServices Id = "1779" - CommercialAndIndustrialEquipmentRental Id = "1798" - ConsumerGoodsRental Id = "1786" - RealEstate Id = "44" - LeasingNonResIdentialRealEstate Id = "128" - LeasingResIdentialRealEstate Id = "1759" - RealEstateAgentsAndBrokers Id = "1770" - Retail Id = "27" - FoodAndBeverageRetail Id = "1339" - RetailGroceries Id = "22" - OnlineAndMailOrderRetail Id = "1445" - RetailApparelAndFashion Id = "19" - RetailAppliancesElectricalAndElectronicEquipment Id = "1319" - RetailArtDealers Id = "3186" - RetailArtSupplies Id = "111" - RetailBooksAndPrintedNews Id = "1409" - RetailBuildingMaterialsAndGardenEquipment Id = "1324" - RetailFlorists Id = "1423" - RetailFurnitureAndHomeFurnishings Id = "1309" - RetailGasoline Id = "1370" - RetailHealthAndPersonalCareProducts Id = "1359" - RetailPharmacies Id = "3250" - RetailLuxuryGoodsAndJewelry Id = "143" - RetailMotorVehicles Id = "1292" - RetailMusicalInstruments Id = "1407" - RetailOfficeEquipment Id = "138" - RetailOfficeSuppliesAndGifts Id = "1424" - RetailRecyclableMaterialsUsedMerchandise Id = "1431" - TechnologyInformationAndMedia Id = "1594" - MediaTelecommunications Id = "3133" - BookAndPeriodicalPublishing Id = "82" - BookPublishing Id = "1602" - NewspaperPublishing Id = "81" - PeriodicalPublishing Id = "1600" - BroadcastMediaProductionAndDistribution Id = "36" - CableAndSatelliteProgramming Id = "1641" - RadioAndTelevisionBroadcasting Id = "1633" - MoviesVIdeosAndSound Id = "35" - AnimationAndPostProduction Id = "127" - MediaProduction Id = "126" - MoviesAndSoundRecording Id = "1611" - SoundRecording Id = "1623" - SheetMusicPublishing Id = "1625" - Telecommunications Id = "8" - SatelliteTelecommunications Id = "1649" - TelecommunicationsCarriers Id = "1644" - WirelessServices Id = "119" - TechnologyInformationAndInternet Id = "6" - DataInfrastructureAndAnalytics Id = "2458" - BlockchainServices Id = "3134" - BusinessIntelligencePlatforms Id = "3128" - ClimateDataAndAnalytics Id = "3252" - InformationServices Id = "84" - InternetPublishing Id = "3132" - BusinessContent Id = "3129" - OnlineAudioAndVIdeoMedia Id = "113" - InternetNews Id = "3124" - Libraries Id = "85" - Blogs Id = "3125" - InternetMarketplacePlatforms Id = "1285" - SocialNetworkingPlatforms Id = "3127" - SoftwareDevelopment Id = "4" - ComputerGames Id = "109" - MobileGamingApps Id = "3131" - ComputerNetworkingProducts Id = "5" - DataSecuritySoftwareProducts Id = "3130" - DesktopComputingSoftwareProducts Id = "3101" - EmbeddedSoftwareProducts Id = "3099" - MobileComputingSoftwareProducts Id = "3100" - TransportationLogisticsSupplyChainAndStorage Id = "116" - AirlinesAndAviation Id = "94" - FreightAndPackageTransportation Id = "87" - GroundPassengerTransportation Id = "1495" - InterurbanAndRuralBusServices Id = "1504" - SchoolAndEmployeeBusServices Id = "1512" - ShuttlesAndSpecialNeedsTransportationServices Id = "1517" - SightseeingTransportation Id = "1532" - TaxiAndLimousineServices Id = "1505" - UrbanTransitServices Id = "1497" - MaritimeTransportation Id = "95" - PipelineTransportation Id = "1520" - PostalServices Id = "1573" - RailTransportation Id = "1481" - TruckTransportation Id = "92" - WarehousingAndStorage Id = "93" - Utilities Id = "59" - ElectricPowerGeneration Id = "383" - FossilFuelElectricPowerGeneration Id = "385" - NuclearElectricPowerGeneration Id = "386" - RenewableEnergyPowerGeneration Id = "3240" - BiomassElectricPowerGeneration Id = "390" - GeothermalElectricPowerGeneration Id = "389" - HydroelectricPowerGeneration Id = "384" - SolarElectricPowerGeneration Id = "387" - WindElectricPowerGeneration Id = "2489" - ElectricPowerTransmissionControlAndDistribution Id = "382" - NaturalGasDistribution Id = "397" - WaterWasteSteamAndAirConditioningServices Id = "398" - SteamAndAirConditioningSupply Id = "404" - WasteCollection Id = "1981" - WasteTreatmentAndDisposal Id = "1986" - WaterSupplyAndIrrigationSystems Id = "400" - Wholesale Id = "133" - WholesaleAlcoholicBeverages Id = "1267" - WholesaleApparelAndSewingSupplies Id = "1222" - WholesaleAppliancesElectricalAndElectronics Id = "1171" - WholesaleBuildingMaterials Id = "49" - WholesaleChemicalAndAlliedProducts Id = "1257" - WholesaleComputerEquipment Id = "1157" - WholesaleDrugsAndSundries Id = "1221" - WholesaleFoodAndBeverage Id = "1231" - WholesaleFootwear Id = "1230" - WholesaleFurnitureAndHomeFurnishings Id = "1137" - WholesaleHardwarePlumbingHeatingEquipment Id = "1178" - WholesaleImportAndExport Id = "134" - WholesaleLuxuryGoodsAndJewelry Id = "1208" - WholesaleMachinery Id = "1187" - WholesaleMetalsAndMinerals Id = "1166" - WholesaleMotorVehiclesAndParts Id = "1128" - WholesalePaperProducts Id = "1212" - WholesalePetroleumAndPetroleumProducts Id = "1262" - WholesalePhotographyEquipmentAndSupplies Id = "1153" - WholesaleRawFarmProducts Id = "1250" - WholesaleRecyclableMaterials Id = "1206" + // Technology & Software + SoftwareDevelopment Id = "4" + ComputerHardwareManufacturing Id = "3" + ComputerNetworkingProducts Id = "5" + ItServicesAndItConsulting Id = "96" + ComputerAndNetworkSecurity Id = "118" + Telecommunications Id = "8" + WirelessServices Id = "119" + TechnologyInformationAndInternet Id = "6" + DataInfrastructureAndAnalytics Id = "2458" + InformationServices Id = "84" + InternetPublishing Id = "3132" + SocialNetworkingPlatforms Id = "3127" + ComputerGames Id = "109" + MobileGamingApps Id = "3131" + BlockchainServices Id = "3134" + BusinessIntelligencePlatforms Id = "3128" + + // Financial Services + FinancialServices Id = "43" + Banking Id = "41" + Insurance Id = "42" + InvestmentBanking Id = "45" + CapitalMarkets Id = "129" + VentureCapitalAndPrivateEquityPrincipals Id = "106" + SecuritiesAndCommodityExchanges Id = "1713" + FundsAndTrusts Id = "1742" + + // Healthcare & Medical + Hospitals Id = "2081" + MedicalPractices Id = "13" + MedicalEquipmentManufacturing Id = "17" + PublicHealth Id = "2358" + VeterinaryServices Id = "16" + BiotechnologyResearch Id = "12" + + // Manufacturing + Manufacturing Id = "25" + ComputersAndElectronicsManufacturing Id = "24" + SemiconductorManufacturing Id = "7" + MachineryManufacturing Id = "55" + IndustrialMachineryManufacturing Id = "135" + FoodAndBeverageManufacturing Id = "23" + TextileManufacturing Id = "60" + MotorVehicleManufacturing Id = "53" + MotorVehiclePartsManufacturing Id = "1042" + AviationAndAerospaceComponentManufacturing Id = "52" + DefenseAndSpaceManufacturing Id = "1" + PlasticsManufacturing Id = "117" + RubberProductsManufacturing Id = "763" + PaperAndForestProductManufacturing Id = "61" + WoodProductManufacturing Id = "784" + FurnitureAndHomeFurnishingsManufacturing Id = "26" + SportingGoodsManufacturing Id = "20" + PrintingServices Id = "83" + + // Retail & Consumer Goods + Retail Id = "27" + RetailGroceries Id = "22" + OnlineAndMailOrderRetail Id = "1445" + RetailApparelAndFashion Id = "19" + RetailAppliancesElectricalAndElectronicEquipment Id = "1319" + RetailBooksAndPrintedNews Id = "1409" + RetailBuildingMaterialsAndGardenEquipment Id = "1324" + RetailFurnitureAndHomeFurnishings Id = "1309" + RetailHealthAndPersonalCareProducts Id = "1359" + RetailLuxuryGoodsAndJewelry Id = "143" + RetailMotorVehicles Id = "1292" + RetailOfficeEquipment Id = "138" + RetailOfficeSuppliesAndGifts Id = "1424" + + // Professional Services + ProfessionalServices Id = "1810" + Accounting Id = "47" + LegalServices Id = "10" + LawPractice Id = "9" + BusinessConsultingAndServices Id = "11" + StrategicManagementServices Id = "102" + HumanResourcesServices Id = "137" + MarketingServices Id = "1862" + AdvertisingServices Id = "80" + PublicRelationsAndCommunicationsServices Id = "98" + MarketResearch Id = "97" + ArchitectureAndPlanning Id = "50" + DesignServices Id = "99" + GraphicDesign Id = "140" + InteriorDesign Id = "3126" + EngineeringServices Id = "3242" + EnvironmentalServices Id = "86" + ResearchServices Id = "70" + ThinkTanks Id = "130" + Photography Id = "136" + TranslationAndLocalization Id = "108" + WritingAndEditing Id = "103" + + // Education + Education Id = "1999" + HigherEducation Id = "68" + ProfessionalTrainingAndCoaching Id = "105" + SportsAndRecreationInstruction Id = "2027" + + // Transportation & Logistics + TransportationLogisticsSupplyChainAndStorage Id = "116" + AirlinesAndAviation Id = "94" + FreightAndPackageTransportation Id = "87" + MaritimeTransportation Id = "95" + RailTransportation Id = "1481" + TruckTransportation Id = "92" + WarehousingAndStorage Id = "93" + PostalServices Id = "1573" + + // Energy & Utilities + Utilities Id = "59" + ElectricPowerGeneration Id = "383" + RenewableEnergyPowerGeneration Id = "3240" + OilAndGas Id = "57" + Mining Id = "56" + OilGasAndMining Id = "332" + + // Media & Entertainment + TechnologyInformationAndMedia Id = "1594" + BroadcastMediaProductionAndDistribution Id = "36" + RadioAndTelevisionBroadcasting Id = "1633" + MoviesVIdeosAndSound Id = "35" + MediaProduction Id = "126" + SoundRecording Id = "1623" + BookAndPeriodicalPublishing Id = "82" + NewspaperPublishing Id = "81" + PeriodicalPublishing Id = "1600" + EntertainmentProvIders Id = "28" + ArtistsAndWriters Id = "38" + Musicians Id = "115" + + // Construction & Real Estate + Construction Id = "48" + CivilEngineering Id = "51" + RealEstate Id = "44" + RealEstateAgentsAndBrokers Id = "1770" + + // Hospitality & Services + Hospitality Id = "31" + HotelsAndMotels Id = "2194" + Restaurants Id = "32" + FoodAndBeverageServices Id = "34" + TravelArrangements Id = "30" + EventsServices Id = "110" + WellnessAndFitnessServices Id = "124" + ConsumerServices Id = "91" + + // Government & Non-Profit + ArmedForces Id = "71" + GovernmentRelationsServices Id = "148" + NonProfitOrganizations Id = "100" + CivicAndSocialOrganizations Id = "90" + PoliticalOrganizations Id = "107" + ProfessionalOrganizations Id = "1911" + Fundraising Id = "101" + + // Wholesale & Distribution + Wholesale Id = "133" + WholesaleImportAndExport Id = "134" + WholesaleComputerEquipment Id = "1157" + WholesaleFoodAndBeverage Id = "1231" + WholesaleBuildingMaterials Id = "49" + WholesaleMachinery Id = "1187" + WholesaleMotorVehiclesAndParts Id = "1128" + + // Other Services + StaffingAndRecruiting Id = "104" + ExecutiveSearchServices Id = "1923" + OfficeAdministration Id = "1916" + SecurityAndInvestigations Id = "121" + EquipmentRentalServices Id = "1779" + Libraries Id = "85" ) var All = util.NewSet( - AccommodationServices, - FoodAndBeverageServices, - BarsTavernsAndNightclubs, - Caterers, - MobileFoodServices, - Restaurants, - Hospitality, - BedAndBreakfastsHostelsHomestays, - HotelsAndMotels, - AdministrativeAndSupportServices, - CollectionAgencies, - EventsServices, - FacilitiesServices, - JanitorialServices, - LandscapingServices, - Fundraising, - OfficeAdministration, - SecurityAndInvestigations, - SecurityGuardsAndPatrolServices, - SecuritySystemsServices, - StaffingAndRecruiting, - ExecutiveSearchServices, - TemporaryHelpServices, - TelephoneCallCenters, - TranslationAndLocalization, - TravelArrangements, - WritingAndEditing, - Construction, - BuildingConstruction, - CivilEngineering, - SubdivisionOfLand, - UtilitySystemConstruction, - SpecialtyTradeContractors, - BuildingEquipmentContractors, - BuildingFinishingContractors, - BuildingStructureAndExteriorContractors, - ConsumerServices, - CivicAndSocialOrganizations, - Associations, - PoliticalOrganizations, - ProfessionalOrganizations, - HouseholdServices, - NonProfitOrganizations, - PersonalAndLaundryServices, - LaundryAndDrycleaningServices, - PersonalCareServices, - PetServices, - PhilanthropicFundraisingServices, - ReligiousInstitutions, - RepairAndMaintenance, - CommercialAndIndustrialMachineryMaintenance, - ElectronicAndPrecisionEquipmentMaintenance, - FootwearAndLeatherGoodsRepair, - ReupholsteryAndFurnitureRepair, - VehicleRepairAndMaintenance, - Education, - HigherEducation, - PrimaryAndSecondaryEducation, - ProfessionalTrainingAndCoaching, - TechnicalAndVocationalTraining, - CosmetologyAndBarberSchools, - FineArtsSchools, - FlightTraining, - LanguageSchools, - SecretarialSchools, - SportsAndRecreationInstruction, - ArtistsAndWriters, - MuseumsHistoricalSitesAndZoos, - HistoricalSites, - Museums, - ZoosAndBotanicalGardens, - Musicians, - PerformingArtsAndSpectatorSports, - CircusesAndMagicShows, - DanceCompanies, - PerformingArts, - SpectatorSports, - Racetracks, - SportsTeamsAndClubs, - TheaterCompanies, - RecreationalFacilities, - AmusementParksAndArcades, - GamblingFacilitiesAndCasinos, - GolfCoursesAndCountryClubs, - SkiingFacilities, - WellnessAndFitnessServices, - FarmingRanchingForestry, - Farming, - Horticulture, - ForestryAndLogging, - RanchingAndFisheries, - Fisheries, - Ranching, + // Technology & Software + SoftwareDevelopment, + ComputerHardwareManufacturing, + ComputerNetworkingProducts, + ItServicesAndItConsulting, + ComputerAndNetworkSecurity, + Telecommunications, + WirelessServices, + TechnologyInformationAndInternet, + DataInfrastructureAndAnalytics, + InformationServices, + InternetPublishing, + SocialNetworkingPlatforms, + ComputerGames, + MobileGamingApps, + BlockchainServices, + BusinessIntelligencePlatforms, + + // Financial Services FinancialServices, - CapitalMarkets, - InvestmentAdvice, + Banking, + Insurance, InvestmentBanking, - InvestmentManagement, - SecuritiesAndCommodityExchanges, + CapitalMarkets, VentureCapitalAndPrivateEquityPrincipals, - CreditIntermediation, - Banking, - InternationalTradeAndDevelopment, - LoanBrokers, - SavingsInstitutions, + SecuritiesAndCommodityExchanges, FundsAndTrusts, - InsuranceAndEmployeeBenefitFunds, - PensionFunds, - TrustsAndEstates, - Insurance, - ClaimsAdjustingActuarialServices, - InsuranceAgenciesAndBrokerages, - InsuranceCarriers, - GovernmentAdministration, - AdministrationOfJustice, - CorrectionalInstitutions, - CourtsOfLaw, - FireProtection, - LawEnforcement, - PublicSafety, - EconomicPrograms, - TransportationPrograms, - UtilitiesAdministration, - EnvironmentalQualityPrograms, - AirWaterAndWasteProgramManagement, - ConservationPrograms, - HealthAndHumanServices, - EducationAdministrationPrograms, - PublicAssistancePrograms, - PublicHealth, - HousingAndCommunityDevelopment, - CommunityDevelopmentAndUrbanPlanning, - HousingPrograms, - MilitaryAndInternationalAffairs, - ArmedForces, - InternationalAffairs, - PublicPolicyOffices, - ExecutiveOffices, - LegislativeOffices, - SpaceResearchAndTechnology, - HoldingCompanies, - HospitalsAndHealthCare, - CommunityServices, - ServicesForTheElderlyAndDisabled, + + // Healthcare & Medical Hospitals, - ChildDayCareServices, - EmergencyAndReliefServices, - VocationalRehabilitationServices, MedicalPractices, - AlternativeMedicine, - AmbulanceServices, - Chiropractors, - Dentists, - FamilyPlanningCenters, - HomeHealthCareServices, - MedicalAndDiagnosticLaboratories, - MentalHealthCare, - Optometrists, - OutpatientCareCenters, - PhysicalOccupationalAndSpeechTherapists, - Physicians, + MedicalEquipmentManufacturing, + PublicHealth, + VeterinaryServices, + BiotechnologyResearch, + + // Manufacturing Manufacturing, - ApparelManufacturing, - FashionAccessoriesManufacturing, - AppliancesElectricalAndElectronicsManufacturing, - ElectricLightingEquipmentManufacturing, - ElectricalEquipmentManufacturing, - FuelCellManufacturing, - HouseholdApplianceManufacturing, - ChemicalManufacturing, - AgriculturalChemicalManufacturing, - ArtificialRubberAndSyntheticFiberManufacturing, - ChemicalRawMaterialsManufacturing, - PaintCoatingAndAdhesiveManufacturing, - PersonalCareProductManufacturing, - PharmaceuticalManufacturing, - SoapAndCleaningProductManufacturing, - ClimateTechnologyProductManufacturing, ComputersAndElectronicsManufacturing, - CommunicationsEquipmentManufacturing, - ComputerHardwareManufacturing, - AccessibleHardwareManufacturing, - MagneticAndOpticalMediaManufacturing, - MeasuringAndControlInstrumentManufacturing, - SmartMeterManufacturing, SemiconductorManufacturing, - RenewableEnergySemiconductorManufacturing, - FabricatedMetalProducts, - ArchitecturalAndStructuralMetalManufacturing, - BoilersTanksAndShippingContainerManufacturing, - ConstructionHardwareManufacturing, - CutleryAndHandtoolManufacturing, - MetalTreatments, - MetalValveBallAndRollerManufacturing, - SpringAndWireProductManufacturing, - TurnedProductsAndFastenerManufacturing, - FoodAndBeverageManufacturing, - Breweries, - Distilleries, - Wineries, - AnimalFeedManufacturing, - BakedGoodsManufacturing, - BeverageManufacturing, - DairyProductManufacturing, - FruitAndVegetablePreservesManufacturing, - MeatProductsManufacturing, - SeafoodProductManufacturing, - SugarAndConfectioneryProductManufacturing, - FurnitureAndHomeFurnishingsManufacturing, - HouseholdAndInstitutionalFurnitureManufacturing, - MattressAndBlindsManufacturing, - OfficeFurnitureAndFixturesManufacturing, - GlassCeramicsAndConcreteManufacturing, - AbrasivesAndNonmetallicMineralsManufacturing, - ClayAndRefractoryProductsManufacturing, - GlassProductManufacturing, - LimeAndGypsumProductsManufacturing, - LeatherProductManufacturing, - FootwearManufacturing, - WomensHandbagManufacturing, MachineryManufacturing, - AgricultureConstructionMiningMachineryManufacturing, - AutomationMachineryManufacturing, - RobotManufacturing, - CommercialAndServiceIndustryMachineryManufacturing, - EnginesAndPowerTransmissionEquipmentManufacturing, - RenewableEnergyEquipmentManufacturing, - HvacAndRefrigerationEquipmentManufacturing, IndustrialMachineryManufacturing, - MetalworkingMachineryManufacturing, - MedicalEquipmentManufacturing, - OilAndCoalProductManufacturing, - PaperAndForestProductManufacturing, - PlasticsAndRubberProductManufacturing, - PackagingAndContainersManufacturing, - PlasticsManufacturing, - RubberProductsManufacturing, - PrimaryMetalManufacturing, - PrintingServices, - SportingGoodsManufacturing, + FoodAndBeverageManufacturing, TextileManufacturing, - TobaccoManufacturing, - TransportationEquipmentManufacturing, - AviationAndAerospaceComponentManufacturing, - DefenseAndSpaceManufacturing, MotorVehicleManufacturing, - AlternativeFuelVehicleManufacturing, MotorVehiclePartsManufacturing, - RailroadEquipmentManufacturing, - Shipbuilding, + AviationAndAerospaceComponentManufacturing, + DefenseAndSpaceManufacturing, + PlasticsManufacturing, + RubberProductsManufacturing, + PaperAndForestProductManufacturing, WoodProductManufacturing, - OilGasAndMining, - Mining, - CoalMining, - MetalOreMining, - NonmetallicMineralMining, - OilAndGas, - NaturalGasExtraction, - OilExtraction, - ProfessionalServices, - Accounting, - AdvertisingServices, - GovernmentRelationsServices, - PublicRelationsAndCommunicationsServices, - MarketResearch, - ArchitectureAndPlanning, - AccessibleArchitectureAndDesign, - BusinessConsultingAndServices, - EnvironmentalServices, - HumanResourcesServices, - MarketingServices, - OperationsConsulting, - OutsourcingAndOffshoringConsulting, - StrategicManagementServices, - DesignServices, - GraphicDesign, - RegenerativeDesign, - InteriorDesign, - EngineeringServices, - RoboticsEngineering, - SurveyingAndMappingServices, - ItServicesAndItConsulting, - ComputerAndNetworkSecurity, - DigitalAccessibilityServices, - ItSystemCustomSoftwareDevelopment, - ItSystemDataServices, - ItSystemDesignServices, - ItSystemInstallationAndDisposal, - ItSystemOperationsAndMaintenance, - ItSystemTestingAndEvaluation, - ItSystemTrainingAndSupport, - LegalServices, - AlternativeDisputeResolution, - LawPractice, - Photography, - ResearchServices, - BiotechnologyResearch, - NanotechnologyResearch, - ThinkTanks, - ServicesForRenewableEnergy, - VeterinaryServices, - RealEstateAndEquipmentRentalServices, - EquipmentRentalServices, - CommercialAndIndustrialEquipmentRental, - ConsumerGoodsRental, - RealEstate, - RealEstateAgentsAndBrokers, + FurnitureAndHomeFurnishingsManufacturing, + SportingGoodsManufacturing, + PrintingServices, + + // Retail & Consumer Goods Retail, - FoodAndBeverageRetail, RetailGroceries, OnlineAndMailOrderRetail, RetailApparelAndFashion, RetailAppliancesElectricalAndElectronicEquipment, - RetailArtDealers, - RetailArtSupplies, RetailBooksAndPrintedNews, RetailBuildingMaterialsAndGardenEquipment, - RetailFlorists, RetailFurnitureAndHomeFurnishings, - RetailGasoline, RetailHealthAndPersonalCareProducts, - RetailPharmacies, RetailLuxuryGoodsAndJewelry, RetailMotorVehicles, - RetailMusicalInstruments, RetailOfficeEquipment, RetailOfficeSuppliesAndGifts, - RetailRecyclableMaterialsUsedMerchandise, - TechnologyInformationAndMedia, - MediaTelecommunications, - BookAndPeriodicalPublishing, - BookPublishing, - NewspaperPublishing, - PeriodicalPublishing, - BroadcastMediaProductionAndDistribution, - CableAndSatelliteProgramming, - RadioAndTelevisionBroadcasting, - AnimationAndPostProduction, - MediaProduction, - MoviesAndSoundRecording, - SoundRecording, - SheetMusicPublishing, - Telecommunications, - SatelliteTelecommunications, - TelecommunicationsCarriers, - WirelessServices, - TechnologyInformationAndInternet, - DataInfrastructureAndAnalytics, - BlockchainServices, - BusinessIntelligencePlatforms, - ClimateDataAndAnalytics, - InformationServices, - InternetPublishing, - BusinessContent, - InternetNews, - Libraries, - Blogs, - InternetMarketplacePlatforms, - SocialNetworkingPlatforms, - SoftwareDevelopment, - ComputerGames, - MobileGamingApps, - ComputerNetworkingProducts, - DataSecuritySoftwareProducts, - DesktopComputingSoftwareProducts, - EmbeddedSoftwareProducts, - MobileComputingSoftwareProducts, + + // Professional Services + ProfessionalServices, + Accounting, + LegalServices, + LawPractice, + BusinessConsultingAndServices, + StrategicManagementServices, + HumanResourcesServices, + MarketingServices, + AdvertisingServices, + PublicRelationsAndCommunicationsServices, + MarketResearch, + ArchitectureAndPlanning, + DesignServices, + GraphicDesign, + InteriorDesign, + EngineeringServices, + EnvironmentalServices, + ResearchServices, + ThinkTanks, + Photography, + TranslationAndLocalization, + WritingAndEditing, + + // Education + Education, + HigherEducation, + ProfessionalTrainingAndCoaching, + SportsAndRecreationInstruction, + + // Transportation & Logistics TransportationLogisticsSupplyChainAndStorage, AirlinesAndAviation, FreightAndPackageTransportation, - GroundPassengerTransportation, - InterurbanAndRuralBusServices, - SchoolAndEmployeeBusServices, - ShuttlesAndSpecialNeedsTransportationServices, - SightseeingTransportation, - TaxiAndLimousineServices, - UrbanTransitServices, MaritimeTransportation, - PipelineTransportation, - PostalServices, RailTransportation, TruckTransportation, WarehousingAndStorage, + PostalServices, + + // Energy & Utilities Utilities, ElectricPowerGeneration, - FossilFuelElectricPowerGeneration, - NuclearElectricPowerGeneration, RenewableEnergyPowerGeneration, - BiomassElectricPowerGeneration, - GeothermalElectricPowerGeneration, - HydroelectricPowerGeneration, - SolarElectricPowerGeneration, - WindElectricPowerGeneration, - ElectricPowerTransmissionControlAndDistribution, - NaturalGasDistribution, - WaterWasteSteamAndAirConditioningServices, - SteamAndAirConditioningSupply, - WasteCollection, - WasteTreatmentAndDisposal, - WaterSupplyAndIrrigationSystems, + OilAndGas, + Mining, + OilGasAndMining, + + // Media & Entertainment + TechnologyInformationAndMedia, + BroadcastMediaProductionAndDistribution, + RadioAndTelevisionBroadcasting, + MoviesVIdeosAndSound, + MediaProduction, + SoundRecording, + BookAndPeriodicalPublishing, + NewspaperPublishing, + PeriodicalPublishing, + EntertainmentProvIders, + ArtistsAndWriters, + Musicians, + + // Construction & Real Estate + Construction, + CivilEngineering, + RealEstate, + RealEstateAgentsAndBrokers, + + // Hospitality & Services + Hospitality, + HotelsAndMotels, + Restaurants, + FoodAndBeverageServices, + TravelArrangements, + EventsServices, + WellnessAndFitnessServices, + ConsumerServices, + + // Government & Non-Profit + ArmedForces, + GovernmentRelationsServices, + NonProfitOrganizations, + CivicAndSocialOrganizations, + PoliticalOrganizations, + ProfessionalOrganizations, + Fundraising, + + // Wholesale & Distribution Wholesale, - WholesaleAlcoholicBeverages, - WholesaleApparelAndSewingSupplies, - WholesaleAppliancesElectricalAndElectronics, - WholesaleBuildingMaterials, - WholesaleChemicalAndAlliedProducts, + WholesaleImportAndExport, WholesaleComputerEquipment, - WholesaleDrugsAndSundries, WholesaleFoodAndBeverage, - WholesaleFootwear, - WholesaleFurnitureAndHomeFurnishings, - WholesaleHardwarePlumbingHeatingEquipment, - WholesaleImportAndExport, - WholesaleLuxuryGoodsAndJewelry, + WholesaleBuildingMaterials, WholesaleMachinery, - WholesaleMetalsAndMinerals, WholesaleMotorVehiclesAndParts, - WholesalePaperProducts, - WholesalePetroleumAndPetroleumProducts, - WholesalePhotographyEquipmentAndSupplies, - WholesaleRawFarmProducts, - WholesaleRecyclableMaterials, + + // Other Services + StaffingAndRecruiting, + ExecutiveSearchServices, + OfficeAdministration, + SecurityAndInvestigations, + EquipmentRentalServices, + Libraries, ) + +type IndustriesConfig struct { + All util.Set[Id] + // Technology & Software + SoftwareDevelopment Id + ComputerHardwareManufacturing Id + ComputerNetworkingProducts Id + ItServicesAndItConsulting Id + ComputerAndNetworkSecurity Id + Telecommunications Id + WirelessServices Id + TechnologyInformationAndInternet Id + DataInfrastructureAndAnalytics Id + InformationServices Id + InternetPublishing Id + SocialNetworkingPlatforms Id + ComputerGames Id + MobileGamingApps Id + BlockchainServices Id + BusinessIntelligencePlatforms Id + + // Financial Services + FinancialServices Id + Banking Id + Insurance Id + InvestmentBanking Id + CapitalMarkets Id + VentureCapitalAndPrivateEquityPrincipals Id + SecuritiesAndCommodityExchanges Id + FundsAndTrusts Id + + // Healthcare & Medical + Hospitals Id + MedicalPractices Id + MedicalEquipmentManufacturing Id + PublicHealth Id + VeterinaryServices Id + BiotechnologyResearch Id + + // Manufacturing + Manufacturing Id + ComputersAndElectronicsManufacturing Id + SemiconductorManufacturing Id + MachineryManufacturing Id + IndustrialMachineryManufacturing Id + FoodAndBeverageManufacturing Id + TextileManufacturing Id + MotorVehicleManufacturing Id + MotorVehiclePartsManufacturing Id + AviationAndAerospaceComponentManufacturing Id + DefenseAndSpaceManufacturing Id + PlasticsManufacturing Id + RubberProductsManufacturing Id + PaperAndForestProductManufacturing Id + WoodProductManufacturing Id + FurnitureAndHomeFurnishingsManufacturing Id + SportingGoodsManufacturing Id + PrintingServices Id + + // Retail & Consumer Goods + Retail Id + RetailGroceries Id + OnlineAndMailOrderRetail Id + RetailApparelAndFashion Id + RetailAppliancesElectricalAndElectronicEquipment Id + RetailBooksAndPrintedNews Id + RetailBuildingMaterialsAndGardenEquipment Id + RetailFurnitureAndHomeFurnishings Id + RetailHealthAndPersonalCareProducts Id + RetailLuxuryGoodsAndJewelry Id + RetailMotorVehicles Id + RetailOfficeEquipment Id + RetailOfficeSuppliesAndGifts Id + + // Professional Services + ProfessionalServices Id + Accounting Id + LegalServices Id + LawPractice Id + BusinessConsultingAndServices Id + StrategicManagementServices Id + HumanResourcesServices Id + MarketingServices Id + AdvertisingServices Id + PublicRelationsAndCommunicationsServices Id + MarketResearch Id + ArchitectureAndPlanning Id + DesignServices Id + GraphicDesign Id + InteriorDesign Id + EngineeringServices Id + EnvironmentalServices Id + ResearchServices Id + ThinkTanks Id + Photography Id + TranslationAndLocalization Id + WritingAndEditing Id + + // Education + Education Id + HigherEducation Id + ProfessionalTrainingAndCoaching Id + SportsAndRecreationInstruction Id + + // Transportation & Logistics + TransportationLogisticsSupplyChainAndStorage Id + AirlinesAndAviation Id + FreightAndPackageTransportation Id + MaritimeTransportation Id + RailTransportation Id + TruckTransportation Id + WarehousingAndStorage Id + PostalServices Id + + // Energy & Utilities + Utilities Id + ElectricPowerGeneration Id + RenewableEnergyPowerGeneration Id + OilAndGas Id + Mining Id + OilGasAndMining Id + + // Media & Entertainment + TechnologyInformationAndMedia Id + BroadcastMediaProductionAndDistribution Id + RadioAndTelevisionBroadcasting Id + MoviesVIdeosAndSound Id + MediaProduction Id + SoundRecording Id + BookAndPeriodicalPublishing Id + NewspaperPublishing Id + PeriodicalPublishing Id + EntertainmentProvIders Id + ArtistsAndWriters Id + Musicians Id + + // Construction & Real Estate + Construction Id + CivilEngineering Id + RealEstate Id + RealEstateAgentsAndBrokers Id + + // Hospitality & Services + Hospitality Id + HotelsAndMotels Id + Restaurants Id + FoodAndBeverageServices Id + TravelArrangements Id + EventsServices Id + WellnessAndFitnessServices Id + ConsumerServices Id + + // Government & Non-Profit + ArmedForces Id + GovernmentRelationsServices Id + NonProfitOrganizations Id + CivicAndSocialOrganizations Id + PoliticalOrganizations Id + ProfessionalOrganizations Id + Fundraising Id + + // Wholesale & Distribution + Wholesale Id + WholesaleImportAndExport Id + WholesaleComputerEquipment Id + WholesaleFoodAndBeverage Id + WholesaleBuildingMaterials Id + WholesaleMachinery Id + WholesaleMotorVehiclesAndParts Id + + // Other Services + StaffingAndRecruiting Id + ExecutiveSearchServices Id + OfficeAdministration Id + SecurityAndInvestigations Id + EquipmentRentalServices Id + Libraries Id +} + +var Industries = IndustriesConfig{ + All: *All, + // Technology & Software + SoftwareDevelopment: SoftwareDevelopment, + ComputerHardwareManufacturing: ComputerHardwareManufacturing, + ComputerNetworkingProducts: ComputerNetworkingProducts, + ItServicesAndItConsulting: ItServicesAndItConsulting, + ComputerAndNetworkSecurity: ComputerAndNetworkSecurity, + Telecommunications: Telecommunications, + WirelessServices: WirelessServices, + TechnologyInformationAndInternet: TechnologyInformationAndInternet, + DataInfrastructureAndAnalytics: DataInfrastructureAndAnalytics, + InformationServices: InformationServices, + InternetPublishing: InternetPublishing, + SocialNetworkingPlatforms: SocialNetworkingPlatforms, + ComputerGames: ComputerGames, + MobileGamingApps: MobileGamingApps, + BlockchainServices: BlockchainServices, + BusinessIntelligencePlatforms: BusinessIntelligencePlatforms, + + // Financial Services + FinancialServices: FinancialServices, + Banking: Banking, + Insurance: Insurance, + InvestmentBanking: InvestmentBanking, + CapitalMarkets: CapitalMarkets, + VentureCapitalAndPrivateEquityPrincipals: VentureCapitalAndPrivateEquityPrincipals, + SecuritiesAndCommodityExchanges: SecuritiesAndCommodityExchanges, + FundsAndTrusts: FundsAndTrusts, + + // Healthcare & Medical + Hospitals: Hospitals, + MedicalPractices: MedicalPractices, + MedicalEquipmentManufacturing: MedicalEquipmentManufacturing, + PublicHealth: PublicHealth, + VeterinaryServices: VeterinaryServices, + BiotechnologyResearch: BiotechnologyResearch, + + // Manufacturing + Manufacturing: Manufacturing, + ComputersAndElectronicsManufacturing: ComputersAndElectronicsManufacturing, + SemiconductorManufacturing: SemiconductorManufacturing, + MachineryManufacturing: MachineryManufacturing, + IndustrialMachineryManufacturing: IndustrialMachineryManufacturing, + FoodAndBeverageManufacturing: FoodAndBeverageManufacturing, + TextileManufacturing: TextileManufacturing, + MotorVehicleManufacturing: MotorVehicleManufacturing, + MotorVehiclePartsManufacturing: MotorVehiclePartsManufacturing, + AviationAndAerospaceComponentManufacturing: AviationAndAerospaceComponentManufacturing, + DefenseAndSpaceManufacturing: DefenseAndSpaceManufacturing, + PlasticsManufacturing: PlasticsManufacturing, + RubberProductsManufacturing: RubberProductsManufacturing, + PaperAndForestProductManufacturing: PaperAndForestProductManufacturing, + WoodProductManufacturing: WoodProductManufacturing, + FurnitureAndHomeFurnishingsManufacturing: FurnitureAndHomeFurnishingsManufacturing, + SportingGoodsManufacturing: SportingGoodsManufacturing, + PrintingServices: PrintingServices, + + // Retail & Consumer Goods + Retail: Retail, + RetailGroceries: RetailGroceries, + OnlineAndMailOrderRetail: OnlineAndMailOrderRetail, + RetailApparelAndFashion: RetailApparelAndFashion, + RetailAppliancesElectricalAndElectronicEquipment: RetailAppliancesElectricalAndElectronicEquipment, + RetailBooksAndPrintedNews: RetailBooksAndPrintedNews, + RetailBuildingMaterialsAndGardenEquipment: RetailBuildingMaterialsAndGardenEquipment, + RetailFurnitureAndHomeFurnishings: RetailFurnitureAndHomeFurnishings, + RetailHealthAndPersonalCareProducts: RetailHealthAndPersonalCareProducts, + RetailLuxuryGoodsAndJewelry: RetailLuxuryGoodsAndJewelry, + RetailMotorVehicles: RetailMotorVehicles, + RetailOfficeEquipment: RetailOfficeEquipment, + RetailOfficeSuppliesAndGifts: RetailOfficeSuppliesAndGifts, + + // Professional Services + ProfessionalServices: ProfessionalServices, + Accounting: Accounting, + LegalServices: LegalServices, + LawPractice: LawPractice, + BusinessConsultingAndServices: BusinessConsultingAndServices, + StrategicManagementServices: StrategicManagementServices, + HumanResourcesServices: HumanResourcesServices, + MarketingServices: MarketingServices, + AdvertisingServices: AdvertisingServices, + PublicRelationsAndCommunicationsServices: PublicRelationsAndCommunicationsServices, + MarketResearch: MarketResearch, + ArchitectureAndPlanning: ArchitectureAndPlanning, + DesignServices: DesignServices, + GraphicDesign: GraphicDesign, + InteriorDesign: InteriorDesign, + EngineeringServices: EngineeringServices, + EnvironmentalServices: EnvironmentalServices, + ResearchServices: ResearchServices, + ThinkTanks: ThinkTanks, + Photography: Photography, + TranslationAndLocalization: TranslationAndLocalization, + WritingAndEditing: WritingAndEditing, + + // Education + Education: Education, + HigherEducation: HigherEducation, + ProfessionalTrainingAndCoaching: ProfessionalTrainingAndCoaching, + SportsAndRecreationInstruction: SportsAndRecreationInstruction, + + // Transportation & Logistics + TransportationLogisticsSupplyChainAndStorage: TransportationLogisticsSupplyChainAndStorage, + AirlinesAndAviation: AirlinesAndAviation, + FreightAndPackageTransportation: FreightAndPackageTransportation, + MaritimeTransportation: MaritimeTransportation, + RailTransportation: RailTransportation, + TruckTransportation: TruckTransportation, + WarehousingAndStorage: WarehousingAndStorage, + PostalServices: PostalServices, + + // Energy & Utilities + Utilities: Utilities, + ElectricPowerGeneration: ElectricPowerGeneration, + RenewableEnergyPowerGeneration: RenewableEnergyPowerGeneration, + OilAndGas: OilAndGas, + Mining: Mining, + OilGasAndMining: OilGasAndMining, + + // Media & Entertainment + TechnologyInformationAndMedia: TechnologyInformationAndMedia, + BroadcastMediaProductionAndDistribution: BroadcastMediaProductionAndDistribution, + RadioAndTelevisionBroadcasting: RadioAndTelevisionBroadcasting, + MoviesVIdeosAndSound: MoviesVIdeosAndSound, + MediaProduction: MediaProduction, + SoundRecording: SoundRecording, + BookAndPeriodicalPublishing: BookAndPeriodicalPublishing, + NewspaperPublishing: NewspaperPublishing, + PeriodicalPublishing: PeriodicalPublishing, + EntertainmentProvIders: EntertainmentProvIders, + ArtistsAndWriters: ArtistsAndWriters, + Musicians: Musicians, + + // Construction & Real Estate + Construction: Construction, + CivilEngineering: CivilEngineering, + RealEstate: RealEstate, + RealEstateAgentsAndBrokers: RealEstateAgentsAndBrokers, + + // Hospitality & Services + Hospitality: Hospitality, + HotelsAndMotels: HotelsAndMotels, + Restaurants: Restaurants, + FoodAndBeverageServices: FoodAndBeverageServices, + TravelArrangements: TravelArrangements, + EventsServices: EventsServices, + WellnessAndFitnessServices: WellnessAndFitnessServices, + ConsumerServices: ConsumerServices, + + // Government & Non-Profit + ArmedForces: ArmedForces, + GovernmentRelationsServices: GovernmentRelationsServices, + NonProfitOrganizations: NonProfitOrganizations, + CivicAndSocialOrganizations: CivicAndSocialOrganizations, + PoliticalOrganizations: PoliticalOrganizations, + ProfessionalOrganizations: ProfessionalOrganizations, + Fundraising: Fundraising, + + // Wholesale & Distribution + Wholesale: Wholesale, + WholesaleImportAndExport: WholesaleImportAndExport, + WholesaleComputerEquipment: WholesaleComputerEquipment, + WholesaleFoodAndBeverage: WholesaleFoodAndBeverage, + WholesaleBuildingMaterials: WholesaleBuildingMaterials, + WholesaleMachinery: WholesaleMachinery, + WholesaleMotorVehiclesAndParts: WholesaleMotorVehiclesAndParts, + + // Other Services + StaffingAndRecruiting: StaffingAndRecruiting, + ExecutiveSearchServices: ExecutiveSearchServices, + OfficeAdministration: OfficeAdministration, + SecurityAndInvestigations: SecurityAndInvestigations, + EquipmentRentalServices: EquipmentRentalServices, + Libraries: Libraries, +} diff --git a/types/linkedin/linkedin.go b/types/linkedin/linkedin.go new file mode 100644 index 0000000..842e5ac --- /dev/null +++ b/types/linkedin/linkedin.go @@ -0,0 +1,25 @@ +package linkedin + +import ( + "github.com/masa-finance/tee-types/types/linkedin/experiences" + "github.com/masa-finance/tee-types/types/linkedin/functions" + "github.com/masa-finance/tee-types/types/linkedin/industries" + "github.com/masa-finance/tee-types/types/linkedin/profile" + "github.com/masa-finance/tee-types/types/linkedin/seniorities" +) + +type linkedin struct { + Profile *profile.Profile + Seniorities *seniorities.SenioritiesConfig + Experiences *experiences.ExperiencesConfig + Functions *functions.FunctionsConfig + Industries *industries.IndustriesConfig +} + +var LinkedIn = linkedin{ + Profile: &profile.Profile{}, + Seniorities: &seniorities.Seniorities, + Experiences: &experiences.Experiences, + Functions: &functions.Functions, + Industries: &industries.Industries, +} diff --git a/types/linkedin/linkedin_suite_test.go b/types/linkedin/linkedin_suite_test.go new file mode 100644 index 0000000..8f46e3d --- /dev/null +++ b/types/linkedin/linkedin_suite_test.go @@ -0,0 +1,13 @@ +package linkedin_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestTypes(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Types Suite") +} diff --git a/types/linkedin/linkedin_test.go b/types/linkedin/linkedin_test.go new file mode 100644 index 0000000..67776bc --- /dev/null +++ b/types/linkedin/linkedin_test.go @@ -0,0 +1,208 @@ +package linkedin_test + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/masa-finance/tee-types/types" + "github.com/masa-finance/tee-types/types/linkedin/experiences" + "github.com/masa-finance/tee-types/types/linkedin/functions" + "github.com/masa-finance/tee-types/types/linkedin/industries" + "github.com/masa-finance/tee-types/types/linkedin/seniorities" +) + +var _ = Describe("LinkedIn Types", func() { + Describe("LinkedIn Package", func() { + It("should have all required fields", func() { + linkedin := types.LinkedIn + + Expect(linkedin.Profile).ToNot(BeNil()) + Expect(linkedin.Seniorities).ToNot(BeNil()) + Expect(linkedin.Experiences).ToNot(BeNil()) + Expect(linkedin.Functions).ToNot(BeNil()) + Expect(linkedin.Industries).ToNot(BeNil()) + }) + }) + + Describe("Seniorities", func() { + It("should have all seniority levels", func() { + seniorities := types.LinkedIn.Seniorities + + Expect(seniorities.InTraining).To(Equal(seniorities.InTraining)) + Expect(seniorities.EntryLevel).To(Equal(seniorities.EntryLevel)) + Expect(seniorities.Senior).To(Equal(seniorities.Senior)) + Expect(seniorities.Strategic).To(Equal(seniorities.Strategic)) + Expect(seniorities.EntryLevelManager).To(Equal(seniorities.EntryLevelManager)) + Expect(seniorities.ExperiencedManager).To(Equal(seniorities.ExperiencedManager)) + Expect(seniorities.Director).To(Equal(seniorities.Director)) + Expect(seniorities.VicePresident).To(Equal(seniorities.VicePresident)) + Expect(seniorities.CXO).To(Equal(seniorities.CXO)) + Expect(seniorities.Partner).To(Equal(seniorities.Partner)) + }) + + It("should have correct ID values", func() { + Expect(string(types.LinkedIn.Seniorities.InTraining)).To(Equal("100")) + Expect(string(types.LinkedIn.Seniorities.EntryLevel)).To(Equal("110")) + Expect(string(types.LinkedIn.Seniorities.Senior)).To(Equal("120")) + Expect(string(types.LinkedIn.Seniorities.Strategic)).To(Equal("130")) + Expect(string(types.LinkedIn.Seniorities.EntryLevelManager)).To(Equal("200")) + Expect(string(types.LinkedIn.Seniorities.ExperiencedManager)).To(Equal("210")) + Expect(string(types.LinkedIn.Seniorities.Director)).To(Equal("220")) + Expect(string(types.LinkedIn.Seniorities.VicePresident)).To(Equal("300")) + Expect(string(types.LinkedIn.Seniorities.CXO)).To(Equal("310")) + Expect(string(types.LinkedIn.Seniorities.Partner)).To(Equal("320")) + }) + + It("should have All set containing all seniorities", func() { + all := types.LinkedIn.Seniorities.All + + Expect(all.Contains(seniorities.InTraining)).To(BeTrue()) + Expect(all.Contains(seniorities.EntryLevel)).To(BeTrue()) + Expect(all.Contains(seniorities.Senior)).To(BeTrue()) + Expect(all.Contains(seniorities.Strategic)).To(BeTrue()) + Expect(all.Contains(seniorities.EntryLevelManager)).To(BeTrue()) + Expect(all.Contains(seniorities.ExperiencedManager)).To(BeTrue()) + Expect(all.Contains(seniorities.Director)).To(BeTrue()) + Expect(all.Contains(seniorities.VicePresident)).To(BeTrue()) + Expect(all.Contains(seniorities.CXO)).To(BeTrue()) + Expect(all.Contains(seniorities.Partner)).To(BeTrue()) + + Expect(all.Length()).To(Equal(10)) + }) + }) + + Describe("Experiences", func() { + It("should have all experience levels", func() { + experiences := types.LinkedIn.Experiences + + Expect(experiences.LessThanAYear).To(Equal(experiences.LessThanAYear)) + Expect(experiences.OneToTwoYears).To(Equal(experiences.OneToTwoYears)) + Expect(experiences.ThreeToFiveYears).To(Equal(experiences.ThreeToFiveYears)) + Expect(experiences.SixToTenYears).To(Equal(experiences.SixToTenYears)) + Expect(experiences.MoreThanTenYears).To(Equal(experiences.MoreThanTenYears)) + }) + + It("should have correct ID values", func() { + Expect(string(types.LinkedIn.Experiences.LessThanAYear)).To(Equal("1")) + Expect(string(types.LinkedIn.Experiences.OneToTwoYears)).To(Equal("2")) + Expect(string(types.LinkedIn.Experiences.ThreeToFiveYears)).To(Equal("3")) + Expect(string(types.LinkedIn.Experiences.SixToTenYears)).To(Equal("4")) + Expect(string(types.LinkedIn.Experiences.MoreThanTenYears)).To(Equal("5")) + }) + + It("should have All set containing all experiences", func() { + all := types.LinkedIn.Experiences.All + + Expect(all.Contains(experiences.LessThanAYear)).To(BeTrue()) + Expect(all.Contains(experiences.OneToTwoYears)).To(BeTrue()) + Expect(all.Contains(experiences.ThreeToFiveYears)).To(BeTrue()) + Expect(all.Contains(experiences.SixToTenYears)).To(BeTrue()) + Expect(all.Contains(experiences.MoreThanTenYears)).To(BeTrue()) + + Expect(all.Length()).To(Equal(5)) + }) + }) + + Describe("Functions", func() { + It("should have all function types", func() { + functions := types.LinkedIn.Functions + + Expect(functions.Accounting).To(Equal(functions.Accounting)) + Expect(functions.Engineering).To(Equal(functions.Engineering)) + Expect(functions.Marketing).To(Equal(functions.Marketing)) + Expect(functions.Sales).To(Equal(functions.Sales)) + Expect(functions.HumanResources).To(Equal(functions.HumanResources)) + }) + + It("should have correct ID values for key functions", func() { + Expect(string(types.LinkedIn.Functions.Accounting)).To(Equal("1")) + Expect(string(types.LinkedIn.Functions.Engineering)).To(Equal("8")) + Expect(string(types.LinkedIn.Functions.Marketing)).To(Equal("15")) + Expect(string(types.LinkedIn.Functions.Sales)).To(Equal("25")) + Expect(string(types.LinkedIn.Functions.HumanResources)).To(Equal("12")) + }) + + It("should have All set containing all functions", func() { + all := types.LinkedIn.Functions.All + + Expect(all.Contains(functions.Accounting)).To(BeTrue()) + Expect(all.Contains(functions.Engineering)).To(BeTrue()) + Expect(all.Contains(functions.Marketing)).To(BeTrue()) + Expect(all.Contains(functions.Sales)).To(BeTrue()) + Expect(all.Contains(functions.HumanResources)).To(BeTrue()) + Expect(all.Contains(functions.InformationTechnology)).To(BeTrue()) + Expect(all.Contains(functions.Finance)).To(BeTrue()) + + Expect(all.Length()).To(Equal(25)) + }) + }) + + Describe("Industries", func() { + It("should have all industry types", func() { + industries := types.LinkedIn.Industries + + Expect(industries.SoftwareDevelopment).To(Equal(industries.SoftwareDevelopment)) + Expect(industries.FinancialServices).To(Equal(industries.FinancialServices)) + Expect(industries.Manufacturing).To(Equal(industries.Manufacturing)) + Expect(industries.Retail).To(Equal(industries.Retail)) + Expect(industries.Education).To(Equal(industries.Education)) + }) + + It("should have correct ID values for key industries", func() { + Expect(string(types.LinkedIn.Industries.SoftwareDevelopment)).To(Equal("4")) + Expect(string(types.LinkedIn.Industries.FinancialServices)).To(Equal("43")) + Expect(string(types.LinkedIn.Industries.Manufacturing)).To(Equal("25")) + Expect(string(types.LinkedIn.Industries.Retail)).To(Equal("27")) + Expect(string(types.LinkedIn.Industries.Education)).To(Equal("1999")) + }) + + It("should have All set containing all industries", func() { + all := types.LinkedIn.Industries.All + + Expect(all.Contains(industries.SoftwareDevelopment)).To(BeTrue()) + Expect(all.Contains(industries.FinancialServices)).To(BeTrue()) + Expect(all.Contains(industries.Manufacturing)).To(BeTrue()) + Expect(all.Contains(industries.Retail)).To(BeTrue()) + Expect(all.Contains(industries.Education)).To(BeTrue()) + Expect(all.Contains(industries.Hospitals)).To(BeTrue()) + Expect(all.Contains(industries.ProfessionalServices)).To(BeTrue()) + + Expect(all.Length()).To(BeNumerically(">=", 100)) // Should have many industries + }) + + It("should have technology industries", func() { + all := types.LinkedIn.Industries.All + + Expect(all.Contains(industries.SoftwareDevelopment)).To(BeTrue()) + Expect(all.Contains(industries.ComputerHardwareManufacturing)).To(BeTrue()) + Expect(all.Contains(industries.Telecommunications)).To(BeTrue()) + Expect(all.Contains(industries.TechnologyInformationAndInternet)).To(BeTrue()) + }) + + It("should have financial industries", func() { + all := types.LinkedIn.Industries.All + + Expect(all.Contains(industries.FinancialServices)).To(BeTrue()) + Expect(all.Contains(industries.Banking)).To(BeTrue()) + Expect(all.Contains(industries.Insurance)).To(BeTrue()) + Expect(all.Contains(industries.InvestmentBanking)).To(BeTrue()) + }) + }) + + Describe("Type Consistency", func() { + It("should have consistent ID types across all collections", func() { + // All IDs should be string type + Expect(string(types.LinkedIn.Seniorities.InTraining)).To(BeAssignableToTypeOf("")) + Expect(string(types.LinkedIn.Experiences.LessThanAYear)).To(BeAssignableToTypeOf("")) + Expect(string(types.LinkedIn.Functions.Accounting)).To(BeAssignableToTypeOf("")) + Expect(string(types.LinkedIn.Industries.SoftwareDevelopment)).To(BeAssignableToTypeOf("")) + }) + + It("should have non-empty ID values", func() { + Expect(types.LinkedIn.Seniorities.InTraining).ToNot(BeEmpty()) + Expect(types.LinkedIn.Experiences.LessThanAYear).ToNot(BeEmpty()) + Expect(types.LinkedIn.Functions.Accounting).ToNot(BeEmpty()) + Expect(types.LinkedIn.Industries.SoftwareDevelopment).ToNot(BeEmpty()) + }) + }) +}) diff --git a/types/linkedin/seniorities/seniorities.go b/types/linkedin/seniorities/seniorities.go index 7685c99..98e978c 100644 --- a/types/linkedin/seniorities/seniorities.go +++ b/types/linkedin/seniorities/seniorities.go @@ -31,3 +31,31 @@ var All = util.NewSet( CXO, Partner, ) + +type SenioritiesConfig struct { + All util.Set[Id] + InTraining Id + EntryLevel Id + Senior Id + Strategic Id + EntryLevelManager Id + ExperiencedManager Id + Director Id + VicePresident Id + CXO Id + Partner Id +} + +var Seniorities = SenioritiesConfig{ + All: *All, + InTraining: InTraining, + EntryLevel: EntryLevel, + Senior: Senior, + Strategic: Strategic, + EntryLevelManager: EntryLevelManager, + ExperiencedManager: ExperiencedManager, + Director: Director, + VicePresident: VicePresident, + CXO: CXO, + Partner: Partner, +} diff --git a/types/types.go b/types/types.go new file mode 100644 index 0000000..64b43d0 --- /dev/null +++ b/types/types.go @@ -0,0 +1,7 @@ +package types + +import ( + linkedin "github.com/masa-finance/tee-types/types/linkedin" +) + +var LinkedIn = linkedin.LinkedIn From b0e017d049def96a7ae143cf7e071b7b02e0719c Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Wed, 8 Oct 2025 21:00:39 +0200 Subject: [PATCH 05/26] chore: cleanup type tests for linkedin --- types/linkedin/linkedin_test.go | 130 +++++++------------------------- 1 file changed, 29 insertions(+), 101 deletions(-) diff --git a/types/linkedin/linkedin_test.go b/types/linkedin/linkedin_test.go index 67776bc..5b23693 100644 --- a/types/linkedin/linkedin_test.go +++ b/types/linkedin/linkedin_test.go @@ -26,31 +26,18 @@ var _ = Describe("LinkedIn Types", func() { Describe("Seniorities", func() { It("should have all seniority levels", func() { - seniorities := types.LinkedIn.Seniorities - - Expect(seniorities.InTraining).To(Equal(seniorities.InTraining)) - Expect(seniorities.EntryLevel).To(Equal(seniorities.EntryLevel)) - Expect(seniorities.Senior).To(Equal(seniorities.Senior)) - Expect(seniorities.Strategic).To(Equal(seniorities.Strategic)) - Expect(seniorities.EntryLevelManager).To(Equal(seniorities.EntryLevelManager)) - Expect(seniorities.ExperiencedManager).To(Equal(seniorities.ExperiencedManager)) - Expect(seniorities.Director).To(Equal(seniorities.Director)) - Expect(seniorities.VicePresident).To(Equal(seniorities.VicePresident)) - Expect(seniorities.CXO).To(Equal(seniorities.CXO)) - Expect(seniorities.Partner).To(Equal(seniorities.Partner)) - }) + s := types.LinkedIn.Seniorities - It("should have correct ID values", func() { - Expect(string(types.LinkedIn.Seniorities.InTraining)).To(Equal("100")) - Expect(string(types.LinkedIn.Seniorities.EntryLevel)).To(Equal("110")) - Expect(string(types.LinkedIn.Seniorities.Senior)).To(Equal("120")) - Expect(string(types.LinkedIn.Seniorities.Strategic)).To(Equal("130")) - Expect(string(types.LinkedIn.Seniorities.EntryLevelManager)).To(Equal("200")) - Expect(string(types.LinkedIn.Seniorities.ExperiencedManager)).To(Equal("210")) - Expect(string(types.LinkedIn.Seniorities.Director)).To(Equal("220")) - Expect(string(types.LinkedIn.Seniorities.VicePresident)).To(Equal("300")) - Expect(string(types.LinkedIn.Seniorities.CXO)).To(Equal("310")) - Expect(string(types.LinkedIn.Seniorities.Partner)).To(Equal("320")) + Expect(s.InTraining).To(Equal(seniorities.InTraining)) + Expect(s.EntryLevel).To(Equal(seniorities.EntryLevel)) + Expect(s.Senior).To(Equal(seniorities.Senior)) + Expect(s.Strategic).To(Equal(seniorities.Strategic)) + Expect(s.EntryLevelManager).To(Equal(seniorities.EntryLevelManager)) + Expect(s.ExperiencedManager).To(Equal(seniorities.ExperiencedManager)) + Expect(s.Director).To(Equal(seniorities.Director)) + Expect(s.VicePresident).To(Equal(seniorities.VicePresident)) + Expect(s.CXO).To(Equal(seniorities.CXO)) + Expect(s.Partner).To(Equal(seniorities.Partner)) }) It("should have All set containing all seniorities", func() { @@ -73,21 +60,13 @@ var _ = Describe("LinkedIn Types", func() { Describe("Experiences", func() { It("should have all experience levels", func() { - experiences := types.LinkedIn.Experiences - - Expect(experiences.LessThanAYear).To(Equal(experiences.LessThanAYear)) - Expect(experiences.OneToTwoYears).To(Equal(experiences.OneToTwoYears)) - Expect(experiences.ThreeToFiveYears).To(Equal(experiences.ThreeToFiveYears)) - Expect(experiences.SixToTenYears).To(Equal(experiences.SixToTenYears)) - Expect(experiences.MoreThanTenYears).To(Equal(experiences.MoreThanTenYears)) - }) + e := types.LinkedIn.Experiences - It("should have correct ID values", func() { - Expect(string(types.LinkedIn.Experiences.LessThanAYear)).To(Equal("1")) - Expect(string(types.LinkedIn.Experiences.OneToTwoYears)).To(Equal("2")) - Expect(string(types.LinkedIn.Experiences.ThreeToFiveYears)).To(Equal("3")) - Expect(string(types.LinkedIn.Experiences.SixToTenYears)).To(Equal("4")) - Expect(string(types.LinkedIn.Experiences.MoreThanTenYears)).To(Equal("5")) + Expect(e.LessThanAYear).To(Equal(experiences.LessThanAYear)) + Expect(e.OneToTwoYears).To(Equal(experiences.OneToTwoYears)) + Expect(e.ThreeToFiveYears).To(Equal(experiences.ThreeToFiveYears)) + Expect(e.SixToTenYears).To(Equal(experiences.SixToTenYears)) + Expect(e.MoreThanTenYears).To(Equal(experiences.MoreThanTenYears)) }) It("should have All set containing all experiences", func() { @@ -105,21 +84,13 @@ var _ = Describe("LinkedIn Types", func() { Describe("Functions", func() { It("should have all function types", func() { - functions := types.LinkedIn.Functions + f := types.LinkedIn.Functions - Expect(functions.Accounting).To(Equal(functions.Accounting)) - Expect(functions.Engineering).To(Equal(functions.Engineering)) - Expect(functions.Marketing).To(Equal(functions.Marketing)) - Expect(functions.Sales).To(Equal(functions.Sales)) - Expect(functions.HumanResources).To(Equal(functions.HumanResources)) - }) - - It("should have correct ID values for key functions", func() { - Expect(string(types.LinkedIn.Functions.Accounting)).To(Equal("1")) - Expect(string(types.LinkedIn.Functions.Engineering)).To(Equal("8")) - Expect(string(types.LinkedIn.Functions.Marketing)).To(Equal("15")) - Expect(string(types.LinkedIn.Functions.Sales)).To(Equal("25")) - Expect(string(types.LinkedIn.Functions.HumanResources)).To(Equal("12")) + Expect(f.Accounting).To(Equal(functions.Accounting)) + Expect(f.Engineering).To(Equal(functions.Engineering)) + Expect(f.Marketing).To(Equal(functions.Marketing)) + Expect(f.Sales).To(Equal(functions.Sales)) + Expect(f.HumanResources).To(Equal(functions.HumanResources)) }) It("should have All set containing all functions", func() { @@ -139,21 +110,13 @@ var _ = Describe("LinkedIn Types", func() { Describe("Industries", func() { It("should have all industry types", func() { - industries := types.LinkedIn.Industries + i := types.LinkedIn.Industries - Expect(industries.SoftwareDevelopment).To(Equal(industries.SoftwareDevelopment)) - Expect(industries.FinancialServices).To(Equal(industries.FinancialServices)) - Expect(industries.Manufacturing).To(Equal(industries.Manufacturing)) - Expect(industries.Retail).To(Equal(industries.Retail)) - Expect(industries.Education).To(Equal(industries.Education)) - }) - - It("should have correct ID values for key industries", func() { - Expect(string(types.LinkedIn.Industries.SoftwareDevelopment)).To(Equal("4")) - Expect(string(types.LinkedIn.Industries.FinancialServices)).To(Equal("43")) - Expect(string(types.LinkedIn.Industries.Manufacturing)).To(Equal("25")) - Expect(string(types.LinkedIn.Industries.Retail)).To(Equal("27")) - Expect(string(types.LinkedIn.Industries.Education)).To(Equal("1999")) + Expect(i.SoftwareDevelopment).To(Equal(industries.SoftwareDevelopment)) + Expect(i.FinancialServices).To(Equal(industries.FinancialServices)) + Expect(i.Manufacturing).To(Equal(industries.Manufacturing)) + Expect(i.Retail).To(Equal(industries.Retail)) + Expect(i.Education).To(Equal(industries.Education)) }) It("should have All set containing all industries", func() { @@ -169,40 +132,5 @@ var _ = Describe("LinkedIn Types", func() { Expect(all.Length()).To(BeNumerically(">=", 100)) // Should have many industries }) - - It("should have technology industries", func() { - all := types.LinkedIn.Industries.All - - Expect(all.Contains(industries.SoftwareDevelopment)).To(BeTrue()) - Expect(all.Contains(industries.ComputerHardwareManufacturing)).To(BeTrue()) - Expect(all.Contains(industries.Telecommunications)).To(BeTrue()) - Expect(all.Contains(industries.TechnologyInformationAndInternet)).To(BeTrue()) - }) - - It("should have financial industries", func() { - all := types.LinkedIn.Industries.All - - Expect(all.Contains(industries.FinancialServices)).To(BeTrue()) - Expect(all.Contains(industries.Banking)).To(BeTrue()) - Expect(all.Contains(industries.Insurance)).To(BeTrue()) - Expect(all.Contains(industries.InvestmentBanking)).To(BeTrue()) - }) - }) - - Describe("Type Consistency", func() { - It("should have consistent ID types across all collections", func() { - // All IDs should be string type - Expect(string(types.LinkedIn.Seniorities.InTraining)).To(BeAssignableToTypeOf("")) - Expect(string(types.LinkedIn.Experiences.LessThanAYear)).To(BeAssignableToTypeOf("")) - Expect(string(types.LinkedIn.Functions.Accounting)).To(BeAssignableToTypeOf("")) - Expect(string(types.LinkedIn.Industries.SoftwareDevelopment)).To(BeAssignableToTypeOf("")) - }) - - It("should have non-empty ID values", func() { - Expect(types.LinkedIn.Seniorities.InTraining).ToNot(BeEmpty()) - Expect(types.LinkedIn.Experiences.LessThanAYear).ToNot(BeEmpty()) - Expect(types.LinkedIn.Functions.Accounting).ToNot(BeEmpty()) - Expect(types.LinkedIn.Industries.SoftwareDevelopment).ToNot(BeEmpty()) - }) }) }) From 5380e85bbc78309f8036e98a8046e36494e93490 Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Wed, 8 Oct 2025 21:06:40 +0200 Subject: [PATCH 06/26] chore: cleanup errors --- args/linkedin/profile/profile.go | 18 +++++++++--------- args/linkedin/profile/profile_test.go | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index 67443ad..544bbfb 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -14,12 +14,12 @@ import ( ) var ( - ErrScraperModeNotSupported = errors.New("scraper mode not supported") - ErrMaxItemsTooLarge = errors.New("max items must be less than or equal to 100") - ErrYearsOfExperienceNotSupported = errors.New("years of experience not supported") - ErrSeniorityLevelNotSupported = errors.New("seniority level not supported") - ErrFunctionNotSupported = errors.New("function not supported") - ErrIndustryNotSupported = errors.New("industry not supported") + ErrScraperModeNotSupported = errors.New("scraper mode not supported") + ErrMaxItemsTooLarge = errors.New("max items must be less than or equal to 100") + ErrExperienceNotSupported = errors.New("years of experience not supported") + ErrSeniorityNotSupported = errors.New("seniority level not supported") + ErrFunctionNotSupported = errors.New("function not supported") + ErrIndustryNotSupported = errors.New("industry not supported") ) const ( @@ -88,17 +88,17 @@ func (a *Arguments) Validate() error { } for _, yoe := range a.YearsOfExperience { if !experiences.All.Contains(yoe) { - errs = append(errs, fmt.Errorf("%w: %v", ErrYearsOfExperienceNotSupported, yoe)) + errs = append(errs, fmt.Errorf("%w: %v", ErrExperienceNotSupported, yoe)) } } for _, yac := range a.YearsAtCurrentCompany { if !experiences.All.Contains(yac) { - errs = append(errs, fmt.Errorf("%w: %v", ErrYearsOfExperienceNotSupported, yac)) + errs = append(errs, fmt.Errorf("%w: %v", ErrExperienceNotSupported, yac)) } } for _, sl := range a.SeniorityLevels { if !seniorities.All.Contains(sl) { - errs = append(errs, fmt.Errorf("%w: %v", ErrSeniorityLevelNotSupported, sl)) + errs = append(errs, fmt.Errorf("%w: %v", ErrSeniorityNotSupported, sl)) } } for _, f := range a.Functions { diff --git a/args/linkedin/profile/profile_test.go b/args/linkedin/profile/profile_test.go index 3294523..a3b77be 100644 --- a/args/linkedin/profile/profile_test.go +++ b/args/linkedin/profile/profile_test.go @@ -97,7 +97,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { } err := args.Validate() Expect(err).To(HaveOccurred()) - Expect(errors.Is(err, profile.ErrYearsOfExperienceNotSupported)).To(BeTrue()) + Expect(errors.Is(err, profile.ErrExperienceNotSupported)).To(BeTrue()) }) @@ -111,7 +111,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { } err := args.Validate() Expect(err).To(HaveOccurred()) - Expect(errors.Is(err, profile.ErrYearsOfExperienceNotSupported)).To(BeTrue()) + Expect(errors.Is(err, profile.ErrExperienceNotSupported)).To(BeTrue()) }) @@ -125,7 +125,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { } err := args.Validate() Expect(err).To(HaveOccurred()) - Expect(errors.Is(err, profile.ErrSeniorityLevelNotSupported)).To(BeTrue()) + Expect(errors.Is(err, profile.ErrSeniorityNotSupported)).To(BeTrue()) }) It("should fail with invalid function", func() { From 11f7c8668d7da1b88502e0edbc72e7d898c79488 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:07:17 -0700 Subject: [PATCH 07/26] Update args/linkedin/profile/profile.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- args/linkedin/profile/profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index 544bbfb..b022f15 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -35,7 +35,7 @@ type Arguments struct { Query string `json:"searchQuery"` MaxItems uint `json:"maxItems"` Locations []string `json:"locations"` - CurrentComanies []string `json:"currentCompanies"` + CurrentCompanies []string `json:"currentCompanies"` PastCompanies []string `json:"pastCompanies"` CurrentJobTitles []string `json:"currentJobTitles"` PastJobTitles []string `json:"pastJobTitles"` From 79451b22f35e1d5bfa23887a85e12e9cc11ecd0f Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:07:30 -0700 Subject: [PATCH 08/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index 1d74529..254fdea 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -669,7 +669,7 @@ var Industries = IndustriesConfig{ BookAndPeriodicalPublishing: BookAndPeriodicalPublishing, NewspaperPublishing: NewspaperPublishing, PeriodicalPublishing: PeriodicalPublishing, - EntertainmentProvIders: EntertainmentProvIders, + EntertainmentProviders: EntertainmentProviders, ArtistsAndWriters: ArtistsAndWriters, Musicians: Musicians, From 22d86ea6412a306ba5d97ede2ace868fe443d7b0 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:07:40 -0700 Subject: [PATCH 09/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index 254fdea..2945a66 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -663,7 +663,7 @@ var Industries = IndustriesConfig{ TechnologyInformationAndMedia: TechnologyInformationAndMedia, BroadcastMediaProductionAndDistribution: BroadcastMediaProductionAndDistribution, RadioAndTelevisionBroadcasting: RadioAndTelevisionBroadcasting, - MoviesVIdeosAndSound: MoviesVIdeosAndSound, + MoviesVideosAndSound: MoviesVideosAndSound, MediaProduction: MediaProduction, SoundRecording: SoundRecording, BookAndPeriodicalPublishing: BookAndPeriodicalPublishing, From b18850e2e099cee4d97bb8e6a5a1bf09f2ca28c0 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:07:47 -0700 Subject: [PATCH 10/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index 2945a66..c84399d 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -491,7 +491,7 @@ type IndustriesConfig struct { BookAndPeriodicalPublishing Id NewspaperPublishing Id PeriodicalPublishing Id - EntertainmentProvIders Id + EntertainmentProviders Id ArtistsAndWriters Id Musicians Id From 57f80629f2e79a83cea0e89f717c961476b47c51 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:07:54 -0700 Subject: [PATCH 11/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index c84399d..827c790 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -485,7 +485,7 @@ type IndustriesConfig struct { TechnologyInformationAndMedia Id BroadcastMediaProductionAndDistribution Id RadioAndTelevisionBroadcasting Id - MoviesVIdeosAndSound Id + MoviesVideosAndSound Id MediaProduction Id SoundRecording Id BookAndPeriodicalPublishing Id From 7987fef6365c4f919da926d9c4ebc24c2b20b660 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:08:00 -0700 Subject: [PATCH 12/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index 827c790..2697d4a 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -313,7 +313,7 @@ var All = util.NewSet( BookAndPeriodicalPublishing, NewspaperPublishing, PeriodicalPublishing, - EntertainmentProvIders, + EntertainmentProviders, ArtistsAndWriters, Musicians, From b310fbe1c490ff195b69c220f36d984fb537d494 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:08:09 -0700 Subject: [PATCH 13/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index 2697d4a..2ffc094 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -307,7 +307,7 @@ var All = util.NewSet( TechnologyInformationAndMedia, BroadcastMediaProductionAndDistribution, RadioAndTelevisionBroadcasting, - MoviesVIdeosAndSound, + MoviesVideosAndSound, MediaProduction, SoundRecording, BookAndPeriodicalPublishing, From 0f875baddeb0b66863df9830bab12e68ae3749dc Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:08:20 -0700 Subject: [PATCH 14/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index 2ffc094..1e4a3fe 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -136,7 +136,7 @@ const ( BookAndPeriodicalPublishing Id = "82" NewspaperPublishing Id = "81" PeriodicalPublishing Id = "1600" - EntertainmentProvIders Id = "28" + EntertainmentProviders Id = "28" ArtistsAndWriters Id = "38" Musicians Id = "115" From f4ec5a34703b4fd052c73e6e8b2f85b58d648ee7 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:08:28 -0700 Subject: [PATCH 15/26] Update types/linkedin/industries/industries.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/industries/industries.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/industries/industries.go b/types/linkedin/industries/industries.go index 1e4a3fe..772ad9d 100644 --- a/types/linkedin/industries/industries.go +++ b/types/linkedin/industries/industries.go @@ -130,7 +130,7 @@ const ( TechnologyInformationAndMedia Id = "1594" BroadcastMediaProductionAndDistribution Id = "36" RadioAndTelevisionBroadcasting Id = "1633" - MoviesVIdeosAndSound Id = "35" + MoviesVideosAndSound Id = "35" MediaProduction Id = "126" SoundRecording Id = "1623" BookAndPeriodicalPublishing Id = "82" From e2dde58f5c870bb2d6064330c2c659711a5ada37 Mon Sep 17 00:00:00 2001 From: Grant Foster Date: Wed, 8 Oct 2025 12:08:39 -0700 Subject: [PATCH 16/26] Update types/linkedin/profile/profile.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- types/linkedin/profile/profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/profile/profile.go b/types/linkedin/profile/profile.go index a7257ad..8ea9ee6 100644 --- a/types/linkedin/profile/profile.go +++ b/types/linkedin/profile/profile.go @@ -16,7 +16,7 @@ const ( var AllScraperModes = util.NewSet(ScraperModeShort, ScraperModeFull, ScraperModeFullEmail) -// Profile represents a complete profile response +// Profile represents a complete profile response type Profile struct { ID string `json:"id"` PublicIdentifier string `json:"publicIdentifier"` From 743abdd4716cc188adee1e14af389b1fae4e2acf Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Wed, 8 Oct 2025 23:12:10 +0200 Subject: [PATCH 17/26] chore: fix spacing --- args/linkedin/linkedin.go | 1 + args/linkedin/profile/profile.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/args/linkedin/linkedin.go b/args/linkedin/linkedin.go index a213807..6ff612d 100644 --- a/args/linkedin/linkedin.go +++ b/args/linkedin/linkedin.go @@ -4,6 +4,7 @@ import ( "github.com/masa-finance/tee-types/args/linkedin/profile" ) +// TODO: clean this up, you can't surface types in a struct... type linkedin struct { Profile *profile.Arguments } diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index b022f15..93eb346 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -35,7 +35,7 @@ type Arguments struct { Query string `json:"searchQuery"` MaxItems uint `json:"maxItems"` Locations []string `json:"locations"` - CurrentCompanies []string `json:"currentCompanies"` + CurrentCompanies []string `json:"currentCompanies"` PastCompanies []string `json:"pastCompanies"` CurrentJobTitles []string `json:"currentJobTitles"` PastJobTitles []string `json:"pastJobTitles"` From b470b4fbd896956427ced6cd26ba5bcfaded9e4f Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 00:02:48 +0200 Subject: [PATCH 18/26] chore: omit empty --- args/linkedin/profile/profile.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index 93eb346..5fc3f55 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -34,21 +34,21 @@ type Arguments struct { ScraperMode profile.ScraperMode `json:"scraperMode"` Query string `json:"searchQuery"` MaxItems uint `json:"maxItems"` - Locations []string `json:"locations"` + Locations []string `json:"locations,omitempty"` CurrentCompanies []string `json:"currentCompanies"` - PastCompanies []string `json:"pastCompanies"` - CurrentJobTitles []string `json:"currentJobTitles"` - PastJobTitles []string `json:"pastJobTitles"` - Schools []string `json:"schools"` - YearsOfExperience []experiences.Id `json:"yearsOfExperienceIds"` - YearsAtCurrentCompany []experiences.Id `json:"yearsAtCurrentCompanyIds"` - SeniorityLevels []seniorities.Id `json:"seniorityLevelIds"` - Functions []functions.Id `json:"functionIds"` - Industries []industries.Id `json:"industryIds"` - FirstNames []string `json:"firstNames"` - LastNames []string `json:"lastNames"` - RecentlyChangedJobs bool `json:"recentlyChangedJobs"` - StartPage uint `json:"startPage"` + PastCompanies []string `json:"pastCompanies,omitempty"` + CurrentJobTitles []string `json:"currentJobTitles,omitempty"` + PastJobTitles []string `json:"pastJobTitles,omitempty"` + Schools []string `json:"schools,omitempty"` + YearsOfExperience []experiences.Id `json:"yearsOfExperienceIds,omitempty"` + YearsAtCurrentCompany []experiences.Id `json:"yearsAtCurrentCompanyIds,omitempty"` + SeniorityLevels []seniorities.Id `json:"seniorityLevelIds,omitempty"` + Functions []functions.Id `json:"functionIds,omitempty"` + Industries []industries.Id `json:"industryIds,omitempty"` + FirstNames []string `json:"firstNames,omitempty"` + LastNames []string `json:"lastNames,omitempty"` + RecentlyChangedJobs bool `json:"recentlyChangedJobs,omitempty"` + StartPage uint `json:"startPage,omitempty"` } func (a *Arguments) UnmarshalJSON(data []byte) error { From 7ded3bde0729c81adbeec5f05703ee3bd508fcba Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 00:05:45 +0200 Subject: [PATCH 19/26] chore: fix missing omit --- args/linkedin/profile/profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index 5fc3f55..345b768 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -35,7 +35,7 @@ type Arguments struct { Query string `json:"searchQuery"` MaxItems uint `json:"maxItems"` Locations []string `json:"locations,omitempty"` - CurrentCompanies []string `json:"currentCompanies"` + CurrentCompanies []string `json:"currentCompanies,omitempty"` PastCompanies []string `json:"pastCompanies,omitempty"` CurrentJobTitles []string `json:"currentJobTitles,omitempty"` PastJobTitles []string `json:"pastJobTitles,omitempty"` From a6a8a587578331341931d9f231cf679fee05c06a Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 00:35:52 +0200 Subject: [PATCH 20/26] fix: profile marshalling --- types/linkedin/profile/profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/linkedin/profile/profile.go b/types/linkedin/profile/profile.go index 8ea9ee6..4f35ff3 100644 --- a/types/linkedin/profile/profile.go +++ b/types/linkedin/profile/profile.go @@ -20,7 +20,7 @@ var AllScraperModes = util.NewSet(ScraperModeShort, ScraperModeFull, ScraperMode type Profile struct { ID string `json:"id"` PublicIdentifier string `json:"publicIdentifier"` - URL string `json:"Url"` + URL string `json:"linkedinUrl"` FirstName string `json:"firstName"` LastName string `json:"lastName"` Headline string `json:"headline"` From 2fca02a9a185ab32dfdb0a5381cae7104a692ddd Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 01:20:53 +0200 Subject: [PATCH 21/26] chore: update umarshalling for mode --- args/linkedin/profile/profile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index 345b768..47335a3 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -31,7 +31,7 @@ const ( // Arguments defines args for LinkedIn profile operations type Arguments struct { QueryType teetypes.Capability `json:"type"` - ScraperMode profile.ScraperMode `json:"scraperMode"` + ScraperMode profile.ScraperMode `json:"profileScraperMode"` Query string `json:"searchQuery"` MaxItems uint `json:"maxItems"` Locations []string `json:"locations,omitempty"` From d34fe98f53399e13591f0d02c75bbf1335784d16 Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 06:08:53 +0200 Subject: [PATCH 22/26] chore: update profile --- .gitignore | 2 + args/args.go | 5 +- args/linkedin/linkedin.go | 9 +- args/linkedin/profile/profile.go | 2 +- types/linkedin/linkedin.go | 12 +-- types/linkedin/linkedin_test.go | 1 - types/linkedin/profile/profile.go | 163 +++++++++++++++++++++--------- 7 files changed, 130 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index f5f7bd6..cffb9a7 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ go.work # LLM-related files .aider* GEMINI.md + +/examples/*json \ No newline at end of file diff --git a/args/args.go b/args/args.go index c90cb19..f090037 100644 --- a/args/args.go +++ b/args/args.go @@ -4,12 +4,11 @@ import ( "encoding/json" "fmt" - linkedin "github.com/masa-finance/tee-types/args/linkedin" + "github.com/masa-finance/tee-types/args/linkedin" teetypes "github.com/masa-finance/tee-types/types" ) -// LinkedIn is the LinkedIn arguments by type -var LinkedIn = linkedin.LinkedIn +type LinkedInProfileArguments = linkedin.ProfileArguments // QueryTypeArgument provides a minimal structure to extract the QueryType (json "type") // This is used across different job types to determine the specific capability being requested diff --git a/args/linkedin/linkedin.go b/args/linkedin/linkedin.go index 6ff612d..fa8d175 100644 --- a/args/linkedin/linkedin.go +++ b/args/linkedin/linkedin.go @@ -4,11 +4,4 @@ import ( "github.com/masa-finance/tee-types/args/linkedin/profile" ) -// TODO: clean this up, you can't surface types in a struct... -type linkedin struct { - Profile *profile.Arguments -} - -var LinkedIn = linkedin{ - Profile: &profile.Arguments{}, -} +type ProfileArguments = *profile.Arguments diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index 47335a3..205831e 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -25,7 +25,7 @@ var ( const ( DefaultMaxItems = 10 DefaultScraperMode = profile.ScraperModeShort - MaxItems = 100 + MaxItems = 200 // 2500 on the actor, but we will run over 1MB memory limit on responses ) // Arguments defines args for LinkedIn profile operations diff --git a/types/linkedin/linkedin.go b/types/linkedin/linkedin.go index 842e5ac..80e0ff8 100644 --- a/types/linkedin/linkedin.go +++ b/types/linkedin/linkedin.go @@ -8,18 +8,18 @@ import ( "github.com/masa-finance/tee-types/types/linkedin/seniorities" ) -type linkedin struct { - Profile *profile.Profile - Seniorities *seniorities.SenioritiesConfig +type LinkedInConfig struct { Experiences *experiences.ExperiencesConfig + Seniorities *seniorities.SenioritiesConfig Functions *functions.FunctionsConfig Industries *industries.IndustriesConfig } -var LinkedIn = linkedin{ - Profile: &profile.Profile{}, - Seniorities: &seniorities.Seniorities, +var LinkedIn = LinkedInConfig{ Experiences: &experiences.Experiences, + Seniorities: &seniorities.Seniorities, Functions: &functions.Functions, Industries: &industries.Industries, } + +type Profile = *profile.Profile diff --git a/types/linkedin/linkedin_test.go b/types/linkedin/linkedin_test.go index 5b23693..3ce35ae 100644 --- a/types/linkedin/linkedin_test.go +++ b/types/linkedin/linkedin_test.go @@ -16,7 +16,6 @@ var _ = Describe("LinkedIn Types", func() { It("should have all required fields", func() { linkedin := types.LinkedIn - Expect(linkedin.Profile).ToNot(BeNil()) Expect(linkedin.Seniorities).ToNot(BeNil()) Expect(linkedin.Experiences).ToNot(BeNil()) Expect(linkedin.Functions).ToNot(BeNil()) diff --git a/types/linkedin/profile/profile.go b/types/linkedin/profile/profile.go index 4f35ff3..cadaa12 100644 --- a/types/linkedin/profile/profile.go +++ b/types/linkedin/profile/profile.go @@ -18,44 +18,58 @@ var AllScraperModes = util.NewSet(ScraperModeShort, ScraperModeFull, ScraperMode // Profile represents a complete profile response type Profile struct { - ID string `json:"id"` - PublicIdentifier string `json:"publicIdentifier"` - URL string `json:"linkedinUrl"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` - Headline string `json:"headline"` - About string `json:"about"` - OpenToWork bool `json:"openToWork"` - Hiring bool `json:"hiring"` - Photo string `json:"photo"` - Premium bool `json:"premium"` - Influencer bool `json:"influencer"` - Location Location `json:"location"` - Verified bool `json:"verified"` - RegisteredAt time.Time `json:"registeredAt"` - TopSkills string `json:"topSkills"` - ConnectionsCount int `json:"connectionsCount"` - FollowerCount int `json:"followerCount"` - CurrentPosition []CurrentPosition `json:"currentPosition"` - Experience []Experience `json:"experience"` - Education []Education `json:"education"` - Certifications []Certification `json:"certifications"` - Projects []Project `json:"projects"` - Volunteering []Volunteering `json:"volunteering"` - ReceivedRecommendations []any `json:"receivedRecommendations"` // we don't have examples of this data yet... - Skills []Skill `json:"skills"` - Courses []Course `json:"courses"` - Publications []Publication `json:"publications"` - Patents []any `json:"patents"` // we don't have examples of this data yet... - HonorsAndAwards []HonorAndAward `json:"honorsAndAwards"` - Languages []Language `json:"languages"` - Featured any `json:"featured"` // we don't have examples of this data yet... - MoreProfiles []MoreProfile `json:"moreProfiles"` + ID string `json:"id"` + PublicIdentifier string `json:"publicIdentifier"` + URL string `json:"linkedinUrl"` + FirstName string `json:"firstName"` + LastName string `json:"lastName"` + Headline *string `json:"headline,omitempty"` + About *string `json:"about,omitempty"` + Summary *string `json:"summary,omitempty"` + OpenToWork bool `json:"openToWork,omitempty"` + OpenProfile bool `json:"openProfile,omitempty"` + Hiring bool `json:"hiring,omitempty"` + Photo *string `json:"photo,omitempty"` + PictureUrl *string `json:"pictureUrl,omitempty"` + Premium bool `json:"premium,omitempty"` + Influencer bool `json:"influencer,omitempty"` + Location Location `json:"location"` + Verified bool `json:"verified,omitempty"` + RegisteredAt time.Time `json:"registeredAt"` + TopSkills *string `json:"topSkills,omitempty"` + ConnectionsCount int `json:"connectionsCount,omitempty"` + FollowerCount int `json:"followerCount,omitempty"` + ComposeOptionType *string `json:"composeOptionType,omitempty"` + + // Full mode + CurrentPosition []CurrentPosition `json:"currentPosition,omitempty"` + + // Short mode + CurrentPositions []ShortCurrentPosition `json:"currentPositions,omitempty"` + + Experience []Experience `json:"experience,omitempty"` + Education []Education `json:"education,omitempty"` + Certifications []Certification `json:"certifications,omitempty"` + Projects []Project `json:"projects,omitempty"` + Volunteering []Volunteering `json:"volunteering,omitempty"` + ReceivedRecommendations []Recommendation `json:"receivedRecommendations,omitempty"` + Skills []Skill `json:"skills,omitempty"` + Courses []Course `json:"courses,omitempty"` + Publications []Publication `json:"publications,omitempty"` + Patents []Patent `json:"patents,omitempty"` + HonorsAndAwards []HonorAndAward `json:"honorsAndAwards,omitempty"` + Languages []Language `json:"languages,omitempty"` + Featured any `json:"featured,omitempty"` + MoreProfiles []MoreProfile `json:"moreProfiles,omitempty"` + + // Email mode + Emails []string `json:"emails,omitempty"` + CompanyWebsites []CompanyWebsite `json:"companyWebsites,omitempty"` } // Location represents the location information type Location struct { - Text string `json:"Text"` + Text string `json:"linkedinText"` CountryCode string `json:"countryCode"` Parsed ParsedLocation `json:"parsed"` } @@ -73,22 +87,25 @@ type ParsedLocation struct { // CurrentPosition represents current position information type CurrentPosition struct { - CompanyName string `json:"companyName"` + CompanyID *string `json:"companyId,omitempty"` + CompanyLinkedinUrl *string `json:"companyLinkedinUrl,omitempty"` + CompanyName string `json:"companyName"` + DateRange *DatePeriod `json:"dateRange,omitempty"` } // Experience represents work experience type Experience struct { Position string `json:"position"` - Location string `json:"location"` - EmploymentType string `json:"employmentType"` - WorkplaceType *string `json:"workplaceType"` + Location *string `json:"location,omitempty"` + EmploymentType *string `json:"employmentType,omitempty"` + WorkplaceType *string `json:"workplaceType,omitempty"` CompanyName string `json:"companyName"` - CompanyURL string `json:"companyUrl"` - CompanyID string `json:"companyId"` - CompanyUniversalName string `json:"companyUniversalName"` + CompanyURL *string `json:"companyUrl,omitempty"` + CompanyID *string `json:"companyId,omitempty"` + CompanyUniversalName *string `json:"companyUniversalName,omitempty"` Duration string `json:"duration"` - Description string `json:"description"` - Skills []string `json:"skills"` + Description *string `json:"description,omitempty"` + Skills []string `json:"skills,omitempty"` StartDate DateRange `json:"startDate"` EndDate DateRange `json:"endDate"` } @@ -174,7 +191,7 @@ type HonorAndAward struct { // Language represents a language with proficiency level type Language struct { Name string `json:"name"` - Proficiency string `json:"proficiency"` + Proficiency string `json:"proficiency,omitempty"` } // MoreProfile represents a related profile @@ -184,5 +201,61 @@ type MoreProfile struct { LastName string `json:"lastName"` Position *string `json:"position,omitempty"` PublicIdentifier string `json:"publicIdentifier"` - URL string `json:"Url"` + URL string `json:"linkedinUrl"` +} + +// ShortCurrentPosition represents the short profile current positions array +type ShortCurrentPosition struct { + TenureAtPosition *Tenure `json:"tenureAtPosition,omitempty"` + CompanyName string `json:"companyName"` + Title *string `json:"title,omitempty"` + Current *bool `json:"current,omitempty"` + TenureAtCompany *Tenure `json:"tenureAtCompany,omitempty"` + StartedOn *StartedOn `json:"startedOn,omitempty"` + CompanyID *string `json:"companyId,omitempty"` + CompanyLinkedinUrl *string `json:"companyLinkedinUrl,omitempty"` +} + +type Tenure struct { + NumYears *int `json:"numYears,omitempty"` + NumMonths *int `json:"numMonths,omitempty"` +} + +type StartedOn struct { + Month int `json:"month"` + Year int `json:"year"` +} + +// DatePeriod represents a date period with optional start and end parts +type DatePeriod struct { + Start *DateParts `json:"start,omitempty"` + End *DateParts `json:"end,omitempty"` +} + +type DateParts struct { + Month *int `json:"month,omitempty"` + Year *int `json:"year,omitempty"` + Day *int `json:"day,omitempty"` +} + +// CompanyWebsite represents company website with validation hint +type CompanyWebsite struct { + URL string `json:"url"` + Domain string `json:"domain"` + ValidEmailServer *bool `json:"validEmailServer,omitempty"` +} + +// Recommendation captures received recommendations +type Recommendation struct { + GivenBy *string `json:"givenBy,omitempty"` + GivenByLink *string `json:"givenByLink,omitempty"` + GivenAt *string `json:"givenAt,omitempty"` + Description string `json:"description"` +} + +// Patent represents a patent entry +type Patent struct { + Title string `json:"title"` + Number *string `json:"number,omitempty"` + IssuedAt string `json:"issuedAt"` } From fa7ca06f44583cbd50c3002ac286c3c81b666cfd Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 06:12:27 +0200 Subject: [PATCH 23/26] chore: fixes test --- args/linkedin/profile/profile_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/args/linkedin/profile/profile_test.go b/args/linkedin/profile/profile_test.go index a3b77be..73f7523 100644 --- a/args/linkedin/profile/profile_test.go +++ b/args/linkedin/profile/profile_test.go @@ -68,7 +68,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, - MaxItems: 150, + MaxItems: 1500, } err := args.Validate() Expect(err).To(HaveOccurred()) @@ -161,17 +161,17 @@ var _ = Describe("LinkedIn Profile Arguments", func() { QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: "InvalidMode", - MaxItems: 150, + MaxItems: 1500, YearsOfExperience: []experiences.Id{"invalid"}, SeniorityLevels: []seniorities.Id{"invalid"}, } err := args.Validate() Expect(err).To(HaveOccurred()) // Should contain multiple error messages - Expect(err.Error()).To(ContainSubstring("max items must be less than or equal to 100")) - Expect(err.Error()).To(ContainSubstring("scraper mode not supported")) - Expect(err.Error()).To(ContainSubstring("years of experience not supported")) - Expect(err.Error()).To(ContainSubstring("seniority level not supported")) + Expect(errors.Is(err, profile.ErrMaxItemsTooLarge)).To(BeTrue()) + Expect(errors.Is(err, profile.ErrScraperModeNotSupported)).To(BeTrue()) + Expect(errors.Is(err, profile.ErrExperienceNotSupported)).To(BeTrue()) + Expect(errors.Is(err, profile.ErrSeniorityNotSupported)).To(BeTrue()) }) }) From 117a2ffa27550f63da36ed96c56d4952e9ef9eaf Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 06:28:30 +0200 Subject: [PATCH 24/26] fix: max --- args/linkedin/profile/profile.go | 2 +- types/linkedin/profile/profile.go | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/args/linkedin/profile/profile.go b/args/linkedin/profile/profile.go index 205831e..399caa0 100644 --- a/args/linkedin/profile/profile.go +++ b/args/linkedin/profile/profile.go @@ -25,7 +25,7 @@ var ( const ( DefaultMaxItems = 10 DefaultScraperMode = profile.ScraperModeShort - MaxItems = 200 // 2500 on the actor, but we will run over 1MB memory limit on responses + MaxItems = 1000 // 2500 on the actor, but we will run over 1MB memory limit on responses ) // Arguments defines args for LinkedIn profile operations diff --git a/types/linkedin/profile/profile.go b/types/linkedin/profile/profile.go index cadaa12..424c950 100644 --- a/types/linkedin/profile/profile.go +++ b/types/linkedin/profile/profile.go @@ -19,7 +19,7 @@ var AllScraperModes = util.NewSet(ScraperModeShort, ScraperModeFull, ScraperMode // Profile represents a complete profile response type Profile struct { ID string `json:"id"` - PublicIdentifier string `json:"publicIdentifier"` + PublicIdentifier string `json:"publicIdentifier,omitempty"` URL string `json:"linkedinUrl"` FirstName string `json:"firstName"` LastName string `json:"lastName"` @@ -33,9 +33,9 @@ type Profile struct { PictureUrl *string `json:"pictureUrl,omitempty"` Premium bool `json:"premium,omitempty"` Influencer bool `json:"influencer,omitempty"` - Location Location `json:"location"` + Location Location `json:"location,omitempty"` Verified bool `json:"verified,omitempty"` - RegisteredAt time.Time `json:"registeredAt"` + RegisteredAt time.Time `json:"registeredAt,omitempty"` TopSkills *string `json:"topSkills,omitempty"` ConnectionsCount int `json:"connectionsCount,omitempty"` FollowerCount int `json:"followerCount,omitempty"` @@ -70,19 +70,19 @@ type Profile struct { // Location represents the location information type Location struct { Text string `json:"linkedinText"` - CountryCode string `json:"countryCode"` - Parsed ParsedLocation `json:"parsed"` + CountryCode string `json:"countryCode,omitempty"` + Parsed ParsedLocation `json:"parsed,omitempty"` } // ParsedLocation represents the parsed location details type ParsedLocation struct { - Text string `json:"text"` - CountryCode string `json:"countryCode"` - RegionCode *string `json:"regionCode"` - Country string `json:"country"` - CountryFull string `json:"countryFull"` - State string `json:"state"` - City string `json:"city"` + Text string `json:"text,omitempty"` + CountryCode string `json:"countryCode,omitempty"` + RegionCode *string `json:"regionCode,omitempty"` + Country string `json:"country,omitempty"` + CountryFull string `json:"countryFull,omitempty"` + State string `json:"state,omitempty"` + City string `json:"city,omitempty"` } // CurrentPosition represents current position information @@ -200,7 +200,7 @@ type MoreProfile struct { FirstName string `json:"firstName"` LastName string `json:"lastName"` Position *string `json:"position,omitempty"` - PublicIdentifier string `json:"publicIdentifier"` + PublicIdentifier string `json:"publicIdentifier,omitempty"` URL string `json:"linkedinUrl"` } From 6d5812815e461319b58a8083ff63a1a17d8a8763 Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 06:30:43 +0200 Subject: [PATCH 25/26] fix: omitempty --- types/linkedin/profile/profile.go | 100 +++++++++++++++--------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/types/linkedin/profile/profile.go b/types/linkedin/profile/profile.go index 424c950..e74439e 100644 --- a/types/linkedin/profile/profile.go +++ b/types/linkedin/profile/profile.go @@ -119,95 +119,95 @@ type DateRange struct { // Education represents educational background type Education struct { - SchoolName string `json:"schoolName"` - SchoolURL string `json:"schoolUrl"` - Degree string `json:"degree"` - FieldOfStudy *string `json:"fieldOfStudy"` - Skills []string `json:"skills"` - StartDate DateRange `json:"startDate"` - EndDate DateRange `json:"endDate"` - Period string `json:"period"` + SchoolName string `json:"schoolName,omitempty"` + SchoolURL string `json:"schoolUrl,omitempty"` + Degree string `json:"degree,omitempty"` + FieldOfStudy *string `json:"fieldOfStudy,omitempty"` + Skills []string `json:"skills,omitempty"` + StartDate DateRange `json:"startDate,omitempty"` + EndDate DateRange `json:"endDate,omitempty"` + Period string `json:"period,omitempty"` } // Certification represents a certification type Certification struct { - Title string `json:"title"` - IssuedAt string `json:"issuedAt"` - IssuedBy string `json:"issuedBy"` - IssuedByLink string `json:"issuedByLink"` + Title string `json:"title,omitempty"` + IssuedAt string `json:"issuedAt,omitempty"` + IssuedBy string `json:"issuedBy,omitempty"` + IssuedByLink string `json:"issuedByLink,omitempty"` } // Project represents a project type Project struct { - Title string `json:"title"` - Description string `json:"description"` - Duration string `json:"duration"` - StartDate DateRange `json:"startDate"` - EndDate DateRange `json:"endDate"` + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Duration string `json:"duration,omitempty"` + StartDate DateRange `json:"startDate,omitempty"` + EndDate DateRange `json:"endDate,omitempty"` } // Volunteering represents volunteer experience type Volunteering struct { - Role string `json:"role"` - Duration string `json:"duration"` - StartDate *DateRange `json:"startDate"` - EndDate *DateRange `json:"endDate"` - OrganizationName string `json:"organizationName"` - OrganizationURL *string `json:"organizationUrl"` - Cause string `json:"cause"` + Role string `json:"role,omitempty"` + Duration string `json:"duration,omitempty"` + StartDate *DateRange `json:"startDate,omitempty"` + EndDate *DateRange `json:"endDate,omitempty"` + OrganizationName string `json:"organizationName,omitempty"` + OrganizationURL *string `json:"organizationUrl,omitempty"` + Cause string `json:"cause,omitempty"` } // Skill represents a skill with optional positions and endorsements type Skill struct { - Name string `json:"name"` + Name string `json:"name,omitempty"` Positions []string `json:"positions,omitempty"` Endorsements string `json:"endorsements,omitempty"` } // Course represents a course type Course struct { - Title string `json:"title"` - AssociatedWith string `json:"associatedWith"` - AssociatedWithLink string `json:"associatedWithLink"` + Title string `json:"title,omitempty"` + AssociatedWith string `json:"associatedWith,omitempty"` + AssociatedWithLink string `json:"associatedWithLink,omitempty"` } // Publication represents a publication type Publication struct { - Title string `json:"title"` - PublishedAt string `json:"publishedAt"` - Link string `json:"link"` + Title string `json:"title,omitempty"` + PublishedAt string `json:"publishedAt,omitempty"` + Link string `json:"link,omitempty"` } // HonorAndAward represents an honor or award type HonorAndAward struct { - Title string `json:"title"` - IssuedBy string `json:"issuedBy"` - IssuedAt string `json:"issuedAt"` - Description string `json:"description"` - AssociatedWith string `json:"associatedWith"` - AssociatedWithLink string `json:"associatedWithLink"` + Title string `json:"title,omitempty"` + IssuedBy string `json:"issuedBy,omitempty"` + IssuedAt string `json:"issuedAt,omitempty"` + Description string `json:"description,omitempty"` + AssociatedWith string `json:"associatedWith,omitempty"` + AssociatedWithLink string `json:"associatedWithLink,omitempty"` } // Language represents a language with proficiency level type Language struct { - Name string `json:"name"` + Name string `json:"name,omitempty"` Proficiency string `json:"proficiency,omitempty"` } // MoreProfile represents a related profile type MoreProfile struct { - ID string `json:"id"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` + ID string `json:"id,omitempty"` + FirstName string `json:"firstName,omitempty"` + LastName string `json:"lastName,omitempty"` Position *string `json:"position,omitempty"` PublicIdentifier string `json:"publicIdentifier,omitempty"` - URL string `json:"linkedinUrl"` + URL string `json:"linkedinUrl,omitempty"` } // ShortCurrentPosition represents the short profile current positions array type ShortCurrentPosition struct { TenureAtPosition *Tenure `json:"tenureAtPosition,omitempty"` - CompanyName string `json:"companyName"` + CompanyName string `json:"companyName,omitempty"` Title *string `json:"title,omitempty"` Current *bool `json:"current,omitempty"` TenureAtCompany *Tenure `json:"tenureAtCompany,omitempty"` @@ -222,8 +222,8 @@ type Tenure struct { } type StartedOn struct { - Month int `json:"month"` - Year int `json:"year"` + Month int `json:"month,omitempty"` + Year int `json:"year,omitempty"` } // DatePeriod represents a date period with optional start and end parts @@ -240,8 +240,8 @@ type DateParts struct { // CompanyWebsite represents company website with validation hint type CompanyWebsite struct { - URL string `json:"url"` - Domain string `json:"domain"` + URL string `json:"url,omitempty"` + Domain string `json:"domain,omitempty"` ValidEmailServer *bool `json:"validEmailServer,omitempty"` } @@ -250,12 +250,12 @@ type Recommendation struct { GivenBy *string `json:"givenBy,omitempty"` GivenByLink *string `json:"givenByLink,omitempty"` GivenAt *string `json:"givenAt,omitempty"` - Description string `json:"description"` + Description string `json:"description,omitempty"` } // Patent represents a patent entry type Patent struct { - Title string `json:"title"` + Title string `json:"title,omitempty"` Number *string `json:"number,omitempty"` - IssuedAt string `json:"issuedAt"` + IssuedAt string `json:"issuedAt,omitempty"` } From 2f46f903bcb98fc0cdc4137db876ae1220eca38f Mon Sep 17 00:00:00 2001 From: grantdfoster Date: Thu, 9 Oct 2025 06:44:35 +0200 Subject: [PATCH 26/26] chore: cleanup --- args/linkedin/linkedin.go | 2 +- args/linkedin/profile/profile_test.go | 31 ++++++++++++++------------- args/unmarshaller.go | 3 +-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/args/linkedin/linkedin.go b/args/linkedin/linkedin.go index fa8d175..92ed3e7 100644 --- a/args/linkedin/linkedin.go +++ b/args/linkedin/linkedin.go @@ -4,4 +4,4 @@ import ( "github.com/masa-finance/tee-types/args/linkedin/profile" ) -type ProfileArguments = *profile.Arguments +type ProfileArguments = profile.Arguments diff --git a/args/linkedin/profile/profile_test.go b/args/linkedin/profile/profile_test.go index 73f7523..6c9e5de 100644 --- a/args/linkedin/profile/profile_test.go +++ b/args/linkedin/profile/profile_test.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/masa-finance/tee-types/args" "github.com/masa-finance/tee-types/args/linkedin/profile" "github.com/masa-finance/tee-types/types" "github.com/masa-finance/tee-types/types/linkedin/experiences" @@ -19,7 +20,7 @@ import ( var _ = Describe("LinkedIn Profile Arguments", func() { Describe("Marshalling and unmarshalling", func() { It("should set default values", func() { - args := profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", } @@ -32,7 +33,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should override default values", func() { - args := profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", MaxItems: 50, @@ -49,7 +50,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { Describe("Validation", func() { It("should succeed with valid arguments", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -64,7 +65,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with max items too large", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -76,7 +77,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with invalid scraper mode", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: "InvalidMode", @@ -88,7 +89,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with invalid years of experience", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -102,7 +103,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with invalid years at current company", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -116,7 +117,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with invalid seniority level", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -129,7 +130,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with invalid function", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -143,7 +144,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with invalid industry", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -157,7 +158,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should handle multiple validation errors", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: "InvalidMode", @@ -177,7 +178,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { Describe("GetCapability", func() { It("should return the query type", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, } Expect(args.GetCapability()).To(Equal(types.CapSearchByProfile)) @@ -186,7 +187,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { Describe("ValidateForJobType", func() { It("should succeed with valid job type and capability", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -197,7 +198,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail with invalid job type", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByQuery, Query: "software engineer", ScraperMode: profiletypes.ScraperModeShort, @@ -208,7 +209,7 @@ var _ = Describe("LinkedIn Profile Arguments", func() { }) It("should fail if base validation fails", func() { - args := &profile.Arguments{ + args := args.LinkedInProfileArguments{ QueryType: types.CapSearchByProfile, Query: "software engineer", ScraperMode: "InvalidMode", diff --git a/args/unmarshaller.go b/args/unmarshaller.go index 3a68a11..9057885 100644 --- a/args/unmarshaller.go +++ b/args/unmarshaller.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" - linkedinProfile "github.com/masa-finance/tee-types/args/linkedin/profile" "github.com/masa-finance/tee-types/types" ) @@ -131,7 +130,7 @@ func unmarshalLinkedInArguments(jobType types.JobType, args map[string]any) (Job switch minimal.QueryType { case types.CapSearchByProfile: - linkedInArgs := &linkedinProfile.Arguments{} + linkedInArgs := &LinkedInProfileArguments{} if err := unmarshalToStruct(args, linkedInArgs); err != nil { return nil, fmt.Errorf("failed to unmarshal LinkedIn job arguments: %w", err) }