UNPKG

jsjiit

Version:

Browser-compatible API for interacting with JIIT (Jaypee Institute of Information Technology) WebPortal. Bypasses CAPTCHA :)

889 lines (882 loc) 32.8 kB
// src/exceptions.js var APIError = class extends Error { constructor(message) { super(message); this.name = "APIError"; } }; var LoginError = class extends APIError { constructor(message) { super(message); this.name = "LoginError"; } }; var SessionError = class extends Error { constructor(message) { super(message); this.name = "SessionError"; } }; var SessionExpired = class extends SessionError { constructor(message) { super(message); this.name = "SessionExpired"; } }; var NotLoggedIn = class extends SessionError { constructor(message) { super(message); this.name = "NotLoggedIn"; } }; var AccountAPIError = class extends Error { constructor(message) { super(message); this.name = "AccountAPIError"; } }; // src/registration.js var RegisteredSubject = class _RegisteredSubject { /** * Class containing registered subject info like Lecturer name, credits, etc * @param {string} employee_name - Name of the employee/lecturer * @param {string} employee_code - Code of the employee * @param {string} minor_subject - Minor subject information * @param {string} remarks - Any remarks * @param {string} stytype - Style type * @param {number} credits - Number of credits * @param {string} subject_code - Code of the subject * @param {string} subject_component_code - Component code of the subject * @param {string} subject_desc - Description of the subject * @param {string} subject_id - ID of the subject * @param {string} audtsubject - Audit subject information */ constructor(employee_name, employee_code, minor_subject, remarks, stytype, credits, subject_code, subject_component_code, subject_desc, subject_id, audtsubject) { this.employee_name = employee_name; this.employee_code = employee_code; this.minor_subject = minor_subject; this.remarks = remarks; this.stytype = stytype; this.credits = credits; this.subject_code = subject_code; this.subject_component_code = subject_component_code; this.subject_desc = subject_desc; this.subject_id = subject_id; this.audtsubject = audtsubject; } /** * Static method to create a RegisteredSubject from a JSON object * @param {object} resp - JSON object representing RegisteredSubject * @returns {RegisteredSubject} A new RegisteredSubject instance */ static from_json(resp) { return new _RegisteredSubject( resp["employeename"], resp["employeecode"], resp["minorsubject"], resp["remarks"], resp["stytype"], resp["credits"], resp["subjectcode"], resp["subjectcomponentcode"], resp["subjectdesc"], resp["subjectid"], resp["audtsubject"] ); } }; var Registrations = class { /** * Class containing all registered subjects and total course credits for the semester * @param {object} resp - JSON response object with registrations and total credits */ constructor(resp) { this.raw_response = resp; this.total_credits = resp["totalcreditpoints"]; this.subjects = resp["registrations"].map(RegisteredSubject.from_json); } }; // src/attendance.js var AttendanceHeader = class _AttendanceHeader { /** * Class which contains header info in the Attendance API * @param {string} branchdesc - Description of the branch * @param {string} name - Name of the student or entity * @param {string} programdesc - Description of the program * @param {string} stynumber - Style number or identifier */ constructor(branchdesc, name, programdesc, stynumber) { this.branchdesc = branchdesc; this.name = name; this.programdesc = programdesc; this.stynumber = stynumber; } /** * Static method to create an AttendanceHeader from a JSON object * @param {object} resp - JSON object representing AttendanceHeader * @returns {AttendanceHeader} A new AttendanceHeader instance */ static from_json(resp) { return new _AttendanceHeader(resp.branchdesc, resp.name, resp.programdesc, resp.stynumber); } }; var Semester = class _Semester { /** * Class which contains Semester info * @param {string} registration_code - Registration code of the semester * @param {string} registration_id - Registration ID of the semester */ constructor(registration_code, registration_id) { this.registration_code = registration_code; this.registration_id = registration_id; } /** * Static method to create a Semester from a JSON object * @param {object} resp - JSON object representing Semester * @returns {Semester} A new Semester instance */ static from_json(resp) { return new _Semester(resp.registrationcode, resp.registrationid); } }; var AttendanceMeta = class { /** * Class which contains metadata for Attendance * @param {object} resp - JSON response object with headers and semesters */ constructor(resp) { this.raw_response = resp; this.headers = resp.headerlist.map(AttendanceHeader.from_json); this.semesters = resp.semlist.map(Semester.from_json); } /** * Returns the latest AttendanceHeader * @returns {AttendanceHeader} The first header in the list */ latest_header() { return this.headers[0]; } /** * Returns the latest Semester * @returns {Semester} The first semester in the list */ latest_semester() { return this.semesters[0]; } }; // src/exam.js var ExamEvent = class _ExamEvent { /** * Class containing exam event info * @param {string} exam_event_code - Code of the exam event * @param {number} event_from - Event from timestamp * @param {string} exam_event_desc - Description of the exam event * @param {string} registration_id - Registration ID * @param {string} exam_event_id - Exam event ID */ constructor(exam_event_code, event_from, exam_event_desc, registration_id, exam_event_id) { this.exam_event_code = exam_event_code; this.event_from = event_from; this.exam_event_desc = exam_event_desc; this.registration_id = registration_id; this.exam_event_id = exam_event_id; } /** * Static method to create an ExamEvent from a JSON object * @param {object} resp - JSON object representing ExamEvent * @returns {ExamEvent} A new ExamEvent instance */ static from_json(resp) { return new _ExamEvent( resp["exameventcode"], resp["eventfrom"], resp["exameventdesc"], resp["registrationid"], resp["exameventid"] ); } }; // src/utils.js function generate_date_seq(date = null) { if (date === null) { date = /* @__PURE__ */ new Date(); } const day = String(date.getDate()).padStart(2, "0"); const month = String(date.getMonth() + 1).padStart(2, "0"); const year = String(date.getFullYear()).slice(2); const weekday = String(date.getDay()); return day[0] + month[0] + year[0] + weekday + day[1] + month[1] + year[1]; } function get_random_char_seq(n) { const charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; let result = ""; for (let i = 0; i < n; i++) { const randomIndex = Math.floor(Math.random() * charset.length); result += charset[randomIndex]; } return result; } // src/encryption.js function base64Encode(data) { return btoa(String.fromCharCode.apply(null, new Uint8Array(data))); } var IV = new TextEncoder().encode("dcek9wb8frty1pnm"); async function generate_key(date = null) { const dateSeq = generate_date_seq(date); const keyData = new TextEncoder().encode("qa8y" + dateSeq + "ty1pn"); return window.crypto.subtle.importKey("raw", keyData, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]); } async function generate_local_name(date = null) { const randomCharSeq = get_random_char_seq(4); const dateSeq = generate_date_seq(date); const randomSuffix = get_random_char_seq(5); const nameBytes = new TextEncoder().encode(randomCharSeq + dateSeq + randomSuffix); const encryptedBytes = await encrypt(nameBytes); return base64Encode(encryptedBytes); } async function encrypt(data) { const key = await generate_key(); const encrypted = await window.crypto.subtle.encrypt({ name: "AES-CBC", iv: IV }, key, data); return new Uint8Array(encrypted); } async function serialize_payload(payload) { const raw = new TextEncoder().encode(JSON.stringify(payload)); const pbytes = await encrypt(raw); return base64Encode(pbytes); } // src/wrapper.js var API = "https://webportal.jiit.ac.in:6011/StudentPortalAPI"; var DEFCAPTCHA = { captcha: "phw5n", hidden: "gmBctEffdSg=" }; var WebPortalSession = class { /** * Creates a WebPortalSession instance from API response * @param {Object} resp - Response object from login API * @param {Object} resp.regdata - Registration data containing user details * @param {Array} resp.regdata.institutelist - List of institutes user has access to * @param {string} resp.regdata.memberid - Member ID of the user * @param {string} resp.regdata.userid - User ID * @param {string} resp.regdata.token - Token for authentication * @param {string} resp.regdata.clientid - Client ID * @param {string} resp.regdata.membertype - Type of member * @param {string} resp.regdata.name - Name of the user * @param {string} resp.regdata.enrollmentno - Enrollment number */ constructor(resp) { this.raw_response = resp; this.regdata = resp["regdata"]; let institute = this.regdata["institutelist"][0]; this.institute = institute["label"]; this.instituteid = institute["value"]; this.memberid = this.regdata["memberid"]; this.userid = this.regdata["userid"]; this.token = this.regdata["token"]; let expiry_timestamp = JSON.parse(atob(this.token.split(".")[1]))["exp"]; this.expiry = new Date(expiry_timestamp * 1e3); this.clientid = this.regdata["clientid"]; this.membertype = this.regdata["membertype"]; this.name = this.regdata["name"]; this.enrollmentno = this.regdata["enrollmentno"]; } /** * Generates authentication headers for API requests * @returns {Promise<Object>} Headers object containing Authorization and LocalName */ async get_headers() { const localname = await generate_local_name(); return { Authorization: `Bearer ${this.token}`, LocalName: localname }; } }; var WebPortal = class { /** * Creates a WebPortal instance */ constructor() { this.session = null; } /** * Internal method to make HTTP requests to the API * @private * @param {string} method - HTTP method (GET, POST etc) * @param {string} url - API endpoint URL * @param {Object} [options={}] - Request options * @param {Object} [options.headers] - Additional headers * @param {Object} [options.json] - JSON payload * @param {string} [options.body] - Raw body payload * @param {boolean} [options.authenticated] - Whether request needs authentication * @param {Error} [options.exception] - Custom error class to throw * @returns {Promise<Object>} API response * @throws {APIError} On API or network errors */ async __hit(method, url, options = {}) { let exception = APIError; if (options.exception) { exception = options.exception; delete options.exception; } console.log(options); let header; if (options.authenticated) { header = await this.session.get_headers(); delete options.authenticated; } else { let localname = await generate_local_name(); header = { LocalName: localname }; } if (options.headers) { options.headers = { ...options.headers, ...header }; } else { options.headers = header; } let fetchOptions = { method, headers: { "Content-Type": "application/json", ...options.headers } }; if (options.json) { fetchOptions.body = JSON.stringify(options.json); } else { fetchOptions.body = options.body; } try { console.log("fetching", url, "with options", fetchOptions); const response = await fetch(url, fetchOptions); if (response.status === 513) { throw new exception("JIIT Web Portal server is temporarily unavailable (HTTP 513). Please try again later."); } if (response.status === 401) { throw new SessionExpired(response.error); } const resp = await response.json(); if (resp.status && resp.status.responseStatus !== "Success") { throw new exception(`status: ${JSON.stringify(resp.status, null, 2)}`); } return resp; } catch (error) { if (error instanceof TypeError && error.message.includes("CORS")) { throw new exception("JIIT Web Portal server is temporarily unavailable. Please try again later."); } throw new exception(error.message || "Unknown error"); } } /** * Logs in a student user * @param {string} username - Student username * @param {string} password - Student password * @param {{captcha: string, hidden: string}} [captcha=DEFCAPTCHA] - CAPTCHA * @returns {Promise<WebPortalSession>} New session instance * @throws {LoginError} On login failure */ async student_login(username, password, captcha = DEFCAPTCHA) { let pretoken_endpoint = "/token/pretoken-check"; let token_endpoint = "/token/generate-token1"; let payload = { username, usertype: "S", captcha }; payload = await serialize_payload(payload); let resp = await this.__hit("POST", API + pretoken_endpoint, { body: payload, exception: LoginError }); let payload2 = resp["response"]; delete payload2["rejectedData"]; payload2["Modulename"] = "STUDENTMODULE"; payload2["passwordotpvalue"] = password; payload2 = await serialize_payload(payload2); const resp2 = await this.__hit("POST", API + token_endpoint, { body: payload2, exception: LoginError }); this.session = new WebPortalSession(resp2["response"]); return this.session; } /** * Gets personal information of logged in student * @returns {Promise<Object>} Student personal information */ async get_personal_info() { const ENDPOINT = "/studentpersinfo/getstudent-personalinformation"; const payload = { clinetid: "SOAU", instituteid: this.session.instituteid }; const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets bank account information of logged in student * @returns {Promise<Object>} Student bank information */ async get_student_bank_info() { const ENDPOINT = "/studentbankdetails/getstudentbankinfo"; const payload = { instituteid: this.session.instituteid, studentid: this.session.memberid }; const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Changes password for logged in student * @param {string} old_password - Current password * @param {string} new_password - New password * @returns {Promise<Object>} Response indicating success/failure * @throws {AccountAPIError} On password change failure */ async change_password(old_password, new_password) { const ENDPOINT = "/clxuser/changepassword"; const payload = { membertype: this.session.membertype, oldpassword: old_password, newpassword: new_password, confirmpassword: new_password }; const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true, exception: AccountAPIError }); return resp["response"]; } /** * Gets attendance metadata including headers and semesters * @returns {Promise<AttendanceMeta>} Attendance metadata */ async get_attendance_meta() { const ENDPOINT = "/StudentClassAttendance/getstudentInforegistrationforattendence"; const payload = { clientid: this.session.clientid, instituteid: this.session.instituteid, membertype: this.session.membertype }; const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return new AttendanceMeta(resp["response"]); } /** * Gets attendance details for a semester * @param {AttendanceHeader} header - Attendance header * @param {Semester} semester - Semester object * @returns {Promise<Object>} Attendance details */ async get_attendance(header, semester) { const ENDPOINT = "/StudentClassAttendance/getstudentattendancedetail"; const payload = await serialize_payload({ clientid: this.session.clientid, instituteid: this.session.instituteid, registrationcode: semester.registration_code, registrationid: semester.registration_id, stynumber: header.stynumber }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets attendance for every class of the subject for the semester. * @param {Semester} semester - Semester object * @param {string} subjectid - Subject ID * @param {string} individualsubjectcode - Individual subject code * @param {Array<string>} subjectcomponentids - Array of subject component IDs * @returns {Promise<Object>} Subject attendance details */ async get_subject_daily_attendance(semester, subjectid, individualsubjectcode, subjectcomponentids) { const ENDPOINT = "/StudentClassAttendance/getstudentsubjectpersentage"; const payload = await serialize_payload({ cmpidkey: subjectcomponentids.map((id) => ({ subjectcomponentid: id })), clientid: this.session.clientid, instituteid: this.session.instituteid, registrationcode: semester.registration_code, registrationid: semester.registration_id, subjectcode: individualsubjectcode, subjectid }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets list of registered semesters * @returns {Promise<Array<Semester>>} Array of semester objects */ async get_registered_semesters() { const ENDPOINT = "/reqsubfaculty/getregistrationList"; const payload = await serialize_payload({ instituteid: this.session.instituteid, studentid: this.session.memberid }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]["registrations"].map((i) => Semester.from_json(i)); } /** * Gets registered subjects and faculty details for a semester * @param {Semester} semester - Semester object * @returns {Promise<Registrations>} Registration details */ async get_registered_subjects_and_faculties(semester) { const ENDPOINT = "/reqsubfaculty/getfaculties"; const payload = await serialize_payload({ instituteid: this.session.instituteid, studentid: this.session.memberid, registrationid: semester.registration_id }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return new Registrations(resp["response"]); } /** * Gets semesters that have exam events * @returns {Promise<Array<Semester>>} Array of semester objects */ async get_semesters_for_exam_events() { const ENDPOINT = "/studentcommonsontroller/getsemestercode-withstudentexamevents"; const payload = await serialize_payload({ clientid: this.session.clientid, instituteid: this.session.instituteid, memberid: this.session.memberid }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]["semesterCodeinfo"]["semestercode"].map((i) => Semester.from_json(i)); } /** * Gets exam events for a semester * @param {Semester} semester - Semester object * @returns {Promise<Array<ExamEvent>>} Array of exam event objects */ async get_exam_events(semester) { const ENDPOINT = "/studentcommonsontroller/getstudentexamevents"; const payload = await serialize_payload({ instituteid: this.session.instituteid, registationid: semester.registration_id // not a typo }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]["eventcode"]["examevent"].map((i) => ExamEvent.from_json(i)); } /** * Gets exam schedule for an exam event * @param {ExamEvent} exam_event - Exam event object * @returns {Promise<Object>} Exam schedule details */ async get_exam_schedule(exam_event) { const ENDPOINT = "/studentsttattview/getstudent-examschedule"; const payload = await serialize_payload({ instituteid: this.session.instituteid, registrationid: exam_event.registration_id, exameventid: exam_event.exam_event_id }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets semesters that have marks available * @returns {Promise<Array<Semester>>} Array of semester objects */ async get_semesters_for_marks() { const ENDPOINT = "/studentcommonsontroller/getsemestercode-exammarks"; const payload = await serialize_payload({ instituteid: this.session.instituteid, studentid: this.session.memberid }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]["semestercode"].map((i) => Semester.from_json(i)); } /** * Downloads marks PDF for a semester * @param {Semester} semester - Semester object * @throws {APIError} On download failure */ async download_marks(semester) { const ENDPOINT = "/studentsexamview/printstudent-exammarks/" + // this.session.memberid + // "/" + this.session.instituteid + "/" + semester.registration_id + "/" + semester.registration_code; const localname = await generate_local_name(); let _headers = await this.session.get_headers(localname); const fetchOptions = { method: "GET", headers: _headers }; try { const resp = await fetch(API + ENDPOINT, fetchOptions); const blob = await resp.blob(); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `marks_${semester.registration_code}.pdf`; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); a.remove(); } catch (error) { throw new APIError(error); } } /** * Gets semesters that have grade cards available * @returns {Promise<Array<Semester>>} Array of semester objects */ async get_semesters_for_grade_card() { const ENDPOINT = "/studentgradecard/getregistrationList"; const payload = await serialize_payload({ instituteid: this.session.instituteid }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]["registrations"].map((i) => Semester.from_json(i)); } /** * Gets program ID for grade card * @private * @returns {Promise<string>} Program ID */ async __get_program_id() { const ENDPOINT = "/studentgradecard/getstudentinfo"; const payload = await serialize_payload({ instituteid: this.session.instituteid }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]["programid"]; } /** * Gets grade card for a semester * @param {Semester} semester - Semester object * @returns {Promise<Object>} Grade card details */ async get_grade_card(semester) { const programid = await this.__get_program_id(); const ENDPOINT = "/studentgradecard/showstudentgradecard"; const payload = await serialize_payload({ branchid: this.session.branch_id, instituteid: this.session.instituteid, programid, registrationid: semester.registration_id }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets current semester number * @private * @returns {Promise<number>} Current semester number */ async __get_semester_number() { const ENDPOINT = "/studentsgpacgpa/checkIfstudentmasterexist"; const payload = await serialize_payload({ instituteid: this.session.instituteid, studentid: this.session.memberid, name: this.session.name, enrollmentno: this.session.enrollmentno }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]["studentlov"]["currentsemester"]; } /** * Gets SGPA and CGPA details * @returns {Promise<Object>} SGPA and CGPA details */ async get_sgpa_cgpa() { const ENDPOINT = "/studentsgpacgpa/getallsemesterdata"; const stynumber = await this.__get_semester_number(); const payload = await serialize_payload({ instituteid: this.session.instituteid, studentid: this.session.memberid, stynumber }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets pending miscellaneous charges/fines for the logged-in student * @returns {Promise<Object>} The raw 'response' dict from the API. * If there are no pending payments, the API returns * status: Failure with error "NO APPROVED REQUEST FOUND". * @throws {APIError} On any non-Success responseStatus */ async get_fines_msc_charges() { const ENDPOINT = "/collectionpendingpayments/getpendingpaymentsdata"; const payload = await serialize_payload({ instituteid: this.session.instituteid, studentid: this.session.memberid }); const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets the fee summary for the logged-in student * @returns {Promise<Object>} The raw 'response' dict from the API * @throws {APIError} On any non-Success responseStatus */ async get_fee_summary() { const ENDPOINT = "/studentfeeledger/loadfeesummary"; const payload = { instituteid: this.session.instituteid }; const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } /** * Gets subject choices for a semester * @param {Semester} semester - A Semester object * @returns {Promise<Object>} A dictionary with subject choices data * @throws {APIError} Raised for generic API error */ async get_subject_choices(semester) { const ENDPOINT = "/studentchoiceprint/getsubjectpreference"; const payload = { instituteid: this.session.instituteid, studentid: this.session.memberid, registrationid: semester.registration_id }; const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); return resp["response"]; } async get_hostel_details() { const ENDPOINT = "/myhostelallocationdetail/gethostelallocationdetail"; const payload = { clientid: this.session.clientid, instituteid: this.session.instituteid, studentid: this.session.memberid }; const resp = await this.__hit("POST", API + ENDPOINT, { json: payload, authenticated: true }); if (!resp?.response) { throw new Error("Hostel details not found"); } return resp.response; } async fill_feedback_form(feedback_option) { const SEMESTER_ENDPOINT = "/feedbackformcontroller/getFeedbackEvent"; const payload = { instituteid: this.session.instituteid }; const resp = await this.__hit("POST", API + SEMESTER_ENDPOINT, { json: payload, authenticated: true }); let semesters = resp["response"]["eventList"]; let latest_semester = semesters[semesters.length - 1]; let latest_semester_code = latest_semester["eventcode"]; let latest_semester_event_id = latest_semester["eventid"]; let latest_semester_event_description = latest_semester["eventdescription"]; const GRID_ENDPOINT = "/feedbackformcontroller/getGriddataForFeedback"; const grid_payload = await serialize_payload({ instituteid: this.session.instituteid, studentid: this.session.memberid, eventid: latest_semester_event_id }); const grid_resp = await this.__hit("POST", API + GRID_ENDPOINT, { json: grid_payload, authenticated: true }); let grid_data = grid_resp["response"]["gridData"]; let question_feedback_payload_array = grid_data.map((data) => { return { instituteid: this.session.instituteid, eventid: latest_semester_event_id, eventdescription: latest_semester_event_description, facultyid: data["employeeid"], facultyname: data["employeename"], registrationid: data["registrationid"], studentid: data["studentid"], subjectcode: data["subjectcode"], subjectcomponentcode: data["subjectcomponentcode"], subjectcomponentid: data["subjectcomponentid"], subjectdescription: data["subjectdescription"], subjectid: data["subjectid"] }; }); const GET_QUESTIONS_ENDPOINT = "/feedbackformcontroller/getIemQuestion"; const SAVE_ENDPOINT = "/feedbackformcontroller/savedatalist"; for (let question_feedback_payload of question_feedback_payload_array) { try { const questions_api_resp2 = await this.__hit("POST", API + GET_QUESTIONS_ENDPOINT, { json: question_feedback_payload, authenticated: true }); } catch (error) { continue; } if (!questions_api_resp || !questions_api_resp.response || !questions_api_resp.response.questionList) { console.error( "Failed to retrieve question list or invalid response structure for payload:", question_feedback_payload, "Response:", questions_api_resp ); continue; } let actual_question_list = questions_api_resp["response"]["questionList"]; let questions_to_submit = actual_question_list.map((q) => ({ ...q, // Spread existing question properties rating: feedback_option // Set the rating using the function's argument })); let save_data_payload = { instituteid: question_feedback_payload.instituteid, // This comes from this.session.instituteid via map studentid: this.session.memberid, // Logged-in user's ID eventid: question_feedback_payload.eventid, // This comes from latest_semester_event_id via map subjectid: question_feedback_payload.subjectid, // From the specific grid item facultyid: question_feedback_payload.facultyid, // From the specific grid item registrationid: question_feedback_payload.registrationid, // From the specific grid item questionid: questions_to_submit, // The list of questions with updated ratings facultycomments: null, // Defaulting to null; can be parameterized if needed coursecomments: null // Defaulting to null; can be parameterized if needed }; save_data_payload = await serialize_payload(save_data_payload); await this.__hit("POST", API + SAVE_ENDPOINT, { json: save_data_payload, authenticated: true }); } } }; function authenticated(method) { return function(...args) { if (this.session == null) { throw new NotLoggedIn(); } return method.apply(this, args); }; } var authenticatedMethods = [ "get_personal_info", "get_student_bank_info", "change_password", "get_attendance_meta", "get_attendance", "get_subject_daily_attendance", "get_registered_semesters", "get_registered_subjects_and_faculties", "get_semesters_for_exam_events", "get_exam_events", "get_exam_schedule", "get_semesters_for_marks", "download_marks", "get_semesters_for_grade_card", "__get_program_id", "get_grade_card", "__get_semester_number", "get_sgpa_cgpa", "get_hostel_details", "get_fines_msc_charges", "get_fee_summary", "get_subject_choices" ]; authenticatedMethods.forEach((methodName) => { WebPortal.prototype[methodName] = authenticated(WebPortal.prototype[methodName]); }); export { API, APIError, AccountAPIError, AttendanceHeader, AttendanceMeta, DEFCAPTCHA, ExamEvent, LoginError, NotLoggedIn, RegisteredSubject, Registrations, Semester, SessionError, SessionExpired, WebPortal, WebPortalSession, generate_local_name }; //# sourceMappingURL=jsjiit.esm.js.map