classcharts-api
Advanced tools
Comparing version 2.0.0 to 2.1.0
@@ -1,3 +0,3 @@ | ||
import type { AxiosRequestConfig, AxiosInstance } from "axios"; | ||
import type { ActivityResponse, AnnouncementsResponse, AttendanceResponse, BadgesResponse, BehaviourResponse, DetentionsResponse, GetActivityOptions, GetAttendanceOptions, GetBehaviourOptions, GetFullActivityOptions, GetHomeworkOptions, GetLessonsOptions, GetStudentInfoResponse, HomeworksResponse, LessonsResponse } from "./types"; | ||
import { type Options as KyOptions } from "ky-universal"; | ||
import type { ActivityResponse, AnnouncementsResponse, AttendanceResponse, BadgesResponse, BehaviourResponse, DetentionsResponse, GetActivityOptions, GetAttendanceOptions, GetBehaviourOptions, GetFullActivityOptions, GetHomeworkOptions, GetLessonsOptions, GetStudentInfoResponse, HomeworksResponse, LessonsResponse } from "./types.js"; | ||
/** | ||
@@ -12,3 +12,2 @@ * The base client | ||
protected API_BASE: string; | ||
protected axios: AxiosInstance; | ||
/** | ||
@@ -18,5 +17,5 @@ * | ||
*/ | ||
constructor(API_BASE: string, axiosConfig?: AxiosRequestConfig); | ||
constructor(API_BASE: string); | ||
getNewSessionId(): Promise<void>; | ||
makeAuthedRequest(path: string, axiosOptions: Omit<AxiosRequestConfig, "path">, options?: { | ||
makeAuthedRequest(path: string, kyOptions: KyOptions, options?: { | ||
revalidateToken?: boolean; | ||
@@ -23,0 +22,0 @@ }): Promise<any>; |
@@ -1,13 +0,7 @@ | ||
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ClasschartsClient = void 0; | ||
const axios_1 = __importDefault(require("axios")); | ||
const consts_1 = require("./consts"); | ||
import ky from "ky-universal"; | ||
import { PING_INTERVAL } from "./consts.js"; | ||
/** | ||
* The base client | ||
*/ | ||
class ClasschartsClient { | ||
export class ClasschartsClient { | ||
/** | ||
@@ -17,3 +11,3 @@ * | ||
*/ | ||
constructor(API_BASE, axiosConfig) { | ||
constructor(API_BASE) { | ||
this.studentId = 0; | ||
@@ -25,9 +19,2 @@ this.sessionId = ""; | ||
this.API_BASE = API_BASE; | ||
this.axios = axios_1.default.create({ | ||
...axiosConfig, | ||
headers: { | ||
...axiosConfig?.headers, | ||
}, | ||
validateStatus: () => true, | ||
}); | ||
} | ||
@@ -39,6 +26,3 @@ async getNewSessionId() { | ||
method: "POST", | ||
data: pingFormData.toString(), | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}, | ||
body: pingFormData, | ||
}, { revalidateToken: false }); | ||
@@ -48,3 +32,3 @@ this.sessionId = pingData.meta.session_id; | ||
} | ||
async makeAuthedRequest(path, axiosOptions, options) { | ||
async makeAuthedRequest(path, kyOptions, options) { | ||
if (!this.sessionId) | ||
@@ -59,20 +43,20 @@ throw new Error("No session ID"); | ||
const requestOptions = { | ||
...axiosOptions, | ||
url: path, | ||
...kyOptions, | ||
headers: { | ||
Cookie: this?.authCookies?.join(";") ?? [], | ||
authorization: "Basic " + this.sessionId, | ||
...axiosOptions.headers, | ||
Authorization: "Basic " + this.sessionId, | ||
...kyOptions.headers, | ||
}, | ||
}; | ||
if (options?.revalidateToken === true && this.lastPing) { | ||
if (Date.now() - this.lastPing + 5000 > consts_1.PING_INTERVAL) { | ||
if (Date.now() - this.lastPing + 5000 > PING_INTERVAL) { | ||
await this.getNewSessionId(); | ||
} | ||
} | ||
const request = await this.axios.request(requestOptions); | ||
const responseJSON = request.data; | ||
const request = await ky(path, requestOptions); | ||
const responseJSON = (await request.json()); | ||
if (responseJSON.success == 0) { | ||
throw new Error(responseJSON.error); | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
return responseJSON; | ||
@@ -85,5 +69,7 @@ } | ||
async getStudentInfo() { | ||
const body = new URLSearchParams(); | ||
body.append("include_data", "true"); | ||
const data = await this.makeAuthedRequest(this.API_BASE + "/ping", { | ||
method: "POST", | ||
data: "include_data=true", | ||
body: body, | ||
}); | ||
@@ -229,3 +215,2 @@ return data; | ||
} | ||
exports.ClasschartsClient = ClasschartsClient; | ||
//# sourceMappingURL=baseClient.js.map |
@@ -1,8 +0,5 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.PING_INTERVAL = exports.API_BASE_PARENT = exports.API_BASE_STUDENT = exports.BASE_URL = void 0; | ||
exports.BASE_URL = "https://www.classcharts.com"; | ||
exports.API_BASE_STUDENT = `${exports.BASE_URL}/apiv2student`; | ||
exports.API_BASE_PARENT = `${exports.BASE_URL}/apiv2parent`; | ||
exports.PING_INTERVAL = 180 * 1000; // 3 minutes | ||
export const BASE_URL = "https://www.classcharts.com"; | ||
export const API_BASE_STUDENT = `${BASE_URL}/apiv2student`; | ||
export const API_BASE_PARENT = `${BASE_URL}/apiv2parent`; | ||
export const PING_INTERVAL = 180 * 1000; // 3 minutes | ||
//# sourceMappingURL=consts.js.map |
@@ -1,2 +0,2 @@ | ||
export * from "./parentClient"; | ||
export * from "./studentClient"; | ||
export * from "./parentClient.js"; | ||
export * from "./studentClient.js"; |
@@ -1,19 +0,3 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./parentClient"), exports); | ||
__exportStar(require("./studentClient"), exports); | ||
export * from "./parentClient.js"; | ||
export * from "./studentClient.js"; | ||
//# sourceMappingURL=index.js.map |
@@ -1,4 +0,3 @@ | ||
import type { AxiosRequestConfig } from "axios"; | ||
import type { GetPupilsResponse } from "./types"; | ||
import { ClasschartsClient } from "./baseClient"; | ||
import type { GetPupilsResponse } from "./types.js"; | ||
import { ClasschartsClient } from "./baseClient.js"; | ||
/** | ||
@@ -16,3 +15,3 @@ * Parent Client | ||
*/ | ||
constructor(email: string, password: string, axiosConfig?: AxiosRequestConfig); | ||
constructor(email: string, password: string); | ||
/** | ||
@@ -19,0 +18,0 @@ * Logs the user in the client and authenticates with classcharts |
@@ -1,11 +0,9 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ParentClient = void 0; | ||
const baseClient_1 = require("./baseClient"); | ||
const consts_1 = require("./consts"); | ||
const utils_1 = require("./utils"); | ||
import ky from "ky-universal"; | ||
import { ClasschartsClient } from "./baseClient.js"; | ||
import { API_BASE_PARENT, BASE_URL } from "./consts.js"; | ||
import { parseCookies } from "./utils.js"; | ||
/** | ||
* Parent Client | ||
*/ | ||
class ParentClient extends baseClient_1.ClasschartsClient { | ||
export class ParentClient extends ClasschartsClient { | ||
/** | ||
@@ -16,4 +14,4 @@ * | ||
*/ | ||
constructor(email, password, axiosConfig) { | ||
super(consts_1.API_BASE_PARENT, axiosConfig); | ||
constructor(email, password) { | ||
super(API_BASE_PARENT); | ||
this.password = ""; | ||
@@ -36,23 +34,24 @@ this.email = ""; | ||
formData.append("recaptcha-token", "no-token-avaliable"); | ||
const request = await this.axios.request({ | ||
url: consts_1.BASE_URL + "/parent/login", | ||
const headers = new Headers({ | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}); | ||
const response = await ky(BASE_URL + "/parent/login", { | ||
method: "POST", | ||
data: formData.toString(), | ||
maxRedirects: 0, | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}, | ||
validateStatus: () => true, | ||
body: formData, | ||
headers: headers, | ||
}); | ||
if (request.status != 302 || !request.headers["set-cookie"]) | ||
throw new Error("Unauthenticated: Classcharts returned an error"); | ||
const cookies = String(request.headers["set-cookie"]); | ||
if (response.status != 302 || !response.headers.get("set-cookie")) | ||
throw new Error("Unauthenticated: Classcharts returned an error: " + | ||
response.status + | ||
" " + | ||
response.statusText); | ||
const cookies = String(response.headers.get("set-cookie")); | ||
// this.authCookies = cookies.split(";"); | ||
const sessionCookies = (0, utils_1.parseCookies)(cookies); | ||
const sessionCookies = parseCookies(cookies); | ||
const sessionID = JSON.parse(String(sessionCookies["parent_session_credentials"])); | ||
this.sessionId = sessionID.session_id; | ||
super.sessionId = sessionID.session_id; | ||
this.pupils = await this.getPupils(); | ||
if (!this.pupils) | ||
throw new Error("Account has no pupils attached"); | ||
this.studentId = this.pupils[0].id; | ||
super.studentId = this.pupils[0].id; | ||
} | ||
@@ -64,3 +63,3 @@ /** | ||
async getPupils() { | ||
return this.makeAuthedRequest(this.API_BASE + "/pupils", { | ||
return super.makeAuthedRequest(super.API_BASE + "/pupils", { | ||
method: "GET", | ||
@@ -80,3 +79,3 @@ }); | ||
if (pupil.id == pupilId) { | ||
this.studentId = pupil.id; | ||
super.studentId = pupil.id; | ||
return; | ||
@@ -88,3 +87,2 @@ } | ||
} | ||
exports.ParentClient = ParentClient; | ||
//# sourceMappingURL=parentClient.js.map |
@@ -1,3 +0,2 @@ | ||
import type { AxiosRequestConfig } from "axios"; | ||
import { ClasschartsClient } from "./baseClient"; | ||
import { ClasschartsClient } from "./baseClient.js"; | ||
/** | ||
@@ -14,3 +13,3 @@ * Student Client | ||
*/ | ||
constructor(studentCode: string, dateOfBirth?: string, axiosConfig?: AxiosRequestConfig); | ||
constructor(studentCode: string, dateOfBirth?: string); | ||
/** | ||
@@ -17,0 +16,0 @@ * Initialises the client and authenticates with classcharts |
@@ -1,11 +0,9 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.StudentClient = void 0; | ||
const consts_1 = require("./consts"); | ||
const baseClient_1 = require("./baseClient"); | ||
const utils_1 = require("./utils"); | ||
import { API_BASE_STUDENT, BASE_URL } from "./consts.js"; | ||
import { ClasschartsClient } from "./baseClient.js"; | ||
import { parseCookies } from "./utils.js"; | ||
import ky from "ky-universal"; | ||
/** | ||
* Student Client | ||
*/ | ||
class StudentClient extends baseClient_1.ClasschartsClient { | ||
export class StudentClient extends ClasschartsClient { | ||
/** | ||
@@ -16,4 +14,4 @@ * | ||
*/ | ||
constructor(studentCode, dateOfBirth, axiosConfig) { | ||
super(consts_1.API_BASE_STUDENT, axiosConfig); | ||
constructor(studentCode, dateOfBirth) { | ||
super(API_BASE_STUDENT); | ||
this.studentCode = ""; | ||
@@ -36,17 +34,17 @@ this.dateOfBirth = ""; | ||
formData.append("recaptcha-token", "no-token-avaliable"); | ||
const request = await this.axios.request({ | ||
url: consts_1.BASE_URL + "/student/login", | ||
const request = await ky(BASE_URL + "/student/login", { | ||
method: "POST", | ||
data: formData.toString(), | ||
maxRedirects: 0, | ||
headers: { | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}, | ||
validateStatus: () => true, | ||
body: formData, | ||
redirect: "manual", | ||
throwHttpErrors: false, | ||
}); | ||
if (request.status != 302 || !request.headers["set-cookie"]) | ||
throw new Error("Unauthenticated: Classcharts returned an error"); | ||
const cookies = String(request.headers["set-cookie"]); | ||
this.authCookies = cookies.split(";"); | ||
const sessionCookies = (0, utils_1.parseCookies)(cookies); | ||
if (request.status != 302 || !request.headers.get("set-cookie")) { | ||
throw new Error("Unauthenticated: Classcharts returned an error: " + | ||
request.status + | ||
" " + | ||
request.statusText); | ||
} | ||
const cookies = String(request.headers.get("set-cookie")); | ||
this.authCookies = cookies.split(","); | ||
const sessionCookies = parseCookies(cookies); | ||
const sessionID = JSON.parse(String(sessionCookies["student_session_credentials"])); | ||
@@ -59,3 +57,2 @@ this.sessionId = sessionID.session_id; | ||
} | ||
exports.StudentClient = StudentClient; | ||
//# sourceMappingURL=studentClient.js.map |
@@ -1,2 +0,2 @@ | ||
type ClassChartsResponse<T, E> = { | ||
export type ClassChartsResponse<T, E> = { | ||
data: T; | ||
@@ -3,0 +3,0 @@ meta: E; |
@@ -1,3 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
export {}; | ||
//# sourceMappingURL=types.js.map |
@@ -1,5 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.parseCookies = void 0; | ||
function parseCookies(input) { | ||
export function parseCookies(input) { | ||
const output = {}; | ||
@@ -9,7 +6,11 @@ const cookies = input.split(","); | ||
const cookieSplit = cookie.split(";")[0].split("="); | ||
output[decodeURIComponent(cookieSplit[0])] = decodeURIComponent(cookieSplit[1]); | ||
output[leftTrim(decodeURIComponent(cookieSplit[0]))] = decodeURIComponent(cookieSplit[1]); | ||
} | ||
return output; | ||
} | ||
exports.parseCookies = parseCookies; | ||
function leftTrim(str) { | ||
if (!str) | ||
return str; | ||
return str.replace(/^\s+/g, ""); | ||
} | ||
//# sourceMappingURL=utils.js.map |
{ | ||
"name": "classcharts-api", | ||
"version": "2.0.0", | ||
"type": "module", | ||
"version": "2.1.0", | ||
"description": "A typescript wrapper for getting information from the Classcharts API", | ||
@@ -23,3 +24,4 @@ "keywords": [ | ||
"test": "jest", | ||
"prepublishOnly": "pnpm run build" | ||
"prepublishOnly": "pnpm run build", | ||
"publishNow": "pnpx np --no-publish && npm publish" | ||
}, | ||
@@ -29,3 +31,3 @@ "author": "James Cook", | ||
"dependencies": { | ||
"axios": "^1.3.5" | ||
"ky-universal": "^0.11.0" | ||
}, | ||
@@ -37,6 +39,6 @@ "files": [ | ||
"@types/jest": "^29.5.0", | ||
"@types/node": "^18", | ||
"@typescript-eslint/eslint-plugin": "^5.57.1", | ||
"@typescript-eslint/parser": "^5.57.1", | ||
"eslint": "^8.37.0", | ||
"@types/node": "^18.15.11", | ||
"@typescript-eslint/eslint-plugin": "^5.58.0", | ||
"@typescript-eslint/parser": "^5.58.0", | ||
"eslint": "^8.38.0", | ||
"eslint-config-prettier": "^8.8.0", | ||
@@ -47,4 +49,4 @@ "jest": "^29.5.0", | ||
"ts-jest": "^29.1.0", | ||
"typedoc": "^0.23.28", | ||
"typescript": "^5.0.3" | ||
"typedoc": "^0.24.2", | ||
"typescript": "^5.0.4" | ||
}, | ||
@@ -51,0 +53,0 @@ "types": "./dist/index.d.ts", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Yes
42682
882
+ Addedky-universal@^0.11.0
+ Addedabort-controller@3.0.0(transitive)
+ Addeddata-uri-to-buffer@4.0.1(transitive)
+ Addedevent-target-shim@5.0.1(transitive)
+ Addedfetch-blob@3.2.0(transitive)
+ Addedformdata-polyfill@4.0.10(transitive)
+ Addedky@1.7.5(transitive)
+ Addedky-universal@0.11.0(transitive)
+ Addednode-domexception@1.0.0(transitive)
+ Addednode-fetch@3.3.2(transitive)
+ Addedweb-streams-polyfill@3.3.3(transitive)
- Removedaxios@^1.3.5
- Removedasynckit@0.4.0(transitive)
- Removedaxios@1.8.1(transitive)
- Removedcall-bind-apply-helpers@1.0.2(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removeddunder-proto@1.0.1(transitive)
- Removedes-define-property@1.0.1(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedes-object-atoms@1.1.1(transitive)
- Removedes-set-tostringtag@2.1.0(transitive)
- Removedfollow-redirects@1.15.9(transitive)
- Removedform-data@4.0.2(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedget-intrinsic@1.3.0(transitive)
- Removedget-proto@1.0.1(transitive)
- Removedgopd@1.2.0(transitive)
- Removedhas-symbols@1.1.0(transitive)
- Removedhas-tostringtag@1.0.2(transitive)
- Removedhasown@2.0.2(transitive)
- Removedmath-intrinsics@1.1.0(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedproxy-from-env@1.1.0(transitive)