This repository has been archived by the owner on May 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
350 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
from hoshino import Service, priv, MessageSegment | ||
from ..util import support_private | ||
from .main import Daily_Note, Error_Message, Account_Error | ||
from .info_card import draw_info_card | ||
|
||
sv_help = ''' | ||
'''.strip() | ||
sv = Service( | ||
name='原神实时便笺', # 功能名 | ||
use_priv=priv.NORMAL, # 使用权限 | ||
manage_priv=priv.ADMIN, # 管理权限 | ||
visible=True, # 可见性 | ||
enable_on_default=True, # 默认启用 | ||
bundle='娱乐', #分组归类 | ||
help_=sv_help # 帮助说明 | ||
) | ||
|
||
|
||
@support_private(sv) | ||
@sv.on_prefix(('yss', 'yss#', '原神状态', '原神实时', '原神便笺')) | ||
async def main(bot, ev): | ||
text = ev.message.extract_plain_text().strip() | ||
cookie_raw = '' | ||
try: | ||
if text.startswith('绑定'): | ||
if ev.detail_type == 'group': | ||
raise Error_Message('请撤回, 不支持在群内绑定, 请私聊机器人') | ||
cookie_raw = text[2:] | ||
info = await Daily_Note(ev.user_id, cookie_raw).get_info() | ||
im = await draw_info_card(info) | ||
await bot.send(ev, MessageSegment.image(im), at_sender=True) | ||
|
||
except Error_Message as e: | ||
await bot.send(ev, repr(e), at_sender=True) | ||
except Account_Error as e: | ||
await bot.send(ev, 'cookie信息错误, 请重新检查是否正确', at_sender=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
class Error_Message(Exception): | ||
def __init__(self, message=''): | ||
self.message = message | ||
|
||
def __repr__(self): | ||
return self.message | ||
|
||
class Cookie_Error(Error_Message): | ||
def __repr__(self): | ||
t = ''' | ||
1. 打开米游社(https://bbs.mihoyo.com/ys/) | ||
2. 登录游戏账号 | ||
3. F12打开控制台 | ||
4. 输入以下代码运行 | ||
javascript:(()=>{_=(n)=>document.cookie.match(`[;\s+]?${n}=([^;]*)`)?.pop();alert(_("account_id")+","+_("cookie_token"))})(); | ||
5. 复制提示的内容, 私聊发给机器人 | ||
私聊格式为 | ||
原神便笺绑定xxxxxxxxxxxxxx | ||
其中xxxxxxxxxxxxxx是复制的内容 | ||
''' | ||
return t.rstrip() | ||
|
||
|
||
class Login_Error(Error_Message): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import datetime | ||
from pathlib import Path | ||
|
||
from ..imghandler import * | ||
from ..util import cache, get_font, get_path, pil2b64 | ||
from .main import Daily_Note_Info | ||
|
||
default_text_color = '#78818b' | ||
success_text_color = '#669999' | ||
|
||
assets_dir = Path(get_path('assets')) / 'daily_note' | ||
box_bg = Image.open(assets_dir / "bg.png") | ||
expedition_box = Image.open(assets_dir / "expeditions_item.png") | ||
expedition_box_ok = Image.open(assets_dir / "expeditions_item_ok.png") | ||
|
||
def in_time(time_str1, time_str2): | ||
now = datetime.datetime.now() | ||
day = str(now.date()) | ||
t1 = datetime.datetime.strptime(day + time_str1, '%Y-%m-%d%H:%M') | ||
t2 = datetime.datetime.strptime(day + time_str2, '%Y-%m-%d%H:%M') | ||
if t2 < t1: | ||
return True | ||
return now > t1 and now < t2 | ||
|
||
|
||
async def get_time_icon(): | ||
morning = ('6:00', '11:00', '早晨.png') | ||
noon = ('11:00', '17:00', '中午.png') | ||
dusk = ('17:00', '19:00', '黄昏.png') | ||
night = ('19:00', '6:00', '夜晚.png') | ||
for t1, t2, png in [morning, noon, dusk, night]: | ||
if in_time(t1, t2): | ||
return Image.open(assets_dir / png) | ||
raise Exception('unknown time') | ||
|
||
|
||
async def gen_expedition_items(expeditions): | ||
for exp in expeditions: | ||
remained_time = int(exp['remained_time']) | ||
avatar = await get_pic(exp['avatar_side_icon'], (49, 60)) | ||
|
||
if exp['status'] == 'Finished': | ||
bg = expedition_box_ok.copy() | ||
s = '已完成!' | ||
ok = True | ||
else: | ||
bg = expedition_box.copy() | ||
mm, ss = divmod(remained_time, 60) | ||
hh, mm = divmod(mm, 60) | ||
s = "剩余%d小时%02d分%02d秒" % (hh, mm, ss) | ||
ok = False | ||
|
||
draw_text_by_line(bg, (0, 49.88), s, get_font(49), ok and success_text_color or default_text_color, 881, True) | ||
yield (avatar, bg.resize((273, 76))) | ||
|
||
|
||
async def draw_info_card(info: Daily_Note_Info): | ||
now = datetime.datetime.now() | ||
|
||
bg = Image.new('RGB', (box_bg.width, box_bg.height), '#f1ece6') | ||
easy_paste(bg, box_bg.copy()) | ||
|
||
now_str = now.strftime(" %m月%d日\n%H:%M:%S") | ||
draw_text_by_line(bg, (219.38, 59.79), now_str, get_font(21), default_text_color, 881) | ||
easy_paste(bg, await get_time_icon(), (84, 30)) | ||
|
||
# 树脂完全回复时间 | ||
resin_recovery_time = now + datetime.timedelta(seconds=int(info.resin_recovery_time)) | ||
resin_recovery_time_day = resin_recovery_time.day > now.day and '明天' or '今天' | ||
resin_recovery_str = f'将于{resin_recovery_time_day} {resin_recovery_time.strftime("%H:%M:%S")} 完全回复' | ||
draw_text_by_line(bg, (173.09, 150.2), resin_recovery_str, get_font(16), default_text_color, 881) | ||
|
||
# 树脂 | ||
resin_str = f'{info.current_resin}/{info.max_resin}' | ||
draw_text_by_line(bg, (233.55, 196.93), resin_str, get_font(36), default_text_color, 881) | ||
|
||
# 每日 | ||
ok = False | ||
task_str = f'{info.finished_task_num}/{info.total_task_num}' | ||
if info.finished_task_num == info.total_task_num: | ||
task_str = '完成' | ||
ok = True | ||
draw_text_by_line(bg, (253, 327), task_str, get_font(36), ok and success_text_color or default_text_color, 881) | ||
|
||
# 周本 | ||
ok = False | ||
resin_discount_str = f'{info.remain_resin_discount_num}/{info.resin_discount_num_limit}' | ||
if info.remain_resin_discount_num == 0: | ||
resin_discount_str = '完成' | ||
ok = True | ||
draw_text_by_line(bg, (253, 452), resin_discount_str, get_font(36), ok and success_text_color or default_text_color, 881) | ||
|
||
# 探索 | ||
first_expeditions_time = int(min([x['remained_time'] for x in info.expeditions])) | ||
first_expeditions_time = now + datetime.timedelta(seconds=first_expeditions_time) | ||
first_expeditions_time_day = first_expeditions_time.day > now.day and '明天' or '今天' | ||
first_expeditions_str = f'最快{first_expeditions_time_day} {first_expeditions_time.strftime("%H:%M:%S")} 派遣完成' | ||
draw_text_by_line(bg, (600, 74), first_expeditions_str, get_font(18), default_text_color, 881) | ||
|
||
bg = bg.convert("RGBA") | ||
exp_index = 114 | ||
async for avatar, exp_bg in gen_expedition_items(info.expeditions): | ||
bg = easy_alpha_composite(bg, avatar, (538, exp_index)) | ||
bg = easy_alpha_composite(bg, exp_bg, (587, exp_index)) | ||
|
||
exp_index += 72 | ||
|
||
return pil2b64(bg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
from typing import List | ||
from dataclasses import dataclass | ||
from http.cookies import SimpleCookie | ||
from ..player_info import query | ||
from .error import * | ||
|
||
Account_Error = query.Account_Error | ||
|
||
|
||
@dataclass | ||
class Daily_Note_expeditions: | ||
avatar_side_icon: str # 头像icon | ||
status: str # 'Finished' or 'Ongoing' 状态 | ||
remained_time: str # 剩余时间 | ||
|
||
|
||
@dataclass | ||
class Daily_Note_Info: | ||
current_resin: int # 当前树脂 | ||
max_resin: int # 最大树脂 | ||
resin_recovery_time: str # 树脂回复时间 | ||
finished_task_num: int # 完成委托个数 | ||
total_task_num: int # 全部委托个数 | ||
is_extra_task_reward_received: bool | ||
remain_resin_discount_num: int # 周本树脂减半剩余次数 | ||
resin_discount_num_limit: int # 周本树脂减半次数 | ||
current_expedition_num: int # 当前派遣数量 | ||
max_expedition_num: int # 最大派遣数量 | ||
expeditions: List[Daily_Note_expeditions] # 派遣列表 | ||
|
||
|
||
class Daily_Note(): | ||
def __init__(self, qid, cookie_raw=None): | ||
self.qid = qid | ||
|
||
self.cookie = query.get_cookie_by_qid(qid) | ||
|
||
if not any([cookie_raw, self.cookie]): | ||
raise Cookie_Error() | ||
|
||
self.uid = query.get_uid_by_qid(qid) | ||
if not self.uid: | ||
raise Error_Message('请先使用ys#绑定') | ||
|
||
self.cookie = SimpleCookie(self.cookie) | ||
if cookie_raw: | ||
self.cookie.load( | ||
dict(zip(['account_id', 'cookie_token'], | ||
cookie_raw.split(',')))) | ||
|
||
self.cookie_raw = self.cookie.output(header='', sep=';').strip() | ||
|
||
async def get_info(self) -> Daily_Note_Info: | ||
json_data = await query.daily_note(self.uid, self.cookie_raw) | ||
|
||
if json_data.retcode == 10102: | ||
raise Login_Error('请先在米游社角色信息那打开实时便笺功能') | ||
if json_data.retcode != 0: | ||
raise Login_Error(json_data.message) | ||
|
||
query.save_cookie(self.qid, self.cookie_raw) | ||
return Daily_Note_Info(**json_data.data) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.