65.9K
CodeProject 正在变化。 阅读更多。
Home

tv2html:使用离线可浏览 HTML 对您的电视节目进行分类

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2024 年 4 月 10 日

MIT

5分钟阅读

viewsIcon

5194

downloadIcon

195

生成一个可 Web 浏览的界面来访问您的存档电视节目内容

引言

我有一些几年前在 DVD 和蓝光上购买的节目,我已经将它们归档了,因为我讨厌光盘切换,而且我喜欢有备份。

问题在于浏览这些节目,这让我只能使用普通的 Windows 文件资源管理器或连接到智能电视的某种 DLNA 服务,当这些服务可用时还可以,但并非总是如此,例如旅行时。

我所做的是创建一个命令行实用程序,为您选择的电视节目创建一个可 Web 浏览的界面。它使用 themoviedb.org 的 REST API 来检索有关您节目的信息。然后,您可以浏览到您节目的根目录的 index.html 文件,它将提供一个可导航的界面,显示您所有的视频,并附带系列、季和集信息。

免责声明:有些读者可能会看到这个并想到“哇,我可以用我的盗版媒体来做这个!” - 对于这些读者,我无法阻止您如何使用它,但我也不赞成。而且,实际上,支付您想要的东西通常比运行 VPN 更便宜。

必备组件

  • 您需要一台能够生成 Visual Studio .NET C# 控制台应用程序项目的机器
  • 您需要一个来自 themoviedb.org 的授权令牌。创建一个免费账户,登录,然后转到“账户菜单”->“设置|API”来创建或检索您的授权令牌。不要将其与 API 密钥混淆。

更新:添加了配置文件支持。修复了错误。

背景

这个项目的大部分内容都是模拟的“ASP.NET 页面”,它们绑定到从 REST API 返回的 JSON。我的 csppg 项目用于将 .aspx 文件转换为可以从应用程序执行的 C# 代码。csppg 可执行文件在预编译事件中引用。

为了方便将数据绑定到 JSON,我们使用了 这段代码 的一个变种。

有一个核心的 Tmdb 对象,它处理应用程序的一些核心功能,例如进行 REST 查询或下载文件。

为了处理命令行解析和其他细节,该项目使用了我的 Program.Base 项目。

使用应用程序

下面,AUTH_TOKEN 应该是您从 themoviedb 网站获得的那个大而丑的哈希值。

搜索所有名称中包含“burn”的节目并列出它们

tv2html "burn" AUTH_TOKEN

搜索“Burn Notice” - 将生成到“TV”子目录,因为它将是唯一的匹配项

tv2html "burn notice" AUTH_TOKEN /output TV

生成节目 ID 2919(Burn Notice)并将结果写入当前目录。

tv2html #2919 AUTH_TOKEN

请注意,您可以通过在可执行文件的当前工作目录中提供一个 tv2html.config 文件来省略命令行中的身份验证令牌。该配置文件类似于 .NET 框架项目中的 App.config,但为了跨平台兼容性,不包含可执行文件的扩展名。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="authToken" value="AUTH_TOKEN"/>
  </appSettings>
</configuration>

AUTH_TOKEN 替换为您的身份验证令牌。解决方案文件夹中提供了一个模板。

几件事

  • 创建的目录结构遵循 [Series]\[Season]\[S0#E0# Episode Name] 的形式。
  • index.html 文件是您的主要入口点。在系列文件夹和每个季文件夹中都有一个。
  • 已创建或已下载的文件夹和图像不会被再次创建或下载。如果您想确保获得来自 The Movie DB 的最新信息,请删除它们。
  • 在生成过程中,代码会查找文件夹中是否存在视频文件。如果找到受支持格式的视频文件,则该剧集页面将嵌入该视频。例如,它会搜索 Burn Notice\Season 1\S01E01 Pilot.(mp4|webm|mpeg|ogg)。否则,它将列为不可用。如果您稍后添加更多视频,您将需要重新运行 tv2html 来重新生成您的页面。

编码应用程序

大部分工作由“aspx”文件完成。这些不是真正的 ASP.NET 页面。首先,它们不支持相同的指令,而且它们只支持 C#。此外,没有 Web 服务器的参与。相反,根解决方案文件夹中的 csppg 工具用于将这些类似 aspx 的文件转换为可以从应用程序调用的 C# 代码。我们使用此方法以及 .aspx 扩展名是为了获得 T4 引擎不提供的 IntelliSense,而且此工具不像 T4 那样需要大量投入。

主 Program.csRun() 方法仅处理最后的参数逻辑、初始获取以及运行模板。

  • series.index.aspx 负责顶级的 index.html
  • season.index.aspx 负责每个季的 index.html
  • episode.aspx 负责每个剧集 html 文件。

如果您查看这些文件的内容,您会发现大量使用了 dynamic 关键字。这允许 C# 晚期绑定到我们的 JSON 元素,就好像它们是 C# 中原生的静态类型对象一样。

否则,索引文件就是灵活的网格布局,其中包含季或剧集数据。每个页面都有一个飞出导航侧边栏。剧集页面包含一个视频,如果找不到视频,则显示静态图像。

特别值得关注的是 Tmdb.cs 文件,它处理了一些关键的应用程序功能,包括将 JSON 元素公开为晚期可绑定对象、与 REST 服务器交互以及下载文件。我在介绍中链接的文章中已经介绍了 JSON 的晚期绑定,但我已将该文件中的其他功能发布在这里。

public static string GetSafeFilename(string file)
{
    var result = "";
    var inv = Path.GetInvalidFileNameChars();
    var sb = new StringBuilder();
    sb.Clear();
    for (int j = 0; j < file.Length; j++)
    {
        if (Array.IndexOf(inv, file[j]) > -1)
        {
            sb.Append('_');
        }
        else
        {
            sb.Append(file[j]);
        }
    }
    result = Path.Combine(result, sb.ToString());
        
    return result;
}
public static JsonDocument GetJson(string url)
{
    JsonDocument result;
    using (var msg = new HttpRequestMessage(HttpMethod.Get, url))
    {
        msg.Headers.Clear();
        msg.Headers.Add("accept", "application/json");
        msg.Headers.Add("Authorization", "bearer " + AuthToken);
        using (var resp = _client.Send(msg))
        {
            result = JsonDocument.Parse(resp.Content.ReadAsStream());
        }
    }
    return result;
}
public static void Download(string url, string path, bool overwrite = false)
{
    if (overwrite || !File.Exists(path))
    {
        using (var msg = new HttpRequestMessage(HttpMethod.Get, url))
        {
            using (var resp = _client.Send(msg))
            {
                var dir = Path.GetDirectoryName(path);
                if(!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir!);
                }
                using (var outstm = File.OpenWrite(path))
                {
                    resp.Content.ReadAsStream().CopyTo(outstm);
                }

            }
        }
    }
}
public static object GetObject(string url)
{
    return new TmdbElement(GetJson(url).RootElement);
}

那里没有什么特别复杂的。GetSafeFilename() 函数只是将无效的文件名字符转换为下划线。其余的甚至更容易理解。

现在主要的混乱是我们处理所有逻辑的 ASPX 文件,并调用上面的函数。它们的格式不适合在此处放置源代码,但您可以看看它们。如果您熟悉 ASP.NET,应该不难理解。

历史

  • 2024 年 4 月 10 日 - 初次提交
  • 2024 年 4 月 10 日 - 添加了配置文件支持,修复了错误
© . All rights reserved.