JeanExtreme002 / FlightRadarAPI

:airplane: Unofficial SDK for FlightRadar24 for Python 3 and NodeJS
https://pypi.org/project/FlightRadarAPI/
MIT License
296 stars 60 forks source link

Error Fetching Flight Details & Json does not meet RFC 8259 Standards #36

Closed YesItsTheRealIvoie2006 closed 1 year ago

YesItsTheRealIvoie2006 commented 1 year ago
>>> print(fr().get_flight_details("DL200"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\api.py", line 97, in get_flight_details
    return request.get_content()
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\request.py", line 42, in get_content
    return json.loads(content)
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
>>> print(get_flight_details("DL200"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'get_flight_details' is not defined
>>> print(fr.get_flight_details("DL200"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: FlightRadar24API.get_flight_details() missing 1 required positional argument: 'flight_id'
>>> print(fr.get_flight_details("DL200","DL200"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\api.py", line 97, in get_flight_details
    return request.get_content()
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\request.py", line 42, in get_content
    return json.loads(content)
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
>>> stor=fr.get_flight_details("DL200","DL200")))
  File "<stdin>", line 1
    stor=fr.get_flight_details("DL200","DL200")))
                                               ^
SyntaxError: unmatched ')'
>>> stor=fr.get_flight_details("DL200","DL200"))
  File "<stdin>", line 1
    stor=fr.get_flight_details("DL200","DL200"))
                                               ^
SyntaxError: unmatched ')'
>>> stor=fr.get_flight_details("DL200","DL200")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\api.py", line 97, in get_flight_details
    return request.get_content()
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\request.py", line 42, in get_content
    return json.loads(content)
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
>>> stor=str(fr.get_flight_details("DL200","DL200"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\api.py", line 97, in get_flight_details
    return request.get_content()
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Ivoie\AppData\Roaming\Python\Python311\site-packages\FlightRadar24\request.py", line 42, in get_content
    return json.loads(content)
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
>>>

There is a tempory workround that I have implimented in some of my scripts

for airport in airports:
    nyoomzones=nyoomzones+1
    a=ast.literal_eval(str(airport))
    a=str(a)
    #a=a.replace("'  ",'"  ')
    a=a.replace(": '",': "')
    a=a.replace("{'",'{"')
    a=a.replace("'}",'"}')
    a=a.replace("':",'":')
    a=a.replace("',",'",')
    a=a.replace(", '",', "')
    a=a.replace(": '",': "')
    a=a.replace("\\xa0","")
    # print(a)
    b=json.loads(a)
    # print(f'\n airport #{nyoomzones} of {len(airports)} {b["name"]} , {b["country"]} , (iata code: {b["iata"]} , icao code: {b["icao"]} ) \n location : " longditude : {b["lon"]} latitude : {b["lat"]} altitude : {b["alt"]} " \n ')
    nyoomspot.append(b["name"]) #Airport name
    nyoomno.append(nyoomzones) #airport number
    nyoomcontroler.append(b["country"]) #Airport country
    nyoomiata.append(b["iata"]) #Airport IATA code
    nyoomicao.append(b["icao"]) #Airport ICAO code
    nyoomlat.append(b["lat"]) #Airport latitude x (left , right)
    nyoomlon.append(b["lon"]) #Airport londitude y (forward , back)
    nyoomalt.append(b["alt"]) #Airport Altitude z (up down)

^For fetching airports (was correctly implimented) V For fetching more info on an airport

 nyoominfo = fr_api.get_airport(nyoomicao[f])
    c=ast.literal_eval(str(nyoominfo))
    c=str(c)
    #a=a.replace("'  ",'"  ')
    c=c.replace(": '",': "')
    c=c.replace("{'",'{"')
    c=c.replace("'}",'"}')
    c=c.replace("':",'":')
    c=c.replace("',",'",')
    c=c.replace(", '",', "')
    c=c.replace(": '",': "')
    c=c.replace("\\xa0","")
    c=c.replace("['", '["')
    c=c.replace("']", '"]')
    c=c.replace("None", '"None"')
    c=c.replace("True", 'true')
    c=c.replace("False", 'false')
    c=c.replace("http://", '')
    c=c.replace("https://", '')
    print(c)
    d=json.loads(c)
    #{} {} {} {} {} {} {}
    infoName=d['name']
    infoCode=d['code']
    infoPosition=d['position']
    infoTimezone=d['timezone']
    infoVisible=d['visible']
    infoWebsite=d['website']
    infoStats=d['stats']
    print(f"name : {infoName} \n\n code : {infoCode} \n\n pos : {infoPosition} \n\n timezone : {infoTimezone} \n\n visib : {infoVisible} \n\n webs : {infoWebsite} \n\n stats : {infoStats} ")
    print(f"       Details about Airport #{nyoomno[f]}\n=======================================\nName : {nyoomspot[f]}          Longditude : {nyoomlon[f]}\nCountry : {nyoomcontroler[f]}          Latitude : {nyoomlat[f]}\nA.L.No : {nyoomno[f]}          Altitude : {nyoomalt[f]}\nIATA : {nyoomiata[f]}          ICAO : {nyoomicao[f]}")

   # print(f"Airport information : {nyoominfo} ")
   # print(f"METAR REPORT FROM {nyoomspot} ({nyoomicao[f]}): {gd.Metar(nyoomicao[f]).getAttribute('metar')}\nMORE INFO: https://meteocentre.com/doc/metar.html \n DOI : {gd.Metar(nyoomicao[f]).getAttribute('data_date')} \n Changements : {gd.Metar(nyoomicao[f]).getAttribute('changements')} \n auto : {gd.Metar(nyoomicao[f]).getAttribute('auto')} \n Wind : {gd.Metar(nyoomicao[f]).getAttribute('wind')} \n RVR : {gd.Metar(nyoomicao[f]).getAttribute('rvr')} \n Weather : {gd.Metar(nyoomicao[f]).getAttribute('weather')} \n Cloud : {gd.Metar(nyoomicao[f]).getAttribute('cloud')} \n tempretures : {gd.Metar(nyoomicao[f]).getAttribute('temperatures')} \n qnh : {gd.Metar(nyoomicao[f]).getAttribute('qnh')} \n visibility : {gd.Metar(nyoomicao[f]).getAttribute('visibility')} \n propertys : {gd.Metar(nyoomicao[f]).getAttribute('properties')} \n VMC : {gd.Metar(nyoomicao[f]).getAttribute('vmc')} \n")
    print(f"Generating full report '{nyoomspot[f]} on {stmp}.txt'")
    if (os.path.exists(f"C:/Users/{os.getlogin()}/AIRPORTREPORTS/")==False):
      os.mkdir(f"C:/Users/{os.getlogin()}/AIRPORTREPORTS/") 
    with open(f"C:/Users/{os.getlogin()}/AIRPORTREPORTS/{nyoomspot[f]} on {stmp}.txt","w",encoding="utf-8") as frr:

      frr.write(f"Details about Airport #{nyoomno[f]} + METAR REPORT \n=======================================\nName : {nyoomspot[f]}          Longditude : {nyoomlon[f]}\nCountry : {nyoomcontroler[f]}          Latitude : {nyoomlat[f]}\nA.L.No : {nyoomno[f]}          Altitude : {nyoomalt[f]}\nIATA : {nyoomiata[f]}          ICAO : {nyoomicao[f]}")
      frr.write(f"\nAirport information : {c}")

However I am stonewalled when manually attempting to fetch info on a certain flight For example DL200 which is a flight from Atlanta USA to Gautueng SOUTH AFRICA The so called JSON pharser cannot read the data because it doesnt comply with RFC 8259 , one such issue in the garbaled mess of data is the lack of doubble quotes , and the capitalisation of the first letter of booleans where they should be lowercase. Some values such as None get returned without being quoted with the doubbles , thus throws a missing value error

FOR MORE INFORMATION ON THE JAVA SCRIPT OBJECT NOTATION RFC 8259 STANDARD REFER TO : https://www.rfc-editor.org/rfc/rfc8259

YesItsTheRealIvoie2006 commented 1 year ago

I will be investigating the source code to see if I can narrow down the issue

YesItsTheRealIvoie2006 commented 1 year ago

Core.py seems to be the bad actor here, however It is not your code , its the source, their JSON is not meeting the RFC 8259 standard. However , one can filter the json to correct for the error, see first post, I kindly request that this be implemented, hope to hear from you soon!

JeanExtreme002 commented 1 year ago

Hello @YesItsTheRealIvoie2006 ! Sorry for taking so long to respond to you. I've been (and still am) very busy at my current work, and I haven't had time to understand this problem yet. Could you open a Pull Request please? I will review it as soon as possible.

I appreciate your attention and cooperation!

YesItsTheRealIvoie2006 commented 1 year ago

Hello @JeanExtreme002 ! No worries! I understand the delay. I am at this current moment in time unable to create a PR because there is only one branch , Pull Requests require 2 branches in order to be made. I cannot make a branch as I do not have the permission to do such a thing at this moment in time. The reason PR's require two branches as GitHub states that they need be compared in order to highlight changes between branches.

I kindly ask that you please open up a Development/Beta branch in order to facilitate a PR.

JeanExtreme002 commented 1 year ago

Hi @YesItsTheRealIvoie2006 ! You can fork the branch and open a PR from yours/main to origin/main.

YesItsTheRealIvoie2006 commented 1 year ago

Hello again @JeanExtreme002 , thank you for telling me, I have now created a fork. I am going to make a pr as soon as possible , just need to highlight where the offender is in the code so that there is a diff x3, would upload from my PRJ folder on my laptop but that got wiped due to a freak accident I had with drivers on my system. But hey , we live and learn.

Will comment again soon , - Ivoie

YesItsTheRealIvoie2006 commented 1 year ago

Hey @JeanExtreme002 , me again, created that pull request you wanted! it can be found here: https://github.com/JeanExtreme002/FlightRadarAPI/pull/38 #38 Sincearly - Ivoie

JeanExtreme002 commented 1 year ago

Hi again @YesItsTheRealIvoie2006! I have investigated your code of the issue, and the problem is not the response of flightradar24. You are just passing an invalid flight ID. The flight_id is not the registration of callsign of a flight, but the ID used specifically by flightradar24 website, that you can find by the Flight object's attribute id. Example:

>>> fr_api = FlightRadar24API()
>>> flight = fr_api.get_flights("DAL")[0]
>>> print("The correct flight ID is:", flight.id)
    The correct flight ID is: 30e81a55
>>> details = fr_api.get_flight_details(flight.id)
>>> isinstance(details, dict)  # Checks if it returned details
    True

Anyway, thank you for your attention and patience, and I apologize for the delay in investigating the problem.

I'm closing this issue and the PR #38

JeanExtreme002 commented 1 year ago

To avoid this kind of confusion, get_flight_details() now accepts a Flight instance as argument.