Skip to content

Instantly share code, notes, and snippets.

@KevinJump
Created October 12, 2020 20:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KevinJump/f1d5656994f9c4c1a92ad410b2e52c40 to your computer and use it in GitHub Desktop.
Save KevinJump/f1d5656994f9c4c1a92ad410b2e52c40 to your computer and use it in GitHub Desktop.
Umbraco service to load ebooks as content.
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using VersOne.Epub;
namespace Our.Umbraco.BookContent
{
public class BookService
{
private readonly IContentService contentService;
public BookService(IContentService contentService)
{
this.contentService = contentService;
}
public void AddBook(int rootId, string file)
{
EpubBook book = EpubReader.ReadBook(file);
var bookRoot = CreateBookFolder(rootId, book.Title);
if (bookRoot > 0)
{
/*
foreach(var item in book.Content.Html)
{
CreateBookFiles(bookRoot, item.Key, item.Value);
}
*/
for(int i = 0; i < book.Navigation.Count; i++)
{
EpubNavigationItem next = null;
if (i < book.Navigation.Count - 1)
next = book.Navigation[i + 1];
// CreateChapter(bookRoot, book.Navigation[i].HtmlContentFile, book.Navigation[i].Title, book.Navigation[i].Link, next);
CreateChapter(bookRoot, book.Navigation[i], next);
}
}
}
private int CreateBookFolder(int root, string title)
{
var bookFolder = contentService.Create(title, root, "bookFolder");
if (bookFolder != null)
{
var save = contentService.Save(bookFolder);
if (save.Success)
{
return bookFolder.Id;
}
}
return -1;
}
private void CreateChapter(int root, EpubNavigationItem currentNav, EpubNavigationItem nextNav)
{
var chapter = contentService.Create(currentNav.Title, root, "bookChapter");
contentService.Save(chapter);
if (currentNav.NestedItems.Any())
{
for(int i =0; i < currentNav.NestedItems.Count; i++)
{
EpubNavigationItem next = null;
if (i < currentNav.NestedItems.Count - 1)
next = currentNav.NestedItems[i + 1];
CreateChapter(chapter.Id, currentNav.NestedItems[i], next);
}
}
else
{
CreateChapter(chapter, currentNav.HtmlContentFile, currentNav.Link, nextNav?.Link);
}
}
private void CreateChapter(IContent chapter, EpubTextContentFile content, EpubNavigationItemLink start, EpubNavigationItemLink end)
{
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(content.Content);
var text = new StringBuilder();
var startNode = doc.DocumentNode.SelectNodes($"//*[@id=\"{start.Anchor}\"]").FirstOrDefault();
if (startNode != null)
{
var current = startNode;
while(current != null)
{
text.AppendLine(current.OuterHtml);
current = current.NextSibling;
if (end != null && MatchesAnchor(current, end.Anchor))
{
break;
}
}
chapter.SetValue("bookText", text.ToString());
contentService.Save(chapter);
}
}
private bool MatchesAnchor(HtmlNode node, string id)
{
if (node != null && node.HasAttributes && node.Attributes.Contains("id"))
{
if (node.Attributes["id"].Value == id) return true;
}
return false;
}
}
}
@KevinJump
Copy link
Author

Takes the id of the content node you want to add it to, and the path to a .epub file (download some from https://www.gutenberg.org/)

uses VersOne.Epub package (v.3)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment