from spider import Spider, SpiderItemType, SpiderSource, SpiderItem, SpiderPlayURL, SpiderSubtitle
from utils import get_image_path
from proxy import get_proxy_url
from bs4 import BeautifulSoup
from cache import get_cache, set_cache
from Cryptodome.Cipher import AES
import requests
import xbmcaddon
import xbmcgui
import string
import re
import json
import time
import base64
import hashlib

_ADDON = xbmcaddon.Addon()


class SpiderCZSPP(Spider):

    def name(self):
        return '厂长资源'

    def logo(self):
        return get_image_path('czspp.png')

    def hide(self):
        return not _ADDON.getSettingBool('data_source_czspp_switch')

    def is_searchable(self):
        return True

    def list_items(self, parent_item=None, page=1):
        if parent_item is None:
            items = [
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='dbtop250',
                    name='豆瓣电影Top250',
                    params={
                        'type': 'category',
                        'url': 'https://czzy01.com/dbtop250'
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='huayudianying',
                    name='最新电影',
                    params={
                        'type': 'category',
                        'url': 'https://czzy01.com/zuixindianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='huayudianying',
                    name='华语电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/huayudianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='meiguodianying',
                    name='欧美电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/meiguodianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='ribendianying',
                    name='日本电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/ribendianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='hanguodianying',
                    name='韩国电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/hanguodianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='yindudianying',
                    name='印度电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/yindudianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='yingguodianying',
                    name='英国电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/yingguodianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='faguodianying',
                    name='法国电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/faguodianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='jianadadianying',
                    name='加拿大电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/jianadadianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='eluosidianying',
                    name='俄罗斯电影',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/eluosidianying',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='dianshiju',
                    name='电视剧',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/dianshiju',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='guochanju',
                    name='国产剧',
                    params={
                        'type':
                        'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/guochanju',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='mj',
                    name='美剧',
                    params={
                        'type': 'category',
                        'url': 'https://czzy01.com/movie_bt/movie_bt_series/mj',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='rj',
                    name='日剧',
                    params={
                        'type': 'category',
                        'url': 'https://czzy01.com/movie_bt/movie_bt_series/rj',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='hj',
                    name='韩剧',
                    params={
                        'type': 'category',
                        'url': 'https://czzy01.com/movie_bt/movie_bt_series/hj',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='hwj',
                    name='海外剧（其他）',
                    params={
                        'type': 'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/hwj',
                    },
                ),
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id='dohua',
                    name='动画',
                    params={
                        'type': 'category',
                        'url':
                        'https://czzy01.com/movie_bt/movie_bt_series/dohua',
                    },
                ),
            ]
            return items, False
        elif parent_item['params']['type'] == 'category':
            url = '{}/page/{}'.format(parent_item['params']['url'], page)
            r = self._get_and_pass_captcha(url)
            soup = BeautifulSoup(r.text, 'html.parser')

            items = []
            for e in soup.select('div.mi_ne_kd > ul > li'):
                items.append(
                    SpiderItem(
                        type=SpiderItemType.Directory,
                        id=re.search(
                            r'/(\d+)\.html',
                            e.select('a')[0].get('href'),
                        ).group(1),
                        name=e.select('img')[0].get('alt').strip(),
                        cover=e.select('img')[0].get('data-original'),
                        params={
                            'type': 'video',
                            'url': e.select('a')[0].get('href'),
                        },
                    ))

            total_page = int(
                soup.select('div.pagenavi_txt > a')[-1].get('href').split('/')
                [-1])
            return items, page < total_page
        elif parent_item['params']['type'] == 'video':
            url = parent_item['params']['url']
            r = self._get_and_pass_captcha(url)
            soup = BeautifulSoup(r.text, 'html.parser')

            cover = soup.select('div.dyimg > img')[0].get('src')
            description = soup.select('div.yp_context')[0].text.strip()
            area = ''
            year = 0
            director = ''
            cast = []
            for e in soup.select('ul.moviedteail_list > li'):
                info = e.text.strip()
                if len(info) < 4:
                    continue
                key = info[:2]
                value = info[3:]
                if key == '地区':
                    area = value
                elif key == '年份':
                    try:
                        year = int(value)
                    except:
                        pass
                elif key == '导演':
                    director = value
                elif key == '主演':
                    cast = value.split(' ')

            items = []
            for a in soup.select('div.paly_list_btn > a'):
                items.append(
                    SpiderItem(
                        type=SpiderItemType.File,
                        name=a.text.strip(),
                        cover=cover,
                        description=description,
                        cast=cast,
                        director=director,
                        area=area,
                        year=year,
                        sources=[
                            SpiderSource(
                                'czspp',
                                {
                                    'url': a.get('href'),
                                },
                            )
                        ],
                    ))
            return items, False
        else:
            return [], False

    def resolve_play_url(self, source_params):
        url = source_params['url']
        r = self._get_and_pass_captcha(url)

        m = re.search(
            r'\"([^\"]+)\";var [\d\w]+=function dncry.*md5.enc.Utf8.parse\(\"([\d\w]+)\".*md5.enc.Utf8.parse\(([\d]+)\)',
            r.text,
        )
        if m:
            b64 = m.group(1)
            key = m.group(2).encode()
            iv = m.group(3).encode()

            enc = base64.b64decode(b64)
            cipher = AES.new(key, AES.MODE_CBC, iv)
            padded_data = cipher.decrypt(enc)
            data = padded_data[:-padded_data[-1]].decode()

            play_url = ''
            m = re.search(r'video: *\{url: *\"([^\"]+)\"', data)
            if m:
                play_url = m.group(1)
                if play_url.endswith('.m3u8'):
                    play_url = get_proxy_url(
                        SpiderCZSPP.__name__,
                        self.proxy_m3u8.__name__,
                        {
                            'url': play_url,
                        },
                    )

            subtitles = []
            m = re.search(r'subtitle: *\{url: *\"([^\"]+)\"', data)
            if m:
                subtitles.append(SpiderSubtitle('czspp', m.group(1)))

            return SpiderPlayURL(play_url, subtitles=subtitles)
        else:
            xbmcgui.Dialog().ok('提示', '非厂长自压片源，请自行寻找其他片源观看\n(懒得解密播放地址)')
            return None

    def search(self, keyword):
        r = self._get_and_pass_captcha('https://czzy01.com/',
                                       params={
                                           's': keyword,
                                       })
        soup = BeautifulSoup(r.text, 'html.parser')

        mdict = dict.fromkeys(string.punctuation)
        mdict[' '] = None
        mdict['：'] = None
        table = str.maketrans(mdict)

        items = []
        for e in soup.select('div.mi_ne_kd > ul > li'):
            name = e.select('img')[0].get('alt').strip()
            if keyword.translate(table) not in name.translate(table):
                continue
            items.append(
                SpiderItem(
                    type=SpiderItemType.Directory,
                    id=re.search(
                        r'/(\d+)\.html',
                        e.select('a')[0].get('href'),
                    ).group(1),
                    name=name,
                    cover=e.select('img')[0].get('data-original'),
                    params={
                        'type': 'video',
                        'url': e.select('a')[0].get('href'),
                    },
                ))

        return items

    def proxy_m3u8(self, ctx, params):
        url = params['url']

        cache_key = 'czspp_m3u8'.format(url)
        data = get_cache(cache_key)
        headers = None
        body = None
        if data:
            data = json.loads(data)
            if data['url'] == url and data['expires_at'] >= int(time.time()):
                headers = data['headers']
                body = data['body']

        if body is None or headers is None:
            r = requests.get(url, stream=True, verify=False)

            try:
                headers = {}
                for key in r.headers:
                    if key.lower() in [
                            'connection',
                            'transfer-encoding',
                            'content-type',
                            'content-length',
                            'content-range',
                            'accept-ranges',
                    ]:
                        continue
                    headers[key] = r.headers[key]
                headers['Content-Type'] = 'application/vnd.apple.mpegurl'

                body = ''
                for line in r.iter_lines(8192):
                    line = line.decode()
                    if len(line) > 0 and not line.startswith('#'):
                        if not line.startswith('http'):
                            if line.startswith('/'):
                                line = url[:url.index('/', 8)] + line
                            else:
                                line = url[:url.rindex('/') + 1] + line
                        line = get_proxy_url(
                            SpiderCZSPP.__name__,
                            self.proxy_ts.__name__,
                            {
                                'url': line,
                            },
                        )
                    body += line + '\n'

                set_cache(
                    cache_key,
                    json.dumps({
                        'url': url,
                        'headers': headers,
                        'body': body,
                        'expires_at': int(time.time()) + 60,
                    }))
            except Exception as e:
                print(e)
            finally:
                try:
                    r.close()
                except:
                    pass

        if body is not None and headers is not None:
            ctx.send_response(200)
            for key in headers:
                ctx.send_header(key, headers[key])
            ctx.end_headers()
            ctx.wfile.write(body.encode())

    def proxy_ts(self, ctx, params):
        url = params['url']

        headers = {}
        for key in ctx.headers:
            if key.lower() in [
                    'user-agent',
                    'host',
            ]:
                continue
            headers[key] = ctx.headers[key]
        r = requests.get(url, headers=headers, stream=True, verify=False)
        r.headers['Content-Type'] = 'video/MP2T'

        try:
            ctx.send_response(r.status_code)
            for key in r.headers:
                if key.lower() in [
                        'connection',
                        'transfer-encoding',
                ]:
                    continue
                ctx.send_header(key, r.headers[key])
            ctx.end_headers()

            stripped_image_header = False
            for chunk in r.iter_content(8192):
                if not stripped_image_header:
                    chunk = chunk.lstrip(b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A')
                    stripped_image_header = True
                ctx.wfile.write(chunk)
        except Exception as e:
            print(e)
        finally:
            try:
                r.close()
            except:
                pass

    def _get_and_pass_captcha(self, url, params={}):
        headers = {
            'Origin':
            'https://czzy01.com/',
            'Referer':
            'https://czzy01.com/',
            'User-Agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
            'Cookie': 'esc_search_captcha=1',
        }
        return requests.get(url, params=params, headers=headers)

        session = requests.session()

        cookie_cache_key = 'czspp_cookie'
        data = get_cache(cookie_cache_key)
        if data:
            cookie = json.loads(data)
            for name in cookie:
                value = cookie[name]
                session.cookies.set(name, value)

        r = session.get(url, hparams=params, eaders=headers)
        if '人机识别' not in r.text:
            return r

        nurl = 'https://czzy01.com' + re.search(r'src=\"(.*?)\"',
                                               r.text).group(1)
        nr = session.get(nurl, headers=headers)
        key = re.search(r'var key=\"(.*?)\"', nr.text).group(1)
        avalue = re.search(r'value=\"(.*?)\"', nr.text).group(1)
        c = ''
        for i in range(0, len(avalue)):
            a = avalue[i]
            b = ord(a)
            c = c + str(b)
        value = hashlib.md5(c.encode()).hexdigest()
        session.get(
            'https://czzy01.com/a20be899_96a6_40b2_88ba_32f1f75f1552_yanzheng_ip.php?type=96c4e20a0e951f471d32dae103e83881&key={0}&value={1}'
            .format(key, value),
            headers=headers)
        set_cache(cookie_cache_key, json.dumps(session.cookies.get_dict()))

        return session.get(url, params=params, headers=headers)
