Skip to content

Commit

Permalink
feat: add all workflow to import recordings on PuMuKIT
Browse files Browse the repository at this point in the history
  • Loading branch information
Yurujai committed Dec 19, 2024
1 parent 49a81a9 commit 3f9ef51
Show file tree
Hide file tree
Showing 10 changed files with 282 additions and 75 deletions.
102 changes: 63 additions & 39 deletions Command/ImportRecordingsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,16 @@
namespace Pumukit\BlackboardBundle\Command;

use Doctrine\ODM\MongoDB\DocumentManager;
use MongoDB\BSON\ObjectId;
use Pumukit\BlackboardBundle\Document\CollaborateRecording;
use Pumukit\BlackboardBundle\Services\CollaborateAPIAuth;
use Pumukit\BlackboardBundle\Services\CollaborateAPICourseRecordings;
use Pumukit\BlackboardBundle\Services\CollaborateAPIRecording;
use Pumukit\BlackboardBundle\Services\CollaborateAPISessionSearch;
use Pumukit\BlackboardBundle\Services\CollaborateCreateRecording;
use Pumukit\BlackboardBundle\Services\LearnAPIAuth;
use Pumukit\BlackboardBundle\Services\LearnAPICourse;
use Pumukit\CoreBundle\Services\i18nService;
use Pumukit\EncoderBundle\Services\DTO\JobOptions;
use Pumukit\EncoderBundle\Services\JobCreator;
use Pumukit\SchemaBundle\Document\Role;
use Pumukit\SchemaBundle\Document\Series;
use Pumukit\SchemaBundle\Document\User;
use Pumukit\SchemaBundle\Document\ValueObject\Path;
use Pumukit\SchemaBundle\Services\FactoryService;
use Pumukit\SchemaBundle\Services\UserService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand All @@ -26,48 +21,31 @@

class ImportRecordingsCommand extends Command
{
public const DEFAULT_TMP_PATH = '';

private LearnAPIAuth $learnAPIAuth;
private LearnAPICourse $learnAPICourse;
private CollaborateAPIAuth $collaborateAPIAuth;
private CollaborateAPICourseRecordings $collaborateAPICourseRecordings;
private CollaborateAPIRecording $collaborateAPIRecording;
private CollaborateAPISessionSearch $collaborateAPISessionSearch;
private CollaborateCreateRecording $collaborateCreateRecording;
private DocumentManager $documentManager;
private HttpClientInterface $httpClient;
private FactoryService $factoryService;
private JobCreator $jobCreator;
private i18nService $i18nService;
private UserService $userService;
private $tmpPath;

public function __construct(
LearnAPIAuth $learnAPIAuth,
LearnAPICourse $learnAPICourse,
CollaborateAPIAuth $collaborateAPIAuth,
CollaborateAPICourseRecordings $collaborateAPICourseRecordings,
CollaborateAPIRecording $collaborateAPIRecording,
CollaborateAPISessionSearch $collaborateAPISessionSearch,
CollaborateCreateRecording $collaborateCreateRecording,
DocumentManager $documentManager,
HttpClientInterface $httpClient,
FactoryService $factoryService,
JobCreator $jobCreator,
i18nService $i18nService,
UserService $userService,
string $tmpPath,
string $name = null
) {
$this->learnAPIAuth = $learnAPIAuth;
$this->learnAPICourse = $learnAPICourse;
$this->collaborateAPIAuth = $collaborateAPIAuth;
$this->collaborateAPICourseRecordings = $collaborateAPICourseRecordings;
$this->collaborateAPIRecording = $collaborateAPIRecording;
$this->collaborateAPISessionSearch = $collaborateAPISessionSearch;
$this->collaborateCreateRecording = $collaborateCreateRecording;
$this->documentManager = $documentManager;
$this->httpClient = $httpClient;
$this->factoryService = $factoryService;
$this->jobCreator = $jobCreator;
$this->i18nService = $i18nService;
$this->userService = $userService;
$this->tmpPath = $tmpPath;

parent::__construct($name);
}
Expand All @@ -82,27 +60,57 @@ public function configure(): void

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

$output->writeln('<info>STEP 1: Getting recordings to import</info>');
$recordings = $this->getRecordingsToImport();

$output->writeln('<info>STEP 2: Validate recordings to import</info>');
foreach ($recordings as $recording) {
$users = $this->isValidToImport($recording);
$output->writeln(' ---> STEP 2.1: Getting recording '.$recording->recording());
if (empty($users)) {
$output->writeln(' ---> STEP 2.2:[WARNING] Recording with ID '.$recording->recording().' doesnt have owners on PuMuKIT');

continue;
}

$pathFile = $this->downloadRecording($recording);
$series = $this->getSeries();
$series = $this->getSeries($recording);
$multimediaObject = $this->factoryService->createMultimediaObject($series);
$i18nTitle = $this->i18nService->generateI18nText($recording->title());
$multimediaObject->setI18nTitle($i18nTitle);
$multimediaObject->setRecordDate($recording->created());
$jobOptions = new JobOptions('master_copy', 2, 'en', [], []);
$this->jobCreator->fromPath($multimediaObject, $pathFile, $jobOptions);
$multimediaObject->setProperty('blackboard_recording', $recording->recording());
$recording->markAsImported();

$role = $this->getOwnerRole();
foreach ($users as $user) {
$multimediaObject->addPersonWithRole($user->getPerson(), $role);
}

$this->documentManager->flush();

$output->writeln(' ---> STEP 2.2: Recording with ID '.$recording->recording().' imported');
}

return Command::SUCCESS;
}

private function isValidToImport(CollaborateRecording $recording): array
{
$owners = $recording->owners();
$users = [];
foreach ($owners as $key => $owner) {
$user = $this->documentManager->getRepository(User::class)->findOneBy(['email' => $key]);
if ($user) {
$users[] = $user;
}
}

return $users;
}

private function getRecordingsToImport(): array
{
return $this->documentManager->getRepository(CollaborateRecording::class)->findBy([
Expand All @@ -123,13 +131,29 @@ private function downloadRecording(CollaborateRecording $recording): ?Path
$extension = explode('.', $data['path']);
$extension = end($extension);

file_put_contents(self::DEFAULT_TMP_PATH.$extension, $fileContent);
file_put_contents($this->tmpPath.'/'.$recording->recording().'.'.$extension, $fileContent);

return Path::create($this->tmpPath.'/'.$recording->recording().'.'.$extension);
}

private function getSeries(CollaborateRecording $recording): Series
{
$series = $this->documentManager->getRepository(Series::class)->findOneBy([
'properties.blackboard_course' => $recording->courseUUID(),
]);

if (!$series) {
$title = $this->i18nService->generateI18nText('Blackboard course: '.$recording->courseName());
$series = $this->factoryService->createSeries(null, $title);
$series->setProperty('blackboard_course', $recording->courseUUID());
$this->documentManager->flush();
}

return Path::create(self::DEFAULT_TMP_PATH.$extension);
return $series;
}

private function getSeries(): Series
private function getOwnerRole(): Role
{
return $this->documentManager->getRepository(Series::class)->findOneBy(['_id' => new ObjectId('67613c953788ffd1da05c983')]);
return $this->documentManager->getRepository(Role::class)->findOneBy(['cod' => 'owner']);
}
}
108 changes: 82 additions & 26 deletions Command/SyncMediaCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Pumukit\BlackboardBundle\Services\CollaborateAPICourseRecordings;
use Pumukit\BlackboardBundle\Services\CollaborateAPIRecording;
use Pumukit\BlackboardBundle\Services\CollaborateAPISessionSearch;
use Pumukit\BlackboardBundle\Services\CollaborateAPIUser;
use Pumukit\BlackboardBundle\Services\CollaborateCreateRecording;
use Pumukit\BlackboardBundle\Services\LearnAPIAuth;
use Pumukit\BlackboardBundle\Services\LearnAPICourse;
Expand All @@ -21,28 +22,31 @@ class SyncMediaCommand extends Command
private CollaborateAPIAuth $collaborateAPIAuth;
private CollaborateAPICourseRecordings $collaborateAPICourseRecordings;
private CollaborateAPIRecording $collaborateAPIRecording;
private CollaborateAPISessionSearch $collaborateAPISessionSearch;
private CollaborateCreateRecording $collaborateCreateRecording;
private CollaborateAPISessionSearch $collaborateAPISessionSearch;
private CollaborateAPIUser $collaborateAPIUser;

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

parent::__construct($name);
$this->collaborateAPIUser = $collaborateAPIUser;
}

public function configure(): void
Expand All @@ -55,57 +59,109 @@ public function configure(): void

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

try {
$learnToken = $this->learnAPIAuth->getToken();
$output->writeln('DONE');
} catch (\Exception $exception) {
$output->writeln('<error>ERROR: '.$exception->getMessage().'</error>');

return Command::FAILURE;
}

$output->writeln('<info>***** Getting collaborate token to use api *****</info>');
$collaborateToken = $this->collaborateAPIAuth->getToken();
$output->writeln('<info>STEP 2: Connecting to Blackboard Collaborate API</info>');

$output->writeln('<info>***** Getting list of courses *****</info>');
try {
$collaborateToken = $this->collaborateAPIAuth->getToken();
$output->writeln('DONE');
} catch (\Exception $exception) {
$output->writeln('<error>ERROR: '.$exception->getMessage().'</error>');

return Command::FAILURE;
}

$output->writeln('<info>STEP 3: Getting list of courses from Blackboard Learn</info>');
$courses = $this->learnAPICourse->getIdsFromCourses($learnToken);
$output->writeln('<info>[COLLABORATE] Courses found '.count($courses).'</info>');
$coursesIds = array_keys($courses);
$output->writeln('Courses found '.count($courses));

$output->writeln('<info>STEP 4: Getting course recordings from Blackboard Collaborate</info>');
$courseRecordings = $this->courseRecordings($coursesIds, $collaborateToken);
$output->writeln('Recordings found '.count($courseRecordings));

$output->writeln('<info>STEP 5: Save recording data on PuMuKIT</info>');
$this->saveRecordings($courseRecordings, $courses, $output, $collaborateToken);

return Command::SUCCESS;
}

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

return $courseRecordings;
}

private function saveRecordings(array $courseRecordings, array $courses, OutputInterface $output, string $collaborateToken): void
{
foreach ($courseRecordings as $key => $recordings) {
foreach ($recordings as $element) {
$output->writeln('<info>***** Getting data from recording '.$element['id'].'</info>');
$output->writeln('<info> ---> STEP 5.1: Getting data from recording '.$element['id'].'</info>');

$recording = $this->collaborateAPIRecording->getRecordingData($collaborateToken, $element['id']);
if (!$recording || !isset($recording['mediaDownloadUrl'])) {
$output->writeln('<comment> ---> STEP 5.2: No accesible recording</comment>');
$output->writeln('');

continue;
}

$downloadUrl = $recording['mediaDownloadUrl'];
$title = $recording['name'];
$created = $recording['created'];

// TODO: Obtener usuarios moderadores del curso. Crear serie del curso y agregar los moderadores. Autoprovisionar los usuarios.
// TODO: Get info about moderator to assing on PuMuKIT.
// $sessions = $this->collaborateAPISessionSearch->searchSessions($collaborateToken);
//
// $sessionsNames = array_column($sessions['results'], 'name');
// $index = array_search($element['sessionName'], $sessionsNames);
// $sessionId = $sessions['results'][$index]['id'];
//
// $enrollments = $this->collaborateAPISessionSearch->getEnrollmentsBySessionId($collaborateToken, $sessionId);

$collaborateRecording = CollaborateRecording::create($element['id'], $key, $downloadUrl, $element['sessionName'], $title, $created);
$collaborateRecording = CollaborateRecording::create($element['id'], $key, $courses[$key], $downloadUrl, $element['sessionName'], $title, $created);
$owners = $this->recordingOwners($element['sessionName'], $collaborateToken);
$collaborateRecording->addOwners($owners);

$recording = $this->collaborateCreateRecording->create($collaborateRecording);

if ($recording) {
$output->writeln('<info>Created new collaborate recording with ID '.$recording->recording().'</info>');
}
$output->writeln(' ---> STEP 5.2: Created new collaborate recording with ID '.$recording->recording());
$output->writeln('');
}
}
}

return Command::SUCCESS;
private function recordingOwners(string $sessionName, string $collaborateToken): array
{
$sessions = $this->collaborateAPISessionSearch->searchSessions($collaborateToken);

$sessionsResults = array_column($sessions['results'], 'name');
$index = array_search($sessionName, $sessionsResults);
$sessionId = $sessions['results'][$index]['id'];

$enrollments = $this->collaborateAPISessionSearch->getEnrollmentsBySessionId($collaborateToken, $sessionId);

$owners = [];
foreach ($enrollments['results'] as $enrollment) {
if ('moderator' === $enrollment['launchingRole']) {
$owners[] = $enrollment['userId'];
}
}

$users = [];
foreach ($owners as $owner) {
$user = $this->collaborateAPIUser->searchUser($collaborateToken, $owner);
$users[$user['email']] = $user['displayName'];
}

return $users;
}
}
Loading

0 comments on commit 3f9ef51

Please sign in to comment.