jack há 4 meses atrás
pai
commit
fd08d2a86e

+ 180 - 0
message/message_dlt.py

@@ -0,0 +1,180 @@
+# -*- coding: utf-8 -*-
+"""
+获取超级大乐透结果, 并匹配自己购买的号码, 配合定时执行使用
+"""
+
+import sys
+import os
+import asyncio
+import httpx
+
+sys.path.append(os.path.join(os.path.abspath(__file__).split('manual')[0] + 'manual'))
+
+from utils.utils_send_gotify import GotifyNotifier
+
+
+class CheckDlt:
+    def __init__(self):
+        self.url = 'https://webapi.sporttery.cn/gateway/lottery/getHistoryPageListV1.qry?gameNo=85&provinceId=0&pageSize=1&isVerify=1&pageNo=1'
+        self.headers = {
+            "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, br, zstd",
+            "Accept-Language": "zh-CN,zh;q=0.9",
+            "Cache-Control": "max-age=0",
+            "Priority": "u=0, i",
+            "Sec-CH-UA": '"Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"',
+            "Sec-CH-UA-Mobile": "?0",
+            "Sec-CH-UA-Platform": '"macOS"',
+            "Sec-Fetch-Dest": "document",
+            "Sec-Fetch-Mode": "navigate",
+            "Sec-Fetch-Site": "none",
+            "Sec-Fetch-User": "?1",
+            "Upgrade-Insecure-Requests": "1",
+            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36"
+        }
+        self.my_dlt = [
+            ['10', '11', '16', '17', '18', '11', '12'],
+            ['02', '03', '11', '12', '23', '05', '06'],
+            ['07', '09', '15', '17', '22', '09', '11'],
+            ['05', '06', '07', '34', '35', '02', '09'],
+            ['09', '10', '11', '21', '22', '04', '05']
+        ]
+
+    async def req(self):
+        async with httpx.AsyncClient() as client:
+            try:
+                resp = await client.get(self.url, timeout=5)
+                if resp.status_code != 200:
+                    print('state code: {}'.format(resp.status_code))
+                    log_detail = '访问失败, 状态码:{},url:{}'.format(resp.status_code, self.url)
+                    print(log_detail)
+                    return None
+            except Exception as e:
+                print(f'请求失败 {e}')
+                return None
+
+            return resp.json()
+
+    def data_handle(self, data):
+        if not data:
+            print('获取数据为空')
+            return None
+
+        value = data.get('value')
+        data_list = value.get('list')
+
+        if not data_list:
+            print('获取数据为空')
+            return None
+
+        result_data = []
+
+        for d in data_list:
+            numbers = d.get('lotteryUnsortDrawresult')
+            try:
+                if len(numbers.split(' ')) < 7:
+                    continue
+            except Exception as e:
+                print('numbers: {}, err: {}'.format(numbers, e))
+                continue
+
+            red_list = numbers.split(' ')[:5]
+            blue_list = numbers.split(' ')[5:]
+
+            red_list.sort()
+            blue_list.sort()
+
+            try:
+                # 切开红球,蓝球数组
+                red1 = red_list[0]
+                red2 = red_list[1]
+                red3 = red_list[2]
+                red4 = red_list[3]
+                red5 = red_list[4]
+                blue1 = blue_list[0]
+                blue2 = blue_list[1]
+            except Exception as e:
+                print('红球或蓝球数据丢失')
+                continue
+
+            result_data.append({
+                'serial': d.get('lotteryDrawNum'),
+                'red1': red1 or '',
+                'red2': red2 or '',
+                'red3': red3 or '',
+                'red4': red4 or '',
+                'red5': red5 or '',
+                'blue1': blue1 or '',
+                'blue2': blue2 or '',
+                'drawPdfUrl': d.get('drawPdfUrl'),
+                'date': d.get('lotteryDrawTime'),
+                'pool': d.get('poolBalanceAfterdraw')
+            })
+
+        if result_data:
+            return result_data
+        else:
+            print('返回的数据为空, 获取数据失败')
+            return None
+
+    def data_compare(self, all_data):
+        if not all_data:
+            return '', ''
+
+        data = all_data[0]
+
+        red_list = [data['red1'], data['red2'], data['red3'], data['red4'], data['red5']]
+        blue_list = [data['blue1'], data['blue2']]
+
+        # 期号
+        subject = '{}'.format(data['serial'])
+
+        # 组成每期数据的text
+        serial_text = 'serial: {}\t\tlottery draw date: {}\nbonus pool: {} RMB\n{}\nlottery draw num: {} + {}\n\n'.format(
+            data['serial'], data['date'], data['pool'], '*' * 90,
+            red_list, blue_list)
+
+        for my_num in self.my_dlt:
+            my_red_list = my_num[:5]
+            my_blue_list = my_num[5:]
+
+            # 使用列表推导式找出两个列表中都存在的元素
+            red_common_elements = [element for element in red_list if element in my_red_list]
+            blue_common_elements = [element for element in blue_list if element in my_blue_list]
+
+            # 计算相等元素的数量
+            red_equal_count = len(red_common_elements)
+            blue_equal_count = len(blue_common_elements)
+
+            serial_text += 'my nums: {} + {}\nred hit: {}\nblue hit: {}\n\n'.format(my_red_list, my_blue_list,
+                                                                                    red_equal_count,
+                                                                                    blue_equal_count)
+
+        serial_text += '{}\n\n\n\n'.format('*' * 90)
+
+        return serial_text, subject
+
+    def send_message(self, text, subject):
+        if not text:
+            return
+
+        title = f'dlt {subject}'
+
+        # 推送到 message
+        GotifyNotifier(title, text, 'dlt').send_message()
+
+        # 发送到邮件
+        # SendEmail(title, title, text).send()
+
+    async def main(self):
+        data = await self.req()
+        result_data = self.data_handle(data)
+        if not result_data:
+            return
+
+        text, subject = self.data_compare(result_data)
+        self.send_message(text, subject)
+
+
+if __name__ == '__main__':
+    asyncio.run(CheckDlt().main())

+ 247 - 0
requirements.txt

@@ -0,0 +1,247 @@
+aiodns==3.2.0
+aiofiles==24.1.0
+aiogram==3.18.0
+aiohappyeyeballs==2.4.6
+aiohttp==3.9.5
+aiohttp-socks==0.8.4
+aioquic==1.2.0
+aiosignal==1.3.2
+annotated-types==0.7.0
+anyio==4.1.0
+appdirs==1.4.4
+APScheduler==3.10.4
+asgiref==3.8.1
+async-timeout==4.0.3
+atomicwrites==1.4.1
+attrs==25.1.0
+base58==2.1.1
+beautifulsoup4==4.12.2
+bech32==1.2.0
+better-proxy==1.1.5
+bidict==0.23.1
+bitarray==3.1.0
+blessed==1.20.0
+blinker==1.9.0
+Brotli==1.1.0
+bs4==0.0.1
+cairocffi==1.7.1
+CairoSVG==2.7.1
+captchatools==1.5.0
+ccxt==4.4.75
+certifi==2025.1.31
+cffi==1.16.0
+charset-normalizer==3.4.1
+ckzg==2.0.1
+click==8.1.7
+colorama==0.4.6
+coloredlogs==15.0.1
+cryptography==36.0.1
+cssselect2==0.8.0
+curl_cffi==0.10.0
+customtkinter==5.2.2
+Cython==3.1.2
+cytoolz==1.0.1
+darkdetect==0.8.0
+dateparser==1.1.3
+ddddocr==1.5.6
+defusedxml==0.7.1
+distro==1.9.0
+dnspython==2.4.2
+docutils==0.21.2
+dukpy==0.4.0
+easy-clash-tool==0.0.3
+easy-spider-tool==1.0.16
+editor==1.6.6
+et_xmlfile==2.0.0
+eth-account==0.13.5
+eth-hash==0.7.1
+eth-keyfile==0.8.1
+eth-keys==0.6.1
+eth-rlp==2.2.0
+eth-typing==5.2.0
+eth-utils==5.2.0
+eth_abi==5.2.0
+exceptiongroup==1.2.0
+fake-useragent==1.5.1
+Faker==23.2.1
+fastapi==0.115.12
+Flask==3.1.0
+flatbuffers==25.2.10
+frozenlist==1.5.0
+greenlet==3.1.1
+h11==0.14.0
+h2==4.1.0
+hexbytes==1.3.0
+hpack==4.0.0
+httpcore==1.0.2
+httptools==0.6.4
+httpx==0.27.2
+humanfriendly==10.0
+hyperframe==6.0.1
+idna==3.10
+ifaddr==0.2.0
+importlib-metadata==7.0.0
+inquirer==3.4.0
+itsdangerous==2.2.0
+jieba==0.42.1
+Jinja2==3.1.6
+jiter==0.5.0
+jsonpath==0.82
+jsonschema==4.23.0
+jsonschema-specifications==2023.12.1
+kaitaistruct==0.10
+ldap3==2.9.1
+loguru==0.7.3
+lxml==5.3.0
+magic-filter==1.0.12
+markdown-it-py==3.0.0
+markdown2==2.5.3
+MarkupSafe==3.0.2
+matrix-client==0.4.0
+matrix-nio==0.25.0
+mdurl==0.1.2
+mitmproxy==11.0.2
+mitmproxy-macos==0.10.7
+mitmproxy_rs==0.10.7
+mnemonic==0.21
+MouseInfo==0.1.3
+mpmath==1.3.0
+msgpack==1.1.0
+multidict==6.1.0
+mutf8==1.0.6
+names==0.3.0
+nicegui==2.14.1
+numpy==1.26.4
+ollama==0.4.6
+onnxruntime==1.16.3
+openai==1.42.0
+opencv-python-headless==4.11.0.86
+openpyxl==3.1.5
+orjson==3.10.16
+outcome==1.3.0.post0
+packaging==23.2
+paho-mqtt==2.1.0
+pandas==2.2.3
+parsimonious==0.10.0
+passlib==1.7.4
+patchright==1.50.0
+pillow==11.1.0
+ping3==4.0.4
+playwright==1.46.0
+primp==0.14.0
+prompt_toolkit==3.0.50
+propcache==0.3.0
+protobuf==5.29.3
+pscript==0.7.7
+psycopg2==2.9.9
+publicsuffix2==2.20191221
+py-solc-x==2.0.3
+pyasn1==0.5.1
+pyasn1_modules==0.4.1
+PyAutoGUI==0.9.54
+pycares==4.6.0
+pycparser==2.21
+pycryptodome==3.21.0
+pydantic==2.10.6
+pydantic_core==2.27.2
+pydivert==2.1.0
+pyee==12.1.1
+PyExecJS==1.5.1
+PyGetWindow==0.0.9
+Pygments==2.19.1
+pygpt4all==1.1.0
+pygptj==2.0.3
+pyhttpx==2.10.9
+pyllamacpp==2.4.2
+pylsqpack==0.3.19
+pymongo==4.6.1
+PyMsgBox==1.0.9
+PyNaCl==1.5.0
+pynocaptcha==2.0.52
+pyobjc-core==11.0
+pyobjc-framework-Cocoa==11.0
+pyobjc-framework-Quartz==11.0
+pyOpenSSL==21.0.0
+pyparsing==3.1.1
+pyperclip==1.9.0
+pyppeteer==2.0.0
+PyRect==0.2.0
+PyRSS2Gen==1.1
+PyScreeze==1.0.1
+pyshark==0.6
+PySocks==1.7.1
+python-dateutil==2.9.0.post0
+python-dotenv==1.1.0
+python-engineio==4.12.0
+python-multipart==0.0.20
+python-socketio==5.13.0
+python-socks==2.5.1
+pytweening==1.2.0
+pytz==2025.1
+pyunormalize==16.0.0
+PyYAML==6.0.2
+questionary==2.1.0
+RandomWords==0.4.0
+readchar==4.2.1
+redis==5.0.1
+referencing==0.35.1
+regex==2024.11.6
+requests==2.32.3
+retrying==1.3.4
+rich==13.9.4
+rlp==4.1.0
+rpds-py==0.20.0
+rsa==4.8
+ruamel.yaml==0.18.6
+ruamel.yaml.clib==0.2.12
+rubicon-objc==0.5.0
+runs==1.2.2
+scapy==2.5.0
+schedule==1.2.1
+screeninfo==0.8.1
+selenium==4.16.0
+selenium-wire==5.1.0
+service-identity==24.2.0
+simple-websocket==1.1.0
+six==1.16.0
+sniffio==1.3.0
+sortedcontainers==2.4.0
+soupsieve==2.5
+SQLAlchemy==2.0.36
+starlette==0.46.2
+sui-brownie==1.2.4
+sympy==1.13.3
+tabulate==0.9.0
+tenacity==8.2.3
+termcolor==2.4.0
+tinycss2==1.4.0
+toml==0.10.2
+toolz==1.0.0
+tornado==6.4.2
+tqdm==4.66.1
+trio==0.23.1
+trio-websocket==0.11.1
+types-requests==2.32.0.20250301
+typing_extensions==4.12.2
+tzdata==2025.2
+tzlocal==5.2
+unpaddedbase64==2.1.0
+urllib3==2.3.0
+urwid==2.6.16
+uvicorn==0.29.0
+uvloop==0.21.0
+vbuild==0.8.2
+watchfiles==1.0.5
+wcwidth==0.2.13
+web3==7.8.0
+webencodings==0.5.1
+websockets==13.1
+Werkzeug==3.1.3
+win32_setctime==1.2.0
+wsproto==1.2.0
+xmltodict==0.13.0
+xmod==1.8.1
+yarl==1.18.3
+you-get==0.4.1730
+zipp==3.17.0
+zstandard==0.22.0

+ 33 - 0
siliconflow-api/main.py

@@ -0,0 +1,33 @@
+import httpx
+
+content = "简单讲解一下mvc模型上下文"
+key = "sk-mepewzmlykchrjosberepdvvbnrjbhoamewefnckokitveqf"
+model = "THUDM/GLM-4.1V-9B-Thinking"
+url = "https://api.siliconflow.cn/v1/chat/completions"
+
+headers = {
+    "Authorization": f"Bearer {key}",
+    "Content-Type": "application/json"
+}
+payload = {
+    "model": model,
+    "messages": [{"role": "user", "content": content}]
+}
+
+with httpx.Client(timeout=999) as client:
+    response = client.post(url, headers=headers, json=payload)
+    if response.json()["choices"][0]["message"]["content"]:
+        content = response.json()["choices"][0]["message"]["content"]
+        content = content.split("\n")
+        for i in content:
+            print(i)
+    else:
+        print(response.json())
+
+
+
+
+
+
+
+    

+ 0 - 28
utils/utils_call_free_al.py

@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from openai import OpenAI
-
-
-class FREEAI(object):
-    def call_ai(self, message):
-        try:
-            client = OpenAI(
-                api_key="sk-rM32T5VuyyCFyZGyEe006aEdFe6e4301A7627f7a3973Df17",
-                base_url="https://knox.chat/v1",
-            )
-
-            completion = client.chat.completions.create(
-                model="deepseek-ai/DeepSeek-R1-Distill-Llama-70B-free",
-                messages=[{"role": "user", "content": f"{message}"}],
-                temperature=0.3,
-            )
-
-            result = completion.choices[0].message.content
-
-            return result
-        except Exception as e:
-            print(e)
-
-# free = FREEAI()
-# chat = free.call_kimi('你好')
-# print(chat)

+ 0 - 28
utils/utils_call_kimi.py

@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from openai import OpenAI
-
-
-class KIMI(object):
-    def call_kimi(self, message):
-        try:
-            print('call kimi')
-            client = OpenAI(
-                api_key="sk-Fz9tRF8naXReN2H7zcB1AEtnpOmhonFPJgxlVvQHpql54Ymu",
-                base_url="https://api.moonshot.cn/v1",
-            )
-
-            completion = client.chat.completions.create(
-                model="moonshot-v1-8k",
-                messages=[{"role": "user", "content": f"{message}"}],
-                temperature=0.3,
-            )
-
-            result = completion.choices[0].message.content
-
-            return result
-        except Exception as e:
-            print(e)
-
-    def call_ai(self, message):
-        pass

+ 0 - 38
utils/utils_call_ollama.py

@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-import time
-from ollama import Client as oClient
-
-
-class OllamaChat(object):
-    def call_ollama(self, host, role, text, prompt_words, model='llava:13b', temperature=0.4):
-        message = text + '\n\n' + prompt_words
-        print(f'use model: {model}')
-        try:
-            response_iter = oClient(host=host).chat(model=model,
-                                                    messages=[
-                                                        {'role': 'system', 'content': role},
-                                                        {'role': 'user', 'content': message}
-                                                    ],
-                                                    options={"temperature": temperature},
-                                                    stream=False)
-            return response_iter['message']['content']
-        except Exception as e:
-            print(f"\n发生错误: {e}")
-
-
-# if __name__ == "__main__":
-#     C = OllamaChat()
-#     start_time = time.time()
-#
-#     role = '你是一个聊天机器人'
-#
-#     text = 'hello'
-#
-#     prompt_words = '你好呀'
-#
-#     response_context = C.call_ollama('http://192.168.31.28:11434', role, text, prompt_words, model='llava:13b')
-#     print(response_context)
-#
-#     end_time = time.time()
-#     run_time = end_time - start_time
-#     print(f"程序运行时间:{run_time} 秒\n")

+ 0 - 68
utils/utils_check_base.py

@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-消息模块基础, 用于打开浏览器等相关操作
-"""
-import random
-
-from playwright.sync_api import sync_playwright
-import sys
-import os
-import time
-
-sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
-
-from utils.utils_logs_handle import LogsHandle
-
-
-class CryptoCrawler:
-    def __init__(self, url_list, selectors, check_difference=False, headless=True, proxy=False):
-        self.url_list = url_list
-        self.selectors = selectors
-        self.check_difference = check_difference  # 用于检测数据是否发生变化 (开关)
-        self.data_difference = False  # 用于检测数据是否发生变化 (结果) (默认 否)
-        self.logs_handle = LogsHandle()  # 记录日志
-        self.db = 'CHECK'
-        self.collection = 'check'
-        self.headless = headless
-        self.proxy = proxy
-
-    def main(self):
-        with sync_playwright() as playwright:
-            if self.proxy:
-                browser = playwright.webkit.launch(headless=self.headless, proxy={'server': '127.0.0.1:7890'})
-            else:
-                browser = playwright.webkit.launch(headless=self.headless)
-            context = browser.new_context(viewport={'width': 1920, 'height': 1080})
-            page = context.new_page()
-
-            all_data = []
-
-            for url_info in self.url_list:
-                for key, url in url_info.items():
-                    result_list = []
-                    try:
-                        page.goto(url)
-                        page.wait_for_load_state('load')
-                        time.sleep(5)  # 确保页面完全加载
-
-                        for selector in self.selectors:
-                            element = page.query_selector(selector)
-                            if element:
-                                res = element.text_content().strip()
-                                result_list.append({key: res})
-                    except Exception as e:
-                        err_str = f"Error fetching {url}: {e}"
-                        self.logs_handle.logs_write(self.collection, err_str, 'error', False)
-                        continue
-
-                    if result_list:
-                        all_data.append(result_list)
-
-                    time.sleep(random.randint(1, 3))
-
-            browser.close()
-
-            if all_data:
-                return all_data
-            else:
-                return None

+ 0 - 64
utils/utils_daily_task_scheduler.py

@@ -1,64 +0,0 @@
-# -*- coding: utf-8 -*-
-import os
-import time
-from datetime import datetime
-"""
-TaskScheduler 类用于管理定时任务的执行时间。
-
-该类通过在指定的文件中存储时间戳来记录任务的上次执行时间和下次执行时间。
-它提供了两个主要方法:load_start_time 和 save_start_time。
-load_start_time 方法用于检查是否到达任务的执行时间,如果未到达则返回 0,否则返回上次执行时间。
-save_start_time 方法用于更新下次执行时间,默认为当前时间加上指定的时间间隔(默认为 24 小时)。
-
-Attributes:
-    file_path (str): 存储时间戳的文件路径。
-    time_span (int): 任务执行的时间间隔,默认为 86400 秒(24 小时)。
-
-Methods:
-    load_start_time(): 检查是否到达任务的执行时间。
-    save_start_time(): 更新下次执行时间。
-
-Example:
-    >>> scheduler = TaskScheduler("task_time.txt")
-    >>> last_start_time = scheduler.load_start_time()
-    >>> if last_start_time != 0:
-    >>>     # 执行任务
-    >>> scheduler.save_start_time()
-
-Note:
-    该类假设文件路径是有效的,并且有足够的权限进行读写操作。
-    如果文件不存在,将自动创建并写入当前时间戳。
-"""
-
-class TaskScheduler:
-    def __init__(self, file_path, time_span=86400):
-        self.file_path = file_path
-        self.time_span = time_span
-
-    def load_start_time(self):
-        timestamp_now = int(time.time())
-
-        start_time = 0
-        if not os.path.exists(self.file_path):
-            with open(self.file_path, "w") as file:
-                file.write(str(timestamp_now))
-            print('创建执行时间文件 {}'.format(datetime.fromtimestamp(timestamp_now).strftime('%Y-%m-%d %H:%M:%S')))
-            return timestamp_now
-        else:
-            with open(self.file_path, "r") as file:
-                start_time = int(file.read())
-            if start_time > timestamp_now:
-                print('任务未到执行时间, 下次执行时间: {}'.format(datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S')))
-                return 0
-            print('开始执行定时任务')
-            return start_time
-
-    def save_start_time(self):
-        timestamp_now = int(time.time())
-        date_now = datetime.fromtimestamp(timestamp_now).strftime('%Y-%m-%d %H:%M:%S')
-
-        # 时间戳 +24 小时
-        timestamp_now += self.time_span
-        print('写入下次执行时间: {}'.format(datetime.fromtimestamp(timestamp_now).strftime('%Y-%m-%d %H:%M:%S')))
-        with open(self.file_path, "w") as file:
-            file.write(str(timestamp_now))

+ 0 - 82
utils/utils_logs_handle.py

@@ -1,82 +0,0 @@
-# -*- coding: UTF-8 -*-
-'''
-获取每天日期,新建 logs 文件
-存到 logs 文件夹中
-'''
-import time
-from datetime import datetime
-import os
-import sys
-
-sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
-
-from utils.utils_mongo_handle import MongoHandle
-from utils.utils_send_email import SendEmail
-from base.base_load_config import load_config, get_base_path
-
-config_json = load_config()
-base_project = get_base_path()
-
-
-class LogsHandle(object):
-    def __init__(self):
-        self.now_day = time.strftime('%Y-%m-%d', time.localtime())
-        db = 'logs'
-        collection = 'logs_' + self.now_day
-        self.mongo = MongoHandle(db=db, collection=collection, del_db=False, del_collection=False, auto_remove=0)
-
-    def logs_generate(self):
-        data_to_insert = {
-            "title": "logs",
-            "context": 'generate logs',
-            "state": "create",
-            "create_time": int(time.time()),
-            "create_datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-        }
-
-        self.mongo.collection.insert_one(data_to_insert)
-
-    def logs_send(self):
-        subject = 'auto collection logs'
-        title = 'auto collection - logs: {}'.format(self.now_day)
-        text = ''
-
-        # TODO
-        # 从 mongodb 读取日志, 拼接 text, 发送邮件
-        # 查询所有文档
-        cursor = self.mongo.collection.find()
-        # 遍历结果集
-        for record in cursor:
-            text += "logs_source: {}, logs_detail: {}, state: {} logs_create_time: {}\n\n".format(
-                record.setdefault('title'),
-                record.setdefault('content'),
-                record.setdefault('state'),
-                record.setdefault('create_datetime'),
-            )
-
-        S = SendEmail(subject=subject, title=title, text=text)
-        S.send()
-
-    def logs_write(self, title_source=None, content=None, state=None, send_now=False):
-        data_to_insert = {
-            "title": title_source,
-            "context": content,
-            "state": state,
-            "create_time": int(time.time()),
-            "create_datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-        }
-
-        self.mongo.collection.insert_one(data_to_insert)
-
-        if send_now:
-            subject = 'auto collection'
-            title = 'auto collection - running logs: {}'.format(self.now_day)
-            text = 'logs_source: {}, logs_detail: {}, state: {} logs_create_time: {}'.format(
-                data_to_insert.setdefault('title'),
-                data_to_insert.setdefault('content'),
-                data_to_insert.setdefault('state'),
-                data_to_insert.setdefault('create_datetime'),
-            )
-
-            Send = SendEmail(subject=subject, title=title, text=text)
-            Send.send()

+ 0 - 62
utils/utils_mongo_handle.py

@@ -1,62 +0,0 @@
-# -*-coding: utf-8 -*-
-import pymongo
-from pymongo import errors
-import time
-import sys
-import os
-
-sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
-
-from base.base_load_config import load_config, get_base_path
-
-config_json = load_config()
-base_project = get_base_path()
-
-DB_USER = config_json.get('DB_USER')
-DB_PASSWORD = config_json.get('DB_PASSWORD')
-DB_IP = config_json.get('DB_IP')
-DB_PORT = config_json.get('DB_PORT')
-MONGO_LINK = f'mongodb://{DB_USER}:{DB_PASSWORD}@{DB_IP}:{DB_PORT}/'
-
-
-class MongoHandle(object):
-    def __init__(self, db, collection, del_db=False, del_collection=False, auto_remove=0):
-        self.client = pymongo.MongoClient(MONGO_LINK)
-        self.db = db
-        self.collection = collection
-
-        if del_db and db:
-            # 检查数据库是否存在
-            if db in self.client.list_database_names():
-                # 删除数据库
-                self.client.drop_database(db)
-        self.db = self.client[db]
-
-        if del_collection and self.collection:
-            # 检查集合是否存在
-            if self.collection in self.db.list_collection_names():
-                # 删除集合
-                self.db.drop_collection(collection)
-        self.collection = self.db[collection]
-
-        if auto_remove:
-            self.auto_remove_data(auto_remove)
-
-    def write_data(self, data):
-        self.collection.insert_one(data)
-
-    def load_data(self):
-        # MongoDB 会在第一次写入时自动创建数据库和集合
-        return list(self.collection.find({}, {'_id': False}))
-
-    def auto_remove_data(self, day):
-        for data in self.collection.find({'create_time': {'$lt': int(time.time()) - day * 24 * 60 * 60}}):
-            self.collection.delete_one({'_id': data['_id']})
-
-# if __name__ == '__main__':
-#     mongo = MongoHandle('test_db', 'test_collection', False, False, 0)
-#     mongo.collection.insert_one({'name': 'test'})
-#     mongo.collection.insert_many([{'name': 'test1'}, {'name': 'test2'}])
-#     print(mongo.collection.find_one())
-#     print(mongo.collection.find())
-#     print('done!')

+ 0 - 58
utils/utils_send_email.py

@@ -1,58 +0,0 @@
-# -*- coding: UTF-8 -*-
-import smtplib
-from email.mime.text import MIMEText
-from email.header import Header
-import os
-import sys
-
-sys.path.append(os.path.join(os.path.abspath(__file__).split('auto')[0] + 'auto'))
-
-from base.base_load_config import load_config, get_base_path
-
-config_json = load_config()
-base_project = get_base_path()
-
-PROJECT_NAME = config_json.get('PROJECT_NAME')
-DB_USER = config_json.get('DB_USER')
-DB_PASSWORD = config_json.get('DB_PASSWORD')
-DB_IP = config_json.get('DB_IP')
-DB_PORT = config_json.get('DB_PORT')
-MONGO_LINK = f'mongodb://{DB_USER}:{DB_PASSWORD}@{DB_IP}:{DB_PORT}/'
-MAIL_HOST = config_json.get('MAIL_HOST')
-MAIL_USER = config_json.get('MAIL_USER')
-MAIL_PASS = config_json.get('MAIL_PASS')
-MAIL_SENDER = config_json.get('MAIL_SENDER')
-MAIL_RECEIVERS = config_json.get('MAIL_RECEIVERS')
-
-
-class SendEmail(object):
-    def __init__(self, subject='auto subject', title='auto title', text='auto text') -> None:
-        # 第三方 SMTP 服务
-        self.mail_host = MAIL_HOST  # 设置服务器
-        self.mail_user = MAIL_USER  # 用户名
-        self.mail_pass = MAIL_PASS  # 口令
-
-        self.sender = MAIL_SENDER
-        self.receivers = [MAIL_RECEIVERS]
-
-        self.subject = subject
-        self.title = title
-        self.text = text
-
-    def send(self):
-        message = MIMEText(self.text, 'plain', 'utf-8')
-        message['From'] = Header(self.title, 'utf-8')
-        message['To'] = Header("auto", 'utf-8')
-        message['Subject'] = Header(self.subject, 'utf-8')
-
-        try:
-            smtpObj = smtplib.SMTP_SSL(self.mail_host)
-            smtpObj.login(self.mail_user, self.mail_pass)
-            smtpObj.sendmail(self.sender, self.receivers, message.as_string())
-            print("邮件发送成功")
-        except smtplib.SMTPException as e:
-            print("Error: 无法发送邮件", e)
-
-# if __name__ == '__main__':
-#     email = SendEmail(subject="测试邮件", title="测试邮件", text="这是一封测试邮件。")
-#     email.send()

+ 0 - 40
utils/utils_send_matrix.py

@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-# pip install matrix_client
-
-from matrix_client.client import MatrixClient
-from matrix_client.api import MatrixHttpApi
-
-class MatrixBot:
-    def __init__(self, user, password):
-        self.base_url = "https://matrix.erhe.top"
-        self.user = user
-        self.password = password
-        self.client = MatrixClient("https://matrix.erhe.top")
-        self.token = self.login()
-        self.to = "!CgWvWEnLbKYvhXLvil:chat.abeginner.cn"
-
-    def login(self):
-        self.token = self.client.login(username=self.user, password=self.password)
-        return self.token
-
-    def send_message(self, message):
-        if self.token:
-            try:
-                api = MatrixHttpApi(self.base_url, token=self.token)
-                api.send_message(self.to, message)
-            except Exception as e:
-                print(e)
-                api = MatrixHttpApi(self.base_url, token=self.token)
-                api.send_message(self.to, str(e))
-
-        else:
-            print("Bot is not logged in. Please login first.")
-
-if __name__ == '__main__':
-    # 测试调用
-    user = "message-bot"
-    pw = "aaaAAA111!!!"
-    message = "123987456"
-
-    bot = MatrixBot(user, pw)
-    bot.send_message(message)

+ 0 - 31
utils/utils_send_serverchan.py

@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import httpx
-
-
-class ServerChanNotifier:
-    def __init__(self, title, message):
-        self.serverchan_url = 'https://sctapi.ftqq.com/SCT158272TRDcSniEdGR0TKhqhUl66LPHb.send'
-        self.title = title
-        self.message = message
-
-    def send_message(self):
-        # 构建POST请求的body
-        body = {
-            'text': self.title,
-            'desp': self.message
-        }
-
-        # 发送POST请求
-        with httpx.Client() as client:
-            response = client.post(
-                url=self.serverchan_url,
-                headers={'Content-Type': 'application/x-www-form-urlencoded'},
-                data=body
-            )
-
-        # 检查响应状态码
-        if response.status_code == 200:
-            print('ServerChan Message sent successfully!')
-        else:
-            print('Failed to send message:', response.text)

+ 0 - 219
utils/utils_sync_psql.py

@@ -1,219 +0,0 @@
-# -*- coding: utf-8 -*-
-# 内部数据库同步数据脚本, 用于同一台服务器, 将mongodb数据同步到pgsql
-from datetime import datetime
-from pymongo import MongoClient
-import psycopg2
-from psycopg2 import sql
-
-MONGOLINK = 'mongodb://root:aaaAAA111!!!@erhe.top:38000/'
-PGSQLPARAMS = {
-    # 'database': 'postgres',  # 默认连接到postgres数据库,超级用户数据库
-    'user': 'toor',
-    'password': 'aaaAAA111',  # 替换为你的密码
-    'host': '192.168.31.177',
-    'port': 5432
-}
-
-
-def mongo():
-    # mongodb
-    client = MongoClient(MONGOLINK)
-
-    # 指定数据库名称
-    db_name = 'NEWS'  # 替换为你的数据库名称
-
-    # 选择数据库
-    db = client[db_name]
-
-    # 列出数据库中的所有集合
-    collections = db.list_collection_names()
-
-    all_data = []
-
-    for collection_name in collections:
-        # 选择集合
-        collection = db[collection_name]
-
-        # 读取集合中的所有数据
-        for document in collection.find({}, {'_id': 0}):
-            all_data.append(document)
-
-    sorted_data = []
-
-    if all_data:
-        sorted_data = sorted(all_data, key=lambda x: x['create_time'], reverse=True)
-
-    return sorted_data
-
-
-def pg(sorted_data):
-    table_name = 'auto'
-    PGSQLPARAMS.update({'database': table_name})
-    conn = psycopg2.connect(**PGSQLPARAMS)
-
-    # 记录相同数据, 如果查过指定数量, 则退出程序, 避免浪费资源
-    same_data = 500
-    for doc in sorted_data:
-        if same_data > 0:
-            try:
-                cur = conn.cursor()
-
-                create_time_dt = None
-                if doc.get('create_time'):
-                    create_time_dt = datetime.utcfromtimestamp(doc['create_time'])
-
-                values = {
-                    'name': doc.get('title'),
-                    'context': doc.get('context') or '',
-                    'source_url': doc.get('source_url') or '',
-                    'link': doc.get('line') or '',
-                    'article_type': doc.get('article_type') or '',
-                    'article_source': doc.get('article_source') or '',
-                    'img_url': doc.get('img_url') or '',
-                    'keyword': doc.get('keyword') or '',
-                    'posted_date': doc.get('posted_date') or '',
-                    'create_time_ts': doc.get('create_time') or '',
-                    'create_time': create_time_dt,
-                    'create_datetime': datetime.strptime(doc['create_datetime'], '%Y-%m-%d %H:%M:%S') if doc.get(
-                        'create_datetime') else None
-                }
-
-                # 将create_time转换为适合数据库的时间戳格式
-                create_time_dt = datetime.utcfromtimestamp(values['create_time_ts']) if values[
-                    'create_time_ts'] else None
-                values['create_time'] = create_time_dt
-
-                # 将create_datetime转换为适合数据库的时间戳格式
-                create_datetime_str = doc.get('create_datetime')
-                values['create_datetime'] = datetime.strptime(create_datetime_str,
-                                                              '%Y-%m-%d %H:%M:%S') if create_datetime_str else None
-
-                # 检查数据库中是否已存在相同title的记录
-                check_query = "SELECT id FROM news_info WHERE name = %s;"
-                cur.execute(check_query, (values['name'],))
-
-                # 如果没有找到记录,则插入新记录
-                if not cur.fetchone():
-                    insert_query = """
-                        INSERT INTO news_info (name, context, source_url, link, article_type, article_source, img_url, keyword, posted_date, create_time, create_datetime)
-                        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
-                        """
-                    cur.execute(insert_query, (
-                        values['name'],
-                        values['context'],
-                        values['source_url'],
-                        values['link'],
-                        values['article_type'],
-                        values['article_source'],
-                        values['img_url'],
-                        values['keyword'],
-                        values['posted_date'],
-                        values['create_time'],
-                        values['create_datetime']
-                    ))
-                    conn.commit()
-                    print(f'已保存{values}')
-                else:
-                    same_data -= 1
-            except Exception as e:
-                print("Error during search: ", e)
-            finally:
-                # 关闭游标和连接
-                if 'cur' in locals():
-                    cur.close()
-        else:
-            print('相同数据计数已到最大值, 退出程序')
-            break
-    conn.close()
-
-
-def create_db():
-    db_name = 'postgres'
-
-    PGSQLPARAMS.update({'database': db_name})
-    # 连接到数据库
-    conn = psycopg2.connect(**PGSQLPARAMS)
-    conn.autocommit = True  # 确保创建数据库的命令可以立即执行
-
-    # 创建一个cursor对象
-    cur = conn.cursor()
-
-    # 要创建的数据库名
-    new_db = 'auto'
-    # 数据库所有者
-    owner = 'toor'
-
-    try:
-        # 检查数据库是否存在
-        cur.execute(sql.SQL("SELECT 1 FROM pg_catalog.pg_database WHERE datname = %s"), (new_db,))
-        exists = cur.fetchone()
-        if not exists:
-            # 如果数据库不存在,创建它
-            cur.execute(sql.SQL("CREATE DATABASE {} WITH OWNER {} ENCODING 'UTF8'").format(
-                sql.Identifier(new_db),
-                sql.Identifier(owner)
-            ))
-            print(f"Database '{new_db}' created successfully.")
-        else:
-            print(f"Database '{new_db}' already exists.")
-    except Exception as e:
-        print(f"An error occurred: {e}")
-    finally:
-        # 关闭cursor和连接
-        cur.close()
-        conn.close()
-
-
-def create_table():
-    db_name = 'auto'
-
-    PGSQLPARAMS.update({'database': db_name})
-
-    # 创建数据库连接
-    conn = psycopg2.connect(**PGSQLPARAMS)
-
-    # 创建一个 cursor 对象
-    cur = conn.cursor()
-
-    # 定义表结构的 SQL 语句
-    create_table_sql = """
-    CREATE TABLE IF NOT EXISTS news_info (
-        id SERIAL PRIMARY KEY,
-        name VARCHAR(255) NOT NULL,
-        context TEXT,
-        source_url VARCHAR(255),
-        link VARCHAR(255),
-        article_type VARCHAR(50),
-        article_source VARCHAR(50),
-        img_url VARCHAR(255),
-        keyword VARCHAR(255),
-        posted_date VARCHAR,
-        create_time_ts BIGINT,
-        create_time TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,
-        create_datetime TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP
-    );
-    """
-
-    try:
-        # 执行 SQL 语句来创建表
-        cur.execute(create_table_sql)
-        conn.commit()  # 提交事务
-        print("Table 'auto' created successfully.")
-    except Exception as e:
-        print(f"An error occurred while creating table: {e}")
-        conn.rollback()  # 发生错误时回滚事务
-    finally:
-        # 关闭 cursor 和连接
-        cur.close()
-        conn.close()
-
-
-if __name__ == '__main__':
-    create_db()
-    create_table()
-
-    sorted_data = mongo()
-    if sorted_data:
-        pg(sorted_data)
-
-    print("Done!")

+ 109 - 0
web3/faucet.py

@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+import re
+
+import httpx
+import asyncio
+import json
+import random
+import logging
+from typing import List
+from fake_useragent import UserAgent  # 导入 fake_useragent 模块
+
+# 配置日志
+logging.basicConfig(
+    level=logging.INFO,
+    format='%(asctime)s - %(levelname)s - %(message)s'
+)
+logger = logging.getLogger(__name__)
+
+# 初始化 fake_useragent
+ua = UserAgent()
+
+
+async def send_post_request(wallet: str, timeout: float = 10.0) -> None:
+    """
+    向目标网站发送 POST 请求以领取水。
+
+    Args:
+        wallet: 钱包地址
+        timeout: 请求超时时间(秒)
+    """
+    url = "https://faucet.nerzo.xyz/monad"
+
+    headers = {
+        "accept": "text/x-component",
+        "accept-encoding": "gzip, deflate, br, zstd",
+        "accept-language": "zh-CN,zh;q=0.9",
+        "content-type": "text/plain;charset=UTF-8",
+        "next-action": "405d6e23437f844564e65cdd65851724c449d7f778",
+        "next-router-state-tree": '["",{"children":["(faucet)",{"children":["monad",{"children":["__PAGE__",{},"/monad","refresh"]}]}]},null,null,true]',
+        "origin": "https://faucet.nerzo.xyz",
+        "priority": "u=1, i",
+        "referer": "https://faucet.nerzo.xyz/monad",
+        "sec-ch-ua": '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
+        "sec-ch-ua-mobile": "?0",
+        "sec-ch-ua-platform": '"Windows"',
+        "sec-fetch-dest": "empty",
+        "sec-fetch-mode": "cors",
+        "sec-fetch-site": "same-origin",
+        "user-agent": ua.random,
+        "x-deployment-id": "dpl_DWgqqeB8V4ASD1aCKUqWZwcPwnVd"
+    }
+    payload = json.dumps([wallet])
+
+    async with httpx.AsyncClient(timeout=timeout, proxy={'http://': 'http://127.0.0.1:7890'}) as client:
+        retry = 3
+        while retry > 0:  # 修复了 retry 的逻辑错误
+            try:
+                response = await client.post(url, headers=headers, content=payload)
+                # logger.info(f"Wallet: {wallet} | Status Code: {response.status_code} | Response: {response.text}")
+                logger.info(f"Wallet: {wallet} | Status Code: {response.status_code}")
+                if 'message' in response.text:
+                    message = re.findall(r'"message":"(.*?)"', response.text)[0]
+                    logger.info(f"Wallet: {wallet} | Message: {message}")
+                return response
+            except httpx.RequestError as e:
+                logger.error(f"Wallet: {wallet} | Request failed: {e}")
+                retry -= 1
+
+                if retry <= 0:
+                    return None
+
+
+async def main(wallet_list: List[str], min_delay: float = 5.0, max_delay: float = 8.0) -> None:
+    """
+    批量处理钱包地址,发送 POST 请求,并添加随机延时。
+
+    Args:
+        wallet_list: 钱包地址列表
+        min_delay: 最小延时(秒)
+        max_delay: 最大延时(秒)
+    """
+    for i, wallet in enumerate(wallet_list, 1):
+        logger.info(f"Processing wallet {i}/{len(wallet_list)}: {wallet}")
+        await send_post_request(wallet)
+        # 在最后一个钱包之前添加随机延时
+        if i < len(wallet_list):
+            delay = random.uniform(min_delay, max_delay)
+            logger.info(f"Waiting for {delay:.2f} seconds before next request")
+            await asyncio.sleep(delay)
+
+
+if __name__ == "__main__":
+    wallet_list = [
+        '0xe50B77Cd771243b8Ae1d6ce33b4E13ECC5Fa28a6',
+        '0x9ea2ECAD4090E32916e03b77d7C75CbF6C8E0A55',
+        '0xE8A4b0C04300154DC9B1D0e565Ba70F996614690',
+        '0x1b623c5d70c93b437d93c305bf2cfa389095f636',
+        '0x06D25c3e0E1F753ac0486a3f8aaD7259149656cB',
+        '0x15cFEE34Ca4541CAc9a1c4B6F6aB47A65877E240',
+        '0x7aBF0dA8Ac07B6dE7206e467988455E1AD0b60B5',
+        '0xF736f45d4663a8D8DfF7EFA55b1Cf6Fe38D026c8',
+        '0x83173eECf3a6d9ABB79682568e16c2eAd361620e',
+        '0xa401b85B4849Fc7610Bd180cc937859C78528F47',
+        '0x10A43E7Fe77E2D84adBeC26cF0bFc6f403841266',
+        '0x70D5EE1DfddD3726f0D71F4CD5a8Ef43aC651a75'
+    ]
+    random.shuffle(wallet_list)
+    asyncio.run(main(wallet_list))
+    print("done")