Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
KT-Yeh committed Feb 4, 2024
2 parents 55d7c62 + 7f89219 commit 98a9e66
Show file tree
Hide file tree
Showing 25 changed files with 848 additions and 500 deletions.
5 changes: 2 additions & 3 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
[flake8]

# E203: Whitespace before ':'
# E704: Multiple statements on one line
# W503: Line break before binary operator
ignore =
E203,
W503,
extend-ignore = E203, E704, W503

# F401: Module imported but unused
# F403: Unable to detect undefined names
Expand Down
3 changes: 2 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ beautifulsoup4 = "~=4.11"
prometheus-client = "~=0.16"
psutil = "~=5.9"
"enkanetwork.py" = {git = "https://github.com/KT-Yeh/EnkaNetwork.py"}
mihomo = {git = "https://github.com/KT-Yeh/mihomo"}
mihomo = {git = "https://github.com/KT-Yeh/mihomo", ref = "v1.1.7"}
sqlalchemy = {version = "~=2.0.16", extras = ["asyncio"]}
python-dotenv = "~=1.0.0"
alembic = "~=1.11.1"
genshinpyrail = {ref = "gdb", git = "https://github.com/KT-Yeh/GenshinPyRail.git"}

[dev-packages]
black = "*"
Expand Down
841 changes: 431 additions & 410 deletions Pipfile.lock

Large diffs are not rendered by default.

Binary file added assets/image/forgotten_hall/bg_blue.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions cogs/abyss/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from utility import EmbedTemplate, config, custom_log

from .ui_genshin import SpiralAbyssUI
from .ui_starrail import ForgottenHallUI
from .ui_starrail import ChooseAbyssModeButton, ForgottenHallUI


class SpiralAbyssCog(commands.Cog, name="深境螺旋"):
Expand Down Expand Up @@ -43,7 +43,15 @@ async def slash_abyss(
case genshin.Game.GENSHIN:
await SpiralAbyssUI.abyss(interaction, user or interaction.user, season)
case genshin.Game.STARRAIL:
await ForgottenHallUI.launch(interaction, user or interaction.user, season)
# 選擇忘卻之庭、虛構敘事
view = ChooseAbyssModeButton()
await interaction.response.send_message(view=view)
await view.wait()

if view.value is None:
return
mode = view.value
await ForgottenHallUI.launch(interaction, user or interaction.user, mode, season)
case _:
return

Expand Down
102 changes: 74 additions & 28 deletions cogs/abyss/ui_starrail.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,55 @@
import asyncio
import enum
import typing

import discord

import genshin_py
from database import Database, StarrailForgottenHall, User
from database import Database, StarrailForgottenHall, StarrailPureFiction, User
from utility import EmbedTemplate, config


class AbyssMode(str, enum.Enum):
"""星穹鐵道深淵模式"""

FORGOTTEN_HALL = "forgotten_hall"
"""忘卻之庭"""
PURE_FICTION = "pure_fiction"
"""虛構敘事"""


# Make a discord button to choose which mode
class ChooseAbyssModeButton(discord.ui.View):
"""選擇星穹鐵道深淵模式的按鈕"""

def __init__(self):
super().__init__(timeout=config.discord_view_short_timeout)
self.value = None

@discord.ui.button(label="忘卻之庭", style=discord.ButtonStyle.blurple)
async def forgotten_hall(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.defer()
self.value = AbyssMode.FORGOTTEN_HALL
self.stop()

@discord.ui.button(label="虛構敘事", style=discord.ButtonStyle.blurple)
async def pure_fiction(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.defer()
self.value = AbyssMode.PURE_FICTION
self.stop()


class HallRecordDropdown(discord.ui.Select):
"""選擇忘卻之庭歷史紀錄的下拉選單"""
"""選擇忘卻之庭、虛構敘事歷史紀錄的下拉選單"""

def __init__(
self,
user: discord.User | discord.Member,
nickname: str,
uid: int,
hall_data_list: typing.Sequence[StarrailForgottenHall],
hall_data_list: typing.Sequence[StarrailForgottenHall]
| typing.Sequence[StarrailPureFiction],
):
hall_data_list = sorted(
sorted_hall_data_list = sorted(
hall_data_list, key=lambda x: x.data.begin_time.datetime, reverse=True
)
options = [
Expand All @@ -27,13 +58,13 @@ def __init__(
f"{hall.data.end_time.datetime.strftime('%Y.%m.%d')}] ★ {hall.data.total_stars}",
value=str(i),
)
for i, hall in enumerate(hall_data_list)
for i, hall in enumerate(sorted_hall_data_list)
]
super().__init__(placeholder="選擇期數:", options=options)
self.user = user
self.nickname = nickname
self.uid = uid
self.hall_data_list = hall_data_list
self.hall_data_list = sorted_hall_data_list

async def callback(self, interaction: discord.Interaction):
await interaction.response.defer()
Expand All @@ -49,15 +80,15 @@ async def callback(self, interaction: discord.Interaction):


class HallFloorDropdown(discord.ui.Select):
"""選擇忘卻之庭樓層的下拉選單"""
"""選擇忘卻之庭、虛構敘事樓層的下拉選單"""

def __init__(
self,
overview: discord.Embed,
avatar: bytes,
nickname: str,
uid: int,
hall_data: StarrailForgottenHall,
hall_data: StarrailForgottenHall | StarrailPureFiction,
save_or_remove: typing.Literal["SAVE", "REMOVE"],
):
# 第一個選項依據參數顯示為保存或是刪除紀錄
Expand Down Expand Up @@ -97,12 +128,12 @@ async def callback(self, interaction: discord.Interaction):
if self.save_or_remove == "SAVE":
await Database.insert_or_replace(self.hall_data)
await interaction.response.send_message(
embed=EmbedTemplate.normal("已儲存本次忘卻之庭紀錄"), ephemeral=True
embed=EmbedTemplate.normal("已儲存本次挑戰紀錄"), ephemeral=True
)
else: # self.save_or_remove == 'REMOVE'
await Database.delete_instance(self.hall_data)
await interaction.response.send_message(
embed=EmbedTemplate.normal("已刪除本次忘卻之庭紀錄"), ephemeral=True
embed=EmbedTemplate.normal("已刪除本次挑戰紀錄"), ephemeral=True
)
else:
await interaction.response.send_message(
Expand All @@ -129,13 +160,17 @@ async def present(
user: discord.User | discord.Member,
nickname: str,
uid: int,
hall_data: StarrailForgottenHall,
hall_data: StarrailForgottenHall | StarrailPureFiction,
*,
view_item: discord.ui.Item | None = None,
):
if isinstance(hall_data, StarrailForgottenHall):
title = "忘卻之庭"
else: # isinstance(hall_data, StarrailPureFiction)
title = "虛構敘事"
hall = hall_data.data
embed = genshin_py.parse_starrail_hall_overview(hall)
embed.title = f"{user.display_name} 的忘卻之庭戰績"
embed.title = f"{user.display_name} {title}戰績"
embed.set_thumbnail(url=user.display_avatar.url)
view = None
if len(hall.floors) > 0:
Expand All @@ -152,15 +187,13 @@ async def present(
async def launch(
interaction: discord.Interaction,
user: discord.User | discord.Member,
mode: AbyssMode,
season_choice: typing.Literal["THIS_SEASON", "PREVIOUS_SEASON", "HISTORICAL_RECORD"],
):
try:
defer, userstats = await asyncio.gather(
interaction.response.defer(),
genshin_py.get_starrail_userstats(user.id),
)
userstats = await genshin_py.get_starrail_userstats(user.id)
except Exception as e:
await interaction.edit_original_response(embed=EmbedTemplate.error(e))
await interaction.edit_original_response(embed=EmbedTemplate.error(e), view=None)
return

nickname = userstats.info.nickname
Expand All @@ -169,25 +202,38 @@ async def launch(
uid = uid or 0

if season_choice == "HISTORICAL_RECORD": # 查詢歷史紀錄
hall_data_list = await Database.select_all(
StarrailForgottenHall,
StarrailForgottenHall.discord_id.is_(user.id),
)
if mode == AbyssMode.FORGOTTEN_HALL:
hall_data_list = await Database.select_all(
StarrailForgottenHall,
StarrailForgottenHall.discord_id.is_(user.id),
)
else: # mode == AbyssMode.PURE_FICTION
hall_data_list = await Database.select_all(
StarrailPureFiction,
StarrailPureFiction.discord_id.is_(user.id),
)
if len(hall_data_list) == 0:
await interaction.edit_original_response(
embed=EmbedTemplate.normal("此使用者沒有保存任何歷史紀錄")
embed=EmbedTemplate.normal("此使用者沒有保存任何歷史紀錄"),
view=None,
)
else:
view = discord.ui.View(timeout=config.discord_view_short_timeout)
view.add_item(HallRecordDropdown(user, nickname, uid, hall_data_list))
await interaction.edit_original_response(view=view)
else: # 查詢 Hoyolab 紀錄 (THIS_SEASON、PREVIOUS_SEASON)
try:
hall = await genshin_py.get_starrail_forgottenhall(
user.id, (season_choice == "PREVIOUS_SEASON")
)
if mode == AbyssMode.FORGOTTEN_HALL:
hall = await genshin_py.get_starrail_forgottenhall(
user.id, (season_choice == "PREVIOUS_SEASON")
)
hall_data = StarrailForgottenHall(user.id, hall.season, hall)
else: # mode == AbyssMode.PURE_FICTION
hall = await genshin_py.get_starrail_pure_fiction(
user.id, (season_choice == "PREVIOUS_SEASON")
)
hall_data = StarrailPureFiction(user.id, hall.season_id, hall)
except Exception as e:
await interaction.edit_original_response(embed=EmbedTemplate.error(e))
await interaction.edit_original_response(embed=EmbedTemplate.error(e), view=None)
else:
hall_data = StarrailForgottenHall(user.id, hall.season, hall)
await ForgottenHallUI.present(interaction, user, nickname, uid, hall_data)
31 changes: 30 additions & 1 deletion cogs/characters/cog.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import asyncio
import io

import discord
import genshin
from discord import app_commands
from discord.ext import commands
from genshinpyrail.genshinpyrail import genshin_character_list, honkai_character_list
from genshinpyrail.src.tools.model import GenshinCharterList, StarRaillCharterList

import genshin_py
from utility import EmbedTemplate
Expand Down Expand Up @@ -44,9 +47,35 @@ async def slash_characters(self, interaction: discord.Interaction, game: genshin
return
except Exception as e:
await interaction.edit_original_response(embed=EmbedTemplate.error(e))
else:
return

try:
# 使用 genshinpyrail 產生圖片
match game:
case genshin.Game.GENSHIN:
data = await genshin_character_list.Creat(characters).start()
image = GenshinCharterList(**data).card
case genshin.Game.STARRAIL:
data = await honkai_character_list.Creat(characters).start()
image = StarRaillCharterList(**data).card
if image is None:
raise ValueError("沒有圖片")
except Exception:
# 文字呈現
view = DropdownView(interaction.user, characters)
await interaction.edit_original_response(content="請選擇角色:", view=view)
return
else:
# 圖片呈現
fp = io.BytesIO()
image = image.convert("RGB")
image.save(fp, "jpeg", optimize=True, quality=90)
fp.seek(0)
embed = EmbedTemplate.normal(f"{interaction.user.display_name} 的角色一覽")
embed.set_image(url="attachment://image.jpeg")
await interaction.edit_original_response(
embed=embed, attachments=[discord.File(fp, "image.jpeg")]
)


async def setup(client: commands.Bot):
Expand Down
14 changes: 13 additions & 1 deletion cogs/cookie_setting/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ class GameSelectionView(discord.ui.View):
discord.SelectOption(label="原神", value="genshin"),
discord.SelectOption(label="崩壞3", value="honkai3rd"),
discord.SelectOption(label="星穹鐵道", value="hkrpg"),
discord.SelectOption(label="未定事件簿", value="tot"),
],
min_values=1,
max_values=3,
max_values=4,
placeholder="請選擇遊戲 (可多選):",
)
async def select_callback(self, interaction: discord.Interaction, select: discord.ui.Select):
Expand Down Expand Up @@ -57,6 +58,15 @@ class CookieModal(discord.ui.Modal, title="提交Cookie"):
max_length=150,
)

ltmid_v2: discord.ui.TextInput[discord.ui.Modal] = discord.ui.TextInput(
label="ltmid_v2",
placeholder="請貼上取得的 ltmid_v2",
style=discord.TextStyle.short,
required=False,
min_length=5,
max_length=20,
)

def __init__(self, games: list[genshin.Game]):
self.games: list[genshin.Game] = games
super().__init__()
Expand All @@ -79,6 +89,8 @@ async def on_submit(self, interaction: discord.Interaction):
cookie += f" ltuid{v2_str}={self.ltuid_v2.value};"
else: # ltuid_v2 不是數字,可能是 ltmid_v2
cookie += f" ltmid_v2={self.ltuid_v2.value};"
if len(self.ltmid_v2.value) > 0:
cookie += f" ltmid_v2={self.ltmid_v2.value};"

LOG.Info(f"設定 {LOG.User(interaction.user)} 的Cookie:{self.cookie.value}")
try:
Expand Down
6 changes: 5 additions & 1 deletion cogs/daily_checkin/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def __init__(self, bot: commands.Bot):
Choice(name="原神", value="原神"),
Choice(name="崩壞3", value="崩壞3"),
Choice(name="星穹鐵道", value="星穹鐵道"),
Choice(name="未定事件簿(台服)", value="未定事件簿(台服)"),
Choice(name="未定事件簿(國際服)", value="未定事件簿(國際服)"),
]
)
@app_commands.choices(
Expand All @@ -35,14 +37,16 @@ def __init__(self, bot: commands.Bot):
async def slash_daily(
self,
interaction: discord.Interaction,
game: Literal["原神", "崩壞3", "星穹鐵道"],
game: Literal["原神", "崩壞3", "星穹鐵道", "未定事件簿(台服)", "未定事件簿(國際服)"],
is_geetest: Literal["是", "否"] = "否",
user: Optional[discord.User] = None,
):
choice = {
"has_genshin": True if game == "原神" else False,
"has_honkai3rd": True if game == "崩壞3" else False,
"has_starrail": True if game == "星穹鐵道" else False,
"has_themis": True if game == "未定事件簿(國際服)" else False,
"has_themis_tw": True if game == "未定事件簿(台服)" else False,
"is_geetest": True if is_geetest == "是" else False,
}

Expand Down
4 changes: 3 additions & 1 deletion cogs/schedule/command_cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ async def slash_schedule(
options_view = DailyRewardOptionsView(interaction.user)
await interaction.response.send_message(
"請依序選擇:\n"
"1. 要簽到的遊戲 (請選擇 1~3 項)\n"
"1. 要簽到的遊戲 (可同時多選)\n"
"2. 要簽到的時間\n"
f"3. 簽到時希望小幫手 tag 你 ({interaction.user.mention}) 嗎?",
view=options_view,
Expand All @@ -127,6 +127,8 @@ async def slash_schedule(
has_genshin=options_view.has_genshin,
has_honkai3rd=options_view.has_honkai3rd,
has_starrail=options_view.has_starrail,
has_themis=options_view.has_themis,
has_themis_tw=options_view.has_themis_tw,
)
if checkin_user.next_checkin_time < datetime.now():
checkin_user.update_next_checkin_time()
Expand Down

0 comments on commit 98a9e66

Please sign in to comment.