Přidáno získání kreditu a objednávání
This commit is contained in:
parent
7a3483c81f
commit
58880b9ab3
6 changed files with 90 additions and 17 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,3 +8,4 @@ build/
|
||||||
# Omit committing pubspec.lock for library packages; see
|
# Omit committing pubspec.lock for library packages; see
|
||||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
pubspec.lock
|
pubspec.lock
|
||||||
|
.env*
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
## O knihovně
|
## O knihovně
|
||||||
Experimentální **neoficiální** webscrape knihovna pro komunikaci se systémem [iCanteen](https://www.z-ware.cz/internetove-objednavky)
|
Experimentální **neoficiální** webscrape knihovna pro komunikaci se systémem [iCanteen](https://www.z-ware.cz/internetove-objednavky)
|
||||||
|
|
||||||
|
[![wakatime](https://wakatime.com/badge/user/17178fab-a33c-430f-a764-7b3f26c7b966/project/82873d93-5b79-4978-a5f6-612e21641817.svg)](https://wakatime.com/badge/user/17178fab-a33c-430f-a764-7b3f26c7b966/project/82873d93-5b79-4978-a5f6-612e21641817)
|
||||||
|
|
||||||
## Funkční funkce(*)
|
## Funkční funkce(*)
|
||||||
- získání jídelníčku na aktuální den (s cenami)
|
- získání jídelníčku na aktuální den (s cenami)
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,28 @@ import 'jidlo.dart';
|
||||||
class Canteen {
|
class Canteen {
|
||||||
final String url;
|
final String url;
|
||||||
Map<String, String> cookies = {"JSESSIONID": "", "XSRF-TOKEN": ""};
|
Map<String, String> cookies = {"JSESSIONID": "", "XSRF-TOKEN": ""};
|
||||||
|
double _kredit = 0.0;
|
||||||
|
bool prihlasen = false;
|
||||||
Canteen(this.url);
|
Canteen(this.url);
|
||||||
|
|
||||||
|
/// Vrátí aktuální kredit ze serveru jako [double]. Jelikož je async, nejdřív [Future]
|
||||||
|
///
|
||||||
|
/// Nastane-li chyba, vrací [Null]
|
||||||
|
Future<double> ziskejKredit() async {
|
||||||
|
if (!prihlasen) return 0.0;
|
||||||
|
var r = await _getRequest("/faces/secured/main.jsp");
|
||||||
|
if (r == null) return 0.0;
|
||||||
|
File("./test.txt").writeAsStringSync(r);
|
||||||
|
var m = double.tryParse(RegExp(r' +<span id="Kredit" .+?>(.+?)(?=&)')
|
||||||
|
.firstMatch(r)!
|
||||||
|
.group(1)!
|
||||||
|
.replaceAll(",", ".")
|
||||||
|
.replaceAll(RegExp(r"[^\w.]"), ""));
|
||||||
|
if (m == null) return 0.0;
|
||||||
|
_kredit = m;
|
||||||
|
return _kredit;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> getFirstSession() async {
|
Future<void> getFirstSession() async {
|
||||||
var res = await http.get(Uri.parse(url));
|
var res = await http.get(Uri.parse(url));
|
||||||
_parseCookies(res.headers['set-cookie']!);
|
_parseCookies(res.headers['set-cookie']!);
|
||||||
|
@ -36,8 +56,9 @@ class Canteen {
|
||||||
/// `user` - uživatelské jméno
|
/// `user` - uživatelské jméno
|
||||||
/// `password` - heslo
|
/// `password` - heslo
|
||||||
///
|
///
|
||||||
|
/// Vrátí `true`, když se uživatel přihlásil, jinak `false`
|
||||||
/// TODO: Házet chyby
|
/// TODO: Házet chyby
|
||||||
Future<void> login(String user, String password) async {
|
Future<bool> login(String user, String password) async {
|
||||||
if (cookies["JSESSIONID"] == "" || cookies["XSRF-TOKEN"] == "") {
|
if (cookies["JSESSIONID"] == "" || cookies["XSRF-TOKEN"] == "") {
|
||||||
await getFirstSession();
|
await getFirstSession();
|
||||||
}
|
}
|
||||||
|
@ -59,11 +80,17 @@ class Canteen {
|
||||||
"targetUrl":
|
"targetUrl":
|
||||||
"/faces/secured/main.jsp?terminal=false&status=true&printer=&keyboard="
|
"/faces/secured/main.jsp?terminal=false&status=true&printer=&keyboard="
|
||||||
});
|
});
|
||||||
|
if (res.headers['set-cookie']!.contains("remember-me=;")) {
|
||||||
|
return false; // špatné heslo
|
||||||
|
}
|
||||||
|
|
||||||
_parseCookies(res.headers['set-cookie']!);
|
_parseCookies(res.headers['set-cookie']!);
|
||||||
if (res.statusCode != 302) {
|
if (res.statusCode != 302) {
|
||||||
print(res.body);
|
print(res.body);
|
||||||
print("ERROR");
|
print("ERROR");
|
||||||
}
|
}
|
||||||
|
prihlasen = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builder pro GET request
|
/// Builder pro GET request
|
||||||
|
@ -128,9 +155,9 @@ class Canteen {
|
||||||
var vydejna = RegExp(r'(?<=<span style="color: #1b75bb;">).+?(?=<)')
|
var vydejna = RegExp(r'(?<=<span style="color: #1b75bb;">).+?(?=<)')
|
||||||
.firstMatch(s); // název výdejny / verze 2.18
|
.firstMatch(s); // název výdejny / verze 2.18
|
||||||
vydejna ??= RegExp(
|
vydejna ??= RegExp(
|
||||||
|
// TODO: Lepší systém pro podporu různých verzí iCanteen
|
||||||
r'(?<=<span class="smallBoldTitle" style="color: #1b75bb;">).+?(?=<)')
|
r'(?<=<span class="smallBoldTitle" style="color: #1b75bb;">).+?(?=<)')
|
||||||
.firstMatch(s); // název výdejny / verze 2.10
|
.firstMatch(s); // název výdejny / verze 2.10
|
||||||
File("dva.txt").writeAsStringSync(s);
|
|
||||||
var hlavni = RegExp(
|
var hlavni = RegExp(
|
||||||
r' {20}(([a-zA-ZěščřžýáíéÉÍÁÝŽŘČŠĚŤŇťň.,:\/]+ )+[a-zA-ZěščřžýáíéÉÍÁÝŽŘČŠĚŤŇťň.,:\/]+)',
|
r' {20}(([a-zA-ZěščřžýáíéÉÍÁÝŽŘČŠĚŤŇťň.,:\/]+ )+[a-zA-ZěščřžýáíéÉÍÁÝŽŘČŠĚŤŇťň.,:\/]+)',
|
||||||
dotAll: true)
|
dotAll: true)
|
||||||
|
@ -141,7 +168,8 @@ class Canteen {
|
||||||
nazev: hlavni,
|
nazev: hlavni,
|
||||||
objednano: false,
|
objednano: false,
|
||||||
cislo: vydejna!.group(0).toString(),
|
cislo: vydejna!.group(0).toString(),
|
||||||
lzeObjednat: false));
|
lzeObjednat: false,
|
||||||
|
den: den));
|
||||||
}
|
}
|
||||||
jidelnicek.add(Jidelnicek(den, jidla));
|
jidelnicek.add(Jidelnicek(den, jidla));
|
||||||
}
|
}
|
||||||
|
@ -150,11 +178,17 @@ class Canteen {
|
||||||
|
|
||||||
/// Získá jídlo pro daný den
|
/// Získá jídlo pro daný den
|
||||||
/// Vyžaduje přihlášení pomocí [login]
|
/// Vyžaduje přihlášení pomocí [login]
|
||||||
Future<Jidelnicek> jidelnicekDen() async {
|
/// Aktuálně pouze dnešní den
|
||||||
|
Future<Jidelnicek> jidelnicekDen({DateTime? den}) async {
|
||||||
|
den ??= DateTime.now();
|
||||||
var res = await _getRequest(
|
var res = await _getRequest(
|
||||||
"/faces/secured/main.jsp?terminal=false&android=false&keyboard=false&printer=false");
|
"/faces/secured/main.jsp?day=${den.year}-${(den.month < 10) ? "0" + den.month.toString() : den.month}-${(den.day < 10) ? "0" + den.day.toString() : den.day}&terminal=false&printer=false&keyboard=false");
|
||||||
var den = DateTime.parse(RegExp(r'(?<=day-).+?(?=")', dotAll: true)
|
if (res!.contains("<title>iCanteen - přihlášení uživatele</title>")) {
|
||||||
.firstMatch(res!)!
|
prihlasen = false;
|
||||||
|
throw Exception("Nepřihlášen");
|
||||||
|
}
|
||||||
|
var obedDen = DateTime.parse(RegExp(r'(?<=day-).+?(?=")', dotAll: true)
|
||||||
|
.firstMatch(res)!
|
||||||
.group(0)
|
.group(0)
|
||||||
.toString());
|
.toString());
|
||||||
var jidla = <Jidlo>[];
|
var jidla = <Jidlo>[];
|
||||||
|
@ -173,6 +207,8 @@ class Canteen {
|
||||||
!(o.contains("nelze zrušit") || o.contains("nelze objednat"));
|
!(o.contains("nelze zrušit") || o.contains("nelze objednat"));
|
||||||
var cenaMatch =
|
var cenaMatch =
|
||||||
RegExp(r'(?<=Cena objednaného jídla">).+?(?=&)').firstMatch(o);
|
RegExp(r'(?<=Cena objednaného jídla">).+?(?=&)').firstMatch(o);
|
||||||
|
cenaMatch ??=
|
||||||
|
RegExp(r'(?<=Cena při objednání jídla: ).+?(?=&)').firstMatch(o);
|
||||||
cenaMatch ??=
|
cenaMatch ??=
|
||||||
RegExp(r'(?<=Cena při objednání jídla">).+?(?=&)').firstMatch(o);
|
RegExp(r'(?<=Cena při objednání jídla">).+?(?=&)').firstMatch(o);
|
||||||
var cena =
|
var cena =
|
||||||
|
@ -202,20 +238,46 @@ class Canteen {
|
||||||
cislo: vydejna,
|
cislo: vydejna,
|
||||||
lzeObjednat: lzeObjednat,
|
lzeObjednat: lzeObjednat,
|
||||||
cena: cena,
|
cena: cena,
|
||||||
orderUrl: orderUrl));
|
orderUrl: orderUrl,
|
||||||
|
den: obedDen));
|
||||||
// KONEC formátování do třídy
|
// KONEC formátování do třídy
|
||||||
}
|
}
|
||||||
|
|
||||||
return Jidelnicek(den, jidla);
|
return Jidelnicek(obedDen, jidla);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> objednat(Jidlo j) async {
|
/// Objedná vybrané jídlo
|
||||||
|
/// Vrátí upravenou instanci [Jidlo], v případě chyby vrací originální
|
||||||
|
Future<Jidlo> objednat(Jidlo j) async {
|
||||||
//TODO
|
//TODO
|
||||||
if (!j.lzeObjednat || j.orderUrl == null || j.orderUrl!.isEmpty) {
|
if (!j.lzeObjednat || j.orderUrl == null || j.orderUrl!.isEmpty) {
|
||||||
return false;
|
return j;
|
||||||
}
|
}
|
||||||
var res = await _getRequest(j.orderUrl!);
|
var res =
|
||||||
print(res);
|
await _getRequest("/faces/secured/" + j.orderUrl!); // provést operaci
|
||||||
return true;
|
if (res == null || res.contains("Chyba")) return j;
|
||||||
|
|
||||||
|
var novy = await _getRequest(
|
||||||
|
"/faces/secured/db/dbJidelnicekOnDayView.jsp?day=${j.den.year}-${(j.den.month < 10) ? "0" + j.den.month.toString() : j.den.month}-${(j.den.day < 10) ? "0" + j.den.day.toString() : j.den.day}&terminal=false&rating=null&printer=false&keyboard=false"); // získat novou URL pro objednávání
|
||||||
|
if (novy == null) return j;
|
||||||
|
var lzeObjednat =
|
||||||
|
!(novy.contains("nelze zrušit") || novy.contains("nelze objednat"));
|
||||||
|
String orderUrl = "";
|
||||||
|
if (lzeObjednat) {
|
||||||
|
// pokud lze objednat, nastavíme adresu pro objednání
|
||||||
|
orderUrl = RegExp(r"(?<=ajaxOrder\(this, ').+?(?=')")
|
||||||
|
.firstMatch(novy)!
|
||||||
|
.group(0)!
|
||||||
|
.replaceAll("amp;", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Jidlo(
|
||||||
|
cislo: j.cislo,
|
||||||
|
nazev: j.nazev,
|
||||||
|
objednano: !j.objednano,
|
||||||
|
cena: j.cena,
|
||||||
|
lzeObjednat: j.lzeObjednat,
|
||||||
|
orderUrl: orderUrl,
|
||||||
|
den: j.den); // vrátit upravenou instanci
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,14 @@ class Jidlo {
|
||||||
|
|
||||||
///Lze objednat?
|
///Lze objednat?
|
||||||
bool lzeObjednat;
|
bool lzeObjednat;
|
||||||
|
|
||||||
|
DateTime den;
|
||||||
final String? orderUrl;
|
final String? orderUrl;
|
||||||
Jidlo(
|
Jidlo(
|
||||||
{required this.nazev,
|
{required this.nazev,
|
||||||
required this.objednano,
|
required this.objednano,
|
||||||
required this.cislo,
|
required this.cislo,
|
||||||
|
required this.den,
|
||||||
this.cena,
|
this.cena,
|
||||||
required this.lzeObjednat,
|
required this.lzeObjednat,
|
||||||
this.orderUrl});
|
this.orderUrl});
|
||||||
|
|
|
@ -11,6 +11,7 @@ environment:
|
||||||
# path: ^1.8.0
|
# path: ^1.8.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
dotenv: ^3.0.0
|
||||||
lints: ^1.0.0
|
lints: ^1.0.0
|
||||||
test: ^1.16.0
|
test: ^1.16.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
import 'package:canteenlib/canteenlib.dart';
|
import 'package:canteenlib/canteenlib.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
import 'package:dotenv/dotenv.dart' show load, env;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('A group of tests', () {
|
group('A group of tests', () {
|
||||||
Canteen c = Canteen("a");
|
load();
|
||||||
|
Canteen c = Canteen(env["ADDRESS"]!);
|
||||||
|
|
||||||
setUp(() {
|
setUp(() {
|
||||||
// Additional setup goes here.
|
c.login(env["USER"]!, env["PASS"]!);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('First Test', () {
|
test('First Test', () {
|
||||||
expect(true, isTrue);
|
c.jidelnicekDen().then((t) {
|
||||||
|
expect(DateTime.now().day, t.den.day);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue