Skip to content
Snippets Groups Projects
isbn_detect.go 1.73 KiB
Newer Older
package liber

import (
	"io"
	"io/ioutil"
	"regexp"
	"strconv"
	"strings"

	"github.com/meskio/epubgo"
)

var isbnRx = regexp.MustCompile(`(?:ISBN(?:-10|-13)?\s*:?\s*)?((?:(?:[\d]-?){9}|(?:[\d]-?){12})[\dxX])(?:[^-\d]|$)`)

func findISBNInEpub(epub *epubgo.Epub) []string {
	var isbn []string

	spine, err := epub.Spine()
	if err != nil {
		return nil
	}

	for spine.Next() == nil {
		r, err := spine.Open()
		if err != nil {
			continue
		}
		if found := findISBNInPage(r); len(found) > 0 {
			isbn = append(isbn, found...)
		}
		r.Close()
	}

	return isbn
}

func findISBNInPage(r io.Reader) []string {
	data, err := ioutil.ReadAll(r)
	if err != nil {
		return nil
	}
	var result []string
	for _, m := range isbnRx.FindAllSubmatch(data, -1) {
		if len(m) > 1 {
			isbn := string(m[1])
			if validateIsbn(isbn) {
				result = append(result, isbn)
			}
		}
	}
	return result
}

func validateIsbn10(isbn string) bool {
	var sum int
	var multiply int = 10
	for i, v := range isbn {
		if v == '-' {
			continue
		}
		digitString := string(v)

		if i == 9 && digitString == "X" {
			digitString = "10"
		}

		digit, err := strconv.Atoi(digitString)
		if err != nil {
			return false
		}
		sum = sum + (multiply * digit)
		multiply--
	}

	return sum%11 == 0
}

func validateIsbn13(isbn string) bool {
	var sum int
	for i, v := range isbn {
		var multiply int
		if i%2 == 0 {
			multiply = 1
		} else {
			multiply = 3
		}

		digit, err := strconv.Atoi(string(v))
		if err != nil {
			return false
		}
		sum = sum + (multiply * digit)
	}

	return sum%10 == 0
}

func validateIsbn(isbn string) bool {
	isbn = strings.Replace(isbn, "-", "", -1)
	switch len(isbn) {
	case 10:
		return validateIsbn10(isbn)
	case 13:
		return validateIsbn13(isbn)
	default:
		return false
	}
}