savings changes for jordi to play around

This commit is contained in:
Ethan Fang
2024-09-18 15:04:41 -05:00
parent 52cac94e26
commit e9ee4046df
10 changed files with 254 additions and 8 deletions

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CmdPal.Extensions.Helpers;
namespace YouTubeExtension.Helper;
internal sealed partial class GetVideoInfoAction : InvokableCommand
{
private readonly YouTubeVideo _video;
internal GetVideoInfoAction(YouTubeVideo video)
{
this._video = video;
this.Name = "See more information";
this.Icon = new("\uE946");
}
public override CommandResult Invoke()
{
return CommandResult.KeepOpen();
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CmdPal.Extensions.Helpers;
namespace YouTubeExtension.Helper;
internal sealed partial class OpenChannelLinkAction : InvokableCommand
{
private readonly YouTubeVideo _video;
internal OpenChannelLinkAction(YouTubeVideo video)
{
this._video = video;
this.Name = "Open channel";
this.Icon = new("\uF131");
}
public override CommandResult Invoke()
{
Process.Start(new ProcessStartInfo(_video.ChannelUrl) { UseShellExecute = true });
return CommandResult.KeepOpen();
}
}

View File

@@ -12,15 +12,15 @@ using Microsoft.CmdPal.Extensions.Helpers;
namespace YouTubeExtension.Helper;
internal sealed partial class LinkAction : InvokableCommand
internal sealed partial class OpenVideoLinkAction : InvokableCommand
{
private readonly YouTubeVideo _video;
internal LinkAction(YouTubeVideo video)
internal OpenVideoLinkAction(YouTubeVideo video)
{
this._video = video;
this.Name = "Open link";
this.Icon = new("https://www.youtube.com/favicon.ico");
this.Name = "Open video";
this.Icon = new("\uE714");
}
public override CommandResult Invoke()

View File

@@ -21,6 +21,12 @@ public sealed class YouTubeVideo
// The author or channel name of the video
public string Author { get; init; } = string.Empty;
// The channel id (needed for the channel URL)
public string ChannelId { get; set; }
// The URL link to the channel
public string ChannelUrl { get; set; }
// The URL to the thumbnail image of the video
public string ThumbnailUrl { get; init; } = string.Empty;

View File

@@ -27,7 +27,7 @@ internal sealed partial class YouTubeAPIForm : Form
"body": [
{
"type": "Input.Text",
"style": "text",
"style": "password",
"id": "apiKey",
"label": "API Key",
"isRequired": true,

View File

@@ -20,7 +20,7 @@ internal sealed partial class YouTubeAPIPage : FormPage
public YouTubeAPIPage()
{
Name = "YouTube API";
Name = "Edit YouTube API Key";
Icon = new("https://www.youtube.com/favicon.ico");
}
}

View File

@@ -0,0 +1,117 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using YouTubeExtension.Helper;
namespace YouTubeExtension.Pages;
internal sealed partial class YouTubeChannelsPage : DynamicListPage
{
public YouTubeChannelsPage()
{
Icon = new("https://www.youtube.com/favicon.ico");
Name = "YouTube";
this.ShowDetails = true;
}
public override ISection[] GetItems(string query)
{
return DoGetItems(query).GetAwaiter().GetResult(); // Fetch and await the task synchronously
}
private async Task<ISection[]> DoGetItems(string query)
{
// Fetch YouTube videos based on the query
List<YouTubeVideo> items = await GetYouTubeVideos(query);
// Create a section and populate it with the video results
var section = new ListSection()
{
Title = "Search Results",
Items = items.Select(video => new ListItem(new OpenVideoLinkAction(video))
{
Title = video.Title,
Subtitle = $"{video.Author}",
Details = new Details()
{
Title = video.Title,
HeroImage = new(video.ThumbnailUrl),
Body = $"{video.Author}",
},
Tags = [new Tag()
{
Text = video.PublishedAt.ToString("MMMM dd, yyyy", CultureInfo.InvariantCulture), // Show the date of the video post
}
],
}).ToArray(),
};
return new[] { section }; // Properly return an array of sections
}
// Method to fetch videos from YouTube API
private static async Task<List<YouTubeVideo>> GetYouTubeVideos(string query)
{
var state = File.ReadAllText(YouTubeHelper.StateJsonPath());
var jsonState = JsonNode.Parse(state);
var apiKey = jsonState["apiKey"]?.ToString() ?? string.Empty;
var videos = new List<YouTubeVideo>();
using HttpClient client = new HttpClient();
{
try
{
// Send the request to the YouTube API with the provided query
var response = await client.GetStringAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={query}&key={apiKey}&maxResults=2");
var json = JsonNode.Parse(response);
// Parse the response
if (json?["items"] is JsonArray itemsArray)
{
foreach (var item in itemsArray)
{
// Add each video to the list with title, link, author, thumbnail, and captions (if available)
videos.Add(new YouTubeVideo
{
Title = item["snippet"]?["title"]?.ToString() ?? string.Empty,
Link = $"https://www.youtube.com/watch?v={item["id"]?["videoId"]?.ToString()}",
Author = item["snippet"]?["channelTitle"]?.ToString() ?? string.Empty,
ThumbnailUrl = item["snippet"]?["thumbnails"]?["default"]?["url"]?.ToString() ?? string.Empty, // Get the default thumbnail URL
Captions = "Captions not available", // Placeholder for captions; You can integrate with another API if needed
PublishedAt = DateTime.Parse(item["snippet"]?["publishedAt"]?.ToString(), CultureInfo.InvariantCulture), // Use CultureInfo.InvariantCulture
});
}
}
}
catch (Exception ex)
{
// Handle any errors from the API call or parsing
videos.Add(new YouTubeVideo
{
Title = "Error fetching data",
Link = string.Empty,
Author = $"Error: {ex.Message}",
ThumbnailUrl = string.Empty,
Captions = string.Empty,
PublishedAt = DateTime.MinValue,
});
}
}
return videos;
}
}

View File

@@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using Microsoft.UI.Windowing;
namespace SamplePagesExtension;
internal sealed partial class YouTubeVideoInfoMarkdownPage : MarkdownPage
{
private readonly string _markdown = @"
# Markdown Guide
Markdown is a lightweight markup language with plain text formatting syntax. It's often used to format readme files, for writing messages in online forums, and to create rich text using a simple, plain text editor.
---
## Headings
You can create headings using the `#` symbol, with the number of `#` determining the heading level.
```markdown
# H1 Heading
## H2 Heading
### H3 Heading
#### H4 Heading
";
public YouTubeVideoInfoMarkdownPage()
{
Icon = new("\uE946");
Name = "See more information";
}
public override string[] Bodies()
{
return [_markdown];
}
}

View File

@@ -9,10 +9,13 @@ using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.Json.Nodes;
using System.Threading.Channels;
using System.Threading.Tasks;
using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.Extensions.Helpers;
using SamplePagesExtension;
using YouTubeExtension.Helper;
using YouTubeExtension.Pages;
namespace YouTubeExtension;
@@ -39,7 +42,7 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
var section = new ListSection()
{
Title = "Search Results",
Items = items.Select(video => new ListItem(new LinkAction(video))
Items = items.Select(video => new ListItem(new OpenVideoLinkAction(video))
{
Title = video.Title,
Subtitle = $"{video.Author}",
@@ -54,6 +57,11 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
Text = video.PublishedAt.ToString("MMMM dd, yyyy", CultureInfo.InvariantCulture), // Show the date of the video post
}
],
MoreCommands = [
new CommandContextItem(new OpenChannelLinkAction(video)),
new CommandContextItem(new YouTubeVideoInfoMarkdownPage()),
new CommandContextItem(new YouTubeAPIPage()),
],
}).ToArray(),
};
@@ -74,7 +82,7 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
try
{
// Send the request to the YouTube API with the provided query
var response = await client.GetStringAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={query}&key={apiKey}&maxResults=20");
var response = await client.GetStringAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={query}&key={apiKey}&maxResults=2");
var json = JsonNode.Parse(response);
// Parse the response
@@ -88,6 +96,8 @@ internal sealed partial class YouTubeVideosPage : DynamicListPage
Title = item["snippet"]?["title"]?.ToString() ?? string.Empty,
Link = $"https://www.youtube.com/watch?v={item["id"]?["videoId"]?.ToString()}",
Author = item["snippet"]?["channelTitle"]?.ToString() ?? string.Empty,
ChannelId = item["snippet"]?["channelId"]?.ToString() ?? string.Empty,
ChannelUrl = $"https://www.youtube.com/channel/{item["snippet"]?["channelId"]?.ToString()}" ?? string.Empty,
ThumbnailUrl = item["snippet"]?["thumbnails"]?["default"]?["url"]?.ToString() ?? string.Empty, // Get the default thumbnail URL
Captions = "Captions not available", // Placeholder for captions; You can integrate with another API if needed
PublishedAt = DateTime.Parse(item["snippet"]?["publishedAt"]?.ToString(), CultureInfo.InvariantCulture), // Use CultureInfo.InvariantCulture

View File

@@ -25,6 +25,7 @@ public partial class YouTubeExtensionActionsProvider : ICommandProvider
private readonly IListItem[] _commands = [
new ListItem(new YouTubeVideosPage()) { Title = "Search Videos", Subtitle = "YouTube" },
new ListItem(new YouTubeChannelsPage()) { Title = "Search Channels", Subtitle = "YouTube" },
];
private readonly YouTubeAPIPage apiPage = new();