Skip to content

Commit

Permalink
fix: add sync command to save on PMK recordings and then download and…
Browse files Browse the repository at this point in the history
… import
  • Loading branch information
Yurujai committed Dec 13, 2024
1 parent 21c473b commit 73ee662
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 24 deletions.
79 changes: 68 additions & 11 deletions Command/SyncMediaCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
namespace Pumukit\BlackboardBundle\Command;

use Pumukit\BlackboardBundle\Services\CollaborateAPIAuth;
use Pumukit\BlackboardBundle\Services\CollaborateAPIRecordings;
use Pumukit\BlackboardBundle\Services\CollaborateAPICourseRecordings;
use Pumukit\BlackboardBundle\Services\CollaborateAPIRecording;
use Pumukit\BlackboardBundle\Services\CollaborateAPISessionSearch;
use Pumukit\BlackboardBundle\Services\LearnAPIAuth;
use Pumukit\BlackboardBundle\Services\LearnAPICourse;
use Pumukit\BlackboardBundle\ValueObject\CollaborateRecording;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -15,19 +18,25 @@ class SyncMediaCommand extends Command
private LearnAPIAuth $learnAPIAuth;
private LearnAPICourse $learnAPICourse;
private CollaborateAPIAuth $collaborateAPIAuth;
private CollaborateAPIRecordings $collaborateAPIRecordings;
private CollaborateAPICourseRecordings $collaborateAPICourseRecordings;
private CollaborateAPIRecording $collaborateAPIRecording;
private CollaborateAPISessionSearch $collaborateAPISessionSearch;

public function __construct(
LearnAPIAuth $learnAPIAuth,
LearnAPICourse $learnAPICourse,
CollaborateAPIAuth $collaborateAPIAuth,
CollaborateAPIRecordings $collaborateAPIRecordings,
CollaborateAPICourseRecordings $collaborateAPICourseRecordings,
CollaborateAPIRecording $collaborateAPIRecording,
CollaborateAPISessionSearch $collaborateAPISessionSearch,
string $name = null
) {
$this->learnAPIAuth = $learnAPIAuth;
$this->learnAPICourse = $learnAPICourse;
$this->collaborateAPIAuth = $collaborateAPIAuth;
$this->collaborateAPIRecordings = $collaborateAPIRecordings;
$this->collaborateAPICourseRecordings = $collaborateAPICourseRecordings;
$this->collaborateAPIRecording = $collaborateAPIRecording;
$this->collaborateAPISessionSearch = $collaborateAPISessionSearch;

parent::__construct($name);
}
Expand All @@ -42,18 +51,66 @@ public function configure(): void

public function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('***** Getting learn token to use api *****');
$output->writeln('<info>***** Getting learn token to use api *****</info>');
$learnToken = $this->learnAPIAuth->getToken();

$output->writeln('***** Getting list of courses *****');
$courses = $this->learnAPICourse->getIdsFromCourses($learnToken);

$output->writeln('***** Getting collaborate token to use api *****');
$output->writeln('<info>***** Getting collaborate token to use api *****</info>');
$collaborateToken = $this->collaborateAPIAuth->getToken();

$output->writeln('<info>***** Getting list of courses *****</info>');
$courses = $this->learnAPICourse->getIdsFromCourses($learnToken);
$output->writeln('<info>[COLLABORATE] Courses found '. count($courses) .'</info>');

$courseRecordings = [];
$output->writeln('***** Getting recordings from course *****');
foreach ($courses as $course) {
$output->writeln('***** Getting recordings from course *****');
$this->collaborateAPIRecordings->getCourseRecordings($collaborateToken, $course);
$courseData = $this->collaborateAPICourseRecordings->getCourseRecordings($collaborateToken, $course);
if(isset($courseData['results']) && 0 !== count($courseData['results'])) {
$courseRecordings[$course] = $courseData['results'];
}
}

foreach ($courseRecordings as $key => $recordings) {
foreach ($recordings as $element) {
$output->writeln('<info>***** Getting data from recording '. $element['id'] .'</info>');

$recording = $this->collaborateAPIRecording->getRecordingData($collaborateToken, $element['id']);
if(!$recording || !isset($recording['mediaDownloadUrl'])) {
continue;
}

$downloadUrl = $recording['mediaDownloadUrl'];
$session = $this->collaborateAPISessionSearch->searchBySessionName($collaborateToken, $element['sessionName']);

//$enrollments = $this->collaborateAPISessionSearch->getEnrollmentsBySessionId($collaborateToken, '4d0d37cb688f431e973b6ac19ff10599');
$enrollments = $this->collaborateAPISessionSearch->getEnrollmentsBySessionId($collaborateToken, '2f74e38cb29042a4af2da9d9c8398caa');
var_dump($enrollments);die;
$collaborateRecording = CollaborateRecording::create($element['id'], $key, $element['sessionName'], $downloadUrl);
}
}

die;

$sessions = [];
foreach ($recordingSession as $key => $element) {
$session = $this->collaborateAPISessionSearch->searchBySessionName($collaborateToken, $element);
if(!isset($session['results'][0])) {
continue;
}
$sessions[] = $this->collaborateAPISessionSearch->getEnrollmentsBySessionId($collaborateToken, $session['results'][0]['id']);
}

$users = [];
foreach ($sessions as $session) {
if(!isset($session['results'])) {
continue;
}

foreach($session['results'] as $sessionResult) {
if($sessionResult['launchingRole'] === 'moderator') {
$users[] = $sessionResult['userId'];
}
}
}

return Command::SUCCESS;
Expand Down
8 changes: 6 additions & 2 deletions Resources/config/pumukit_blackboard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ services:
Pumukit\BlackboardBundle\Services\CollaborateAPIAuth:
class: Pumukit\BlackboardBundle\Services\CollaborateAPIAuth

Pumukit\BlackboardBundle\Services\CollaborateAPIRecordings:
class: Pumukit\BlackboardBundle\Services\CollaborateAPIRecordings
Pumukit\BlackboardBundle\Services\CollaborateAPICourseRecordings:
class: Pumukit\BlackboardBundle\Services\CollaborateAPICourseRecordings

Pumukit\BlackboardBundle\Services\CollaborateAPIRecording:
class: Pumukit\BlackboardBundle\Services\CollaborateAPIRecording

Pumukit\BlackboardBundle\Services\CollaborateAPISessionSearch:
class: Pumukit\BlackboardBundle\Services\CollaborateAPISessionSearch
11 changes: 4 additions & 7 deletions Services/CollaborateAPIAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ public function getToken(): string
{
try {
$response = $this->client->request('POST', $this->configuration->apiTokenUrl(), [
'headers' => [
'Authorization' => 'Bearer '.$this->assertion,
'Content-Type' => 'application/json',
],
'json' => $this->payload,
'auth_basic' => [$this->configuration->key(), $this->configuration->secret()],
'body' => $this->payload,
'verify_peer' => $this->verify_cert,
]);

Expand All @@ -57,11 +54,11 @@ private function generateJWTPayload(): void
];

$this->header = [
'alg' => 'RS256',
'alg' => 'HS256',
'typ' => 'JWT',
];

$this->assertion = JWT::encode($claims, $this->configuration->secret(), 'RS256');
$this->assertion = JWT::encode($claims, $this->configuration->secret(), 'HS256');
$this->grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer';

$this->payload = [
Expand Down
16 changes: 16 additions & 0 deletions Services/CollaborateAPIConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,20 @@ public function apiRecordingUrl(): string
{
return $this->host().self::API_BASE_PATH.'/recordings';
}

public function recordingDataUrl(string $recordingId): string
{
return $this->host().self::API_BASE_PATH.'/recordings/'.$recordingId.'/data';
}

public function recordingInfoUrl(string $recordingId): string
{
return $this->host().self::API_BASE_PATH.'/recordings/'.$recordingId;
}

public function sessionDataUrl(): string
{
return $this->host().self::API_BASE_PATH.'/sessions';
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class CollaborateAPIRecordings
class CollaborateAPICourseRecordings
{
private HttpClientInterface $client;
private CollaborateAPIConfiguration $configuration;
Expand All @@ -32,12 +32,13 @@ private function recordings(string $accessToken, string $courseId): string
'Accept' => 'application/json',
],
'query' => [
'externalCourseId' => $courseId,
// 'contextId' => $courseId,
'contextExtId' => $courseId,
],
]);

if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new \Exception('Unable to get courses. Response status code: '.$response->getStatusCode());
throw new \Exception('Unable to get course recordings. Response status code: '.$response->getStatusCode());
}

return $response->getContent();
Expand Down
52 changes: 52 additions & 0 deletions Services/CollaborateAPIRecording.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Pumukit\BlackboardBundle\Services;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class CollaborateAPIRecording
{
private HttpClientInterface $client;
private CollaborateAPIConfiguration $configuration;

public function __construct(HttpClientInterface $client, CollaborateAPIConfiguration $configuration)
{
$this->client = $client;
$this->configuration = $configuration;
}

public function getRecordingData(string $accessToken, string $recording): ?array
{
$path = $this->configuration->recordingDataUrl($recording);
$recordingsResponse = $this->recordings($accessToken, $path);

return json_decode($recordingsResponse, true);
}

public function getRecordingInfo(string $accessToken, string $recording): ?array
{
$path = $this->configuration->recordingInfoUrl($recording);
$recordingsResponse = $this->recordings($accessToken, $path);

return json_decode($recordingsResponse, true);
}

private function recordings(string $accessToken, string $path): ?string
{
$response = $this->client->request('GET', $path, [
'headers' => [
'Authorization' => 'Bearer '.$accessToken,
'Accept' => 'application/json',
'Content-Type' => 'application/json'
],
'verify_peer' => true,
]);

if (Response::HTTP_OK !== $response->getStatusCode()) {
return null;
}

return $response->getContent();
}
}
76 changes: 76 additions & 0 deletions Services/CollaborateAPISessionSearch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Pumukit\BlackboardBundle\Services;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class CollaborateAPISessionSearch
{
private HttpClientInterface $client;
private CollaborateAPIConfiguration $configuration;

public function __construct(HttpClientInterface $client, CollaborateAPIConfiguration $configuration)
{
$this->client = $client;
$this->configuration = $configuration;
}

public function searchBySessionName(string $accessToken, string $sessionName): ?array
{
$sessionResponse = $this->sessionByName($accessToken, $sessionName);

return json_decode($sessionResponse, true);
}

public function getEnrollmentsBySessionId(string $accessToken, string $sessionId): ?array
{
$sessionResponse = $this->sessionById($accessToken, $sessionId);

return json_decode($sessionResponse, true);
}

private function sessionByName(string $accessToken, string $sessionName): ?string
{
try {
$response = $this->client->request('GET', $this->configuration->sessionDataUrl(), [
'headers' => [
'Authorization' => 'Bearer '.$accessToken,
'Accept' => 'application/json',
],
// 'query' => [
// 'name' => $sessionName,
// ],
]);

if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new \Exception('Unable to get session. Response status code: '.$response->getStatusCode());
}

return $response->getContent();
} catch (\Exception $exception) {
throw new \Exception($exception->getMessage());
}
}

private function sessionById(string $accessToken, string $sesionId): ?string
{
try {
$response = $this->client->request('GET', $this->configuration->sessionDataUrl().'/'.$sesionId.'/enrollments', [
'headers' => [
'Authorization' => 'Bearer '.$accessToken,
'Accept' => 'application/json',
]
]);

if (Response::HTTP_OK !== $response->getStatusCode()) {
throw new \Exception('Unable to get session. Response status code: '.$response->getStatusCode());
}

return $response->getContent();
} catch (\Exception $exception) {
throw new \Exception($exception->getMessage());
}
}

}
2 changes: 1 addition & 1 deletion Services/LearnAPICourse.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function getIdsFromCourses(string $accessToken): array

$courseIds = [];
foreach ($courses['results'] as $course) {
$courseIds[] = $course['courseId'];
$courseIds[] = $course['uuid'];
}

return $courseIds;
Expand Down
55 changes: 55 additions & 0 deletions ValueObject/CollaborateRecording.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Pumukit\BlackboardBundle\ValueObject;

final class CollaborateRecording
{
private string $id;
private string $courseUUID;
private string $downloadUrl;
private string $sessionName;
private string $user;

private function __construct(string $id, string $courseUUID, string $downloadUrl, string $sessionName)
{
$this->id = $id;
$this->courseUUID = $courseUUID;
$this->downloadUrl = $downloadUrl;
$this->sessionName = $sessionName;
}

public static function create(string $id, string $courseUUID, string $downloadUrl, string $sessionName): CollaborateRecording
{
return new self($id, $courseUUID, $downloadUrl, $sessionName);
}

public function addUser(string $user): void
{
$this->user = $user;
}

public function id(): string
{
return $this->id;
}

public function courseUUID(): string
{
return $this->courseUUID;
}

public function downloadUrl(): string
{
return $this->downloadUrl;
}

public function sessionName(): string
{
return $this->sessionName;
}

public function user(): ?string
{
return $this->user;
}
}

0 comments on commit 73ee662

Please sign in to comment.