flight_radar 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/flight_radar.gemspec CHANGED
@@ -1,33 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'lib/flight_radar/version'
4
+
3
5
  Gem::Specification.new do |spec|
4
- spec.name = "flight_radar"
5
- spec.version = "0.2.0"
6
- spec.authors = ["Jakub Polak"]
7
- spec.email = ["jakub.polak.vz@gmail.com"]
6
+ spec.name = 'flight_radar'
7
+ spec.version = FlightRadar::VERSION
8
+ spec.authors = ['Jakub Polak']
9
+ spec.email = ['jakub.polak.vz@gmail.com']
8
10
 
9
- spec.summary = "Ruby gem for fetching aircraft data from Flightradar24"
10
- spec.description = "To use this API see more information at: https://www.flightradar24.com/terms-and-conditions"
11
- spec.homepage = "https://github.com/kupolak/flight_radar"
12
- spec.license = "MIT"
13
- spec.required_ruby_version = ">= 2.7.0"
11
+ spec.summary = 'Ruby gem for fetching aircraft data from Flightradar24'
12
+ spec.description = 'Unofficial Ruby wrapper for Flightradar24 API. Fetch real-time flight data, ' \
13
+ 'airport statistics, airline information, and more. For terms see: ' \
14
+ 'https://www.flightradar24.com/terms-and-conditions'
15
+ spec.homepage = 'https://github.com/kupolak/flight_radar'
16
+ spec.license = 'MIT'
17
+ spec.required_ruby_version = '>= 3.2.0'
14
18
 
15
- spec.metadata["homepage_uri"] = spec.homepage
16
- spec.metadata["source_code_uri"] = "https://github.com/kupolak/flight_radar"
17
- spec.metadata["changelog_uri"] = "https://github.com/kupolak/flight_radar/blob/main/CHANGELOG.md"
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = spec.homepage
21
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
22
+ spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
23
+ spec.metadata['documentation_uri'] = 'https://kupolak.github.io/flight_radar/'
18
24
 
19
25
  # Specify which files should be added to the gem when it is released.
20
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
27
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
28
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
23
29
  end
24
- spec.bindir = "exe"
30
+ spec.bindir = 'exe'
25
31
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
26
- spec.require_paths = ["lib"]
32
+ spec.require_paths = ['lib']
27
33
 
28
- spec.add_dependency "httparty", "~> 0.21.0"
34
+ spec.add_dependency 'httparty', '>= 0.21', '< 0.24'
29
35
 
30
- spec.add_development_dependency "rake", "~>13.1.0"
31
- spec.add_development_dependency "rspec", "~>3.12.0"
32
- spec.add_development_dependency "rubocop", "~>1.59.0"
36
+ spec.metadata['rubygems_mfa_required'] = 'true'
33
37
  end
@@ -1,59 +1,64 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # The `Core` module contains constants related to FlightRadar API endpoints,
4
+ # URLs for various data sources, and headers used in HTTP requests.
3
5
  module Core
4
- API_FLIGHT_RADAR_BASE_URL = "https://api.flightradar24.com/common/v1"
5
- CDN_FLIGHT_RADAR_BASE_URL = "https://cdn.flightradar24.com"
6
- FLIGHT_RADAR_BASE_URL = "https://www.flightradar24.com"
7
- DATA_LIVE_BASE_URL = "https://data-live.flightradar24.com"
8
- DATA_CLOUD_BASE_URL = "https://data-cloud.flightradar24.com"
6
+ API_FLIGHT_RADAR_BASE_URL = 'https://api.flightradar24.com/common/v1'
7
+ CDN_FLIGHT_RADAR_BASE_URL = 'https://cdn.flightradar24.com'
8
+ FLIGHT_RADAR_BASE_URL = 'https://www.flightradar24.com'
9
+ DATA_LIVE_BASE_URL = 'https://data-live.flightradar24.com'
10
+ DATA_CLOUD_BASE_URL = 'https://data-cloud.flightradar24.com'
9
11
 
10
12
  # User login URL.
11
- USER_LOGIN_URL = "#{FLIGHT_RADAR_BASE_URL}/user/login"
12
- USER_LOGOUT_URL = "#{FLIGHT_RADAR_BASE_URL}/user/logout"
13
+ USER_LOGIN_URL = "#{FLIGHT_RADAR_BASE_URL}/user/login".freeze
14
+ USER_LOGOUT_URL = "#{FLIGHT_RADAR_BASE_URL}/user/logout".freeze
13
15
 
14
16
  # Most tracked data URL
15
- MOST_TRACKED_URL = "#{FLIGHT_RADAR_BASE_URL}/flights/most-tracked"
17
+ MOST_TRACKED_URL = "#{FLIGHT_RADAR_BASE_URL}/flights/most-tracked".freeze
16
18
 
17
19
  # Search data URL
18
- SEARCH_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/v1/search/web/find?query={}&limit=50"
20
+ SEARCH_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/v1/search/web/find".freeze
19
21
 
20
22
  # Flights data URLs.
21
- REAL_TIME_FLIGHT_TRACKER_DATA_URL = "#{DATA_CLOUD_BASE_URL}/zones/fcgi/feed.js"
22
- FLIGHT_DATA_URL = "#{DATA_LIVE_BASE_URL}/clickhandler/?flight={}"
23
+ REAL_TIME_FLIGHT_TRACKER_DATA_URL = "#{DATA_CLOUD_BASE_URL}/zones/fcgi/feed.js".freeze
24
+ FLIGHT_DATA_URL = "#{DATA_LIVE_BASE_URL}/clickhandler/?flight={}".freeze
25
+ FLIGHT_PLAYBACK_URL = "#{DATA_LIVE_BASE_URL}/clickhandler/".freeze
23
26
 
24
27
  # Airports data URLs.
25
- API_AIRPORT_DATA_URL = "#{API_FLIGHT_RADAR_BASE_URL}/airport.json"
26
- AIRPORT_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/airports/traffic-stats/?airport="
27
- AIRPORTS_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/_json/airports.php"
28
+ API_AIRPORT_DATA_URL = "#{API_FLIGHT_RADAR_BASE_URL}/airport.json".freeze
29
+ AIRPORT_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/airports/traffic-stats/?airport=".freeze
30
+ AIRPORTS_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/_json/airports.php".freeze
31
+ AIRPORT_ARRIVALS_URL = "#{FLIGHT_RADAR_BASE_URL}/data/airports/".freeze
32
+ AIRPORT_DEPARTURES_URL = "#{FLIGHT_RADAR_BASE_URL}/data/airports/".freeze
28
33
 
29
34
  # Airlines data URL.
30
- AIRLINES_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/_json/airlines.php"
35
+ AIRLINES_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/_json/airlines.php".freeze
31
36
 
32
37
  # Zones data URL.
33
- ZONES_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/js/zones.js.php"
38
+ ZONES_DATA_URL = "#{FLIGHT_RADAR_BASE_URL}/js/zones.js.php".freeze
34
39
 
35
40
  # Country flag image URL.
36
- COUNTRY_FLAG_URL = "#{FLIGHT_RADAR_BASE_URL}/static/images/data/flags-small/"
41
+ COUNTRY_FLAG_URL = "#{FLIGHT_RADAR_BASE_URL}/static/images/data/flags-small/".freeze
37
42
 
38
43
  # Airline logo image URL.
39
- AIRLINE_LOGO_URL = "#{CDN_FLIGHT_RADAR_BASE_URL}/assets/airlines/logotypes/"
40
- ALTERNATIVE_AIRLINE_LOGO_URL = "#{FLIGHT_RADAR_BASE_URL}/static/images/data/operators/"
44
+ AIRLINE_LOGO_URL = "#{CDN_FLIGHT_RADAR_BASE_URL}/assets/airlines/logotypes/".freeze
45
+ ALTERNATIVE_AIRLINE_LOGO_URL = "#{FLIGHT_RADAR_BASE_URL}/static/images/data/operators/".freeze
41
46
 
42
47
  HEADERS = {
43
- "accept-encoding": "gzip, br",
44
- "accept-language": "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7",
45
- "cache-control": "max-age=0",
46
- "origin": "#{FLIGHT_RADAR_BASE_URL}",
47
- "referer": "#{FLIGHT_RADAR_BASE_URL}/",
48
- "sec-fetch-dest": "empty",
49
- "sec-fetch-mode": "cors",
50
- "sec-fetch-site": "same-site",
51
- "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
52
- }
53
-
54
- JSON_HEADERS = HEADERS
55
- JSON_HEADERS["accept"] = "application/json"
56
-
57
- IMAGE_HEADERS = HEADERS
58
- IMAGE_HEADERS["accept"] = "image/gif, image/jpg, image/jpeg, image/png"
48
+ 'accept-encoding': 'gzip, br',
49
+ 'accept-language': 'pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7',
50
+ 'cache-control': 'max-age=0',
51
+ origin: FLIGHT_RADAR_BASE_URL.to_s,
52
+ referer: "#{FLIGHT_RADAR_BASE_URL}/",
53
+ 'sec-fetch-dest': 'empty',
54
+ 'sec-fetch-mode': 'cors',
55
+ 'sec-fetch-site': 'same-site',
56
+ 'user-agent': 'Mozilla/5.0 (Windows NT 6.1)
57
+ AppleWebKit/537.36 (KHTML, like Gecko)
58
+ Chrome/87.0.4280.88 Safari/537.36'
59
+ }.freeze
60
+
61
+ JSON_HEADERS = HEADERS.merge('accept' => 'application/json').freeze
62
+
63
+ IMAGE_HEADERS = HEADERS.merge('accept' => 'image/gif, image/jpg, image/jpeg, image/png').freeze
59
64
  end
@@ -1,73 +1,109 @@
1
- # frozen_string_literal: true
2
-
3
- class Flight
4
- @default_text = "N/A"
5
-
6
- attr_accessor :id
7
-
8
- def initialize(flight_id, info)
9
- @id = flight_id
10
- @icao_24bit = get_info(info[0])
11
- @latitude = get_info(info[1])
12
- @longitude = get_info(info[2])
13
- @heading = get_info(info[3])
14
- @altitude = get_info(info[4])
15
- @ground_speed = get_info(info[5])
16
- @squawk = get_info(info[6])
17
- @aircraft_code = get_info(info[8])
18
- @registration = get_info(info[9])
19
- @time = get_info(info[10])
20
- @origin_airport_iata = get_info(info[11])
21
- @destination_airport_iata = get_info(info[12])
22
- @number = get_info(info[13])
23
- @airline_iata = get_info(info[13][0..1])
24
- @on_ground = get_info(info[14])
25
- @vertical_speed = get_info(info[15])
26
- @callsign = get_info(info[16])
27
- @airline_icao = get_info(info[18])
28
- end
29
-
30
- def inspect
31
- to_s
32
- end
33
-
34
- def to_s
35
- "<(#{@aircraft_code}) #{@registration} - Altitude: #{@altitude} - Ground Speed: #{@ground_speed} - Heading: #{@ground_speed}>"
36
- end
37
-
38
- def altitude
39
- "#{@altitude} ft"
40
- end
41
-
42
- def flight_level
43
- if @altitude > 10_000
44
- "#{@altitude[0..2]} FL"
45
- else
46
- altitude
47
- end
48
- end
49
-
50
- def ground_speed
51
- speed = "#{@ground_speed} kt"
52
- speed += "s" if @ground_speed > 1
53
- speed
54
- end
55
-
56
- def heading
57
- "#{@heading}°"
58
- end
59
-
60
- def vertical_speed
61
- "#{@vertical_speed} fpm"
62
- end
63
-
64
- private
65
-
66
- def get_info(info)
67
- if (info || info.zero?) && (info != @default_text)
68
- info
69
- else
70
- @default_text
71
- end
72
- end
73
- end
1
+ # frozen_string_literal: true
2
+
3
+ # The `Flight` class represents information about a flight obtained from a data source.
4
+ # It provides methods to access and format various attributes related to the flight,
5
+ # such as altitude, ground speed, heading, and more.
6
+ class Flight
7
+ DEFAULT_TEXT = 'N/A'
8
+
9
+ # Accessor for the flight ID.
10
+ attr_accessor :id
11
+
12
+ # Read-only accessors for flight attributes.
13
+ attr_reader :icao_24bit, :latitude, :longitude,
14
+ :squawk, :aircraft_code, :registration, :time, :origin_airport_iata,
15
+ :destination_airport_iata, :number, :airline_iata, :on_ground,
16
+ :callsign, :airline_icao
17
+
18
+ # Initializes a new instance of the `Flight` class with the given flight ID and information.
19
+ #
20
+ # @param flight_id [String] The unique identifier for the flight.
21
+ # @param info [Array<String>] An array containing various information about the flight.
22
+ # The order of elements in the array is assumed to follow a specific pattern.
23
+ # (e.g., info[0] is ICAO 24-bit address, info[1] is latitude, info[2] is longitude, and so on.)
24
+ # rubocop:disable Metrics
25
+ def initialize(flight_id, info)
26
+ @id = flight_id
27
+ @icao_24bit = get_info(info[0])
28
+ @latitude = get_info(info[1])
29
+ @longitude = get_info(info[2])
30
+ @heading = get_info(info[3])
31
+ @altitude = get_info(info[4])
32
+ @ground_speed = get_info(info[5])
33
+ @squawk = get_info(info[6])
34
+ @aircraft_code = get_info(info[8])
35
+ @registration = get_info(info[9])
36
+ @time = get_info(info[10])
37
+ @origin_airport_iata = get_info(info[11])
38
+ @destination_airport_iata = get_info(info[12])
39
+ @number = get_info(info[13])
40
+ @airline_iata = @number != DEFAULT_TEXT && @number.length >= 2 ? @number[0..1] : DEFAULT_TEXT
41
+ @on_ground = get_info(info[14])
42
+ @vertical_speed = get_info(info[15])
43
+ @callsign = get_info(info[16])
44
+ @airline_icao = get_info(info[18])
45
+ end
46
+ # rubocop:enable Metrics
47
+
48
+ # Returns a string representation of the `Flight` object.
49
+ #
50
+ # @return [String] A formatted string containing relevant information about the flight.
51
+ def to_s
52
+ "<(#{@aircraft_code}) #{@registration}
53
+ - Altitude: #{@altitude}
54
+ - Ground Speed: #{@ground_speed}
55
+ - Heading: #{@heading}>"
56
+ end
57
+
58
+ # Returns a formatted string representing the altitude of the flight.
59
+ #
60
+ # @return [String] Formatted altitude string (e.g., "5000 ft").
61
+ def altitude
62
+ "#{@altitude} ft"
63
+ end
64
+
65
+ # Returns a formatted string representing the flight level based on altitude.
66
+ #
67
+ # @return [String] Formatted flight level string (e.g., "FL350").
68
+ def flight_level
69
+ return altitude if @altitude == DEFAULT_TEXT || @altitude.to_i <= 10_000
70
+
71
+ "FL#{(@altitude.to_i / 100).to_s.rjust(3, '0')}"
72
+ end
73
+
74
+ # Returns a formatted string representing the ground speed of the flight.
75
+ #
76
+ # @return [String] Formatted ground speed string (e.g., "300 kts").
77
+ def ground_speed
78
+ return "#{@ground_speed} kt" if @ground_speed == DEFAULT_TEXT
79
+
80
+ speed_value = @ground_speed.to_i
81
+ speed = "#{speed_value} kt"
82
+ speed += 's' if speed_value > 1
83
+ speed
84
+ end
85
+
86
+ # Returns a formatted string representing the heading of the flight.
87
+ #
88
+ # @return [String] Formatted heading string (e.g., "120°").
89
+ def heading
90
+ "#{@heading}°"
91
+ end
92
+
93
+ # Returns a formatted string representing the vertical speed of the flight.
94
+ #
95
+ # @return [String] Formatted vertical speed string (e.g., "1000 fpm").
96
+ def vertical_speed
97
+ "#{@vertical_speed} fpm"
98
+ end
99
+
100
+ private
101
+
102
+ # Helper method to ensure that the information is not nil or the default text.
103
+ #
104
+ # @param info [String] The information to be validated.
105
+ # @return [String] The original information if it is not nil or the default text.
106
+ def get_info(info)
107
+ info && info != DEFAULT_TEXT ? info : DEFAULT_TEXT
108
+ end
109
+ end
@@ -1,38 +1,80 @@
1
- # frozen_string_literal: true
2
-
3
- require "httparty"
4
-
5
- # Request class for handling API requests
6
- class Request
7
- def initialize(url, headers = {}, params = {})
8
- @url = url
9
- @params = params
10
- @headers = headers
11
- @lang = "en"
12
-
13
- @response = send_request(url, headers, params)
14
- end
15
-
16
- def content
17
- @response.parsed_response
18
- end
19
-
20
- def content_type
21
- @response.content_type
22
- end
23
-
24
- def status_code
25
- @response.code
26
- end
27
-
28
- private
29
-
30
- def params_to_string(params)
31
- params.to_a.map { |k, v| "#{k}=#{v}" }.join("&")
32
- end
33
-
34
- def send_request(url, headers, params)
35
- url = "#{url}?#{params_to_string(params)}" if params
36
- HTTParty.get(url, headers)
37
- end
38
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+
5
+ # The `Request` class handles making HTTP requests using the HTTParty gem.
6
+ class Request
7
+ # Initializes a new instance of the `Request` class.
8
+ #
9
+ # @param url [String] The URL for the HTTP request.
10
+ # @param headers [Hash] (optional) The headers to include in the HTTP request.
11
+ # @param params [Hash] (optional) The parameters to include in the HTTP request.
12
+ def initialize(url, headers = {}, params = {})
13
+ @url = url
14
+ @params = params
15
+ @headers = headers
16
+ @lang = 'en'
17
+
18
+ @response = send_request(url, headers, params)
19
+ end
20
+
21
+ # Returns the parsed content of the HTTP response.
22
+ #
23
+ # @return [Hash] The parsed content of the HTTP response.
24
+ def content
25
+ @response.parsed_response
26
+ end
27
+
28
+ # Returns the content type of the HTTP response.
29
+ #
30
+ # @return [String] The content type of the HTTP response.
31
+ def content_type
32
+ @response.content_type
33
+ end
34
+
35
+ # Returns the status code of the HTTP response.
36
+ #
37
+ # @return [Integer] The status code of the HTTP response.
38
+ def status_code
39
+ @response.code
40
+ end
41
+
42
+ # Checks if the HTTP response code indicates success.
43
+ #
44
+ # @return [Boolean] Returns true if the response code is within the range 200 to 299 (inclusive), indicating success.
45
+ def success?
46
+ (200..299).include?(@response.code)
47
+ end
48
+
49
+ private
50
+
51
+ # Sends an HTTP GET request using the specified URL, headers, and parameters.
52
+ #
53
+ # @param url [String] The URL for the HTTP request.
54
+ # @param headers [Hash] The headers to include in the HTTP request.
55
+ # @param params [Hash] The parameters to include in the HTTP request.
56
+ # @return [HTTParty::Response] The HTTParty response object.
57
+ def send_request(url, headers, params)
58
+ full_url = build_full_url(url, params)
59
+ HTTParty.get(full_url, headers)
60
+ end
61
+
62
+ # Builds the full URL by appending parameters to the base URL.
63
+ #
64
+ # @param url [String] The base URL.
65
+ # @param params [Hash] The parameters to include in the URL.
66
+ # @return [String] The full URL for the HTTP request.
67
+ def build_full_url(url, params)
68
+ return url unless params
69
+
70
+ "#{url}?#{params_to_string(params)}"
71
+ end
72
+
73
+ # Converts parameters to a query string.
74
+ #
75
+ # @param params [Hash] The parameters to convert.
76
+ # @return [String] The query string representation of the parameters.
77
+ def params_to_string(params)
78
+ HTTParty::HashConversions.to_params(params)
79
+ end
80
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlightRadar
4
+ VERSION = '0.3.0'
5
+ end