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

Issue#27 / Draft 1 : Email template for Invitation to Learners by Instructors #28

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
10e87e9
new
NeoZ666 Apr 18, 2024
8c6500f
new stuff
NeoZ666 May 4, 2024
14febba
Merge branch 'main' of https://github.com/NeoZ666/learning-tokens
NeoZ666 May 4, 2024
c094bc1
changes.
NeoZ666 May 5, 2024
789c964
Working modal pop up for sending emails
NeoZ666 May 6, 2024
527d434
fixed config
NeoZ666 May 6, 2024
607dfe5
Modals and Mails both added
NeoZ666 May 7, 2024
e30cd9d
Updated with both mail and UI
NeoZ666 May 7, 2024
0fc732c
Fixed hardhat.config
NeoZ666 May 7, 2024
63c10d5
Removed Redundancy
NeoZ666 May 7, 2024
66dd62b
Merge pull request #1 from NeoZ666/Modal-branch
NeoZ666 May 7, 2024
81c8a16
Reverted changes to Register.tsx
NeoZ666 May 7, 2024
fc9b4dc
Reverted to original state
NeoZ666 May 7, 2024
012be64
Designed custom mails for invites
NeoZ666 May 7, 2024
cfd936e
Updated Directory Path for Email dev in package.json
NeoZ666 May 7, 2024
4f0fb55
Removed Redundancy
NeoZ666 May 7, 2024
0f872c7
Small Fixes
NeoZ666 May 7, 2024
d694415
Updates
NeoZ666 May 7, 2024
19e3922
Updated yarn.lock
NeoZ666 May 7, 2024
c7b5b7b
Merge branch 'Updated-Branch' into main
NeoZ666 May 7, 2024
4b63ccb
Revert back
NeoZ666 May 7, 2024
35c89b5
Merge branch 'main' of https://github.com/NeoZ666/learning-tokens
NeoZ666 May 7, 2024
db2b77c
Revert "new"
NeoZ666 May 7, 2024
e9d2f2c
Revert "new"
NeoZ666 May 7, 2024
caf3b4e
Revert "new"
NeoZ666 May 7, 2024
3fcd2b9
Made Loading Skeletons for Pages
NeoZ666 May 8, 2024
b2907dc
Updates to package.json
NeoZ666 May 8, 2024
2d67a77
Merge branch 'main' of https://github.com/hyperledger-labs/learning-t…
NeoZ666 Dec 11, 2024
f69378e
Fixed submodule
NeoZ666 Dec 11, 2024
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
52 changes: 52 additions & 0 deletions ltsdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# [ltsdk](https://www.npmjs.com/package/ltsdk)

This package provides functions to interact with the Zoom API, fetch participant and poll data, process this data, and return the processed results.

## Installation

To install the package, use the following command:

```sh
npm install ltsdk
```

## Usage
Here is an example of how to use the run function from the ltsdk package:

```typescript
import { run } from 'ltsdk';
import * as fs from 'fs';
import * as path from 'path';

(async () => {
const accountId = "YOUR_ACCOUNT_ID";
const clientId = "YOUR_CLIENT_ID";
const clientSecret = "YOUR_CLIENT_SECRET";
const meetingId = "YOUR_MEETING_ID";
try {
const processedData = await run(accountId, clientId, clientSecret, meetingId);
console.log(processedData);
} catch (error) {
console.error('Error:', error);
}
})();
```

Run the script:

```bash
tsc .\index.ts
node .\index.js
```

## Parameters
accountId (string): The Zoom account ID.
clientId (string): The Zoom client ID.
clientSecret (string): The Zoom client secret.
meetingId (string): The ID of the Zoom meeting.

## Returns
A promise that resolves to the processed data.

## License
Linux Foundation
1 change: 1 addition & 0 deletions ltsdk/dist/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { run } from './zoomprocessor';
6 changes: 6 additions & 0 deletions ltsdk/dist/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use strict";
// index.ts
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = void 0;
var zoomprocessor_1 = require("./zoomprocessor");
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return zoomprocessor_1.run; } });
1 change: 1 addition & 0 deletions ltsdk/dist/src/zoomprocessor.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export declare function run(accountId: string, clientId: string, clientSecret: string, meetingId: string): Promise<any>;
217 changes: 217 additions & 0 deletions ltsdk/dist/src/zoomprocessor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = run;
const axios_1 = __importDefault(require("axios"));
function getZoomAccessToken(accountId, clientId, clientSecret) {
return __awaiter(this, void 0, void 0, function* () {
const tokenUrl = `https://zoom.us/oauth/token?grant_type=account_credentials&account_id=${accountId}`;
const authHeader = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
try {
const response = yield axios_1.default.post(tokenUrl, null, {
headers: {
Authorization: `Basic ${authHeader}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const bearerToken = response.data.access_token;
return bearerToken;
}
catch (error) {
console.error('Error obtaining Zoom access token:', error);
throw new Error('Failed to obtain Zoom access token');
}
});
}
function getPastMeetingParticipants(baseUrl, meetingId, bearerToken) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
try {
const url = `${baseUrl}/past_meetings/${meetingId}/participants`;
const response = yield axios_1.default.get(url, {
headers: {
Authorization: `Bearer ${bearerToken}`,
'Content-Type': 'application/json',
},
});
return {
data: response.data,
status: response.status,
statusText: response.statusText,
};
}
catch (error) {
if (axios_1.default.isAxiosError(error)) {
throw new Error(((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || error.message);
}
else {
throw new Error('An unknown error occurred');
}
}
});
}
function getMeetingPollsQuestions(baseUrl, meetingId, bearerToken) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
try {
const url = `${baseUrl}/meetings/${meetingId}/polls`;
const response = yield axios_1.default.get(url, {
headers: {
Authorization: `Bearer ${bearerToken}`,
'Content-Type': 'application/json',
},
});
return {
data: response.data,
status: response.status,
statusText: response.statusText,
};
}
catch (error) {
throw new Error(((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || error.message);
}
});
}
function getPastMeetingPolls(baseUrl, meetingId, bearerToken) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
try {
const url = `${baseUrl}/past_meetings/${meetingId}/polls`;
const response = yield axios_1.default.get(url, {
headers: {
Authorization: `Bearer ${bearerToken}`,
},
});
return {
data: response.data,
status: response.status,
statusText: response.statusText,
};
}
catch (error) {
throw new Error(((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || error.message);
}
});
}
function processParticipantsAndPollsData(participants, pollScores) {
const participantMap = new Map();
participants.forEach(participant => {
const name = participant.name;
const joinTime = new Date(participant.join_time).getTime();
const leaveTime = new Date(participant.leave_time).getTime();
const duration = (leaveTime - joinTime) / 1000;
const mappingData = { Email: participant.user_email || 'NaN', LTId: 'NaN' };
if (participantMap.has(name)) {
participantMap.get(name).totalTime += duration;
}
else {
participantMap.set(name, {
totalTime: duration,
joinTime: joinTime,
leaveTime: leaveTime,
email: mappingData.Email,
LTId: mappingData.LTId,
total_score: 0,
attempted: 0,
total_questions: 0,
});
}
});
pollScores.forEach((data, name) => {
const participantData = participantMap.get(name);
if (participantData) {
participantData.total_score = data.total_score;
participantData.attempted = data.attempted;
participantData.total_questions = data.total_questions;
}
});
return participantMap;
}
function saveProcessedDataToFile(data, meetingId) {
const processedData = {
meetingId: meetingId,
attendees: Array.from(data.entries()).map(([name, participantData]) => ({
name,
totalTime: participantData.totalTime,
joinTime: participantData.joinTime,
leaveTime: participantData.leaveTime,
email: participantData.email,
LTId: participantData.LTId,
total_score: participantData.total_score,
attempted: participantData.attempted,
total_questions: participantData.total_questions,
}))
};
return processedData;
}
function calculateScore(pollsQuestionsResponse, pollsAnswers) {
const participantMap = new Map();
pollsAnswers.questions.forEach((participant) => {
const participantData = {
totalTime: 0,
joinTime: 0,
leaveTime: 0,
email: '',
LTId: '',
total_score: 0,
attempted: 0,
total_questions: 0,
};
participant.question_details.forEach((responseDetail) => {
const pollQuestion = pollsQuestionsResponse.polls.find(poll => poll.id === responseDetail.polling_id);
if (pollQuestion) {
const question = pollQuestion.questions.find(q => q.name == responseDetail.question);
const scoreObj = {
title: pollQuestion.title,
question: (question === null || question === void 0 ? void 0 : question.name) || 'Default',
score: 0
};
if (question) {
participantData.attempted++;
if (!question.right_answers) {
scoreObj.score++;
participantData.total_score++;
}
else {
if (question.right_answers.includes(responseDetail.answer)) {
scoreObj.score++;
participantData.total_score++;
}
}
}
participantData.total_questions = participantData.attempted;
}
});
participantMap.set(participant.name, participantData);
});
return participantMap;
}
function run(accountId, clientId, clientSecret, meetingId) {
return __awaiter(this, void 0, void 0, function* () {
const baseUrl = "https://api.zoom.us/v2";
try {
const bearerToken = yield getZoomAccessToken(accountId, clientId, clientSecret);
const participantsResponse = yield getPastMeetingParticipants(baseUrl, meetingId, bearerToken);
const pollsQuestionResponse = yield getMeetingPollsQuestions(baseUrl, meetingId, bearerToken);
const pollsResponse = yield getPastMeetingPolls(baseUrl, meetingId, bearerToken);
const scores = calculateScore(pollsQuestionResponse.data, pollsResponse.data);
const participantMap = processParticipantsAndPollsData(participantsResponse.data.participants, scores);
const processedData = saveProcessedDataToFile(participantMap, meetingId);
return processedData;
}
catch (error) {
console.error('Error:', error);
}
});
}
1 change: 1 addition & 0 deletions ltsdk/dist/tests/zoomprocessor.test.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {};
20 changes: 20 additions & 0 deletions ltsdk/dist/tests/zoomprocessor.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const zoomprocessor_1 = require("../src/zoomprocessor");
test('fetch and process Zoom data', () => __awaiter(void 0, void 0, void 0, function* () {
const accountId = "YOUR_ACCOUNT_ID";
const clientId = "YOUR_CLIENT_ID";
const clientSecret = "YOUR_CLIENT_SECRET";
const meetingId = 'YOUR_MEETING_ID';
const processedData = yield (0, zoomprocessor_1.run)(accountId, clientId, clientSecret, meetingId);
expect(processedData).toMatchSnapshot();
}));
5 changes: 5 additions & 0 deletions ltsdk/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/tests/**/*.test.ts'],
};
Loading