module AiLocationContext
Public Instance Methods
Source
# File lib/ai/location_context.rb, line 155 def build_context_lines(question, channel_users: nil, search: Geocoder.method(:search), web_fetch: nil) return [] unless where_is_question?(question) result = lookup( question, channel_users: channel_users, search: search, web_fetch: web_fetch ) subject = result[:subject] return [] if subject.nil? || subject.empty? lines = ["Subject: #{subject}"] if result[:found] case result[:source] when :web lines << "Web lookup: #{result[:text]}" else lines << "Location (#{source_label(result[:source])}): #{result[:label]}" if result[:coords] lat, lon = result[:coords] lines << "Coordinates: #{lat}, #{lon}" end end elsif result[:error] lines << "Location: #{result[:error]}" end lines end
Source
# File lib/ai/location_context.rb, line 18 def extract_subject(question) normalized = AiWhereIsTrigger.parse_question(question.to_s.strip) return nil unless normalized AiWhereIsTrigger.extract_subject(normalized) end
Source
# File lib/ai/location_context.rb, line 25 def find_channel_user(users, nick) target = nick.to_s.strip return nil if target.empty? Array(users).find { |user| user.nick.to_s.casecmp?(target) } end
Source
# File lib/ai/location_context.rb, line 119 def lookup(question, channel_users: nil, search: Geocoder.method(:search), web_fetch: nil) subject = extract_subject(question) return { found: false, subject: nil } if subject.nil? || subject.empty? if subject !~ /\s/ && channel_users nick_result = lookup_nick(channel_users, subject, search: search) return nick_result.merge(subject: subject) if nick_result && nick_result[:found] end if subject.match?(GeoLookup::IPV4) ip_result = lookup_ip(subject, search: search) return ip_result.merge(subject: subject) if ip_result[:found] end place_result = lookup_place(subject, search: search) return place_result.merge(subject: subject) if place_result[:found] web_result = lookup_web(subject, web_fetch: web_fetch) return web_result.merge(subject: subject) if web_result[:found] { found: false, subject: subject } end
Source
# File lib/ai/location_context.rb, line 60 def lookup_ip(ip, search: Geocoder.method(:search)) text = ip.to_s.strip return { found: false } unless text.match?(GeoLookup::IPV4) result = GeoLookup.lookup_ip(text, search: search) return { found: false } unless result { found: true, source: :maxmind, label: GeoLookup.location_label(result), coords: GeoLookup.coordinates_for(result), ip: text } end
Source
# File lib/ai/location_context.rb, line 32 def lookup_nick(users, nick, search: Geocoder.method(:search)) user = find_channel_user(users, nick) return nil unless user host = user.host.to_s ip = GeoLookup.extract_ip(host) unless ip return { found: false, source: :maxmind, error: GeoLookup.host_error(nick: user.nick, host: host) } end result = GeoLookup.lookup_ip(ip, search: search) unless result return { found: false, source: :maxmind, error: "Could not geolocate #{user.nick}" } end { found: true, source: :maxmind, label: GeoLookup.location_label(result), coords: GeoLookup.coordinates_for(result), nick: user.nick } end
Source
# File lib/ai/location_context.rb, line 76 def lookup_place(place, search: Geocoder.method(:search)) result = GeoLookup.lookup_place(place, search: search) return { found: false } unless result { found: true, source: :geocode, label: GeoLookup.location_label(result), coords: GeoLookup.coordinates_for(result) } end
Source
# File lib/ai/location_context.rb, line 88 def lookup_web(subject, web_fetch:) return { found: false } if web_fetch.nil? lookup = web_fetch.call("where is #{subject}") if lookup.is_a?(Hash) return { found: false } unless lookup[:found] text = lookup[:text].to_s.strip return { found: false } if text.empty? return { found: true, source: :web, text: text, query: lookup[:query] || "where is #{subject}" } end text = lookup.to_s.strip return { found: false } if text.empty? { found: true, source: :web, text: text, query: "where is #{subject}" } rescue StandardError { found: false } end
Source
# File lib/ai/location_context.rb, line 142 def source_label(source) case source when :maxmind GeoLookup.ip_source_label when :geocode "geocode" when :web "web" else source.to_s end end
Source
# File lib/ai/location_context.rb, line 14 def where_is_question?(question) !AiWhereIsTrigger.parse_question(question.to_s.strip).nil? end