From 567aea179ba550f25dd2335ec0ef1d5b691e244e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maty=C3=A1=C5=A1=20Caras?= Date: Wed, 30 Mar 2022 15:30:51 +0200 Subject: [PATCH] =?UTF-8?q?Burza=20+=20snad=20to=20co=20mi=20furt=20pad?= =?UTF-8?q?=C3=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 10 ++++ COMPATIBILITY.md | 2 +- README.md | 5 +- lib/src/canteen.dart | 119 +++++++++++++++++++++++++++++++++++-------- lib/src/tridy.dart | 30 +++++++++-- pubspec.yaml | 4 +- 6 files changed, 140 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2042be4..f546905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ +## 0.1.0-alpha.4 +- Přidáno získání a objednávání cizích jídel z burzy +- Třída `Jidlo`: ~~cislo~~ 👉 **varianta** +- Nová třída `Burza` pro cizí jídla z burzy +- Více Exceptionů + +[Všechny změny](https://github.com/hernikplays/canteenlib/compare/0.1.0-alpha.3...0.1.0-alpha.4) + ## 0.1.0-alpha.3 - Kontrolovat správný status kód u GET požadavků +[Všechny změny](https://github.com/hernikplays/canteenlib/compare/0.1.0-alpha.1...0.1.0-alpha.4) + ## 0.1.0-alpha.2 - Nevytvářet debugovací soubor - Místo ziskejKredit používáme ziskejUzivatele (Třída Uzivatel) diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 73d37bf..edc51f8 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -9,7 +9,7 @@ Výchozí verze, pro kterou aktuálně je knihovna tvořena, je **2.18.19** | Provozovatel | Verze iCanteen | Funkční | Verze knihovny | |:--------------:|------------------|---------|----------------| -| SŠTE Brno | iCanteen 2.18.19 | ✅ | 0.1.0-alpha | +| SŠTE Brno | iCanteen 2.18.19 | ✅ | 0.1.0-alpha.4 | | SPŠ Třebíč | iCanteen 2.10.25 | ❓ | 0.1.0-alpha | Pokud chcete přispět s testem, otestujte tuto knihovnu na instanci iCanteen, kde, nejlépe legálně, máte přístup, a nahlašte své poznatky [zde](https://github.com/hernikplays/canteenlib/issues/new?assignees=hernikplays&labels=kompatibilita&template=hl--en--kompatibility.md&title=Kompatibilita%3A+) \ No newline at end of file diff --git a/README.md b/README.md index 9db7f64..13fa6b2 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,17 @@ ## O knihovně 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) +[![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) [![Pub Version (including pre-releases)](https://img.shields.io/pub/v/canteenlib?color=lightblue&include_prereleases&label=latest%20version)](https://pub.dev/packages/canteenlib) ## Funkční funkce(*) - získání jídelníčku na aktuální den (s cenami) - Objednání / zrušení objednávek - Nabídnutí jídla do burzy / zrušení +- Získání a objednání cizího jídla z burzy ## To do -- Získání a objednání cizího jídla z burzy - Kompatibilita se staršími verzemi iCanteen +- Stabilita *\* Knihovna nemusí fungovat na všech instancích systému iCanteen, proto žádám každého, kdo může a je uživatelem iCanteen, aby otestoval funkčnost této knihovny a případné problémy [nahlásil](https://github.com/hernikplays/canteenlib/issues)* diff --git a/lib/src/canteen.dart b/lib/src/canteen.dart index 9f6fbd8..a53c577 100644 --- a/lib/src/canteen.dart +++ b/lib/src/canteen.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:http/http.dart' as http; import 'tridy.dart'; @@ -35,9 +33,11 @@ class Canteen { /// Vrátí informace o uživateli ve formě instance [Uzivatel] Future ziskejUzivatele() async { - if (!prihlasen) throw Exception("Bez přihlášení"); + if (!prihlasen) throw Exception("Uživatel není přihlášený"); var r = await _getRequest("/web/setting"); - if (r == null) throw Exception("Při požadavku došlo k chybě"); + if (r.contains("přihlášení uživatele")) { + throw Exception("Uživatel není přihlášený"); + } var m = double.tryParse(RegExp(r' +(.+?)(?=&)') .firstMatch(r)! .group(1)! @@ -72,8 +72,9 @@ class Canteen { } Future getFirstSession() async { - if (url.endsWith("/")) - url = url.substring(0, url.length - 1); // odstranit lomítko + if (url.endsWith("/")) { + url = url.substring(0, url.length - 1); + } // odstranit lomítko var res = await http.get(Uri.parse(url)); _parseCookies(res.headers['set-cookie']!); } @@ -134,7 +135,7 @@ class Canteen { /// Builder pro GET request /// V případě chyby na serveru (divný status kód) vyhodí [Exception] - Future _getRequest(String path) async { + Future _getRequest(String path) async { var r = await http.get(Uri.parse(url + path), headers: { "Cookie": "JSESSIONID=" + cookies["JSESSIONID"]! + @@ -161,7 +162,7 @@ class Canteen { var reg = RegExp( r'((?=
).+?(?=
))|((?=
).*<\/span>)', dotAll: true) - .allMatches(res!) + .allMatches(res) .toList(); List jidelnicek = []; for (var t in reg) { @@ -210,7 +211,7 @@ class Canteen { jidla.add(Jidlo( nazev: hlavni, objednano: false, - cislo: vydejna!.group(0).toString(), + varianta: vydejna!.group(0).toString(), lzeObjednat: false, den: den, naBurze: false)); @@ -223,10 +224,13 @@ class Canteen { /// Získá jídlo pro daný den /// Vyžaduje přihlášení pomocí [login] Future jidelnicekDen({DateTime? den}) async { + if (!prihlasen) { + throw Exception("Uživatel není přihlášen"); + } den ??= DateTime.now(); var res = await _getRequest( "/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"); - if (res!.contains("iCanteen - přihlášení uživatele")) { + if (res.contains("iCanteen - přihlášení uživatele")) { prihlasen = false; throw Exception("Nepřihlášen"); } @@ -286,7 +290,7 @@ class Canteen { nazev: jidlaProDen[1] .replaceAll(r' (?=[^a-zA-ZěščřžýáíéĚŠČŘŽÝÁÍÉŤŇťň])', ''), objednano: objednano, - cislo: vydejna, + varianta: vydejna, lzeObjednat: lzeObjednat, cena: cena, orderUrl: orderUrl, @@ -301,18 +305,25 @@ class Canteen { } /// Objedná vybrané jídlo - /// Vrátí upravenou instanci [Jidlo], v případě chyby vrací originální + /// + /// Vrátí upravenou instanci [Jidlo], v případě chyby vyhodí [Exception] Future objednat(Jidlo j) async { + if (!prihlasen) { + throw Exception("Uživatel není přihlášen"); + } if (!j.lzeObjednat || j.orderUrl == null || j.orderUrl!.isEmpty) { - return j; + throw Exception("Jídlo nelze objednat nebo nemá adresu pro objednání"); } var res = await _getRequest("/faces/secured/" + j.orderUrl!); // provést operaci - if (res == null || res.contains("Chyba")) return j; + if (res.contains("Chyba")) throw Exception("Při požadavku došlo k chybě"); + if (res.contains("přihlášení uživatele")) { + prihlasen = false; + throw Exception("Uživatel není přihlášen"); + } 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; @@ -334,7 +345,7 @@ class Canteen { } return Jidlo( - cislo: j.cislo, + varianta: j.varianta, nazev: j.nazev, objednano: !j.objednano, cena: j.cena, @@ -347,19 +358,27 @@ class Canteen { : !burzaUrl.contains("plusburza")); // vrátit upravenou instanci } - /// Uloží jídlo z/do burzy + /// Uloží vaše jídlo z/do burzy /// - /// Vrací upravenou instanci [Jidlo], v případě chyby vrací originální + /// Vrací upravenou instanci [Jidlo], v případě chyby vyhodí [Exception] Future doBurzy(Jidlo j) async { + if (!prihlasen) { + throw Exception("Uživatel není přihlášen"); + } if (j.burzaUrl == null || j.burzaUrl!.isEmpty) { - return j; + throw Exception( + "Jídlo nelze uložit do burzy nebo nemá adresu pro uložení"); } var res = await _getRequest("/faces/secured/" + j.burzaUrl!); // provést operaci - if (res == null || res.contains("Chyba")) return j; + if (res.contains("Chyba")) return j; + if (res.contains("přihlášení uživatele")) { + prihlasen = false; + throw Exception("Uživatel není přihlášen"); + } + 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; @@ -381,7 +400,7 @@ class Canteen { } return Jidlo( - cislo: j.cislo, + varianta: j.varianta, nazev: j.nazev, objednano: !j.objednano, cena: j.cena, @@ -393,4 +412,60 @@ class Canteen { ? false : !burzaUrl.contains("plusburza")); // vrátit upravenou instanci } + + /// Získá aktuální jídla v burze + Future> ziskatBurzu() async { + if (!prihlasen) throw Exception("Uživatel není přihlášen"); + List burza = []; + var r = await _getRequest("/faces/secured/burza.jsp"); + if (r.contains("Chyba")) throw Exception("Při požadavku došlo k chybě"); + if (r.contains("přihlášení uživatele")) { + prihlasen = false; + throw Exception("Uživatel není přihlášen"); + } + var dostupnaJidla = + RegExp(r'(?<=).+?(?=<\/tr>)', dotAll: true) + .allMatches(r); // vyfiltrujeme jednotlivá jídla + if (dostupnaJidla.isNotEmpty) { + for (var burzaMatch in dostupnaJidla) { + var bu = burzaMatch.group(0)!; + var data = RegExp( + r'((?<=).+?(?=<))|(?<=).+?(?=<)|((?<=).+?(?=<))', + dotAll: true) + .allMatches(bu) + .toList(); + // Získat datum + var datumRaw = RegExp(r'\d\d\.\d\d\.\d{4}') + .firstMatch(data[1].group(0)!)! + .group(0)! + .split("."); + var datum = + DateTime.parse("${datumRaw[2]}-${datumRaw[1]}-${datumRaw[0]}"); + // Získat variantu + var varianta = data[0].group(0)!; + // Získat název jídla + var nazev = data[2].group(0)!.replaceAll(RegExp(r'\n| '), ""); + // Získat počet kusů + var pocet = int.parse(data[3].group(0)!.replaceAll(" ks", "")); + var url = RegExp(r"(?<=')db.+?(?=')").firstMatch(bu)!.group(0)!; + var jidlo = Burza( + den: datum, + varianta: varianta, + jidlo: nazev, + pocet: pocet, + url: url); + burza.add(jidlo); + } + } + return burza; + } + + /// Objedná jídlo z burzy pomocí URL z instance třídy Burza + /// + /// Vrací [bool] - true pokud se podařilo objednat, jinak false + Future objednatZBurzy(Burza b) async { + var res = await _getRequest("/faces/secured/" + b.url!); + if (res.contains("Chyba")) return false; + return true; + } } diff --git a/lib/src/tridy.dart b/lib/src/tridy.dart index 387b85d..1703192 100644 --- a/lib/src/tridy.dart +++ b/lib/src/tridy.dart @@ -6,8 +6,8 @@ class Jidlo { /// Objednal si uživatel toto jídlo? bool objednano; - /// Název výdejny - String cislo; + /// Název varianty + String varianta; /// Cena double? cena; @@ -29,7 +29,7 @@ class Jidlo { Jidlo( {required this.nazev, required this.objednano, - required this.cislo, + required this.varianta, required this.den, this.cena, required this.lzeObjednat, @@ -38,6 +38,30 @@ class Jidlo { required this.naBurze}); } +class Burza { + /// Den, který je jídlo vydáváno + DateTime den; + + /// URL pro objednání + final String? url; + + /// Název jídla + String jidlo; + + /// Varianta + String? varianta; + + /// Počet kusů tohoto jídla dostupného na burze + int pocet; + + Burza( + {required this.den, + required this.url, + required this.jidlo, + required this.pocet, + this.varianta}); +} + /// Reprezentuje jídelníček pro jeden dan class Jidelnicek { /// Den, pro který je jídelníček zveřejněn diff --git a/pubspec.yaml b/pubspec.yaml index 06efd9b..6c905d4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: canteenlib -description: Knihovna pro komunikaci se stravovacím systémem iCanteen -version: 0.1.0-alpha.3 +description: Knihovna pro komunikaci se stravovacím systémem iCanteen s možností objednávání jídla +version: 0.1.0-alpha.4 repository: 'https://github.com/hernikplays/canteenlib' issue_tracker: 'https://github.com/hernikplays/canteenlib/issues'