<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>EBook on Producthunt daily</title>
        <link>https://producthunt.programnotes.cn/en/tags/ebook/</link>
        <description>Recent content in EBook on Producthunt daily</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Mon, 30 Jun 2025 15:32:16 +0800</lastBuildDate><atom:link href="https://producthunt.programnotes.cn/en/tags/ebook/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>BookLore</title>
        <link>https://producthunt.programnotes.cn/en/p/booklore/</link>
        <pubDate>Mon, 30 Jun 2025 15:32:16 +0800</pubDate>
        
        <guid>https://producthunt.programnotes.cn/en/p/booklore/</guid>
        <description>&lt;img src="https://images.unsplash.com/photo-1678491451801-4c98a0e50552?ixid=M3w0NjAwMjJ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3NTEyNjg2Mzd8&amp;ixlib=rb-4.1.0" alt="Featured image of post BookLore" /&gt;&lt;h1 id=&#34;adityachandelgitbooklore&#34;&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/adityachandelgit/BookLore&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;adityachandelgit/BookLore&lt;/a&gt;
&lt;/h1&gt;&lt;h1 id=&#34;booklore&#34;&gt;BookLore
&lt;/h1&gt;&lt;p&gt;&lt;img src=&#34;https://img.shields.io/github/v/release/adityachandelgit/BookLore&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;GitHub release (latest by date)&#34;
	
	
&gt;
&lt;img src=&#34;https://img.shields.io/github/license/adityachandelgit/BookLore&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;License&#34;
	
	
&gt;
&lt;img src=&#34;https://img.shields.io/github/issues/adityachandelgit/BookLore&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Issues&#34;
	
	
&gt;
&lt;img src=&#34;https://img.shields.io/github/stars/adityachandelgit/BookLore?style=social&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Stars&#34;
	
	
&gt;
&lt;a class=&#34;link&#34; href=&#34;https://discord.gg/Ee5hd458Uz&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://img.shields.io/badge/Chat-Discord-blue?logo=discord&amp;amp;style=flat&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Join us on Discord&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;BookLore is a self-hosted web app for organizing and managing your personal book collection. It provides an intuitive interface to browse, read, and track your progress across PDFs and eBooks. With robust metadata management, multi-user support, and a sleek, modern UI, BookLore makes it easy to build and explore your personal library.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://producthunt.programnotes.cn/assets/demo.gif&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;BookLore Demo&#34;
	
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;-key-features&#34;&gt;✨ Key Features
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;📚 &lt;strong&gt;Organized Book Management&lt;/strong&gt; - Categorize books with &lt;strong&gt;Libraries&lt;/strong&gt; and &lt;strong&gt;Shelves&lt;/strong&gt; for easy discovery and structured organization.&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Smart Metadata Handling&lt;/strong&gt; - Automatically fetch book details from &lt;strong&gt;Goodreads&lt;/strong&gt;, &lt;strong&gt;Amazon&lt;/strong&gt;, and &lt;strong&gt;Google Books&lt;/strong&gt;, or edit them manually with fine-grained control.&lt;/li&gt;
&lt;li&gt;👥 &lt;strong&gt;Multi-User Support&lt;/strong&gt; - Admins can create accounts, assign libraries, and manage permissions for metadata edits, uploads, and downloads.&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Built-in PDF &amp;amp; ePub Reader&lt;/strong&gt; - A fast, feature-rich reader for PDFs and ePubs, with customizable reading settings and a clean UI.&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;OPDS 1.2 Support&lt;/strong&gt; - Browse and download books through the &lt;strong&gt;Open Publication Distribution System&lt;/strong&gt; – compatible with many reading apps.&lt;/li&gt;
&lt;li&gt;🔐 &lt;strong&gt;Optional OIDC Authentication&lt;/strong&gt; - Secure access with &lt;strong&gt;OpenID Connect&lt;/strong&gt;, supporting both local JWT authentication and external providers like &lt;strong&gt;Authentik&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;📤 &lt;strong&gt;Multi-Book Uploads&lt;/strong&gt; - Upload multiple books at once with metadata auto-detection and file organization.&lt;/li&gt;
&lt;li&gt;📧 &lt;strong&gt;Send Books via Email&lt;/strong&gt; - Share books directly with others by sending them via email – quick and easy.&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Continuous Improvements&lt;/strong&gt; - Frequent updates with new features, performance enhancements, and UI improvements. BookLore is perfect for self-hosters who want complete control over their digital library. Stay tuned for updates!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;-video-guides--tutorials&#34;&gt;🎥 Video Guides &amp;amp; Tutorials
&lt;/h2&gt;&lt;p&gt;For a step-by-step walkthrough, check out the official BookLore video guides on YouTube:&lt;/p&gt;
&lt;p&gt;📺 &lt;a class=&#34;link&#34; href=&#34;https://www.youtube.com/watch?v=UMrn_fIeFRo&amp;amp;list=PLi0fq0zaM7lqY7dX0R66jQtKW64z4_Tdz&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;BookLore Tutorials – YouTube&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These videos cover deployment, configuration, and feature highlights to help you get started quickly.&lt;/p&gt;
&lt;h2 id=&#34;-deploy-with-docker&#34;&gt;🐳 Deploy with Docker
&lt;/h2&gt;&lt;p&gt;You can quickly set up and run BookLore using Docker.&lt;/p&gt;
&lt;h3 id=&#34;1-install-docker--docker-compose&#34;&gt;1️⃣ Install Docker &amp;amp; Docker Compose
&lt;/h3&gt;&lt;p&gt;Ensure you have &lt;a class=&#34;link&#34; href=&#34;https://docs.docker.com/get-docker/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Docker&lt;/a&gt; and &lt;a class=&#34;link&#34; href=&#34;https://docs.docker.com/compose/install/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Docker Compose&lt;/a&gt; installed.&lt;/p&gt;
&lt;h3 id=&#34;2-create-docker-composeyml&#34;&gt;2️⃣ Create docker-compose.yml
&lt;/h3&gt;&lt;p&gt;Create a &lt;code&gt;docker-compose.yml&lt;/code&gt; file with content:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;booklore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;ghcr.io/adityachandelgit/booklore-app:latest&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;container_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;booklore&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;PUID=1000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;PGID=1000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;TZ=Etc/UTC&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;DATABASE_URL=jdbc:mariadb://mariadb:3306/booklore&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Only modify this if you&amp;#39;re familiar with JDBC and your database setup&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;DATABASE_USERNAME=booklore&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Must match MYSQL_USER defined in the mariadb container&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;DATABASE_PASSWORD=your_secure_password&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Use a strong password; must match MYSQL_PASSWORD defined in the mariadb container &lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;SWAGGER_ENABLED=false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Enable or disable Swagger UI (API docs). Set to &amp;#39;true&amp;#39; to allow access; &amp;#39;false&amp;#39; to block access (recommended for production).&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;depends_on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;mariadb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;condition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;service_healthy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;s2&#34;&gt;&amp;#34;6060:6060&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;/your/local/path/to/booklore/data:/app/data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;/your/local/path/to/booklore/books:/books&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;restart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;mariadb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;lscr.io/linuxserver/mariadb:11.4.5&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;container_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;mariadb&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;PUID=1000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;PGID=1000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;TZ=Etc/UTC&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;MYSQL_ROOT_PASSWORD=super_secure_password&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Use a strong password for the database&amp;#39;s root user, should be different from MYSQL_PASSWORD&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;MYSQL_DATABASE=booklore&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;MYSQL_USER=booklore&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Must match DATABASE_USERNAME defined in the booklore container&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;MYSQL_PASSWORD=your_secure_password&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Use a strong password; must match DATABASE_PASSWORD defined in the booklore container&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;/your/local/path/to/mariadb/config:/config&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;restart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;unless-stopped&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;healthcheck&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;CMD&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;mariadb-admin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ping&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;-h&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;interval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;5s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;5s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;retries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Note: You can find the latest BookLore image tag &lt;code&gt;BOOKLORE_IMAGE_TAG&lt;/code&gt; (e.g. v.0.x.x) from the Releases section:
📦 &lt;a class=&#34;link&#34; href=&#34;https://github.com/adityachandelgit/BookLore/releases&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Latest Image Tag – GitHub Releases&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;3-start-the-containers&#34;&gt;3️⃣ Start the Containers
&lt;/h3&gt;&lt;p&gt;Run the following command to start the services:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;docker compose up -d&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;4-access-booklore&#34;&gt;4️⃣ Access BookLore
&lt;/h3&gt;&lt;p&gt;Once the containers are up, access BookLore in your browser at:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;http://localhost:6060&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;-oidcoauth2-authentication-authentik-pocket-id-etc&#34;&gt;🔑 OIDC/OAuth2 Authentication (Authentik, Pocket ID, etc.)
&lt;/h2&gt;&lt;p&gt;BookLore supports optional OIDC/OAuth2 authentication for secure access. This feature allows you to integrate external authentication providers for a seamless login experience.&lt;/p&gt;
&lt;p&gt;While the integration has been tested with &lt;strong&gt;Authentik&lt;/strong&gt; and &lt;strong&gt;Pocket ID&lt;/strong&gt;, it should work with other OIDC providers like &lt;strong&gt;Authelia&lt;/strong&gt; as well. The setup allows you to use either JWT-based local authentication or external providers, giving users the flexibility to choose their preferred method.&lt;/p&gt;
&lt;p&gt;For detailed instructions on setting up OIDC authentication:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;📺 &lt;a class=&#34;link&#34; href=&#34;https://www.youtube.com/watch?v=r6Ufh9ldF9M&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;YouTube video on configuring Authentik with BookLore&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;📘 &lt;a class=&#34;link&#34; href=&#34;docs/OIDC-Setup-With-PocketID.md&#34; &gt;Step-by-step setup guide for Pocket ID&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;-remote-authentication-trusted-header-sso-forward-auth&#34;&gt;🔐 Remote Authentication (Trusted Header SSO, Forward Auth)
&lt;/h2&gt;&lt;p&gt;If you run BookLore behind a reverse proxy with remote authentication (middleware),
you can enable automatic login by setting &lt;code&gt;REMOTE_AUTH_ENABLED&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This allows you to use your existing authentication system (e.g., OAuth, SAML) to log in to BookLore.&lt;/p&gt;
&lt;p&gt;The following remote auth environment variables can be configured:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Variable Name&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
          &lt;th&gt;Default Value&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;REMOTE_AUTH_ENABLED&lt;/td&gt;
          &lt;td&gt;Enable remote authentication&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;REMOTE_AUTH_CREATE_NEW_USERS&lt;/td&gt;
          &lt;td&gt;Auto-create users from remote auth&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;REMOTE_AUTH_HEADER_NAME&lt;/td&gt;
          &lt;td&gt;HTTP header containing user&amp;rsquo;s name&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;Remote-Name&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;REMOTE_AUTH_HEADER_USER&lt;/td&gt;
          &lt;td&gt;HTTP header containing username&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;Remote-User&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;REMOTE_AUTH_HEADER_EMAIL&lt;/td&gt;
          &lt;td&gt;HTTP header containing user&amp;rsquo;s email&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;Remote-Email&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;REMOTE_AUTH_HEADER_GROUPS&lt;/td&gt;
          &lt;td&gt;HTTP header containing user&amp;rsquo;s groups&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;Remote-Groups&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;REMOTE_AUTH_ADMIN_GROUP&lt;/td&gt;
          &lt;td&gt;Group name that grants admin privileges&lt;/td&gt;
          &lt;td&gt;-&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Example implementations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.authelia.com/integration/trusted-header-sso/introduction/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.authelia.com/integration/trusted-header-sso/introduction/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://caddyserver.com/docs/caddyfile/directives/forward_auth&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://caddyserver.com/docs/caddyfile/directives/forward_auth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://doc.traefik.io/traefik/middlewares/http/forwardauth/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://doc.traefik.io/traefik/middlewares/http/forwardauth/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/sevensolutions/traefik-oidc-auth&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/sevensolutions/traefik-oidc-auth&lt;/a&gt; (Traefik OIDC Auth)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;-community--support&#34;&gt;🤝 Community &amp;amp; Support
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;🐞 Found a bug? &lt;a class=&#34;link&#34; href=&#34;https://github.com/adityachandelgit/BookLore/issues&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Open an issue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;✨ Want to contribute? &lt;a class=&#34;link&#34; href=&#34;https://github.com/adityachandelgit/BookLore/blob/master/CONTRIBUTING.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Check out CONTRIBUTING.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;💬 Ask questions or share feedback: &lt;a class=&#34;link&#34; href=&#34;https://github.com/adityachandelgit/BookLore/discussions&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Discussions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Join our Discord&lt;/strong&gt;: &lt;a class=&#34;link&#34; href=&#34;https://discord.gg/Ee5hd458Uz&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Click here to chat with the community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;-contributors--developers&#34;&gt;👨‍💻 Contributors &amp;amp; Developers
&lt;/h2&gt;&lt;p&gt;Thanks to all the amazing people who contribute to Booklore.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/adityachandelgit/BookLore/graphs/contributors&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://contrib.rocks/image?repo=adityachandelgit/BookLore&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Contributors List&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;-star-history&#34;&gt;⭐ Star History
&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://star-history.com/#adityachandelgit/BookLore&amp;amp;Date&amp;amp;theme=dark&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://api.star-history.com/svg?repos=adityachandelgit/BookLore&amp;amp;type=Date&amp;amp;theme=dark&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Star History Chart&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;-support-the-project&#34;&gt;💖 Support the Project
&lt;/h2&gt;&lt;p&gt;If you find BookLore helpful, consider ⭐ starring the repo!&lt;/p&gt;
&lt;p&gt;Or support the project via &lt;a class=&#34;link&#34; href=&#34;https://venmo.com/AdityaChandel&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Venmo&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://venmo.com/AdityaChandel&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://img.shields.io/badge/Venmo-Donate-blue?logo=venmo&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Venmo&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;-tech-stack&#34;&gt;🧰 Tech Stack
&lt;/h2&gt;&lt;p align=&#34;left&#34;&gt;
  &lt;img src=&#34;https://img.shields.io/badge/Spring%20Boot-6DB33F?style=for-the-badge&amp;logo=springboot&amp;logoColor=white&#34; alt=&#34;Spring Boot&#34; style=&#34;margin-right: 10px;&#34;/&gt;
  &lt;img src=&#34;https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&amp;logo=angular&amp;logoColor=white&#34; alt=&#34;Angular&#34; style=&#34;margin-right: 10px;&#34;/&gt;
  &lt;img src=&#34;https://img.shields.io/badge/MariaDB-003545?style=for-the-badge&amp;logo=mariadb&amp;logoColor=white&#34; alt=&#34;MariaDB&#34; style=&#34;margin-right: 10px;&#34;/&gt;
  &lt;img src=&#34;https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&amp;logo=docker&amp;logoColor=white&#34; alt=&#34;Docker&#34; style=&#34;margin-right: 10px;&#34;/&gt;
&lt;/p&gt;
&lt;h2 id=&#34;-license&#34;&gt;⚖️ License
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;http://www.gnu.org/licenses/gpl.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GNU GPL v3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Copyright 2024-2025&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>tchMaterial-parser</title>
        <link>https://producthunt.programnotes.cn/en/p/tchmaterial-parser/</link>
        <pubDate>Sun, 18 May 2025 15:26:34 +0800</pubDate>
        
        <guid>https://producthunt.programnotes.cn/en/p/tchmaterial-parser/</guid>
        <description>&lt;img src="https://images.unsplash.com/photo-1695871136637-5e636f8469af?ixid=M3w0NjAwMjJ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3NDc1NTMxMjl8&amp;ixlib=rb-4.1.0" alt="Featured image of post tchMaterial-parser" /&gt;&lt;h1 id=&#34;happycola233tchmaterial-parser&#34;&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/happycola233/tchMaterial-parser&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;happycola233/tchMaterial-parser&lt;/a&gt;
&lt;/h1&gt;&lt;h1 id=&#34;国家中小学智慧教育平台-电子课本下载工具&#34;&gt;&lt;a class=&#34;link&#34; href=&#34;https://basic.smartedu.cn/tchMaterial/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;国家中小学智慧教育平台&lt;/a&gt; 电子课本下载工具
&lt;/h1&gt;&lt;p&gt;&lt;img src=&#34;https://img.shields.io/badge/Python-3.x-blue.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Python Version&#34;
	
	
&gt;
&lt;img src=&#34;https://img.shields.io/badge/License-MIT-green.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;License&#34;
	
	
&gt;
&lt;img src=&#34;https://img.shields.io/badge/Made_With-%E2%9D%A4-red.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Made With Love❤️&#34;
	
	
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!TIP]
🚀最新版本 v3.0 现已发布，欢迎体验！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本工具可以帮助您从&lt;a class=&#34;link&#34; href=&#34;https://basic.smartedu.cn/tchMaterial/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;国家中小学智慧教育平台&lt;/strong&gt;&lt;/a&gt;获取电子课本的 PDF 文件网址并进行下载，让您更方便地获取课本内容。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[!NOTE]&lt;/p&gt;
&lt;p&gt;自&lt;strong&gt;2025 年 2 月&lt;/strong&gt;起，国家中小学智慧教育平台&lt;strong&gt;需要登录&lt;/strong&gt;才能访问电子课本资源，用户需提供 &lt;strong&gt;Access Token&lt;/strong&gt;（即登录凭据）才可正常使用本工具的下载功能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;👉请先按照&lt;a class=&#34;link&#34; href=&#34;#2-%e8%ae%be%e7%bd%ae-access-token&#34; &gt;下方指南&lt;/a&gt;设置 Access Token，否则程序将无法解析资源！&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;工具特点&#34;&gt;✨工具特点
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;支持 Access Token 登录&lt;/strong&gt;🔑：支持用户手动输入 Access Token，在 Windows 操作系统下会存入注册表，下次启动可自动加载。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持批量下载&lt;/strong&gt;📚：一次输入多个电子课本预览页面网址，即可批量下载 PDF 课本文件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动文件命名&lt;/strong&gt;📂：程序会自动使用教材名称作为文件名，方便管理下载的课本文件。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高 DPI 适配&lt;/strong&gt;🖥️：优化 UI 以适配高分辨率屏幕，避免界面模糊问题。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;下载进度可视化&lt;/strong&gt;📊：实时显示下载进度，支持暂停/恢复操作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨平台支持&lt;/strong&gt;💻：支持 Windows、Linux、macOS 等操作系统（需要图形界面）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;下载与安装方法&#34;&gt;⬇️下载与安装方法
&lt;/h2&gt;&lt;h3 id=&#34;github-releases-页面&#34;&gt;GitHub Releases 页面
&lt;/h3&gt;&lt;p&gt;由于我们的精力有限，本项目的 &lt;a class=&#34;link&#34; href=&#34;https://github.com/happycola233/tchMaterial-parser/releases&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Releases 页面&lt;/a&gt;&lt;strong&gt;仅会发布适用于 Windows 与 Linux 操作系统的 x64 架构&lt;/strong&gt;的程序。&lt;/p&gt;
&lt;p&gt;在下载完成之后，即可运行本程序，不需要额外的安装步骤。&lt;/p&gt;
&lt;h3 id=&#34;arch-用户软件仓库aur&#34;&gt;Arch 用户软件仓库（AUR）
&lt;/h3&gt;&lt;p&gt;对于 &lt;strong&gt;Arch Linux&lt;/strong&gt; 操作系统，本程序已发布至&lt;a class=&#34;link&#34; href=&#34;https://aur.archlinux.org/packages/tchmaterial-parser&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Arch 用户软件仓库&lt;/a&gt;，因此您还可以通过在终端中输入以下命令安装：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;yay -S tchmaterial-parser
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;感谢 &lt;a class=&#34;link&#34; href=&#34;https://github.com/iamzhz&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;@iamzhz&lt;/a&gt; 制作了本工具的发行包（&lt;a class=&#34;link&#34; href=&#34;../../issues/26&#34; &gt;#26&lt;/a&gt;）！&lt;/p&gt;
&lt;h2 id=&#34;使用方法&#34;&gt;🛠️使用方法
&lt;/h2&gt;&lt;h3 id=&#34;1-输入教材链接&#34;&gt;1. 输入教材链接📥
&lt;/h3&gt;&lt;p&gt;将电子课本的&lt;strong&gt;预览页面网址&lt;/strong&gt;粘贴到程序文本框中，支持多个 URL（每行一个）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;示例网址&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;https://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&amp;amp;contentId=XXXXXX&amp;amp;catalogType=tchMaterial&amp;amp;subCatalog=tchMaterial
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;2-设置-access-token&#34;&gt;2. 设置 Access Token🔑
&lt;/h3&gt;&lt;p&gt;若您第一次使用本程序，需点击 “&lt;strong&gt;设置 Token&lt;/strong&gt;” 按钮，粘贴 Access Token 并保存。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;打开浏览器&lt;/strong&gt;，访问&lt;a class=&#34;link&#34; href=&#34;https://auth.smartedu.cn/uias/login&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;国家中小学智慧教育平台&lt;/a&gt;并&lt;strong&gt;登录账号&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;按下 &lt;strong&gt;F12&lt;/strong&gt; 或 &lt;strong&gt;Ctrl+Shift+I&lt;/strong&gt;，或右键——检查（审查元素）打开&lt;strong&gt;开发者工具&lt;/strong&gt;，选择&lt;strong&gt;控制台（Console）&lt;/strong&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在控制台粘贴以下代码后回车（Enter）：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;authKey&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Object&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;keys&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;localStorage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;find&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;startsWith&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ND_UC_AUTH&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;authKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;未找到 Access Token，请确保已登录！&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;tokenData&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;JSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;localStorage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getItem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;authKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;accessToken&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;JSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tokenData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;access_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;%cAccess Token: &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;color: green; font-weight: bold&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;accessToken&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;复制控制台输出的 &lt;strong&gt;Access Token&lt;/strong&gt;，然后在本程序中点击 “&lt;strong&gt;设置 Token&lt;/strong&gt;” 按钮，粘贴并保存 Token。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;[!NOTE]
Access Token 可能会过期，若下载失败提示 &lt;strong&gt;401 Unauthorized&lt;/strong&gt;，请重新获取并设置新的 Token。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;3-开始下载&#34;&gt;3. 开始下载🚀
&lt;/h3&gt;&lt;p&gt;点击 “&lt;strong&gt;下载&lt;/strong&gt;” 按钮，程序将自动解析并下载 PDF 课本。&lt;/p&gt;
&lt;p&gt;本工具支持&lt;strong&gt;批量下载&lt;/strong&gt;，所有 PDF 文件会自动按课本名称命名并保存在选定目录中。&lt;/p&gt;
&lt;h2 id=&#34;常见问题&#34;&gt;❓常见问题
&lt;/h2&gt;&lt;h3 id=&#34;1-为什么下载失败&#34;&gt;1. 为什么下载失败？⚠️
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;检查是否已&lt;a class=&#34;link&#34; href=&#34;#2-%e8%ae%be%e7%bd%ae-access-token&#34; &gt;&lt;strong&gt;正确设置 Access Token&lt;/strong&gt;&lt;/a&gt;🔑，且没有过期。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;确认网络连接是否正常&lt;/strong&gt;🌐，有时网络不稳定可能导致下载失败。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;确保输入的网址有效&lt;/strong&gt;🔗，部分旧资源可能已被移除。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;2-access-token-保存在哪里&#34;&gt;2. Access Token 保存在哪里？💾
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Windows 操作系统&lt;/strong&gt;：Token 会存储在&lt;strong&gt;注册表&lt;/strong&gt; &lt;code&gt;HKEY_CURRENT_USER\Software\tchMaterial-parser&lt;/code&gt; 项中的 &lt;code&gt;AccessToken&lt;/code&gt; 值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linux 操作系统&lt;/strong&gt;: Token 会存储在 &lt;code&gt;~/.config/tchMaterial-parser/data.json&lt;/code&gt; 的文件中。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;macOS 等操作系统&lt;/strong&gt;：Token 仅在运行时临时存储于内存，不会自动保存，程序重启后需重新输入，目前我们正在努力改进该功能。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;3-token-会不会泄露&#34;&gt;3. Token 会不会泄露？🔐
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;本程序&lt;strong&gt;不会上传&lt;/strong&gt; Token，也不会存储在云端，仅用于本地请求授权。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;请勿在公开场合分享 Token&lt;/strong&gt;，以免您的账号被他人使用，造成严重后果。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;star-history&#34;&gt;⭐Star History
&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://star-history.com/#happycola233/tchMaterial-parser&amp;amp;Date&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://api.star-history.com/svg?repos=happycola233/tchMaterial-parser&amp;amp;type=Date&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Star History Chart&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;贡献指南&#34;&gt;🤝贡献指南
&lt;/h2&gt;&lt;p&gt;如果您发现 Bug 或有改进建议，欢迎提交 &lt;strong&gt;Issue&lt;/strong&gt; 或 &lt;strong&gt;Pull Request&lt;/strong&gt;，让我们一起完善本工具！&lt;/p&gt;
&lt;h2 id=&#34;许可证&#34;&gt;📜许可证
&lt;/h2&gt;&lt;p&gt;本项目基于 &lt;a class=&#34;link&#34; href=&#34;LICENSE&#34; &gt;MIT 许可证&lt;/a&gt;，欢迎自由使用和二次开发。&lt;/p&gt;
&lt;h2 id=&#34;友情链接&#34;&gt;💌友情链接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;📚您也可以在 &lt;a class=&#34;link&#34; href=&#34;https://github.com/TapXWorld/ChinaTextbook&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;ChinaTextbook&lt;/a&gt; 项目中下载归档的教材 PDF。&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
