//import 'package:html'; import 'dart:convert'; import 'dart:developer'; import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:http/http.dart' as http; import 'package:flutter/foundation.dart'; import 'package:jiffy/jiffy.dart'; import 'package:tp5/core/utils.dart'; final lidoapiProvider = Provider((ref) { return LidoApi(); }); class LidoApi { //static const url = "https://tar.lido.aero"; static const url = kIsWeb ? "https://proxy.fares.cyou" : "https://tar.lido.aero"; //static const url = "https://proxy.fares.cyou"; static const realurl = "https://tar.lido.aero"; final timeout = Duration(seconds: 7); LidoApi({this.username = "", this.password = ""}); bool logged = false; String username; String password; String get cookie => "${cookieMap.keys.fold("", (t, e) => (t == "") ? "$e=${cookieMap[e]}" : "$t; $e=${cookieMap[e]}")};SameSite=None; Secure"; Map cookieMap = {}; Map get headers => { "Accept": "application/vnd.lsy.lido.lcb.v1.hal+json", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en", "Connection": "keep-alive", "Content-Type": "application/json;charset=UTF-8", //"Host": Uri.parse(realurl).host, "Origin": Uri.parse(realurl).host, //"sec-ch-ua":'" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"', // "sec-ch-ua-mobile": "?0", // "sec-ch-ua-platform": "Windows", // "Sec-Fetch-Dest": "empty", // "Sec-Fetch-Mode": "cors", // "Sec-Fetch-Site": "same-origin", "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36', "X-lido-applicationId": "lido-lcb", "X-lido-clientId": "lido-lcb-web", "X-lido-customerId": "TAR", "X-lido-operatingAirline": "", "X-lido-timeStamp": DateTime.now().toUtc().toIso8601String(), "X-lido-traceId": "0c497133-2a92-45a0-8ffe-a03c77852201", "cookie": "SERVERID=docker2; $cookie", "X-lido-csrf": cookieMap["lido_csrf"] ?? "", }; Future logout() async { var response = await http.post(Uri.parse('${url}USR/actionLogout.jsp'), body: {"Cookie": cookie}); logged = false; } bool credSaved() { return (Hive.box("profile").get("lido_user", defaultValue: "") != "") && (Hive.box("profile").get("lido_pass", defaultValue: "") != ""); } Future login({String? user, String? pass}) async { username = user ?? Hive.box("profile").get("lido_user", defaultValue: ""); password = pass ?? Hive.box("profile").get("lido_pass", defaultValue: ""); try { var response = await http .get( Uri.parse( '$url/lido/las/login.jsp?DESMON_RESULT_PAGE=$realurl/briefing//'), ) .timeout(timeout); cookieMap.addAll(_getcookies(response.headers["set-cookie"] ?? response.headers["_set-cookie"] ?? "")); //print(response.headers); response = await http.post( Uri.parse('$url/lido/las/dwr/call/plaincall/LoginBean.login.dwr'), body: { "callCount": "1", "nextReverseAjaxIndex": "0", "c0-scriptName": "LoginBean", "c0-methodName": "login", "c0-id": "0", "c0-param0": "string:$username", "c0-param1": "string:$password", "c0-param2": "string:", "c0-param3": "string:LIDO", "c0-param4": "string:en", "batchId": "0", "instanceId": "0", "page": "/lido/las/login.jsp?DESMON_RESULT_PAGE=$realurl/briefing&DESMON_CODE=LAS_002&DESMON_LANG=en", "scriptSessionId": "lSUqDnaTyhevHY6vpNvPdIR~IuUygzP8a2p/kYr1m2p-BgwpWJ4*a" }, headers: {}); cookieMap.addAll(_getcookies(response.headers["set-cookie"] ?? "")); //log("lidoapi: login : $username $password ${response.statusCode} ${response.body}"); final message = RegExp(r'(?<=errorMessage2:")(.+)(?=",)') .firstMatch(response.body) ?.group(0) ?? RegExp(r'(?<=errorMessage1:")(.+)(?=",)') .firstMatch(response.body) ?.group(0); final errorcode = RegExp(r'(?<=errorCode:)(.+?)(?=,)') .firstMatch(response.body) ?.group(0) ?? "xx"; // print(errorcode); final changepass = RegExp(r'(?<=forcePasswdChange:)(.+)(?=,)') .firstMatch(response.body) ?.group(0) == "true"; logged = errorcode == "null"; cookieMap = (!logged) ? {} : cookieMap; // log("api lido 4d login \nuser:$username\npass:$password\nstatuscode${response.statusCode}\nlogged:$logged\nmsg:$message"); log("api lido 4d login errorcode: $errorcode"); //invalide username or password if (errorcode == "LAS_112" && (user == null) && (pass == null)) { await Hive.box("profile").delete("lido_user"); await Hive.box("profile").delete("lido_pass"); await Hive.box("profile").put("lido_user_old", username); await Hive.box("profile").put("lido_pass_old", pass); } return { 'error': logged ? null : message, 'data': {"logged": logged, "message": message}, 'meta': { "changepass": changepass, "user": username, "pass": password, "cookie": cookieMap, "errorcode": errorcode } }; } catch (e) { return { 'error': e.toString(), 'data': {"logged": false}, 'meta': {"user": username, "pass": password, "cookie": null} }; } } Future getDoc(String link, {String? mediaType, bool loginfirst = false}) async { try { if (loginfirst) { final out = await login(); if (!logged) return out; } final murl = link.replaceFirst(realurl, url); var response = await http.get( Uri.parse(murl) // .replace(queryParameters: {}), , headers: {"X-lido-businessId": "ViewBP", ...headers}); // log(response.headers.toString()); Map decodedresponse; print("lidoapi: getdoc: ${response.statusCode} "); // try { // decodedresponse = json.decode(response.body) ?? {}; // } catch (e) { // decodedresponse = { // "body": response.body, // "response": response.statusCode // }; // } //log("lidoapi: getDoc: responsestatus: ${response.body}"); if (!loginfirst && response.statusCode != 200) { return await getDoc(link, mediaType: mediaType, loginfirst: true); } // String? message = decodedresponse["errorsAndWarnings"]?["warnings"]?[0] // ?["message"] ?? // decodedresponse["errorsAndWarnings"]?["errors"]?[0]?["message"] ?? // ((response.statusCode == 200) ? null : "ERR"); // log("lidoapi: getDoc: success: ${decodedresponse["content"]}"); return { 'error': response.statusCode >= 300 ? response.statusCode : null, 'data': response.body, 'meta': {"user": username, "pass": password, "cookie": cookieMap} }; } catch (e) { return {'error': e.toString(), 'data': {}, 'meta': {}}; } } Future list( {Jiffy? start, Jiffy? end, String dep = "", String des = "", String al = "", String fnum = "", bool loginfirst = false}) async { final key = "${start?.format(pattern: "yyyyMMdd_HH_mm") ?? ""} $dep $des $al $fnum"; try { if (loginfirst) { final out = await login(); if (!logged) return out; } final startdate = (start ?? (Jiffy.now().toUtc().subtract(hours: 12))) .millisecondsSinceEpoch; final enddate = (end ?? Jiffy.parseFromMillisecondsSinceEpoch(startdate).add(hours: 48)) .millisecondsSinceEpoch; var response = await http.get( Uri.parse( "$url/lido/lcb/ui/flights?page=0&size=100&startDateTime=1653148128544&endDateTime=1653191328544") .replace(queryParameters: { "page": "0", "size": "1000", "startDateTime": startdate.toString(), "endDateTime": enddate.toString(), ...(al != "" ? {"commAirLine": al} : {}), ...(fnum != "" ? {"flightNumber": fnum} : {}), ...(dep != "" ? {"departure": dep} : {}), ...(des != "" ? {"destination": des} : {}), }), headers: {"X-lido-businessId": "SearchFlights", ...headers}); //log(response.headers.toString()); Map decodedresponse; // print("${response.body}"); try { decodedresponse = json.decode(response.body) ?? {}; } catch (e) { decodedresponse = { "body": response.body, "response": response.statusCode }; } //log("lidoapi: list: responsestatus: ${response.statusCode}"); if (!loginfirst && response.statusCode != 200) { return await list( al: al, fnum: fnum, dep: dep, des: des, start: start, end: end, loginfirst: true); } String? message = decodedresponse["errorsAndWarnings"]?["warnings"]?[0] ?["message"] ?? decodedresponse["errorsAndWarnings"]?["errors"]?[0]?["message"] ?? ((response.statusCode == 200) ? null : "ERR"); // log("lidoapi: list: success: ${decodedresponse["content"]}"); Map res = { 'error': message, 'data': (message == null) ? decodedresponse["content"] : null, 'meta': { "legs": (decodedresponse["totalElements"] ?? 0) > 0 ? decodedresponse["content"].fold([], (t, e) { t.add(e["leg"]["legidentifier"]); return t; }) : [], "user": username, "pass": password, "nb": decodedresponse["totalElements"] ?? 0, "cookie": cookieMap } }; // cache response if success Hive.box("lido").put(key, json.encode(res)); return res; } catch (e) { print("lidoapi: list:"); final res = { 'error': e.toString(), 'data': {}, 'meta': {}, 'cache': json.decode(Hive.box("lido").get(key, defaultValue: "{}")) }; return res; } } Future ofp( {required String legid, String? brieflink, bool loginfirst = false}) async { try { if (loginfirst) { final out = await login(); if (!logged) return out; } // brieflink = res["data"]?[0]?["_links"]?["self"]?["href"]; // legid = res["data"]?[0]?["leg"]?["legidentifier"]; brieflink = brieflink ?? "$url/lido/lcb/ui/$legid/briefing"; var response = await http.put(Uri.parse(brieflink), headers: { "X-lido-businessId": 'SearchBP', ...headers, }, //body: json.encode(({"commercialAirline": al,"flightNumber": fnum,"operationalSuffix": "","date": dateoforigin.toString() body: json.encode(({ "categories": [ "OFP", "IWFR", "ATS", "DISP", "NOTAM", "SIGWXROUTE", "VERTPROF", "CREWINFO", "UAD", "RAIM", "VAATCA", "CDA", "DISMAP", "DMS", "ABD", "OFPDLK", "TLR", // "OFP", // "NOTAM", // // "APTDXML", // "SOFP", // "CDA", // "RADAR", // "OFPDLK", // // "ATSXML", // // "REGWXXML", // "WXSIGWX", // "SIGWXROUTE", // "VAATCA", // // "ASPDXML", // // "NOTAMXML", // "OTS", // "SFC", // "WINDDATA", // // "RAIMXML", // "TLR", // // "ARPTWXXML", // "SOFPINFO", // // "HAZARDADVISORYXML", // "IWFRXML", // "OFPNLXML", // "VERTPROF", // "SOFPSUM", // "APLI", // "RAIM", // "UAD", // "DISMAP", // "WXSATWX" // "APLI", // "APTDXML", // "SOFP", // "CDA", // "RADAR", // "OFPDLK", // "ATSXML", // "REGWXXML", // "WXSIGWX", // "SIGWXROUTE", // "VAATCA", // "ASPDXML", // "NOTAMXML", // "OTS", // "SFC", // "WINDDATA", // "RAIMXML", // "ARPTWXXML", // "SOFPINFO", // "IWFRXML", // "OFPNLXML", // "VERTPROF", // "SOFPSUM", // "RAIM", // "UAD", // "DISMAP", // "WXSATWX" ], }))); //log(response.body); Map decodedresponse; try { decodedresponse = (json.decode(response.body) ?? {}); } catch (e) { decodedresponse = {}; } String? message = decodedresponse["errorsAndWarnings"]?["warnings"]?[0] ?["message"] ?? decodedresponse["errorsAndWarnings"]?["errors"]?[0]?["message"] ?? ((response.statusCode == 201) ? null : "ERR"); log("lidoapi: ofp: statuscode: ${response.statusCode} msg: $message"); return { 'error': (message == null) ? null : message, 'data': decodedresponse, 'meta': { "user": username, "pass": password, "cookie": cookieMap, "legid": legid } }; } catch (e) { return {'error': e.toString(), 'data': {}, 'meta': {}}; } } Future ofppdf( {required String legid, String? fileid, bool loginfirst = false}) async { try { if (loginfirst) { final out = await login(); if (!logged) return out; } var response = await http.put( Uri.parse("$url/lido/lcb/ui/briefing/multi/print?force=true"), headers: { "Accept": "application/vnd.lsy.lido.lcb.v1.hal+json,application/pdf", //"Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en", "Connection": "keep-alive", "Content-Type": "application/json;charset=UTF-8", "Cookie": cookie, //"host": Uri.parse(realurl).host, "Origin": Uri.parse(realurl).host, // "sec-ch-ua":'" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"', "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", "X-lido-applicationId": "lido-lcb", "X-lido-businessId": "printBP", "X-lido-clientId": "lido-lcb-web", "X-lido-csrf": cookieMap["lido_csrf"] ?? "", "X-lido-customerId": "TAR", "X-lido-operatingAirline": "TU", "X-lido-timeStamp": "2022-05-25T06:29:56.659Z", "X-lido-traceId": "3cbab7e0-56ca-49ec-b158-8899c0d3bbbb", }, body: json.encode({ "legIdentifiers": [legid], "categories": [ "OFP", "ATS", "CREWINFO", "DISP", "IWFR", "NOTAM", "UAD", "WXSIGWX", "VERTPROF", "RAIM", "DMS", "WXNOTAM", "ABD", "SIGWXROUTE", //"WXSATWX" ], "merge": false, "quickprint": false, "weatherDataRequired": false, })); if (!loginfirst && response.statusCode > 201) { return ofppdf(legid: legid, fileid: fileid, loginfirst: true); } // log("lidoapi: pdfofp2: status: ${response.statusCode} fileid: $fileid "); //final id ="${DateFormat("yyyyMMdd").format(DateTime.fromMillisecondsSinceEpoch(dateoforigin))}_${dep}_${des}_$al$fnum"; final ok = response.headers.containsKey("content-disposition"); // log("lidoapi: pdfofp2: status: ${response.headers} "); final xfileid = fileid ?? PathTo().lidoFile("$legid.pdf"); if (ok) { await downloadPdf(response, xfileid); } final res = { 'error': (ok) ? null : "no PDF downloaded", 'data': (ok) ? { "downloaded": true, "fileid": xfileid, } : { "downloaded": false, "fileid": null, }, 'meta': {"user": username, "pass": password, "cookie": cookieMap} }; return res; } catch (e) { final res = { 'error': e.toString(), 'data': { { "downloaded": false, "fileid": null, } }, 'meta': {} }; final xfileid = fileid ?? PathTo().lidoFile("$legid.pdf"); if (File(xfileid).existsSync()) { res["cache"] = xfileid; } return res; } } Map _getcookies(String cookiesData, {List vars = const [ "lido_auth", "lido_csrf", "JSESSIONID", "SERVERID" ]}) { Map cookies = {}; for (var title in vars) { if (cookiesData.contains(title)) { List at = (RegExp(r'(' + title + ')(.*?)[^;]+').stringMatch(cookiesData) ?? "") .split('='); cookies[title] = at[1]; } } return cookies; } Future downloadPdf(http.Response response, String fileid) async { try { if (response.statusCode == 201) { final pdfBytes = response.bodyBytes; final file = File(fileid); await file.writeAsBytes(pdfBytes); print('PDF downloaded and saved to $fileid'); } else { print('Error downloading PDF: ${response.statusCode}'); } } catch (e) { print('Error downloading file: $e'); } } }