public IDictionary <List <BaseItem>, List <BaseItem> > GetItemsByActor(User user, List <string> actorNames) { var actors = new List <BaseItem>(); foreach (var actor in actorNames) { var actorName = StringNormalization.ValidateSpeechQueryString(actor); var actorQuery = LibraryManager.GetItemsResult(new InternalItemsQuery() { IncludeItemTypes = new[] { "Person" }, SearchTerm = actorName, Recursive = true }); if (actorQuery.TotalRecordCount <= 0) { continue; } actors.Add(actorQuery.Items[0]); } var query = LibraryManager.GetItemsResult(new InternalItemsQuery(user) { IncludeItemTypes = new[] { "Series", "Movie" }, Recursive = true, PersonIds = actors.Select(a => a.InternalId).ToArray() }); return(new Dictionary <List <BaseItem>, List <BaseItem> >() { { actors, query.Items.ToList() } }); }
protected static void UpComingEpisodes(StringBuilder speech, List <BaseItem> items, DateTime date) { speech.Append("There "); speech.Append(items?.Count > 1 ? "are" : "is"); speech.Append(SayAsCardinal(items?.Count.ToString())); speech.Append(" upcoming episode"); speech.Append(items?.Count > 1 ? "s" : ""); speech.Append($" scheduled to air over the next {(date - DateTime.Now).Days} days."); speech.Append(InsertStrengthBreak(StrengthBreak.weak)); var schedule = items.DistinctBy(item => item.Parent.ParentId).ToList(); var dateGroup = schedule.GroupBy(s => s?.PremiereDate); foreach (var d in dateGroup) { // ReSharper disable once PossibleNullReferenceException // ReSharper disable once PossibleInvalidOperationException speech.Append($"On {d.Key.Value.DayOfWeek}'s:"); speech.Append(InsertStrengthBreak(StrengthBreak.strong)); var i = 1; foreach (var item in d) { speech.Append(StringNormalization.ValidateSpeechQueryString(item.Parent.Parent.Name)); if (item.IndexNumber == 1) { speech.Append($" which will premiere season {SayAsCardinal(item.Parent.IndexNumber.ToString())} "); speech.Append(SayAsDate(Date.md, d.Key.Value.ToString("M/d"))); speech.Append(InsertStrengthBreak(StrengthBreak.weak)); } speech.Append(", "); if (d.Count() > 1 && i == d.Count() - 1) { speech.Append(" and "); } i++; } } speech.Append( $"This completes the list of episodes scheduled for the next {(date - DateTime.Now).Days} days. "); }
protected static void NewLibraryItems(StringBuilder speech, List <BaseItem> items, DateTime date, IAlexaSession session) { speech.Append("There "); speech.Append(items?.Count > 1 ? "are" : "is"); speech.Append(SayAsCardinal(items?.Count.ToString())); speech.Append(" new "); speech.Append(items?.Count > 1 ? items[0].GetType().Name + "s" : items?[0].GetType().Name); //var date = DateTime.Parse(query.args[0]); speech.Append($" added in the past {(date - DateTime.Now).Days * -1} days. "); if (!session.supportsApl) { speech.Append(string.Join($", {InsertStrengthBreak(StrengthBreak.weak)}", // ReSharper disable once AssignNullToNotNullAttribute items?.ToArray().Select(item => StringNormalization.ValidateSpeechQueryString(item.Name)))); } }
protected static void ItemBrowse(StringBuilder speech, BaseItem item, IAlexaSession session, bool deviceAvailable = true) { if (deviceAvailable == false) { speech.Append(GetSpeechPrefix(SpeechPrefix.DYSFLUENCY_NEGATIVE)); speech.Append(InsertStrengthBreak(StrengthBreak.weak)); speech.Append(GetSpeechPrefix(SpeechPrefix.APOLOGETIC)); speech.Append(InsertStrengthBreak(StrengthBreak.weak)); speech.Append("That device is currently unavailable."); return; } //speech.Append(GetSpeechPrefix(SpeechPrefix.COMPLIANCE)); speech.Append(InsertStrengthBreak(StrengthBreak.weak)); if (RandomIndex.NextDouble() > 0.5 && !item.IsFolder) //Randomly incorporate "Here is.." into phrasing { speech.Append("Here is "); } var name = StringNormalization.ValidateSpeechQueryString(item.Name); speech.Append(name); if (!item.IsFolder) //Don't describe a rating of a library or collection folder. { var rating = item.OfficialRating; speech.Append(", "); speech.Append(string.IsNullOrEmpty(rating) ? "unrated" : $"Rated {rating}"); } if (!session.hasRoom) { return; } speech.Append(InsertStrengthBreak(StrengthBreak.weak)); speech.Append("Showing in the "); speech.Append(session.room.Name); }
public async Task <string> Response() { await AlexaResponseClient.Instance.PostProgressiveResponse("OK.", AlexaRequest.context.System.apiAccessToken, AlexaRequest.request.requestId); //TODO: Why does validating a room throw an object exception in this class? No other Intent class throws an object exception here. try { Session.room = await RoomContextManager.Instance.ValidateRoom(AlexaRequest, Session); } catch { } //catch the exception and throw it away. If there is a room requested at this point there will be no exception. Session.hasRoom = !(Session.room is null); if (!Session.hasRoom && !Session.supportsApl) { Session.PersistedRequestData = AlexaRequest; AlexaSessionManager.Instance.UpdateSession(Session, null); return(await RoomContextManager.Instance.RequestRoom(AlexaRequest, Session)); } var request = AlexaRequest.request; var intent = request.intent; var slots = intent.slots; var collectionRequest = slots.MovieCollection.value ?? slots.Movie.value; collectionRequest = StringNormalization.ValidateSpeechQueryString(collectionRequest); ServerController.Instance.Log.Info($"Collection Request: {collectionRequest}"); var collection = ServerDataQuery.Instance.GetCollectionItems(Session.User, collectionRequest); var collectionItems = collection.Values.FirstOrDefault(); var collectionBaseItem = collection.Keys.FirstOrDefault(); //Parental Control check for baseItem if (!(collectionBaseItem is null)) { if (!collectionBaseItem.IsParentalAllowed(Session.User)) { if (Plugin.Instance.Configuration.EnableServerActivityLogNotifications) { await ServerController.Instance.CreateActivityEntry(LogSeverity.Warn, $"{Session.User} attempted to view a restricted item.", $"{Session.User} attempted to view {collectionBaseItem.Name}.").ConfigureAwait(false); } var genericLayoutProperties = await DataSourcePropertiesManager.Instance.GetGenericViewPropertiesAsync($"Stop! Rated {collectionBaseItem.OfficialRating}", "/particles"); var aplaDataSource = await DataSourcePropertiesManager.Instance.GetAudioResponsePropertiesAsync(new InternalAudioResponseQuery() { SpeechResponseType = SpeechResponseType.ParentalControlNotAllowed, item = collectionBaseItem, session = Session }); return(await AlexaResponseClient.Instance.BuildAlexaResponseAsync(new Response() { shouldEndSession = true, directives = new List <IDirective>() { await RenderDocumentDirectiveManager.Instance.RenderVisualDocumentDirectiveAsync(genericLayoutProperties, Session), await RenderDocumentDirectiveManager.Instance.RenderAudioDocumentDirectiveAsync(aplaDataSource) } }, Session)); } } if (Session.hasRoom) { try { await ServerController.Instance.BrowseItemAsync(Session, collectionBaseItem); } catch (Exception exception) { ServerController.Instance.Log.Error(exception.Message); } } var sequenceLayoutProperties = await DataSourcePropertiesManager.Instance.GetBaseItemCollectionSequenceViewPropertiesAsync(collectionItems, collectionBaseItem); //Update Session Session.NowViewingBaseItem = collectionBaseItem; AlexaSessionManager.Instance.UpdateSession(Session, sequenceLayoutProperties); var renderDocumentDirective = await RenderDocumentDirectiveManager.Instance.RenderVisualDocumentDirectiveAsync(sequenceLayoutProperties, Session); return(await AlexaResponseClient.Instance.BuildAlexaResponseAsync(new Response() { outputSpeech = new OutputSpeech() { phrase = $"{collectionBaseItem?.Name}", }, shouldEndSession = null, directives = new List <IDirective>() { renderDocumentDirective }, }, Session)); }
public async Task <string> Response() { await AlexaResponseClient.Instance.PostProgressiveResponse($"OK. { SpeechBuilderService.GetSpeechPrefix(SpeechPrefix.REPOSE)}.", AlexaRequest.context.System.apiAccessToken, AlexaRequest.request.requestId); Session.room = await RoomContextManager.Instance.ValidateRoom(AlexaRequest, Session); Session.hasRoom = !(Session.room is null); if (!Session.hasRoom && !Session.supportsApl) { Session.PersistedRequestData = AlexaRequest; AlexaSessionManager.Instance.UpdateSession(Session, null); return(await RoomContextManager.Instance.RequestRoom(AlexaRequest, Session)); } var request = AlexaRequest.request; var intent = request.intent; var slots = intent.slots; var searchName = (slots.Movie.value ?? slots.Series.value) ?? slots.MovieCollection.value; searchName = StringNormalization.ValidateSpeechQueryString(searchName); if (string.IsNullOrEmpty(searchName)) { return(await new NotUnderstood(AlexaRequest, Session).Response()); } var result = ServerDataQuery.Instance.QuerySpeechResultItem(searchName, new[] { "Movie", "Series", "Collection" }); if (result is null) { var aplaDataSourceProperties = await DataSourcePropertiesManager.Instance.GetAudioResponsePropertiesAsync(new InternalAudioResponseQuery() { SpeechResponseType = SpeechResponseType.NoItemExists }); return(await AlexaResponseClient.Instance.BuildAlexaResponseAsync(new Response() { shouldEndSession = true, directives = new List <IDirective>() { await RenderDocumentDirectiveManager.Instance.RenderAudioDocumentDirectiveAsync(aplaDataSourceProperties) } }, Session)); } //User should not access this item. Warn the user, and place a notification in the Emby Activity Label if (!result.IsParentalAllowed(Session.User)) { try { var config = Plugin.Instance.Configuration; if (config.EnableServerActivityLogNotifications) { await ServerController.Instance.CreateActivityEntry(LogSeverity.Warn, $"{Session.User} attempted to view a restricted item.", $"{Session.User} attempted to view {result.Name}."); } } catch { } var genericLayoutProperties = await DataSourcePropertiesManager.Instance.GetGenericViewPropertiesAsync($"Stop! Rated {result.OfficialRating}", "/particles"); var parentalControlNotAllowedAudioProperties = await DataSourcePropertiesManager.Instance.GetAudioResponsePropertiesAsync(new InternalAudioResponseQuery() { SpeechResponseType = SpeechResponseType.ParentalControlNotAllowed, item = result, session = Session }); return(await AlexaResponseClient.Instance.BuildAlexaResponseAsync(new Response() { shouldEndSession = null, directives = new List <IDirective>() { await RenderDocumentDirectiveManager.Instance.RenderVisualDocumentDirectiveAsync(genericLayoutProperties, Session), await RenderDocumentDirectiveManager.Instance.RenderAudioDocumentDirectiveAsync(parentalControlNotAllowedAudioProperties) } }, Session)); } if (Session.hasRoom) { try { await ServerController.Instance.BrowseItemAsync(Session, result); } catch (Exception exception) { ServerController.Instance.Log.Error(exception.Message); } } var sequenceLayoutProperties = await DataSourcePropertiesManager.Instance.GetBaseItemDetailViewPropertiesAsync(result, Session); var aplaDataSource1 = await DataSourcePropertiesManager.Instance.GetAudioResponsePropertiesAsync(new InternalAudioResponseQuery() { SpeechResponseType = SpeechResponseType.ItemBrowse, item = result, session = Session } ); //Update Session Session.NowViewingBaseItem = result; AlexaSessionManager.Instance.UpdateSession(Session, sequenceLayoutProperties); var renderDocumentDirective = await RenderDocumentDirectiveManager.Instance.RenderVisualDocumentDirectiveAsync(sequenceLayoutProperties, Session); var renderAudioDirective = await RenderDocumentDirectiveManager.Instance.RenderAudioDocumentDirectiveAsync(aplaDataSource1); try { return(await AlexaResponseClient.Instance.BuildAlexaResponseAsync(new Response() { shouldEndSession = null, directives = new List <IDirective>() { renderDocumentDirective, renderAudioDirective } }, Session)); } catch (Exception exception) { throw new Exception("I was unable to build the render document. " + exception.Message); } }