public function execute() { $this->verbose = $this->hasOption("verbose"); $this->dryRun = $this->hasOption("dryRun"); $this->limit = $this->getOption("limit", self::BATCH_SIZE); $titles = $this->getScreenplayTitles(); $ooyalaAsset = new OoyalaAsset(); if ($this->dryRun) { echo "Dry run...\n"; } foreach ($titles as $title) { $videoFile = WikiaFileHelper::getVideoFileFromTitle($title); if (empty($videoFile)) { $this->log("Skipping video '{$title}' -- couldn't find video file"); $this->skippedVideos++; continue; } $ooyalaData = $this->prepForOoyala($videoFile); if ($this->dryRun) { echo "Ready to migrate video " . $videoFile->getName() . " to Ooyala with the following data:\n"; print_r($ooyalaData); $success = true; $videoId = "TestID"; } else { // $videoId gets set in addRemoteAsset() $success = $ooyalaAsset->addRemoteAsset($ooyalaData, $videoId); } if (!$success) { $this->log("Error uploading video {$ooyalaData['assetTitle']} onto Ooyala. Skipping update locally"); $this->skippedVideos++; continue; } $localData = $this->prepForLocal($videoFile, $ooyalaData, $videoId); if ($this->dryRun) { echo "Ready to update video " . $videoFile->getName() . " locally with the following new metadata\n"; print_r(unserialize($localData)); } else { $this->updateVideoLocally($videoFile, $localData, $videoId); } $this->migratedVideos++; } $this->printSummary(); }
/** * This task is run when a video is uploaded but the provider does not have a * thumbnail for us to use. This gets triggered the first time a thumbnail * cannot be found, and is queued up again at longer intervals until we either * get a thumbnail from the provider, or exhaust all of our attempts. * @param $title * @param $delayIndex * @param $provider * @param $videoId * @return FileRepoStatus */ public function retryThumbUpload($title, $delayIndex, $provider, $videoId) { global $IP, $wgCityId; /** @var Title $title */ $file = WikiaFileHelper::getVideoFileFromTitle($title); if (empty($file)) { $msg = "File not found on wiki"; if ($title instanceof Title) { $title = $title->getText(); } $this->log("error", $delayIndex, $title, $provider, ["errorMsg" => $msg]); return Status::newFatal($msg); } $delayIndex++; $this->log("start", $delayIndex, $title->getText(), $provider); // IVA requires extra steps to update their thumbnail, use the script we have for that if ($provider == self::IVA) { $cmd = sprintf("SERVER_ID={$wgCityId} php {$IP}/maintenance/wikia/VideoHandlers/updateOoyalaThumbnail.php --videoId={$videoId} --delayIndex={$delayIndex}"); $response = wfShellExec($cmd, $exitStatus); if ($exitStatus == 0) { $msg = "Video thumbnail uploaded successfully"; $status = Status::newGood($msg); } else { $msg = "Error uploading video thumbnail: {$response}"; $status = Status::newFatal($msg); } } else { $helper = new VideoHandlerHelper(); $status = $helper->resetVideoThumb($file, null, $delayIndex); } if ($status->isGood()) { // A good status doesn't necessarily mean we updated the actual thumbnail. A good status is returned for // successfully uploading the default thumb as well. Actually check the img sha to see if the thumb changed if ($file->getSha1() != self::DEFAULT_THUMB_SHA) { $this->log("success", $delayIndex, $title->getText(), $provider, ['thumbnail' => $file->getThumbUrl()]); } } else { $this->log("error", $delayIndex, $title->getText(), $provider, ['errorMsg' => $status->getMessage()]); } return $status; }
/** * Update thumbnail in the wiki * * @param string $videoTitle - video title on the wiki * @param string $thumbnailUrl * @param integer $delayIndex * * @global integer $failed * @global boolean $dryRun * @global string $msg * * @return boolean */ function updateThumbnailWiki($videoTitle, $thumbnailUrl, $delayIndex) { global $failed, $dryRun, $msg; $title = $videoTitle; $file = WikiaFileHelper::getVideoFileFromTitle($title); if (empty($file)) { $failed++; print "{$msg}...FAILED (Error: File not found in the wiki. Title: {$videoTitle}).\n"; return false; } $helper = new VideoHandlerHelper(); if (!$dryRun) { $status = $helper->resetVideoThumb($file, $thumbnailUrl, $delayIndex); if (!$status->isGood()) { $failed++; print "{$msg}...FAILED (Error: Cannot reset video thumbnail in the wiki. Title: {$videoTitle}).\n"; return false; } } return true; }
/** * Compare new metadata with the one from file * @param array $video * @param string $msg * @param array $newMeta * @return boolean */ function compareMetadataFile($video, $msg, $newMeta) { // find duplicate videos from wiki $duplicates = WikiaFileHelper::getDuplicateVideos('ooyala', $video['embed_code'], 2); if (empty($duplicates)) { echo "\n\tNOTE: {$msg} ... File not found in DB\n"; return false; } else { if (count($duplicates) > 1) { $dupes = array(); foreach ($duplicates as $dup) { $dupes[] = $dup['video_title']; } echo "\n\tNOTE: {$msg} ... (Found " . count($duplicates) . " duplicates: " . implode(',', $dupes) . ")\n"; return false; } } // get file object $title = $duplicates[0]['video_title']; $file = WikiaFileHelper::getVideoFileFromTitle($title); if (empty($file)) { echo "\n\tNOTE: {$msg} ... File not found\n"; return false; } $fileMeta = unserialize($file->getMetadata()); foreach ($fileMeta as $key => &$value) { if ($key == 'ageRequired') { $fileMeta['age_required'] = $value; unset($fileMeta['ageRequired']); } else { if ($key == 'language') { $fileMeta['lang'] = $value; unset($fileMeta['language']); } else { if ($key == 'published') { $value = date('Y-m-d', $value); } else { $keyLc = strtolower($key); if ($key != $keyLc) { $fileMeta[$keyLc] = $value; unset($fileMeta[$key]); } } } } } echo "\n\tCompare to File:\n"; compareMetadata($fileMeta, $newMeta); return true; }
/** * Get valid videos - list of video title * @param array $videos * @return array $validVideos */ public function getValidVideos($videos) { $validVideos = array(); foreach ($videos as $videoTitle) { $title = urldecode($videoTitle); $file = WikiaFileHelper::getVideoFileFromTitle($title); if (!empty($file)) { $validVideos[] = $file->getTitle()->getDBKey(); } } return $validVideos; }
public function execute() { $this->test = $this->hasOption('test'); $this->verbose = $this->hasOption('verbose'); $this->opt = $this->getOption('opt'); $this->startDate = $this->getOption('start'); $this->endDate = $this->getOption('end'); $this->provider = $this->getOption('provider'); if (empty($this->opt) || !in_array($this->opt, self::$opts)) { die("Error: invalid option. Please enter 'reupload' or 'data'.\n"); } if ($this->opt == 'reupload' && (empty($this->startDate) || empty($this->endDate))) { die("Error: Reuploading image requires start date and end date.\n"); } $app = F::app(); echo "Wiki: {$app->wg->CityId} ({$app->wg->DBname})\n"; if ($this->test) { echo "== TEST MODE ==\n"; } $startTime = time(); $cnt = 0; $success = 0; $failed = 0; $affected = 0; if ($this->opt == 'reupload') { $videos = $this->getVideos(); } else { $videos = VideoInfoHelper::getLocalVideoTitles(); } $total = count($videos); $helper = new VideoHandlerHelper(); foreach ($videos as $title) { $cnt++; $this->debug("Video [{$cnt} of {$total}]: {$title} "); $file = WikiaFileHelper::getVideoFileFromTitle($title); // check if the file exists if (empty($file)) { echo " ... FAILED (File not found)\n"; $failed++; continue; } // check for test mode if ($this->test) { $this->debug("... DONE\n"); $success++; continue; } if ($this->opt == 'reupload') { if ($this->provider == 'screenplay') { $thumbUrl = ScreenplayApiWrapper::getThumbnailUrlFromAsset($file->getVideoId()); if (empty($thumbUrl)) { echo " ... FAILED (Thumbnail URL not found)\n"; $failed++; continue; } } else { $thumbUrl = null; } $status = $helper->resetVideoThumb($file, $thumbUrl); } else { if ($this->opt == 'data') { if (file_exists($file->getLocalRefPath())) { $status = $helper->updateThumbnailData($file); } else { $status = Status::newFatal('Path not found'); } } else { $status = Status::newGood(); } } if ($status->isGood()) { if ($this->opt == 'data') { $changed = $status->value; } else { $changed = 1; } $this->debug("... DONE ({$changed} affected).\n"); $success++; if ($changed > 0) { $affected++; } } else { $errorMsg = array(); foreach ($status->errors as $err) { $errorMsg[] = $err['message']; } $this->debug("... FAILED (" . implode(', ', $errorMsg) . ")\n"); $failed++; } } $diff = $app->wg->lang->formatTimePeriod(time() - $startTime); echo "Wiki {$app->wg->CityId} ({$app->wg->DBname}): Total: {$total}, Success: {$success} ({$affected} affected), Failed: {$failed}. Finished after {$diff}\n"; }
/** * Gets the duration of a video. * @param string $title * @return int Number of seconds */ protected function getDuration($title) { $file = WikiaFileHelper::getVideoFileFromTitle($title); return $file ? round($file->getMetadataDuration()) : 0; }
/** * @inheritdoc */ public function import($content = '', array $params = []) { wfProfileIn(__METHOD__); $articlesCreated = 0; foreach ($this->getCollectionFeeds() as $collectionFeed) { $content = $this->downloadCollectionFeed($collectionFeed); if (empty($content)) { continue; } $doc = new DOMDocument('1.0', 'UTF-8'); @$doc->loadXML($content); $items = $doc->getElementsByTagName('item'); $numItems = $items->length; $this->logger->videoFound($numItems); $elements = $doc->getElementsByTagName('language'); if ($elements->length > 0) { $language = $this->convertLanguageCode($elements->item(0)->textContent); } else { $language = ''; } for ($i = 0; $i < $numItems; ++$i) { $clipData = []; $item = $items->item($i); $clipData['series'] = $item->getElementsByTagName('seriesTitle')->item(0)->textContent; // check for video name $elements = $item->getElementsByTagName('title'); if ($elements->length > 0) { $clipData['titleName'] = $clipData['series'] . ' - ' . html_entity_decode($elements->item(0)->textContent); } else { $this->logger->videoSkipped(); continue; } // Skip the premium videos - free publish date for them is in the future $elements = $item->getElementsByTagName('freePubDate'); if ($elements->length > 0) { $freePublishDate = strtotime($elements->item(0)->textContent); if ($freePublishDate > time()) { $this->logger->videoSkipped("\nPremium video (title: {$clipData['titleName']})\n"); continue; } } if (WikiaFileHelper::getVideoFileFromTitle($clipData['titleName'])) { $this->logger->videoSkipped("\nDuplicate video (title: {$clipData['titleName']})\n"); continue; } $clipData['name'] = $clipData['titleName']; $elements = $item->getElementsByTagName('description'); if ($elements->length > 0) { $clipData['description'] = trim(strip_tags($elements->item(0)->textContent)); } else { $clipData['description'] = ''; } // check for video id $elements = $item->getElementsByTagName('mediaId'); if ($elements->length > 0) { $clipData['videoId'] = (int) $elements->item(0)->textContent; } if (!isset($clipData['videoId'])) { $this->logger->videoWarnings("ERROR: videoId NOT found for {$clipData['titleName']} - {$clipData['description']}.\n"); continue; } if (empty($clipData['videoId'])) { $this->logger->videoWarnings("ERROR: Empty videoId for {$clipData['titleName']} - {$clipData['description']}.\n"); continue; } // check for nonadult videos $elements = $item->getElementsByTagName('rating'); $clipData['ageGate'] = $elements->length > 0 && $elements->item(0)->textContent == 'nonadult' ? 0 : 1; if ($clipData['ageGate']) { print "Adult video: {$clipData['titleName']} ({$clipData['videoId']}).\n"; $clipData['ageRequired'] = '13'; $clipData['industryRating'] = 'PG-13'; } $clipData['published'] = strtotime($item->getElementsByTagName('pubDate')->item(0)->textContent); $clipData['publisher'] = $item->getElementsByTagName('publisher')->item(0)->textContent; $clipData['expirationDate'] = strtotime($item->getElementsByTagName('freeEndPubDate')->item(0)->textContent); $clipData['videoUrl'] = urldecode($item->getElementsByTagName('link')->item(0)->textContent); $subTitleLangs = $item->getElementsByTagName('subtitleLanguages'); if ($subTitleLangs->length > 0) { $clipData['subtitle'] = $this->convertSubtitleLanguageCode($item->getElementsByTagName('subtitleLanguages')->item(0)->textContent); } $clipData['regionalRestrictions'] = strtoupper(str_replace(' ', ', ', $item->getElementsByTagName('restriction')->item(0)->textContent)); $elements = $item->getElementsByTagName('season'); if ($elements->length > 0) { $clipData['season'] = 'Season ' . $elements->item(0)->textContent; } else { $clipData['season'] = ''; } $elements = $item->getElementsByTagName('episodeNumber'); if ($elements->length > 0) { $clipData['episode'] = 'Episode ' . $elements->item(0)->textContent; } else { $clipData['episode'] = ''; } // The first thumbnail returned by crunchyroll is the largest one - get that! $elements = $item->getElementsByTagName('thumbnail'); $clipData['thumbnail'] = $elements->length > 0 ? $elements->item(0)->getAttribute('url') : ''; $elements = $item->getElementsByTagName('keywords'); $clipData['keywords'] = $elements->length > 0 ? $elements->item(0)->textContent : ''; $elements = $item->getElementsByTagName('category'); if ($elements->length > 0) { $clipData['category'] = $this->getCategory($elements->item(0)->textContent); } $clipData['language'] = $language; $clipData['duration'] = $item->getElementsByTagName('duration')->item(0)->textContent; $clipData['hd'] = 0; $clipData['provider'] = 'crunchyroll'; $articlesCreated += $this->createVideo($clipData); } } wfProfileOut(__METHOD__); return $articlesCreated; }
/** * Validate video (called from validateFormField()) * @param string $videoTitle * @param string $errMsg * @return boolean */ public function validateVideoKey($videoTitle, &$errMsg) { $file = WikiaFileHelper::getVideoFileFromTitle($videoTitle); if (!empty($file)) { return true; } $errMsg = wfMessage('videohandler-error-video-no-exist')->plain(); return false; }
/** * Checks to see if the video title passed in has a thumbnail on disk or not. * * @param string|Title $title - The video title to check * @param boolean $fixit - Whether to fix the problem or ignore it * @return Status */ public function fsckVideoThumbnail($title, $fixit = true) { $file = WikiaFileHelper::getVideoFileFromTitle($title); // See if a file exists for this title if (empty($file)) { return Status::newFatal('File object not found'); } // See if the thumbnail exists for this title if (file_exists($file->getLocalRefPath())) { return Status::newGood(['check' => 'ok']); } else { // Determine if we should fix this problem or leave it be if ($fixit) { $status = $this->resetVideoThumb($file); if ($status->isGood()) { return Status::newGood(['check' => 'failed', 'action' => 'fixed']); } else { return $status; } } else { return Status::newGood(['check' => 'failed', 'action' => 'ignored']); } } }
/** * restore video after swapping or keeping it * @requestParam string videoTitle * @requestParam string newTitle * @requestParam integer currentPage * @responseParam string result [ok/error] * @responseParam string msg - result message * @responseParam string html * @responseParam integer totalVideos - total videos with suggestions * @responseParam string redirect - redirect url */ public function restoreVideo() { $videoTitle = $this->request->getVal('videoTitle', ''); $currentPage = $this->getVal('currentPage', 1); $sort = 'recent'; // set default value for response params $this->setDefaultParams(); // validate action $response = $this->sendRequest('LicensedVideoSwapSpecial', 'validateAction', array('videoTitle' => $videoTitle)); $msg = $response->getVal('msg', ''); if (!empty($msg)) { $this->result = 'error'; $this->msg = $msg; } $file = WikiaFileHelper::getVideoFileFromTitle($videoTitle, true); // check if file exists if (empty($file)) { $this->result = 'error'; $this->msg = wfMessage('videohandler-error-video-no-exist')->text(); return; } $helper = new LicensedVideoSwapHelper(); // get the LVS status of this file page $articleId = $videoTitle->getArticleID(); $pageStatusInfo = $helper->getPageStatusInfo($articleId); if (empty($pageStatusInfo['status'])) { $this->result = 'error'; $this->msg = wfMessage('lvs-error-invalid-page-status')->text(); return; } if ($helper->isStatusSwapExact($pageStatusInfo['status'])) { $status = $helper->undeletePage($videoTitle, true); if (!$status->isOK()) { $this->html = ''; $this->result = 'error'; $this->msg = $status->getMessage(); return; } } else { if ($helper->isStatusSwapNorm($pageStatusInfo['status'])) { $newTitle = $this->request->getVal('newTitle', ''); /** @var WikiPage $article */ $article = Article::newFromID($videoTitle->getArticleID()); $redirect = $article->getRedirectTarget(); if ($article->isRedirect() && !empty($redirect) && $redirect->getDBKey() == $newTitle) { $status = $helper->undeletePage($videoTitle); if (!$status->isOK()) { $this->result = 'error'; $this->msg = $status->getMessage(); return; } $result = $helper->removeRedirectLink($article); if (!$result->isOK()) { $this->result = 'error'; $this->msg = $result->getMessage(); return; } } } } // clear the LVS status of this file page $helper->clearPageStatus($articleId); // delete the LVS status info of this file page $helper->deletePageStatusInfo($articleId); // add log for undo swapping video only if (!$helper->isStatusKeep($pageStatusInfo['status'])) { $reason = wfMessage('lvs-log-restore', $file->getTitle()->getText())->text(); $helper->addLog($file->getTitle(), 'licensedvideoswap_restore', $reason); } // clear cache for total videos $helper->invalidateCacheTotalVideos(); // get video list $useMaster = true; $videoList = $helper->getRegularVideoList($sort, $currentPage, $useMaster); // get total videos with suggestions $this->totalVideos = $helper->getUnswappedVideoTotal($useMaster); if (empty($videoList)) { $this->redirect = $helper->getRedirectUrl($currentPage, $sort); } else { $this->html = $this->app->renderView('LicensedVideoSwapSpecial', 'row', array('videoList' => $videoList)); $this->html .= $helper->getPagination($this->totalVideos, $currentPage, $sort); } $this->result = 'ok'; $this->msg = wfMessage('lvs-restore-video-success')->text(); }