Skip to content

Commit 597951a

Browse files
committed
統計サポート
1 parent 53ebae6 commit 597951a

File tree

5 files changed

+231
-6
lines changed

5 files changed

+231
-6
lines changed

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
def skip_enum_members(app, what, name, obj, skip, options):
6363
# Enum クラスのメンバーをスキップする
64-
if isinstance(obj, Enum):
64+
if isinstance(obj, Enum) and obj.__doc__ is not None:
6565
return True # 出力しない
6666
return None # それ以外はデフォルトの動作に任せる
6767

docs/reference/sites.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,18 @@
132132

133133
.. autofunction:: scapi.get_community_featured
134134

135+
.. autoclass:: scapi.TotalSiteStats
136+
137+
.. autofunction:: scapi.get_total_site_stats
138+
139+
.. autoclass:: scapi.MonthlySiteTraffic
140+
141+
.. autofunction:: scapi.get_monthly_site_traffic
142+
143+
.. autoclass:: scapi.MonthlyActivity
144+
145+
.. autofunction:: scapi.get_monthly_activity
146+
135147
その他
136148
------
137149

scapi/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414
check_email,
1515
translation,
1616
get_supported_translation_language,
17-
tts
17+
tts,
18+
TotalSiteStats,
19+
get_total_site_stats,
20+
MonthlySiteTraffic,
21+
get_monthly_site_traffic,
22+
MonthlyActivity,
23+
get_monthly_activity,
1824
)
1925

2026
from .sites.mainpage import (

scapi/sites/other.py

Lines changed: 177 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
from __future__ import annotations
22

3-
from enum import Enum
4-
from typing import TYPE_CHECKING, Literal
3+
from dataclasses import dataclass
4+
from enum import Enum, StrEnum
5+
from typing import TYPE_CHECKING, Literal, TypedDict
56

67
from ..utils.types import (
78
CheckAnyPayload,
89
TranslatePayload,
9-
TranslateSupportedPayload
10+
TranslateSupportedPayload,
11+
TotalSiteStatusPayload,
12+
MonthlySiteTrafficPayload,
13+
MonthlyActivityGraphPayload,
14+
MonthlyActivityPayload
1015
)
1116
from ..utils.common import (
1217
UNKNOWN,
1318
MAYBE_UNKNOWN,
19+
dt_from_timestamp
1420
)
1521

1622
if TYPE_CHECKING:
@@ -144,4 +150,171 @@ async def tts(client:"HTTPClient",language:str,type:Literal["male","female"],tex
144150
"text":text
145151
}
146152
)
147-
return response.data
153+
return response.data
154+
155+
@dataclass
156+
class TotalSiteStats:
157+
project_count:int
158+
user_count:int
159+
studio_comment_count:int
160+
profile_comment_count:int
161+
studio_count:int
162+
comment_count:int
163+
project_comment_count:int
164+
_timestamp:float
165+
166+
async def get_total_site_stats(client:HTTPClient) -> TotalSiteStats:
167+
"""
168+
全体の統計情報を取得する
169+
170+
Args:
171+
client (HTTPClient): 通信に使用するHTTPClient
172+
173+
Returns:
174+
TotalSiteStats:
175+
"""
176+
response = await client.get("https://scratch.mit.edu/statistics/data/daily/")
177+
data:TotalSiteStatusPayload = response.json()
178+
return TotalSiteStats(
179+
project_count=data.get("PROJECT_COUNT"),
180+
user_count=data.get("USER_COUNT"),
181+
studio_comment_count=data.get("STUDIO_COMMENT_COUNT"),
182+
profile_comment_count=data.get("PROFILE_COMMENT_COUNT"),
183+
studio_count=data.get("STUDIO_COUNT"),
184+
comment_count=data.get("COMMENT_COUNT"),
185+
project_comment_count=data.get("PROJECT_COMMENT_COUNT"),
186+
_timestamp=data.get("_TS")
187+
)
188+
189+
@dataclass
190+
class MonthlySiteTraffic:
191+
pageviews:int
192+
users:int
193+
sessions:int
194+
_timestamp:float
195+
196+
async def get_monthly_site_traffic(client:HTTPClient) -> MonthlySiteTraffic:
197+
"""
198+
月のアクティビティ数を取得する。
199+
200+
Args:
201+
client (HTTPClient): 通信に使用するHTTPClient
202+
203+
Returns:
204+
MonthlySiteTraffic:
205+
"""
206+
response = await client.get("https://scratch.mit.edu/statistics/data/monthly-ga/")
207+
data:MonthlySiteTrafficPayload = response.json()
208+
return MonthlySiteTraffic(
209+
pageviews=data.get("pageviews"),
210+
users=data.get("users"),
211+
sessions=data.get("sessions"),
212+
_timestamp=data.get("_TS")
213+
)
214+
215+
216+
217+
GraphData = list[tuple[int, int]]
218+
219+
@dataclass
220+
class CommentData:
221+
"""コメント統計データ"""
222+
project: GraphData
223+
studio: GraphData
224+
profile: GraphData
225+
226+
@dataclass
227+
class ActivityData:
228+
"""アクティビティ統計データ"""
229+
new_projects: GraphData
230+
new_users: GraphData
231+
new_comments: GraphData
232+
233+
@dataclass
234+
class ActiveUserData:
235+
"""アクティブユーザー統計データ"""
236+
project_creators: GraphData
237+
comment_creators: GraphData
238+
239+
@dataclass
240+
class ProjectData:
241+
"""プロジェクト統計データ"""
242+
new_projects: GraphData
243+
remix_projects: GraphData
244+
245+
@dataclass
246+
class AgeDistributionData:
247+
"""年齢分布データ"""
248+
registration_age: GraphData
249+
250+
@dataclass
251+
class MonthlyActivity:
252+
"""
253+
月間アクティビティ統計情報を表す
254+
"""
255+
_timestamp: float
256+
comment_data: CommentData
257+
activity_data: ActivityData
258+
active_user_data: ActiveUserData
259+
project_data: ProjectData
260+
age_distribution_data: AgeDistributionData
261+
country_distribution: dict[str,int]
262+
263+
def _parse_graph_data(raw_data: list[MonthlyActivityGraphPayload], index: int) -> GraphData:
264+
if index < len(raw_data) and "values" in raw_data[index]:
265+
return [(d["x"], d["y"]) for d in raw_data[index]["values"]]
266+
return []
267+
268+
async def get_monthly_activity(client: HTTPClient) -> MonthlyActivity:
269+
"""
270+
月間アクティビティ統計情報を取得する。
271+
272+
Args:
273+
client (HTTPClient): 通信に使用するHTTPClient
274+
275+
Returns:
276+
MonthlyActivity:
277+
"""
278+
response = await client.get("https://scratch.mit.edu/statistics/data/monthly/")
279+
data:MonthlyActivityPayload = response.json()
280+
281+
raw_comment_data = data.get("comment_data", [])
282+
comment_data = CommentData(
283+
project=_parse_graph_data(raw_comment_data, 0),
284+
studio=_parse_graph_data(raw_comment_data, 1),
285+
profile=_parse_graph_data(raw_comment_data, 2),
286+
)
287+
288+
raw_activity_data = data.get("activity_data", [])
289+
activity_data = ActivityData(
290+
new_projects=_parse_graph_data(raw_activity_data, 0),
291+
new_users=_parse_graph_data(raw_activity_data, 1),
292+
new_comments=_parse_graph_data(raw_activity_data, 2),
293+
)
294+
295+
raw_active_user_data = data.get("active_user_data", [])
296+
active_user_data = ActiveUserData(
297+
project_creators=_parse_graph_data(raw_active_user_data, 0),
298+
comment_creators=_parse_graph_data(raw_active_user_data, 1),
299+
)
300+
301+
raw_project_data = data.get("project_data", [])
302+
project_data = ProjectData(
303+
new_projects=_parse_graph_data(raw_project_data, 0),
304+
remix_projects=_parse_graph_data(raw_project_data, 1),
305+
)
306+
307+
raw_age_distribution_data = data.get("age_distribution_data", [])
308+
age_distribution_data = AgeDistributionData(
309+
registration_age=_parse_graph_data(raw_age_distribution_data, 0)
310+
)
311+
312+
return MonthlyActivity(
313+
_timestamp=data.get("_TS", 0.0),
314+
comment_data=comment_data,
315+
activity_data=activity_data,
316+
active_user_data=active_user_data,
317+
project_data=project_data,
318+
country_distribution=data.get("country_distribution", {}),
319+
age_distribution_data=age_distribution_data,
320+
)

scapi/utils/types.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,40 @@ class TranslateSupportedLanguagePayload(TypedDict):
432432
class TranslateSupportedPayload(TypedDict):
433433
result:list[TranslateSupportedLanguagePayload]
434434

435+
class TotalSiteStatusPayload(TypedDict):
436+
PROJECT_COUNT:int
437+
USER_COUNT:int
438+
STUDIO_COMMENT_COUNT:int
439+
PROFILE_COMMENT_COUNT:int
440+
STUDIO_COUNT:int
441+
COMMENT_COUNT:int
442+
PROJECT_COMMENT_COUNT:int
443+
_TS:float
444+
445+
class MonthlySiteTrafficPayload(TypedDict):
446+
pageviews:int
447+
users:int
448+
sessions:int
449+
_TS:float
450+
451+
class MonthlyActivityGraphValuePayload(TypedDict):
452+
x:int
453+
y:int
454+
455+
class MonthlyActivityGraphPayload(TypedDict):
456+
values:list[MonthlyActivityGraphValuePayload]
457+
key:str
458+
color:NotRequired[str]
459+
460+
class MonthlyActivityPayload(TypedDict):
461+
comment_data:list[MonthlyActivityGraphPayload]
462+
_TS:float
463+
activity_data:list[MonthlyActivityGraphPayload]
464+
active_user_data:list[MonthlyActivityGraphPayload]
465+
project_data:list[MonthlyActivityGraphPayload]
466+
age_distribution_data:list[MonthlyActivityGraphPayload]
467+
country_distribution:dict[str,int]
468+
435469
class WSCloudActivityPayload(TypedDict):
436470
method:Literal["set"]
437471
name:str

0 commit comments

Comments
 (0)