Evilmass
commited on
Commit
·
65d3d39
1
Parent(s):
5448935
new build
Browse files- .gitignore +16 -0
- Dockerfile +40 -0
- __init__.py +14 -0
- _playwright/[no_use]aliyundrive.py +79 -0
- _playwright/bilibili.py +123 -0
- _playwright/tsdm.py +116 -0
- _playwright/v2ex.py +72 -0
- _playwright/vits.py +66 -0
- _playwright/wuaipojie.py +60 -0
- _requests/[no_use]restart_vits_server.py +62 -0
- _requests/aliyundrive.py +121 -0
- api.py +65 -0
- app.py +100 -0
- config/settings_prod.py +108 -0
- index.html +57 -0
- option_logger.py +12 -0
- option_mysql.py +54 -0
- requirements.txt +15 -0
- utils.py +181 -0
.gitignore
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cache
|
| 2 |
+
__pycache__/
|
| 3 |
+
sync.ffs_db
|
| 4 |
+
*.pyc
|
| 5 |
+
|
| 6 |
+
# file
|
| 7 |
+
cookie/
|
| 8 |
+
!cookie/.gitkeep
|
| 9 |
+
log/
|
| 10 |
+
!log/.gitkeep
|
| 11 |
+
|
| 12 |
+
# dev
|
| 13 |
+
config/settings_dev.py
|
| 14 |
+
|
| 15 |
+
# test
|
| 16 |
+
test.py
|
Dockerfile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# build cache
|
| 2 |
+
FROM python:3.9-slim-bullseye as builder
|
| 3 |
+
|
| 4 |
+
WORKDIR /tmp
|
| 5 |
+
|
| 6 |
+
# depends
|
| 7 |
+
RUN apt-get update -y
|
| 8 |
+
|
| 9 |
+
# pip
|
| 10 |
+
COPY ./requirements.txt /tmp/requirements.txt
|
| 11 |
+
RUN pip install -r /tmp/requirements.txt
|
| 12 |
+
|
| 13 |
+
# playwright
|
| 14 |
+
RUN playwright install-deps
|
| 15 |
+
|
| 16 |
+
# Set up a new user named "user" with user ID 1000
|
| 17 |
+
RUN useradd -m -u 1000 user
|
| 18 |
+
|
| 19 |
+
# Switch to the "user" user
|
| 20 |
+
USER user
|
| 21 |
+
|
| 22 |
+
# Set home to the user's home directory
|
| 23 |
+
ENV HOME=/home/user \
|
| 24 |
+
PATH=/home/user/.local/bin:$PATH
|
| 25 |
+
|
| 26 |
+
# Set the working directory to the user's home directory
|
| 27 |
+
WORKDIR $HOME/app
|
| 28 |
+
|
| 29 |
+
RUN mkdir $HOME/app/cookie $HOME/app/log $HOME/app/_playwright $HOME/app/config
|
| 30 |
+
|
| 31 |
+
# Try and run pip command after setting the user with `USER user` to avoid permission issues with Python
|
| 32 |
+
RUN playwright install chromium firefox
|
| 33 |
+
|
| 34 |
+
# use cache build
|
| 35 |
+
FROM builder
|
| 36 |
+
|
| 37 |
+
# Copy the current directory contents into the container at $HOME/app setting the owner to the user
|
| 38 |
+
COPY --chown=user . $HOME/app
|
| 39 |
+
|
| 40 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 全局变量 DIR_PATH 不能在其他地方用同一个命名,会被替换
|
| 2 |
+
import sys
|
| 3 |
+
from os.path import abspath, dirname
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
DEBUG = False
|
| 7 |
+
if DEBUG:
|
| 8 |
+
DIR_PATH = abspath(dirname(__file__))
|
| 9 |
+
sys.path.append(DIR_PATH)
|
| 10 |
+
from config.settings_dev import *
|
| 11 |
+
else:
|
| 12 |
+
DIR_PATH = "/home/user/app"
|
| 13 |
+
sys.path.append(DIR_PATH)
|
| 14 |
+
from config.settings_prod import *
|
_playwright/[no_use]aliyundrive.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
import sys
|
| 3 |
+
import asyncio
|
| 4 |
+
|
| 5 |
+
from os.path import abspath, dirname, join
|
| 6 |
+
from playwright.async_api import async_playwright
|
| 7 |
+
|
| 8 |
+
sys.path.append(join(dirname(abspath(__file__)), "../"))
|
| 9 |
+
|
| 10 |
+
from utils import push_msg
|
| 11 |
+
from __init__ import (
|
| 12 |
+
browser_headless,
|
| 13 |
+
browser_proxy,
|
| 14 |
+
aliyundrive_url,
|
| 15 |
+
aliyundrive_cookie_file,
|
| 16 |
+
aliyundrive_title,
|
| 17 |
+
aliyundrive_logger,
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
# 判断登录状态
|
| 22 |
+
async def is_login(page):
|
| 23 |
+
await page.goto(aliyundrive_url)
|
| 24 |
+
# page.locator("li").filter(has_text="回收站").get_by_role("img").click()
|
| 25 |
+
if page.get_by_text("回收站").is_visible(): # 加 await 就会在页面加载完成前跳过
|
| 26 |
+
aliyundrive_logger.info("登录成功")
|
| 27 |
+
return True
|
| 28 |
+
else:
|
| 29 |
+
stderr = "Cookie 过期"
|
| 30 |
+
aliyundrive_logger.error(stderr)
|
| 31 |
+
push_msg(aliyundrive_title, stderr)
|
| 32 |
+
return False
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
# 签到
|
| 36 |
+
async def sign(page):
|
| 37 |
+
msg = []
|
| 38 |
+
|
| 39 |
+
if not await is_login(page):
|
| 40 |
+
return "aliyundrive_not_login"
|
| 41 |
+
|
| 42 |
+
# await page.pause()
|
| 43 |
+
|
| 44 |
+
if page.get_by_text("待领取").is_visible():
|
| 45 |
+
sign_res = "今日已签到"
|
| 46 |
+
aliyundrive_logger.info(sign_res)
|
| 47 |
+
msg.append(sign_res)
|
| 48 |
+
# 领取奖励
|
| 49 |
+
await page.get_by_text("待领取").click()
|
| 50 |
+
reward_res = "今日领取奖励成功"
|
| 51 |
+
aliyundrive_logger.info(reward_res)
|
| 52 |
+
elif page.get_by_text("待签到").is_visible():
|
| 53 |
+
await page.get_by_text("待签到").click()
|
| 54 |
+
sign_res = "签到成功"
|
| 55 |
+
aliyundrive_logger.info(sign_res)
|
| 56 |
+
msg.append(sign_res)
|
| 57 |
+
else:
|
| 58 |
+
reward_res = "今日奖励已领取"
|
| 59 |
+
aliyundrive_logger.info(reward_res)
|
| 60 |
+
return "\n".join(msg)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
async def main():
|
| 64 |
+
async with async_playwright() as playwright:
|
| 65 |
+
browser = await playwright.chromium.launch(headless=browser_headless)
|
| 66 |
+
context = await browser.new_context(storage_state=aliyundrive_cookie_file)
|
| 67 |
+
page = await context.new_page()
|
| 68 |
+
task = asyncio.create_task(sign(page))
|
| 69 |
+
await asyncio.gather(task)
|
| 70 |
+
# 退出
|
| 71 |
+
await page.close()
|
| 72 |
+
await browser.close()
|
| 73 |
+
# 推送
|
| 74 |
+
result = task.result()
|
| 75 |
+
push_msg(aliyundrive_title, "\n".join([result]))
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
if __name__ == "__main__":
|
| 79 |
+
asyncio.run(main())
|
_playwright/bilibili.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
import sys
|
| 3 |
+
import asyncio
|
| 4 |
+
|
| 5 |
+
from datetime import datetime
|
| 6 |
+
from os.path import abspath, dirname, join
|
| 7 |
+
from playwright.async_api import async_playwright
|
| 8 |
+
|
| 9 |
+
sys.path.append(join(dirname(abspath(__file__)), "../"))
|
| 10 |
+
from utils import push_msg, get_bilibili_live_rooms_from_pi
|
| 11 |
+
from __init__ import (
|
| 12 |
+
browser_headless,
|
| 13 |
+
browser_proxy,
|
| 14 |
+
bilibili_url,
|
| 15 |
+
bilibili_sign_url,
|
| 16 |
+
bilibili_live_url,
|
| 17 |
+
bilibili_cookie_file,
|
| 18 |
+
bilibili_title,
|
| 19 |
+
bilibili_logger,
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
bilibili_live_rooms = get_bilibili_live_rooms_from_pi()
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# 判断登录状态
|
| 26 |
+
async def is_login(page):
|
| 27 |
+
await page.goto(bilibili_url)
|
| 28 |
+
if await page.get_by_text("修改资料").is_visible(timeout=2000):
|
| 29 |
+
bilibili_logger.info("登录成功")
|
| 30 |
+
return True
|
| 31 |
+
else:
|
| 32 |
+
stderr = "Cookie 过期"
|
| 33 |
+
bilibili_logger.error(stderr)
|
| 34 |
+
push_msg(bilibili_title, stderr)
|
| 35 |
+
return False
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
# 签到
|
| 39 |
+
async def sign(page):
|
| 40 |
+
msg = []
|
| 41 |
+
|
| 42 |
+
if not await is_login(page):
|
| 43 |
+
return "bilibili_not_login"
|
| 44 |
+
|
| 45 |
+
await page.goto(bilibili_sign_url)
|
| 46 |
+
if await page.get_by_text("无法重复签到").is_visible():
|
| 47 |
+
sign_res = f"签到时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n签到状态:今日已签到"
|
| 48 |
+
bilibili_logger.info(sign_res)
|
| 49 |
+
msg.append(sign_res)
|
| 50 |
+
elif await page.get_by_text('"code":0').is_visible():
|
| 51 |
+
sign_res = f"签到时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n签到状态:签到成功"
|
| 52 |
+
bilibili_logger.info(sign_res)
|
| 53 |
+
msg.append(sign_res)
|
| 54 |
+
else:
|
| 55 |
+
sign_res = f"签到失败"
|
| 56 |
+
bilibili_logger.error(sign_res)
|
| 57 |
+
push_msg(bilibili_title, sign_res)
|
| 58 |
+
msg.append(sign_res)
|
| 59 |
+
|
| 60 |
+
return "\n".join(msg)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
# 直播间打卡
|
| 64 |
+
async def live(page):
|
| 65 |
+
msg = []
|
| 66 |
+
|
| 67 |
+
if not await is_login(page):
|
| 68 |
+
return "bilibili_not_login"
|
| 69 |
+
|
| 70 |
+
for room_id in list(bilibili_live_rooms.keys()):
|
| 71 |
+
await page.goto(f"{bilibili_live_url}/{str(room_id)}")
|
| 72 |
+
# 输入框选择 xpath 绝对定位
|
| 73 |
+
input_box = await page.locator(
|
| 74 |
+
"xpath=/html/body/div[3]/main/div[1]/section[1]/div[3]/div[12]/div/div[2]/div[2]/textarea",
|
| 75 |
+
)
|
| 76 |
+
# 输入内容
|
| 77 |
+
await input_box.fill("1")
|
| 78 |
+
# 发送按钮
|
| 79 |
+
send_button = await page.locator(
|
| 80 |
+
"xpath=/html/body/div[3]/main/div[1]/section[1]/div[3]/div[12]/div/div[3]/div/button/span"
|
| 81 |
+
)
|
| 82 |
+
if await send_button.is_visible():
|
| 83 |
+
# 点击发送按钮
|
| 84 |
+
await send_button.click()
|
| 85 |
+
room_msg = (
|
| 86 |
+
f"直播间:【{bilibili_live_rooms[room_id]}】打卡成功,打卡时间:【{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}】"
|
| 87 |
+
)
|
| 88 |
+
bilibili_logger.info(room_msg)
|
| 89 |
+
else:
|
| 90 |
+
room_msg = (
|
| 91 |
+
f"直播间:【{bilibili_live_rooms[room_id]}】打卡失败,打卡时间:【{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}】"
|
| 92 |
+
)
|
| 93 |
+
bilibili_logger.error(room_msg)
|
| 94 |
+
msg.append(room_msg)
|
| 95 |
+
|
| 96 |
+
return "\n".join(msg)
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
async def bilibili_sign():
|
| 100 |
+
async with async_playwright() as playwright:
|
| 101 |
+
browser = await playwright.firefox.launch(headless=browser_headless)
|
| 102 |
+
context = await browser.new_context(storage_state=bilibili_cookie_file)
|
| 103 |
+
# 签到
|
| 104 |
+
sign_page = await context.new_page()
|
| 105 |
+
sign_task = asyncio.create_task(sign(sign_page))
|
| 106 |
+
await asyncio.gather(sign_task)
|
| 107 |
+
await sign_page.close()
|
| 108 |
+
# 直播间打卡
|
| 109 |
+
live_page = await context.new_page()
|
| 110 |
+
live_task = asyncio.create_task(live(live_page))
|
| 111 |
+
await asyncio.gather(live_task)
|
| 112 |
+
await live_page.close()
|
| 113 |
+
# 退出
|
| 114 |
+
await browser.close()
|
| 115 |
+
# 推送
|
| 116 |
+
sign_result = sign_task.result()
|
| 117 |
+
live_result = live_task.result()
|
| 118 |
+
# ""分割两个服务的消息
|
| 119 |
+
push_msg(bilibili_title, "\n".join([sign_result, "", live_result]))
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
if __name__ == "__main__":
|
| 123 |
+
asyncio.run(bilibili_sign())
|
_playwright/tsdm.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
import sys
|
| 3 |
+
import random
|
| 4 |
+
import asyncio
|
| 5 |
+
|
| 6 |
+
from os.path import abspath, dirname, join
|
| 7 |
+
from playwright.async_api import async_playwright
|
| 8 |
+
|
| 9 |
+
sys.path.append(join(dirname(abspath(__file__)), "../"))
|
| 10 |
+
|
| 11 |
+
from utils import push_msg
|
| 12 |
+
from __init__ import (
|
| 13 |
+
browser_headless,
|
| 14 |
+
browser_proxy,
|
| 15 |
+
tsdm_url,
|
| 16 |
+
tsdm_sign_url,
|
| 17 |
+
tsdm_cliwork_url,
|
| 18 |
+
tsdm_plugin_id,
|
| 19 |
+
tsdm_minds,
|
| 20 |
+
tsdm_cookie_file,
|
| 21 |
+
tsdm_title,
|
| 22 |
+
tsdm_logger,
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
# 判断登录状态
|
| 27 |
+
async def is_login(page):
|
| 28 |
+
await page.goto(tsdm_url)
|
| 29 |
+
if await page.get_by_text("用户组").is_visible():
|
| 30 |
+
tsdm_logger.info("登录成功")
|
| 31 |
+
return True
|
| 32 |
+
else:
|
| 33 |
+
stderr = "Cookie 过期"
|
| 34 |
+
tsdm_logger.error(stderr)
|
| 35 |
+
push_msg(tsdm_title, stderr)
|
| 36 |
+
return False
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
# 签到
|
| 40 |
+
async def sign(page):
|
| 41 |
+
msg = []
|
| 42 |
+
|
| 43 |
+
if not await is_login(page):
|
| 44 |
+
return "tsdm_not_login"
|
| 45 |
+
|
| 46 |
+
# 签到
|
| 47 |
+
await page.goto(tsdm_sign_url)
|
| 48 |
+
if await page.get_by_text("今天已签到").is_visible():
|
| 49 |
+
sign_res = "今天已签到"
|
| 50 |
+
tsdm_logger.info(sign_res)
|
| 51 |
+
msg.append(sign_res)
|
| 52 |
+
else:
|
| 53 |
+
mind = random.choice(list(tsdm_minds.values()))
|
| 54 |
+
tsdm_logger.info(f"签到心情选择:{mind}")
|
| 55 |
+
await page.locator(
|
| 56 |
+
"#ct > div > div.bm.mtn > div.bm_c > form > select"
|
| 57 |
+
).select_option(label=mind)
|
| 58 |
+
await page.get_by_label("不想填写").check()
|
| 59 |
+
await page.get_by_text("点我签到!").click()
|
| 60 |
+
sign_res = "签到成功"
|
| 61 |
+
tsdm_logger.info(sign_res)
|
| 62 |
+
msg.append(sign_res)
|
| 63 |
+
|
| 64 |
+
return "\n".join(msg)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
async def cliwork(page):
|
| 68 |
+
msg = []
|
| 69 |
+
|
| 70 |
+
if not await is_login(page):
|
| 71 |
+
return "tsdm_not_login"
|
| 72 |
+
|
| 73 |
+
# 打工
|
| 74 |
+
await page.goto(tsdm_url) # 切换回电脑版
|
| 75 |
+
await page.goto(tsdm_cliwork_url)
|
| 76 |
+
if await page.get_by_text("您需要等待").is_visible():
|
| 77 |
+
has_work = "今天已打工"
|
| 78 |
+
tsdm_logger.info(has_work)
|
| 79 |
+
msg.append(has_work)
|
| 80 |
+
else:
|
| 81 |
+
for pid in tsdm_plugin_id:
|
| 82 |
+
await page.locator(f"#np_advid{pid} > a > img").click()
|
| 83 |
+
await page.bring_to_front() # 回到第一个标签
|
| 84 |
+
await page.locator("#workstart").click() # 领取奖励
|
| 85 |
+
work_res = "打工成功"
|
| 86 |
+
tsdm_logger.info(work_res)
|
| 87 |
+
msg.append(work_res)
|
| 88 |
+
|
| 89 |
+
return "\n".join(msg)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
async def tsdm_sign():
|
| 93 |
+
async with async_playwright() as playwright:
|
| 94 |
+
browser = await playwright.chromium.launch(headless=browser_headless)
|
| 95 |
+
context = await browser.new_context(storage_state=tsdm_cookie_file)
|
| 96 |
+
# 签到
|
| 97 |
+
sign_page = await context.new_page()
|
| 98 |
+
sign_task = asyncio.create_task(sign(sign_page))
|
| 99 |
+
await asyncio.gather(sign_task)
|
| 100 |
+
await sign_page.close()
|
| 101 |
+
# 打工
|
| 102 |
+
cliwork_page = await context.new_page()
|
| 103 |
+
cliwork_task = asyncio.create_task(cliwork(cliwork_page))
|
| 104 |
+
await asyncio.gather(cliwork_task)
|
| 105 |
+
await cliwork_page.close()
|
| 106 |
+
# 退出
|
| 107 |
+
await browser.close()
|
| 108 |
+
# 推送
|
| 109 |
+
sign_result = sign_task.result()
|
| 110 |
+
cliwork_result = cliwork_task.result()
|
| 111 |
+
# ""分割两个服务的消息
|
| 112 |
+
push_msg(tsdm_title, "\n".join([sign_result, "", cliwork_result]))
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
if __name__ == "__main__":
|
| 116 |
+
asyncio.run(tsdm_sign())
|
_playwright/v2ex.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
import sys
|
| 3 |
+
import asyncio
|
| 4 |
+
|
| 5 |
+
from os.path import abspath, dirname, join
|
| 6 |
+
from playwright.async_api import async_playwright
|
| 7 |
+
|
| 8 |
+
sys.path.append(join(dirname(abspath(__file__)), "../"))
|
| 9 |
+
|
| 10 |
+
from utils import push_msg
|
| 11 |
+
from __init__ import (
|
| 12 |
+
browser_headless,
|
| 13 |
+
browser_proxy,
|
| 14 |
+
v2ex_url,
|
| 15 |
+
v2ex_sign_url,
|
| 16 |
+
v2ex_cookie_file,
|
| 17 |
+
v2ex_title,
|
| 18 |
+
v2ex_logger,
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
# 判断登录状态
|
| 23 |
+
async def is_login(page):
|
| 24 |
+
await page.goto(v2ex_url)
|
| 25 |
+
if await page.get_by_text("记事本").is_visible():
|
| 26 |
+
v2ex_logger.info("登录成功")
|
| 27 |
+
return True
|
| 28 |
+
else:
|
| 29 |
+
stderr = "Cookie 过期"
|
| 30 |
+
v2ex_logger.error(stderr)
|
| 31 |
+
push_msg(v2ex_title, stderr)
|
| 32 |
+
return False
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
# 签到
|
| 36 |
+
async def sign(page):
|
| 37 |
+
msg = []
|
| 38 |
+
|
| 39 |
+
if not await is_login(page):
|
| 40 |
+
return "v2ex_not_login"
|
| 41 |
+
|
| 42 |
+
await page.goto(v2ex_sign_url)
|
| 43 |
+
if await page.get_by_text("每日登录奖励已领取").is_visible():
|
| 44 |
+
sign_res = "今日铜币已领取"
|
| 45 |
+
v2ex_logger.info(sign_res)
|
| 46 |
+
msg.append(sign_res)
|
| 47 |
+
else:
|
| 48 |
+
await page.get_by_text("领取 X 铜币").click()
|
| 49 |
+
sign_res = "领取铜币成功"
|
| 50 |
+
v2ex_logger.info(sign_res)
|
| 51 |
+
msg.append(sign_res)
|
| 52 |
+
|
| 53 |
+
return "\n".join(msg)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
async def v2ex_sign():
|
| 57 |
+
async with async_playwright() as playwright:
|
| 58 |
+
browser = await playwright.chromium.launch(headless=browser_headless)
|
| 59 |
+
context = await browser.new_context(storage_state=v2ex_cookie_file)
|
| 60 |
+
sign_page = await context.new_page()
|
| 61 |
+
sign_task = asyncio.create_task(sign(sign_page))
|
| 62 |
+
await asyncio.gather(sign_task)
|
| 63 |
+
await sign_page.close()
|
| 64 |
+
# 退出
|
| 65 |
+
await browser.close()
|
| 66 |
+
# 推送
|
| 67 |
+
sign_result = sign_task.result()
|
| 68 |
+
push_msg(v2ex_title, "\n".join([sign_result]))
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
if __name__ == "__main__":
|
| 72 |
+
asyncio.run(v2ex_sign())
|
_playwright/vits.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
import sys
|
| 3 |
+
import asyncio
|
| 4 |
+
|
| 5 |
+
from os.path import abspath, dirname, join
|
| 6 |
+
from playwright.async_api import async_playwright
|
| 7 |
+
|
| 8 |
+
sys.path.append(join(dirname(abspath(__file__)), "../"))
|
| 9 |
+
|
| 10 |
+
from utils import push_msg
|
| 11 |
+
from __init__ import (
|
| 12 |
+
browser_headless,
|
| 13 |
+
browser_proxy,
|
| 14 |
+
vits_url,
|
| 15 |
+
vits_cookie_file,
|
| 16 |
+
vits_title,
|
| 17 |
+
vits_logger,
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
# 判断登录状态
|
| 22 |
+
async def is_login(page):
|
| 23 |
+
await page.goto(vits_url)
|
| 24 |
+
if await page.get_by_text("Pause Space").is_visible():
|
| 25 |
+
vits_logger.info("登录成功")
|
| 26 |
+
return True
|
| 27 |
+
else:
|
| 28 |
+
stderr = "Cookie 过期"
|
| 29 |
+
vits_logger.error(stderr)
|
| 30 |
+
push_msg(vits_title, stderr)
|
| 31 |
+
return False
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
# 签到
|
| 35 |
+
async def sign(page):
|
| 36 |
+
if not await is_login(page):
|
| 37 |
+
return "vits_not_login"
|
| 38 |
+
|
| 39 |
+
if await page.get_by_role("button", name="Restart space").is_visible():
|
| 40 |
+
await page.get_by_role("button", name="Restart space").click()
|
| 41 |
+
sign_res = "restart vits server success"
|
| 42 |
+
vits_logger.info(sign_res)
|
| 43 |
+
else:
|
| 44 |
+
sign_res = "restart vits server failed"
|
| 45 |
+
vits_logger.error(sign_res)
|
| 46 |
+
|
| 47 |
+
return sign_res
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
async def vits_sign():
|
| 51 |
+
async with async_playwright() as playwright:
|
| 52 |
+
browser = await playwright.chromium.launch(headless=browser_headless)
|
| 53 |
+
context = await browser.new_context(storage_state=vits_cookie_file)
|
| 54 |
+
sign_page = await context.new_page()
|
| 55 |
+
sign_task = asyncio.create_task(sign(sign_page))
|
| 56 |
+
await asyncio.gather(sign_task)
|
| 57 |
+
await sign_page.close()
|
| 58 |
+
# 退出
|
| 59 |
+
await browser.close()
|
| 60 |
+
# 推送
|
| 61 |
+
sign_result = sign_task.result()
|
| 62 |
+
push_msg(vits_title, sign_result)
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
if __name__ == "__main__":
|
| 66 |
+
asyncio.run(vits_sign())
|
_playwright/wuaipojie.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
import sys
|
| 3 |
+
import asyncio
|
| 4 |
+
|
| 5 |
+
from os.path import abspath, dirname, join
|
| 6 |
+
from playwright.async_api import async_playwright
|
| 7 |
+
|
| 8 |
+
sys.path.append(join(dirname(abspath(__file__)), "../"))
|
| 9 |
+
|
| 10 |
+
from utils import push_msg
|
| 11 |
+
from __init__ import (
|
| 12 |
+
browser_headless,
|
| 13 |
+
browser_proxy,
|
| 14 |
+
wuaipojie_url,
|
| 15 |
+
wuaipojie_sign_url,
|
| 16 |
+
wuaipojie_cookie_file,
|
| 17 |
+
wuaipojie_title,
|
| 18 |
+
wuaipojie_logger,
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
async def sign(page):
|
| 23 |
+
await page.goto(wuaipojie_url)
|
| 24 |
+
|
| 25 |
+
# 判断登录状态
|
| 26 |
+
if await page.get_by_text("提醒").is_enabled():
|
| 27 |
+
wuaipojie_logger.info("登录成功")
|
| 28 |
+
else:
|
| 29 |
+
msg = "Cookie 过期"
|
| 30 |
+
wuaipojie_logger.error(msg)
|
| 31 |
+
return
|
| 32 |
+
|
| 33 |
+
# 签到
|
| 34 |
+
if await page.get_by_text("请下期再来").is_enabled():
|
| 35 |
+
msg = "今天已签到"
|
| 36 |
+
wuaipojie_logger.info(msg)
|
| 37 |
+
else:
|
| 38 |
+
await page.goto(wuaipojie_sign_url)
|
| 39 |
+
msg = "签到成功"
|
| 40 |
+
wuaipojie_logger.info(msg)
|
| 41 |
+
return msg
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
async def wuaipojie_sign():
|
| 45 |
+
async with async_playwright() as playwright:
|
| 46 |
+
browser = await playwright.chromium.launch(headless=browser_headless)
|
| 47 |
+
context = await browser.new_context(storage_state=wuaipojie_cookie_file)
|
| 48 |
+
sign_page = await context.new_page()
|
| 49 |
+
sign_task = asyncio.create_task(sign(sign_page))
|
| 50 |
+
await asyncio.gather(sign_task)
|
| 51 |
+
await sign_page.close()
|
| 52 |
+
# 退出
|
| 53 |
+
await browser.close()
|
| 54 |
+
# 推送
|
| 55 |
+
sign_result = sign_task.result()
|
| 56 |
+
push_msg(wuaipojie_title, "\n".join([sign_result]))
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
if __name__ == "__main__":
|
| 60 |
+
asyncio.run(wuaipojie_sign())
|
_requests/[no_use]restart_vits_server.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import re
|
| 5 |
+
import requests
|
| 6 |
+
|
| 7 |
+
from os.path import abspath, dirname, join
|
| 8 |
+
|
| 9 |
+
# conf
|
| 10 |
+
title = "Huggingface"
|
| 11 |
+
session = requests.Session()
|
| 12 |
+
|
| 13 |
+
# from utils import push_msg
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def restart_vits_server():
|
| 17 |
+
headers = {
|
| 18 |
+
"authority": "huggingface.co",
|
| 19 |
+
"origin": "https://huggingface.co",
|
| 20 |
+
"referer": "https://huggingface.co/login",
|
| 21 |
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
|
| 22 |
+
}
|
| 23 |
+
data = {
|
| 24 |
+
"username": os.environ.get("hf_username"),
|
| 25 |
+
"password": os.environ.get("hf_password"),
|
| 26 |
+
}
|
| 27 |
+
session.post("https://huggingface.co/login", headers=headers, data=data)
|
| 28 |
+
rsp = session.get(
|
| 29 |
+
"https://huggingface.co/spaces/evi0mo/vits-fastapi-server/settings"
|
| 30 |
+
)
|
| 31 |
+
csrf = re.findall(r"name=\"csrf\" value=\"(.*?)\">", rsp.text)[0]
|
| 32 |
+
|
| 33 |
+
res = "init"
|
| 34 |
+
restart_headers = {
|
| 35 |
+
"authority": "huggingface.co",
|
| 36 |
+
"origin": "https://huggingface.co",
|
| 37 |
+
"referer": "https://huggingface.co/spaces/evi0mo/vits-fastapi-server/settings",
|
| 38 |
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
restart_data = {"csrf": csrf}
|
| 42 |
+
session.post(
|
| 43 |
+
"https://huggingface.co/spaces/evi0mo/vits-fastapi-server/restart?factory=false",
|
| 44 |
+
headers=restart_headers,
|
| 45 |
+
data=restart_data,
|
| 46 |
+
)
|
| 47 |
+
# check
|
| 48 |
+
check = session.get(
|
| 49 |
+
"https://huggingface.co/api/spaces/evi0mo/vits-fastapi-server/runtime"
|
| 50 |
+
)
|
| 51 |
+
if check.json()["stage"] == "RUNNING_BUILDING":
|
| 52 |
+
res = "success"
|
| 53 |
+
vits_logger.info(res)
|
| 54 |
+
else:
|
| 55 |
+
res = "failed"
|
| 56 |
+
vits_logger.error(res)
|
| 57 |
+
|
| 58 |
+
# push_msg(title, res)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
if __name__ == "__main__":
|
| 62 |
+
restart_vits_server()
|
_requests/aliyundrive.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 接口参考:https://github.com/Anonym-w/autoSigninAliyun/blob/main/autoSignin.js
|
| 2 |
+
import sys
|
| 3 |
+
import requests
|
| 4 |
+
|
| 5 |
+
from os.path import abspath, dirname, join
|
| 6 |
+
|
| 7 |
+
# conf
|
| 8 |
+
sys.path.append(join(dirname(abspath(__file__)), "../"))
|
| 9 |
+
from utils import (
|
| 10 |
+
push_msg,
|
| 11 |
+
get_aliyundrive_refresh_token,
|
| 12 |
+
update_aliyundrive_access_token,
|
| 13 |
+
)
|
| 14 |
+
from __init__ import (
|
| 15 |
+
aliyundrive_nickname_url,
|
| 16 |
+
aliyundrive_signin_url,
|
| 17 |
+
aliyundrive_access_token_url,
|
| 18 |
+
aliyundrive_reward_url,
|
| 19 |
+
aliyundrive_title,
|
| 20 |
+
aliyundrive_logger,
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
# session
|
| 24 |
+
headers = {"message-Type": "application/json"}
|
| 25 |
+
session = requests.Session()
|
| 26 |
+
query_body = {}
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def get_refresh_token():
|
| 30 |
+
# local storage only work in browser
|
| 31 |
+
return False
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def validate_access_token():
|
| 35 |
+
# token只有三小时有效期,所以定时任务刷新间隔为三小时
|
| 36 |
+
# 从树莓派获取 refresh_token
|
| 37 |
+
refresh_token = get_aliyundrive_refresh_token()
|
| 38 |
+
# 查询结构体
|
| 39 |
+
query_body.update({"grant_type": "refresh_token", "refresh_token": refresh_token})
|
| 40 |
+
# validate
|
| 41 |
+
resp = session.post(aliyundrive_access_token_url, headers=headers, json=query_body)
|
| 42 |
+
if resp.status_code != 200:
|
| 43 |
+
msg = "阿里云 access_token 失效"
|
| 44 |
+
aliyundrive_logger.error(msg)
|
| 45 |
+
push_msg(aliyundrive_title, msg)
|
| 46 |
+
else:
|
| 47 |
+
aliyundrive_logger.info("阿里云 access_token 有效")
|
| 48 |
+
new_access_token = resp.json()["access_token"]
|
| 49 |
+
update_aliyundrive_access_token(new_access_token)
|
| 50 |
+
headers["Authorization"] = f"Bearer {new_access_token}"
|
| 51 |
+
return new_access_token
|
| 52 |
+
return False
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def get_aliyun_nickname():
|
| 56 |
+
nickname = False
|
| 57 |
+
# 获取用户名
|
| 58 |
+
user_res = session.post(aliyundrive_nickname_url, headers=headers, json=query_body)
|
| 59 |
+
if user_res.status_code == 200:
|
| 60 |
+
msg = f"获取用户名成功,stdout:{user_res.json()}"
|
| 61 |
+
nickname = user_res.json()["nick_name"]
|
| 62 |
+
else:
|
| 63 |
+
msg = f"获取用户名失败,stderr:{user_res.json()}"
|
| 64 |
+
aliyundrive_logger.error(msg)
|
| 65 |
+
push_msg(title=aliyundrive_title, message=msg)
|
| 66 |
+
return nickname
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def sign():
|
| 70 |
+
# 签到
|
| 71 |
+
sign_res = session.post(aliyundrive_signin_url, headers=headers, json=query_body)
|
| 72 |
+
if sign_res.status_code != 200:
|
| 73 |
+
sign_msg = f"阿里云盘签到失败,stderr:{sign_res.json()}"
|
| 74 |
+
aliyundrive_logger.error(sign_msg)
|
| 75 |
+
push_msg(title=aliyundrive_title, message=sign_msg)
|
| 76 |
+
else:
|
| 77 |
+
sign_msg = f"阿里云盘签到成功"
|
| 78 |
+
aliyundrive_logger.info(sign_msg)
|
| 79 |
+
sign_jsondata = sign_res.json()
|
| 80 |
+
# 已签到天数
|
| 81 |
+
signin_count = sign_jsondata["result"]["signInCount"]
|
| 82 |
+
# 当天签到信息,数组下标 -1
|
| 83 |
+
current_sign_info = sign_jsondata["result"]["signInLogs"][signin_count - 1]
|
| 84 |
+
# 当天签到获得的奖励信息
|
| 85 |
+
reward_name = current_sign_info["reward"]["name"]
|
| 86 |
+
reward_description = current_sign_info["reward"]["description"]
|
| 87 |
+
curent_reward = f"{reward_name}{reward_description}"
|
| 88 |
+
# 是否已领取奖励,bool
|
| 89 |
+
is_reward = current_sign_info["isReward"]
|
| 90 |
+
return is_reward, signin_count, curent_reward
|
| 91 |
+
return False
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
# 领取奖励
|
| 95 |
+
def get_reward(signin_count):
|
| 96 |
+
query_body.update({"signInDay": signin_count})
|
| 97 |
+
reward_res = session.post(aliyundrive_reward_url, headers=headers, json=query_body)
|
| 98 |
+
if reward_res.status_code == 200:
|
| 99 |
+
aliyundrive_logger.info("领取奖励成功")
|
| 100 |
+
else:
|
| 101 |
+
reward_msg = f"领取奖励失败,stderr:{reward_res.json()}"
|
| 102 |
+
aliyundrive_logger.error(reward_msg)
|
| 103 |
+
push_msg(title=aliyundrive_title, message=reward_msg)
|
| 104 |
+
return reward_msg
|
| 105 |
+
return False
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def aliyundrive_sign():
|
| 109 |
+
validate_access_token()
|
| 110 |
+
nickname = get_aliyun_nickname()
|
| 111 |
+
is_reward, signin_count, curent_reward = sign()
|
| 112 |
+
if not is_reward:
|
| 113 |
+
get_reward(signin_count)
|
| 114 |
+
message = f"{nickname} 签到成功,本月累计签到 {signin_count} 天\n本次签到获得:{curent_reward}"
|
| 115 |
+
aliyundrive_logger.info(message)
|
| 116 |
+
push_msg(title=aliyundrive_title, message=message)
|
| 117 |
+
return message
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
if __name__ == "__main__":
|
| 121 |
+
aliyundrive_sign()
|
api.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
https://github.com/agronholm/apscheduler/blob/3.x/examples/schedulers/asyncio_.py
|
| 3 |
+
"""
|
| 4 |
+
import asyncio
|
| 5 |
+
from collections.abc import Callable, Iterable, Mapping
|
| 6 |
+
import threading
|
| 7 |
+
from typing import Any
|
| 8 |
+
import pytz
|
| 9 |
+
|
| 10 |
+
from datetime import datetime
|
| 11 |
+
from apscheduler.schedulers.background import BackgroundScheduler
|
| 12 |
+
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
| 13 |
+
from loguru import logger
|
| 14 |
+
|
| 15 |
+
from _playwright.bilibili import bilibili_sign
|
| 16 |
+
from _playwright.v2ex import v2ex_sign
|
| 17 |
+
from _playwright.vits import vits_sign
|
| 18 |
+
from _playwright.tsdm import tsdm_sign
|
| 19 |
+
from _playwright.wuaipojie import wuaipojie_sign
|
| 20 |
+
from _requests.aliyundrive import aliyundrive_sign
|
| 21 |
+
from utils import get_cookie_from_pi
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def tick():
|
| 25 |
+
logger.debug(f"Tick! The time is: {datetime.now():%Y-%m-%d %H:%M:%S}")
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def run_scheduler(loop):
|
| 29 |
+
asyncio.set_event_loop(loop)
|
| 30 |
+
# pi
|
| 31 |
+
get_cookie_from_pi()
|
| 32 |
+
# add task
|
| 33 |
+
sign_scheduler = AsyncIOScheduler()
|
| 34 |
+
sign_scheduler.configure(timezone=pytz.timezone("Asia/Shanghai"))
|
| 35 |
+
sign_scheduler.add_job(tick, "cron", hour="*/1")
|
| 36 |
+
sign_scheduler.add_job(bilibili_sign, "cron", hour=5, minute=1, second=0)
|
| 37 |
+
sign_scheduler.add_job(v2ex_sign, "cron", hour=5, minute=2, second=0)
|
| 38 |
+
sign_scheduler.add_job(tsdm_sign, "cron", hour=5, minute=3, second=0)
|
| 39 |
+
sign_scheduler.add_job(wuaipojie_sign, "cron", hour=5, minute=4, second=0)
|
| 40 |
+
sign_scheduler.add_job(vits_sign, "cron", hour=5, minute=5, second=0)
|
| 41 |
+
sign_scheduler.add_job(aliyundrive_sign, "cron", hour="*/2")
|
| 42 |
+
sign_scheduler.start()
|
| 43 |
+
try:
|
| 44 |
+
asyncio.get_event_loop().run_forever()
|
| 45 |
+
except (KeyboardInterrupt, SystemExit):
|
| 46 |
+
pass
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def start_daemon_scheduler(loop):
|
| 50 |
+
t = threading.Thread(target=run_scheduler, args=(loop,), name="schedule", daemon=True)
|
| 51 |
+
t.start()
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
async def kill_daemon_scheduler():
|
| 55 |
+
loop = asyncio._get_running_loop()
|
| 56 |
+
loop.stop()
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
if __name__ == "__main__":
|
| 60 |
+
schedule_loop = asyncio.new_event_loop()
|
| 61 |
+
start_daemon_scheduler(schedule_loop)
|
| 62 |
+
import time
|
| 63 |
+
|
| 64 |
+
time.sleep(3)
|
| 65 |
+
asyncio.run_coroutine_threadsafe(kill_daemon_scheduler(), loop=schedule_loop)
|
app.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding: utf-8
|
| 2 |
+
import asyncio
|
| 3 |
+
import os
|
| 4 |
+
import requests
|
| 5 |
+
|
| 6 |
+
from os.path import join
|
| 7 |
+
from uvicorn import run
|
| 8 |
+
from fastapi import FastAPI
|
| 9 |
+
from fastapi.responses import Response
|
| 10 |
+
from loguru import logger
|
| 11 |
+
|
| 12 |
+
from __init__ import DIR_PATH, api_token
|
| 13 |
+
from utils import push_msg
|
| 14 |
+
from api import start_daemon_scheduler, kill_daemon_scheduler
|
| 15 |
+
|
| 16 |
+
schedule_loop = asyncio.new_event_loop()
|
| 17 |
+
|
| 18 |
+
app = FastAPI()
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
@app.get("/")
|
| 22 |
+
def home():
|
| 23 |
+
html_content = open("index.html").read()
|
| 24 |
+
return Response(content=html_content, status_code=200)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# 开启定时任务
|
| 28 |
+
@app.get("/run")
|
| 29 |
+
def do_run(token: str):
|
| 30 |
+
if token != api_token:
|
| 31 |
+
return {"code": 422}
|
| 32 |
+
|
| 33 |
+
start_daemon_scheduler(schedule_loop)
|
| 34 |
+
res = {"code": 0, "data": "start scheduler"}
|
| 35 |
+
return res
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
# 开启定时任务
|
| 39 |
+
@app.get("/kill")
|
| 40 |
+
def do_kill(token: str):
|
| 41 |
+
if token != api_token:
|
| 42 |
+
return {"code": 422}
|
| 43 |
+
|
| 44 |
+
asyncio.run_coroutine_threadsafe(kill_daemon_scheduler(), loop=schedule_loop)
|
| 45 |
+
res = {"code": 0, "data": "kill scheduler"}
|
| 46 |
+
return res
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
# 查询日志
|
| 50 |
+
@app.get("/log")
|
| 51 |
+
async def do_log(token: str, name: str):
|
| 52 |
+
if token != api_token:
|
| 53 |
+
return {"code": 422}
|
| 54 |
+
|
| 55 |
+
log_file = join(DIR_PATH, f"log/{name}.log")
|
| 56 |
+
with open(log_file, "r", encoding="utf-8") as f:
|
| 57 |
+
data = f.read()
|
| 58 |
+
|
| 59 |
+
res = {"code": 200, "data": data}
|
| 60 |
+
return res
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
# 列出当前目录所有文件
|
| 64 |
+
@app.get("/path")
|
| 65 |
+
def do_path(token: str):
|
| 66 |
+
if token != api_token:
|
| 67 |
+
return {"code": 422}
|
| 68 |
+
|
| 69 |
+
data = []
|
| 70 |
+
for root, _, files in os.walk(DIR_PATH):
|
| 71 |
+
for file in files:
|
| 72 |
+
data.append(join(root, file))
|
| 73 |
+
res = {"code": 0, "data": data}
|
| 74 |
+
return res
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
# 测试连通性
|
| 78 |
+
@app.get("/ip")
|
| 79 |
+
def do_ip(token: str):
|
| 80 |
+
if token != api_token:
|
| 81 |
+
return {"code": 422}
|
| 82 |
+
|
| 83 |
+
ip = requests.get("https://checkip.amazonaws.com").text.strip()
|
| 84 |
+
logger.debug(f"checking ip: {ip}")
|
| 85 |
+
res = {"code": 0, "ip": ip}
|
| 86 |
+
return res
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
# 测试推送消息
|
| 90 |
+
@app.get("/push")
|
| 91 |
+
def do_push(token: str):
|
| 92 |
+
if token != api_token:
|
| 93 |
+
return {"code": 422}
|
| 94 |
+
|
| 95 |
+
data = push_msg("send from huggingface docker", "hello world")
|
| 96 |
+
return {"code": 0, "data": data}
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
if __name__ == "__main__":
|
| 100 |
+
run("app:app", host="0.0.0.0", port=8000, reload=True)
|
config/settings_prod.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding: utf-8
|
| 2 |
+
import os
|
| 3 |
+
import sys
|
| 4 |
+
from os.path import join
|
| 5 |
+
|
| 6 |
+
# 添加根目录引用
|
| 7 |
+
# 不要用同一个 DIR_PATH 命名,会影响 __init__ 中的全局变量
|
| 8 |
+
PROD_PATH = "/home/user/app"
|
| 9 |
+
sys.path.append(PROD_PATH)
|
| 10 |
+
|
| 11 |
+
from option_logger import register_logger
|
| 12 |
+
|
| 13 |
+
# playwright
|
| 14 |
+
browser_headless = True
|
| 15 |
+
browser_proxy = {"server": None}
|
| 16 |
+
user_agent = (
|
| 17 |
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
|
| 18 |
+
)
|
| 19 |
+
ignore_https_errors = True
|
| 20 |
+
|
| 21 |
+
# api
|
| 22 |
+
api_token = os.environ.get("token")
|
| 23 |
+
|
| 24 |
+
# gotify
|
| 25 |
+
gotify_host = os.environ.get("gotify_host")
|
| 26 |
+
gotify_port = os.environ.get("gotify_port")
|
| 27 |
+
gotify_token = os.environ.get("gotify_token")
|
| 28 |
+
|
| 29 |
+
# mysql
|
| 30 |
+
mysql_option = {
|
| 31 |
+
"HOST": os.environ.get("DB_HOST"),
|
| 32 |
+
"PORT": int(os.environ.get("DB_PORT")),
|
| 33 |
+
"USERNAME": os.environ.get("DB_USERNAME"),
|
| 34 |
+
"PASSWORD": os.environ.get("DB_PASSWORD"),
|
| 35 |
+
"DATABASE": os.environ.get("DB_DATABASE"),
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
# for fastapi
|
| 39 |
+
logfile_mapping = {
|
| 40 |
+
"vits": join(PROD_PATH, "log/vits.log"),
|
| 41 |
+
"bilibili": join(PROD_PATH, "log/bilibili.log"),
|
| 42 |
+
"v2ex": join(PROD_PATH, "log/v2ex.log"),
|
| 43 |
+
"tsdm": join(PROD_PATH, "log/tsdm.log"),
|
| 44 |
+
"wuaipojie": join(PROD_PATH, "log/wuaipojie.log"),
|
| 45 |
+
"aliyundrive": join(PROD_PATH, "log/aliyundrive.log"),
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
# vits
|
| 49 |
+
vits_title = "vits server"
|
| 50 |
+
vits_url = "https://huggingface.co/spaces/evi0mo/vits-fastapi-server/settings"
|
| 51 |
+
vits_logger = register_logger("vits", logfile_mapping["vits"])
|
| 52 |
+
vits_cookie_file = join(PROD_PATH, "cookie/vits.json")
|
| 53 |
+
hf_username = os.environ.get("hf_username")
|
| 54 |
+
hf_password = os.environ.get("hf_password")
|
| 55 |
+
|
| 56 |
+
# wuaipojie
|
| 57 |
+
wuaipojie_title = "wuaipojie"
|
| 58 |
+
wuaipojie_logger = register_logger("wuaipojie", logfile_mapping["wuaipojie"])
|
| 59 |
+
wuaipojie_cookie_file = join(PROD_PATH, "cookie/wuaipojie.json")
|
| 60 |
+
wuaipojie_url = "https://www.52pojie.cn/home.php?mod=task&do=apply&id=2"
|
| 61 |
+
wuaipojie_sign_url = "https://www.52pojie.cn/home.php?mod=task&do=draw&id=2"
|
| 62 |
+
|
| 63 |
+
# v2ex
|
| 64 |
+
v2ex_title = "V2EX"
|
| 65 |
+
v2ex_logger = register_logger("v2ex", logfile_mapping["v2ex"])
|
| 66 |
+
v2ex_cookie_file = join(PROD_PATH, "cookie/v2ex.json")
|
| 67 |
+
v2ex_url = "https://v2ex.com"
|
| 68 |
+
v2ex_sign_url = "https://v2ex.com/mission/daily"
|
| 69 |
+
|
| 70 |
+
# bilibili
|
| 71 |
+
bilibili_title = "Bilibili"
|
| 72 |
+
bilibili_logger = register_logger("bilibili", logfile_mapping["bilibili"])
|
| 73 |
+
bilibili_cookie_file = join(PROD_PATH, "cookie/bilibili.json")
|
| 74 |
+
bilibili_url = "https://account.bilibili.com/account/home"
|
| 75 |
+
bilibili_sign_url = "https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign" # 签到地址
|
| 76 |
+
bilibili_live_url = "https://live.bilibili.com" # 直播间地址
|
| 77 |
+
bilibili_live_rooms = os.environ.get("bilibili_live_rooms")
|
| 78 |
+
|
| 79 |
+
# tsdm
|
| 80 |
+
tsdm_title = "天使动漫"
|
| 81 |
+
tsdm_logger = register_logger("tsdm", logfile_mapping["tsdm"])
|
| 82 |
+
tsdm_cookie_file = join(PROD_PATH, "cookie/tsdm.json")
|
| 83 |
+
tsdm_url = "https://www.tsdm39.com/forum.php?mobile=no" # 首页
|
| 84 |
+
tsdm_sign_url = "https://www.tsdm39.com/plugin.php?id=dsu_paulsign:sign&mobile=yes&simpletype=yes" # 手机精简版签到地址
|
| 85 |
+
tsdm_cliwork_url = "https://www.tsdm39.com/plugin.php?id=np_cliworkdz:work" # 打工地址
|
| 86 |
+
tsdm_plugin_id = [1, 2, 4, 6, 7, 9] # 打工插件 id
|
| 87 |
+
tsdm_minds = {
|
| 88 |
+
"kx": "开心",
|
| 89 |
+
"ng": "难过",
|
| 90 |
+
"ym": "郁闷",
|
| 91 |
+
"wl": "无聊",
|
| 92 |
+
"nu": "怒",
|
| 93 |
+
"ch": "擦汗",
|
| 94 |
+
"fd": "奋斗",
|
| 95 |
+
"yl": "慵懒",
|
| 96 |
+
"shuai": "衰",
|
| 97 |
+
} # 心情
|
| 98 |
+
|
| 99 |
+
# aliyundrive
|
| 100 |
+
aliyundrive_title = "阿里云盘"
|
| 101 |
+
aliyundrive_logger = register_logger("aliyundrive", logfile_mapping["aliyundrive"])
|
| 102 |
+
aliyundrive_refresh_token = os.environ.get("aliyundrive_refresh_token")
|
| 103 |
+
aliyundrive_cookie_file = join(PROD_PATH, "cookie/aliyundrive.json")
|
| 104 |
+
aliyundrive_url = "https://www.aliyundrive.com/drive"
|
| 105 |
+
aliyundrive_nickname_url = "https://api.aliyundrive.com/adrive/v2/user/get"
|
| 106 |
+
aliyundrive_access_token_url = "https://auth.aliyundrive.com/v2/account/token"
|
| 107 |
+
aliyundrive_signin_url = "https://member.aliyundrive.com/v1/activity/sign_in_list"
|
| 108 |
+
aliyundrive_reward_url = "https://member.aliyundrive.com/v1/activity/sign_in_reward"
|
index.html
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<html>
|
| 2 |
+
<!-- Title -->
|
| 3 |
+
|
| 4 |
+
<head>
|
| 5 |
+
<title>FastAPI Hello World</title>
|
| 6 |
+
</head>
|
| 7 |
+
|
| 8 |
+
<!-- Stylesheet -->
|
| 9 |
+
<style>
|
| 10 |
+
body {
|
| 11 |
+
font-family: Arial, Helvetica, sans-serif;
|
| 12 |
+
font-size: 16px;
|
| 13 |
+
line-height: 1.5;
|
| 14 |
+
margin: 0;
|
| 15 |
+
padding: 0;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
h1 {
|
| 19 |
+
font-size: 2em;
|
| 20 |
+
margin: 0;
|
| 21 |
+
padding: 0;
|
| 22 |
+
/* Center */
|
| 23 |
+
text-align: center;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
h3 {
|
| 27 |
+
margin: 0;
|
| 28 |
+
padding: 0;
|
| 29 |
+
/* Center */
|
| 30 |
+
text-align: center;
|
| 31 |
+
}
|
| 32 |
+
</style>
|
| 33 |
+
|
| 34 |
+
<!-- Body -->
|
| 35 |
+
|
| 36 |
+
<body>
|
| 37 |
+
<h1>FastAPI Hello World Example</h1>
|
| 38 |
+
|
| 39 |
+
<h3>
|
| 40 |
+
This is a simple example of a FastAPI Hello World application using Docker. See the links below for more
|
| 41 |
+
information.
|
| 42 |
+
</h3>
|
| 43 |
+
<!-- List of different relevant links and descriptions about them -->
|
| 44 |
+
|
| 45 |
+
<div style="margin: 0 auto; width: 50%;">
|
| 46 |
+
|
| 47 |
+
<ul>
|
| 48 |
+
<!-- Link to self /docs -->
|
| 49 |
+
<li>
|
| 50 |
+
<a href="/docs">This API's Interactive Swaggar Docs</a> - Try the API out here!
|
| 51 |
+
</li>
|
| 52 |
+
</ul>
|
| 53 |
+
</div>
|
| 54 |
+
|
| 55 |
+
</body>
|
| 56 |
+
|
| 57 |
+
</html>
|
option_logger.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from loguru import logger
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
# 根据名称注册多个 logger
|
| 5 |
+
def register_logger(bind_name, file_path):
|
| 6 |
+
logger.add(
|
| 7 |
+
file_path,
|
| 8 |
+
format="{time:YYYY-MM-DD HH:mm:ss} {level} {message}",
|
| 9 |
+
filter=lambda record: record["extra"].get("name") == bind_name,
|
| 10 |
+
)
|
| 11 |
+
new_logger = logger.bind(name=bind_name)
|
| 12 |
+
return new_logger
|
option_mysql.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pymysql
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class OptionMysql(object):
|
| 5 |
+
def __init__(self, options):
|
| 6 |
+
host = options["HOST"]
|
| 7 |
+
user = options["USERNAME"]
|
| 8 |
+
password = options["PASSWORD"]
|
| 9 |
+
database = options["DATABASE"]
|
| 10 |
+
port = options["PORT"]
|
| 11 |
+
charset = "utf8"
|
| 12 |
+
# 连接数据库
|
| 13 |
+
self.conn = pymysql.connect(
|
| 14 |
+
host=host,
|
| 15 |
+
port=port,
|
| 16 |
+
user=user,
|
| 17 |
+
password=password,
|
| 18 |
+
database=database,
|
| 19 |
+
charset=charset,
|
| 20 |
+
)
|
| 21 |
+
# 创建游标
|
| 22 |
+
self.cur = self.conn.cursor()
|
| 23 |
+
self.dict_cur = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
|
| 24 |
+
|
| 25 |
+
def __exit__(self):
|
| 26 |
+
self.cur.close()
|
| 27 |
+
self.dict_cur.close()
|
| 28 |
+
self.conn.close()
|
| 29 |
+
|
| 30 |
+
def get_dict_data(self, sql, params=[]):
|
| 31 |
+
"""查询,返回字典类型"""
|
| 32 |
+
try:
|
| 33 |
+
if params:
|
| 34 |
+
self.dict_cur.execute(sql, params)
|
| 35 |
+
else:
|
| 36 |
+
self.dict_cur.execute(sql)
|
| 37 |
+
data = self.dict_cur.fetchall()
|
| 38 |
+
return data
|
| 39 |
+
except Exception as e:
|
| 40 |
+
self.conn.rollback()
|
| 41 |
+
raise e
|
| 42 |
+
|
| 43 |
+
def update_data(self, sql, params=[]):
|
| 44 |
+
"""更新"""
|
| 45 |
+
try:
|
| 46 |
+
if not params:
|
| 47 |
+
self.cur.execute(sql)
|
| 48 |
+
else:
|
| 49 |
+
self.cur.execute(sql, params)
|
| 50 |
+
self.conn.commit()
|
| 51 |
+
except Exception as e:
|
| 52 |
+
self.conn.rollback()
|
| 53 |
+
raise e
|
| 54 |
+
return True
|
requirements.txt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
apscheduler
|
| 2 |
+
psutil
|
| 3 |
+
gotify
|
| 4 |
+
loguru
|
| 5 |
+
playwright
|
| 6 |
+
playwright-stealth
|
| 7 |
+
requests
|
| 8 |
+
tld
|
| 9 |
+
uvicorn
|
| 10 |
+
fastapi
|
| 11 |
+
pytz
|
| 12 |
+
pymysql
|
| 13 |
+
#ddddocr
|
| 14 |
+
#Pillow
|
| 15 |
+
#selenium
|
utils.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding:utf-8
|
| 2 |
+
import os
|
| 3 |
+
import sys
|
| 4 |
+
import socket
|
| 5 |
+
import asyncio
|
| 6 |
+
import psutil
|
| 7 |
+
import requests
|
| 8 |
+
|
| 9 |
+
from os.path import join
|
| 10 |
+
from tld import get_tld
|
| 11 |
+
from loguru import logger
|
| 12 |
+
from playwright.async_api import async_playwright, Page
|
| 13 |
+
from playwright_stealth import stealth_async
|
| 14 |
+
|
| 15 |
+
from option_mysql import OptionMysql
|
| 16 |
+
from __init__ import (
|
| 17 |
+
gotify_host,
|
| 18 |
+
gotify_port,
|
| 19 |
+
gotify_token,
|
| 20 |
+
mysql_option,
|
| 21 |
+
DIR_PATH,
|
| 22 |
+
DEBUG,
|
| 23 |
+
browser_headless,
|
| 24 |
+
browser_proxy,
|
| 25 |
+
ignore_https_errors,
|
| 26 |
+
user_agent,
|
| 27 |
+
aliyundrive_access_token_url,
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
# webdriver
|
| 32 |
+
async def init_page(storage_state=None, browser_type: str = "chromium") -> Page:
|
| 33 |
+
if browser_type not in ("chromium", "firefox", "webkit"):
|
| 34 |
+
raise TypeError("unspported browser")
|
| 35 |
+
|
| 36 |
+
async with async_playwright() as p:
|
| 37 |
+
if browser_type == "chromium":
|
| 38 |
+
browser = await p.chromium.launch(headless=browser_headless)
|
| 39 |
+
elif browser_type == "firefox":
|
| 40 |
+
browser = await p.firefox.launch(headless=browser_headless)
|
| 41 |
+
else:
|
| 42 |
+
logger.error("初始化浏览器失败")
|
| 43 |
+
exit(-1)
|
| 44 |
+
|
| 45 |
+
context = await browser.new_context(
|
| 46 |
+
proxy=browser_proxy,
|
| 47 |
+
ignore_https_errors=ignore_https_errors,
|
| 48 |
+
user_agent=user_agent,
|
| 49 |
+
)
|
| 50 |
+
# 从文件读取 Cookie
|
| 51 |
+
context = await browser.new_context(storage_state=storage_state)
|
| 52 |
+
page = await context.new_page()
|
| 53 |
+
# 隐藏 webdriver 特征
|
| 54 |
+
await stealth_async(page)
|
| 55 |
+
# await page.pause() # async 跳出上下文就会 playwright._impl._api_types.Error: Connection closed
|
| 56 |
+
await goto_github(page)
|
| 57 |
+
await dump_cookie(page) # 创建函数:一个 browser 对应一个 context、page,在 with 内完成多个任务
|
| 58 |
+
await browser.close()
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
async def goto_github(page):
|
| 62 |
+
await page.goto("https://github.com")
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
async def dump_cookie(page):
|
| 66 |
+
# url = "https://www.52pojie.cn/home.php"
|
| 67 |
+
# url = "https://v2ex.com"
|
| 68 |
+
# url = "https://www.bilibili.com"
|
| 69 |
+
# url = "https://www.tsdm39.com/forum.php?mobile=no"
|
| 70 |
+
# url = "https://www.aliyundrive.com/drive"
|
| 71 |
+
url = "https://huggingface.co/login"
|
| 72 |
+
save_cookie = join(DIR_PATH, f"{get_domain(url)}.json")
|
| 73 |
+
await page.goto(url)
|
| 74 |
+
logger.debug(DIR_PATH)
|
| 75 |
+
await page.screenshot(
|
| 76 |
+
path=join(DIR_PATH, "screenshot.png"),
|
| 77 |
+
full_page=True,
|
| 78 |
+
) # 截图
|
| 79 |
+
while input("input c to continue: ") != "c": # 阻塞等待填写登录信息
|
| 80 |
+
continue
|
| 81 |
+
await page.context.storage_state(path=save_cookie) # 保存 Cookie 到文件
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
# 获取容器内 IP
|
| 85 |
+
def get_local_ip():
|
| 86 |
+
net_card_info = []
|
| 87 |
+
info = psutil.net_if_addrs()
|
| 88 |
+
for k, v in info.items():
|
| 89 |
+
for item in v:
|
| 90 |
+
if item[0] == 2 and not item[1] == "127.0.0.1":
|
| 91 |
+
net_card_info.append(item[1])
|
| 92 |
+
local_ip = net_card_info[0]
|
| 93 |
+
return local_ip
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
# 从 url 获取域名
|
| 97 |
+
def get_domain(url: str) -> str:
|
| 98 |
+
result = get_tld(url, as_object=True)
|
| 99 |
+
domain = result.domain
|
| 100 |
+
return domain
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
# 从域名获取 IP
|
| 104 |
+
def get_domain_ip(host: str) -> str:
|
| 105 |
+
domain_ip = socket.gethostbyname(host)
|
| 106 |
+
return domain_ip
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
# gotify 推送
|
| 110 |
+
def push_msg(title, message):
|
| 111 |
+
gotify_ip = get_domain_ip(gotify_host)
|
| 112 |
+
url = f"http://{gotify_ip}:{gotify_port}/message?token={gotify_token}"
|
| 113 |
+
data = {"title": title, "message": message, "priority": 10}
|
| 114 |
+
with requests.post(url, json=data) as resp:
|
| 115 |
+
return resp.json()
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def get_bilibili_live_rooms_from_pi() -> dict:
|
| 119 |
+
logger.info("getting bilibili_live_rooms from pi")
|
| 120 |
+
bilibili_live_rooms = {}
|
| 121 |
+
mysql = OptionMysql(mysql_option)
|
| 122 |
+
sql = f"SELECT room_id, username FROM live_rooms"
|
| 123 |
+
data = mysql.get_dict_data(sql)
|
| 124 |
+
if data:
|
| 125 |
+
for d in data:
|
| 126 |
+
bilibili_live_rooms[d["room_id"]] = d["username"]
|
| 127 |
+
return bilibili_live_rooms
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
def get_cookie_from_pi() -> dict:
|
| 131 |
+
logger.info("getting cookie from pi")
|
| 132 |
+
mysql = OptionMysql(mysql_option)
|
| 133 |
+
sql = f"SELECT cookie_name, cookie_value FROM cookie"
|
| 134 |
+
data = mysql.get_dict_data(sql)
|
| 135 |
+
for d in data:
|
| 136 |
+
log_file = join(DIR_PATH, f"cookie/{d['cookie_name']}.json")
|
| 137 |
+
with open(log_file, "w") as lf:
|
| 138 |
+
lf.write(d["cookie_value"])
|
| 139 |
+
return data[0]["cookie_name"]
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
def get_aliyundrive_refresh_token():
|
| 143 |
+
mysql = OptionMysql(mysql_option)
|
| 144 |
+
sql = f"SELECT token FROM aliyundrive WHERE id=1"
|
| 145 |
+
data = mysql.get_dict_data(sql)
|
| 146 |
+
if data:
|
| 147 |
+
logger.info("获取阿里云盘 refresh_token 成功")
|
| 148 |
+
return data[0]["token"]
|
| 149 |
+
return False
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def update_aliyundrive_access_token(access_token):
|
| 153 |
+
mysql = OptionMysql(mysql_option)
|
| 154 |
+
sql = f"UPDATE aliyundrive SET token=%s WHERE id=2"
|
| 155 |
+
data = mysql.update_data(sql, [access_token])
|
| 156 |
+
if data:
|
| 157 |
+
logger.info("update aliyundrive access token")
|
| 158 |
+
return True
|
| 159 |
+
return False
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
def get_log(log_file: str) -> str:
|
| 163 |
+
with open(log_file, "r", encoding="utf-8") as f:
|
| 164 |
+
data = f.read()
|
| 165 |
+
return data
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
if __name__ == "__main__":
|
| 169 |
+
logger.debug(f"DEBUG Mode: {DEBUG}")
|
| 170 |
+
logger.debug(f"DIR_PATH: {DIR_PATH}")
|
| 171 |
+
# asyncio.run(init_page())
|
| 172 |
+
# logger.debug(f"get_domain_ip: {get_domain_ip(gotify_host)}")
|
| 173 |
+
# logger.debug(f'get_domain: {get_domain("https://github.com")}')
|
| 174 |
+
# logger.debug(f"list_path: {list_path()}")
|
| 175 |
+
# logger.debug(f'push_msg: {push_msg("utils.py", "hello world")}')
|
| 176 |
+
# logger.debug(f"get_aliyun_token_from_pi(): {get_aliyun_token_from_pi()}")
|
| 177 |
+
# logger.debug(f"get_bilibili_live_rooms_from_pi(): {get_bilibili_live_rooms_from_pi()}")
|
| 178 |
+
# logger.debug(f"get_cookie_from_pi(): {get_cookie_from_pi()}")
|
| 179 |
+
# logger.debug(f'get_cron_log(): {get_cron_log("log/tsdm.log")}')
|
| 180 |
+
# logger.debug(f"get_aliyundrive_access_token: {get_aliyundrive_access_token()}")
|
| 181 |
+
# logger.debug(f"update_aliyundrive_access_token: {update_aliyundrive_access_token('123')}")
|