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 15, 2024
2 parents e8ad51a + 6709ff3 commit 2eaeaad
Show file tree
Hide file tree
Showing 9 changed files with 422 additions and 272 deletions.
6 changes: 4 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ name = "pypi"
[packages]
genshin = {ref = "gdb", git = "https://github.com/KT-Yeh/genshin.py"}
"discord.py" = "~=2.2"
pillow = "~=9.4"
pillow = "~=10.2.0"
sentry-sdk = "~=1.16"
jishaku = "~=2.5"
aiosqlite = "~=0.18"
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", ref = "v1.1.7"}
mihomo = {git = "https://github.com/KT-Yeh/mihomo", ref = "pydantic-v1"}
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"}
honkairail = "~=1.1"
hsrcard = {ref = "gdb", git = "https://github.com/KT-Yeh/HSRCard.git"}

[dev-packages]
black = "*"
Expand Down
382 changes: 191 additions & 191 deletions Pipfile.lock

Large diffs are not rendered by default.

67 changes: 44 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,28 @@ Discord 支援伺服器:https://discord.gg/myugWxgRjd

## 簡介
使用機器人直接在 Discord 聊天頻道內查看原神、星穹鐵道內各項資訊,包含:
- 查詢**即時便箋**
- 原神:包含樹脂、洞天寶錢、參數質變儀、探索派遣完成時間...等
- 星穹鐵道:包含開拓力、委託執行
- 每日早上 8 點開始 Hoyolab **自動簽到** (包含簽到**崩壞3****星穹鐵道**)
- **自動檢查即時便箋 (原神、星鐵)**、樹脂 (開拓力)、寶錢、質變儀、探索派遣,當快額滿時發送提醒
- 查詢深境螺旋紀錄
- 查詢旅行者札記
- 個人紀錄卡片(遊戲天數、成就、神瞳、世界探索度...等等)
- 查詢任意玩家的原神/星穹鐵道**角色展示櫃**,顯示展示櫃內角色的面板、聖遺物詳情
- 查看原神遊戲內公告,包含活動、卡池資訊
- 採用新的斜線指令,輸入 / 自動彈出指令提示,不需要記憶任何指令的使用方式

- 原神、崩壞3、星穹鐵道、未定事件簿:
- **自動簽到**:設定時間每天自動幫你簽到 Hoyolab 領獎

- 原神、星穹鐵道:
- 查詢**即時便箋**
- 原神:包含樹脂、每日委託、洞天寶錢、參數質變儀、探索派遣
- 星穹鐵道:包含開拓力、每日實訓、模擬宇宙、歷戰餘響、委託執行
- **自動檢查即時便箋**:樹脂 (開拓力)、每日、寶錢、質變儀、探索派遣,當快額滿時發送提醒
- 查詢深境螺旋、忘卻之庭、虛構敘事紀錄,並可以保存每一期紀錄
- 查詢任意玩家的**角色展示櫃**,顯示展示櫃內角色的面板、聖遺物詳情

- 原神:
- 個人紀錄卡片,包含遊戲天數、成就、神瞳、世界探索度...等等
- 查詢旅行者札記
- 查看遊戲內公告,包含活動、卡池資訊
- 搜尋資料庫,包含角色、武器、各項物品、成就、七聖卡牌資料

## 使用方式
- 邀請到自己伺服器後,輸入斜線 `/` 查看各項指令
- 第一次請先使用指令 `/cookie設定`,Cookie 取得方式:https://bit.ly/3LgQkg0
- 設定自動簽到與樹脂提醒,使用指令 `/schedule排程`
- 設定自動簽到與即時便箋提醒,使用指令 `/schedule排程`

## 展示
更多展示圖片、GIF 請參考巴哈介紹文章:https://forum.gamer.com.tw/Co.php?bsn=36730&sn=162433
Expand All @@ -47,6 +52,7 @@ Genshin-Discord-Bot
├── cogs_external= 存放自訂的 discord.py cog 資料夾,你可以將自己指令的檔案放在這裡
├── configs = 存放設定檔的資料夾
├── database = SQLAlchemy ORM、資料庫操作相關的程式碼
| ├── alembic = = 資料庫結構變動版本控制
| ├── dataclass = 自定義的 data class
| └── legacy = 以前的資料庫程式碼,用來遷移舊資料之外沒有用
├── enka_network = 與 Enka Network API 相關的程式碼
Expand Down Expand Up @@ -114,14 +120,14 @@ Genshin-Discord-Bot

接下來沒特別說明都以 Windows、使用 Powershell 來說明

2. 找到你想放資料的地方,建立機器人資料夾 `Genshin-Discord-Bot`,然後進入
2. 找到你想放資料的地方,建立新資料夾 `Genshin-Discord-Bot`,然後進入

3. 下載 [docker-compose.yml](https://github.com/KT-Yeh/Genshin-Discord-Bot/blob/master/docker-compose.yml) 檔案,放在資料夾內

4. 文字編輯器開啟 `docker-compose.yml` 檔案,基本上都不用動,只要把你剛剛在 [#網頁端](#網頁端) 拿到的三個資料填入底下三個欄位即可,其他設定可根據自己的需求再改,完成後保存
- APPLICATION_ID=123456789
- TEST_SERVER_ID=123456789
- BOT_TOKEN=ABCD123456789
- APPLICATION_ID=`123456789`
- TEST_SERVER_ID=`123456789`
- BOT_TOKEN=`ABCD123456789`

5. 在此資料夾開啟 Powershell,輸入底下命令即可運行
```
Expand All @@ -140,7 +146,9 @@ Windows 右下角的鯨魚圖示打開 Docker Desktop 可以隨時管理機器
註3:若要在多個伺服器間使用,請在你機器人的私訊頻道內輸入 `$jsk sync`,並等待(約幾分鐘)Discord 將指令推送,稱為「全域同步」。


#### 從 v1.2.1 版升級上來
#### 從舊版 v1.2.1 版升級上來 (新安裝者不用看)

<details><summary>>>> 點此查看完整內容 <<<</summary>

1. 建立新的資料夾 `Genshin-Discord-Bot`,一樣先照上面做到第 4 步驟
2. 將舊版的 `data` 資料夾內的資料:`bot.db` (`emoji.json`),複製到新資料夾對應位置
Expand All @@ -159,6 +167,10 @@ Genshin-Discord-Bot/
- Linux:`sudo docker run -v $(pwd)/data:/app/data ghcr.io/kt-yeh/genshin-discord-bot:latest python main.py --migrate_database`
5. 完成變更資料庫後,執行 `docker-compose up` 即可開始運行機器人

</details>

---

### 檔案說明 & 資料備份
成功運行機器人後,你的資料夾結構應該是這樣:
```
Expand All @@ -175,7 +187,7 @@ Genshin-Discord-Bot/
├── grafana_dashboard.json = grafana 面板設定檔案
└── prometheus.yml = prometheus 伺服器設定擋
```
資料都放在 `data` 資料夾內,備份整個資料夾即可
資料都放在 `data` 資料夾內,備份整個資料夾即可;還原的時候將備份的資料覆蓋回 `data` 資料夾即可

### 如何更新
當專案有更新時,到 `Genshin-Discord-Bot` 目錄開啟 Powershell
Expand Down Expand Up @@ -293,8 +305,17 @@ remote_write:
</details>

## 致謝
- 原神 API 使用自: https://github.com/thesadru/genshin.py
- Discord API 使用自: https://github.com/Rapptz/discord.py
- Enka Network API 使用自: https://github.com/EnkaNetwork/API-docs
- Genshin-DB API 使用自: https://github.com/theBowja/genshin-db
- d.py-ext-prometheus: https://github.com/Apollo-Roboto/discord.py-ext-prometheus
API:
- Hoyolab: https://github.com/thesadru/genshin.py
- Discord: https://github.com/Rapptz/discord.py
- Enka Network: https://github.com/EnkaNetwork/API-docs
- Mihomo: https://march7th.xiaohei.moe/en/resource/mihomo_api.html
- Genshin-DB: https://github.com/theBowja/genshin-db

Card:
- [hattvr/enka-card](https://github.com/hattvr/enka-card)
- [DEViantUA/HSRCard](https://github.com/DEViantUA/HSRCard)
- [DEViantUA/GenshinPyRail](https://github.com/DEViantUA/GenshinPyRail)

Misc:
- [Apollo-Roboto/discord.py-ext-prometheus](https://github.com/Apollo-Roboto/discord.py-ext-prometheus)
49 changes: 35 additions & 14 deletions cogs/showcase/ui_starrail.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Callable
from typing import Any

import discord
import sentry_sdk
Expand All @@ -24,7 +24,7 @@ def __init__(self, showcase: Showcase) -> None:
discord.SelectOption(
label=f"★{character.rarity} Lv.{character.level} {character.name}",
value=str(i),
emoji=emoji.starrail_elements.get(character.element),
emoji=emoji.starrail_elements.get(character.element.name),
)
)
options.append(discord.SelectOption(label="刪除角色快取資料", value="-2", emoji="❌"))
Expand All @@ -33,9 +33,10 @@ def __init__(self, showcase: Showcase) -> None:
async def callback(self, interaction: discord.Interaction) -> None:
index = int(self.values[0])
if index >= 0: # 角色資料
embed = self.showcase.get_character_stat_embed(index)
await interaction.response.edit_message(
embed=embed, view=ShowcaseView(self.showcase, index)
await interaction.response.defer()
embed, file = await self.showcase.get_character_card_embed_file(index)
await interaction.edit_original_response(
embed=embed, view=ShowcaseView(self.showcase, index), attachments=[file]
)
elif index == -1: # 玩家資料一覽
embed = self.showcase.get_player_overview_embed()
Expand Down Expand Up @@ -66,15 +67,34 @@ async def callback(self, interaction: discord.Interaction) -> None:
class ShowcaseButton(discord.ui.Button):
"""角色展示櫃按鈕"""

def __init__(self, label: str, function: Callable[..., discord.Embed], *args, **kwargs):
def __init__(self, label: str, showcase: Showcase, chatacter_index: int):
super().__init__(style=discord.ButtonStyle.primary, label=label)
self.callback_func = function
self.callback_args = args
self.callback_kwargs = kwargs
self.label = label
self.showcase = showcase
self.character_index = chatacter_index

async def callback(self, interaction: discord.Interaction) -> Any:
embed = self.callback_func(*self.callback_args, **self.callback_kwargs)
await interaction.response.edit_message(embed=embed, attachments=[])
match self.label:
case "圖片":
await interaction.response.defer()
try:
embed, file = await self.showcase.get_character_card_embed_file(
self.character_index
)
except Exception:
embed = self.showcase.get_character_stat_embed(self.character_index)
await interaction.edit_original_response(embed=embed, attachments=[])
else:
await interaction.edit_original_response(embed=embed, attachments=[file])
case "面板":
embed = self.showcase.get_character_stat_embed(self.character_index)
await interaction.response.edit_message(embed=embed, attachments=[])
case "遺器":
embed = self.showcase.get_relic_stat_embed(self.character_index)
await interaction.response.edit_message(embed=embed, attachments=[])
case "詞條":
embed = self.showcase.get_relic_score_embed(self.character_index)
await interaction.response.edit_message(embed=embed, attachments=[])


class ShowcaseView(discord.ui.View):
Expand All @@ -83,9 +103,10 @@ class ShowcaseView(discord.ui.View):
def __init__(self, showcase: Showcase, character_index: int | None = None):
super().__init__(timeout=config.discord_view_long_timeout)
if character_index is not None:
self.add_item(ShowcaseButton("面板", showcase.get_character_stat_embed, character_index))
self.add_item(ShowcaseButton("遺器", showcase.get_relic_stat_embed, character_index))
self.add_item(ShowcaseButton("詞條", showcase.get_relic_score_embed, character_index))
self.add_item(ShowcaseButton("圖片", showcase, character_index))
self.add_item(ShowcaseButton("面板", showcase, character_index))
self.add_item(ShowcaseButton("遺器", showcase, character_index))
self.add_item(ShowcaseButton("詞條", showcase, character_index))

if len(showcase.data.characters) > 0:
self.add_item(ShowcaseCharactersDropdown(showcase))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""清空星穹鐵道展示櫃資料
Revision ID: 2ba9f9c494d7
Revises: 5d2af112b1f5
Create Date: 2024-02-13 14:59:36.015068
"""

from alembic import op

# revision identifiers, used by Alembic.
revision = "2ba9f9c494d7"
down_revision = "5d2af112b1f5"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.execute("DELETE FROM starrail_showcases")


def downgrade() -> None:
pass
10 changes: 5 additions & 5 deletions database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import genshin
import sqlalchemy
from mihomo import StarrailInfoParsedV1
from mihomo import StarrailInfoParsed
from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, mapped_column

from .dataclass import spiral_abyss
Expand Down Expand Up @@ -326,22 +326,22 @@ class StarrailShowcase(Base):
_raw_data: Mapped[bytes]
"""展示櫃 bytes 資料"""

def __init__(self, uid: int, data: StarrailInfoParsedV1):
def __init__(self, uid: int, data: StarrailInfoParsed):
"""初始化星穹鐵道展示櫃資料表的物件。
Parameters:
------
uid: `int`
星穹鐵道 UID。
data: `StarrailInfoParsedV1`
data: `StarrailInfoParsed`
Mihomo API 資料。
"""
json_str = data.json(by_alias=True)
self.uid = uid
self._raw_data = zlib.compress(json_str.encode("utf-8"), level=5)

@property
def data(self) -> StarrailInfoParsedV1:
def data(self) -> StarrailInfoParsed:
"""Mihomo API 資料"""
data = zlib.decompress(self._raw_data).decode("utf-8")
return StarrailInfoParsedV1.parse_raw(data)
return StarrailInfoParsed.parse_raw(data)
2 changes: 1 addition & 1 deletion enka_network/enka_card
23 changes: 19 additions & 4 deletions genshin_py/parser/starrail.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,26 @@ def parse_starrail_character(character: genshin.models.StarRailDetailCharacter)
return embed


def parse_starrail_hall_overview(hall: genshin.models.StarRailChallenge) -> discord.Embed:
def parse_starrail_hall_overview(
hall: genshin.models.StarRailChallenge | genshin.models.StarRailPureFiction,
) -> discord.Embed:
"""解析星穹鐵道忘卻之庭概述資料,包含關卡進度、戰鬥次數、獲得星數、期數"""
has_crown: bool = hall.total_battles == 10 and hall.total_stars == 30
desc: str = f"{hall.begin_time.datetime.strftime('%Y.%m.%d')} ~ {hall.end_time.datetime.strftime('%Y.%m.%d')}\n"
# 檢查皇冠資格
has_crown: bool = False
if isinstance(hall, genshin.models.StarRailChallenge):
if hall.total_stars == 36:
non_skip_battles = [floor.is_fast for floor in hall.floors].count(False)
has_crown = hall.total_battles == non_skip_battles
else: # isinstance(hall, genshin.models.StarRailPureFiction)
if hall.total_stars == 12:
non_skip_battles = [floor.is_fast for floor in hall.floors].count(False)
has_crown = hall.total_battles == non_skip_battles
battle_nums = f"👑 ({hall.total_battles})" if has_crown else hall.total_battles

desc: str = (
f"{hall.begin_time.datetime.strftime('%Y.%m.%d')} ~ {hall.end_time.datetime.strftime('%Y.%m.%d')}\n"
)
desc += f"關卡進度:{hall.max_floor}\n"
desc += f"戰鬥次數:{'👑 (10)' if has_crown else hall.total_battles} ★:{hall.total_stars}\n"
desc += f"戰鬥次數:{battle_nums} ★:{hall.total_stars}\n"
embed = discord.Embed(description=desc, color=0x934151)
return embed
Loading

0 comments on commit 2eaeaad

Please sign in to comment.