//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');
}
}
}