-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from ddanilyuk/feature/campus
feature/campus
- Loading branch information
Showing
19 changed files
with
568 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// | ||
// CampusController.swift | ||
// | ||
// | ||
// Created by Denys Danyliuk on 02.06.2022. | ||
// | ||
|
||
import Vapor | ||
import KPIHubParser | ||
import Routes | ||
|
||
struct StudySheetResponse: Content { | ||
let studySheet: [StudySheetItem] | ||
} | ||
|
||
struct StudySheetItem: Content { | ||
let lesson: StudySheetLesson | ||
let activities: [StudySheetActivity] | ||
} | ||
|
||
|
||
final class CampusController { | ||
|
||
func userInfo( | ||
request: Request, | ||
loginQuery: CampusLoginQuery | ||
) async throws -> UserInfo { | ||
let oauthResponse = try await oauth(request: request, loginQuery: loginQuery) | ||
let campusAPICredentials = try oauthResponse.content.decode(CampusAPICredentials.self) | ||
|
||
let accountInfoResponse: ClientResponse = try await request.client.get( | ||
"https://api.campus.kpi.ua/Account/Info", | ||
beforeSend: { clientRequest in | ||
let auth = BearerAuthorization(token: campusAPICredentials.accessToken) | ||
clientRequest.headers.bearerAuthorization = auth | ||
} | ||
) | ||
return try accountInfoResponse.content.decode(UserInfo.self) | ||
} | ||
|
||
func studySheet( | ||
request: Request, | ||
loginQuery: CampusLoginQuery | ||
) async throws -> StudySheetResponse { | ||
|
||
let oauthResponse = try await oauth(request: request, loginQuery: loginQuery) | ||
let campusAPICredentials = try oauthResponse.content.decode(CampusAPICredentials.self) | ||
|
||
let authPHPResponse: ClientResponse = try await request.client.get( | ||
"https://campus.kpi.ua/auth.php", | ||
beforeSend: { clientRequest in | ||
clientRequest.headers.cookie = oauthResponse.headers.setCookie | ||
} | ||
) | ||
|
||
let studySheetResponse: ClientResponse = try await request.client.get( | ||
"https://campus.kpi.ua/student/index.php?mode=studysheet", | ||
beforeSend: { clientRequest in | ||
let auth = BearerAuthorization(token: campusAPICredentials.accessToken) | ||
clientRequest.headers.bearerAuthorization = auth | ||
if let phpSessionId = authPHPResponse.headers.setCookie?.all["PHPSESSID"] { | ||
clientRequest.headers.cookie = HTTPCookies( | ||
dictionaryLiteral: ("PHPSESSID", phpSessionId) | ||
) | ||
} | ||
} | ||
) | ||
|
||
let html = try (studySheetResponse.body).htmlString(encoding: .windowsCP1251) | ||
|
||
let studySheetItems = try await StudySheetLessonsParser().parse(html) | ||
.asyncMap { lesson -> StudySheetItem in | ||
let response: ClientResponse = try await request.client.post( | ||
"https://campus.kpi.ua\(lesson.link)", | ||
beforeSend: { clientRequest in | ||
let auth = BearerAuthorization(token: campusAPICredentials.accessToken) | ||
clientRequest.headers.bearerAuthorization = auth | ||
if let phpSessionId = authPHPResponse.headers.setCookie?.all["PHPSESSID"] { | ||
clientRequest.headers.cookie = HTTPCookies( | ||
dictionaryLiteral: ("PHPSESSID", phpSessionId) | ||
) | ||
} | ||
} | ||
) | ||
let html = try (response.body).htmlString(encoding: .windowsCP1251) | ||
let activities = try StudySheetActivitiesParser().parse(html) | ||
return StudySheetItem(lesson: lesson, activities: activities) | ||
} | ||
|
||
return StudySheetResponse(studySheet: studySheetItems) | ||
} | ||
|
||
// MARK: - Helpers | ||
|
||
func oauth( | ||
request: Request, | ||
loginQuery: CampusLoginQuery | ||
) async throws -> ClientResponse { | ||
try await request.client.post( | ||
"https://api.campus.kpi.ua/oauth/token", | ||
beforeSend: { clientRequest in | ||
try clientRequest.query.encode(loginQuery) | ||
} | ||
) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// ByteBuffer+HTML.swift | ||
// | ||
// | ||
// Created by Denys Danyliuk on 04.06.2022. | ||
// | ||
|
||
import Vapor | ||
import Foundation | ||
|
||
extension ByteBuffer { | ||
|
||
public func htmlString(encoding: String.Encoding = .utf8) throws -> String { | ||
let data = Data(buffer: self) | ||
guard | ||
let html = String(data: data, encoding: encoding) | ||
else { | ||
throw Abort(.internalServerError) | ||
} | ||
return html | ||
} | ||
|
||
} | ||
|
||
extension Optional where Wrapped == ByteBuffer { | ||
|
||
public func htmlString(encoding: String.Encoding = .utf8) throws -> String { | ||
switch self { | ||
case let .some(buffer): | ||
return try buffer.htmlString(encoding: encoding) | ||
case .none: | ||
throw Abort(.internalServerError) | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// CampusAPICredentials.swift | ||
// | ||
// | ||
// Created by Denys Danyliuk on 04.06.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
struct CampusAPICredentials: Equatable, Codable { | ||
|
||
let accessToken: String | ||
let sessionId: String | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case accessToken = "access_token" | ||
case sessionId | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,3 +48,9 @@ extension GroupModel: AsyncMigration { | |
} | ||
|
||
} | ||
|
||
// MARK: - GroupModel + Content | ||
|
||
extension GroupModel: Content { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// | ||
// UserInfo.swift | ||
// | ||
// | ||
// Created by Denys Danyliuk on 04.06.2022. | ||
// | ||
|
||
import Foundation | ||
import Vapor | ||
|
||
struct UserInfo: Codable, Equatable { | ||
|
||
// MARK: - StudyGroup | ||
|
||
struct InfoItem: Codable, Equatable { | ||
let id: Int | ||
let name: String | ||
} | ||
|
||
// MARK: - Profile | ||
|
||
struct Profile: Codable, Equatable { | ||
let id: Int | ||
let profile: String | ||
let subdivision: InfoItem | ||
} | ||
|
||
let modules: [String] | ||
let position: [InfoItem] | ||
let subdivision: [InfoItem] | ||
let studyGroup: InfoItem | ||
let sid: String | ||
let email: String | ||
let scientificInterest: String | ||
let username: String | ||
let tgAuthLinked: Bool | ||
let profiles: [Profile] | ||
let id: Int | ||
let userIdentifier: String | ||
let fullName: String | ||
let photo: String | ||
let credo: String | ||
} | ||
|
||
// MARK: UserInfo + Content | ||
|
||
extension UserInfo: Content { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// StudySheetActivity.swift | ||
// | ||
// | ||
// Created by Denys Danyliuk on 03.06.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct StudySheetActivity: Codable { | ||
|
||
public let date: String | ||
public let mark: String | ||
public let type: String | ||
public let teacher: String | ||
public let note: String | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// StudySheetLesson.swift | ||
// | ||
// | ||
// Created by Denys Danyliuk on 03.06.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct StudySheetLesson: Codable { | ||
|
||
public let year: String | ||
public let semester: String | ||
public let link: String | ||
public let name: String | ||
public let teacher: String | ||
|
||
} |
Oops, something went wrong.