Skip to content

Commit

Permalink
Merge pull request #76 from EATSTEAK/dev
Browse files Browse the repository at this point in the history
[release] v0.5.1 - U-saint 업데이트 대응
  • Loading branch information
EATSTEAK authored Jun 12, 2024
2 parents 7c0318d + b5f01ad commit aec6959
Show file tree
Hide file tree
Showing 37 changed files with 818 additions and 525 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rusaint"
version = "0.5.0"
version = "0.5.1"
description = "Easy-to-use SSU u-saint client"
keywords = ["ssu", "u-saint", "scraping", "parser"]
categories = ["web-programming"]
Expand Down
35 changes: 35 additions & 0 deletions rusaint-ffi/src/application/course_grades.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use std::sync::{Arc, RwLock};

use crate::{error::RusaintError, session::USaintSession};

#[derive(uniffi::Object)]
pub struct CourseGradesApplication(
RwLock<rusaint::application::course_grades::CourseGradesApplication>,
);

unsafe impl Send for CourseGradesApplication {}

unsafe impl Sync for CourseGradesApplication {}

#[derive(uniffi::Object)]
pub struct CourseGradesApplicationBuilder {}

#[uniffi::export]
impl CourseGradesApplicationBuilder {
#[uniffi::constructor]
pub fn new() -> Self {
Self {}
}

pub async fn build_with_password(&self) -> Result<CourseGradesApplication, RusaintError> {
let mut original_builder = rusaint::application::USaintClientBuilder::new();
if let Some(session_base) = &self.session {
let session = session_base.construct().await?;
original_builder = original_builder.session(Arc::new(session));
}
let original_app = original_builder
.build_into::<rusaint::application::course_grades::CourseGradesApplication>()
.await?;
Ok(CourseGradesApplication(RwLock::new(original_app)))
}
}
8 changes: 4 additions & 4 deletions src/application/chapel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ use crate::{
use super::{USaintApplication, USaintClient};

/// [채플정보조회](https://ecc.ssu.ac.kr/sap/bc/webdynpro/SAP/ZCMW3681)
pub struct Chapel {
pub struct ChapelApplication {
client: USaintClient,
}

impl USaintApplication for Chapel {
impl USaintApplication for ChapelApplication {
const APP_NAME: &'static str = "ZCMW3681";

fn from_client(client: USaintClient) -> Result<Self, RusaintError> {
Expand All @@ -34,7 +34,7 @@ impl USaintApplication for Chapel {
}
}

impl<'a> Chapel {
impl<'a> ChapelApplication {
define_elements! {
SEL_PERYR: ComboBox<'a> = "ZCMW3681.ID_0001:V_MAIN.TC_SEL_PERYR";
SEL_PERID: ComboBox<'a> = "ZCMW3681.ID_0001:V_MAIN.TC_SEL_PERID";
Expand Down Expand Up @@ -111,5 +111,5 @@ impl<'a> Chapel {
}
}

/// [`Chapel`] 애플리케이션에 사용되는 데이터
/// [`ChapelApplication`] 애플리케이션에 사용되는 데이터
pub mod model;
38 changes: 19 additions & 19 deletions src/application/course_grades/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ use self::model::{ClassGrade, CourseType, GradeSummary, SemesterGrade};
use super::{USaintApplication, USaintClient};

/// [학생 성적 조회](https://ecc.ssu.ac.kr/sap/bc/webdynpro/SAP/ZCMB3W0017)
pub struct CourseGrades {
pub struct CourseGradesApplication {
client: USaintClient,
}

impl USaintApplication for CourseGrades {
impl USaintApplication for CourseGradesApplication {
const APP_NAME: &'static str = "ZCMB3W0017";

fn from_client(client: USaintClient) -> Result<Self, RusaintError> {
Expand All @@ -47,7 +47,7 @@ impl USaintApplication for CourseGrades {
}

#[allow(unused)]
impl<'a> CourseGrades {
impl<'a> CourseGradesApplication {
// Elements for Grade Summaries
define_elements!(
// Grade summaries by semester
Expand Down Expand Up @@ -88,7 +88,7 @@ impl<'a> CourseGrades {
);

async fn close_popups(&mut self) -> Result<(), WebDynproError> {
fn make_close_event(app: &CourseGrades) -> Option<Event> {
fn make_close_event(app: &CourseGradesApplication) -> Option<Event> {
let body = app.client.body();
let popup_selector =
scraper::Selector::parse(format!(r#"[ct="{}"]"#, PopupWindow::CONTROL_ID).as_str())
Expand Down Expand Up @@ -180,10 +180,10 @@ impl<'a> CourseGrades {
/// # tokio_test::block_on(async {
/// # use std::sync::Arc;
/// # use rusaint::USaintSession;
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGrades };
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGradesApplication };
/// # use rusaint::application::USaintClientBuilder;
/// # let session = Arc::new(USaintSession::with_password("20212345", "password").await.unwrap());
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGrades>().await.unwrap();
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGradesApplication>().await.unwrap();
/// let summary = app.recorded_summary(CourseType::Bachelor).await.unwrap();
/// println!("{:?}", summary);
/// // GradeSummary { ... }
Expand Down Expand Up @@ -219,9 +219,9 @@ impl<'a> CourseGrades {
/// # use std::sync::Arc;
/// # use rusaint::USaintSession;
/// # use rusaint::application::USaintClientBuilder;
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGrades };
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGradesApplication };
/// # let session = Arc::new(USaintSession::with_password("20212345", "password").await.unwrap());
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGrades>().await.unwrap();
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGradesApplication>().await.unwrap();
/// let summary = app.certificated_summary(CourseType::Bachelor).await.unwrap();
/// println!("{:?}", summary);
/// // GradeSummary { ... }
Expand Down Expand Up @@ -256,10 +256,10 @@ impl<'a> CourseGrades {
/// # tokio_test::block_on(async {
/// # use std::sync::Arc;
/// # use rusaint::USaintSession;
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGrades };
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGradesApplication };
/// # use rusaint::application::USaintClientBuilder;
/// # let session = Arc::new(USaintSession::with_password("20212345", "password").await.unwrap());
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGrades>().await.unwrap();
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGradesApplication>().await.unwrap();
/// let semesters = app.semesters(CourseType::Bachelor).await.unwrap();
/// println!("{:?}", semesters);
/// // [SemesterGrade { ... }, SemesterGrade { ... }]
Expand Down Expand Up @@ -333,11 +333,11 @@ impl<'a> CourseGrades {
/// # tokio_test::block_on(async {
/// # use std::sync::Arc;
/// # use rusaint::USaintSession;
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGrades };
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGradesApplication };
/// # use rusaint::application::USaintClientBuilder;
/// # use rusaint::model::SemesterType;
/// # let session = Arc::new(USaintSession::with_password("20212345", "password").await.unwrap());
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGrades>().await.unwrap();
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGradesApplication>().await.unwrap();
/// let classes = app.classes(CourseType::Bachelor, "2022", SemesterType::Two, false).await.unwrap();
/// println!("{:?}", classes); // around 3s(depends on network environment)
/// // [ClassGrade { ... }, ClassGrade { ... }]
Expand All @@ -348,11 +348,11 @@ impl<'a> CourseGrades {
/// # tokio_test::block_on(async {
/// # use std::sync::Arc;
/// # use rusaint::USaintSession;
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGrades };
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGradesApplication };
/// # use rusaint::model::SemesterType;
/// # use rusaint::application::USaintClientBuilder;
/// # let session = Arc::new(USaintSession::with_password("20212345", "password").await.unwrap());
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGrades>().await.unwrap();
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGradesApplication>().await.unwrap();
/// let classes = app.classes(CourseType::Bachelor, "2022", SemesterType::Two, true).await.unwrap();
/// println!("{:?}", classes); // around 10s(depends on network environment)
/// // [ClassGrade { ... }, ClassGrade { ... }]
Expand Down Expand Up @@ -436,10 +436,10 @@ impl<'a> CourseGrades {
/// # use std::sync::Arc;
/// # use rusaint::USaintSession;
/// # use rusaint::model::SemesterType;
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGrades };
/// # use rusaint::application::course_grades::{ model::CourseType, CourseGradesApplication };
/// # use rusaint::application::USaintClientBuilder;
/// # let session = Arc::new(USaintSession::with_password("20212345", "password").await.unwrap());
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGrades>().await.unwrap();
/// let mut app = USaintClientBuilder::new().session(session).build_into::<CourseGradesApplication>().await.unwrap();
/// let classes = app.classes(CourseType::Bachelor, "2022", SemesterType::Two, false).await.unwrap();
/// let class = classes.iter().next().unwrap();
/// let class_detail = app.class_detail(CourseType::Bachelor, "2022", SemesterType::Two, class.code()).await.unwrap();
Expand Down Expand Up @@ -495,15 +495,15 @@ impl<'a> CourseGrades {
}
}

/// [`CourseGrades`]에서 사용하는 데이터
/// [`CourseGradesApplication`]에서 사용하는 데이터
pub mod model;

#[cfg(test)]
mod test {
use serial_test::serial;

use crate::{
application::{course_grades::CourseGrades, USaintClientBuilder},
application::{course_grades::CourseGradesApplication, USaintClientBuilder},
global_test_utils::get_session,
webdynpro::element::{layout::PopupWindow, Element},
};
Expand All @@ -514,7 +514,7 @@ mod test {
let session = get_session().await.unwrap();
let mut app = USaintClientBuilder::new()
.session(session)
.build_into::<CourseGrades>()
.build_into::<CourseGradesApplication>()
.await
.unwrap();
app.close_popups().await.unwrap();
Expand Down
6 changes: 3 additions & 3 deletions src/application/course_schedule/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ use crate::{
use super::{USaintApplication, USaintClient};

/// [강의시간표](https://ecc.ssu.ac.kr/sap/bc/webdynpro/SAP/ZCMW2100)
pub struct CourseSchedule {
pub struct CourseScheduleApplication {
client: USaintClient,
}

impl USaintApplication for CourseSchedule {
impl USaintApplication for CourseScheduleApplication {
const APP_NAME: &'static str = "ZCMW2100";

fn from_client(client: USaintClient) -> Result<Self, RusaintError> {
Expand All @@ -40,7 +40,7 @@ impl USaintApplication for CourseSchedule {
}

#[allow(unused)]
impl<'a> CourseSchedule {
impl<'a> CourseScheduleApplication {
// 메인 요소
define_elements! {
PERIOD_YEAR: ComboBox<'a> = "ZCMW_PERIOD_RE.ID_A61C4ED604A2BFC2A8F6C6038DE6AF18:VIW_MAIN.PERYR";
Expand Down
51 changes: 3 additions & 48 deletions src/application/course_schedule/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,8 @@ pub enum LectureCategory {
/// 과목명
lecture_name: String,
},
/// 교직이수
/// 교직
Education,
/// 평생교육사
LifelongLearning,
/// 일반선택
StandardSelection,
/// 대학원
Graduated {
/// 단과대명
Expand Down Expand Up @@ -96,8 +92,6 @@ pub enum LectureCategory {
/// 전공명
major: Option<String>,
},
/// 듀얼리스팅 과목
DualListing,
/// 숭실사이버대
Cyber,
}
Expand Down Expand Up @@ -142,16 +136,6 @@ impl LectureCategory {
Self::Education
}

/// 평생교육사 분류의 [`LectureCategory`]를 만듭니다.
pub fn lifelong_learning() -> Self {
Self::LifelongLearning
}

/// 일반선택 분류의 [`LectureCategory`]를 만듭니다.
pub fn standard_selection() -> Self {
Self::StandardSelection
}

/// 대학원 분류의 [`LectureCategory`]를 만듭니다.
pub fn graduated(collage: &str, department: &str) -> Self {
Self::Graduated {
Expand Down Expand Up @@ -197,11 +181,6 @@ impl LectureCategory {
}
}

/// 듀얼리스팅 과목 분류의 [`LectureCategory`]를 만듭니다.
pub fn dual_listing() -> Self {
Self::DualListing
}

/// 숭실사이버대 분류의 [`LectureCategory`]를 만듭니다.
pub fn cyber() -> Self {
Self::Cyber
Expand Down Expand Up @@ -312,22 +291,6 @@ impl LectureCategory {
}
Self::request(client, TAB_EDU, 4, SEARCH_EDU).await?;
}
LectureCategory::LifelongLearning => {
// 평생교육사
define_elements! {
TAB_LIFELONG: TabStripItem<'_> = "ZCMW2100.ID_0001:VIW_MAIN.TAB_LIFELONG";
SEARCH_LIFELONG: Button<'_> = "ZCMW2100.ID_0001:VIW_MAIN.BUTTON_LIFELONG";
}
Self::request(client, TAB_LIFELONG, 5, SEARCH_LIFELONG).await?;
}
LectureCategory::StandardSelection => {
// 일반선택
define_elements! {
TAB_ROTC_CYBER: TabStripItem<'_> = "ZCMW2100.ID_0001:VIW_MAIN.TAB_ROTC_CYBER";
SEARCH_ROTC_CYBER: Button<'_> = "ZCMW2100.ID_0001:VIW_MAIN.BUTTON_ROTC_CYBER";
}
Self::request(client, TAB_ROTC_CYBER, 6, SEARCH_ROTC_CYBER).await?;
}
LectureCategory::Graduated {
collage,
department,
Expand Down Expand Up @@ -437,14 +400,6 @@ impl LectureCategory {
.await?;
}
}
LectureCategory::DualListing => {
// 듀얼리스팅과목
define_elements! {
TAB_DUALLT_SM: TabStripItem<'_> = "ZCMW2100.ID_0001:VIW_MAIN.TAB_DUALLT_SM";
SEARCH_DUALLT: Button<'_> = "ZCMW2100.ID_0001:VIW_TAB_DUALLT_SM.BTN_DUALLT_SM";
}
Self::request(client, TAB_DUALLT_SM, 13, SEARCH_DUALLT).await?;
}
LectureCategory::Cyber => {
// 숭실사이버대
define_elements! {
Expand Down Expand Up @@ -600,8 +555,8 @@ pub struct Lecture {
#[serde(rename(deserialize = "공학인증"), default, deserialize_with = "deserialize_optional_string")]
abeek_info: Option<String>,
/// 교과영역
#[serde(rename(deserialize = "교과영역"))]
field: String,
#[serde(rename(deserialize = "교과영역"), default, deserialize_with = "deserialize_optional_string")]
field: Option<String>,
/// 과목번호
#[serde(rename(deserialize = "과목번호"))]
code: String,
Expand Down
Loading

0 comments on commit aec6959

Please sign in to comment.