teecket 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/teecket +10 -0
- data/lib/teecket.rb +28 -0
- data/lib/teecket/air_asia.rb +43 -0
- data/lib/teecket/firefly.rb +75 -0
- data/lib/teecket/flight.rb +15 -0
- data/lib/teecket/malaysia_airlines.rb +43 -0
- data/lib/teecket/malindo_air.rb +60 -0
- data/lib/teecket/printer.rb +11 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2188b057b1c90ca438cd0a9c8d1800fdddd05c2f
|
4
|
+
data.tar.gz: 385db9dad3eccd44072b238b35404303595e64e3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 83801f55ee2aa27350e4da061cffd2398681c56e4f473865c50f83ea903fcb9342e623506c49e8d6394c6941f759ac4ec162e76a0293145e8a66cdb8057092dc
|
7
|
+
data.tar.gz: 03c6c00aa42395bd1cd9f99261675094f3cf5f9e50b9b298c11563c244ae4ecb03259705f228a8f052b06a9d0556bdfbf19382395a13a960a2342fecccc2e381
|
data/bin/teecket
ADDED
data/lib/teecket.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'teecket/flight'
|
2
|
+
require 'teecket/air_asia'
|
3
|
+
require 'teecket/malaysia_airlines'
|
4
|
+
require 'teecket/malindo_air'
|
5
|
+
require 'teecket/printer'
|
6
|
+
require 'teecket/firefly'
|
7
|
+
|
8
|
+
require 'byebug'
|
9
|
+
|
10
|
+
class Teecket
|
11
|
+
def self.search(params)
|
12
|
+
airasia = AirAsia.new({ from: params[:from], to: params[:to], date: params[:date] })
|
13
|
+
airasia.get
|
14
|
+
|
15
|
+
firefly = Firefly.new({ from: params[:from], to: params[:to], date: params[:date] })
|
16
|
+
firefly.get
|
17
|
+
|
18
|
+
mas = MalaysiaAirlines.new({ from: params[:from], to: params[:to], date: params[:date] })
|
19
|
+
mas.get
|
20
|
+
|
21
|
+
malindo = MalindoAir.new({ from: params[:from], to: params[:to], date: params[:date] })
|
22
|
+
malindo.get
|
23
|
+
|
24
|
+
output = airasia.fares + mas.fares + malindo.fares + firefly.fares
|
25
|
+
|
26
|
+
puts Printer.table(output)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class AirAsia < Flight
|
2
|
+
def get
|
3
|
+
uri = URI('https://argon.airasia.com/api/7.0/search')
|
4
|
+
|
5
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
6
|
+
http.use_ssl = true
|
7
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
8
|
+
|
9
|
+
req = Net::HTTP::Post.new(uri.path)
|
10
|
+
req.body = "type=classic&origin=#{from}&destination=#{to}&depart=#{date}&return=&passenger-count=1&child-count=0&infant-count=0¤cy=MYR&days=1"
|
11
|
+
|
12
|
+
res = http.request(req)
|
13
|
+
|
14
|
+
result = JSON.parse(res.body)
|
15
|
+
|
16
|
+
if result['session-id']
|
17
|
+
begin
|
18
|
+
result['depart'][date]['details']['low-fare'].each do |rs|
|
19
|
+
depart_at = DateTime.parse(rs['segments'][0]['departure-datetime'])
|
20
|
+
arrive_at = DateTime.parse(rs['segments'][0]['arrival-datetime'])
|
21
|
+
fare = rs['total']['adult']
|
22
|
+
flight_number = rs['segments'][0]['flight-number']
|
23
|
+
origin = rs['segments'][0]['origincode']
|
24
|
+
destination = rs['segments'][0]['destinationcode']
|
25
|
+
|
26
|
+
depart_at = depart_at.strftime('%I:%M %p')
|
27
|
+
arrive_at = arrive_at.strftime('%I:%M %p')
|
28
|
+
fare = sprintf("%.2f", fare)
|
29
|
+
flight_number = flight_number.gsub(/ /, '')
|
30
|
+
|
31
|
+
fares << { flight_name: 'AirAsia',
|
32
|
+
flight_number: flight_number,
|
33
|
+
origin: origin,
|
34
|
+
destination: destination,
|
35
|
+
depart_at: depart_at,
|
36
|
+
arrive_at: arrive_at,
|
37
|
+
fare: fare }
|
38
|
+
end
|
39
|
+
rescue StandardError
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
class Firefly < Flight
|
4
|
+
def get
|
5
|
+
|
6
|
+
uri = URI('https://m.fireflyz.com.my/')
|
7
|
+
|
8
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
9
|
+
http.use_ssl = true
|
10
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
11
|
+
|
12
|
+
req = Net::HTTP::Get.new(uri.path)
|
13
|
+
|
14
|
+
res = http.request(req)
|
15
|
+
|
16
|
+
cookie = res['Set-Cookie']
|
17
|
+
|
18
|
+
uri = URI('https://m.fireflyz.com.my/Search')
|
19
|
+
|
20
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
21
|
+
http.use_ssl = true
|
22
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
23
|
+
|
24
|
+
req = Net::HTTP::Get.new(uri.path, initheader = { 'Cookie' => cookie})
|
25
|
+
|
26
|
+
cookie = res['Set-Cookie']
|
27
|
+
|
28
|
+
uri = URI('https://m.fireflyz.com.my/Search')
|
29
|
+
|
30
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
31
|
+
http.use_ssl = true
|
32
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
33
|
+
|
34
|
+
req = Net::HTTP::Post.new(uri.path, initheader = { 'Cookie' => cookie})
|
35
|
+
req.body = 'type=2&departure_station=KBR&arrival_station=SZB&departure_date=30%2F06%2F2015&return_date=30%2F06%2F2015&adult=1&infant=0'
|
36
|
+
|
37
|
+
res = http.request(req)
|
38
|
+
|
39
|
+
if res['location']
|
40
|
+
uri = URI(res['location'])
|
41
|
+
|
42
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
43
|
+
http.use_ssl = true
|
44
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
45
|
+
|
46
|
+
req = Net::HTTP::Get.new(uri.path, initheader = { 'Cookie' => cookie})
|
47
|
+
|
48
|
+
res = http.request(req)
|
49
|
+
|
50
|
+
doc = Nokogiri::HTML(res.body)
|
51
|
+
|
52
|
+
doc.css('div.market1').each_with_index do |elem, i|
|
53
|
+
depart_at = doc.css('div.market1')[i].css('div.visible-xs').css('table')[1].css('td')[0].text.strip
|
54
|
+
arrive_at = doc.css('div.market1')[i].css('div.visible-xs').css('table')[1].css('td')[1].text.strip
|
55
|
+
fare = doc.css('div.market1')[i].css('div.visible-xs > div').text.strip
|
56
|
+
flight_number = doc.css('div.market1')[i].css('div.visible-xs').css('table')[0].text.strip
|
57
|
+
origin = doc.css('div.market1')[i]['onclick'].scan(/~[A-Z]{3}~/)[0].gsub('~', '')
|
58
|
+
destination = doc.css('div.market1')[i]['onclick'].scan(/~[A-Z]{3}~/)[1].gsub('~', '')
|
59
|
+
|
60
|
+
depart_at = DateTime.parse("#{date} #{depart_at.gsub(/\t/, '').match(/^(.*?)(AM|PM)/).to_s}").strftime('%I:%M %p')
|
61
|
+
arrive_at = DateTime.parse("#{date} #{arrive_at.gsub(/\t/, '').match(/^(.*?)(AM|PM)/).to_s}").strftime('%I:%M %p')
|
62
|
+
fare = fare.gsub(/ MYR/, '')
|
63
|
+
flight_number = flight_number.gsub(/ /, '').gsub(/FLIGHTNO\./, '')
|
64
|
+
|
65
|
+
fares << { flight_name: 'Firefly',
|
66
|
+
flight_number: flight_number,
|
67
|
+
origin: origin,
|
68
|
+
destination: destination,
|
69
|
+
depart_at: depart_at,
|
70
|
+
arrive_at: arrive_at,
|
71
|
+
fare: fare }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class MalaysiaAirlines < Flight
|
2
|
+
def get
|
3
|
+
new_date = DateTime.parse(date)
|
4
|
+
new_date = new_date.strftime('%Y-%m-%d')
|
5
|
+
|
6
|
+
uri = URI("https://flymh.mobi/TravelAPI/travelapi/shop/1/mh/#{from}/#{to}/1/0/0/Economy/#{new_date}/")
|
7
|
+
|
8
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
9
|
+
http.use_ssl = true
|
10
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
11
|
+
|
12
|
+
req = Net::HTTP::Get.new(uri.path, initHeader = { 'X-apiKey' => '52e6d6d613d3a3e825ac02253fe6b5a4'})
|
13
|
+
|
14
|
+
res = http.request(req)
|
15
|
+
res.body.gsub!(/^fn\(/, '')
|
16
|
+
res.body.gsub!(/\)/, '')
|
17
|
+
|
18
|
+
result = JSON.parse(res.body)
|
19
|
+
|
20
|
+
if result['success']
|
21
|
+
result['outboundOptions'].each do |rs|
|
22
|
+
depart_at = DateTime.parse(rs['flights'][0]['depScheduled'])
|
23
|
+
arrive_at = DateTime.parse(rs['flights'][0]['arrScheduled'])
|
24
|
+
fare = rs['fareDetails']['totalTripFare']
|
25
|
+
flight_number = rs['flights'][0]['marketingAirline'] + rs['flights'][0]['flightNumber']
|
26
|
+
origin = rs['flights'][0]['departureAirport']['code']
|
27
|
+
destination = rs['flights'][0]['arrivalAirport']['code']
|
28
|
+
|
29
|
+
depart_at = depart_at.strftime('%I:%M %p')
|
30
|
+
arrive_at = arrive_at.strftime('%I:%M %p')
|
31
|
+
fare = sprintf("%.2f", fare)
|
32
|
+
|
33
|
+
fares << { flight_name: 'Malaysia Airlines',
|
34
|
+
flight_number: flight_number,
|
35
|
+
origin: origin,
|
36
|
+
destination: destination,
|
37
|
+
depart_at: depart_at,
|
38
|
+
arrive_at: arrive_at,
|
39
|
+
fare: fare }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class MalindoAir < Flight
|
2
|
+
def get
|
3
|
+
new_date = DateTime.parse(date)
|
4
|
+
new_date = new_date.strftime('%Q')
|
5
|
+
|
6
|
+
uri = URI('https://mobileapi.malindoair.com/GQWCF_FlightEngine/GQDPMobileBookingService.svc/InitializeGQService')
|
7
|
+
|
8
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
9
|
+
http.use_ssl = true
|
10
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
11
|
+
|
12
|
+
req = Net::HTTP::Post.new(uri.path, initheader = { 'Content-Type' => 'application/json' })
|
13
|
+
req.body = '{"B2BID":"0","UserLoginId":"0","CustomerUserID":91,"Language":"en-GB","isearchType":"15"}'
|
14
|
+
|
15
|
+
res = http.request(req)
|
16
|
+
key = res['wscContext']
|
17
|
+
|
18
|
+
if key
|
19
|
+
uri = URI('https://mobileapi.malindoair.com/GQWCF_FlightEngine/GQDPMobileBookingService.svc/SearchAirlineFlights')
|
20
|
+
|
21
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
22
|
+
http.use_ssl = true
|
23
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
24
|
+
|
25
|
+
req = Net::HTTP::Post.new(uri.path, initheader = { 'Content-Type' => 'application/json',
|
26
|
+
'WscContext' => key })
|
27
|
+
|
28
|
+
payload = "{\"sd\":{\"Adults\":1,\"AirlineCode\":\"\",\"ArrivalCity\":\"#{to}\",\"ArrivalCityName\":null,\"BookingClass\":null,\"CabinClass\":0,\"ChildAge\":[],\"Children\":0,\"CustomerId\":0,\"CustomerType\":0,\"CustomerUserId\":91,\"DepartureCity\":\"#{from}\",\"DepartureCityName\":null,\"DepartureDate\":\"/Date(#{new_date})/\",\"DepartureDateGap\":0,\"DirectFlightsOnly\":false,\"Infants\":0,\"IsPackageUpsell\":false,\"JourneyType\":1,\"ReturnDate\":\"/Date(-2208988800000)/\",\"ReturnDateGap\":0,\"SearchOption\":1},\"fsc\":\"0\"}"
|
29
|
+
|
30
|
+
req.body = payload
|
31
|
+
|
32
|
+
res = http.request(req)
|
33
|
+
|
34
|
+
result = JSON.parse(res.body)
|
35
|
+
|
36
|
+
if result['SearchAirlineFlightsResult']
|
37
|
+
result['SearchAirlineFlightsResult'].each do |rs|
|
38
|
+
depart_at = rs['DepartureDate']
|
39
|
+
arrive_at = rs['ArrivalDate']
|
40
|
+
fare = rs['FlightAmount']
|
41
|
+
flight_number = rs['MACode'] + rs['FlightNo']
|
42
|
+
origin = rs['DepCity']
|
43
|
+
destination = rs['ArrCity']
|
44
|
+
|
45
|
+
depart_at = DateTime.strptime(depart_at.gsub(/^\/Date\(|\)\//, ''), '%Q').strftime('%I:%M %p')
|
46
|
+
arrive_at = DateTime.strptime(arrive_at.gsub(/^\/Date\(|\)\//, ''), '%Q').strftime('%I:%M %p')
|
47
|
+
fare = sprintf("%.2f", fare)
|
48
|
+
|
49
|
+
fares << { flight_name: 'Malindo Air',
|
50
|
+
flight_number: flight_number,
|
51
|
+
origin: origin,
|
52
|
+
destination: destination,
|
53
|
+
depart_at: depart_at,
|
54
|
+
arrive_at: arrive_at,
|
55
|
+
fare: fare }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'terminal-table'
|
2
|
+
|
3
|
+
class Printer
|
4
|
+
def self.table(rows = [])
|
5
|
+
headings = ['Flight', 'Flight #', 'Origin', 'Destination', 'Depart', 'Arrive', 'Fare (RM)']
|
6
|
+
|
7
|
+
new_rows = rows.map { |row| row.values }
|
8
|
+
|
9
|
+
Terminal::Table.new(headings: headings, rows: new_rows)
|
10
|
+
end
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: teecket
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Amree Zaid
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: terminal-table
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.4.5
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.4'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.4.5
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: nokogiri
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.6'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.6.6.2
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.6'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.6.6.2
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: byebug
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '5.0'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 5.0.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '5.0'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 5.0.0
|
73
|
+
description: Search ticket's fare for all major airlines in Malaysia at once
|
74
|
+
email: mohd.amree@gmail.com
|
75
|
+
executables:
|
76
|
+
- teecket
|
77
|
+
extensions: []
|
78
|
+
extra_rdoc_files: []
|
79
|
+
files:
|
80
|
+
- bin/teecket
|
81
|
+
- lib/teecket.rb
|
82
|
+
- lib/teecket/air_asia.rb
|
83
|
+
- lib/teecket/firefly.rb
|
84
|
+
- lib/teecket/flight.rb
|
85
|
+
- lib/teecket/malaysia_airlines.rb
|
86
|
+
- lib/teecket/malindo_air.rb
|
87
|
+
- lib/teecket/printer.rb
|
88
|
+
homepage: https://github.com/amree/teecket
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata: {}
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 2.2.2
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: Search for flights fare in Malaysia
|
112
|
+
test_files: []
|