Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polytech Colloscope #25

Merged
merged 21 commits into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions melos_onyx_workspace.iml
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@
<excludeFolder url="file://$MODULE_DIR$/apps/.flutter/packages/integration_test/integration_test_macos/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/apps/.flutter/packages/integration_test/integration_test_macos/.pub" />
<excludeFolder url="file://$MODULE_DIR$/apps/.flutter/packages/integration_test/integration_test_macos/build" />
<excludeFolder url="file://$MODULE_DIR$/packages/polytechcolloscopeclient/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/packages/polytechcolloscopeclient/.pub" />
<excludeFolder url="file://$MODULE_DIR$/packages/polytechcolloscopeclient/build" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
Expand Down
7 changes: 7 additions & 0 deletions packages/polytechcolloscopeclient/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/

# Avoid committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock
3 changes: 3 additions & 0 deletions packages/polytechcolloscopeclient/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 1.0.0

- Initial version.
1 change: 1 addition & 0 deletions packages/polytechcolloscopeclient/README.md
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# TODO
30 changes: 30 additions & 0 deletions packages/polytechcolloscopeclient/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.

include: package:lints/recommended.yaml

# Uncomment the following section to specify additional rules.

# linter:
# rules:
# - camel_case_types

# analyzer:
# exclude:
# - path/to/excluded/files/**

# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints

# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'src/colloscope_datastructs.dart';
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
export 'src/consts.dart';
export 'src/polytechcolloscopeclient_base.dart';
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:equatable/equatable.dart';

class Student extends Equatable {
final String name;
final String id;

Student(this.name, this.id);

@override
List<Object?> get props => [name, id];

@override
bool? get stringify => true;
}

class StudentColloscope extends Equatable {
final int studentId;
final int trinomeId;
final List kholles;

StudentColloscope(this.studentId, this.trinomeId, this.kholles);

@override
List<Object?> get props => [studentId, trinomeId, kholles];

@override
bool? get stringify => true;
}

class Kholle extends Equatable {
final DateTime date;
final String subject;
final String? message;
final String? kholleur;

Kholle(this.date, this.subject, this.message, this.kholleur);

@override
List<Object?> get props => [date, subject, message, kholleur];

@override
bool? get stringify => true;
}
37 changes: 37 additions & 0 deletions packages/polytechcolloscopeclient/lib/src/consts.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
enum Year {
first,
second,
}

class Consts {
static const String userAgent =
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0";

// HTTPS parce que le https est pas géré
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
static const String _base = "http://math.univ-lyon1.fr/colles/";

static const kholleURL = {
Year.first: "$_base?page=colles_1A",
Year.second: "$_base?page=colles_2A"
};

static const khollesStudentURL = {
Year.first: "$_base?page=colles_1A&id_etudiant=:id",
Year.second: "$_base?page=colles_2A&id_etudiant=:id"
};

static const Map monthsTranslation = {
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
"janvier": DateTime.january,
"février": DateTime.february,
"mars": DateTime.march,
"avril": DateTime.april,
"mai": DateTime.may,
"juin": DateTime.june,
"juillet": DateTime.july,
"août": DateTime.august,
"septembre": DateTime.september,
"octobre": DateTime.october,
"novembre": DateTime.november,
"décembre": DateTime.december
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import 'package:beautiful_soup_dart/beautiful_soup.dart';
import 'package:html/dom.dart';
import 'package:requests_plus/requests_plus.dart';

import 'colloscope_datastructs.dart';
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
import 'consts.dart';

class PolytechColloscopeClient {
final String username, password;
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

PolytechColloscopeClient(this.username, this.password) {
assert(username.isNotEmpty);
assert(password.isNotEmpty);
}

Future<List<Student>> fetchStudents(Year year) async {
var page = await RequestsPlus.get(Consts.kholleURL[year]!,
userName: username, password: password);

BeautifulSoup bs = BeautifulSoup(page.body);

//This isolates the student list part of the page, it consists in a list of <li> elements like
// <li><a href="?page=colles_2A&amp;id_etudiant=STUDENT_ID">INITAL. SUNRNAME</a> (groupe GROUPNUMBER)</li>
var studentsList = bs.find("table.colles")?.find("td > ul");
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

List<Student> students = [];

studentsList?.findAll("li > a").forEach((e) {
hatch01 marked this conversation as resolved.
Show resolved Hide resolved
var name = e.innerHtml;
var link = e.getAttrValue("href");
var id = RegExp(r"id_etudiant=(\d+)").firstMatch(link!)?.group(1);
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

students.add(Student(name, id!));
});

return students;
}

Future<StudentColloscope> getColloscope(Year year, int studentId) async {
// TODO : Add a check to verify the studentid (look 5 lines below)

var page = await RequestsPlus.get(
Consts.khollesStudentURL[year]!
.replaceFirst(":id", studentId.toString()),
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
userName: username,
password: password);

BeautifulSoup bs = BeautifulSoup(page.body);

// We can use this to check if the studentid is valid
var trinomeStr = RegExp(r"trinôme (\d+)")
.firstMatch(bs.find("h3.colles")!.innerHtml)
?.group(1);
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

var trinome = int.parse(trinomeStr!);

var tableHtml = bs.find("table.colles");
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

List kholles = [];

tableHtml?.findAll("tr").forEach((e) {
kholles.add(parseKholle(e));
});

return StudentColloscope(studentId, trinome, kholles);
}

static Kholle parseKholle(Bs4Element e) {
// Gathering data from html (this parsing is awful but can't really do better)

var date = e.children.first.innerHtml.trim();
var secondTd = e.children.elementAtOrNull(1);

var hourAndMinute =
secondTd?.children.first.innerHtml.replaceFirst("&nbsp;", "").trim();
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

var secondDiv = secondTd?.children.elementAtOrNull(1);
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
var kholleur = secondDiv?.find("a")?.text.trim();
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

// This holds the subject of the kholle (and maybe the room because this website html is probably the worst I've ever seen)
var text = "";

var divText =
secondDiv?.nodes.where((element) => element.runtimeType == Text);
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

var subject = divText?.first.text?.replaceAll(RegExp(r'[()]'), "").trim();
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved

String message;
if (divText?.length == 2) {
message =
divText?.last.text?.replaceAll(RegExp(r'[()]'), "").trim() ?? "";
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
} else {
message = "";
}

var dateParsed = RegExp(r"(\d{1,2}) (.{3,9})").firstMatch(date);
var day = dateParsed?.group(1);
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
var month = Consts.monthsTranslation[dateParsed?.group(2)];

var hourAndMinutesParsed =
RegExp(r"(\d{1,2}) h (\d{2})").firstMatch(hourAndMinute!);
var hour = hourAndMinutesParsed?.group(1);
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
var minutes = hourAndMinutesParsed?.group(2);

var dateTime = DateTime(DateTime.now().year, month, int.parse(day!),
int.parse(hour!), int.parse(minutes!));

return Kholle(dateTime, subject!, message, kholleur);
}
}
19 changes: 19 additions & 0 deletions packages/polytechcolloscopeclient/pubspec.yaml
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: polytechcolloscopeclient
description: A starting point for Dart libraries or applications.
version: 1.0.0
# repository: https://github.com/my_org/my_repo

environment:
sdk: ^3.1.3

# Add regular dependencies here.
dependencies:
beautiful_soup_dart: ^0.3.0
dotenv: ^4.2.0
equatable: ^2.0.5
requests_plus: ^4.8.4
# path: ^1.8.0

dev_dependencies:
lints: ^3.0.0
test: ^1.21.0
FlashOnFire marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:dotenv/dotenv.dart';
import 'package:polytechcolloscopeclient/polytechcolloscopeclient.dart';
import 'package:test/test.dart';

Future<void> main() async {
DotEnv env = DotEnv(includePlatformEnvironment: true);

env.load();
final String username = env['USERNAME'] ?? "";
final String password = env['PASSWORD'] ?? "";

if (username.isEmpty || password.isEmpty) {
fail("username or password were empty. check your envt variables");
}

PolytechColloscopeClient client =
PolytechColloscopeClient(username, password);

var students = await client.fetchStudents(Year.first);
print(students);

var colloscope = await client.getColloscope(Year.first, 828);
print(colloscope);
}
Loading