| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- //
- // IndeedSearchURLBuilder.swift
- // indeed_ai_job_search
- //
- // Builds regional Indeed /jobs search URLs from SearchCriteria.
- //
- import Foundation
- enum IndeedSearchURLBuilder {
- static func searchURL(
- criteria: SearchCriteria,
- query: String,
- pageIndex: Int = 0,
- pageSize: Int = IndeedSearchPageRequest.defaultPageSize
- ) -> URL {
- let what = whatQuery(criteria: criteria, query: query)
- let whereValue = whereQuery(criteria: criteria)
- let host = regionalHost(for: criteria)
- var components = URLComponents()
- components.scheme = "https"
- components.host = host
- components.path = "/jobs"
- var items: [URLQueryItem] = [
- URLQueryItem(name: "q", value: what),
- URLQueryItem(name: "l", value: whereValue)
- ]
- if criteria.remoteTypes.contains(.remote), criteria.remoteTypes.count == 1 {
- items.append(URLQueryItem(name: "sc", value: "0kf:attr(DSQF7);"))
- }
- let start = max(0, pageIndex) * max(1, pageSize)
- if start > 0 {
- items.append(URLQueryItem(name: "start", value: String(start)))
- }
- components.queryItems = items
- return components.url ?? URL(string: "https://www.indeed.com/jobs")!
- }
- static func whatQuery(criteria: SearchCriteria, query: String) -> String {
- let title = criteria.jobTitle.trimmingCharacters(in: .whitespacesAndNewlines)
- let keywords = criteria.keywords.trimmingCharacters(in: .whitespacesAndNewlines)
- let trimmedQuery = query.trimmingCharacters(in: .whitespacesAndNewlines)
- var parts: [String] = []
- if !title.isEmpty {
- parts.append(criteria.exactPhrase ? "\"\(title)\"" : title)
- } else if !trimmedQuery.isEmpty {
- parts.append(trimmedQuery)
- }
- if !keywords.isEmpty, keywords.caseInsensitiveCompare(title) != .orderedSame,
- keywords.caseInsensitiveCompare(trimmedQuery) != .orderedSame {
- parts.append(keywords)
- }
- let excluded = criteria.excludedKeywords
- .split(separator: " ")
- .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
- .filter { !$0.isEmpty }
- for term in excluded {
- parts.append("-\(term)")
- }
- let joined = parts.joined(separator: " ").trimmingCharacters(in: .whitespacesAndNewlines)
- return joined.isEmpty ? "jobs" : joined
- }
- static func whereQuery(criteria: SearchCriteria) -> String {
- let city = criteria.city.trimmingCharacters(in: .whitespacesAndNewlines)
- let country = criteria.country.trimmingCharacters(in: .whitespacesAndNewlines)
- if criteria.remoteTypes.contains(.remote),
- criteria.remoteTypes.count == 1,
- city.isEmpty {
- return "Remote"
- }
- if !city.isEmpty, !country.isEmpty {
- return "\(city), \(country)"
- }
- if !city.isEmpty { return city }
- if !country.isEmpty { return country }
- return ""
- }
- static func regionalHost(for criteria: SearchCriteria) -> String {
- let haystack = "\(criteria.country) \(criteria.city)".lowercased()
- if haystack.contains("pakistan")
- || haystack.contains("lahore")
- || haystack.contains("karachi")
- || haystack.contains("islamabad") {
- return "pk.indeed.com"
- }
- if haystack.contains("united kingdom")
- || haystack.contains("london")
- || haystack.contains(" england")
- || haystack.hasSuffix(" uk")
- || haystack == "uk" {
- return "uk.indeed.com"
- }
- if haystack.contains("canada")
- || haystack.contains("toronto")
- || haystack.contains("vancouver") {
- return "ca.indeed.com"
- }
- return "www.indeed.com"
- }
- }
|