
import requests
import json
import re
import os
from PIL import Image

# 域名经常变，注意改
HOST_BOOK = 'http://t349822340044009472.1e10dm.cn'
HOST_IMAGE = 'http://ossmh.jj1699.cn'
BASE_IMAGE_URL = f'{HOST_IMAGE}/images'
CHANNEL_ID = '349822340044009472'

# 主要是用这两个header访问，不加访问不了
HEADERS = {'channelid': CHANNEL_ID}
HEADERS_1 = {'channelid': CHANNEL_ID, 'Referer': HOST_BOOK}

CURRENT_DIR = os.path.dirname(__file__)


class Book(object):
	def __init__(self, book_id):
		self.__book_id = book_id
		self.__book_info = dict()
		self.__chapter_list = list()
		self.__book_real_name = ''
		self.__image_url_example = ''
		self.__url_chapter_type = 0
		self.__url_filename_type = 0
		self.__url_chapter_type_special = 0
		self.__url_filename_type_special = 0

	def _json_to_dict_from_url(self, url, headers):
		jsonstr = requests.get(url, headers=headers).content.decode('utf-8')
		return json.loads(jsonstr)

	def _get_cartoon_info(self):
		url = f'{HOST_BOOK}/api/cartoon_info?id={self.__book_id}'
		res = self._json_to_dict_from_url(url, HEADERS)
		if res['code'] == 200 or res['code'] == '200':
			self.__book_info = res['data']

	def _get_chapter_info(self):
		page = 1
		while True:
			url = f'{HOST_BOOK}/api/catalogue?id={self.__book_id}&page={page}'
			dic = self._json_to_dict_from_url(url, HEADERS)
			self.__chapter_list += dic['data']['data']
			page += 1
			if len(self.__chapter_list) >= dic['data']['total_num']:
				break

	# 有些漫画的 名字 和实际的下载路径中的名字不一样
	def _get_book_real_name(self):
		chapter_id = self.__chapter_list[0]['id']
		url = f'{HOST_BOOK}/api/read?book_id={self.__book_id}&chapter_id={chapter_id}'
		dic = self._json_to_dict_from_url(url, HEADERS_1)
		# http://ossmh.jj1699.cn/images/肉色囚笼/1_第1话我要上你（上）/1.jpg
		self.__image_url_example = dic['data']['now']['content'][0]
		self.__book_real_name = re.findall(r'.*/images/(.*?)/', self.__image_url_example)[0]

	# 初始化图片url 中 chapter部分的规则
	# 是根据第一张图片来初始化的，但是不准，某些情况下 一本漫画的中的 有些章节的路径有变化
	def _check_url_chapter_type(self):
		chaptername = self.__chapter_list[0]['chaptername']
		chapterorder = self.__chapter_list[0]['chapterorder']
		url_chapter = re.findall(r'.*/images/.*?/(.*?)/.*', self.__image_url_example)[0]
		if url_chapter == chaptername:
			self.__url_chapter_type = 1
		elif url_chapter == chaptername.replace(' ',''):
			self.__url_chapter_type = 2
		elif url_chapter == self.__book_real_name + '_subs':
			self.__url_chapter_type = 3
		elif url_chapter == f'{chapterorder}_{chaptername}':
			self.__url_chapter_type = 4
		elif url_chapter == f'{chapterorder}_{chaptername}'.replace(' ',''):
			self.__url_chapter_type = 5
		else:
			self.__url_chapter_type = -1

	# 同理，初始化url中文件名的规则
	def _check_url_filename_type(self):
		re_file_name_1 = r'.*/(book_\d*?_chapter_\d*?_\d*?\.jpg)'
		re_file_name_2 = r'.*/(\d*?\.jpg)'
		file_name_1 = re.findall(re_file_name_1, self.__image_url_example)
		file_name_2 = re.findall(re_file_name_2, self.__image_url_example)
		if not file_name_1 == []:
			self.__url_filename_type = 1
		elif not file_name_2 == []:
			self.__url_filename_type = 2
		else:
			self.__url_filename_type = -1


	def _get_chaptername(self, chaptername_in, chapterorder):
		chaptername, filename = '',''
		if self.__url_chapter_type == 1:
			chaptername = chaptername_in
		elif self.__url_chapter_type == 2:
			chaptername = chaptername_in.replace(' ','')
		elif self.__url_chapter_type == 3:
			chaptername = self.__book_real_name + '_subs'
		elif self.__url_chapter_type == 4:
			chaptername = f'{chapterorder}_{chaptername_in}'
		elif self.__url_chapter_type == 5:
			chaptername = f'{chapterorder}_{chaptername_in}'.replace(' ','')

		# 特殊情况的处理
		if self.__url_chapter_type_special == 1:
			chaptername = self.__book_real_name + '_subs'

		return chaptername

	def _get_filename(self, chapterorder, item):
		if self.__url_filename_type == 1:
			filename = f'book_{self.__book_id}_chapter_{chapterorder}_{item}'
		elif self.__url_filename_type == 2:
			filename = f'{item}'

		# 特殊情况的处理
		if self.__url_filename_type_special == 1:
			filename += '.1'

		return filename

	def _init(self):
		self._get_cartoon_info()
		self._get_chapter_info()
		self._get_book_real_name()
		self._check_url_chapter_type()
		self._check_url_filename_type()

	def _save(self, chaptername_in, file, filename):
		book_name = self.__book_info['title']
		# if not book_name == self.__book_real_name:
		# 	book_name = f'{book_name}（{self.__book_real_name}）'
		book_path = f'{CURRENT_DIR}/downloads/{book_name}'
		chapter_path = f'{book_path}/{chaptername_in}'
		file_path = f'{chapter_path}/{filename}.jpg'
		if not os.path.exists(book_path):
			os.mkdir(book_path)
		if not os.path.exists(chapter_path):
			os.mkdir(chapter_path)
		with open(file_path, 'wb') as fp:
			fp.write(file)

	def _download_chapter(self, chaptername_in, chapterorder):
		item = 1
		retry_time = 0
		success_count = 0
		while True:
			chaptername = self._get_chaptername(chaptername_in, chapterorder)
			filename = self._get_filename(chapterorder, item)
			url = f'{BASE_IMAGE_URL}/{self.__book_real_name}/{chaptername}/{filename}.jpg'
			res = requests.get(url)
			print(url)
			if res.status_code == 404:
				# 此处 比较重要，没有想到其他更好的办法
				# 例如book_id为1的这本漫画，根据第一张图片的规则定好后，实际后面的章节并不是这样的
				# 因此做了自动纠正的功能
				# 两个部分：章节 和 文件名
				# 先处理章节处的url，如果不行再处理文件名。
				# 具体处理在 _get_chaptername() 中
				# 暂时没有遇到其他情况。
				if self.__url_chapter_type_special == 0:
					self.__url_chapter_type_special = 1
					continue
				elif self.__url_filename_type_special == 0:
					self.__url_filename_type_special = 1
					self.__url_chapter_type_special = 0
					continue
				self.__url_filename_type_special = 0
				self.__url_chapter_type_special = 0
				break

			success_count += 1
			self.__url_filename_type_special = 0
			self.__url_chapter_type_special = 0
			self._save(chaptername_in, res.content, filename)
			item += 1

		print(f'下载完成：{chaptername_in}')

	def _download_book(self):
		for chapter in self.__chapter_list:
			chaptername,chapterorder = chapter['chaptername'].strip(),chapter['chapterorder']
			self._download_chapter(chaptername, chapterorder)

		print('全部下载完成')

	def download(self):
		self._init()
		self._download_book()
		image_merge(self.__book_info['title'])

def image_merge(book_name):
	print('正在合成长图, 请稍等....')
	book_path = f'{CURRENT_DIR}/downloads/{book_name}'
	chapter_list = os.listdir(book_path)
	os.mkdir(f'{book_path}/{book_name}')
	for chapter in chapter_list:
		chapter_path = f'{book_path}/{chapter}'
		img_list = []
		img_length_all = 0
		for file in os.listdir(chapter_path):
			try:
				file_name = f'{chapter_path}/{file}'
				img = Image.open(file_name)
				img_list.append(img)
				img_length_all += img.size[1]
			except Exception as e:
				continue

		result = Image.new(img_list[0].mode, (640, img_length_all))
		tmp_height = 0
		for im in img_list:
			result.paste(im, (0, tmp_height))
			tmp_height += im.size[1]

		# 缩放图片，pillow限制，像素不能超过65535
		while result.size[1] >= 65535:
			width = int(result.size[0] * 0.9)
			height = int(result.size[1] * 0.9)
			result = result.resize((width, height), Image.ANTIALIAS)

		# 保存图片
		result.save(f'{book_path}/{book_name}/{chapter}.jpg')

if __name__ == '__main__':
	while True:
		print('')
		print('')
		print('【某某漫画下载】')
		print('')
		print('一般情况下自动合成长图到对应文件下，某些情况合成失败，可选择手动合成，输入名字即可。')
		print('一般情况下都可下载，少数情况，下载可能失败。')
		print('程序简陋，没有ui，有兴趣的小伙伴可以做个ui。')
		print('')
		print('')
		print('1. 下载')
		print('2. 手动合成长图')
		s = input('请选择：')
		if s == '1':
			book_id = input('请输入book_id:')
			if book_id == '':
				os.system('cls')
				continue
			print('开始下载：')
			b = Book(book_id)
			b.download()
			print('下载完成，输入任意值返回')
			os.system('pause')
			os.system('cls')
		elif s == '2':
			name = input('请输入漫画名称（就是下载完后的文件夹名称）:')
			if name == '':
				os.system('cls')
				continue
			image_merge(name)
			print('合成完毕....按任意键返回')
			os.system('pause')
			os.system('cls')
