# -*- coding: utf-8 -*-


import os
import re
import sqlite3
import sys
import json
import time
import pickle
import requests
from datetime import datetime
import logging
import random
import websocket
from urllib.parse import unquote
import gzip
from protobuf.douyin import *
import execjs
import hashlib
import urllib.parse
from threading import Thread
import urllib3
import webview   # 用于创建桌面应用的 Web 视图



urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

session = requests.session()

Settings_Options = {}


def update_global_settings(new_settings_dict):
    """
    Updates the global Settings_Options dictionary.
    This function is intended to be called from main.py.
    """
    global Settings_Options
    Settings_Options = json.loads(new_settings_dict)
    # print(type(Settings_Options))


ID_TO_CONFIG_KEY = {
    112: "douyin_dm",
    122: "douyin_dm",  # 112 和 122 都映射到同一个英文键 "douyin_dm"
    2: "wechat_moments",
    1: "wechat",
    5: "qq",
    4: "qq_zone",
    3: "weibo",
    -1: "link_image"
    # 如果有其他ID，也在这里添加映射
}

# 中文描述映射表：英文键 -> 中文名称（用于输出）
# 这个主要用于生成最终的用户友好信息
CONFIG_KEY_TO_CHINESE = {
    "all": "全部",  # "all" 选项的中文描述
    "douyin_dm": "抖音私信",
    "wechat_moments": "微信朋友圈",
    "wechat": "微信",
    "qq": "QQ",
    "qq_zone": "QQ空间",
    "weibo": "微博",
    "link_image": "链接图片"
    # 确保所有可能出现在 ID_TO_CONFIG_KEY 的值都在这里有中文映射
}


# 拉黑
def lahei(sec_user_id, user_id, Cookie):
    # 拉黑对方，需要sec_user_id和user_id
    # sec_user_id：MS4wLjABAAAAhZ85ZW5BVlcjvTvpTlA6rcGIr_nhpzCSS42uSENLEqE，主页后面
    # user_id：to_uid
    for __ in range(10):
        try:
            url = "https://www-hj.douyin.com/aweme/v1/web/user/block/?device_platform=webapp&aid=6383&channel=channel_pc_web&pc_client_type=1&pc_libra_divert=Windows&update_version_code=170400&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=2560&screen_height=1440&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=131.0.0.0&browser_online=true&engine_name=Blink&engine_version=131.0.0.0"

            # payload = "block_type=1&sec_user_id=MS4wLjABAAAAhZ85ZW5BVlcjvTvpTlA6rcGIr_nhpzCSS42uSENLEqE&source=0&user_id=61163251429"
            payload = f"block_type=1&sec_user_id={sec_user_id}&source=0&user_id={user_id}"
            headers = {
                'Connection': 'keep-alive',
                'Content-Length': '110',
                'Pragma': 'no-cache',
                'Cache-Control': 'no-cache',
                'sec-ch-ua-platform': '"Windows"',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
                'Accept': 'application/json, text/plain, */*',
                'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'sec-ch-ua-mobile': '?0',
                'Origin': 'https://www.douyin.com',
                'Sec-Fetch-Site': 'same-site',
                'Sec-Fetch-Mode': 'cors',
                'Sec-Fetch-Dest': 'empty',
                'Referer': 'https://www.douyin.com/',
                'Accept-Encoding': 'gzip, deflate',
                'Accept-Language': 'zh-CN,zh;q=0.9',
                'Cookie': Cookie
                # 'Cookie': 'ttwid=1%7CU9RBkam_C1udCzD15RdVkhD45xIsm7PIoQlTltJYCTk%7C1732686970%7Cdc4ddd594048baeaa3df7dcdc967e36006df40e0cc901d457382909db2394dc0; UIFID_TEMP=c4a29131752d59acb78af076c3dbdd52744118e38e80b4b96439ef1e20799db082f1380d5cd13efd2ef3c0bf18206e4bfbe0e3610d3ab52bee57c5fcfdc2e02c97ca6e46bdd3de6f984ea807009371b5db9506690172d0a9a5cc4ef43373f876cd4bd5a4eac0347fff8889821f134cf0; hevc_supported=true; strategyABtestKey=%221732686972.739%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.5%7D; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; passport_csrf_token=52363725d47dd1229c220f0470e2f2d7; passport_csrf_token_default=52363725d47dd1229c220f0470e2f2d7; bd_ticket_guard_client_web_domain=2; d_ticket=935e0100ebe543aeb19fb88474608a1615f45; passport_assist_user=CkF9ZXWVA-iZbKerIKHDaEp1xcJZ5lh4uYUgNu1ymCM1HYElnwC0ln3nqAxRA8ByxW37RMx2pswZ8MEQWnOx-MGStBpKCjyc330xG_wrxyc791bEObH0B7n-lL2ZJD6OxxfDqLpVB69azowaOsHM72XIrf2i8PVqW5FEu4LZMQRDvogQhsriDRiJr9ZUIAEiAQMmaH5v; n_mh=07vLiXVhkr6Gw426Bs6p1qWtmm_l_Xu5Jlf1_2HXC3I; sso_uid_tt=f65780cd0e55de027bf9299f9b7dec53; sso_uid_tt_ss=f65780cd0e55de027bf9299f9b7dec53; toutiao_sso_user=331fa717c329a4f4f115118fe1f6f684; toutiao_sso_user_ss=331fa717c329a4f4f115118fe1f6f684; sid_ucp_sso_v1=1.0.0-KDY0MjVkYmNhNjBmMDUwYTRjYjQ2MDY1ZGQyNDZmZTMwMGNiZjg3NWYKIQir86C94o2KBBCZ6Zq6BhjvMSAMMM31iY8GOAZA9AdIBhoCbGYiIDMzMWZhNzE3YzMyOWE0ZjRmMTE1MTE4ZmUxZjZmNjg0; ssid_ucp_sso_v1=1.0.0-KDY0MjVkYmNhNjBmMDUwYTRjYjQ2MDY1ZGQyNDZmZTMwMGNiZjg3NWYKIQir86C94o2KBBCZ6Zq6BhjvMSAMMM31iY8GOAZA9AdIBhoCbGYiIDMzMWZhNzE3YzMyOWE0ZjRmMTE1MTE4ZmUxZjZmNjg0; login_time=1732687003098; passport_auth_status=0d63f05f5920f5fa86371e2c328c60e7%2C; passport_auth_status_ss=0d63f05f5920f5fa86371e2c328c60e7%2C; uid_tt=fe90a08ede420f1008382babb4a01af2; uid_tt_ss=fe90a08ede420f1008382babb4a01af2; sid_tt=27847273045ab5d1055ce9cc29a4cf90; sessionid=27847273045ab5d1055ce9cc29a4cf90; sessionid_ss=27847273045ab5d1055ce9cc29a4cf90; is_staff_user=false; publish_badge_show_info=%220%2C0%2C0%2C1732687004013%22; SelfTabRedDotControl=%5B%5D; _bd_ticket_crypt_doamin=2; _bd_ticket_crypt_cookie=388b6415a7b774ecbb771fd4e6bb8f78; __security_server_data_status=1; sid_guard=27847273045ab5d1055ce9cc29a4cf90%7C1732687005%7C5183999%7CSun%2C+26-Jan-2025+05%3A56%3A44+GMT; sid_ucp_v1=1.0.0-KDk2M2NmYmU2NjkxZTQxYTUwOGM4NzgxMmNhZmQ0YjUxZWYwODBlZmMKGwir86C94o2KBBCd6Zq6BhjvMSAMOAZA9AdIBBoCaGwiIDI3ODQ3MjczMDQ1YWI1ZDEwNTVjZTljYzI5YTRjZjkw; ssid_ucp_v1=1.0.0-KDk2M2NmYmU2NjkxZTQxYTUwOGM4NzgxMmNhZmQ0YjUxZWYwODBlZmMKGwir86C94o2KBBCd6Zq6BhjvMSAMOAZA9AdIBBoCaGwiIDI3ODQ3MjczMDQ1YWI1ZDEwNTVjZTljYzI5YTRjZjkw; store-region=cn-fj; store-region-src=uid; biz_trace_id=41025dff; is_dash_user=1; SEARCH_RESULT_LIST_TYPE=%22single%22; pwa2=%220%7C0%7C3%7C0%22; my_rd=2; live_use_vvc=%22false%22; h265ErrorNum=-1; webcast_local_quality=origin; stream_player_status_params=%22%7B%5C%22is_auto_play%5C%22%3A0%2C%5C%22is_full_screen%5C%22%3A0%2C%5C%22is_full_webscreen%5C%22%3A0%2C%5C%22is_mute%5C%22%3A0%2C%5C%22is_speed%5C%22%3A1%2C%5C%22is_visible%5C%22%3A0%7D%22; __live_version__=%221.1.2.5721%22; live_can_add_dy_2_desktop=%221%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A2560%2C%5C%22screen_height%5C%22%3A1440%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A28%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A0%7D%22; FOLLOW_LIVE_POINT_INFO=%22MS4wLjABAAAAcfYfvFRPvoxRdGJHhNk26Vx0J0Nf9RmuUggT6CeeVxivnBYc1nRoJTwq_N2a6dJs%2F1732723200000%2F0%2F0%2F1732697858379%22; FOLLOW_NUMBER_YELLOW_POINT_INFO=%22MS4wLjABAAAAcfYfvFRPvoxRdGJHhNk26Vx0J0Nf9RmuUggT6CeeVxivnBYc1nRoJTwq_N2a6dJs%2F1732723200000%2F0%2F1732697258380%2F0%22; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtcmVlLXB1YmxpYy1rZXkiOiJCTmRrNUtCTjlJMWk4TW15V1RVMzdxcC9aSEI4WWU2My81M0VDdFF6Nk9pWk4wRVl0K2V4M1UydFZ1bmZ4dFM0V0NxYnVTd1U0NE9HeTdHdFpPajR4STA9IiwiYmQtdGlja2V0LWd1YXJkLXdlYi12ZXJzaW9uIjoyfQ%3D%3D; home_can_add_dy_2_desktop=%221%22; WallpaperGuide=%7B%22showTime%22%3A0%2C%22closeTime%22%3A0%2C%22showCount%22%3A0%2C%22cursor1%22%3A29%2C%22cursor2%22%3A8%7D; odin_tt=1b03c18d171dadef1f2d74f0110f49f52593545553a4eef411d09c01a0fdc369f1aa8355e2dd9f85ce81034ff8c843c8; IsDouyinActive=true'
            }

            response = requests.request("POST", url, headers=headers, data=payload, timeout=3, verify=False)
            # '{"status_code":0,"block_status":1,"extra":{"now":1732697940000,"fatal_item_ids":[],"logid":"20241127165900C4E8A38FAAFFE50C3E07"},"log_pb":{"impr_id":"20241127165900C4E8A38FAAFFE50C3E07"}}'
            if '"status_code":0' in response.text:
                return True
            else:
                # print(response.text)
                return False
        except Exception as e:
            print('lahei', e)

    return False


# 解除拉黑
def jclahei(sec_user_id, Cookie, user_id='7454438944119719433'):
    '''

    :param sec_user_id:
    :param user_id:抖音的user_unique_id值，
    :param Cookie:
    :return:
    '''
    for __ in range(10):
        try:
            url = "https://www.douyin.com/aweme/v1/web/user/block/?device_platform=webapp&aid=6383&channel=channel_pc_web&pc_client_type=1&pc_libra_divert=Windows&update_version_code=170400&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=2560&screen_height=1440&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=131.0.0.0&browser_online=true&engine_name=Blink&engine_version=131.0.0.0&os_name=Windows&os_version=10&cpu_core_num=28&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=0"

            payload = f"block_type=0&sec_user_id={sec_user_id}&source=0&user_id={user_id}"
            headers = {
                'Connection': 'keep-alive',
                'Pragma': 'no-cache',
                'Cache-Control': 'no-cache',
                'sec-ch-ua-platform': '"Windows"',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
                'Accept': 'application/json, text/plain, */*',
                'x-secsdk-csrf-token': 'fHFd=f24ms8IC7K0tv7Zr5yGw69vgstUyiXltzg3pxxtfaQOTRCbXlMU08taG5frPAnrKFo3FN6gXANTYVyn47qi=KY6IgaSiTYosAF939T',
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'Referer': f'https://www.douyin.com/user/{sec_user_id}',
                'Accept-Encoding': 'gzip, deflate',
                'Accept-Language': 'zh-CN,zh;q=0.9',
                # 'Cookie': 'ttwid=1%7CKWXadMDhW9Ryw_ADwbeFK_FV9H-mbn3vFxyte2YAZL8%7C1735621839%7C2023a3817009a569d35894b430f6575ba57c352aa1c8d409409e8419fe2eeac2; UIFID_TEMP=c4a29131752d59acb78af076c3dbdd52744118e38e80b4b96439ef1e20799db02e8e7a5a86363a89fcec77e2d646615eca416b0564627981e02f280480cc7a0b5215a3f91585358e92dd2f7c4807c5002acaaeb100519902234feddc5b68b02bdfe0e29a074b2bf5645cc1afe4195533; s_v_web_id=verify_m5c0fj24_two4VH2Q_uopw_4bO1_9hhn_C0Tcq87kZcJx; hevc_supported=true; dy_swidth=2560; dy_sheight=1440; my_rd=2; fpk1=U2FsdGVkX19XIyl6qGLvr1yaDzNIntOXA6m8G57S4sifGptdOC7CTzX9RIcI5U2LTTFFHXrkPzUGHbjQ7CfRqw==; fpk2=f51bb482c660d0eeadd1f058058a2b35; bd_ticket_guard_client_web_domain=2; passport_csrf_token=8521596f974a978da1e4b354eb1d35c1; passport_csrf_token_default=8521596f974a978da1e4b354eb1d35c1; UIFID=c4a29131752d59acb78af076c3dbdd52744118e38e80b4b96439ef1e20799db02e8e7a5a86363a89fcec77e2d646615eca416b0564627981e02f280480cc7a0bed8fe6dddf462035cabdbffe88852cd4b880a1ac63ce66c05dd898d871d0d9a56122b3387b3aa1bca9b18d5e63727b923ccb09fb874d403178c3c7e258b20a2d2fd65f7e5e111c28ea1fa9ccfbeca9d86001470e9b5c68ef98f37b8469b938d87d0877f83a459825f9347573727217b7b20b2bedc1b0bbef9547713cd654f778; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%2C%22isForcePopClose%22%3A1%7D; is_dash_user=1; __ac_nonce=06775f84a00347ad53f19; __ac_signature=_02B4Z6wo00f01zRL7KAAAIDDA28o.PttSTc0a-gAAKpx60; csrf_session_id=6432c96e165f150b78c22e8447711030; passport_assist_user=Cjzgvg6j8zBZnJqRpkCuCFVCSD6GgohNh0pytKoNp5NXG8lLVmaH3x7_XmHVcBTSbN2B6zNCOQI6-gL6geAaSgo85CasOHZYo_u95TNfT5dF1YykMfnegAC-GyhVlQFvWalAh_Fm3XQuAdpHKHIKdDy5ZQZ441_9kQQZZWeXEPrc5Q0Yia_WVCABIgED7P5X0Q%3D%3D; n_mh=9-mIeuD4wZnlYrrOvfzG3MuT6aQmCUtmr8FxV8Kl8xY; sso_uid_tt=183c57659c43eeceaed318796ff7f102; sso_uid_tt_ss=183c57659c43eeceaed318796ff7f102; toutiao_sso_user=ca675dcc5f006efc313dc69f7e3e0ccb; toutiao_sso_user_ss=ca675dcc5f006efc313dc69f7e3e0ccb; sid_ucp_sso_v1=1.0.0-KGY3MDY2NWZlZjFlNTk2NDRjOTc4ZTc2YzdhOGIxNmY4YjFlYjEzMDYKHQicjOfinAIQ3vDXuwYY7zEgDDC7psTQBTgGQPQHGgJscSIgY2E2NzVkY2M1ZjAwNmVmYzMxM2RjNjlmN2UzZTBjY2I; ssid_ucp_sso_v1=1.0.0-KGY3MDY2NWZlZjFlNTk2NDRjOTc4ZTc2YzdhOGIxNmY4YjFlYjEzMDYKHQicjOfinAIQ3vDXuwYY7zEgDDC7psTQBTgGQPQHGgJscSIgY2E2NzVkY2M1ZjAwNmVmYzMxM2RjNjlmN2UzZTBjY2I; login_time=1735784542133; passport_auth_status=577638629195a1c78981dcc18eb6914d%2C; passport_auth_status_ss=577638629195a1c78981dcc18eb6914d%2C; uid_tt=be33504736d799b7e42458a52241a944; uid_tt_ss=be33504736d799b7e42458a52241a944; sid_tt=3a7970ea751f676dce010b635f8d19b1; sessionid=3a7970ea751f676dce010b635f8d19b1; sessionid_ss=3a7970ea751f676dce010b635f8d19b1; is_staff_user=false; _bd_ticket_crypt_doamin=2; _bd_ticket_crypt_cookie=c2194fa0fb2ed4598e93bbead8b2ec09; __security_server_data_status=1; publish_badge_show_info=%220%2C0%2C0%2C1735784550346%22; passport_fe_beating_status=true; sid_guard=3a7970ea751f676dce010b635f8d19b1%7C1735784552%7C5183993%7CMon%2C+03-Mar-2025+02%3A22%3A25+GMT; sid_ucp_v1=1.0.0-KGUyNWE1YzdkYjc1Zjg3ODMzZDQ4NTFjYjU4ODhlN2Y1MjI2ODkxZWEKGQicjOfinAIQ6PDXuwYY7zEgDDgGQPQHSAQaAmxxIiAzYTc5NzBlYTc1MWY2NzZkY2UwMTBiNjM1ZjhkMTliMQ; ssid_ucp_v1=1.0.0-KGUyNWE1YzdkYjc1Zjg3ODMzZDQ4NTFjYjU4ODhlN2Y1MjI2ODkxZWEKGQicjOfinAIQ6PDXuwYY7zEgDDgGQPQHSAQaAmxxIiAzYTc5NzBlYTc1MWY2NzZkY2UwMTBiNjM1ZjhkMTliMQ; FOLLOW_NUMBER_YELLOW_POINT_INFO=%22MS4wLjABAAAAHZbJJ5e8g4Lk0PIezttIs-bJdhhLb79nOZeFZVjop6o%2F1735833600000%2F1735784585664%2F1735784545513%2F0%22; SelfTabRedDotControl=%5B%5D; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.5%7D; strategyABtestKey=%221735784593.663%22; biz_trace_id=18f02cfb; store-region=cn-fj; store-region-src=uid; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A2560%2C%5C%22screen_height%5C%22%3A1440%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A28%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A0%7D%22; download_guide=%223%2F20250102%2F0%22; IsDouyinActive=true; home_can_add_dy_2_desktop=%221%22; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtcmVlLXB1YmxpYy1rZXkiOiJCSnhRZURwVm5RV2RCWHYyUDdsQkZBQ2grK3hnZW5DZElkS3pML0lqUy9aTXByVWo2ajJUQ1lxUzlxM2pqcThUbWVHR2lET3dpQkMwWnRkbDdKblB2Vnc9IiwiYmQtdGlja2V0LWd1YXJkLXdlYi12ZXJzaW9uIjoyfQ%3D%3D; odin_tt=6428f310d4802afd53a00105de9cc307b50976cb366ec2c003f57d3ad6a461b8a0bee9972f745cb565544ae3f7faab23c3376ad4c22dedbd04e5517c14b449bb'
            }

            response = requests.request("POST", url, headers=headers, data=payload, timeout=3, verify=False,
                                        cookies=Cookie)

            if response.status_code == 200:
                if '"status_code":0' in response.text:
                    return True
                else:
                    # print(response.text)
                    return response.text
            else:
                return response.status_code

        except Exception as e:
            print('jclahei', e)

    return False


# 读取cookie
def load_cookies_from_file(filename):
    # 以二进制写入模式打开文件

    with open(filename, "rb") as f:
        return pickle.load(f)


# 取随机ua
def zhengchang_ua(i):
    # return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42'
    if i == 0:
        first_num = random.randint(55, 62)
        third_num = random.randint(0, 3200)
        fourth_num = random.randint(0, 140)
        os_type = [
            "(Linux; Android 10; MI 9 Build/QKQ1.190825.002; wv)",
            "(Linux; Android 8.1.0; PBCM30 Build/OPM1.171019.011; wv)",
            "(Linux; Android 6.0; HUAWEI MLA-AL10 Build/HUAWEIMLA-AL10; wv)",
            "(Linux; Android 6.0.1; OPPO A57t Build/MMB29M; wv)",
            "(iPhone; CPU iPhone OS 10_3_3 like Mac OS X)",
            "(Linux; U; Android 9; zh-cn; Redmi 7 Build/PKQ1.181021.001)",
            "(Linux; Android 9; V1914A Build/PKQ1.181016.001; wv)",
            "(Linux; U; Android 10; zh-CN; ALP-AL00 Build/HUAWEIALP-AL00)",
            "(Linux; Android 10; VOG-TL00 Build/HUAWEIVOG-TL00; wv)",
            "(Linux; Android 9; Nokia X7 Build/PPR1.180610.011; wv)",
            "(Linux; Android 9.0; S5 Build/PKQ1.190319.001; wv)",
            "(Linux; Android 10; PCT-AL10 Build/HUAWEIPCT-AL10; wv)",
            "(Linux; Android 10; PCT-AL10 Build/HUAWEIPCT-AL10; wv)",
            "(Linux; Android 9; Mi9 Pro 5G Build/PKQ1.190714.001; wv)",
            "(iPhone; CPU iPhone OS 13_4 like Mac OS X)",
            "(Linux; Android 10; OXF-AN00 Build/HUAWEIOXF-AN00; wv)",
            "(Linux; U; Android 9; zh-cn; V1814A Build/PKQ1.180819.001)",
            "(Linux; U; Android 7.0; zh-cn; Redmi Note 4X Build/NRD90M)",
            "(Linux; Android 9; RMX1991 Build/PKQ1.190630.001; wv)",
            "(Linux; Android 10; JNY-AL10 Build/HUAWEIJNY-AL10; wv)",
            "(Linux; Android 10; ELE-AL00 Build/HUAWEIELE-AL00; wv)",
            "(Linux; Android 9; RMX1991 Build/PKQ1.190630.001; wv)",
            "(Linux; U; Android 10; zh-cn; MI 8 Build/QKQ1.190828.002)",
            "(Linux; Android 10; VCE-AL00 Build/HUAWEIVCE-AL00; wv)",
            "(Linux; Android 8.0.0; AUM-TL20 Build/HONORAUM-TL20; wv)",
            "(Linux; Android 10; ALP-AL00 Build/HUAWEIALP-AL00; wv)",
            "(Linux; U; Android 10; zh-cn; MI 8 SE Build/QKQ1.190828.002)",
            "(Linux; Android 7.1.1; OPPO A83 Build/N6F26Q; wv)",
            "(Linux; Android 10; VOG-AL10 Build/HUAWEIVOG-AL10; wv)",
            "(iPhone; CPU iPhone OS 13_3_1 like Mac OS X)",
            "(Linux; U; Android 10; zh-cn; MI 9 Build/QKQ1.190825.002)",
            "(Linux; Android 9; INE-TL00 Build/HUAWEIINE-TL00; wv)",
            "(Linux; Android 9; ONEPLUS A6000 Build/PKQ1.180716.001; wv)",
            "(Linux; U; Android 9; zh-cn; Mi9 Pro 5G Build/PKQ1.190714.001)",
            "(Linux; Android 8.1.0; OPPO R11 Plus Build/OPM1.171019.011; wv)",
            "(Linux; Android 8.1.0; COR-AL00 Build/HUAWEICOR-AL00; wv)",
            "(Linux; Android 7.1.2; M15 Build/N2G47H; wv)",
            "(Linux; arm_64; Android 7.0; LG-H870DS)",
            "(Linux; U; Android 9; zh-cn; MI CC9 Pro Build/PKQ1.190302.001)",
            "(Linux; Android 10; SM-G9730 Build/QP1A.190711.020; wv)",
            "(Linux; Android 7.1.2; Hisense A2T Build/N2G47H; wv)",
            "(Linux; U; Android 8.1.0; zh-CN; 16th Plus Build/OPM1.171019.026)",
            "(Linux; U; Android 9; zh-cn; MI 8 Lite Build/PKQ1.181007.001)",
            "(Linux; Android 9; PAAM00 Build/PKQ1.190414.001; wv)",
            "(iPhone; CPU iPhone OS 10_1_1 like Mac OS X)",
            "(iPhone; CPU iPhone OS 11_4_1 like Mac OS X)",
            "(Linux; Android 9; V1914A Build/PKQ1.181016.001; wv)",
            "(Linux; Android 10; PCT-AL10 Build/HUAWEIPCT-AL10; wv)",
        ]
        chrome_version = "Chrome/{}.0.{}.{}".format(first_num, third_num, fourth_num)

        ua = " ".join(
            [
                "Mozilla/5.0",
                random.choice(os_type),
                "AppleWebKit/537.36",
                "(KHTML, like Gecko)",
                chrome_version,
                "Safari/537.36",
            ]
        )
        return ua
    elif i == 1:
        os_type = [
            "(Windows NT 6.1; WOW64)",
            "(Windows NT 6.0; WOW64)",
            "(Windows NT 6.2; WOW64)",
            "(Windows NT 6.3; WOW64)",
            "(Windows NT 5.1; WOW64)",
            "(Windows NT 5.0; WOW64)",
            "(Windows NT 5.2; WOW64)",
            "(Windows NT 5.3; WOW64)",
            "(Windows NT 10.1; WOW64)",
            "(Windows NT 10.0; WOW64)",
            "(Windows NT 10.2; WOW64)",
            "(Windows NT 10.3; WOW64)",
            "(Windows NT 6.1; WOW64; X64)",
            "(Windows NT 6.0; WOW64; X64)",
            "(Windows NT 6.2; WOW64; X64)",
            "(Windows NT 6.3; WOW64; X64)",
            "(Windows NT 5.1; WOW64; X64)",
            "(Windows NT 5.0; WOW64; X64)",
            "(Windows NT 5.2; WOW64; X64)",
            "(Windows NT 5.3; WOW64; X64)",
            "(Windows NT 10.1; WOW64; X64)",
            "(Windows NT 10.0; WOW64; X64)",
            "(Windows NT 10.2; WOW64; X64)",
            "(Windows NT 10.3; WOW64; X64)",
            "(Windows NT 6.1)",
            "(Windows NT 6.0)",
            "(Windows NT 6.2)",
            "(Windows NT 6.3)",
            "(Windows NT 5.1)",
            "(Windows NT 5.0)",
            "(Windows NT 5.2)",
            "(Windows NT 5.3)",
            "(Windows NT 10.1)",
            "(Windows NT 10.0)",
            "(Windows NT 10.2)",
            "(Windows NT 10.3)",
        ]
        banben = (
                str(random.randint(47, 170))
                + ".0."
                + str(random.randint(2000, 2755))
                + "."
                + str(random.randint(0, 25))
        )

        ua = " ".join(
            [
                "Mozilla/5.0",
                random.choice(os_type),
                "AppleWebKit/537.36",
                "(KHTML, like Gecko)",
                "Chrome/" + banben,
                "Safari/537.36",
            ]
        )
        return ua
    elif i == 2:
        os_type = [
            "(Macintosh; U; PPC Mac OS X 10_5_8; ja-jp)",
            "(Windows; U; Windows NT 6.1; cs-CZ)",
            "(Windows; U; Windows NT 6.0; tr-TR)",
            "(Windows; U; Windows NT 5.1; ru-RU)",
            "(Windows; U; Windows NT 6.0; tr-TR)",
            "(Macintosh; Intel Mac OS X 10_6_8)",
            "(Windows; U; Windows NT 6.1; zh-HK)",
            "(Windows; U; Windows NT 6.0; ja-JP)",
            "(Windows; U; Windows NT 6.0; hu-HU)",
            "(Macintosh; U; Intel Mac OS X 10_6_6; de-de)",
            "(Windows; U; Windows NT 6.1; ko-KR)",
            "(Macintosh; Intel Mac OS X 10_7_3)",
            "(Macintosh; U; PPC Mac OS X 10_5_8; ja-jp)",
            "(Windows; U; Windows NT 6.1; sv-SE)",
            "(Macintosh; U; Intel Mac OS X 10_6_6; fr-ch)",
            "(Windows; U; Windows NT 6.1; de-DE)",
            "(Windows; U; Windows NT 6.0; de-DE)",
            "(Macintosh; U; Intel Mac OS X 10_5_8; zh-cn)",
            "(Macintosh; U; Intel Mac OS X 10_6_6; ja-jp)",
            "(Windows; U; Windows NT 6.0; en-US)",
        ]
        banben = (
                str(random.randint(533, 534))
                + "."
                + str(random.randint(18, 21))
                + "."
                + str(random.randint(1, 27))
        )
        chrome_version = [
            "Version/5.0.3",
            "Version/5.0.4",
            "Version/5.0.2",
            "Version/7.0.3",
            "Version/6.0 Mobile/10A5355d",
            "Version/5.1.7",
            "Version/5.1.6",
            "Version/5.1.3",
            "Version/5.1.4",
            "Version/5.1.2",
            "Version/5.1.3",
        ]

        ua = " ".join(
            [
                "Mozilla/5.0",
                random.choice(os_type),
                "AppleWebKit/" + banben,
                "(KHTML, like Gecko)",
                random.choice(chrome_version),
                "Safari/" + banben,
            ]
        )
        return ua
    elif i == 3:
        os_type = [
            "(Windows NT 10.0; Win64; x64; rv:",
            "(Windows NT 6.3; Win64; x64; rv:",
            "(Windows NT 6.2; Win64; x64; rv:",
            "(Windows NT 10; rv:",
            "(Windows NT 6.3; rv:",
            "(Windows NT 6.2; rv:",
            "(Windows NT 6.1; rv:",
            "(Windows NT 6.1; Win64; x64; rv:",
            "(X11; Linux i586; rv:",
            "(Windows NT 10.0; Win64; x64; rv:",
        ]
        banben = str(random.randint(20, 50)) + ".0"
        chrome_version = [
            "Gecko/20100101 Firefox/",
            "Gecko/20130405 Firefox/",
            "Gecko/20130330 Firefox/",
            "Gecko/20130430 Firefox/",
            "Gecko/20140230 Firefox/",
            "Gecko/20140630 Firefox/",
            "Gecko/20140512 Firefox/",
            "Gecko/20140712 Firefox/",
            "Gecko/20100502 Firefox/",
        ]

        ua = " ".join(
            [
                "Mozilla/5.0",
                random.choice(os_type) + banben + ")",
                random.choice(chrome_version) + banben,
            ]
        )
        return ua
    elif i == 4:
        os_type = [
            "(Macintosh; U; Intel Mac OS X 10_6_7; ",
            "(Macintosh; U; Intel Mac OS X 10_6_5; ",
            "(Windows; U; Windows NT 6.1; ",
            "(Macintosh; U; Intel Mac OS X 10_6_6; ",
            "(Windows; U; Windows NT 6.0; ",
            "(Windows; U; Windows NT 6.1; ",
            "(Windows; U; Windows NT 5.1; ",
            "(Macintosh; U; Intel Mac OS X 10_6_6; ",
            "(Macintosh; U; PPC Mac OS X 10_5_8;",
            "(Macintosh; U; Intel Mac OS X 10_6_7;",
            "(Macintosh; U; Intel Mac OS X 10_6_5;",
            "(Macintosh; U; Intel Mac OS X 10_6_6;",
        ]
        diqu = [
            "ja-jp)",
            "de-de)",
            "de-DE)",
            "fr-ch)",
            "en-US)",
            "cs-CZ)",
            "it-it)",
            "ko-kr)",
            "da-dk)",
            "ar)",
            "hu-HU)",
            "ko-KR)",
            "es-es)",
            "zh-HK)",
            "en-gb)",
        ]
        banben = (
                str(random.randint(532, 535))
                + "."
                + str(random.randint(19, 55))
                + "."
                + str(random.randint(1, 25))
        )

        ua = " ".join(
            [
                "Mozilla/5.0",
                random.choice(os_type) + random.choice(diqu),
                "AppleWebKit/" + banben,
                "(KHTML, like Gecko)",
                "Version/5.0." + str(random.randint(1, 5)),
                "Safari/" + banben,
            ]
        )
        return ua
    elif i == 5:
        os_type = [
            "(Windows; U; Windows NT 5.1",
            "(Macintosh; U; Intel Mac OS X 10_6_6",
            "(Macintosh; U; PPC Mac OS X 10_5_8",
            "(Macintosh; U; Intel Mac OS X 10_6_7",
            "(Macintosh; U; Intel Mac OS X 10_6_5",
            "(Macintosh; U; Intel Mac OS X 10_6_6",
            "(Macintosh; AMD Mac OS X 10_8_2",
            "(Macintosh; Intel Mac OS X 10_10_1",
            "(Macintosh; Intel Mac OS X 10_5_8",
            "(Macintosh; Intel Mac OS X 10_6_0",
            "(Macintosh; Intel Mac OS X 10_6_2",
            "(Macintosh; Intel Mac OS X 10_6_3",
            "(Macintosh; Intel Mac OS X 10_6_4",
            "(Macintosh; Intel Mac OS X 10_6_5",
            "(Macintosh; Intel Mac OS X 10_6_6",
            "(Macintosh; Intel Mac OS X 10_6_7",
            "(Macintosh; Intel Mac OS X 10_6_8",
            "(Macintosh; Intel Mac OS X 10_7_0",
            "(Macintosh; Intel Mac OS X 10_7_1",
            "(Macintosh; Intel Mac OS X 10_7_2",
            "(Macintosh; Intel Mac OS X 10_7_3",
            "(Macintosh; Intel Mac OS X 10_7_4",
            "(Macintosh; Intel Mac OS X 10_7_5",
            "(Macintosh; Intel Mac OS X 10_8_0",
            "(Macintosh; Intel Mac OS X 10_8_1",
            "(Macintosh; Intel Mac OS X 10_8_2",
            "(Macintosh; Intel Mac OS X 10_8_3",
            "(Macintosh; Intel Mac OS X 10_9_0",
            "(Macintosh; Intel Mac OS X 10_9_1",
            "(Macintosh; Intel Mac OS X 10_9_2",
            "(Macintosh; Intel Mac OS X 10_9_3",
            "(Macintosh; PPC Mac OS X 10_6_7",
            "(Macintosh; U; Intel Mac OS X 10_5_6",
            "(Macintosh; U; Intel Mac OS X 10_5_7",
            "(Macintosh; U; Intel Mac OS X 10_5_8",
            "(Macintosh; U; Intel Mac OS X 10_5_9",
            "(Macintosh; U; Intel Mac OS X 10_6_0",
            "(Macintosh; U; Intel Mac OS X 10_6_1",
            "(Macintosh; U; Intel Mac OS X 10_6_2",
            "(Macintosh; U; Intel Mac OS X 10_6_3",
            "(Macintosh; U; Intel Mac OS X 10_6_4",
            "(Macintosh; U; Intel Mac OS X 10_6_5",
            "(Macintosh; U; Intel Mac OS X 10_6_6",
            "(Macintosh; U; Intel Mac OS X 10_6_7",
            "(Macintosh; U; Intel Mac OS X 10_6_8",
            "(Macintosh; U; Intel Mac OS X 10_8",
        ]
        diqu = [
            "; ja-jp)",
            "; e-de)",
            "; de-DE)",
            "; fr-ch)",
            "; en-US)",
            "; cs-CZ)",
            "; it-it)",
            "; ko-kr)",
            "; da-dk)",
            "; ar)",
            "; hu-HU)",
            "; ko-KR)",
            "; es-es)",
            "; zh-HK)",
            "; en-gb)",
            "; id-ID)",
        ]
        banben = (
                str(random.randint(500, 535))
                + "."
                + str(random.randint(0, 55))
                + "."
                + str(random.randint(0, 25))
        )

        ua = " ".join(
            [
                "Mozilla/5.0",
                random.choice(os_type) + random.choice(diqu),
                "AppleWebKit/" + banben,
                "(KHTML, like Gecko)",
                "Version/5.0." + str(random.randint(1, 9)),
                "Safari/" + banben,
            ]
        )
        return ua
    else:
        os_type = [
            "(iPhone; U; CPU iPhone OS 4_3_1 like Mac OS X",
            "(iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X",
            "(iPhone; U; CPU iPhone OS 4_3 like Mac OS X",
            "(iPhone; U; CPU iPhone OS 4_2_4 like Mac OS X",
            "(iPhone; CPU iPhone OS 12_1_4 like Mac OS X",
            "(iPhone; CPU iPhone OS 12_0 like Mac OS X",
            "(iPhone; CPU iPhone OS 11_2 like Mac OS X",
            "(iPhone 6s; CPU iPhone OS 11_4_1 like Mac OS X",
            "(iPhone; CPU iPhone OS 10_1 like Mac OS X",
            "(iPhone; CPU iPhone OS 11_0_2 like Mac OS X",
            "(iPhone; CPU iPhone OS 11_4_1 like Mac OS X",
            "(iPhone; CPU iPhone OS 10_1_1 like Mac OS X",
            "(iPhone; CPU iPhone OS 13_5_1 like Mac OS X",
            "(iPhone; CPU iPhone OS 8_3 like Mac OS X",
            "(iPhone; CPU iPhone OS 14_4 like Mac OS X",
            "(iPhone; CPU iPhone OS 13_6 like Mac OS X",
            "(iPhone; CPU iPhone OS 14_1 like Mac OS X",
            "(iPhone; CPU iPhone OS 13_6_1 like Mac OS X",
        ]
        diqu = [
            "; ja-jp)",
            "; e-de)",
            "; de-DE)",
            "; fr-ch)",
            "; en-US)",
            "; cs-CZ)",
            "; it-it)",
            "; ko-kr)",
            "; da-dk)",
            "; ar)",
            "; hu-HU)",
            "; ko-KR)",
            "; es-es)",
            "; zh-HK)",
            "; en-gb)",
            "; id-ID)",
        ]
        banben = (
                str(random.randint(500, 535))
                + "."
                + str(random.randint(0, 55))
                + "."
                + str(random.randint(0, 25))
        )

        mobi = [
            "Version/6.0 Mobile/10A5355d",
            "Version/5.1 Mobile/9B176",
            "Version/5.0.2 Mobile/8J2",
            "Version/5.0.2 Mobile/8G4",
            "Version/5.0.2 Mobile/8C148",
            "Version/5.0.2 Mobile/8C148a",
            "Version/5.0.2 Mobile/8G4",
            "Version/5.0.2 Mobile/8F190",
            "Version/4.0.5 Mobile/8B5097d",
            "Version/4.0.5 Mobile/8B117",
            "Version/4.0.4 Mobile/7B314",
            "Version/4.0.4 Mobile/7B334b",
            "Version/4.0.4 Mobile/7D11",
            "Version/4.0.4 Mobile/7B500",
            "Version/4.0.4 Mobile/7B360",
            "Version/3.1.1 Mobile/5G77",
        ]

        ua = " ".join(
            [
                "Mozilla/5.0",
                random.choice(os_type) + random.choice(diqu),
                "AppleWebKit/" + banben,
                "(KHTML, like Gecko)",
                random.choice(mobi),
                "Safari/" + banben,
            ]
        )
        return ua


# wss链接加密 获取 signature
def generateSignature(wss):
    """
    出现gbk编码问题则修改 python模块subprocess.py的源码中Popen类的__init__函数参数encoding值为 "utf-8"
    """
    params = (
        "live_id,aid,version_code,webcast_sdk_version,"
        "room_id,sub_room_id,sub_channel_id,did_rule,"
        "user_unique_id,device_platform,device_type,ac,"
        "identity"
    ).split(",")
    wss_params = urllib.parse.urlparse(wss).query.split("&")
    wss_maps = {i.split("=")[0]: i.split("=")[-1] for i in wss_params}
    tpl_params = [f"{i}={wss_maps.get(i, '')}" for i in params]
    param = ",".join(tpl_params)
    md5 = hashlib.md5()
    md5.update(param.encode())
    md5_param = md5.hexdigest()

    # with codecs.open('D:\job_demo\demo\day04\h_sign.js', 'r', encoding='utf8') as f:
    #     script = f.read()

    # ctx = MiniRacer()
    # ctx.eval(script)

    is_pack = getattr(sys, 'frozen', False)
    if is_pack:
        run_path = sys._MEIPASS
    else:
        run_path = os.getcwd()
    js_file_path = os.path.join(run_path, 'h_sign.js')

    with open(js_file_path, "r", encoding="utf-8") as f:
        js_code = f.read()
    ctx = execjs.compile(js_code)

    try:
        signature = ctx.call("get_sign", md5_param)
        return signature
    except Exception as e:
        print(e)


# 检索关键词拉黑
def char_in_list(string, char_list):
    """
    判断字符串中的某个字符是否在列表元素中

    :param char: 要检查的字符
    :param char_list: 字符列表
    :return: 如果字符在列表中则返回True，否则返回False
    """
    for char in char_list.split('\n'):
        if char == '':
            continue
        if char in string:
            if char:
                return char
            else:
                return True
    return False


# 查看用户主页信息
def View_user_home(uid, Cookies):
    # 访问主页，获取用户信息，只有登录才能获取地区
    for __ in range(10):
        try:

            # session = requests.Session()
            # session.mount('https://www.douyin.com', DESAdapter())
            url = "https://www.douyin.com/user/" + uid
            headers = {
                'Connection': 'keep-alive',
                'Pragma': 'no-cache',
                'Cache-Control': 'no-cache',
                'User-Agent': zhengchang_ua(1),
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
                'Accept-Encoding': 'gzip, deflate',
                'Accept-Language': 'zh-CN,zh;q=0.9',
                'cookie': Cookies
            }
            data = {'age': None, 'awemeCount': None, 'desc': None, 'enterpriseVerifyReason': None, 'ip': None,
                    'mplatformFollowersCount': None, "followingCount": None}
            response = requests.get(url=url, headers=headers, timeout=1, verify=False)
            # print(response.text)
            rtext = response.text
            if '>私密账号</p>' in rtext:
                data['private'] = True
            push = re.findall(f'(?:freq_visit_msg|statusMsg).*secUid\\\\":\\\\"{uid}.*?redirectFrom', rtext)
            if push:
                ipLocation = re.findall('"ipLocation\\\\":\\\\"(.*?)\\\\"', push[0])  # IP归属地
                if ipLocation:
                    # 未知是'$undefined'
                    if '$undefined' in ipLocation[0]:
                        data['ip'] = '未知'
                    else:
                        data['ipLocation'] = ipLocation[0].replace('IP属地：', '')
                country = re.findall('"country\\\\":\\\\"(.*?)\\\\"', push[0])  # 城市
                province = re.findall('"province\\\\":\\\\"(.*?)\\\\"', push[0])  # 城市
                city = re.findall('"city\\\\":\\\\"(.*?)\\\\"', push[0])  # 城市
                # 未知是'$undefined'
                if '$undefined' in country or not country:
                    data['country'] = '未知'
                elif '$undefined' in province or not province:
                    data['country'] = country[0]
                elif '$undefined' in city or not city:
                    data['country'] = country[0]
                else:
                    data['country'] = city[0]

                age = re.findall('"age\\\\":(.*?),', push[0])  # 年龄
                if age:
                    # 未知是['null']
                    if 'null' in age[0] or '-1' in age[0]:
                        data['age'] = '未知'
                    else:
                        data['age'] = age[0]
                awemeCount = re.findall('"awemeCount\\\\":(.*?),', push[0])  # 作品数量
                if awemeCount:
                    if awemeCount[0] != '':
                        data['awemeCount'] = awemeCount[0]
                # followingCount = re.findall('"followingCount\\\\":(.*?),', push[0])  # 关注数量
                # if followingCount:
                #     if followingCount[0] != '':
                #         data['followingCount'] = followingCount[0]
                mplatformFollowersCount = re.findall('"mplatformFollowersCount\\\\":(.*?),', push[0])  # 粉丝数量
                if mplatformFollowersCount:
                    if mplatformFollowersCount[0] != '':
                        data['mplatformFollowersCount'] = mplatformFollowersCount[0]
                desc = re.findall('"desc\\\\":\\\\"(.*?)\\\\"', push[0])  # 简介
                if desc:
                    if desc[0] != '':
                        data['desc'] = desc[0]
                enterpriseVerifyReason = re.findall('"enterpriseVerifyReason\\\\":\\\\"(.*?)\\\\"', push[0])  # 有内容就是蓝V
                if enterpriseVerifyReason:
                    if enterpriseVerifyReason[0] != '':
                        data['enterpriseVerifyReason'] = True
            return data
        except Exception as e:
            pass
            # print('fwzy',e)
        return False


# 年龄区间
def check_blacklist_age(age_inputValue, current_age):
    """检查当前年龄是否在拉黑的年龄段内"""
    age_ranges = age_inputValue
    if not age_ranges:
        return False

    # 处理特殊值 "未知"
    if current_age == '未知':
        return '-1' in age_ranges.split(',')

    try:
        current_age_num = int(current_age)
    except ValueError:
        # 非数字且非"未知"的年龄直接返回False
        print(f"警告: 无法将年龄 '{current_age}' 转换为数字。")  # 可选：记录警告
        return False

    # 解析年龄段字符串
    for range_str in age_ranges.split(','):
        range_str = range_str.strip()  # 去除可能的空白字符
        if not range_str:
            continue  # 跳过空的字符串（例如连续逗号 , ,）

        if range_str == '-1':
            continue  # 已在前面处理过-1

        try:
            if '-' in range_str:
                # 处理年龄段
                start_str, end_str = range_str.split('-', 1)  # 限制分割次数
                start = int(start_str)
                end = int(end_str)
                # 检查范围是否合法，虽然不是必须，但更严谨
                if start > end:
                    print(f"警告: 无效的年龄范围 '{range_str}' (开始大于结束)。")  # 可选：记录警告
                    continue  # 跳过无效范围

                if start <= current_age_num <= end:
                    return True
            else:
                # 处理单独的年龄值
                single_age = int(range_str)
                if current_age_num == single_age:
                    return True
        except ValueError:
            # 处理无法转换为数字的范围或值
            print(f"警告: 无法解析拉黑年龄配置项 '{range_str}'。")  # 可选：记录警告
            continue  # 跳过无法解析的项

    return False


# 性别拉黑
def Gender_blocking(gender, gender_options):
    # 将中文性别转换为英文选项
    gender_mapping = {
        '男': 'male',
        '女': 'female',
        '未知': 'unknown'
    }

    # 获取对应的英文选项
    gender_english = gender_mapping.get(gender, 'unknown')

    # 检查是否需要拉黑
    if 'all' in gender_options:
        # print(f"用户性别为 {gender}，被拉黑（全部性别拉黑）")
        return f'性别为：{gender}(全部性别拉黑)'

    elif gender_english in gender_options:
        # print(f"用户性别为 {gender}，被拉黑")
        return f'性别为：{gender}'
        # return True

    # print(f"用户性别为 {gender}，未被拉黑")
    return False


# 分享类型拉黑
def check_share_block(share_target_id, selected_option_keys):
    """
    检查一个分享目标ID是否应该被拉黑，基于给定的选项列表。

    Args:
        share_target_id: 分享目标的数值ID。
        selected_option_keys: 配置中选中的分享类型英文键列表 (e.g., ["wechat_moments", "douyin_dm"])。

    Returns:
        如果应该拉黑，返回描述拉黑原因的字符串；否则返回 False。
    """
    # 1. 将配置选项转换为集合，提高查找效率
    selected_option_set = set(selected_option_keys)

    # 2. 检查是否配置了 "all" 选项
    if "all" in selected_option_set:
        # 如果配置了 "all"，则无论具体是什么分享类型，都视为拉黑
        # 获取目标ID对应的中文名称用于输出信息
        target_config_key = ID_TO_CONFIG_KEY.get(share_target_id)
        target_chinese_name = CONFIG_KEY_TO_CHINESE.get(target_config_key, "未知")
        return f'分享类型为：{target_chinese_name}(全部类型拉黑)'

    # 3. 如果没有配置 "all"，查找目标ID对应的配置键
    target_config_key = ID_TO_CONFIG_KEY.get(share_target_id)

    # 4. 检查目标ID是否已知，并且其对应的配置键是否在选中的选项集合中
    if target_config_key is not None and target_config_key in selected_option_set:
        # 如果目标类型已知且在配置列表中，则视为拉黑
        target_chinese_name = CONFIG_KEY_TO_CHINESE.get(
            target_config_key)  # 此时 target_config_key 肯定在 CONFIG_KEY_TO_CHINESE 中
        return f'分享类型为：{target_chinese_name}（拉黑）'

    # 5. 如果以上条件都不满足，则不拉黑
    return False


# --- 新增：将拉黑记录写入数据库的函数 ---
def insert_blacklist_record(account_url_part, user_sid, user_douyin_id, user_nickname, user_avatar, blacklist_reason):
    """
    将一条拉黑记录插入到 blacklist_records.db 数据库。
    参数:
        account_url_part (str): 拉黑该记录的主播账号的 url_part
        user_sid (str): 被拉黑用户的抖音主页ID (user_sid)
        user_douyin_id (str): 被拉黑用户的抖音号 (display_id)
        user_nickname (str): 被拉黑用户的昵称
        user_avatar (str): 被拉黑用户的头像URL
        blacklist_reason (str): 拉黑原因
    """
    print(
        f"拉黑.py: 尝试将拉黑记录写入数据库，用户: {user_nickname} ({user_douyin_id})，原因: {blacklist_reason}")  # 调试打印
    conn = None
    try:
        # 确定数据库文件路径 (与 login.py 使用相同的逻辑)
        root_path = os.getcwd()
        is_pack = getattr(sys, 'frozen', False)
        if is_pack:
            run_path = sys._MEIPASS
        else:
            run_path = root_path
        blacklist_records_path = os.path.join(run_path, 'blacklist_records.db')

        conn = sqlite3.connect(blacklist_records_path)
        c = conn.cursor()

        # 获取当前时间作为拉黑时间
        blacklist_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

        # 插入数据
        # 使用 INSERT OR IGNORE 来处理 UNIQUE 约束，如果记录已存在，则忽略插入
        c.execute("""
                  INSERT
                  OR IGNORE INTO blacklist_records
                  (account_url_part, user_sid, user_douyin_id, user_nickname, user_avatar, blacklist_reason, blacklist_time)
                  VALUES (?, ?, ?, ?, ?, ?, ?)
                  """, (account_url_part, user_sid, user_douyin_id, user_nickname, user_avatar, blacklist_reason,
                        blacklist_time))

        conn.commit()
        print(f"拉黑.py: 已将拉黑记录写入数据库或记录已存在。用户: {user_nickname}")  # 调试打印

    except sqlite3.Error as e:
        print(f"拉黑.py: 数据库插入错误: {e}")  # 错误打印
        if conn:
            conn.rollback()  # 发生错误时回滚事务
    except Exception as e:
        print(f"拉黑.py: 写入拉黑记录时发生未知错误: {e}")  # 错误打印
    finally:
        if conn:
            conn.close()


# 直播弹幕获取 拉黑 删除拉黑
class DouyinLiveWebFetcher:
    def __init__(self, live_url, roomId, Cookie, account_url_part):
        self.id_dict = {}
        self.Cookies = Cookie
        self.__ttwid = None
        self.room_id = roomId
        self.live_url = live_url
        self.user_agent = zhengchang_ua(1)
        self.account_url_part = account_url_part  # 主播账号id
        self.webview_window = webview.active_window()


    # 启动
    def start(self):

        self._connectWebSocket()

    # 结束
    def stop(self):
        if hasattr(self, 'ws'):
            self.ws.close()

    def _connectWebSocket(self):
        """
        连接抖音直播间websocket服务器，请求直播间数据
        """
        wss = (
            "wss://webcast5-ws-web-hl.douyin.com/webcast/im/push/v2/?app_name=douyin_web"
            "&version_code=180800&webcast_sdk_version=1.0.14-beta.0"
            "&update_version_code=1.0.14-beta.0&compress=gzip&device_platform=web&cookie_enabled=true"
            "&screen_width=1536&screen_height=864&browser_language=zh-CN&browser_platform=Win32"
            "&browser_name=Mozilla"
            "&browser_version=5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,"
            "%20like%20Gecko)%20Chrome/126.0.0.0%20Safari/537.36"
            "&browser_online=true&tz_name=Asia/Shanghai"
            "&cursor=d-1_u-1_fh-7392091211001140287_t-1721106114633_r-1"
            f"&internal_ext=internal_src:dim|wss_push_room_id:{self.room_id}|wss_push_did:7319483754668557238"
            f"|first_req_ms:1721106114541|fetch_time:1721106114633|seq:1|wss_info:0-1721106114633-0-0|"
            f"wrds_v:7392094459690748497"
            f"&host=https://live.douyin.com&aid=6383&live_id=1&did_rule=3&endpoint=live_pc&support_wrds=1"
            f"&user_unique_id=7319483754668557238&im_path=/webcast/im/fetch/&identity=audience"
            f"&need_persist_msg_count=15&insert_task_id=&live_reason=&room_id={self.room_id}&heartbeatDuration=0"
        )

        signature = generateSignature(wss)
        wss += f"&signature={signature}"

        headers = {
            "cookie": f"ttwid={self.ttwid}",
            "user-agent": self.user_agent,
        }
        self.ws = websocket.WebSocketApp(
            wss,
            header=headers,
            on_open=self._wsOnOpen,
            on_message=self._wsOnMessage,
            on_error=self._wsOnError,
            on_close=self._wsOnClose,
        )
        # 运行websocket连接，并处理可能的异常
        try:
            self.ws.run_forever()
        except websocket.WebSocketConnectionClosedException as e:
            logging.error("_connectWebSocket--WebSocket连接已关闭: %s", e)
            self.stop()
        except websocket.WebSocketException as e:
            logging.error("_connectWebSocket--WebSocket异常: %s", e)
            self.stop()
        except Exception as e:
            logging.error("_connectWebSocket--发生未知异常: %s", e)
            self.stop()
            raise  # 重新抛出异常，以便上层处理

    def _wsOnOpen(self, ws):
        """
        连接建立成功
        """
        logging.info(
            f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----直播间链接成功"
        )
        print('直播间链接成功')



        def heartbeat(ws: websocket.WebSocketApp):
            """发送心跳消息的定时任务"""
            while True:
                if ws.keep_running:  # 检查WebSocket连接是否仍在运行
                    # print(f'心跳')
                    ws.send("hi")  # 发送自定义的心跳消息
                    time.sleep(15)  # 等待指定的时间间隔
                else:
                    # print(f'心跳结束')
                    break

        heartbeat_thread = Thread(target=heartbeat, args=(ws,))
        heartbeat_thread.daemon = True  # 设置为守护线程
        heartbeat_thread.start()

    def _wsOnMessage(self, ws: websocket.WebSocketApp, message: str):
        """
        接收到数据
        :param ws: websocket实例
        :param message: 数据
        """
        # while True:
        # 根据proto结构体解析对象

        if message:
            try:
                package = PushFrame().parse(message)
                response = Response().parse(gzip.decompress(package.payload))

                # 返回直播间服务器链接存活确认消息，便于持续获取数据
                if response.need_ack:
                    ack = PushFrame(
                        log_id=package.log_id,
                        payload_type="ack",
                        payload=response.internal_ext.encode("utf-8"),
                    ).SerializeToString()
                    ws.send(ack, websocket.ABNF.OPCODE_BINARY)

                # 根据消息类别解析消息体
                for msg in response.messages_list:
                    method = msg.method
                    try:
                        {
                            "WebcastChatMessage": self._parseChatMsg,  # 聊天消息
                            "WebcastGiftMessage": self._parseGiftMsg,  # 礼物消息
                            "WebcastLikeMessage": self._parseLikeMsg,  # 点赞消息
                            "WebcastMemberMessage": self._parseMemberMsg,  # 进入直播间消息
                            "WebcastSocialMessage": self._parseSocialMsg,  # 关注消息
                            "WebcastRoomUserSeqMessage": self._parseRoomUserSeqMsg,  # 直播间统计
                            "WebcastFansclubMessage": self._parseFansclubMsg,  # 粉丝团消息
                            "WebcastControlMessage": self._parseControlMsg,  # 直播间状态消息
                            "WebcastEmojiChatMessage": self._parseEmojiChatMsg,  # 聊天表情包消息
                            "WebcastRoomStatsMessage": self._parseRoomStatsMsg,  # 直播间统计信息
                            "WebcastRoomMessage": self._parseRoomMsg,  # 直播间信息
                            "WebcastRoomRankMessage": self._parseRankMsg,  # 直播间排行榜信息
                        }.get(method)(msg.payload)
                    except Exception as e:
                        pass
                        # logging.error(f"_wsOnMessage--error occurred: {e}")

            except Exception as e:
                logging.error(f"_wsOnMessage--error occurred: {e}")

    def _wsOnError(self, ws, error):
        # print("WebSocket error: ", error)
        logging.info("WebSocket error: ", error)

    def _wsOnClose(self, ws: websocket.WebSocketApp, *args):
        logging.info(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----直播间断开")

    # 聊天消息 拉黑功能需要实现 已实现 待测试

    def _parseChatMsg(self, payload):
        """聊天消息"""
        message = ChatMessage().parse(payload)
        user_name = message.user.nick_name  # 用户名称
        user_id = message.user.id  # 用户id
        user_sid = message.user.sec_uid  # 用户主页uid
        display_id = message.user.display_id  # 用户抖音ID
        content = message.content  # 用户发送的信息
        user_img = message.user.avatar_thumb  # 用户头像
        if user_img:
            user_img = user_img.url_list_list[0]

        print(
            f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【聊天msg】- 用户名称:{user_name} - 用户id:{user_id} - 用户主页uid:{user_sid} - 用户抖音ID:{display_id} - 用户发送的信息:{content}"
        )
        # 弹幕拉黑
        danmaku_dict = Settings_Options.get('danmaku', {})
        if danmaku_dict and danmaku_dict.get('enabled') and danmaku_dict.get('inputValue'):
            danmaku_causer = char_in_list(content, danmaku_dict.get('inputValue'))
            if danmaku_causer:
                causer = f'弹幕存在违规词:{danmaku_causer}'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(
                    f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

    def _parseGiftMsg(self, payload):
        """礼物消息"""
        message = GiftMessage().parse(payload)
        user_name = message.user.nick_name  # 用户名称
        gift_name = message.gift.name  # 礼物信息
        gift_cnt = message.combo_count  # 礼物数量
        print(
            f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【礼物msg】-{user_name} - 送出了 {gift_name}x{gift_cnt}")

    def _parseLikeMsg(self, payload):
        """点赞消息"""
        message = LikeMessage().parse(payload)
        user_name = message.user.nick_name  # 用户名称
        count = message.count  # 点赞次数
        print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【点赞msg】- {user_name} - 点了{count}个赞")

    # 进入直播间信息 拉黑功能需要实现 已实现 待测试

    def _parseMemberMsg(self, payload):
        """进入直播间信息"""
        message = MemberMessage().parse(payload)
        following_coun = message.user.follow_info.following_count  # 用户关注数
        follower_count = message.user.follow_info.follower_count  # 用户粉丝数
        user_name = message.user.nick_name  # 用户名称
        user_sid = message.user.sec_uid  # 用户主页uid
        user_id = message.user.id  # 用户id
        user_follow_status = message.user.follow_info.follow_status  # 用户关注状态 0：未关注 1：已关注
        user_img = message.user.avatar_thumb  # 用户头像
        if user_img:
            user_img = user_img.url_list_list[0]

        display_id = message.user.display_id  # 用户抖音ID
        gender = ['未知', "男", "女"][message.user.gender]  # 用户性别 0：未知 1：男 2：女

        # if 'ducking' in user_name:
        #     print(message)
        #     input(11111)
        # if '蛋仔' in user_name:
        print(
            f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【进场msg】- 用户名称:{user_name} - 用户id:{user_id} - 用户uid:{user_sid} - 抖音id:{display_id} - 性别:{gender} 进入了直播间"
        )

        # with open('user_data.json', 'a', encoding='utf-8') as f:
        #     f.write(json.dumps({
        #         'account_url_part': self.account_url_part,
        #         'user_sid': user_sid,
        #         'user_douyin_id': display_id,
        #         'user_nickname': user_name,
        #         'user_avatar': user_img,
        #         'blacklist_reason': '进入直播间',
        #         'blacklist_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        #     }, ensure_ascii=False) + ',\n')

        # ID 白名单
        id_whitelist_dict = Settings_Options.get('id-whitelist', {})
        if id_whitelist_dict and id_whitelist_dict.get('enabled') and id_whitelist_dict.get('inputValue'):
            if display_id in id_whitelist_dict.get('inputValue'):
                print(f'{display_id}存在白名单中 不拉黑')
                return

        # ID 黑名单
        id_blacklist_rule_dict = Settings_Options.get('id-blacklist-rule', {})
        # print(id_blacklist_rule_dict)
        # print(Settings_Options)
        if id_blacklist_rule_dict and id_blacklist_rule_dict.get('enabled') and id_blacklist_rule_dict.get(
                'inputValue'):
            # blacklist_ids = [uid.strip() for uid in id_blacklist_rule_dict.get('inputValue','').splitlines() if uid.strip()]
            # print(f'进入黑名单：{blacklist_ids}')
            if display_id in id_blacklist_rule_dict.get('inputValue'):
                causer = '黑名单拉黑'
                print(f'{display_id}存在黑名单中 拉黑')
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")
                return

        # 本地数据互通 数据互通 拉黑 // 待实现

        # 云端数据互通 疑似账号 拉黑 // 待实现

        rcfs = message.anchor_display_text.default_patter.replace('{0:user}', '').replace('{1:string} ', '关注')

        # 统计用户进入次数
        if display_id in self.id_dict:
            self.id_dict[display_id] += 1
        else:
            self.id_dict[display_id] = 1
        enter_sum = self.id_dict[display_id]

        # 通过分享进入直播间 // 偶尔触发 人少的直播间可以
        if '分享' in rcfs:
            share_entry_dict = Settings_Options.get('share-entry', {})
            if share_entry_dict and share_entry_dict.get('enabled'):
                causer = '通过分享进入直播间'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因{causer}")

        # 通过关注进入直播间 粉丝进入
        if int(user_follow_status) == 1:
            follow_entry_dict = Settings_Options.get('follow-entry', {})
            if follow_entry_dict and follow_entry_dict.get('enabled'):
                causer = '通过关注进入直播间'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因{causer}")

        # 性别拉黑
        gender_dict = Settings_Options.get("gender", {})
        if gender_dict:
            if gender_dict.get("enabled") and gender_dict.get("options"):
                selected_genders = gender_dict.get("options")
                causer = Gender_blocking(gender, selected_genders)
                if causer:
                    print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑原因：{causer}")
                    lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)

        # 粉丝数量大于 拉黑
        follower_count_dict = Settings_Options.get("follower-count", {})
        if follower_count_dict and follower_count_dict.get('enabled') and follower_count_dict.get('inputValue'):
            if int(follower_count) > int(follower_count_dict.get('inputValue')):
                causer = f'粉丝数量大于设置的值{follower_count_dict.get("inputValue")}'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

        # 关注数量大于 拉黑
        following_count_dict = Settings_Options.get("following-count", {})

        if following_count_dict and following_count_dict.get('enabled') and following_count_dict.get('inputValue'):
            if int(following_coun) > int(following_count_dict.get('inputValue')):
                causer = f'关注数量大于设置的值{following_count_dict.get("inputValue")}'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

        # 进入次数大于 拉黑

        entry_count_dict = Settings_Options.get('entry-count', {})
        if entry_count_dict and entry_count_dict.get('enabled') and entry_count_dict.get('inputValue'):
            if int(enter_sum) > int(entry_count_dict.get('inputValue')):
                causer = f'进入次数大于设置的值{entry_count_dict.get("inputValue")}'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

        # 昵称关键词 拉黑

        nickname_dict = Settings_Options.get("nickname", {})
        if nickname_dict and nickname_dict.get('enabled') and nickname_dict.get('inputValue'):
            nickname_causer = char_in_list(user_name, nickname_dict.get('inputValue'))
            if nickname_causer:
                causer = f'昵称存在违规词：{nickname_causer}'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

        # 访问用户主页
        '''
        判断 地区 个性签名 IP归属地 年龄区间 作品数量 蓝V 私密账号
        只要有一个满足条件 则进入查看用户主页信息
        '''
        if Settings_Options.get('region', {}).get('enabled') or Settings_Options.get('signature', {}).get(
                'enabled') or Settings_Options.get('ip', {}).get('enabled') or Settings_Options.get('age-range',
                                                                                                    {}).get(
            'enabled') or Settings_Options.get('work-count', {}).get('enabled') or Settings_Options.get('blue-v',
                                                                                                        {}).get(
            'enabled') or Settings_Options.get('private-account', {}).get('enabled'):

            user_data = View_user_home(user_sid, self.Cookies)
            print(f'进入请求用户主页', user_data)
            # 地区 拉黑
            region_dict = Settings_Options.get('region', {})
            if region_dict and region_dict.get('enabled') and region_dict.get('inputValue'):
                region_causer = char_in_list(user_data.get('country', ''), region_dict.get('inputValue'))
                if region_causer:
                    causer = f'地区存在违规词：{region_causer}'
                    lahei(user_sid, user_id, self.Cookies)
                    insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                    print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

            # 个性签名 拉黑
            signature_dict = Settings_Options.get('signature', {})
            if signature_dict and signature_dict.get('enabled') and signature_dict.get('inputValue'):
                signature_causer = char_in_list(user_data.get('desc', ''), signature_dict.get('inputValue'))
                if signature_causer:
                    causer = f'个性签名存在违规词：{signature_causer}'
                    lahei(user_sid, user_id, self.Cookies)
                    insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                    print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

            # IP归属地 拉黑

            ip_dict = Settings_Options.get('ip', {})
            if ip_dict and ip_dict.get('enabled') and ip_dict.get('inputValue'):
                if user_data.get('ipLocation', ''):
                    ip_causer = char_in_list(user_data.get('ipLocation', ''), ip_dict.get('inputValue'))
                else:
                    ip_causer = char_in_list(user_data.get('ip', ''), ip_dict.get('inputValue'))
                if ip_causer:
                    causer = f'IP归属地存在违规词：{ip_causer}'
                    lahei(user_sid, user_id, self.Cookies)
                    insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                    print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

            # 年龄区间 拉黑
            age_range_dict = Settings_Options.get('age-range', {})
            if age_range_dict and age_range_dict.get('enabled') and age_range_dict.get('inputValue'):
                if check_blacklist_age(age_range_dict.get('inputValue'), user_data.get('age', '')):
                    causer = f'年龄区间存在违规词：{user_data.get('age', '')}'
                    lahei(user_sid, user_id, self.Cookies)
                    insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                    print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

            # 作品数量大于 拉黑
            work_count_dict = Settings_Options.get('work-count', {})
            if work_count_dict and work_count_dict.get('enabled') and work_count_dict.get('inputValue'):
                if int(user_data.get('awemeCount', '')) > int(work_count_dict.get('inputValue')):
                    causer = f'作品数量大于设置的值{work_count_dict.get("inputValue")}'
                    lahei(user_sid, user_id, self.Cookies)
                    insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                    print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

            # 开通蓝v 拉黑

            blue_v_dict = Settings_Options.get('blue-v', {})
            if blue_v_dict and blue_v_dict.get('enabled') and user_data.get('enterpriseVerifyReason', ''):
                causer = f'开通蓝V'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

            # 私密账号 拉黑

            private_account_dict = Settings_Options.get('private-account', {})
            if private_account_dict and private_account_dict.get('enabled') and user_data.get('private', ''):
                causer = f'私密账号'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

            # 开通橱窗 拉黑 // 没有相关参数

            # 疑似账号 拉黑 // 不做

    # 关注 分享消息 拉黑功能需要实现 已实现 待测试

    def _parseSocialMsg(self, payload):
        """关注 分享消息"""
        message = SocialMessage().parse(payload)
        user_name = message.user.nick_name  # 用户名称
        user_sid = message.user.sec_uid  # 用户主页uid
        user_id = message.user.id  # 用户id
        display_id = message.user.display_id  # 用户抖音ID
        # print(f'message.follow_count-->{message.follow_count}')
        share_Target = message.share_target  # 分享目标
        user_img = message.user.avatar_thumb  # 用户头像
        if user_img:
            user_img = user_img.url_list_list[0]

        # 分享 拉黑 // 可以确认媒体
        if message.follow_count == 0:
            print(
                f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【分享msg】- 用户名称:{user_name} - 用户id:{user_id} 分享了主播")

            share_dict = Settings_Options.get("share", {})
            if share_dict and share_dict.get("enabled") and share_dict.get("options"):
                selected_share_keys = share_dict.get("options")
                causer = check_share_block(int(share_Target), selected_share_keys)
                if causer:
                    lahei(user_sid, user_id, self.Cookies)
                    insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                    print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")
        # 关注 拉黑
        else:

            print(
                f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【关注msg】- 用户名称:{user_name} - 用户id:{user_id} 关注了主播")

            follow_dict = Settings_Options.get("follow", {})
            if follow_dict and follow_dict.get("enabled"):
                causer = f'关注了主播'
                lahei(user_sid, user_id, self.Cookies)
                insert_blacklist_record(self.account_url_part, user_sid, display_id, user_name, user_img, causer)
                print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}----用户:{user_name}拉黑成功：原因:{causer}")

    def _parseRoomUserSeqMsg(self, payload):
        """直播间统计"""
        message = RoomUserSeqMessage().parse(payload)
        current = message.total  # 当前观看人数
        total = message.total_pv_for_anchor  # 累计观看人数
        print(
            f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【统计msg】- 当前观看人数: {current} - 累计观看人数: {total}")

    def _parseFansclubMsg(self, payload):
        """粉丝团消息"""
        message = FansclubMessage().parse(payload)
        content = message.content  # 内容
        print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【粉丝团msg】 {content}")

    def _parseControlMsg(self, payload):
        """直播间状态消息"""
        message = ControlMessage().parse(payload)

        if message.status == 3:
            print(f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}----直播间已结束')
            self.stop()



    def _parseEmojiChatMsg(self, payload):
        """聊天表情包消息"""
        message = EmojiChatMessage().parse(payload)
        emoji_id = message.emoji_id  # 表情包id
        user = message.user  # 用户
        common = message.common  # 通用信息
        default_content = message.default_content  # 默认内容
        print(
            f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【聊天表情包id】- {emoji_id} - user：{user} - common:{common} - default_content:{default_content}"
        )

    def _parseRoomStatsMsg(self, payload):
        """直播间统计msg"""
        message = RoomStatsMessage().parse(payload)
        display_long = message.display_long  # 直播间统计信息
        print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【直播间统计msg】- {display_long}")

    def _parseRoomMsg(self, payload):
        """直播间msg"""
        message = RoomMessage().parse(payload)
        common = message.common
        room_id = common.room_id  # 直播间id
        print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【直播间msg】- 直播间id:{room_id}")

    def _parseRankMsg(self, payload):
        """直播间排行榜msg"""
        message = RoomRankMessage().parse(payload)
        ranks_list = message.ranks_list
        print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}-----【直播间排行榜msg】{ranks_list}")

    @property
    def ttwid(self):
        """
        产生请求头部cookie中的ttwid字段，访问抖音网页版直播间首页可以获取到响应cookie中的ttwid
        :return: ttwid
        """
        if self.__ttwid:
            return self.__ttwid
        headers = {
            "User-Agent": self.user_agent,
        }
        try:
            response = requests.get(
                "https://live.douyin.com/", headers=headers, verify=False
            )
            response.raise_for_status()
        except Exception as e:
            logging.error(f"ttwid--error occurred: {e}")

        else:
            self.__ttwid = response.cookies.get("ttwid")
            return self.__ttwid


if __name__ == "__main__":
    if not os.path.exists('./user_data.json'):
        open('./user_data.json', 'w', encoding='utf-8').close()
    user_name = ""
    with open(r"D:\job_demo\demo\测试\cookie_name.txt", "r", encoding="utf-8") as f:
        user_name = f.read().split("|")[1].strip()
    Cookie = load_cookies_from_file(
        r"D:\job_demo\demo\测试\MS4wLjABAAAAc9m4vmspNsSiYP348XRC-OLVqSXRn8Rdtl618fbzYag.pkl"
    )
    # print(Cookie)
    # print(type(Cookie))
    cookies_dict = {c.name: c.value for c in Cookie}
    cookie_str = "; ".join(f"{k}={v}" for k, v in cookies_dict.items())
    # 账号的直播链接
    # live_url = 'https://live.douyin.com/699830573874'
    # roomId = '7502733944979360566'
    url_part = 'MS4wLjABAAAAc9m4vmspNsSiYP348XRC-OLVqSXRn8Rdtl618fbzYag'
    live_url = 'https://live.douyin.com/751561170106'
    roomId = '7504920274741660416'
    DouyinLiveWebFetcher(live_url, roomId, Cookie, url_part).start()
