Skip to content

Commit c2f9e70

Browse files
committed
1.5.0
- サーバーステータスを R6SSS WebAPI からではなく内部的に取得するよう変更 - Pycord を `2.4.1` へ更新
1 parent aacdaaf commit c2f9e70

9 files changed

+113
-30
lines changed

README.md

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# R6SServerStatusBot
1+
# R6SSS
22
Discordのテキストチャンネルにレインボーシックス シージのサーバーステータスを送信してくれるBotです。
33

44
[**🛡️ サポートサーバー**](https://discord.gg/bMf9dDjndC)
@@ -9,11 +9,11 @@ Discordのテキストチャンネルにレインボーシックス シージの
99
### 稼働状況
1010
![R6SSS Discord Bot](https://cronitor.io/badges/Za7Cbb/production/uXc8wYxprFTpoguQbbHGQ95r5u4.svg)
1111

12-
[**[Botをサーバーに招待]**](https://discord.com/api/oauth2/authorize?client_id=990497421488451615&permissions=76800&scope=bot%20applications.commands)
12+
[**[Botをサーバーに招待]**](https://discord.com/api/oauth2/authorize?client_id=990497421488451615&permissions=76800&scope=bot%20applications.commands)
1313

1414
## コマンド
15-
- `create [テキストチャンネル]` - 指定したテキストチャンネルへ**1分ごとに自動更新される**サーバーステータスを作成します。
16-
- 送信されたサーバーステータスは、メッセージが削除されるか、`create` コマンドで新しいサーバーステータスが作成されるまで更新され続けます
15+
- `create [テキストチャンネル]` - 指定したテキストチャンネルへ**5分ごとに自動更新される**サーバーステータスを作成します。
16+
- 送信されたサーバーステータスは、**メッセージが削除**されるか、**`create` コマンドで新しいサーバーステータスが作成**されるまで更新され続けます
1717
- テキストチャンネルを指定しなかった場合は、コマンドを実行したチャンネルへ送信されます。
1818
- `status` - 現在のサーバーステータスを送信します。(自動更新はされません)
1919
- `setindicator <True/False>` - サーバーステータスのインジケーター(絵文字)をテキストチャンネルの名前の先頭に表示するかどうかを設定します。
@@ -22,9 +22,5 @@ Discordのテキストチャンネルにレインボーシックス シージの
2222
- `English` (英語)
2323
- `日本語 / Japanese` (日本語)
2424
- `한국어 / Korean` (韓国語)
25-
- `about` - このBotの情報を送信します。
2625
- `ping` - このBotのレイテンシーを送信します。
27-
28-
## API
29-
- URL: http://api.r6sss.milkeyyy.com/
30-
- [**詳しくはこちら**](https://github.com/Milkeyyy/R6SServerStatusBot_WebAPI)
26+
- `about` - このBotの情報を送信します。

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Jinja2==3.1.2
2525
MarkupSafe==2.1.1
2626
multidict==6.0.3
2727
outcome==1.2.0
28-
py-cord==2.4.0
28+
py-cord==2.4.1
2929
pycparser==2.21
3030
pydantic==1.10.2
3131
PySocks==1.7.1

src/heartbeat.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ def loadKeys():
2727
heartbeat = cronitor.Monitor(v[1])
2828
monitor = cronitor.Monitor(v[2])
2929

30-
f.close()
30+
f.close()

src/localizations.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ def translate(text):
2222
return data["Text"][text][locale]
2323
except KeyError as e:
2424
#logging.error(str(e))
25-
return text
25+
return text

src/main.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import logging
44
import os
55
import sys
6+
import time
67
import traceback
78

89
import discord
910
from discord.commands import Option
1011
from discord.ext import tasks
12+
import schedule
1113

1214
import heartbeat
1315
import localizations
@@ -21,7 +23,7 @@
2123
# Botの名前
2224
bot_name = "R6SSS"
2325
# Botのバージョン
24-
bot_version = "1.4.1"
26+
bot_version = "1.5.0"
2527

2628
default_embed = discord.Embed
2729

@@ -158,7 +160,7 @@ async def convertGuildData():
158160
new_gd[guild_id]["server_status_message"]["language"] = old_gd[guild_id]["server_status_message"][2]
159161
new_gd[guild_id]["server_status_message"]["status_indicator"] = True
160162

161-
# 書き込み用にファイルを開く
163+
# 書き込み用にファイルを開く
162164
file = open("guilds.json", "w", encoding="utf-8")
163165
# 辞書をファイルへ保存
164166
file.write(json.dumps(new_gd, indent=2, sort_keys=True))
@@ -172,7 +174,7 @@ async def convertGuildData():
172174
# 1分毎にサーバーステータスを更新する
173175
serverstatus_loop_isrunning = False
174176

175-
@tasks.loop(seconds=60.0)
177+
@tasks.loop(seconds=300.0)
176178
async def updateserverstatus():
177179
global serverstatus_loop_isrunning
178180
serverstatus_loop_isrunning = True
@@ -214,6 +216,14 @@ async def updateserverstatus():
214216
if ch_id != 0 and msg_id != 0 and loc != None:
215217
# IDからテキストチャンネルを取得する
216218
ch = client.get_channel(ch_id)
219+
# チャンネルが存在しない場合はギルドデータからチャンネルIDとメッセージIDを削除する
220+
if ch == None:
221+
db[str(guild.id)]["server_status_message"]["channel_id"] = 0
222+
db[str(guild.id)]["server_status_message"]["message_id"] = 0
223+
# ギルドデータを保存
224+
await saveGuildData()
225+
continue # ループを続ける
226+
217227
ch_name = ch.name
218228

219229
e = ""

src/serverstatus.py

+3-13
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
import logging
44
import urllib
55

6+
import serverstatus_api
67
import statusindicator
78

8-
# サーバーステータスAPIのURL
9-
api_url = "https://api.r6sss.milkeyyy.com"
109

1110
# サーバーステータス辞書
1211
data = {}
@@ -18,17 +17,8 @@
1817
async def get():
1918
global indicator
2019

21-
# サーバーステータスを取得する
22-
res = urllib.request.urlopen(urllib.request.Request(api_url))
23-
#logging.info(str(res.read()))
24-
25-
# ステータスコードが200以外の場合はUnknownなデータを返す
26-
if res.status != 200:
27-
status = {"Unknown": {"Status": {"Connectivity": "Unknown", "Authentication": "Unknown", "Leaderboard": "Unknown", "Matchmaking": "Unknown", "Purchase": "Unknown"}, "Maintenance": None, "ImpactedFeatures": None}, "_update_date": datetime.datetime.utcnow().timestamp()}
28-
indicator = statusindicator.Unknown
29-
return status
30-
31-
status = json.loads(res.read())
20+
# サーバーステータスを取得
21+
status = await serverstatus_api.get_serverstatus()
3222
status["_update_date"] = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9)))
3323

3424
status_list = []

src/serverstatus_api.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import datetime
2+
import json
3+
import logging
4+
import threading
5+
from urllib import request
6+
7+
8+
class serverstatus:
9+
# サーバーステータスAPIのURL
10+
api_url = "https://game-status-api.ubisoft.com/v1/instances?spaceIds=57e580a1-6383-4506-9509-10a390b7e2f1,05bfb3f7-6c21-4c42-be1f-97a33fb5cf66,96c1d424-057e-4ff7-860b-6b9c9222bdbf,98a601e5-ca91-4440-b1c5-753f601a2c90,631d8095-c443-4e21-b301-4af1a0929c27"
11+
pc_api_url = "https://game-status-api.ubisoft.com/v1/instances?appIds=e3d5ea9e-50bd-43b7-88bf-39794f4e3d40"
12+
13+
# サーバーステータス辞書を初期化
14+
data = {}
15+
16+
# サーバーステータスを取得して整えて返す
17+
def get():
18+
logging.info("サーバーステータスを取得")
19+
# サーバーステータスを取得する
20+
res = request.urlopen(request.Request(serverstatus.api_url))
21+
#logging.info(str(res.read()))
22+
res_pc = request.urlopen(request.Request(serverstatus.pc_api_url))
23+
#logging.info(str(res_pc.read()))
24+
25+
# ステータスコードが200ではない場合は不明というステータスを返す
26+
if res.status != 200 or res_pc.status != 200:
27+
logging.error(f"サーバーステータスの取得に失敗 - ステータスコード: {res.status} / {res_pc.status}")
28+
status = {"Unknown": {"Status": {"Connectivity": "Unknown", "Authentication": "Unknown", "Leaderboard": "Unknown", "Matchmaking": "Unknown", "Purchase": "Unknown"}, "Maintenance": False}, "_Update_At": datetime.datetime.utcnow().timestamp()}
29+
return status
30+
31+
raw_status = json.loads(res_pc.read())
32+
raw_status.extend(json.loads(res.read()))
33+
logging.info("取得完了")
34+
35+
# 各プラットフォームのステータスをループ、ステータス辞書に加える
36+
status = {}
37+
for s in raw_status:
38+
p = s["Platform"]
39+
status[p] = {"Status": {"Connectivity": None, "Authentication": "Operational", "Leaderboard": "Operational", "Matchmaking": "Operational", "Purchase": "Operational"}, "Maintenance": None}
40+
41+
status[p]["Status"]["Connectivity"] = s["Status"]
42+
if status[p]["Status"]["Connectivity"] == "Online": status[p]["Status"]["Connectivity"] = "Operational"
43+
44+
# ImpactedFeatures をループする リストに含まれる場合は停止中なので、該当するステータスをOutageにする
45+
for f in s["ImpactedFeatures"]:
46+
status[p]["Status"][f] = "Outage"
47+
48+
# Maintenance が null の場合はステータスの Maintenance に False をセットする
49+
if s["Maintenance"] == None:
50+
status[p]["Maintenance"] = False
51+
else:
52+
status[p]["Maintenance"] = s["Maintenance"]
53+
54+
status[p]["_Update_At"] = datetime.datetime.utcnow().timestamp()
55+
56+
#logging.info(str(status))
57+
58+
logging.info("サーバーステータスの整形完了")
59+
logging.info(str(status))
60+
return status
61+
62+
def update_status():
63+
serverstatus.data = serverstatus.get()
64+
65+
def update_serverstatus():
66+
serverstatus.update_status()
67+
logging.info("Server Status Updated")
68+
69+
async def get_serverstatus(platform: list = None):
70+
status = {}
71+
72+
# パラメーターが指定されていない場合は全てのプラットフォームのステータスを返す
73+
if platform == None:
74+
status = serverstatus.data
75+
if "_last_update" in status.keys(): del status["_last_update"]
76+
else:
77+
# 指定されたプラットフォームのステータスだけ返す
78+
for p in platform:
79+
d = serverstatus.data.get(p)
80+
if d != None:
81+
status[p] = d
82+
83+
# JSONでサーバーステータスのデータを返す
84+
return status
85+
86+
# サーバーステータスの初回更新
87+
serverstatus.update_status()

src/statusicon.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
Interrupted = "<:Interrupted:1052687159062179910>"
33
Degraded = "<:Degraded:1052687157627731968>"
44
Unknown = "<:Unknown:1052687154549112832>"
5-
Maintenance = "<:Maintenance:1052687156033880144>"
5+
Maintenance = "<:Maintenance:1052687156033880144>"

src/statusindicator.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
Degraded = "🔴"
44
Maintenance = "🔧"
55
Unknown = "⬜"
6-
List = [Operational, Interrupted, Degraded, Maintenance, Unknown]
6+
List = [Operational, Interrupted, Degraded, Maintenance, Unknown]

0 commit comments

Comments
 (0)