Skip to content

Commit

Permalink
Merge pull request #1 from teltek/add_sync_command
Browse files Browse the repository at this point in the history
feat: Add sync command
  • Loading branch information
Yurujai authored Dec 17, 2024
2 parents 21c473b + fda3d26 commit 49a81a9
Show file tree
Hide file tree
Showing 14 changed files with 572 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ jobs:
run: find . -type f -name "*.php" -print0 | xargs -0 -n1 -P8 php -l

- name: PHPCSFixer
uses: docker://oskarstark/php-cs-fixer-ga:3.1.0
uses: docker://teltek/php-cs-fixer-ga
with:
args: --config=.php-cs-fixer.dist.php --diff --dry-run
135 changes: 135 additions & 0 deletions Command/ImportRecordingsCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

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\Series;
use Pumukit\SchemaBundle\Document\ValueObject\Path;
use Pumukit\SchemaBundle\Services\FactoryService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\HttpClientInterface;

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;

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,
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;

parent::__construct($name);
}

public function configure(): void
{
$this
->setName('pumukit:blackboard:import:recordings')
->setDescription('This command import blackboard collaborate recordings on PuMuKIT')
;
}

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

$recordings = $this->getRecordingsToImport();

foreach ($recordings as $recording) {
$pathFile = $this->downloadRecording($recording);
$series = $this->getSeries();
$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);
$recording->markAsImported();
$this->documentManager->flush();
}

return Command::SUCCESS;
}

private function getRecordingsToImport(): array
{
return $this->documentManager->getRepository(CollaborateRecording::class)->findBy([
'imported' => false,
]);
}

private function downloadRecording(CollaborateRecording $recording): ?Path
{
$response = $this->httpClient->request('GET', $recording->downloadUrl());
if (Response::HTTP_OK !== $response->getStatusCode()) {
return null;
}

$fileContent = $response->getContent();

$data = parse_url($recording->downloadUrl());
$extension = explode('.', $data['path']);
$extension = end($extension);

file_put_contents(self::DEFAULT_TMP_PATH.$extension, $fileContent);

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

private function getSeries(): Series
{
return $this->documentManager->getRepository(Series::class)->findOneBy(['_id' => new ObjectId('67613c953788ffd1da05c983')]);
}
}
72 changes: 61 additions & 11 deletions Command/SyncMediaCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
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\CollaborateCreateRecording;
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 +19,28 @@ 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;
private CollaborateCreateRecording $collaborateCreateRecording;

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

parent::__construct($name);
}
Expand All @@ -42,18 +55,55 @@ 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'];
$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);
$recording = $this->collaborateCreateRecording->create($collaborateRecording);

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

return Command::SUCCESS;
Expand Down
114 changes: 114 additions & 0 deletions Document/CollaborateRecording.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

namespace Pumukit\BlackboardBundle\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
use MongoDB\BSON\ObjectId;

/**
* @MongoDB\Document(repositoryClass="Pumukit\BlackboardBundle\Repository\CollaborateRecordingRepository")
*/
class CollaborateRecording
{
/**
* @MongoDB\Id
*/
private $id;

/**
* @MongoDB\Field(type="string")
*/
private $recording;

/**
* @MongoDB\Field(type="string")
*/
private $courseUUID;

/**
* @MongoDB\Field(type="string")
*/
private $downloadUrl;

/**
* @MongoDB\Field(type="string")
*/
private $sessionName;

/**
* @MongoDB\Field(type="boolean")
*/
private $imported;

/**
* @MongoDB\Field(type="string")
*/
private $title;

/**
* @MongoDB\Field(type="date")
*/
private $created;

private function __construct(\Pumukit\BlackboardBundle\ValueObject\CollaborateRecording $recording)
{
$this->id = new ObjectId();
$this->recording = $recording->id();
$this->courseUUID = $recording->courseUUID();
$this->downloadUrl = $recording->downloadUrl();
$this->sessionName = $recording->sessionName();
$this->title = $recording->title();
$this->created = new \DateTime($recording->created());
$this->imported = false;
}

public static function create(\Pumukit\BlackboardBundle\ValueObject\CollaborateRecording $recording): CollaborateRecording
{
return new self($recording);
}

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

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

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

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

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

public function imported(): bool
{
return $this->imported;
}

public function markAsImported(): void
{
$this->imported = true;
}

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

public function created(): \DateTime
{
return $this->created;
}
}
9 changes: 9 additions & 0 deletions Repository/CollaborateRecordingRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

namespace Pumukit\BlackboardBundle\Repository;

use Doctrine\ODM\MongoDB\Repository\DocumentRepository;

class CollaborateRecordingRepository extends DocumentRepository {}
11 changes: 9 additions & 2 deletions Resources/config/pumukit_blackboard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ 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

Pumukit\BlackboardBundle\Services\CollaborateCreateRecording:
class: Pumukit\BlackboardBundle\Services\CollaborateCreateRecording
Loading

0 comments on commit 49a81a9

Please sign in to comment.