lib.itmens/catalog/book/utils.py

85 lines
2.1 KiB
Python
Raw Normal View History

2022-12-16 07:58:34 -05:00
import re
2023-08-11 01:43:19 -04:00
from ..common.models import IdType
2022-12-16 07:58:34 -05:00
def check_digit_10(isbn):
assert len(isbn) == 9
sum = 0
for i in range(len(isbn)):
c = int(isbn[i])
w = i + 1
sum += w * c
r = sum % 11
2022-12-29 23:57:02 -05:00
return "X" if r == 10 else str(r)
def check_digit_13(isbn):
assert len(isbn) == 12
sum = 0
for i in range(len(isbn)):
c = int(isbn[i])
w = 3 if i % 2 else 1
sum += w * c
r = 10 - (sum % 10)
2022-12-29 23:57:02 -05:00
return "0" if r == 10 else str(r)
def isbn_10_to_13(isbn):
if not isbn or len(isbn) != 10:
return None
2022-12-29 23:57:02 -05:00
return "978" + isbn[:-1] + check_digit_13("978" + isbn[:-1])
def isbn_13_to_10(isbn):
2022-12-29 23:57:02 -05:00
if not isbn or len(isbn) != 13 or isbn[:3] != "978":
return None
else:
return isbn[3:12] + check_digit_10(isbn[3:12])
def is_isbn_13(isbn):
2023-01-05 03:06:13 -05:00
return re.match(r"^\d{13}$", isbn) is not None
def is_isbn_10(isbn):
2023-01-05 03:06:13 -05:00
return re.match(r"^\d{9}[X0-9]$", isbn) is not None
def is_asin(asin):
2023-01-05 03:06:13 -05:00
return re.match(r"^B[A-Z0-9]{9}$", asin) is not None
2022-12-16 07:58:34 -05:00
2024-05-26 22:57:49 -04:00
def detect_isbn_asin(s: str) -> tuple[IdType, str] | tuple[None, None]:
if not s:
return None, None
2022-12-29 23:57:02 -05:00
n = re.sub(r"[^0-9A-Z]", "", s.upper())
2022-12-16 07:58:34 -05:00
if is_isbn_13(n):
return IdType.ISBN, n
if is_isbn_10(n):
2024-05-26 22:57:49 -04:00
v = isbn_10_to_13(n)
return (IdType.ISBN, v) if v else (None, None)
2022-12-16 07:58:34 -05:00
if is_asin(n):
return IdType.ASIN, n
return None, None
2024-07-28 16:08:36 -04:00
def binding_to_format(binding: str | None):
from .models import Edition
if not binding:
return None
if re.search(r"(Audio|Audible|音频)", binding, flags=re.IGNORECASE):
return Edition.BookFormat.AUDIOBOOK
if re.search(
r"(pub|ebook|e-book|kindle|electronic|电子)", binding, flags=re.IGNORECASE
):
return Edition.BookFormat.HARDCOVER
if re.search(r"(web|网)", binding, flags=re.IGNORECASE):
return Edition.BookFormat.WEB
if re.search(r"(精|Hard)", binding, flags=re.IGNORECASE):
return Edition.BookFormat.HARDCOVER
if re.search(r"(平|Paper|Soft)", binding, flags=re.IGNORECASE):
return Edition.BookFormat.PAPERBACK
return None