#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Maxwell Zhang
# @Time    : 2018/10/31
import json
import requests
import time
from api import Aweme
from utils.sign import Sign
from config import CONFIG


class Crawl():
    def __init__(self):
        self.device_info = Sign().getDevice()
        self.common_params = {
            "iid": self.device_info['iid'],
            "idfa": self.device_info['idfa'],
            "vid": self.device_info['vid'],
            "device_id": self.device_info['device_id'],
            "openudid": self.device_info['openudid'],
            "device_type": self.device_info['device_type'],
            "os_version": self.device_info['os_version'],
            "os_api": self.device_info['os_api'],
            "screen_width": self.device_info['screen_width'],
            "device_platform": self.device_info['device_platform'],
            "version_code": CONFIG['APPINFO']['version_code'],
            "channel": CONFIG['APPINFO']['channel'],
            "app_name": CONFIG['APPINFO']['app_name'],
            "build_number": CONFIG['APPINFO']['build_number'],
            "app_version": CONFIG['APPINFO']['app_version'],
            "aid": CONFIG['APPINFO']['aid'],
            "ac": "WIFI",
            "pass-region": "1",  # new
            # "js_sdk_version": "1.3.0.1"
        }
        self.token = Sign().getToken()

    # 单个用户详细信息
    def user_detail(self, user_id):
        url, extra_params = Aweme().user(user_id=user_id)
        params = dict(self.common_params, **extra_params)

        # 参数加签（* 要对全部参数加签 *）
        sign = Sign().getSign(self.token, params)
        params["mas"] = sign['mas']
        params["as"] = sign['as']
        params["ts"] = sign['ts']

        resp = requests.get(url, params=params, headers=CONFIG['HEADER']).json()
        print(json.dumps(resp))

        data = resp['user']
        out_data = {
            'user_id': data['uid'],
            'nickname': data['nickname'],
            'signature': data['signature'],
            'sex': data['gender'],
            'address': data['country'] + data['city'] + data['district'],
            'constellation': data['constellation'],
            'avatar': data['avatar_larger']['url_list'],
            'url': data['share_info']['share_url'],
            'follower_count': data['follower_count'],  # 粉丝数
            'total_favorited': data['total_favorited'],  # 获赞数
            'following_count': data['following_count'],  # 关注数
            'aweme_count': data['aweme_count'],  # 作品数
            'dongtai_count': data['dongtai_count'],  # 动态数
        }

        return json.dumps(out_data)

    # 关注的用户
    def user_followings(self, target_user_id, target_count=100):
        out_data = {
            'user_id': target_user_id,
            'followings': []
        }

        def get_out_data(max_time=int(time.time())):
            url, extra_params = Aweme().following(user_id=target_user_id, count=20, max_time=max_time)
            params = dict(self.common_params, **extra_params)

            # 参数加签（* 要对全部参数加签 *）
            sign = Sign().getSign(self.token, params)
            params["mas"] = sign['mas']
            params["as"] = sign['as']
            params["ts"] = sign['ts']

            resp = requests.get(url, params=params, headers=CONFIG['HEADER']).json()
            print(json.dumps(resp))

            data = resp['followings']
            for item in list(data):
                item_data = {
                    'user_id': item['uid'],
                    'nickname': item['nickname']
                }
                if item_data not in out_data['followings']:
                    out_data['followings'].append(item_data)

                print('%s/%s' % (len(out_data['followings']), resp['total']))
                print('=' * 20)

                if resp['has_more'] == False or len(resp['followings']) == 0 or len(
                        out_data['followings']) >= target_count:
                    return

            # 默认30s。如果丢失数据可缩小秒数。如果数据重复可增加秒数。
            next_max_time = resp.get('min_time', int(time.time())) - 30
            get_out_data(next_max_time)

        get_out_data()
        return json.dumps(out_data)

    # 用户的粉丝
    def user_followers(self, target_user_id, target_count=100):
        out_data = {
            'user_id': target_user_id,
            'followers': []
        }

        def get_out_data(max_time=int(time.time())):
            url, extra_params = Aweme().follower(user_id=target_user_id, count=20, max_time=max_time)
            params = dict(self.common_params, **extra_params)

            # 参数加签（* 要对全部参数加签 *）
            sign = Sign().getSign(self.token, params)
            params["mas"] = sign['mas']
            params["as"] = sign['as']
            params["ts"] = sign['ts']

            resp = requests.get(url, params=params, headers=CONFIG['HEADER']).json()
            print(json.dumps(resp))

            print(resp['total'])

            data = resp['followers']
            for item in list(data):
                item_data = {
                    'user_id': item['uid'],
                    'nickname': item['nickname']
                }
                if item_data not in out_data['followers']:
                    out_data['followers'].append(item_data)

                print('%s/%s' % (len(out_data['followers']), resp['total']))
                print('=' * 20)

                if resp['has_more'] == False or len(resp['followers']) == 0 or len(
                        out_data['followers']) >= target_count:
                    return

            # 默认30s。如果丢失数据可缩小秒数。如果数据重复可增加秒数。
            next_max_time = resp.get('min_time', int(time.time())) - 30
            get_out_data(next_max_time)

        get_out_data()
        return json.dumps(out_data)

    # 单个视频详细信息
    def video_detail(self, aweme_id):
        url, extra_params = Aweme().detail(aweme_id=aweme_id)
        params = dict(self.common_params, **extra_params)

        # 参数加签（* 要对全部参数加签 *）
        sign = Sign().getSign(self.token, params)
        params["mas"] = sign['mas']
        params["as"] = sign['as']
        params["ts"] = sign['ts']

        resp = requests.get(url, params=params, headers=CONFIG['HEADER']).json()
        print(json.dumps(resp))

        data = resp['aweme_detail']
        out_data = {
            'user_id': data['author']['uid'],
            'nickname': data['author']['nickname'],
            'video_id': data['aweme_id'],
            'video_url': data['video']['play_addr']['url_list'],
            'audio_url': data['music']['play_url']['url_list'],
            'cover_url': data['video']['cover']['url_list'],
            'description': data['desc'],
            'like_count': data['statistics']['digg_count'],
            'share_count': data['statistics']['share_count'],
            'play_count': data['statistics']['play_count'],  # 已废弃，始终为0
            'comment_count': data['statistics']['comment_count'],
            'district': data['poi_info']['address_info']['district'],
            'address': data['poi_info']['address_info']['simple_addr'],
            'poi': data['poi_info']['poi_name'],
        }

        return json.dumps(out_data)

    # 单个视频的评论信息（默认20条）
    def video_comments(self, aweme_id, count=20, cursor=0):
        url, extra_params = Aweme().comment(aweme_id=aweme_id, count=count, cursor=cursor)
        params = dict(self.common_params, **extra_params)

        # 参数加签（* 要对全部参数加签 *）
        sign = Sign().getSign(self.token, params)
        params["mas"] = sign['mas']
        params["as"] = sign['as']
        params["ts"] = sign['ts']

        resp = requests.get(url, params=params, headers=CONFIG['HEADER']).json()
        print(json.dumps(resp))

        print len(resp['comments'])

        data = resp['comments']
        out_data = {
            'video_id': aweme_id,
            'comments': [
                {
                    'video_id': item['aweme_id'],
                    'user_id': item['user']['uid'],
                    'nick': item['user']['nickname'],
                    'comment': item['text']
                } for item in data]
        }

        return json.dumps(out_data)

    # 指定音乐原声的视频列表
    def music_post(self, music_id, target_count=100):
        out_data = {
            'music_id': music_id,
            'video_list': []
        }

        def get_out_data(cursor=0):
            url, extra_params = Aweme().music_aweme(music_id=music_id, count=18, cursor=cursor)
            params = dict(self.common_params, **extra_params)

            # 参数加签（* 要对全部参数加签 *）
            sign = Sign().getSign(self.token, params)
            params["mas"] = sign['mas']
            params["as"] = sign['as']
            params["ts"] = sign['ts']

            resp = requests.get(url, params=params, headers=CONFIG['HEADER']).json()
            print(json.dumps(resp))

            data = resp['aweme_list']
            for item in list(data):
                item_data = {
                    'user_id': item['author']['uid'],
                    'nickname': item['author']['nickname'],
                    'video_id': item['aweme_id'],
                    'video_url': ','.join(item['video']['play_addr']['url_list'])
                }
                if item_data not in out_data['video_list']:
                    out_data['video_list'].append(item_data)

                print('%s/%s' % (len(out_data['video_list']), target_count))
                print('=' * 20)

                if resp['has_more'] == False or len(resp['aweme_list']) == 0 or len(
                        out_data['video_list']) >= target_count:
                    return

            # 默认递增18
            cursor = resp.get('cursor', 0) + 18
            get_out_data(cursor)

        get_out_data()
        return json.dumps(out_data)

    # 视频榜（固定20）
    def hot_video(self):
        url, extra_params = Aweme.hot_video()
        params = dict(self.common_params, **extra_params)

        # 参数加签（* 要对全部参数加签 *）
        sign = Sign().getSign(self.token, params)
        params["mas"] = sign['mas']
        params["as"] = sign['as']
        params["ts"] = sign['ts']

        resp = requests.get(url, params=params, headers=CONFIG['HEADER']).json()
        print(json.dumps(resp))

        out_data = {
            'active_time': resp['active_time'],
            'video_list': []
        }

        data = resp['aweme_list']
        for item in list(data):
            item_data = {
                'user_id': item['aweme_info']['author']['uid'],
                'nickname': item['aweme_info']['author']['nickname'],
                'video_id': item['aweme_info']['aweme_id'],
                'video_url': item['aweme_info']['video']['play_addr']['url_list']
            }
            if item_data not in out_data['video_list']:
                out_data['video_list'].append(item_data)

        return json.dumps(out_data)

    # 推荐用户列表
    def recommand(self, user_id, count=30):
        url, extra_params = Aweme().recommend(target_user_id=user_id, count=count, cursor=0)
        params = dict(self.common_params, **extra_params)

        # 参数加签（* 要对全部参数加签 *）
        sign = Sign().getSign(self.token, params)
        params["mas"] = sign['mas']
        params["as"] = sign['as']
        params["ts"] = sign['ts']

        cookie = {"sessionid": "8cb**************************99d"}  # 这行cookie你不改肯定要报错呀╮(╯▽╰)╭
        resp = requests.get(url, params=params, headers=CONFIG['HEADER'], cookies=cookie).json()
        print(json.dumps(resp))

        print(len(resp['user_list']))

        data = resp['user_list']
        out_data = {
            'user_id': user_id,
            'comments': [
                {
                    'user_id': item['uid'],
                    'nickname': item['nickname'],
                    'fan_count': item['follower_count'],
                    'works_count': item['aweme_count'],
                    'recommend_reason': item['recommend_reason']
                } for item in data]
        }

        return json.dumps(out_data)


# 通用函数，返回api原始信息（用于debug）
def raw():
    device_info = Sign().getDevice()

    common_params = {
        "iid": device_info['iid'],
        "idfa": device_info['idfa'],
        "vid": device_info['vid'],
        "device_id": device_info['device_id'],
        "openudid": device_info['openudid'],
        "device_type": device_info['device_type'],
        "os_version": device_info['os_version'],
        "os_api": device_info['os_api'],
        "screen_width": device_info['screen_width'],
        "device_platform": device_info['device_platform'],
        "version_code": CONFIG['APPINFO']['version_code'],
        "channel": CONFIG['APPINFO']['channel'],
        "app_name": CONFIG['APPINFO']['app_name'],
        "build_number": CONFIG['APPINFO']['build_number'],
        "app_version": CONFIG['APPINFO']['app_version'],
        "aid": CONFIG['APPINFO']['aid'],
        "ac": "WIFI",
        "pass-region": "1",  # new
        # "js_sdk_version": "1.3.0.1"
    }

    # url, extra_params = Aweme().user(user_id='84990209480')
    # url, extra_params = Aweme().following(user_id='84990209480', count=20, max_time=int(time.time()))
    # url, extra_params = Aweme().follower(user_id='84990209480', count=20, max_time=int(time.time()))
    # url, extra_params = Aweme().post(user_id='84990209480', count=20, max_cursor=0)
    # url, extra_params = Aweme().detail(
    #     aweme_id='6612758165299661576')  # 6612758165299661576
    # url, extra_params = Aweme().comment(aweme_id='6617997564333526286', count=20, cursor=0)
    # url, extra_params = Aweme().music_detail(music_id='6612758165299661576')
    # url, extra_params = Aweme().music_aweme(music_id='6612758165299661576', count=18, cursor=0)
    # url, extra_params = Aweme().hot_search()
    url, extra_params = Aweme().hot_video()
    # url, extra_params = Aweme().hot_music()
    # url, extra_params = Aweme().recommend(target_user_id='84990209480', count=30, cursor=0)

    params = dict(common_params, **extra_params)

    # 参数加签（* 要对全部参数加签 *）
    token = Sign().getToken()
    sign = Sign().getSign(token, params)
    params["mas"] = sign['mas']
    params["as"] = sign['as']
    params["ts"] = sign['ts']

    # cookie = {"sessionid": "8cb**************************99d"}
    cookie = {}
    resp = requests.get(url, params=params, headers=CONFIG['HEADER'], cookies=cookie).json()
    print(json.dumps(resp))


if __name__ == '__main__':
    print(Crawl().user_detail('84990209480'))
    # print(Crawl().user_followings('84990209480', 100))
    # print(Crawl().user_followers('84990209480', 100))
    # print(Crawl().video_detail('6618502111090969863'))
    # print(Crawl().video_comments('6618502111090969863'))
    # print(Crawl().music_post('6612758165299661576', 100))
    # print(Crawl().hot_video())
    # print(Crawl().recommand('84990209480'))
    # raw()
