PamGram/plugins/genshin/cookies.py

218 lines
12 KiB
Python
Raw Normal View History

2022-08-05 13:23:04 +00:00
from http.cookies import SimpleCookie, CookieError
from typing import Optional
import genshin
from genshin import InvalidCookies, GenshinException, DataNotPublic
from telegram import Update, ReplyKeyboardRemove, ReplyKeyboardMarkup, TelegramObject
from telegram.ext import CallbackContext, filters, ConversationHandler
2022-08-05 13:23:04 +00:00
from telegram.helpers import escape_markdown
from core.baseplugin import BasePlugin
from core.cookies.error import CookiesNotFoundError
from core.cookies.models import Cookies
from core.cookies.services import CookiesService
from core.plugin import Plugin, handler, conversation
from core.user.error import UserNotFoundError
from core.user.models import User
from core.user.services import UserService
2022-08-05 13:23:04 +00:00
from utils.decorators.error import error_callable
from utils.decorators.restricts import restricts
from utils.log import logger
from utils.models.base import RegionEnum
2022-08-05 13:23:04 +00:00
class AddUserCommandData(TelegramObject):
user: Optional[User] = None
cookies_database_data: Optional[Cookies] = None
region: RegionEnum = RegionEnum.NULL
2022-08-05 13:23:04 +00:00
cookies: dict = {}
game_uid: int = 0
CHECK_SERVER, CHECK_COOKIES, COMMAND_RESULT = range(10100, 10103)
2022-08-05 13:23:04 +00:00
class SetUserCookies(Plugin.Conversation, BasePlugin.Conversation):
"""Cookie绑定"""
2022-08-05 13:23:04 +00:00
def __init__(self, user_service: UserService = None, cookies_service: CookiesService = None):
self.cookies_service = cookies_service
self.user_service = user_service
@conversation.entry_point
@handler.command(command='setcookies', filters=filters.ChatType.PRIVATE, block=True)
2022-08-05 13:23:04 +00:00
@restricts()
@error_callable
async def command_start(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
logger.info(f"用户 {user.full_name}[{user.id}] 绑定账号命令请求")
2022-08-05 13:23:04 +00:00
add_user_command_data: AddUserCommandData = context.chat_data.get("add_user_command_data")
if add_user_command_data is None:
cookies_command_data = AddUserCommandData()
context.chat_data["add_user_command_data"] = cookies_command_data
text = f'你好 {user.mention_markdown_v2()} {escape_markdown("!请选择要绑定的服务器!或回复退出取消操作")}'
2022-08-05 13:23:04 +00:00
reply_keyboard = [['米游社', 'HoYoLab'], ["退出"]]
await message.reply_markdown_v2(text, reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
return CHECK_SERVER
2022-08-05 13:23:04 +00:00
@conversation.state(state=CHECK_SERVER)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=True)
2022-08-05 13:23:04 +00:00
@error_callable
async def check_server(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
2022-08-05 13:23:04 +00:00
add_user_command_data: AddUserCommandData = context.chat_data.get("add_user_command_data")
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
elif message.text == "米游社":
region = RegionEnum.HYPERION
2022-08-05 13:23:04 +00:00
bbs_url = "https://bbs.mihoyo.com/ys/"
bbs_name = "米游社"
elif message.text == "HoYoLab":
2022-08-05 13:23:04 +00:00
bbs_url = "https://www.hoyolab.com/home"
bbs_name = "HoYoLab"
region = RegionEnum.HOYOLAB
2022-08-05 13:23:04 +00:00
else:
await message.reply_text("选择错误,请重新选择")
return CHECK_SERVER
try:
user_info = await self.user_service.get_user_by_id(user.id)
except UserNotFoundError:
user_info = None
if user_info is not None:
try:
cookies_database_data = await self.cookies_service.get_cookies(user.id, region)
add_user_command_data.cookies_database_data = cookies_database_data
except CookiesNotFoundError:
await message.reply_text("你已经绑定UID如果继续操作会覆盖当前UID。")
else:
await message.reply_text("警告你已经绑定Cookie如果继续操作会覆盖当前Cookie。")
add_user_command_data.user = user_info
add_user_command_data.region = region
await message.reply_text(f"请输入{bbs_name}的Cookies或回复退出取消操作", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
javascript = "javascript:(()=>{_=(n)=>{for(i in(r=document.cookie.split(';'))){var a=r[i].split('=');if(a[" \
"0].trim()==n)return a[1]}};c=_('account_id')||alert('无效的Cookie,请重新登录!');c&&confirm(" \
"'将Cookie复制到剪贴板?')&&copy(document.cookie)})(); "
javascript_android = "javascript:(()=>{prompt('',document.cookie)})();"
help_message = f"*关于如何获取Cookies*\n\n" \
f"PC\n" \
f"[1、打开{bbs_name}并登录]({bbs_url})\n" \
f"2、按F12打开开发者工具\n" \
f"3、{escape_markdown('将开发者工具切换至控制台(Console)页签', version=2)}\n" \
f"4、复制下方的代码并将其粘贴在控制台中按下回车\n" \
f"`{escape_markdown(javascript, version=2, entity_type='code')}`\n\n" \
f"Android\n" \
f"[1、通过 Via 浏览器打开{bbs_name}并登录]({bbs_url})\n" \
f"2、复制下方的代码并将其粘贴在地址栏中点击右侧箭头\n" \
f"`{escape_markdown(javascript_android, version=2, entity_type='code')}`"
await message.reply_markdown_v2(help_message, disable_web_page_preview=True)
return CHECK_COOKIES
2022-08-05 13:23:04 +00:00
@conversation.state(state=CHECK_COOKIES)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=True)
2022-08-05 13:23:04 +00:00
@error_callable
async def check_cookies(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
2022-08-05 13:23:04 +00:00
add_user_command_data: AddUserCommandData = context.chat_data.get("add_user_command_data")
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
str_cookies = message.text
2022-08-05 13:23:04 +00:00
cookie = SimpleCookie()
try:
cookie.load(str_cookies)
except CookieError:
await message.reply_text("Cookies格式有误请检查", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
if len(cookie) == 0:
await message.reply_text("Cookies格式有误请检查", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
2022-08-06 06:22:37 +00:00
cookies = {key: morsel.value for key, morsel in cookie.items()}
if not cookies:
await message.reply_text("Cookies格式有误请检查", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
if add_user_command_data.region == RegionEnum.HYPERION:
client = genshin.ChineseClient(cookies=cookies)
elif add_user_command_data.region == RegionEnum.HOYOLAB:
client = genshin.GenshinClient(cookies=cookies)
else:
await message.reply_text("数据错误", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
try:
user_info = await client.get_record_card()
except DataNotPublic:
await message.reply_text("账号疑似被注销,请检查账号状态", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
except InvalidCookies:
await message.reply_text("Cookies已经过期请检查是否正确", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
except GenshinException as error:
await message.reply_text(f"获取账号信息发生错误,错误信息为 {str(error)}请检查Cookie或者账号是否正常",
reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
2022-08-06 06:22:37 +00:00
except (AttributeError, ValueError):
await message.reply_text("Cookies错误请检查是否正确", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
add_user_command_data.cookies = cookies
add_user_command_data.game_uid = user_info.uid
reply_keyboard = [['确认', '退出']]
await message.reply_text("获取角色基础信息成功,请检查是否正确!")
logger.info(f"用户 {user.full_name}[{user.id}] 获取账号 {user_info.nickname}[{user_info.uid}] 信息成功")
text = f"*角色信息*\n" \
f"角色名称:{escape_markdown(user_info.nickname, version=2)}\n" \
f"角色等级:{user_info.level}\n" \
f"UID`{user_info.uid}`\n" \
f"服务器名称:`{user_info.server_name}`\n"
await message.reply_markdown_v2(text, reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
return COMMAND_RESULT
2022-08-05 13:23:04 +00:00
@conversation.state(state=COMMAND_RESULT)
@handler.message(filters=filters.TEXT & ~filters.COMMAND, block=True)
2022-08-05 13:23:04 +00:00
@error_callable
async def command_result(self, update: Update, context: CallbackContext) -> int:
user = update.effective_user
message = update.effective_message
2022-08-05 13:23:04 +00:00
add_user_command_data: AddUserCommandData = context.chat_data.get("add_user_command_data")
if message.text == "退出":
await message.reply_text("退出任务", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
elif message.text == "确认":
2022-08-05 13:23:04 +00:00
if add_user_command_data.user is None:
if add_user_command_data.region == RegionEnum.HYPERION:
2022-08-05 14:45:54 +00:00
user_db = User(user_id=user.id, yuanshen_uid=add_user_command_data.game_uid,
region=add_user_command_data.region)
2022-08-05 13:23:04 +00:00
elif add_user_command_data.region == RegionEnum.HOYOLAB:
2022-08-05 14:45:54 +00:00
user_db = User(user_id=user.id, genshin_uid=add_user_command_data.game_uid,
region=add_user_command_data.region)
2022-08-05 13:23:04 +00:00
else:
await message.reply_text("数据错误")
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
await self.user_service.add_user(user_db)
else:
user_db = add_user_command_data.user
user_db.region = add_user_command_data.region
if add_user_command_data.region == RegionEnum.HYPERION:
user_db.yuanshen_uid = add_user_command_data.game_uid
elif add_user_command_data.region == RegionEnum.HOYOLAB:
user_db.genshin_uid = add_user_command_data.game_uid
else:
await message.reply_text("数据错误")
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
await self.user_service.update_user(user_db)
if add_user_command_data.cookies_database_data is None:
await self.cookies_service.add_cookies(user.id, add_user_command_data.cookies,
add_user_command_data.region)
else:
await self.cookies_service.update_cookies(user.id, add_user_command_data.cookies,
add_user_command_data.region)
logger.info(f"用户 {user.full_name}[{user.id}] 绑定账号成功")
await message.reply_text("保存成功", reply_markup=ReplyKeyboardRemove())
2022-08-05 13:23:04 +00:00
return ConversationHandler.END
else:
await message.reply_text("回复错误,请重新输入")
return COMMAND_RESULT