/** * Execute the console command. * * @return mixed */ public function fire() { if (!DebugHelpers::shouldSiteBeLive()) { $this->info('Not running because site should not be live at the moment.'); return; } $this->info('Looking for media items which contain VOD which has just gone live.'); // media items which have vod which is accessible, have the sent_vod_available_email flag set to 0, and have not had a email about this sent recently $mediaItems = DB::transaction(function () { $mediaItemsWantingEmail = array(); $mediaItems = MediaItem::with("emailTasksMediaItem", "liveStreamItem")->accessible()->whereHas("videoItem", function ($q) { $q->live(); })->where("email_notifications_enabled", true)->where("sent_vod_available_email", false)->lockForUpdate()->get(); foreach ($mediaItems as $a) { // set the flag to say that this has been looked at and an email will probably be sent. $a->sent_vod_available_email = true; $a->save(); $emailSentRecently = $a->emailTasksMediaItem()->where("created_at", ">=", Carbon::now()->subMinutes(15))->count() > 0; if ($emailSentRecently) { continue; } $mediaItemsWantingEmail[] = $a; $emailTask = new EmailTasksMediaItem(array("message_type_id" => EmailHelpers::getMessageTypeIds()['availableNow'])); // create an entry in the tasks table for the emails that are going to be sent $a->emailTasksMediaItem()->save($emailTask); } return $mediaItemsWantingEmail; }); foreach ($mediaItems as $a) { $this->info("Building and sending email for media item with id " . $a->id . " and name \"" . $a->name . "\" which has VOD which has now gone live."); $title = null; $message = null; $liveStreamItem = $a->liveStreamItem; $hasBeenLive = !is_null($liveStreamItem) && $liveStreamItem->isOver(); if ($hasBeenLive) { $title = "Did you miss our live show?"; $message = "Watch it now on our website."; } else { $title = "New content available!"; $message = "We now have new content available to watch on demand at our website."; } EmailHelpers::sendMediaItemEmail($a, '"{title}" Available Now From LA1:TV', $title, $message); $this->info("Sent email to users."); } $this->info("Finished."); }
public function postAdminStreamControlInfoMsg($id) { Auth::getUser()->hasPermissionOr401(Config::get("permissions.mediaItems"), 1); $mediaItem = MediaItem::with("liveStreamItem", "liveStreamItem.stateDefinition")->find($id); if (is_null($mediaItem)) { App::abort(404); } $liveStreamItem = $mediaItem->liveStreamItem; if (is_null($liveStreamItem)) { App::abort(404); } $requestedInfoMsg = null; if (isset($_POST['info_msg'])) { $requestedInfoMsg = $_POST['info_msg']; } if ($requestedInfoMsg === "") { $requestedInfoMsg = null; } if (!is_null($requestedInfoMsg) && strlen($requestedInfoMsg) <= 500) { $liveStreamItem->information_msg = $requestedInfoMsg; $liveStreamItem->save(); } else { if (is_null($requestedInfoMsg)) { $liveStreamItem->information_msg = null; $liveStreamItem->save(); } } $resp = array("infoMsg" => $liveStreamItem->information_msg); return Response::json($resp); }
private function updateMediaItemsIndex() { $entries = ["toAdd" => [], "toRemove" => []]; // in a transaction to make sure that version number that is returned is not one that // has been increased during a transaction which is stil in progress // mysql transaction isolation level should be REPEATABLE READ which will ensure that // the version number that is returned is the old one if it's currently being updated somewhere else, // until the update that is happening somewhere else is complete. $changedMediaItems = DB::transaction(function () { return MediaItem::with("playlists", "playlists.show")->needsReindexing()->get(); }); foreach ($changedMediaItems as $mediaItem) { if ($mediaItem->getIsAccessible()) { $entries["toAdd"][] = ["model" => $mediaItem, "data" => $this->getMediaItemData($mediaItem, $this->coverArtWidth, $this->coverArtHeight)]; } else { // this item is no longer accessible so remove it from the index $entries["toRemove"][] = ["model" => $mediaItem]; } } $this->syncIndexType("mediaItem", new MediaItem(), $entries); }
public function getIndex() { if (Config::get("degradedService.enabled")) { $view = View::make("home.degradedIndex"); $view->contactEmail = Config::get("contactEmails.development"); $this->setContent($view, "home", "home-degraded", array(), null, 200, array()); return; } $promoMediaItem = MediaItem::with("liveStreamItem", "liveStreamItem.liveStream", "videoItem")->accessible()->whereNotNull("time_promoted")->orderBy("time_promoted", "desc")->first(); if (!is_null($promoMediaItem)) { $liveStreamItem = $promoMediaItem->liveStreamItem; if (!is_null($liveStreamItem) && !$liveStreamItem->getIsAccessible()) { $liveStreamItem = null; } $videoItem = $promoMediaItem->videoItem; if (!is_null($videoItem) && !$videoItem->getIsAccessible()) { $videoItem = null; } $shouldShowItem = false; // if there is a live stream which is in the "not live" state the player won't display the vod // even if there is one. It will show the countdown to the start of the live stream. if (is_null($liveStreamItem) || !$liveStreamItem->isNotLive()) { if (!is_null($videoItem) && $videoItem->getIsLive()) { $shouldShowItem = true; } else { if (!is_null($liveStreamItem) && $liveStreamItem->hasWatchableContent()) { $shouldShowItem = true; } } } if (!$shouldShowItem) { $promoMediaItem = null; } } $promoPlaylist = null; if (!is_null($promoMediaItem)) { $promoPlaylist = $promoMediaItem->getDefaultPlaylist(); } $promotedItems = MediaItem::getCachedPromotedItems(); $promotedItemsData = array(); // if there is an item to promote insert it at the start of the carousel if (!is_null($promoMediaItem)) { $coverArtResolutions = Config::get("imageResolutions.coverArt"); $isLiveShow = !is_null($promoMediaItem->liveStreamItem) && !$promoMediaItem->liveStreamItem->isOver(); $liveNow = $isLiveShow && $promoMediaItem->liveStreamItem->isLive(); $promotedItemsData[] = array("coverArtUri" => $promoPlaylist->getMediaItemCoverArtUri($promoMediaItem, $coverArtResolutions['full']['w'], $coverArtResolutions['full']['h']), "name" => $promoMediaItem->name, "seriesName" => !is_null($promoPlaylist->show) ? $promoPlaylist->generateName() : null, "availableMsg" => $liveNow ? "Live Now!" : $this->buildTimeStr($isLiveShow, $promoMediaItem->scheduled_publish_time), "uri" => $promoPlaylist->getMediaItemUri($promoMediaItem)); } foreach ($promotedItems as $a) { $mediaItem = $a['mediaItem']; if (!is_null($promoMediaItem) && intval($mediaItem->id) === intval($promoMediaItem->id)) { // prevent duplicate continue; } $isLiveShow = !is_null($mediaItem->liveStreamItem) && !$mediaItem->liveStreamItem->isOver(); $liveNow = $isLiveShow && $mediaItem->liveStreamItem->isLive(); $promotedItemsData[] = array("coverArtUri" => $a['coverArtUri'], "name" => $mediaItem->name, "seriesName" => $a['seriesName'], "availableMsg" => $liveNow ? "Live Now!" : $this->buildTimeStr($isLiveShow, $mediaItem->scheduled_publish_time), "uri" => $a['uri']); } $coverArtResolutions = Config::get("imageResolutions.coverArt"); $recentlyAddedItems = MediaItem::getCachedRecentItems(); $recentlyAddedTableData = array(); foreach ($recentlyAddedItems as $i => $a) { $mediaItem = $a['mediaItem']; $recentlyAddedTableData[] = array("uri" => $a['uri'], "active" => false, "title" => $mediaItem->name, "escapedDescription" => null, "playlistName" => $a['playlistName'], "episodeNo" => $i + 1, "thumbnailUri" => $a['coverArtUri'], "thumbnailFooter" => null, "duration" => $a['duration']); } $mostPopularItems = MediaItem::getCachedMostPopularItems(); $mostPopularTableData = array(); foreach ($mostPopularItems as $i => $a) { $mediaItem = $a['mediaItem']; $mostPopularTableData[] = array("uri" => $a['uri'], "active" => false, "title" => $mediaItem->name, "escapedDescription" => null, "playlistName" => $a['playlistName'], "episodeNo" => $i + 1, "thumbnailUri" => $a['coverArtUri'], "thumbnailFooter" => null, "duration" => $a['duration']); } $view = View::make("home.index"); $view->promotedItemsData = $promotedItemsData; $view->recentlyAddedPlaylistFragment = count($recentlyAddedTableData) > 0 ? View::make("fragments.home.playlist", array("stripedTable" => true, "headerRowData" => null, "tableData" => $recentlyAddedTableData)) : null; $view->mostPopularPlaylistFragment = count($mostPopularTableData) > 0 ? View::make("fragments.home.playlist", array("stripedTable" => true, "headerRowData" => null, "tableData" => $mostPopularTableData)) : null; $view->twitterWidgetId = Config::get("twitter.timeline_widget_id"); $hasPromoItem = !is_null($promoMediaItem); $showPromoItem = $hasPromoItem; if ($hasPromoItem) { // determine if the user has already seen the promo $cookieVal = Cookie::get('seenPromo-' . $promoMediaItem->id); if (!is_null($cookieVal) && $cookieVal === $promoMediaItem->time_promoted->timestamp) { // user already seen promo $showPromoItem = false; } // put a cookie in the users browser to inform us in the future that the user has seen this promo video // store the time so that if the item is repromoted in the future, it will be shown again. Cookie::queue('seenPromo-' . $promoMediaItem->id, $promoMediaItem->time_promoted->timestamp, 40320); // store for 4 weeks } $view->showPromoItem = $showPromoItem; if ($showPromoItem) { $userHasMediaItemsPermission = false; if (Auth::isLoggedIn()) { $userHasMediaItemsPermission = Auth::getUser()->hasPermission(Config::get("permissions.mediaItems"), 0); } $view->promoPlayerInfoUri = PlayerHelpers::getInfoUri($promoPlaylist->id, $promoMediaItem->id); $view->promoRegisterWatchingUri = PlayerHelpers::getRegisterWatchingUri($promoPlaylist->id, $promoMediaItem->id); $view->promoRegisterLikeUri = PlayerHelpers::getRegisterLikeUri($promoPlaylist->id, $promoMediaItem->id); $view->promoAdminOverrideEnabled = $userHasMediaItemsPermission; $view->promoLoginRequiredMsg = "Please log in to use this feature."; } $this->setContent($view, "home", "home", array(), null, 200, array()); }
public function generateMediaItemsResponseData($limit, $sortMode, $sortDirection, $vodIncludeSetting, $streamIncludeSetting, $showStreamUris, $showVodUris) { $maxLimit = Config::get("api.mediaItemsMaxRetrieveLimit"); if ($limit > $maxLimit) { $limit = $maxLimit; } $mediaItems = null; if ($sortMode === "POPULARITY") { if ($sortDirection === "ASC") { throw new Exception("ASC sort direction not supported for POPULARITY sort mode."); } else { if ($sortDirection === "DESC") { // intentional } else { throw new Exception("Invalid sort direction."); } } $items = MediaItem::getCachedMostPopularItems(); $allMediaItems = array_column($items, 'mediaItem'); $mediaItems = []; foreach ($allMediaItems as $a) { $includeVod = null; if ($vodIncludeSetting === "VOD_OPTIONAL") { // intentional } else { if ($vodIncludeSetting === "HAS_VOD") { $includeVod = !is_null($a->videoItem) && $a->videoItem->getIsAccessible(); } else { if ($vodIncludeSetting === "HAS_AVAILABLE_VOD") { $includeVod = !is_null($a->videoItem) && $a->getIsAccessible() && $a->videoItem->getIsLive(); } else { throw new Exception("Invalid vod include setting."); } } } $includeStream = null; if ($streamIncludeSetting === "STREAM_OPTIONAL") { // intentional } else { if ($streamIncludeSetting === "HAS_STREAM") { $includeStream = !is_null($a->liveStreamItem) && $a->liveStreamItem->getIsAccessible(); } else { if ($streamIncludeSetting === "HAS_LIVE_STREAM") { $includeStream = !is_null($a->liveStreamItem) && $a->liveStreamItem->getIsAccessible() && $a->liveStreamItem->isLive(); } else { throw new Exception("Invalid stream include setting."); } } } if (is_null($includeStream) && is_null($includeVod) || $includeStream || $includeVod) { $mediaItems[] = $a; } } } else { if ($sortMode === "SCHEDULED_PUBLISH_TIME") { $mediaItems = MediaItem::with("liveStreamItem", "liveStreamItem.stateDefinition", "liveStreamItem.liveStream", "videoItem", "videoItem.sourceFile.vodData")->accessible(); $mediaItems = $mediaItems->where(function ($q) use(&$vodIncludeSetting, &$streamIncludeSetting) { if ($vodIncludeSetting === "VOD_OPTIONAL") { // intentional } else { if ($vodIncludeSetting === "HAS_VOD") { $q->whereHas("videoItem", function ($q2) { $q2->accessible(); }); } else { if ($vodIncludeSetting === "HAS_AVAILABLE_VOD") { $q->whereHas("videoItem", function ($q2) { $q2->live(); }); } else { throw new Exception("Invalid vod include setting."); } } } if ($streamIncludeSetting === "STREAM_OPTIONAL") { // intentional } else { if ($streamIncludeSetting === "HAS_STREAM") { $q->orWhereHas("liveStreamItem", function ($q2) { $q2->accessible(); }); } else { if ($streamIncludeSetting === "HAS_LIVE_STREAM") { $q->orWhereHas("liveStreamItem", function ($q2) { $q2->live(); }); } else { throw new Exception("Invalid stream include setting."); } } } }); $sortAsc = null; if ($sortDirection === "ASC") { $sortAsc = true; } else { if ($sortDirection === "DESC") { $sortAsc = false; } else { throw new Exception("Invalid sort direction."); } } $mediaItems = $mediaItems->orderBy("media_items.scheduled_publish_time", $sortAsc ? "asc" : "desc")->orderBy("id", "asc")->take($limit)->get()->all(); } else { throw new Exception("Invalid sort mode."); } } $mediaItemsAndPlaylists = []; foreach ($mediaItems as $a) { $mediaItemsAndPlaylists[] = [null, $a]; } $data = ["mediaItems" => $this->mediaItemTransformer->transformCollection($mediaItemsAndPlaylists, $this->getMediaItemTransformerOptions($showStreamUris, $showVodUris))]; return new ApiResponseData($data); }
public function getIndex($dayGroupOffset = 0) { $dayGroupOffset = intval($dayGroupOffset); $daysPerPage = intval(Config::get("guide.daysPerPage")); $numPages = intval(Config::get("guide.numPages")); if (abs($dayGroupOffset) > $numPages) { App::abort(404); } $dayOffset = $dayGroupOffset * $daysPerPage; $startDate = Carbon::now()->startOfDay()->addDays($dayOffset); $endDate = Carbon::now()->startOfDay()->addDays($dayOffset + $daysPerPage); $mediaItems = MediaItem::with("liveStreamItem")->accessible()->scheduledPublishTimeBetweenDates($startDate, $endDate)->orderBy("scheduled_publish_time", "asc")->orderBy("name", "asc")->orderBy("description", "asc")->get(); // of form ("dateStr", "mediaItems") $calendarData = array(); $previousMediaItem = null; $lastDate = $startDate; foreach ($mediaItems as $a) { if (is_null($previousMediaItem) || $previousMediaItem->scheduled_publish_time->startOfDay()->timestamp !== $a->scheduled_publish_time->startOfDay()->timestamp) { // new day $calendarData[] = array("dateStr" => $this->getDateString($a->scheduled_publish_time->startOfDay()), "mediaItems" => array()); $lastDate = $a->scheduled_publish_time->startOfDay(); } $calendarData[count($calendarData) - 1]['mediaItems'][] = $a; $previousMediaItem = $a; } $coverArtResolutions = Config::get("imageResolutions.coverArt"); $viewCalendarData = array(); foreach ($calendarData as $day) { $playlistTableData = array(); foreach ($day['mediaItems'] as $i => $item) { $playlist = $item->getDefaultPlaylist(); $thumbnailUri = Config::get("custom.default_cover_uri"); if (!Config::get("degradedService.enabled")) { $thumbnailUri = $playlist->getMediaItemCoverArtUri($item, $coverArtResolutions['thumbnail']['w'], $coverArtResolutions['thumbnail']['h']); } $playlistName = null; if (!is_null($playlist->show)) { // the current item in the playlist is part of a show. $playlistName = $playlist->generateName(); } $isLive = !is_null($item->liveStreamItem) && $item->liveStreamItem->getIsAccessible(); $playlistTableData[] = array("uri" => $playlist->getMediaItemUri($item), "title" => $playlist->generateEpisodeTitle($item), "escapedDescription" => !is_null($item->description) ? e($item->description) : null, "playlistName" => $playlistName, "episodeNo" => null, "thumbnailUri" => $thumbnailUri, "thumbnailFooter" => array("isLive" => $isLive, "dateTxt" => $item->scheduled_publish_time->format("H:i")), "active" => false); } $playlistFragment = View::make("fragments.home.playlist", array("stripedTable" => false, "headerRowData" => null, "tableData" => $playlistTableData)); $viewCalendarData[] = array("dateStr" => $day['dateStr'], "playlistFragment" => $playlistFragment); } $twitterProperties = array(); $twitterProperties[] = array("name" => "card", "content" => "summary"); $openGraphProperties = array(); $description = "View a schedule of our upcoming content and also content you may have missed."; $twitterProperties[] = array("name" => "description", "content" => str_limit($description, 197, "...")); $openGraphProperties[] = array("name" => "og:description", "content" => $description); $title = "Guide"; $twitterProperties[] = array("name" => "title", "content" => $title); $openGraphProperties[] = array("name" => "og:title", "content" => $title); $view = View::make("home.guide.index"); $view->calendarData = $viewCalendarData; $view->titleDatesStr = $this->getDateString($startDate) . " - " . $this->getDateString((new Carbon($endDate))->subDays(1)); $view->previousPageUri = $dayGroupOffset !== -1 * $numPages ? URL::route("guide", array($dayGroupOffset - 1)) : null; $view->previousPageStartDateStr = $this->getDateString($startDate->subDays($daysPerPage)); $view->nextPageUri = $dayGroupOffset !== $numPages ? URL::route("guide", array($dayGroupOffset + 1)) : null; $view->nextPageStartDateStr = $this->getDateString($endDate); $this->setContent($view, "guide", "guide", $openGraphProperties, $title, 200, $twitterProperties); }
public function postComments($mediaItemId) { $mediaItem = MediaItem::with("comments", "comments.siteUser")->accessible()->find($mediaItemId); if (is_null($mediaItem)) { App::abort(404); } if (!$mediaItem->comments_enabled) { App::abort(403); // forbidden } // X = a number of comments // id = the id of the comment to start at. -1 means return the last X comments. loadLaterComments must be false in this case // load_later_comments = if true return all comments from the specified id otherwise load comments before it. // the id that is provided isn't checked to be valid as the comment it points too may have been deleted. $id = FormHelpers::getValue("id"); $loadLaterComments = FormHelpers::getValue("load_later_comments") === "1"; $id = !is_null($id) ? intval($id) : null; if (is_null($id)) { throw new Exception("Id must be set."); } else { if ($id === -1 && $loadLaterComments) { throw new Exception("If the id is -1 then load_later_comments must be false."); } } $commentsModels = null; $more = null; if ($loadLaterComments) { $commentsModels = $mediaItem->comments()->orderBy("id", "asc")->where("id", ">=", $id)->limit(Config::get("comments.number_to_retrieve") + 1)->get(); $more = $commentsModels->count() === Config::get("comments.number_to_retrieve") + 1; if ($more) { $commentsModels->pop(); } } else { $commentsModels = $mediaItem->comments()->orderBy("id", "desc"); if ($id !== -1) { $commentsModels = $commentsModels->where("id", "<=", $id); } $commentsModels = $commentsModels->limit(Config::get("comments.number_to_retrieve") + 1)->get(); $more = $commentsModels->count() === Config::get("comments.number_to_retrieve") + 1; if ($more) { $commentsModels->pop(); } $commentsModels = $commentsModels->reverse(); // get in ascending order } // true if a user is logged into the cms and has permission to manage comments and post as station. $userHasCommentsPermission = Auth::isLoggedIn() && Auth::getUser()->hasPermission(Config::get("permissions.siteComments"), 0); $comments = array(); foreach ($commentsModels as $a) { // should not be returning supplied id if ($id !== -1 && intval($a->id) === $id) { continue; } $siteUser = $a->siteUser; $permissionToDelete = $userHasCommentsPermission || Facebook::isLoggedIn() && !is_null($siteUser) && intval(Facebook::getUser()->id) === intval($siteUser->id); $escapedMsg = URLHelpers::escapeAndReplaceUrls($a->msg); $comments[] = array("id" => intval($a->id), "profilePicUri" => !is_null($siteUser) ? $siteUser->getProfilePicUri(100, 100) : Config::get("comments.station_profile_picture_uri"), "postTime" => $a->created_at->timestamp, "name" => !is_null($siteUser) ? $siteUser->name : Config::get("comments.station_name"), "escapedMsg" => $escapedMsg, "permissionToDelete" => $permissionToDelete, "edited" => (bool) $a->edited); } $response = array("comments" => $comments, "more" => $more); return Response::json($response); }