# Source: https://github.com/smallfawn/QLScriptPublic/blob/main/daily/bjxd.py # Raw: https://raw.githubusercontent.com/smallfawn/QLScriptPublic/main/daily/bjxd.py # Repo: smallfawn/QLScriptPublic # Path: daily/bjxd.py # UploadedAt: 2026-04-02T02:22:19Z # SHA256: a680cf465f0ac16d7a83b7b70762ad13ce94b713829255df0a6390cfde87402e # Category: APP版/抓包 # Evidence: cookie/token/authorization/header """ 北京现代 APP 自动任务脚本 功能:自动完成签到、浏览文章、每日答题等任务 new Env("北京现代"); 环境变量: BJXD: str - 北京现代 APP api token (多个账号用英文逗号分隔,建议每个账号一个变量) BJXD1/BJXD2/BJXD3: str - 北京现代 APP api token (每个账号一个变量) BJXD_ANSWER: str - 预设答案 (可选, ABCD 中的一个) AI_API_KEY: str - 通用 AI APIKey (可选) AI_REQUEST_URL: str - 通用 AI 请求 URL (可选) AI_MODEL: str - 通用 AI 模型名称 (可选) AI_REQUEST_PARAMS: str - 通用 AI 请求参数 (可选, JSON 格式字符串) HUNYUAN_API_KEY: str - 腾讯混元AI APIKey (已废弃,不建议使用) GLM_API_KEY: str - 智谱 GLM AI APIKey (已废弃,不建议使用) cron: 25 6 * * * """ import os import random import time import json from datetime import datetime from typing import List, Dict, Any import requests from urllib3.exceptions import InsecureRequestWarning, InsecurePlatformWarning # 禁用 SSL 警告 requests.packages.urllib3.disable_warnings(InsecureRequestWarning) requests.packages.urllib3.disable_warnings(InsecurePlatformWarning) class BeiJingHyundai: """北京现代APP自动任务类""" # 基础配置 NAME = "北京现代 APP 自动任务" BASE_URL = "https://bm2-api.bluemembers.com.cn" # API endpoints API_USER_INFO = "/v1/app/account/users/info" API_MY_SCORE = "/v1/app/user/my_score" API_TASK_LIST = "/v1/app/user/task/list" API_SIGN_LIST = "/v1/app/user/reward_list" API_SIGN_SUBMIT = "/v1/app/user/reward_report" API_ARTICLE_LIST = "/v1/app/white/article/list2" API_ARTICLE_DETAIL = "/v1/app/white/article/detail_app/{}" API_ARTICLE_SCORE_SUBMIT = "/v1/app/score" API_QUESTION_INFO = "/v1/app/special/daily/ask_info" API_QUESTION_SUBMIT = "/v1/app/special/daily/ask_answer" # 预设的备用 share_user_hid 列表 BACKUP_HIDS = [ "a6688ec1a9ee429fa7b68d50e0c92b1f", "bb8cd2e44c7b45eeb8cc5f7fa71c3322", "5f640c50061b400c91be326c8fe0accd", "55a5d82dacd9417483ae369de9d9b82d", ] def __init__(self): """初始化实例变量""" self.token: str = "" # 当前用户token self.user: Dict[str, Any] = {} # 当前用户信息 self.users: List[Dict[str, Any]] = [] # 所有用户信息列表 self.correct_answer: str = "" # 正确答案 self.preset_answer: str = "" # 预设答案 self.ai_hunyuan_api_key: str = "" # 腾讯混元AI APIKey(兼容旧环境变量) self.ai_glm_api_key: str = "" # 智谱 GLM AI APIKey(兼容旧环境变量) self.ai_api_key: str = "" # 通用 AI APIKey self.ai_request_url: str = "" # AI 请求地址 self.ai_model: str = "" # AI 模型 self.ai_request_params: str = "" # AI 请求参数(JSON字符串格式) self.wrong_answers: set = set() # 错误答案集合 self.log_content: str = "" # 日志内容 def log(self, content: str, print_to_console: bool = True) -> None: """添加日志""" if print_to_console: print(content) self.log_content += content + "\n" def push_notification(self) -> None: """推送通知""" try: QLAPI.notify(self.NAME, self.log_content) except NameError: print(f"\n\n🚀 推送通知\n\n{self.NAME}\n\n{self.log_content}") def make_request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]: """ 发送API请求 Args: method: 请求方法 (GET/POST) endpoint: API端点 **kwargs: 请求参数 Returns: Dict[str, Any]: API响应数据 """ url = f"{self.BASE_URL}{endpoint}" headers = {"token": self.token, "device": "iOS", "app-version": "8.31.2"} if "headers" not in kwargs: kwargs["headers"] = headers else: kwargs["headers"].update(headers) try: response = requests.request(method, url, timeout=30, **kwargs) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: self.log(f"❌ API request failed: {str(e)}") return {"code": -1, "msg": str(e)} def get_user_info(self) -> Dict[str, Any]: """ 获取用户信息 Returns: Dict[str, Any]: 用户信息字典,获取失败返回空字典 """ response = self.make_request("GET", self.API_USER_INFO) print(f"get_user_info API response ——> {response}") if response.get("code") == 0: data = response.get("data", {}) # 直接生成掩码后的手机号 masked_phone = f"{data.get('phone', '')[:3]}******{data.get('phone', '')[-2:]}" return { "token": self.token, "hid": data.get("hid", ""), "nickname": data.get("nickname", ""), "phone": masked_phone, # 直接存储掩码后的手机号 "score_value": data.get("score_value", 0), "share_user_hid": "", "task": {"sign": False, "view": False, "question": False}, } self.log(f"❌ 账号已失效, 请重新获取 token: {self.token}") return {} def get_score_details(self) -> None: """显示积分详情,包括总积分、今日变动和最近记录""" params = {"page_no": "1", "page_size": "10"} # 获取最近10条记录 response = self.make_request("GET", self.API_MY_SCORE, params=params) print(f"get_score_details API response ——> {response}") if response.get("code") == 0: data = response.get("data", {}) # 先获取今日记录 today = datetime.now().strftime("%Y-%m-%d") points_record = data.get("points_record", {}) today_records = [ record for record in points_record.get("list", []) if record.get("created_at", "").startswith(today) ] # 计算今日积分变化 today_score = sum( int(record.get("score_str", "0").strip("+")) for record in today_records ) today_score_str = f"+{today_score}" if today_score > 0 else str(today_score) self.log(f"🎉 总积分: {data.get('score', 0)} | 今日积分变动: {today_score_str}") # 输出今日积分记录 if today_records: self.log("今日积分记录:") for record in today_records: self.log( f"{record.get('created_at', '')} {record.get('desc', '')} {record.get('score_str', '')}" ) else: self.log("今日暂无积分变动") # 任务相关 def check_task_status(self, user: Dict[str, Any]) -> None: """检查任务状态""" response = self.make_request("GET", self.API_TASK_LIST) print(f"get_task_status API response ——> {response}") if response.get("code") != 0: self.log(f'❌ 获取任务列表失败: {response.get("msg", "未知错误")}') return actions = response.get("data", {}) # 检查签到任务 if "action4" in actions: user["task"]["sign"] = actions["action4"].get("status") == 1 else: self.log("❌ task list action4 签到任务 不存在") # 检查浏览文章任务 if "action12" in actions: user["task"]["view"] = actions["action12"].get("status") == 1 else: self.log("❌ task list action12 浏览文章任务 不存在") # 检查答题任务 if "action39" in actions: user["task"]["question"] = actions["action39"].get("status") == 1 else: self.log("❌ task list action39 答题任务 不存在") # 签到相关 def get_sign_info(self) -> None: """执行签到任务""" max_attempts = 5 # 最大尝试次数 best_score = 0 best_params = None for attempt in range(max_attempts): response = self.make_request("GET", self.API_SIGN_LIST) print(f"get_sign_info (attempt {attempt + 1}) API response ——> {response}") if response.get("code") != 0: self.log(f'❌ 获取签到列表失败: {response.get("msg", "未知错误")}') break data = response.get("data", {}) hid = data.get("hid", "") reward_hash = data.get("rewardHash", "") for item in data.get("list", []): if item.get("hid") == hid: current_score = item.get("score", 0) print( f"第{attempt + 1}次获取签到列表: score={current_score} hid={hid} rewardHash={reward_hash}" ) if current_score > best_score: best_score = current_score best_params = (hid, reward_hash, current_score) print(f"当前可获得签到积分: {best_score}") break if attempt < max_attempts - 1: # 不是最后一次循环 print(f"继续尝试获取更高积分, 延时5-10s") time.sleep(random.randint(5, 10)) else: # 最后一次循环 即将提交签到 print(f"即将提交签到, 延时3-4s") time.sleep(random.randint(3, 4)) if best_params: self.submit_sign(*best_params) else: self.log("❌ 未能获取到有效的签到参数") def submit_sign(self, hid: str, reward_hash: str, score: int) -> None: """提交签到""" json_data = { "hid": hid, "hash": reward_hash, "sm_deviceId": "", "ctu_token": None, } response = self.make_request("POST", self.API_SIGN_SUBMIT, json=json_data) print(f"submit_sign API response ——> {response}") if response.get("code") == 0: self.log(f"✅ 签到成功 | 积分 +{score}") else: self.log(f'❌ 签到失败: {response.get("msg", "未知错误")}') # 文章浏览相关 def get_article_list(self) -> List[str]: """获取文章列表""" params = { "page_no": "1", "page_size": "20", "type_hid": "", } response = self.make_request("GET", self.API_ARTICLE_LIST, params=params) print(f"get_article_list API response ——> {response}") if response.get("code") == 0: # 从文章列表中随机选择3个ID data = response.get("data", {}) article_list = [item.get("data_id", "") for item in data.get("list", []) if item.get("data_id")] return random.sample(article_list, min(3, len(article_list))) self.log(f'❌ 获取文章列表失败: {response.get("msg", "未知错误")}') return [] def get_article_detail(self, article_id: str) -> None: """浏览文章""" self.log(f"浏览文章 article_id: {article_id}") endpoint = self.API_ARTICLE_DETAIL.format(article_id) try: # 调用make_request访问文章详情 response = self.make_request("GET", endpoint) # 记录响应状态,便于调试 if response.get("code") == -1: self.log(f"⚠️ 文章浏览异常: {response.get('msg', '未知错误')}") else: self.log(f"✅ 文章浏览成功") except Exception as e: # 捕获所有可能的异常,确保脚本不会在此处中断 self.log(f"❌ 文章浏览过程中发生异常: {str(e)}") def submit_article_score(self) -> None: """提交文章积分""" json_data = { "ctu_token": "", "action": 12, } response = self.make_request( "POST", self.API_ARTICLE_SCORE_SUBMIT, json=json_data ) print(f"submit_article_score API response ——> {response}") if response.get("code") == 0: data = response.get("data", {}) score = data.get("score", 0) self.log(f"✅ 浏览文章成功 | 积分 +{score}") else: self.log(f'❌ 浏览文章失败: {response.get("msg", "未知错误")}') # 答题相关 def get_question_info(self, share_user_hid: str) -> None: """执行答题任务""" params = {"date": datetime.now().strftime("%Y%m%d")} response = self.make_request("GET", self.API_QUESTION_INFO, params=params) print(f"get_question_info API response ——> {response}") if response.get("code") != 0: self.log(f'❌ 获取问题失败: {response.get("msg", "未知错误")}') return data = response.get("data", {}) # data['state'] 1=表示未答题 2=已答题且正确 3=答错且未有人帮忙答题 4=答错但有人帮忙答题 if data.get("state") == 3: self.log("今日已答题但回答错误,当前无人帮助答题,跳过") return if data.get("state") != 1: if data.get("answer"): answer = data.get("answer", [""])[0] if answer in ["A", "B", "C", "D"]: self.correct_answer = answer self.log(f"今日已答题,跳过,答案:{answer}") return self.log("今日已答题,但未获取到答案,跳过") return question_info = data.get("question_info", {}) questions_hid = question_info.get("questions_hid", "") # 构建问题字符串,只包含未被标记为错误的选项 question_str = f"{question_info.get('content', '')}\n" valid_options = [] for option in question_info.get("option", []): if option.get("option") not in self.wrong_answers: valid_options.append(option) question_str += f'{option.get("option", "")}. {option.get("option_content", "")}\n' else: print(f"跳过错误选项 {option.get('option', '')}. {option.get('option_content', '')}") print(f"\n问题详情:\n{question_str}") # 如果只剩一个选项,直接使用 if len(valid_options) == 1: answer = valid_options[0]["option"] self.log(f"仅剩一个选项,使用答案: {answer}") time.sleep(random.randint(3, 5)) self.submit_question_answer(questions_hid, answer, share_user_hid) return # 获取答案并提交 answer = self.get_question_answer(question_str) time.sleep(random.randint(3, 5)) self.submit_question_answer(questions_hid, answer, share_user_hid) def get_ai_answer(self, question: str) -> str: """获取通用AI答案""" if not self.ai_api_key or not self.ai_request_url or not self.ai_model: return "" headers = { "Authorization": f"Bearer {self.ai_api_key}", "Content-Type": "application/json", } # 构建默认的消息内容 system_prompt = "你是一位北京现代汽车品牌的专家,对车型配置非常熟悉。\n以下是一道单选题,请只从题目实际列出的选项里选择正确答案。\n注意:题目可能只给出 2 个或 3 个选项,并非永远 4 个。\n请仅输出对应选项的那个英文字母,不要输出任何其他字符。" # 构建默认的 json_data json_data = { "model": self.ai_model, "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": question} ] } # 如果提供了额外的请求参数,合并到 json_data 中 if self.ai_request_params: try: extra_params = json.loads(self.ai_request_params) json_data.update(extra_params) except json.JSONDecodeError as e: print(f"❌ AI 请求参数解析失败: {str(e)}") try: print(f"通用 AI API request ——> {json_data}") response = requests.post( self.ai_request_url, headers=headers, json=json_data, ) print(f"通用 AI API response status ——> {response.status_code}") print(f"通用 AI API response text ——> {response.text}") response.raise_for_status() response_json = response.json() # 获取AI回答内容并转大写 choices = response_json.get("choices", []) if choices and len(choices) > 0: message = choices[0].get("message", {}) ai_response = message.get("content", "").upper() else: ai_response = "" # 使用集合操作找出有效答案 valid_answers = set("ABCD") - self.wrong_answers found_answers = set(ai_response) & valid_answers # 如果找到答案则返回其中一个 if found_answers: return found_answers.pop() else: self.log(f"❌ 没有找到符合的 AI 答案") return "" except Exception as e: self.log(f"通用 AI API 请求失败: {str(e)}") return "" def get_question_answer(self, question: str) -> str: """获取答题答案""" # 1. 存在正确答案时,使用正确答案 if self.correct_answer: self.log(f"使用历史正确答案: {self.correct_answer}") return self.correct_answer # 2. 存在预设答案时,使用预设答案 if self.preset_answer: self.log(f"使用预设答案: {self.preset_answer}") return self.preset_answer # 3. 存在AI配置时,使用通用AI方法获取答案 if self.ai_api_key and self.ai_request_url and self.ai_model: ai_answer = self.get_ai_answer(question) if ai_answer: self.log(f"使用 AI 答案: {ai_answer}") return ai_answer # 4. 随机选择答案(排除错误答案) answer = self.get_random_answer() self.log(f"随机答题,答案: {answer}") return answer def get_random_answer(self) -> str: """获取随机答案,排除已知错误答案""" available_answers = set(["A", "B", "C", "D"]) - self.wrong_answers if not available_answers: self.wrong_answers.clear() available_answers = set(["A", "B", "C", "D"]) return random.choice(list(available_answers)) def get_answered_question(self) -> None: """从已答题账号获取答案""" params = {"date": datetime.now().strftime("%Y%m%d")} response = self.make_request("GET", self.API_QUESTION_INFO, params=params) print(f"get_answered_question API response ——> {response}") if response.get("code") != 0: self.log(f'❌ 从已答题账号获取问题失败: {response.get("msg", "未知错误")}') return data = response.get("data", {}) # data['state'] 1=表示未答题 2=已答题且正确 4=已答题但错误 if response.get("code") == 0 and data.get("answer"): answer = data.get("answer", [""])[0] if answer in ["A", "B", "C", "D"]: self.correct_answer = answer self.log(f"从已答题账号获取到答案:{answer}") return self.log("从已答题账号获取答案失败") def submit_question_answer( self, question_id: str, answer: str, share_user_hid: str ) -> None: """提交答题答案""" json_data = { "answer": answer, "questions_hid": question_id, "ctu_token": "", } if share_user_hid: json_data["date"] = datetime.now().strftime("%Y%m%d") json_data["share_user_hid"] = share_user_hid response = self.make_request("POST", self.API_QUESTION_SUBMIT, json=json_data) print(f"submit_question_answer API response ——> {response}") if response.get("code") == 0: data = response.get("data", {}) if data.get("state") == 3: # 答错 # 记录错误答案 self.wrong_answers.add(answer) # 如果是正确答案,清除它 if self.correct_answer == answer: self.correct_answer = "" # 如果是预设答案,清除它 if self.preset_answer == answer: self.preset_answer = "" self.log("❌ 答题错误") elif data.get("state") == 2: # 答对了 if self.correct_answer != answer: self.correct_answer = answer score = data.get("answer_score", 0) self.log(f"✅ 答题正确 | 积分 +{score}") else: self.log(f'❌ 答题失败: {response.get("msg", "未知错误")}') def get_backup_share_hid(self, user_hid: str) -> str: """从备用 hid 列表中获取一个不同于用户自身的 hid""" available_hids = [hid for hid in self.BACKUP_HIDS if hid != user_hid] return random.choice(available_hids) if available_hids else "" def run(self) -> None: """运行主程序""" try: from dotenv import load_dotenv load_dotenv() print("✅ dotenv 成功加载 .env 文件") except ImportError: print("⚠️ 缺少 dotenv 库, 青龙环境请忽略, 本地运行请安装此库") # 使用列表保持顺序,使用集合实现去重 tokens = [] tokens_set = set() # 方式1: 从BJXD环境变量获取(逗号分隔的多个token) token_str = os.getenv("BJXD") if token_str: # 过滤空值并保持顺序添加 for token in token_str.split(","): token = token.strip() if token and token not in tokens_set: tokens.append(token) tokens_set.add(token) # 方式2: 从BJXD1/BJXD2/BJXD3等环境变量获取 i = 1 empty_count = 0 # 记录连续空值的数量 while empty_count < 5: # 连续5个空值才退出 token = os.getenv(f"BJXD{i}") if not token: empty_count += 1 else: token = token.strip() if token and token not in tokens_set: # 确保token不是空字符串且未重复 empty_count = 0 # 重置连续空值计数 tokens.append(token) tokens_set.add(token) i += 1 if not tokens: self.log( "⛔️ 未获取到 tokens, 请检查环境变量 BJXD 或 BJXD1/BJXD2/... 是否填写" ) self.push_notification() return self.log(f"👻 共获取到用户 token {len(tokens)} 个") # 获取新的 AI 配置参数 self.ai_api_key = os.getenv("AI_API_KEY", "") self.ai_request_url = os.getenv("AI_REQUEST_URL", "") self.ai_model = os.getenv("AI_MODEL", "") self.ai_request_params = os.getenv("AI_REQUEST_PARAMS", "") # 兼容旧的环境变量 if not self.ai_api_key and not self.ai_request_url and not self.ai_model: # 检查旧的腾讯混元 AI 配置 self.ai_hunyuan_api_key = os.getenv("HUNYUAN_API_KEY", "") if self.ai_hunyuan_api_key: self.ai_api_key = self.ai_hunyuan_api_key self.ai_request_url = "https://api.hunyuan.cloud.tencent.com/v1/chat/completions" self.ai_model = "hunyuan-turbo" self.ai_request_params = json.dumps({"enable_enhancement": True, "force_search_enhancement": True, "enable_instruction_search": True}) self.log("💯 已获取到腾讯混元 AI 配置, 使用腾讯混元 AI 答题") else: self.log("😭 未设置腾讯混元 AI HUNYUAN_API_KEY 环境变量") # 检查旧的智谱 GLM AI 配置 self.ai_glm_api_key = os.getenv("GLM_API_KEY", "") if self.ai_glm_api_key: self.ai_api_key = self.ai_glm_api_key self.ai_request_url = "https://open.bigmodel.cn/api/paas/v4/chat/completions" self.ai_model = "glm-4.5-flash" self.ai_request_params = json.dumps({"do_sample": False}) self.log("💯 已获取到智谱 GLM AI 配置, 使用智谱 GLM AI 答题") else: self.log("😭 未设置智谱 GLM AI GLM_API_KEY 环境变量") else: # 使用新的 AI 配置 if self.ai_api_key and self.ai_request_url and self.ai_model: self.log("💯 已获取到通用 AI 配置, 使用通用 AI 答题") else: self.log("⚠️ 通用 AI 配置不完整, 请检查 AI_API_KEY、AI_REQUEST_URL 和 AI_MODEL 环境变量") # 获取预设答案 self.preset_answer = os.getenv("BJXD_ANSWER", "").upper() if self.preset_answer: if self.preset_answer in ["A", "B", "C", "D"]: self.log(f"📝 已获取预设答案: {self.preset_answer}") else: self.preset_answer = "" self.log("❌ 预设答案格式错误,仅支持 A/B/C/D") self.log("获取用户信息") # 获取所有用户信息 for token in tokens: self.token = token user = self.get_user_info() if user: self.users.append(user) time.sleep(random.randint(3, 5)) if not self.users: self.log("❌ 未获取到有效用户") # 最后推送通知 self.push_notification() return # 设置分享用户ID for i, user in enumerate(self.users): prev_index = (i - 1) if i > 0 else len(self.users) - 1 # 如果有多个用户且上一个用户不是自己,使用上一个用户的 hid if len(self.users) > 1 and self.users[prev_index].get("hid") != user.get("hid"): user["share_user_hid"] = self.users[prev_index].get("hid", "") else: # 否则从备用 hid 列表中选择一个 user["share_user_hid"] = self.get_backup_share_hid(user.get("hid", "")) # 执行任务 self.log("\n============ 执行任务 ============") for i, user in enumerate(self.users, 1): # 更新当前用户信息 self.token = user["token"] self.user = user # 随机延迟 if i > 1: print("\n进行下一个账号, 等待 5-10 秒...") time.sleep(random.randint(5, 10)) self.log(f"\n======== ▷ 第 {i} 个账号 ◁ ========") # 打印用户信息 self.log( f"👻 用户名: {self.user.get('nickname', '未知')} | " f"手机号: {self.user.get('phone', '未知')} | " f"积分: {self.user.get('score_value', 0)}\n" f"🆔 用户hid: {self.user.get('hid', '')}\n" f"🆔 分享hid: {self.user.get('share_user_hid', '')}" ) # 检查任务状态 self.check_task_status(self.user) self.log(f"任务状态: {self.user['task']}") # 调试使用 设置任务状态 self.user["task"]["question"] = True # self.user["task"]["sign"] = False # self.user["task"]["view"] = False # 获取任务状态 user_task = self.user.get("task", {}) # 任务:答题 if not user_task.get("question"): self.get_question_info(self.user.get("share_user_hid", "")) else: self.log("✅ 答题任务 已完成,跳过") if not self.correct_answer: self.get_answered_question() # 任务:签到 if not user_task.get("sign"): self.get_sign_info() time.sleep(random.randint(5, 10)) else: self.log("✅ 签到任务 已完成,跳过") # 任务:阅读文章 if not user_task.get("view"): article_ids = self.get_article_list() if article_ids: for index, article_id in enumerate(article_ids): # 已经只有3篇了 self.log(f"🔄 开始处理第 {index + 1}/{len(article_ids)} 篇文章") try: self.get_article_detail(article_id) except Exception as e: self.log(f"❌ 第 {index + 1} 篇文章处理失败: {str(e)}") # 每篇文章之间的延迟 time.sleep(random.randint(10, 15)) # 所有文章处理完成后提交积分 try: self.submit_article_score() except Exception as e: self.log(f"❌ 提交文章积分失败: {str(e)}") else: self.log("✅ 浏览文章任务 已完成,跳过") self.log("\n============ 积分详情 ============") for i, user in enumerate(self.users, 1): if i > 1: print("\n进行下一个账号, 等待 5-10 秒...") time.sleep(random.randint(5, 10)) # 更新当前用户信息 self.token = user["token"] self.user = user self.log(f"\n======== ▷ 第 {i} 个账号 ◁ ========") # 打印用户信息 self.log( f"👻 用户名: {self.user.get('nickname', '未知')} | 手机号: {self.user.get('phone', '未知')}" ) # 显示积分详情 self.get_score_details() # 最后推送通知 self.push_notification() if __name__ == "__main__": BeiJingHyundai().run()