mirror of
https://github.com/PaiGramTeam/PamGram.git
synced 2024-11-25 15:42:14 +00:00
✨ 添加自动签到相关功能
添加自动签到相关请求和定时任务 并没写插件 )
This commit is contained in:
parent
542a2a1fab
commit
9c208f7b4c
11
apps/sign/__init__.py
Normal file
11
apps/sign/__init__.py
Normal file
@ -0,0 +1,11 @@
|
||||
from utils.apps.manager import listener_service
|
||||
from utils.mysql import MySQL
|
||||
from .repositories import SignRepository
|
||||
from .services import SignServices
|
||||
|
||||
|
||||
@listener_service()
|
||||
def create_game_strategy_service(mysql: MySQL):
|
||||
_repository = SignRepository(mysql)
|
||||
_service = SignServices(_repository)
|
||||
return _service
|
25
apps/sign/models.py
Normal file
25
apps/sign/models.py
Normal file
@ -0,0 +1,25 @@
|
||||
import enum
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import func
|
||||
from sqlmodel import SQLModel, Field, Enum, Column, DateTime
|
||||
|
||||
|
||||
class SignStatusEnum(int, enum.Enum):
|
||||
STATUS_SUCCESS = 0 # 签到成功
|
||||
INVALID_COOKIES = 1 # Cookie无效
|
||||
ALREADY_CLAIMED = 2 # 已经获取奖励
|
||||
GENSHIN_EXCEPTION = 3 # API异常
|
||||
TIMEOUT_ERROR = 4 # 请求超时
|
||||
BAD_REQUEST = 5 # 请求失败
|
||||
FORBIDDEN = 6 # 这错误一般为通知失败 机器人被用户BAN
|
||||
|
||||
|
||||
class Sign(SQLModel, table=True):
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
user_id: int = Field()
|
||||
chat_id: int = Field()
|
||||
time_created: Optional[datetime] = Field(sa_column=Column(DateTime(timezone=True), server_default=func.now()))
|
||||
time_updated: Optional[datetime] = Field(sa_column=Column(DateTime(timezone=True), onupdate=func.now()))
|
||||
status: Optional[SignStatusEnum] = Field(sa_column=Column(Enum(SignStatusEnum)))
|
41
apps/sign/repositories.py
Normal file
41
apps/sign/repositories.py
Normal file
@ -0,0 +1,41 @@
|
||||
from typing import List, cast, Optional
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from utils.mysql import MySQL
|
||||
from .models import Sign
|
||||
|
||||
|
||||
class SignRepository:
|
||||
def __init__(self, mysql: MySQL):
|
||||
self.mysql = mysql
|
||||
|
||||
async def add(self, sign: Sign):
|
||||
async with self.mysql.Session() as session:
|
||||
session = cast(AsyncSession, session)
|
||||
session.add(sign)
|
||||
await session.commit()
|
||||
|
||||
async def update(self, sign: Sign):
|
||||
async with self.mysql.Session() as session:
|
||||
session = cast(AsyncSession, session)
|
||||
session.add(sign)
|
||||
await session.commit()
|
||||
await session.refresh(sign)
|
||||
|
||||
async def get_by_user_id(self, user_id: int) -> Optional[Sign]:
|
||||
async with self.mysql.Session() as session:
|
||||
session = cast(AsyncSession, session)
|
||||
statement = select(Sign).where(Sign.user_id == user_id)
|
||||
results = await session.exec(statement)
|
||||
if sign := results.first():
|
||||
return sign[0]
|
||||
return None
|
||||
|
||||
async def get_all(self) -> List[Sign]:
|
||||
async with self.mysql.Session() as session:
|
||||
query = select(Sign)
|
||||
results = await session.exec(query)
|
||||
signs = results.all()
|
||||
return [sign[0] for sign in signs]
|
19
apps/sign/services.py
Normal file
19
apps/sign/services.py
Normal file
@ -0,0 +1,19 @@
|
||||
from .models import Sign
|
||||
from .repositories import SignRepository
|
||||
|
||||
|
||||
class SignServices:
|
||||
def __init__(self, sign_repository: SignRepository) -> None:
|
||||
self._repository: SignRepository = sign_repository
|
||||
|
||||
async def get_all(self):
|
||||
return await self._repository.get_all()
|
||||
|
||||
async def add(self, sign: Sign):
|
||||
return await self._repository.add(sign)
|
||||
|
||||
async def update(self, sign: Sign):
|
||||
return await self._repository.update(sign)
|
||||
|
||||
async def get_by_user_id(self, user_id: int):
|
||||
return await self._repository.get_by_user_id(user_id)
|
96
jobs/sign.py
Normal file
96
jobs/sign.py
Normal file
@ -0,0 +1,96 @@
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from aiohttp import ClientConnectorError
|
||||
from genshin import Game, GenshinException, AlreadyClaimed, InvalidCookies
|
||||
from telegram.error import BadRequest, Forbidden
|
||||
from telegram.ext import CallbackContext, JobQueue
|
||||
|
||||
from apps.cookies import CookiesService
|
||||
from apps.sign.models import SignStatusEnum
|
||||
from apps.sign.services import SignServices
|
||||
from apps.user import UserService
|
||||
from config import config
|
||||
from logger import Log
|
||||
from utils.apps.inject import inject
|
||||
from utils.helpers import get_genshin_client
|
||||
from utils.job.manager import listener_jobs_class
|
||||
|
||||
|
||||
@listener_jobs_class()
|
||||
class SignJob:
|
||||
|
||||
@inject
|
||||
def __init__(self, sign_service: SignServices = None, user_service: UserService = None,
|
||||
cookies_service: CookiesService = None):
|
||||
self.sign_service = sign_service
|
||||
self.cookies_service = cookies_service
|
||||
self.user_service = user_service
|
||||
|
||||
@classmethod
|
||||
def build_jobs(cls, job_queue: JobQueue):
|
||||
sign = cls()
|
||||
if config.DEBUG:
|
||||
job_queue.run_once(sign.sign, 3, name="SignJobTest")
|
||||
# 每天凌晨执行
|
||||
job_queue.run_daily(sign.sign, datetime.time(hour=0, minute=0, second=0), name="SignJob")
|
||||
|
||||
async def sign(self, context: CallbackContext):
|
||||
Log.info("正在执行自动签到")
|
||||
sign_list = await self.sign_service.get_all()
|
||||
for sign_db in sign_list:
|
||||
if sign_db.status != SignStatusEnum.STATUS_SUCCESS:
|
||||
continue
|
||||
user_id = sign_db.user_id
|
||||
try:
|
||||
client = await get_genshin_client(user_id, self.user_service, self.cookies_service)
|
||||
rewards = await client.get_monthly_rewards(game=Game.GENSHIN, lang="zh-cn")
|
||||
daily_reward_info = await client.get_reward_info(game=Game.GENSHIN)
|
||||
if not daily_reward_info.signed_in:
|
||||
request_daily_reward = await client.request_daily_reward("sign", method="POST", game=Game.GENSHIN)
|
||||
Log.info(f"UID {client.uid} 签到请求 {request_daily_reward}")
|
||||
result = "OK"
|
||||
else:
|
||||
result = "今天旅行者已经签到过了~"
|
||||
reward = rewards[daily_reward_info.claimed_rewards - (1 if daily_reward_info.signed_in else 0)]
|
||||
today = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
cn_timezone = datetime.timezone(datetime.timedelta(hours=8))
|
||||
now = datetime.datetime.now(cn_timezone)
|
||||
missed_days = now.day - daily_reward_info.claimed_rewards
|
||||
if not daily_reward_info.signed_in:
|
||||
missed_days -= 1
|
||||
text = f"########### 定时签到 ###########\n" \
|
||||
f"#### {today} (UTC+8) ####\n" \
|
||||
f"UID: {client.uid}\n" \
|
||||
f"今日奖励: {reward.name} × {reward.amount}\n" \
|
||||
f"本月漏签次数:{missed_days}\n" \
|
||||
f"签到结果: {result}"
|
||||
except InvalidCookies:
|
||||
text = "自动签到执行失败,Cookie无效"
|
||||
sign_db.status = SignStatusEnum.INVALID_COOKIES
|
||||
except AlreadyClaimed:
|
||||
text = "今天旅行者已经签到过了~"
|
||||
sign_db.status = SignStatusEnum.ALREADY_CLAIMED
|
||||
except GenshinException as exc:
|
||||
text = f"自动签到执行失败,API返回信息为 {str(exc)}"
|
||||
sign_db.status = SignStatusEnum.GENSHIN_EXCEPTION
|
||||
except ClientConnectorError:
|
||||
text = "签到失败了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ "
|
||||
sign_db.status = SignStatusEnum.TIMEOUT_ERROR
|
||||
except BaseException as exc:
|
||||
Log.error(f"执行自动签到时发生错误", exc)
|
||||
continue
|
||||
try:
|
||||
await context.bot.send_message(sign_db.chat_id, text)
|
||||
except BadRequest as exc:
|
||||
Log.error(f"执行自动签到时发生错误", exc)
|
||||
sign_db.status = SignStatusEnum.BAD_REQUEST
|
||||
except Forbidden as exc:
|
||||
Log.error(f"执行自动签到时发生错误", exc)
|
||||
sign_db.status = SignStatusEnum.FORBIDDEN
|
||||
except BaseException as exc:
|
||||
Log.error(f"执行自动签到时发生错误", exc)
|
||||
continue
|
||||
sign_db.time_updated = datetime.datetime.now()
|
||||
await self.sign_service.update(sign_db)
|
||||
Log.info("执行自动签到完成")
|
Loading…
Reference in New Issue
Block a user