ossapi 3.1.9__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ossapi-3.1.9 → ossapi-3.3.0}/PKG-INFO +22 -5
- {ossapi-3.1.9 → ossapi-3.3.0}/README.md +21 -4
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/__init__.py +7 -6
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/enums.py +18 -3
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/models.py +67 -44
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/ossapiv2.py +114 -20
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/ossapiv2_async.py +107 -19
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi.egg-info/PKG-INFO +22 -5
- {ossapi-3.1.9 → ossapi-3.3.0}/pyproject.toml +1 -1
- {ossapi-3.1.9 → ossapi-3.3.0}/tests/__init__.py +7 -10
- {ossapi-3.1.9 → ossapi-3.3.0}/tests/test_endpoints.py +42 -4
- {ossapi-3.1.9 → ossapi-3.3.0}/tests/test_models.py +1 -1
- {ossapi-3.1.9 → ossapi-3.3.0}/tests/test_v1.py +4 -4
- {ossapi-3.1.9 → ossapi-3.3.0}/LICENSE +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/encoder.py +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/mod.py +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/ossapi.py +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/replay.py +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi/utils.py +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi.egg-info/SOURCES.txt +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi.egg-info/dependency_links.txt +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi.egg-info/requires.txt +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/ossapi.egg-info/top_level.txt +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/setup.cfg +0 -0
- {ossapi-3.1.9 → ossapi-3.3.0}/tests/test_cursor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ossapi
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: Complete python wrapper for osu! api v2 and v1.
|
|
5
5
|
Author-email: Liam DeVoe <orionldevoe@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/circleguard/ossapi
|
|
@@ -14,13 +14,14 @@ License-File: LICENSE
|
|
|
14
14
|
|
|
15
15
|
# ossapi ([documentation](https://circleguard.github.io/ossapi/)) [](https://pypi.org/project/ossapi/)
|
|
16
16
|
|
|
17
|
-
ossapi is
|
|
17
|
+
ossapi is the definitive python wrapper for the osu! api. ossapi has complete coverage of [api v2](https://osu.ppy.sh/docs/index.html) and [api v1](https://github.com/ppy/osu-api/wiki), and provides both sync (`Ossapi`) and async (`OssapiAsync`) versions for api v2.
|
|
18
18
|
|
|
19
19
|
If you need support or would like to contribute, feel free to ask in the `#ossapi` channel of the [circleguard discord](https://discord.gg/e84qxkQ).
|
|
20
20
|
|
|
21
21
|
* [Installation](#installation)
|
|
22
22
|
* [Quickstart](#quickstart)
|
|
23
23
|
* [Async](#async)
|
|
24
|
+
* [Lazer](#lazer)
|
|
24
25
|
* [Endpoints](#endpoints)
|
|
25
26
|
* [Beatmaps](#endpoints-beatmaps)
|
|
26
27
|
* [Beatmapsets](#endpoints-beatmapsets)
|
|
@@ -73,7 +74,7 @@ from ossapi import Ossapi
|
|
|
73
74
|
api = Ossapi(client_id, client_secret)
|
|
74
75
|
|
|
75
76
|
# see docs for full list of endpoints
|
|
76
|
-
print(api.user("
|
|
77
|
+
print(api.user("tybug").username)
|
|
77
78
|
print(api.user(12092800, mode="osu").username)
|
|
78
79
|
print(api.beatmap(221777).id)
|
|
79
80
|
```
|
|
@@ -89,13 +90,29 @@ from ossapi import Ossapi
|
|
|
89
90
|
api = Ossapi(client_id, client_secret)
|
|
90
91
|
|
|
91
92
|
async def main():
|
|
92
|
-
await api.user("
|
|
93
|
+
await api.user("tybug")
|
|
93
94
|
|
|
94
95
|
asyncio.run(main())
|
|
95
96
|
```
|
|
96
97
|
|
|
97
98
|
[Read more about OssapiAsync on the docs.](https://circleguard.github.io/ossapi/async.html)
|
|
98
99
|
|
|
100
|
+
## Lazer
|
|
101
|
+
|
|
102
|
+
You can retrieve lazer-specific data (scores, leaderboards, etc) with ossapi:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from ossapi import Ossapi
|
|
106
|
+
|
|
107
|
+
api_lazer = Ossapi(client_id, client_secret, domain="lazer")
|
|
108
|
+
|
|
109
|
+
# best score on the lazer server (lazer + osu scores combined)
|
|
110
|
+
scores = api_lazer.user_scores(12092800, "best")
|
|
111
|
+
print(scores[0].pp)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
[Read more about domains on the docs.](https://circleguard.github.io/ossapi/domains.html)
|
|
115
|
+
|
|
99
116
|
## Endpoints
|
|
100
117
|
|
|
101
118
|
All endpoints for api v2.
|
|
@@ -170,7 +187,7 @@ All endpoints for api v2.
|
|
|
170
187
|
|
|
171
188
|
## API v1 Usage
|
|
172
189
|
|
|
173
|
-
You can get your api v1 key at <https://osu.ppy.sh/
|
|
190
|
+
You can get your api v1 key at <https://osu.ppy.sh/home/account/edit#legacy-api>.
|
|
174
191
|
|
|
175
192
|
Basic usage:
|
|
176
193
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# ossapi ([documentation](https://circleguard.github.io/ossapi/)) [](https://pypi.org/project/ossapi/)
|
|
2
2
|
|
|
3
|
-
ossapi is
|
|
3
|
+
ossapi is the definitive python wrapper for the osu! api. ossapi has complete coverage of [api v2](https://osu.ppy.sh/docs/index.html) and [api v1](https://github.com/ppy/osu-api/wiki), and provides both sync (`Ossapi`) and async (`OssapiAsync`) versions for api v2.
|
|
4
4
|
|
|
5
5
|
If you need support or would like to contribute, feel free to ask in the `#ossapi` channel of the [circleguard discord](https://discord.gg/e84qxkQ).
|
|
6
6
|
|
|
7
7
|
* [Installation](#installation)
|
|
8
8
|
* [Quickstart](#quickstart)
|
|
9
9
|
* [Async](#async)
|
|
10
|
+
* [Lazer](#lazer)
|
|
10
11
|
* [Endpoints](#endpoints)
|
|
11
12
|
* [Beatmaps](#endpoints-beatmaps)
|
|
12
13
|
* [Beatmapsets](#endpoints-beatmapsets)
|
|
@@ -59,7 +60,7 @@ from ossapi import Ossapi
|
|
|
59
60
|
api = Ossapi(client_id, client_secret)
|
|
60
61
|
|
|
61
62
|
# see docs for full list of endpoints
|
|
62
|
-
print(api.user("
|
|
63
|
+
print(api.user("tybug").username)
|
|
63
64
|
print(api.user(12092800, mode="osu").username)
|
|
64
65
|
print(api.beatmap(221777).id)
|
|
65
66
|
```
|
|
@@ -75,13 +76,29 @@ from ossapi import Ossapi
|
|
|
75
76
|
api = Ossapi(client_id, client_secret)
|
|
76
77
|
|
|
77
78
|
async def main():
|
|
78
|
-
await api.user("
|
|
79
|
+
await api.user("tybug")
|
|
79
80
|
|
|
80
81
|
asyncio.run(main())
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
[Read more about OssapiAsync on the docs.](https://circleguard.github.io/ossapi/async.html)
|
|
84
85
|
|
|
86
|
+
## Lazer
|
|
87
|
+
|
|
88
|
+
You can retrieve lazer-specific data (scores, leaderboards, etc) with ossapi:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from ossapi import Ossapi
|
|
92
|
+
|
|
93
|
+
api_lazer = Ossapi(client_id, client_secret, domain="lazer")
|
|
94
|
+
|
|
95
|
+
# best score on the lazer server (lazer + osu scores combined)
|
|
96
|
+
scores = api_lazer.user_scores(12092800, "best")
|
|
97
|
+
print(scores[0].pp)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
[Read more about domains on the docs.](https://circleguard.github.io/ossapi/domains.html)
|
|
101
|
+
|
|
85
102
|
## Endpoints
|
|
86
103
|
|
|
87
104
|
All endpoints for api v2.
|
|
@@ -156,7 +173,7 @@ All endpoints for api v2.
|
|
|
156
173
|
|
|
157
174
|
## API v1 Usage
|
|
158
175
|
|
|
159
|
-
You can get your api v1 key at <https://osu.ppy.sh/
|
|
176
|
+
You can get your api v1 key at <https://osu.ppy.sh/home/account/edit#legacy-api>.
|
|
160
177
|
|
|
161
178
|
Basic usage:
|
|
162
179
|
|
|
@@ -6,7 +6,7 @@ from importlib import metadata
|
|
|
6
6
|
|
|
7
7
|
from ossapi.ossapi import (OssapiV1, ReplayUnavailableException,
|
|
8
8
|
InvalidKeyException, APIException)
|
|
9
|
-
from ossapi.ossapiv2 import Ossapi, Grant, Scope
|
|
9
|
+
from ossapi.ossapiv2 import Ossapi, Grant, Scope, Domain
|
|
10
10
|
from ossapi.models import (Beatmap, BeatmapCompact, BeatmapUserScore,
|
|
11
11
|
ForumTopicAndPosts, Search, CommentBundle, Cursor, Score,
|
|
12
12
|
BeatmapsetSearchResult, ModdingHistoryEventsBundle, User, Rankings,
|
|
@@ -17,7 +17,8 @@ from ossapi.models import (Beatmap, BeatmapCompact, BeatmapUserScore,
|
|
|
17
17
|
UserCompact, BeatmapsetCompact, ForumPoll, Room, RoomPlaylistItem,
|
|
18
18
|
RoomPlaylistItemMod, RoomLeaderboardScore, RoomLeaderboardUserScore,
|
|
19
19
|
RoomLeaderboard, Match, Matches, MatchResponse, ScoreMatchInfo, MatchGame,
|
|
20
|
-
MatchEventDetail, MatchEvent, ScoringType, TeamType
|
|
20
|
+
MatchEventDetail, MatchEvent, ScoringType, TeamType, StatisticsVariant,
|
|
21
|
+
Events)
|
|
21
22
|
from ossapi.enums import (GameMode, ScoreType, RankingFilter, RankingType,
|
|
22
23
|
UserBeatmapType, BeatmapDiscussionPostSort, UserLookupKey,
|
|
23
24
|
BeatmapsetEventType, CommentableType, CommentSort, ForumTopicSort,
|
|
@@ -26,7 +27,7 @@ from ossapi.enums import (GameMode, ScoreType, RankingFilter, RankingType,
|
|
|
26
27
|
BeatmapsetSearchCategory, BeatmapsetSearchMode,
|
|
27
28
|
BeatmapsetSearchExplicitContent, BeatmapsetSearchLanguage,
|
|
28
29
|
BeatmapsetSearchGenre, NewsPostKey, BeatmapsetSearchSort, RoomType,
|
|
29
|
-
RoomCategory, RoomSearchType, MatchEventType)
|
|
30
|
+
RoomCategory, RoomSearchType, MatchEventType, Variant, EventsSort)
|
|
30
31
|
from ossapi.mod import Mod
|
|
31
32
|
from ossapi.replay import Replay
|
|
32
33
|
from ossapi.encoder import ModelEncoder, serialize_model
|
|
@@ -42,7 +43,7 @@ __all__ = [
|
|
|
42
43
|
"OssapiV1", "ReplayUnavailableException", "InvalidKeyException",
|
|
43
44
|
"APIException",
|
|
44
45
|
# OssapiV2 core
|
|
45
|
-
"Ossapi", "OssapiAsync", "Grant", "Scope",
|
|
46
|
+
"Ossapi", "OssapiAsync", "Grant", "Scope", "Domain",
|
|
46
47
|
# OssapiV2 models
|
|
47
48
|
"Beatmap", "BeatmapCompact", "BeatmapUserScore", "ForumTopicAndPosts",
|
|
48
49
|
"Search", "CommentBundle", "Cursor", "Score", "BeatmapsetSearchResult",
|
|
@@ -55,7 +56,7 @@ __all__ = [
|
|
|
55
56
|
"Room", "RoomPlaylistItem", "RoomPlaylistItemMod", "RoomLeaderboardScore",
|
|
56
57
|
"RoomLeaderboardUserScore", "RoomLeaderboard", "Match", "Matches",
|
|
57
58
|
"MatchResponse", "ScoreMatchInfo", "MatchGame", "MatchEventDetail",
|
|
58
|
-
"MatchEvent",
|
|
59
|
+
"MatchEvent", "StatisticsVariant", "Events",
|
|
59
60
|
# OssapiV2 enums
|
|
60
61
|
"GameMode", "ScoreType", "RankingFilter", "RankingType",
|
|
61
62
|
"UserBeatmapType", "BeatmapDiscussionPostSort", "UserLookupKey",
|
|
@@ -66,7 +67,7 @@ __all__ = [
|
|
|
66
67
|
"BeatmapsetSearchExplicitContent", "BeatmapsetSearchLanguage",
|
|
67
68
|
"BeatmapsetSearchGenre", "NewsPostKey", "BeatmapsetSearchSort", "RoomType",
|
|
68
69
|
"RoomCategory", "RoomSearchType", "MatchEventType", "ScoringType",
|
|
69
|
-
"TeamType",
|
|
70
|
+
"TeamType", "Variant", "EventsSort",
|
|
70
71
|
# OssapiV2 exceptions
|
|
71
72
|
"AccessDeniedError", "TokenExpiredError", "InsufficientScopeError",
|
|
72
73
|
# misc
|
|
@@ -88,10 +88,8 @@ class UserAccountHistoryType(EnumModel):
|
|
|
88
88
|
SILENCE = "silence"
|
|
89
89
|
|
|
90
90
|
class MessageType(EnumModel):
|
|
91
|
-
DISQUALIFY = "disqualify"
|
|
92
91
|
HYPE = "hype"
|
|
93
92
|
MAPPER_NOTE = "mapper_note"
|
|
94
|
-
NOMINATION_RESET = "nomination_reset"
|
|
95
93
|
PRAISE = "praise"
|
|
96
94
|
PROBLEM = "problem"
|
|
97
95
|
REVIEW = "review"
|
|
@@ -217,6 +215,7 @@ class RoomCategory(EnumModel):
|
|
|
217
215
|
# 430a2/resources/js/interfaces/room-json.ts#L7
|
|
218
216
|
NORMAL = "normal"
|
|
219
217
|
SPOTLIGHT = "spotlight"
|
|
218
|
+
FEATURED_ARTIST = "featured_artist"
|
|
220
219
|
|
|
221
220
|
class MatchEventType(EnumModel):
|
|
222
221
|
# https://github.dev/ppy/osu-web/blob/3d1586392102b05f2a3b264905c4dbb7b2
|
|
@@ -246,6 +245,10 @@ class TeamType(EnumModel):
|
|
|
246
245
|
TEAM_VS = "team-vs"
|
|
247
246
|
TAG_TEAM_VS = "tag-team-vs"
|
|
248
247
|
|
|
248
|
+
class Variant(EnumModel):
|
|
249
|
+
# can't start a python identifier with an integer
|
|
250
|
+
KEY_4 = "4k"
|
|
251
|
+
KEY_7 = "7k"
|
|
249
252
|
|
|
250
253
|
|
|
251
254
|
# ===============
|
|
@@ -298,6 +301,7 @@ class ChannelType(EnumModel):
|
|
|
298
301
|
TEMPORARY = "TEMPORARY"
|
|
299
302
|
PM = "PM"
|
|
300
303
|
GROUP = "GROUP"
|
|
304
|
+
ANNOUNCE = "ANNOUNCE"
|
|
301
305
|
|
|
302
306
|
class CommentableType(EnumModel):
|
|
303
307
|
NEWS_POST = "news_post"
|
|
@@ -379,8 +383,8 @@ class BeatmapsetSearchLanguage(EnumModel):
|
|
|
379
383
|
ENGLISH = 2
|
|
380
384
|
JAPANESE = 3
|
|
381
385
|
CHINESE = 4
|
|
382
|
-
KOREAN = 6
|
|
383
386
|
INSTRUMENTAL = 5
|
|
387
|
+
KOREAN = 6
|
|
384
388
|
FRENCH = 7
|
|
385
389
|
GERMAN = 8
|
|
386
390
|
SWEDISH = 9
|
|
@@ -425,6 +429,9 @@ class RoomSearchType(EnumModel):
|
|
|
425
429
|
PARTICIPATED = "participated"
|
|
426
430
|
ENDED = "ended"
|
|
427
431
|
|
|
432
|
+
class EventsSort(EnumModel):
|
|
433
|
+
NEW = "id_desc"
|
|
434
|
+
OLD = "id_asc"
|
|
428
435
|
|
|
429
436
|
|
|
430
437
|
# =================
|
|
@@ -609,6 +616,14 @@ class ForumPostBody(Model):
|
|
|
609
616
|
html: str
|
|
610
617
|
raw: str
|
|
611
618
|
|
|
619
|
+
class ForumPollText(Model):
|
|
620
|
+
bbcode: str
|
|
621
|
+
html: str
|
|
622
|
+
|
|
623
|
+
class ForumPollTitle(Model):
|
|
624
|
+
bbcode: str
|
|
625
|
+
html: str
|
|
626
|
+
|
|
612
627
|
class ReviewsConfig(Model):
|
|
613
628
|
max_blocks: int
|
|
614
629
|
|
|
@@ -16,7 +16,8 @@ from ossapi.enums import (UserAccountHistory, ProfileBanner, UserBadge, Country,
|
|
|
16
16
|
BeatmapsetEventType, UserRelationType, UserLevel, UserGradeCounts,
|
|
17
17
|
GithubUser, ChangelogSearch, ForumTopicType, ForumPostBody, ForumTopicSort,
|
|
18
18
|
ChannelType, ReviewsConfig, NewsSearch, Nomination, RankHighest, RoomType,
|
|
19
|
-
RoomCategory, MatchEventType, ScoringType, TeamType
|
|
19
|
+
RoomCategory, MatchEventType, ScoringType, TeamType, Variant, ForumPollText,
|
|
20
|
+
ForumPollTitle)
|
|
20
21
|
from ossapi.utils import Datetime, Model, BaseModel, Field
|
|
21
22
|
|
|
22
23
|
T = TypeVar("T")
|
|
@@ -86,7 +87,6 @@ class UserCompact(Model):
|
|
|
86
87
|
# ---------------
|
|
87
88
|
avatar_url: str
|
|
88
89
|
country_code: str
|
|
89
|
-
default_group: str
|
|
90
90
|
id: int
|
|
91
91
|
is_active: bool
|
|
92
92
|
is_bot: bool
|
|
@@ -107,14 +107,13 @@ class UserCompact(Model):
|
|
|
107
107
|
blocks: Optional[UserRelation]
|
|
108
108
|
country: Optional[Country]
|
|
109
109
|
cover: Optional[Cover]
|
|
110
|
+
default_group: Optional[str]
|
|
110
111
|
favourite_beatmapset_count: Optional[int]
|
|
111
|
-
# undocumented
|
|
112
112
|
follow_user_mapping: Optional[List[int]]
|
|
113
113
|
follower_count: Optional[int]
|
|
114
114
|
friends: Optional[List[UserRelation]]
|
|
115
115
|
graveyard_beatmapset_count: Optional[int]
|
|
116
116
|
groups: Optional[List[UserGroup]]
|
|
117
|
-
# undocumented
|
|
118
117
|
guest_beatmapset_count: Optional[int]
|
|
119
118
|
is_admin: Optional[bool]
|
|
120
119
|
is_bng: Optional[bool]
|
|
@@ -130,7 +129,11 @@ class UserCompact(Model):
|
|
|
130
129
|
mapping_follower_count: Optional[int]
|
|
131
130
|
monthly_playcounts: Optional[List[UserMonthlyPlaycount]]
|
|
132
131
|
page: Optional[UserPage]
|
|
132
|
+
pending_beatmapset_count: Optional[int]
|
|
133
133
|
previous_usernames: Optional[List[str]]
|
|
134
|
+
# deprecated, replaced by rank_history
|
|
135
|
+
rankHistory: Optional[RankHistory]
|
|
136
|
+
rank_history: Optional[RankHistory]
|
|
134
137
|
# deprecated, replaced by ranked_beatmapset_count
|
|
135
138
|
ranked_and_approved_beatmapset_count: Optional[int]
|
|
136
139
|
ranked_beatmapset_count: Optional[int]
|
|
@@ -143,13 +146,10 @@ class UserCompact(Model):
|
|
|
143
146
|
support_level: Optional[int]
|
|
144
147
|
# deprecated, replaced by pending_beatmapset_count
|
|
145
148
|
unranked_beatmapset_count: Optional[int]
|
|
146
|
-
pending_beatmapset_count: Optional[int]
|
|
147
149
|
unread_pm_count: Optional[int]
|
|
148
150
|
user_achievements: Optional[List[UserAchievement]]
|
|
149
151
|
user_preferences: Optional[UserProfileCustomization]
|
|
150
|
-
|
|
151
|
-
# deprecated, replaced by rank_history
|
|
152
|
-
rankHistory: Optional[RankHistory]
|
|
152
|
+
|
|
153
153
|
|
|
154
154
|
def expand(self) -> User:
|
|
155
155
|
return self._fk_user(self.id)
|
|
@@ -264,17 +264,17 @@ class BeatmapsetCompact(Model):
|
|
|
264
264
|
creator: str
|
|
265
265
|
favourite_count: int
|
|
266
266
|
id: int
|
|
267
|
+
nsfw: bool
|
|
268
|
+
offset: int
|
|
267
269
|
play_count: int
|
|
268
270
|
preview_url: str
|
|
269
271
|
source: str
|
|
270
272
|
status: RankStatus
|
|
273
|
+
spotlight: bool
|
|
271
274
|
title: str
|
|
272
275
|
title_unicode: str
|
|
273
276
|
user_id: int
|
|
274
277
|
video: bool
|
|
275
|
-
nsfw: bool
|
|
276
|
-
offset: int
|
|
277
|
-
spotlight: bool
|
|
278
278
|
# documented as being in `Beatmapset` only, but returned by
|
|
279
279
|
# `api.beatmapset_events` which uses a `BeatmapsetCompact`.
|
|
280
280
|
hype: Optional[Hype]
|
|
@@ -283,6 +283,7 @@ class BeatmapsetCompact(Model):
|
|
|
283
283
|
# ---------------
|
|
284
284
|
beatmaps: Optional[List[Beatmap]]
|
|
285
285
|
converts: Optional[Any]
|
|
286
|
+
current_nominations: Optional[List[Nomination]]
|
|
286
287
|
current_user_attributes: Optional[Any]
|
|
287
288
|
description: Optional[Any]
|
|
288
289
|
discussions: Optional[Any]
|
|
@@ -291,12 +292,12 @@ class BeatmapsetCompact(Model):
|
|
|
291
292
|
has_favourited: Optional[bool]
|
|
292
293
|
language: Optional[Any]
|
|
293
294
|
nominations: Optional[Any]
|
|
295
|
+
pack_tags: Optional[List[str]]
|
|
294
296
|
ratings: Optional[Any]
|
|
295
297
|
recent_favourites: Optional[Any]
|
|
296
298
|
related_users: Optional[Any]
|
|
297
|
-
_user: Optional[UserCompact] = Field(name="user")
|
|
298
|
-
# undocumented
|
|
299
299
|
track_id: Optional[int]
|
|
300
|
+
_user: Optional[UserCompact] = Field(name="user")
|
|
300
301
|
|
|
301
302
|
def expand(self) -> Beatmapset:
|
|
302
303
|
return self._fk_beatmapset(self.id)
|
|
@@ -308,6 +309,7 @@ class Beatmapset(BeatmapsetCompact):
|
|
|
308
309
|
availability: Availability
|
|
309
310
|
bpm: float
|
|
310
311
|
can_be_hyped: bool
|
|
312
|
+
deleted_at: Optional[Datetime]
|
|
311
313
|
discussion_enabled: bool
|
|
312
314
|
discussion_locked: bool
|
|
313
315
|
is_scoreable: bool
|
|
@@ -319,9 +321,6 @@ class Beatmapset(BeatmapsetCompact):
|
|
|
319
321
|
storyboard: bool
|
|
320
322
|
submitted_date: Optional[Datetime]
|
|
321
323
|
tags: str
|
|
322
|
-
current_nominations: Optional[List[Nomination]]
|
|
323
|
-
deleted_at: Optional[Datetime]
|
|
324
|
-
pack_tags: List[str]
|
|
325
324
|
|
|
326
325
|
def expand(self) -> Beatmapset:
|
|
327
326
|
return self
|
|
@@ -434,18 +433,18 @@ class Comment(Model):
|
|
|
434
433
|
class CommentBundle(Model):
|
|
435
434
|
commentable_meta: List[CommentableMeta]
|
|
436
435
|
comments: List[Comment]
|
|
436
|
+
cursor: CursorT
|
|
437
437
|
has_more: bool
|
|
438
438
|
has_more_id: Optional[int]
|
|
439
439
|
included_comments: List[Comment]
|
|
440
440
|
pinned_comments: Optional[List[Comment]]
|
|
441
|
+
# TODO this should be type CommentSort
|
|
441
442
|
sort: str
|
|
442
443
|
top_level_count: Optional[int]
|
|
443
444
|
total: Optional[int]
|
|
444
445
|
user_follow: bool
|
|
445
446
|
user_votes: List[int]
|
|
446
447
|
users: List[UserCompact]
|
|
447
|
-
# undocumented
|
|
448
|
-
cursor: CursorT
|
|
449
448
|
|
|
450
449
|
class ForumPost(Model):
|
|
451
450
|
created_at: Datetime
|
|
@@ -477,11 +476,27 @@ class ForumTopic(Model):
|
|
|
477
476
|
type: ForumTopicType
|
|
478
477
|
updated_at: Datetime
|
|
479
478
|
user_id: int
|
|
480
|
-
poll:
|
|
479
|
+
poll: Optional[ForumPollModel]
|
|
481
480
|
|
|
482
481
|
def user(self) -> User:
|
|
483
482
|
return self._fk_user(self.user_id)
|
|
484
483
|
|
|
484
|
+
class ForumPollModel(Model):
|
|
485
|
+
allow_vote_change: bool
|
|
486
|
+
ended_at: Optional[Datetime]
|
|
487
|
+
hide_incomplete_results: bool
|
|
488
|
+
last_vote_at: Optional[Datetime]
|
|
489
|
+
max_votes: int
|
|
490
|
+
options: List[ForumPollOption]
|
|
491
|
+
started_at: Datetime
|
|
492
|
+
title: ForumPollTitle
|
|
493
|
+
total_vote_count: int
|
|
494
|
+
|
|
495
|
+
class ForumPollOption(Model):
|
|
496
|
+
id: int
|
|
497
|
+
text: ForumPollText
|
|
498
|
+
vote_count: Optional[int]
|
|
499
|
+
|
|
485
500
|
class ForumTopicAndPosts(Model):
|
|
486
501
|
cursor: CursorT
|
|
487
502
|
search: ForumTopicSearch
|
|
@@ -579,13 +594,9 @@ class BeatmapsetDiscussion(Model):
|
|
|
579
594
|
can_be_resolved: bool
|
|
580
595
|
can_grant_kudosu: bool
|
|
581
596
|
created_at: Datetime
|
|
582
|
-
# documented as non-optional, api.beatmapset_events() might give a null
|
|
583
|
-
# response for this? but very rarely. need to find a repro case
|
|
584
597
|
current_user_attributes: Any
|
|
585
598
|
updated_at: Datetime
|
|
586
599
|
deleted_at: Optional[Datetime]
|
|
587
|
-
# similarly as for current_user_attributes, in the past this has been null
|
|
588
|
-
# but can't find a repro case
|
|
589
600
|
last_post_at: Datetime
|
|
590
601
|
kudosu_denied: bool
|
|
591
602
|
starting_post: Optional[BeatmapsetDiscussionPost]
|
|
@@ -613,6 +624,8 @@ class BeatmapsetDiscussionVote(Model):
|
|
|
613
624
|
beatmapset_discussion_id: int
|
|
614
625
|
created_at: Datetime
|
|
615
626
|
updated_at: Datetime
|
|
627
|
+
# TODO is this field ever actually returned? not documented and can't find
|
|
628
|
+
# a repro case.
|
|
616
629
|
cursor_string: Optional[str]
|
|
617
630
|
|
|
618
631
|
def user(self):
|
|
@@ -731,6 +744,7 @@ class Build(Model):
|
|
|
731
744
|
version: Optional[str]
|
|
732
745
|
changelog_entries: Optional[List[ChangelogEntry]]
|
|
733
746
|
versions: Optional[Versions]
|
|
747
|
+
youtube_id: Optional[str]
|
|
734
748
|
|
|
735
749
|
class Versions(Model):
|
|
736
750
|
next: Optional[Build]
|
|
@@ -851,8 +865,8 @@ class BeatmapDifficultyAttributes(Model):
|
|
|
851
865
|
stamina_difficulty: Optional[float]
|
|
852
866
|
rhythm_difficulty: Optional[float]
|
|
853
867
|
colour_difficulty: Optional[float]
|
|
854
|
-
|
|
855
|
-
|
|
868
|
+
approach_rate: Optional[float]
|
|
869
|
+
great_hit_window: Optional[float]
|
|
856
870
|
|
|
857
871
|
# ctb attributes
|
|
858
872
|
approach_rate: Optional[float]
|
|
@@ -861,6 +875,9 @@ class BeatmapDifficultyAttributes(Model):
|
|
|
861
875
|
great_hit_window: Optional[float]
|
|
862
876
|
score_multiplier: Optional[float]
|
|
863
877
|
|
|
878
|
+
class Events(Model):
|
|
879
|
+
cursor_string: str
|
|
880
|
+
events: List[Event]
|
|
864
881
|
|
|
865
882
|
|
|
866
883
|
# ================
|
|
@@ -1032,15 +1049,14 @@ class ChatChannel(Model):
|
|
|
1032
1049
|
channel_id: int
|
|
1033
1050
|
description: Optional[str]
|
|
1034
1051
|
icon: Optional[str]
|
|
1035
|
-
# documented as non-optional (to see that it can be null, pm tillerino)
|
|
1036
1052
|
moderated: Optional[bool]
|
|
1037
1053
|
name: str
|
|
1038
1054
|
type: ChannelType
|
|
1039
1055
|
uuid: Optional[str]
|
|
1056
|
+
message_length_limit: int
|
|
1040
1057
|
|
|
1041
1058
|
# optional fields
|
|
1042
1059
|
# ---------------
|
|
1043
|
-
first_message_id: Optional[int]
|
|
1044
1060
|
last_message_id: Optional[int]
|
|
1045
1061
|
last_read_id: Optional[int]
|
|
1046
1062
|
recent_messages: Optional[List[ChatMessage]]
|
|
@@ -1089,31 +1105,38 @@ class UserRelation(Model):
|
|
|
1089
1105
|
def target(self) -> Union[User, UserCompact]:
|
|
1090
1106
|
return self._fk_user(self.target_id, existing=self.target)
|
|
1091
1107
|
|
|
1108
|
+
class StatisticsVariant(Model):
|
|
1109
|
+
mode: GameMode
|
|
1110
|
+
variant: Variant
|
|
1111
|
+
country_rank: Optional[int]
|
|
1112
|
+
global_rank: Optional[int]
|
|
1113
|
+
pp: float
|
|
1092
1114
|
|
|
1093
1115
|
class UserStatistics(Model):
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1116
|
+
count_100: int
|
|
1117
|
+
count_300: int
|
|
1118
|
+
count_50: int
|
|
1119
|
+
count_miss: int
|
|
1120
|
+
country_rank: Optional[int]
|
|
1121
|
+
grade_counts: UserGradeCounts
|
|
1097
1122
|
hit_accuracy: float
|
|
1123
|
+
is_ranked: bool
|
|
1124
|
+
level: UserLevel
|
|
1125
|
+
maximum_combo: int
|
|
1098
1126
|
play_count: int
|
|
1099
1127
|
play_time: int
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
maximum_combo: int
|
|
1103
|
-
replays_watched_by_others: int
|
|
1104
|
-
is_ranked: bool
|
|
1105
|
-
grade_counts: UserGradeCounts
|
|
1106
|
-
country_rank: Optional[int]
|
|
1128
|
+
pp: float
|
|
1129
|
+
pp_exp: float
|
|
1107
1130
|
global_rank: Optional[int]
|
|
1131
|
+
global_rank_exp: Optional[float]
|
|
1132
|
+
# deprecated, replaced by global_rank and country_rank
|
|
1108
1133
|
rank: Optional[Any]
|
|
1134
|
+
ranked_score: int
|
|
1135
|
+
replays_watched_by_others: int
|
|
1136
|
+
total_hits: int
|
|
1137
|
+
total_score: int
|
|
1109
1138
|
user: Optional[UserCompact]
|
|
1110
|
-
variants: Optional[
|
|
1111
|
-
global_rank_exp: Optional[float]
|
|
1112
|
-
pp_exp: float
|
|
1113
|
-
count_100: int
|
|
1114
|
-
count_300: int
|
|
1115
|
-
count_50: int
|
|
1116
|
-
count_miss: int
|
|
1139
|
+
variants: Optional[List[StatisticsVariant]]
|
|
1117
1140
|
|
|
1118
1141
|
class UserStatisticsRulesets(Model):
|
|
1119
1142
|
# undocumented
|