Habiticalib 0.3.7rc1__tar.gz → 0.4.0rc0__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.
Files changed (75) hide show
  1. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/PKG-INFO +1 -1
  2. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/pyproject.toml +5 -5
  3. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/__init__.py +34 -6
  4. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/const.py +1 -1
  5. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/lib.py +110 -0
  6. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/typedefs.py +171 -23
  7. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_serialize.ambr +15 -0
  8. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_user.ambr +1 -1
  9. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.cruft.json +0 -0
  10. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.editorconfig +0 -0
  11. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/FUNDING.yml +0 -0
  12. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/dependabot.yml +0 -0
  13. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/labels.yml +0 -0
  14. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/release-drafter.yml +0 -0
  15. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/workflows/build.yml +0 -0
  16. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/workflows/documentation.yml +0 -0
  17. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/workflows/draft.yml +0 -0
  18. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.github/workflows/labeler.yml +0 -0
  19. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.gitignore +0 -0
  20. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.pre-commit-config.yaml +0 -0
  21. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/.vscode/settings.json +0 -0
  22. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/LICENSE +0 -0
  23. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/README.md +0 -0
  24. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/docs/index.md +0 -0
  25. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/docs/reference/habiticalib.md +0 -0
  26. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/mkdocs.yml +0 -0
  27. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/exceptions.py +0 -0
  28. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/ha.py +0 -0
  29. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/helpers.py +0 -0
  30. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/src/habiticalib/py.typed +0 -0
  31. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__init__.py +0 -0
  32. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar.png +0 -0
  33. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[animated_background].png +0 -0
  34. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[default].png +0 -0
  35. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[kickstarter_backer_gear].png +0 -0
  36. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[kickstarter_pet_mount].png +0 -0
  37. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[seafoam].png +0 -0
  38. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[shinySeed].png +0 -0
  39. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[sleeping].png +0 -0
  40. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[snowball].png +0 -0
  41. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[special_0].png +0 -0
  42. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[special_1].png +0 -0
  43. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[spookySparkles].png +0 -0
  44. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[weapon_critical].png +0 -0
  45. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[with_chair].png +0 -0
  46. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_to_file.png +0 -0
  47. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar.ambr +0 -0
  48. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_login.ambr +0 -0
  49. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_tasks.ambr +0 -0
  50. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/conftest.py +0 -0
  51. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/empty_data.json +0 -0
  52. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/login.json +0 -0
  53. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/task.json +0 -0
  54. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/task_order.json +0 -0
  55. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/tasks.json +0 -0
  56. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user.json +0 -0
  57. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_anonymized.json +0 -0
  58. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles.json +0 -0
  59. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_animated_background.json +0 -0
  60. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_kickstarter.json +0 -0
  61. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_kickstarter_pets.json +0 -0
  62. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_seafoam.json +0 -0
  63. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_shinySeed.json +0 -0
  64. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_sleeping.json +0 -0
  65. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_snowball.json +0 -0
  66. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_special_0.json +0 -0
  67. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_special_1.json +0 -0
  68. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_spookySparkles.json +0 -0
  69. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_weapon_critical.json +0 -0
  70. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_with_chair.json +0 -0
  71. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/test_avatar.py +0 -0
  72. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/test_login.py +0 -0
  73. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/test_serialize.py +0 -0
  74. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/test_tasks.py +0 -0
  75. {habiticalib-0.3.7rc1 → habiticalib-0.4.0rc0}/tests/test_user.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Habiticalib
3
- Version: 0.3.7rc1
3
+ Version: 0.4.0rc0
4
4
  Summary: Asynchronous Python client library for the Habitica API
5
5
  Project-URL: Documentation, https://tr4nt0r.github.io/habiticalib/
6
6
  Project-URL: Source, https://github.com/tr4nt0r/habiticalib
@@ -75,16 +75,16 @@ path = "src/habiticalib/const.py"
75
75
  [tool.hatch.envs.default]
76
76
  python = "3.12"
77
77
  dependencies = [
78
- "aiohttp==3.11.11",
78
+ "aiohttp==3.11.12",
79
79
  "mashumaro==3.15",
80
80
  "orjson==3.10.15",
81
81
  "Pillow==11.1.0",
82
- "mypy==1.14.1",
83
- "ruff==0.9.4",
82
+ "mypy==1.15.0",
83
+ "ruff==0.9.6",
84
84
  "pytest==8.3.4",
85
85
  "pytest-cov==6.0.0",
86
- "mkdocs-material==9.6.1",
87
- "mkdocstrings[python]==0.27.0",
86
+ "mkdocs-material==9.6.3",
87
+ "mkdocstrings[python]==0.28.0",
88
88
  "pytest-asyncio==0.25.3",
89
89
  "aioresponses==0.7.8",
90
90
  "pre-commit==4.1.0",
@@ -46,11 +46,17 @@ from .typedefs import (
46
46
  GearItems,
47
47
  GearItemsAvatar,
48
48
  GearType,
49
+ GlobalActivity,
50
+ GlobalActivityWebhook,
51
+ GroupChatReceived,
52
+ GroupChatReceivedOptions,
53
+ GroupChatReceivedWebhook,
49
54
  GroupTask,
50
55
  HabiticaCastSkillResponse,
51
56
  HabiticaClass,
52
57
  HabiticaClassSystemResponse,
53
58
  HabiticaContentResponse,
59
+ HabiticaDeleteWebhookResponse,
54
60
  HabiticaErrorResponse,
55
61
  HabiticaGroupMembersResponse,
56
62
  HabiticaLoginResponse,
@@ -67,6 +73,7 @@ from .typedefs import (
67
73
  HabiticaUserAnonymizedResponse,
68
74
  HabiticaUserExport,
69
75
  HabiticaUserResponse,
76
+ HabiticaWebhookResponse,
70
77
  HairPreferences,
71
78
  HatchingPotionEntry,
72
79
  HistoryUser,
@@ -98,6 +105,9 @@ from .typedefs import (
98
105
  PurchasedUser,
99
106
  PushDevicesUser,
100
107
  PushNotificationsPreferences,
108
+ QuestActivity,
109
+ QuestActivityOptions,
110
+ QuestActivityWebhook,
101
111
  QuestBoss,
102
112
  QuestBossRage,
103
113
  QuestCollect,
@@ -123,6 +133,9 @@ from .typedefs import (
123
133
  SuppressModalsPreferences,
124
134
  TagsUser,
125
135
  Task,
136
+ TaskActivity,
137
+ TaskActivityOptions,
138
+ TaskActivityWebhook,
126
139
  TaskData,
127
140
  TaskFilter,
128
141
  TaskPriority,
@@ -135,12 +148,13 @@ from .typedefs import (
135
148
  TrainingStats,
136
149
  TutorialFlags,
137
150
  UltimateGearSetsAchievments,
151
+ UserActivity,
152
+ UserActivityOptions,
153
+ UserActivityWebhook,
138
154
  UserAnonymizedData,
139
155
  UserData,
140
156
  UserTasks,
141
- WebhooksOptions,
142
- WebhooksType,
143
- WebhooksUser,
157
+ WebhookType,
144
158
  )
145
159
 
146
160
  __all__ = [
@@ -185,6 +199,11 @@ __all__ = [
185
199
  "GearItems",
186
200
  "GearItemsAvatar",
187
201
  "GearType",
202
+ "GlobalActivity",
203
+ "GlobalActivityWebhook",
204
+ "GroupChatReceived",
205
+ "GroupChatReceivedOptions",
206
+ "GroupChatReceivedWebhook",
188
207
  "GroupTask",
189
208
  "Habitica",
190
209
  "HabiticaCastSkillResponse",
@@ -194,6 +213,7 @@ __all__ = [
194
213
  "HabiticaClassSystemResponse",
195
214
  "HabiticaContentResponse",
196
215
  "HabiticaContentResponse",
216
+ "HabiticaDeleteWebhookResponse",
197
217
  "HabiticaErrorResponse",
198
218
  "HabiticaErrorResponse",
199
219
  "HabiticaException",
@@ -227,6 +247,7 @@ __all__ = [
227
247
  "HabiticaUserExport",
228
248
  "HabiticaUserResponse",
229
249
  "HabiticaUserResponse",
250
+ "HabiticaWebhookResponse",
230
251
  "HairPreferences",
231
252
  "HatchingPotionEntry",
232
253
  "HistoryUser",
@@ -261,6 +282,9 @@ __all__ = [
261
282
  "PurchasedUser",
262
283
  "PushDevicesUser",
263
284
  "PushNotificationsPreferences",
285
+ "QuestActivity",
286
+ "QuestActivityOptions",
287
+ "QuestActivityWebhook",
264
288
  "QuestBoss",
265
289
  "QuestBossRage",
266
290
  "QuestCollect",
@@ -291,6 +315,9 @@ __all__ = [
291
315
  "TagsUser",
292
316
  "TagsUser",
293
317
  "Task",
318
+ "TaskActivity",
319
+ "TaskActivityOptions",
320
+ "TaskActivityWebhook",
294
321
  "TaskData",
295
322
  "TaskData",
296
323
  "TaskFilter",
@@ -305,15 +332,16 @@ __all__ = [
305
332
  "TrainingStats",
306
333
  "TutorialFlags",
307
334
  "UltimateGearSetsAchievments",
335
+ "UserActivity",
336
+ "UserActivityOptions",
337
+ "UserActivityWebhook",
308
338
  "UserAnonymizedData",
309
339
  "UserAnonymizedData",
310
340
  "UserData",
311
341
  "UserData",
312
342
  "UserTasks",
313
343
  "UserTasks",
314
- "WebhooksOptions",
315
- "WebhooksType",
316
- "WebhooksUser",
344
+ "WebhookType",
317
345
  "__version__",
318
346
  "deserialize_task",
319
347
  "extract_avatar",
@@ -1,6 +1,6 @@
1
1
  """Constants for Habiticalib."""
2
2
 
3
- __version__ = "0.3.7rc1"
3
+ __version__ = "0.4.0rc0"
4
4
 
5
5
  DEFAULT_URL = "https://habitica.com/"
6
6
  ASSETS_URL = "https://habitica-assets.s3.amazonaws.com/mobileApp/images/"
@@ -38,10 +38,13 @@ from .typedefs import (
38
38
  Attributes,
39
39
  Avatar,
40
40
  Direction,
41
+ GlobalActivity,
42
+ GroupChatReceived,
41
43
  HabiticaCastSkillResponse,
42
44
  HabiticaClass,
43
45
  HabiticaClassSystemResponse,
44
46
  HabiticaContentResponse,
47
+ HabiticaDeleteWebhookResponse,
45
48
  HabiticaErrorResponse,
46
49
  HabiticaGroupMembersResponse,
47
50
  HabiticaLoginResponse,
@@ -58,10 +61,14 @@ from .typedefs import (
58
61
  HabiticaUserAnonymizedResponse,
59
62
  HabiticaUserExport,
60
63
  HabiticaUserResponse,
64
+ HabiticaWebhookResponse,
61
65
  Language,
66
+ QuestActivity,
62
67
  Skill,
63
68
  Task,
69
+ TaskActivity,
64
70
  TaskFilter,
71
+ UserActivity,
65
72
  )
66
73
 
67
74
  if TYPE_CHECKING:
@@ -2073,3 +2080,106 @@ class Habitica:
2073
2080
  "password": self._headers.get("X-API-KEY"),
2074
2081
  }, # type: ignore[var-annotated]
2075
2082
  )
2083
+
2084
+ async def create_webhook(
2085
+ self,
2086
+ webhook: TaskActivity
2087
+ | GroupChatReceived
2088
+ | UserActivity
2089
+ | QuestActivity
2090
+ | GlobalActivity,
2091
+ ) -> HabiticaWebhookResponse:
2092
+ """Create a new webhook.
2093
+
2094
+ Parameters
2095
+ ----------
2096
+ webhook : TaskActivity or GroupChatReceived or UserActivity or QuestActivity or GlobalActivity
2097
+ The webhook object to be created. It should be an instance of one of the following types:
2098
+ - TaskActivity
2099
+ - GroupChatReceived
2100
+ - UserActivity
2101
+ - QuestActivity
2102
+ - GlobalActivity
2103
+
2104
+ Returns
2105
+ -------
2106
+ HabiticaWebhookResponse
2107
+ A response object containing the created webhook.
2108
+
2109
+ Raises
2110
+ ------
2111
+ BadRequestError
2112
+ A parameter did not pass validation.
2113
+
2114
+ """
2115
+
2116
+ url = self.url / "api/v3/user/webhook"
2117
+
2118
+ return HabiticaWebhookResponse.from_json(
2119
+ await self._request("post", url=url, json=webhook.to_dict(omit_none=True))
2120
+ )
2121
+
2122
+ async def delete_webhook(
2123
+ self, webhook_id: str | UUID
2124
+ ) -> HabiticaDeleteWebhookResponse:
2125
+ """Delete a webhook by its UUID.
2126
+
2127
+ Parameters
2128
+ ----------
2129
+ webhook_id : str or UUID
2130
+ The UUID identifier of the webhook to delete.
2131
+
2132
+ Returns
2133
+ -------
2134
+ HabiticaDeleteWebhookResponse
2135
+ A response object containing a list of the remaining webhooks.
2136
+
2137
+ Raises
2138
+ ------
2139
+ NotFoundError
2140
+ The specified webhook could not be found.
2141
+ """
2142
+ url = self.url / "api/v3/user/webhook" / str(webhook_id)
2143
+
2144
+ return HabiticaDeleteWebhookResponse.from_json(
2145
+ await self._request("delete", url)
2146
+ )
2147
+
2148
+ async def update_webhook(
2149
+ self,
2150
+ webhook: TaskActivity
2151
+ | GroupChatReceived
2152
+ | UserActivity
2153
+ | QuestActivity
2154
+ | GlobalActivity,
2155
+ ) -> HabiticaWebhookResponse:
2156
+ """Update a webhook by its UUID with the provided data.
2157
+
2158
+ Parameters
2159
+ ----------
2160
+ webhook : TaskActivity or GroupChatReceived or UserActivity or QuestActivity or GlobalActivity
2161
+ The webhook data to be updated. It must be an instance of one of the specified types.
2162
+
2163
+ Returns
2164
+ -------
2165
+ HabiticaWebhookResponse
2166
+ The response object containing the updated webhook.
2167
+
2168
+
2169
+ Raises
2170
+ ------
2171
+ ValueError
2172
+ If the identifier was not provided.
2173
+ BadRequestError
2174
+ A parameter did not pass validation.
2175
+
2176
+ """
2177
+ if not webhook.id:
2178
+ msg = "You must provide the identifier of the webhook to update."
2179
+ raise ValueError(msg)
2180
+
2181
+ url = self.url / "api/v3/user/webhook" / str(webhook.id)
2182
+
2183
+ return HabiticaWebhookResponse.from_json(
2184
+ await self._request("put", url, json=webhook.to_dict(omit_none=True))
2185
+ )
@@ -7,12 +7,13 @@ from dataclasses import dataclass, field
7
7
  import datetime as dt
8
8
  from datetime import UTC, datetime
9
9
  from enum import Enum, StrEnum
10
- from typing import Any, NotRequired, TypedDict
10
+ from typing import Annotated, Any, NotRequired, TypedDict
11
11
  from uuid import UUID
12
12
 
13
13
  from mashumaro import field_options
14
14
  from mashumaro.config import TO_DICT_ADD_OMIT_NONE_FLAG
15
15
  from mashumaro.mixins.orjson import DataClassORJSONMixin
16
+ from mashumaro.types import Discriminator
16
17
 
17
18
 
18
19
  def serialize_datetime(date: str | int | None) -> datetime | None:
@@ -776,48 +777,187 @@ class PushDevicesUser(BaseModel):
776
777
  updatedAt: datetime
777
778
 
778
779
 
779
- class WebhooksType(StrEnum):
780
+ class WebhookType(StrEnum):
780
781
  """Webhook types."""
781
782
 
782
783
  TASK_ACTIVITY = "taskActivity"
783
784
  USER_ACTIVITY = "userActivity"
784
785
  QUEST_ACTIVITY = "questActivity"
785
786
  GROUP_CHAT_RECEIVED = "groupChatReceived"
787
+ GLOBAL_ACTIVITY = "globalActivity"
786
788
 
787
789
 
788
790
  @dataclass(kw_only=True)
789
- class WebhooksOptions(BaseModel):
790
- """Webhooks options data."""
791
+ class QuestActivityOptions(BaseModel):
792
+ """Quest activity options."""
791
793
 
792
- created: bool | None = None
793
- updated: bool | None = None
794
- deleted: bool | None = None
795
- scored: bool | None = None
796
- questStarted: bool | None = None
797
- questFinished: bool | None = None
798
- questInvited: bool | None = None
799
- petHatched: bool | None = None
800
- mountRaised: bool | None = None
801
- leveledUp: bool | None = None
802
- groupId: UUID | None = None
794
+ questStarted: bool = False
795
+ questFinished: bool = False
796
+ questInvited: bool = False
803
797
 
804
798
 
805
799
  @dataclass(kw_only=True)
806
- class WebhooksUser(BaseModel):
807
- """Webhooks user data."""
800
+ class UserActivityOptions(BaseModel):
801
+ """User activity options."""
802
+
803
+ petHatched: bool = False
804
+ mountRaised: bool = False
805
+ leveledUp: bool = False
808
806
 
807
+
808
+ @dataclass
809
+ class GroupChatReceivedOptions(BaseModel):
810
+ """Group chat received options."""
811
+
812
+ groupId: UUID
813
+
814
+
815
+ @dataclass(kw_only=True)
816
+ class TaskActivityOptions(BaseModel):
817
+ """Task activity options."""
818
+
819
+ created: bool = False
820
+ updated: bool = False
821
+ deleted: bool = False
822
+ checklistScored: bool = False
823
+ scored: bool = True
824
+
825
+
826
+ @dataclass(kw_only=True)
827
+ class Webhook(BaseModel):
828
+ """Webhook base class."""
829
+
830
+ url: str | None = field(default=None, kw_only=False)
831
+ enabled: bool | None = None
832
+ label: str | None = None
809
833
  id: UUID | None = None
810
- Type: WebhooksType = WebhooksType.TASK_ACTIVITY
811
- url: str | None = None
812
- enabled: bool = True
834
+
835
+
836
+ @dataclass(kw_only=True)
837
+ class TaskActivity(Webhook):
838
+ """Task activity."""
839
+
840
+ Type: WebhookType = field(default=WebhookType.TASK_ACTIVITY, init=False)
841
+ options: TaskActivityOptions = field(default_factory=TaskActivityOptions)
842
+
843
+
844
+ @dataclass(kw_only=True)
845
+ class GroupChatReceived(Webhook):
846
+ """Group chat received."""
847
+
848
+ def __post_init__(self) -> None:
849
+ """Initialize the GroupChatReceived class."""
850
+ if self.groupId:
851
+ if not isinstance(self.groupId, UUID):
852
+ self.groupId = UUID(self.groupId)
853
+
854
+ self.options = GroupChatReceivedOptions(groupId=self.groupId)
855
+ self.groupId = None
856
+
857
+ groupId: UUID | str | None = field(default=None, kw_only=False)
858
+ Type: WebhookType = field(default=WebhookType.GROUP_CHAT_RECEIVED, init=False)
859
+ options: GroupChatReceivedOptions = field(init=False)
860
+
861
+
862
+ @dataclass(kw_only=True)
863
+ class UserActivity(Webhook):
864
+ """User activity."""
865
+
866
+ Type: WebhookType = field(default=WebhookType.USER_ACTIVITY, init=False)
867
+ options: UserActivityOptions = field(default_factory=UserActivityOptions)
868
+
869
+
870
+ @dataclass(kw_only=True)
871
+ class QuestActivity(Webhook):
872
+ """Quest activity."""
873
+
874
+ Type: WebhookType = field(default=WebhookType.QUEST_ACTIVITY, init=False)
875
+ options: QuestActivityOptions = field(default_factory=QuestActivityOptions)
876
+
877
+
878
+ @dataclass(kw_only=True)
879
+ class GlobalActivity(Webhook):
880
+ """Global activity.
881
+
882
+ Note: global webhooks send a request for every type of event
883
+ """
884
+
885
+ Type: WebhookType = field(default=WebhookType.GLOBAL_ACTIVITY, init=False)
886
+
887
+
888
+ class HabiticaWebhookResponse(HabiticaResponse):
889
+ """Representation of a webhook data response."""
890
+
891
+ data: Annotated[
892
+ Webhook,
893
+ Discriminator(
894
+ field="type",
895
+ include_subtypes=True,
896
+ ),
897
+ ]
898
+
899
+
900
+ class HabiticaDeleteWebhookResponse(HabiticaResponse):
901
+ """Representation of a delete webhook response."""
902
+
903
+ data: list[
904
+ Annotated[
905
+ Webhook,
906
+ Discriminator(
907
+ field="type",
908
+ include_subtypes=True,
909
+ ),
910
+ ]
911
+ ]
912
+
913
+
914
+ @dataclass(kw_only=True)
915
+ class WebhookUser(BaseModel):
916
+ """Webhooks user data."""
917
+
813
918
  failures: int = 0
814
- label: str = ""
815
- options = WebhooksOptions
816
919
  lastFailureAt: datetime | None = None
817
920
  createdAt: datetime | None = None
818
921
  updatedAt: datetime | None = None
819
922
 
820
923
 
924
+ @dataclass(kw_only=True)
925
+ class TaskActivityWebhook(WebhookUser, TaskActivity):
926
+ """Task activity webhook."""
927
+
928
+ type = "taskActivity"
929
+
930
+
931
+ @dataclass(kw_only=True)
932
+ class QuestActivityWebhook(WebhookUser, QuestActivity):
933
+ """Quest activity webhook."""
934
+
935
+ type = "questActivity"
936
+
937
+
938
+ @dataclass(kw_only=True)
939
+ class GlobalActivityWebhook(WebhookUser, GlobalActivity):
940
+ """Global activity webhook."""
941
+
942
+ type = "globalActivity"
943
+
944
+
945
+ @dataclass(kw_only=True)
946
+ class GroupChatReceivedWebhook(WebhookUser, GroupChatReceived):
947
+ """Group chat received webhook."""
948
+
949
+ type = "groupChatReceived"
950
+ groupId: None = None
951
+ options: GroupChatReceivedOptions = field(init=True)
952
+
953
+
954
+ @dataclass(kw_only=True)
955
+ class UserActivityWebhook(WebhookUser, UserActivity):
956
+ """User activity webhook."""
957
+
958
+ type = "userActivity"
959
+
960
+
821
961
  @dataclass(kw_only=True)
822
962
  class PinnedItemsUser(BaseModel):
823
963
  """PinnedItems user data."""
@@ -851,7 +991,15 @@ class UserData(Avatar, BaseModel):
851
991
  tasksOrder: TasksOrderUser = field(default_factory=TasksOrderUser)
852
992
  extra: dict = field(default_factory=dict)
853
993
  pushDevices: list[PushDevicesUser] = field(default_factory=list)
854
- webhooks: list[WebhooksUser] = field(default_factory=list)
994
+ webhooks: list[
995
+ Annotated[
996
+ Webhook,
997
+ Discriminator(
998
+ field="type",
999
+ include_subtypes=True,
1000
+ ),
1001
+ ]
1002
+ ] = field(default_factory=list)
855
1003
  loginIncentives: int | None = None
856
1004
  invitesSent: int | None = None
857
1005
  pinnedItems: list[PinnedItemsUser] = field(default_factory=list)
@@ -1909,6 +1909,13 @@
1909
1909
  'failures': 0,
1910
1910
  'id': '43a67e37-1bae-4b11-8d3d-6c4b1b480231',
1911
1911
  'label': 'My Webhook',
1912
+ 'options': dict({
1913
+ 'checklistScored': False,
1914
+ 'created': False,
1915
+ 'deleted': False,
1916
+ 'scored': True,
1917
+ 'updated': False,
1918
+ }),
1912
1919
  'type': 'taskActivity',
1913
1920
  'updatedAt': '2025-02-08T22:06:17.195000+00:00',
1914
1921
  'url': 'https://some-webhook-url.com',
@@ -1917,6 +1924,9 @@
1917
1924
  'enabled': True,
1918
1925
  'failures': 0,
1919
1926
  'label': 'My Chat Webhook',
1927
+ 'options': dict({
1928
+ 'groupId': '89ee933e-79e5-43ed-8722-3ca5a58be79f',
1929
+ }),
1920
1930
  'type': 'groupChatReceived',
1921
1931
  'url': 'https://some-webhook-url.com',
1922
1932
  }),
@@ -1924,6 +1934,11 @@
1924
1934
  'enabled': True,
1925
1935
  'failures': 0,
1926
1936
  'label': 'My Activity Webhook',
1937
+ 'options': dict({
1938
+ 'leveledUp': False,
1939
+ 'mountRaised': False,
1940
+ 'petHatched': False,
1941
+ }),
1927
1942
  'type': 'userActivity',
1928
1943
  'url': 'https://some-webhook-url.com',
1929
1944
  }),
@@ -1,6 +1,6 @@
1
1
  # serializer version: 1
2
2
  # name: test_get_user
3
- HabiticaUserResponse(data=UserData(items=ItemsUser(gear=GearItems(equipped=EquippedGear(weapon='weapon_special_fall2024Warrior', armor='armor_special_fall2024Warrior', head='head_special_fall2024Warrior', shield='shield_special_fall2024Warrior', back='back_mystery_201402', headAccessory='headAccessory_special_pinkHeadband', eyewear='eyewear_special_pinkHalfMoon', body='body_mystery_202003'), costume=EquippedGear(weapon=None, armor='armor_base_0', head='head_base_0', shield='shield_base_0', back=None, headAccessory=None, eyewear=None, body=None), owned={'headAccessory_special_blackHeadband': True, 'headAccessory_special_blueHeadband': True, 'headAccessory_special_greenHeadband': True, 'headAccessory_special_pinkHeadband': True, 'headAccessory_special_redHeadband': True, 'headAccessory_special_whiteHeadband': True, 'headAccessory_special_yellowHeadband': True, 'eyewear_special_blackTopFrame': True, 'eyewear_special_blueTopFrame': True, 'eyewear_special_greenTopFrame': True, 'eyewear_special_pinkTopFrame': True, 'eyewear_special_redTopFrame': True, 'eyewear_special_whiteTopFrame': True, 'eyewear_special_yellowTopFrame': True, 'eyewear_special_blackHalfMoon': True, 'eyewear_special_blueHalfMoon': True, 'eyewear_special_greenHalfMoon': True, 'eyewear_special_pinkHalfMoon': True, 'eyewear_special_redHalfMoon': True, 'eyewear_special_whiteHalfMoon': True, 'eyewear_special_yellowHalfMoon': True}), currentMount='Velociraptor-Base', currentPet='Rat-Shade', special=SpecialItems(birthdayReceived=[], birthday=0, thankyouReceived=[], thankyou=0, greetingReceived=[], greeting=0, nyeReceived=[], nye=0, valentineReceived=[], valentine=0, seafoam=0, shinySeed=0, spookySparkles=0, snowball=0, congrats=0, congratsReceived=[], getwell=0, getwellReceived=[], goodluck=0, goodluckReceived=[]), lastDrop=LastDropItems(count=0, date=datetime.datetime(2024, 10, 19, 18, 43, 39, 784000, tzinfo=datetime.timezone.utc)), quests={'dustbunnies': 1}, mounts={}, food={}, hatchingPotions={}, eggs={}, pets={}), preferences=PreferencesUser(hair=HairPreferences(color='red', base=3, bangs=1, beard=0, mustache=0, flower=1), size='slim', skin='915533', shirt='blue', chair='none', costume=False, sleep=False, background='violet', emailNotifications=EmailNotificationsPreferences(unsubscribeFromAll=False, newPM=True, kickedGroup=True, wonChallenge=True, giftedGems=True, giftedSubscription=True, invitedParty=True, invitedGuild=True, questStarted=True, invitedQuest=True, importantAnnouncements=True, weeklyRecaps=True, onboarding=True, majorUpdates=True, subscriptionReminders=True, contentRelease=True), pushNotifications=PushNotificationsPreferences(unsubscribeFromAll=False, newPM=True, wonChallenge=True, giftedGems=True, giftedSubscription=True, invitedParty=True, invitedGuild=True, questStarted=True, invitedQuest=True, majorUpdates=True, mentionParty=True, mentionJoinedGuild=True, mentionUnjoinedGuild=True, partyActivity=True, contentRelease=True), suppressModals=SuppressModalsPreferences(levelUp=False, hatchPet=False, raisePet=False, streak=False), tasks=TasksPreferences(activeFilter=ActiveFilterTask(habit='all', daily='all', todo='remaining', reward='all'), groupByChallenge=False, confirmScoreNotes=False, mirrorGroupTasks=[]), dayStart=0, hideHeader=False, timezoneOffset=-120, sound='rosstavoTheme', allocationMode='flat', autoEquip=True, dateFormat='MM/dd/yyyy', stickyHeader=True, disableClasses=False, newTaskEdit=False, dailyDueDefaultView=False, advancedCollapsed=False, toolbarCollapsed=False, reverseChatOrder=False, developerMode=False, displayInviteToPartyWhenPartyIs1=True, automaticAllocation=None, webhooks={}, improvementCategories=[], timezoneOffsetAtLastCron=None, language=<Language.DE: 'de'>), stats=StatsUser(buffs=BuffsStats(seafoam=False, shinySeed=False, snowball=False, spookySparkles=False, Str=0, per=0, con=0, stealth=0, streaks=False, Int=0), Class=<HabiticaClass.WARRIOR: 'warrior'>, training=TrainingStats(Str=0.0, per=0, con=0, Int=0), hp=50.0, mp=10.0, exp=0, gp=0.0, lvl=1, points=0, Str=0, con=0, per=0, toNextLevel=25, maxHealth=50, maxMP=30, Int=0), id=UUID('c18e1853-bded-47a9-82e2-adfdad08894d'), flags=FlagsUser(customizationsNotification=False, tour=TourFlags(intro=-1, classes=-1, stats=-1, tavern=-1, party=-1, guilds=-1, challenges=-1, market=-1, pets=-1, mounts=-1, hall=-1, equipment=-1, groupPlans=-1), showTour=True, tutorial=TutorialFlags(common=CommonTutorial(habits=True, dailies=True, todos=True, rewards=True, party=True, pets=True, gems=True, skills=True, classes=True, tavern=True, equipment=True, items=True, mounts=True, inbox=True, stats=True), ios=IosTutorial(addTask=False, editTask=False, deleteTask=False, filterTask=False, groupPets=False, inviteParty=False, reorderTask=False)), dropsEnabled=False, itemsEnabled=False, lastNewStuffRead='', rewrite=True, classSelected=False, rebirthEnabled=False, levelDrops={}, recaptureEmailsPhase=0, weeklyRecapEmailsPhase=0, lastWeeklyRecap=datetime.datetime(2024, 10, 19, 18, 43, 39, 782000, tzinfo=datetime.timezone.utc), communityGuidelinesAccepted=False, cronCount=0, welcomed=True, armoireEnabled=True, armoireOpened=False, armoireEmpty=False, cardReceived=False, warnedLowHealth=False, verifiedUsername=True, newStuff=False, thirdPartyTools=None, mathUpdates=None, lastFreeRebirth=None, chatRevoked=None, chatShadowMuted=None, lastWeeklyRecapDiscriminator=None, onboardingEmailsPhase=None), auth=AuthUser(local=LocalAuth(email='test@example.com', username='test', lowerCaseUsername='test', has_password=True), timestamps=LocalTimestamps(created=datetime.datetime(2024, 10, 19, 18, 43, 39, 782000, tzinfo=datetime.timezone.utc), loggedin=datetime.datetime(2024, 10, 19, 18, 43, 39, 782000, tzinfo=datetime.timezone.utc), updated=datetime.datetime(2024, 10, 19, 18, 44, 51, 37000, tzinfo=datetime.timezone.utc)), facebook={}, google={}, apple={}), achievements=AchievementsUser(ultimateGearSets=UltimateGearSetsAchievments(healer=False, wizard=False, rogue=False, warrior=False), streak=0, challenges=[], perfect=0, quests=QuestsAchievments(bewilder=None, burnout=None, stressbeast=None, harpy=None, atom3=None, vice3=None, vice1=None, gryphon=None, evilsanta2=None, evilsanta=None, dilatory_derby=None, dilatory=None, atom2=None, atom1=None, dysheartener=None), backToBasics=None, dustDevil=None, primedForPainting=None, completedTask=None, createdTask=None, fedPet=None, hatchedPet=None, purchasedEquipment=None, tickledPink=None, goodAsGold=None, boneCollector=None, seeingRed=None, violetsAreBlue=None, shadyCustomer=None, joinedGuild=None, joinedChallenge=None, partyUp=None), backer=BackerUser(tier=None, npc=None, tokensApplied=None), contributor=ContributorUser(contributions=None, level=None, text=None), permissions=PermissionsUser(fullAccess=None, news=None, userSupport=None, challengeAdmin=None, moderator=None, coupons=None), purchased=PurchasedUser(plan=PlanPurchased(consecutive=ConsecutivePlan(trinkets=0, gemCapExtra=0, offset=0, count=0), mysteryItems=[], gemsBought=0, extraMonths=0, dateUpdated=None, perkMonthCount=-1, quantity=1), txnCount=0, background={'violet': True}, shirt={}, hair={}, skin={}, ads=False, mobileChat=None), history=HistoryUser(todos=[], exp=[]), invitations=InvitationsUser(party={}, guilds=[], parties=[]), party=PartyUser(quest=QuestParty(progress=ProgressQuest(up=0.0, down=0.0, collect={}, collectedItems=0), RSVPNeeded=False, key=None, completed=None), order='level', orderAscending='ascending', _id=None), profile=ProfileUser(blurb=None, imageUrl=None, name='test'), notifications=[], tags=[TagsUser(id=UUID('5358c71f-fe0f-4583-84a3-109b70c699fd'), name='Arbeit', challenge=None, group=None), TagsUser(id=UUID('45870b8b-3e1e-4e13-a722-6afcacdf689f'), name='Training', challenge=None, group=None), TagsUser(id=UUID('3e49b9db-0cc5-4070-b860-e16f1e4806a4'), name='Gesundheit + Wohlbefinden', challenge=None, group=None), TagsUser(id=UUID('0d85319e-7b9c-43e2-81ed-2a706521d5e3'), name='Schule', challenge=None, group=None), TagsUser(id=UUID('b7cf86bf-97ac-42d3-b5d0-5ffe998b62b4'), name='Teams', challenge=None, group=None), TagsUser(id=UUID('c584d792-0a9b-4646-a6ca-a67bb6ef3c36'), name='Hausarbeiten', challenge=None, group=None), TagsUser(id=UUID('0602fd13-edf2-46a7-99c0-c5084046efbb'), name='Kreativität', challenge=None, group=None)], inbox=InboxUser(newMessages=0, optOut=False, blocks=[], messages={}), tasksOrder=TasksOrderUser(habits=[UUID('21b10675-e238-4462-be11-1a4f8012fc9c'), UUID('69909140-a920-4b83-b018-b9156760aca3'), UUID('7e0679cf-e9cd-4604-b429-d061ea16ce72'), UUID('270df162-d47d-488b-9c1d-4fc4f0e2b2d2'), UUID('80ad00b5-622e-4d1a-af4d-6a6c199f3571'), UUID('0712669d-8374-4211-84ea-715cbcbae9c1'), UUID('56dee98d-038a-43f3-a514-59b1ed9a52ee'), UUID('25df4765-754c-47b1-a011-83b31f70c4fb')], dailys=[UUID('e22e9ef0-15be-478a-81c7-f9fdbb4fac10'), UUID('2a74baa2-3acd-426c-bce4-6b4bb145a8d5'), UUID('e18d0899-7c59-41c0-affd-318b8850c3e5'), UUID('3d0cecac-73c1-462b-ab39-a39cea107e6b'), UUID('1ed21cd0-e6f5-4707-b1b4-fb376d462387'), UUID('9117ad5e-2cda-43e0-a07c-0b175d32c0eb')], todos=[UUID('ac13c62c-9375-4809-a357-0e42b01a1b43'), UUID('2388ccad-0387-4ea6-9968-2d10d994e903'), UUID('5c6efb91-6ae3-4cad-8b19-2dd2fc52a965'), UUID('80afe0b9-e367-4473-8117-b8bc7115f54a'), UUID('4cc21c36-886c-4a43-b580-877e958a37fd'), UUID('10a45996-7133-4ca1-84d8-abf1093d9dcc'), UUID('fb867459-ae50-4cee-9017-c13206c6dfa2')], rewards=[UUID('4b18ccf6-3934-43a5-a153-31af8b2a36d9')]), extra={}, pushDevices=[], webhooks=[WebhooksUser(id=UUID('43a67e37-1bae-4b11-8d3d-6c4b1b480231'), Type=<WebhooksType.TASK_ACTIVITY: 'taskActivity'>, url='https://some-webhook-url.com', enabled=True, failures=0, label='My Webhook', lastFailureAt=None, createdAt=datetime.datetime(2025, 2, 8, 22, 6, 8, 894000, tzinfo=datetime.timezone.utc), updatedAt=datetime.datetime(2025, 2, 8, 22, 6, 17, 195000, tzinfo=datetime.timezone.utc)), WebhooksUser(id=None, Type=<WebhooksType.GROUP_CHAT_RECEIVED: 'groupChatReceived'>, url='https://some-webhook-url.com', enabled=True, failures=0, label='My Chat Webhook', lastFailureAt=None, createdAt=None, updatedAt=None), WebhooksUser(id=None, Type=<WebhooksType.USER_ACTIVITY: 'userActivity'>, url='https://some-webhook-url.com', enabled=True, failures=0, label='My Activity Webhook', lastFailureAt=None, createdAt=None, updatedAt=None)], loginIncentives=0, invitesSent=0, pinnedItems=[PinnedItemsUser(path='gear.flat.weapon_warrior_0', Type='marketGear'), PinnedItemsUser(path='gear.flat.armor_warrior_1', Type='marketGear'), PinnedItemsUser(path='gear.flat.shield_warrior_1', Type='marketGear'), PinnedItemsUser(path='gear.flat.head_warrior_1', Type='marketGear'), PinnedItemsUser(path='potion', Type='potion'), PinnedItemsUser(path='armoire', Type='armoire')], pinnedItemsOrder=[], unpinnedItems=[], secret=None, balance=0.0, lastCron=datetime.datetime(2024, 10, 19, 18, 43, 39, 784000, tzinfo=datetime.timezone.utc), needsCron=False, challenges=[], guilds=[], newMessages={}), success=True, notifications=[], userV=5, appVersion='5.28.8')
3
+ HabiticaUserResponse(data=UserData(items=ItemsUser(gear=GearItems(equipped=EquippedGear(weapon='weapon_special_fall2024Warrior', armor='armor_special_fall2024Warrior', head='head_special_fall2024Warrior', shield='shield_special_fall2024Warrior', back='back_mystery_201402', headAccessory='headAccessory_special_pinkHeadband', eyewear='eyewear_special_pinkHalfMoon', body='body_mystery_202003'), costume=EquippedGear(weapon=None, armor='armor_base_0', head='head_base_0', shield='shield_base_0', back=None, headAccessory=None, eyewear=None, body=None), owned={'headAccessory_special_blackHeadband': True, 'headAccessory_special_blueHeadband': True, 'headAccessory_special_greenHeadband': True, 'headAccessory_special_pinkHeadband': True, 'headAccessory_special_redHeadband': True, 'headAccessory_special_whiteHeadband': True, 'headAccessory_special_yellowHeadband': True, 'eyewear_special_blackTopFrame': True, 'eyewear_special_blueTopFrame': True, 'eyewear_special_greenTopFrame': True, 'eyewear_special_pinkTopFrame': True, 'eyewear_special_redTopFrame': True, 'eyewear_special_whiteTopFrame': True, 'eyewear_special_yellowTopFrame': True, 'eyewear_special_blackHalfMoon': True, 'eyewear_special_blueHalfMoon': True, 'eyewear_special_greenHalfMoon': True, 'eyewear_special_pinkHalfMoon': True, 'eyewear_special_redHalfMoon': True, 'eyewear_special_whiteHalfMoon': True, 'eyewear_special_yellowHalfMoon': True}), currentMount='Velociraptor-Base', currentPet='Rat-Shade', special=SpecialItems(birthdayReceived=[], birthday=0, thankyouReceived=[], thankyou=0, greetingReceived=[], greeting=0, nyeReceived=[], nye=0, valentineReceived=[], valentine=0, seafoam=0, shinySeed=0, spookySparkles=0, snowball=0, congrats=0, congratsReceived=[], getwell=0, getwellReceived=[], goodluck=0, goodluckReceived=[]), lastDrop=LastDropItems(count=0, date=datetime.datetime(2024, 10, 19, 18, 43, 39, 784000, tzinfo=datetime.timezone.utc)), quests={'dustbunnies': 1}, mounts={}, food={}, hatchingPotions={}, eggs={}, pets={}), preferences=PreferencesUser(hair=HairPreferences(color='red', base=3, bangs=1, beard=0, mustache=0, flower=1), size='slim', skin='915533', shirt='blue', chair='none', costume=False, sleep=False, background='violet', emailNotifications=EmailNotificationsPreferences(unsubscribeFromAll=False, newPM=True, kickedGroup=True, wonChallenge=True, giftedGems=True, giftedSubscription=True, invitedParty=True, invitedGuild=True, questStarted=True, invitedQuest=True, importantAnnouncements=True, weeklyRecaps=True, onboarding=True, majorUpdates=True, subscriptionReminders=True, contentRelease=True), pushNotifications=PushNotificationsPreferences(unsubscribeFromAll=False, newPM=True, wonChallenge=True, giftedGems=True, giftedSubscription=True, invitedParty=True, invitedGuild=True, questStarted=True, invitedQuest=True, majorUpdates=True, mentionParty=True, mentionJoinedGuild=True, mentionUnjoinedGuild=True, partyActivity=True, contentRelease=True), suppressModals=SuppressModalsPreferences(levelUp=False, hatchPet=False, raisePet=False, streak=False), tasks=TasksPreferences(activeFilter=ActiveFilterTask(habit='all', daily='all', todo='remaining', reward='all'), groupByChallenge=False, confirmScoreNotes=False, mirrorGroupTasks=[]), dayStart=0, hideHeader=False, timezoneOffset=-120, sound='rosstavoTheme', allocationMode='flat', autoEquip=True, dateFormat='MM/dd/yyyy', stickyHeader=True, disableClasses=False, newTaskEdit=False, dailyDueDefaultView=False, advancedCollapsed=False, toolbarCollapsed=False, reverseChatOrder=False, developerMode=False, displayInviteToPartyWhenPartyIs1=True, automaticAllocation=None, webhooks={}, improvementCategories=[], timezoneOffsetAtLastCron=None, language=<Language.DE: 'de'>), stats=StatsUser(buffs=BuffsStats(seafoam=False, shinySeed=False, snowball=False, spookySparkles=False, Str=0, per=0, con=0, stealth=0, streaks=False, Int=0), Class=<HabiticaClass.WARRIOR: 'warrior'>, training=TrainingStats(Str=0.0, per=0, con=0, Int=0), hp=50.0, mp=10.0, exp=0, gp=0.0, lvl=1, points=0, Str=0, con=0, per=0, toNextLevel=25, maxHealth=50, maxMP=30, Int=0), id=UUID('c18e1853-bded-47a9-82e2-adfdad08894d'), flags=FlagsUser(customizationsNotification=False, tour=TourFlags(intro=-1, classes=-1, stats=-1, tavern=-1, party=-1, guilds=-1, challenges=-1, market=-1, pets=-1, mounts=-1, hall=-1, equipment=-1, groupPlans=-1), showTour=True, tutorial=TutorialFlags(common=CommonTutorial(habits=True, dailies=True, todos=True, rewards=True, party=True, pets=True, gems=True, skills=True, classes=True, tavern=True, equipment=True, items=True, mounts=True, inbox=True, stats=True), ios=IosTutorial(addTask=False, editTask=False, deleteTask=False, filterTask=False, groupPets=False, inviteParty=False, reorderTask=False)), dropsEnabled=False, itemsEnabled=False, lastNewStuffRead='', rewrite=True, classSelected=False, rebirthEnabled=False, levelDrops={}, recaptureEmailsPhase=0, weeklyRecapEmailsPhase=0, lastWeeklyRecap=datetime.datetime(2024, 10, 19, 18, 43, 39, 782000, tzinfo=datetime.timezone.utc), communityGuidelinesAccepted=False, cronCount=0, welcomed=True, armoireEnabled=True, armoireOpened=False, armoireEmpty=False, cardReceived=False, warnedLowHealth=False, verifiedUsername=True, newStuff=False, thirdPartyTools=None, mathUpdates=None, lastFreeRebirth=None, chatRevoked=None, chatShadowMuted=None, lastWeeklyRecapDiscriminator=None, onboardingEmailsPhase=None), auth=AuthUser(local=LocalAuth(email='test@example.com', username='test', lowerCaseUsername='test', has_password=True), timestamps=LocalTimestamps(created=datetime.datetime(2024, 10, 19, 18, 43, 39, 782000, tzinfo=datetime.timezone.utc), loggedin=datetime.datetime(2024, 10, 19, 18, 43, 39, 782000, tzinfo=datetime.timezone.utc), updated=datetime.datetime(2024, 10, 19, 18, 44, 51, 37000, tzinfo=datetime.timezone.utc)), facebook={}, google={}, apple={}), achievements=AchievementsUser(ultimateGearSets=UltimateGearSetsAchievments(healer=False, wizard=False, rogue=False, warrior=False), streak=0, challenges=[], perfect=0, quests=QuestsAchievments(bewilder=None, burnout=None, stressbeast=None, harpy=None, atom3=None, vice3=None, vice1=None, gryphon=None, evilsanta2=None, evilsanta=None, dilatory_derby=None, dilatory=None, atom2=None, atom1=None, dysheartener=None), backToBasics=None, dustDevil=None, primedForPainting=None, completedTask=None, createdTask=None, fedPet=None, hatchedPet=None, purchasedEquipment=None, tickledPink=None, goodAsGold=None, boneCollector=None, seeingRed=None, violetsAreBlue=None, shadyCustomer=None, joinedGuild=None, joinedChallenge=None, partyUp=None), backer=BackerUser(tier=None, npc=None, tokensApplied=None), contributor=ContributorUser(contributions=None, level=None, text=None), permissions=PermissionsUser(fullAccess=None, news=None, userSupport=None, challengeAdmin=None, moderator=None, coupons=None), purchased=PurchasedUser(plan=PlanPurchased(consecutive=ConsecutivePlan(trinkets=0, gemCapExtra=0, offset=0, count=0), mysteryItems=[], gemsBought=0, extraMonths=0, dateUpdated=None, perkMonthCount=-1, quantity=1), txnCount=0, background={'violet': True}, shirt={}, hair={}, skin={}, ads=False, mobileChat=None), history=HistoryUser(todos=[], exp=[]), invitations=InvitationsUser(party={}, guilds=[], parties=[]), party=PartyUser(quest=QuestParty(progress=ProgressQuest(up=0.0, down=0.0, collect={}, collectedItems=0), RSVPNeeded=False, key=None, completed=None), order='level', orderAscending='ascending', _id=None), profile=ProfileUser(blurb=None, imageUrl=None, name='test'), notifications=[], tags=[TagsUser(id=UUID('5358c71f-fe0f-4583-84a3-109b70c699fd'), name='Arbeit', challenge=None, group=None), TagsUser(id=UUID('45870b8b-3e1e-4e13-a722-6afcacdf689f'), name='Training', challenge=None, group=None), TagsUser(id=UUID('3e49b9db-0cc5-4070-b860-e16f1e4806a4'), name='Gesundheit + Wohlbefinden', challenge=None, group=None), TagsUser(id=UUID('0d85319e-7b9c-43e2-81ed-2a706521d5e3'), name='Schule', challenge=None, group=None), TagsUser(id=UUID('b7cf86bf-97ac-42d3-b5d0-5ffe998b62b4'), name='Teams', challenge=None, group=None), TagsUser(id=UUID('c584d792-0a9b-4646-a6ca-a67bb6ef3c36'), name='Hausarbeiten', challenge=None, group=None), TagsUser(id=UUID('0602fd13-edf2-46a7-99c0-c5084046efbb'), name='Kreativität', challenge=None, group=None)], inbox=InboxUser(newMessages=0, optOut=False, blocks=[], messages={}), tasksOrder=TasksOrderUser(habits=[UUID('21b10675-e238-4462-be11-1a4f8012fc9c'), UUID('69909140-a920-4b83-b018-b9156760aca3'), UUID('7e0679cf-e9cd-4604-b429-d061ea16ce72'), UUID('270df162-d47d-488b-9c1d-4fc4f0e2b2d2'), UUID('80ad00b5-622e-4d1a-af4d-6a6c199f3571'), UUID('0712669d-8374-4211-84ea-715cbcbae9c1'), UUID('56dee98d-038a-43f3-a514-59b1ed9a52ee'), UUID('25df4765-754c-47b1-a011-83b31f70c4fb')], dailys=[UUID('e22e9ef0-15be-478a-81c7-f9fdbb4fac10'), UUID('2a74baa2-3acd-426c-bce4-6b4bb145a8d5'), UUID('e18d0899-7c59-41c0-affd-318b8850c3e5'), UUID('3d0cecac-73c1-462b-ab39-a39cea107e6b'), UUID('1ed21cd0-e6f5-4707-b1b4-fb376d462387'), UUID('9117ad5e-2cda-43e0-a07c-0b175d32c0eb')], todos=[UUID('ac13c62c-9375-4809-a357-0e42b01a1b43'), UUID('2388ccad-0387-4ea6-9968-2d10d994e903'), UUID('5c6efb91-6ae3-4cad-8b19-2dd2fc52a965'), UUID('80afe0b9-e367-4473-8117-b8bc7115f54a'), UUID('4cc21c36-886c-4a43-b580-877e958a37fd'), UUID('10a45996-7133-4ca1-84d8-abf1093d9dcc'), UUID('fb867459-ae50-4cee-9017-c13206c6dfa2')], rewards=[UUID('4b18ccf6-3934-43a5-a153-31af8b2a36d9')]), extra={}, pushDevices=[], webhooks=[TaskActivityWebhook(url='https://some-webhook-url.com', enabled=True, label='My Webhook', id=UUID('43a67e37-1bae-4b11-8d3d-6c4b1b480231'), Type=<WebhookType.TASK_ACTIVITY: 'taskActivity'>, options=TaskActivityOptions(created=False, updated=False, deleted=False, checklistScored=False, scored=True), failures=0, lastFailureAt=None, createdAt=datetime.datetime(2025, 2, 8, 22, 6, 8, 894000, tzinfo=datetime.timezone.utc), updatedAt=datetime.datetime(2025, 2, 8, 22, 6, 17, 195000, tzinfo=datetime.timezone.utc)), GroupChatReceivedWebhook(url='https://some-webhook-url.com', enabled=True, label='My Chat Webhook', id=None, groupId=None, Type=<WebhookType.GROUP_CHAT_RECEIVED: 'groupChatReceived'>, options=GroupChatReceivedOptions(groupId=UUID('89ee933e-79e5-43ed-8722-3ca5a58be79f')), failures=0, lastFailureAt=None, createdAt=None, updatedAt=None), UserActivityWebhook(url='https://some-webhook-url.com', enabled=True, label='My Activity Webhook', id=None, Type=<WebhookType.USER_ACTIVITY: 'userActivity'>, options=UserActivityOptions(petHatched=False, mountRaised=False, leveledUp=False), failures=0, lastFailureAt=None, createdAt=None, updatedAt=None)], loginIncentives=0, invitesSent=0, pinnedItems=[PinnedItemsUser(path='gear.flat.weapon_warrior_0', Type='marketGear'), PinnedItemsUser(path='gear.flat.armor_warrior_1', Type='marketGear'), PinnedItemsUser(path='gear.flat.shield_warrior_1', Type='marketGear'), PinnedItemsUser(path='gear.flat.head_warrior_1', Type='marketGear'), PinnedItemsUser(path='potion', Type='potion'), PinnedItemsUser(path='armoire', Type='armoire')], pinnedItemsOrder=[], unpinnedItems=[], secret=None, balance=0.0, lastCron=datetime.datetime(2024, 10, 19, 18, 43, 39, 784000, tzinfo=datetime.timezone.utc), needsCron=False, challenges=[], guilds=[], newMessages={}), success=True, notifications=[], userV=5, appVersion='5.28.8')
4
4
  # ---
5
5
  # name: test_get_user_anonymized
6
6
  HabiticaUserAnonymizedResponse(data=UserAnonymizedData(user=UserData(items=ItemsUser(gear=GearItems(equipped=EquippedGear(weapon=None, armor=None, head=None, shield=None, back=None, headAccessory=None, eyewear=None, body=None), costume=EquippedGear(weapon=None, armor=None, head=None, shield=None, back=None, headAccessory=None, eyewear=None, body=None), owned={}), currentMount=None, currentPet=None, special=SpecialItems(birthdayReceived=[], birthday=None, thankyouReceived=[], thankyou=None, greetingReceived=[], greeting=None, nyeReceived=[], nye=None, valentineReceived=[], valentine=None, seafoam=None, shinySeed=None, spookySparkles=None, snowball=None, congrats=None, congratsReceived=[], getwell=None, getwellReceived=[], goodluck=None, goodluckReceived=[]), lastDrop=LastDropItems(count=None, date=None), quests={}, mounts={}, food={}, hatchingPotions={}, eggs={}, pets={}), preferences=PreferencesUser(hair=HairPreferences(color=None, base=None, bangs=None, beard=None, mustache=None, flower=None), size=None, skin=None, shirt=None, chair=None, costume=None, sleep=None, background=None, emailNotifications=EmailNotificationsPreferences(unsubscribeFromAll=None, newPM=None, kickedGroup=None, wonChallenge=None, giftedGems=None, giftedSubscription=None, invitedParty=None, invitedGuild=None, questStarted=None, invitedQuest=None, importantAnnouncements=None, weeklyRecaps=None, onboarding=None, majorUpdates=None, subscriptionReminders=None, contentRelease=None), pushNotifications=PushNotificationsPreferences(unsubscribeFromAll=None, newPM=None, wonChallenge=None, giftedGems=None, giftedSubscription=None, invitedParty=None, invitedGuild=None, questStarted=None, invitedQuest=None, majorUpdates=None, mentionParty=None, mentionJoinedGuild=None, mentionUnjoinedGuild=None, partyActivity=None, contentRelease=None), suppressModals=SuppressModalsPreferences(levelUp=None, hatchPet=None, raisePet=None, streak=None), tasks=TasksPreferences(activeFilter=ActiveFilterTask(habit=None, daily=None, todo=None, reward=None), groupByChallenge=None, confirmScoreNotes=None, mirrorGroupTasks=[]), dayStart=None, hideHeader=None, timezoneOffset=None, sound=None, allocationMode=None, autoEquip=None, dateFormat=None, stickyHeader=None, disableClasses=None, newTaskEdit=None, dailyDueDefaultView=None, advancedCollapsed=None, toolbarCollapsed=None, reverseChatOrder=None, developerMode=None, displayInviteToPartyWhenPartyIs1=None, automaticAllocation=None, webhooks={}, improvementCategories=[], timezoneOffsetAtLastCron=None, language=None), stats=StatsUser(buffs=BuffsStats(seafoam=None, shinySeed=None, snowball=None, spookySparkles=None, Str=None, per=None, con=None, stealth=None, streaks=None, Int=None), Class=<HabiticaClass.WARRIOR: 'warrior'>, training=TrainingStats(Str=None, per=None, con=None, Int=None), hp=None, mp=None, exp=None, gp=None, lvl=None, points=None, Str=None, con=None, per=None, toNextLevel=None, maxHealth=None, maxMP=None, Int=None), id=None, flags=FlagsUser(customizationsNotification=None, tour=TourFlags(intro=None, classes=None, stats=None, tavern=None, party=None, guilds=None, challenges=None, market=None, pets=None, mounts=None, hall=None, equipment=None, groupPlans=None), showTour=None, tutorial=TutorialFlags(common=None, ios=None), dropsEnabled=None, itemsEnabled=None, lastNewStuffRead=None, rewrite=None, classSelected=None, rebirthEnabled=None, levelDrops={}, recaptureEmailsPhase=None, weeklyRecapEmailsPhase=None, lastWeeklyRecap=None, communityGuidelinesAccepted=None, cronCount=None, welcomed=None, armoireEnabled=None, armoireOpened=None, armoireEmpty=None, cardReceived=None, warnedLowHealth=None, verifiedUsername=None, newStuff=None, thirdPartyTools=None, mathUpdates=None, lastFreeRebirth=None, chatRevoked=None, chatShadowMuted=None, lastWeeklyRecapDiscriminator=None, onboardingEmailsPhase=None), auth=AuthUser(local=LocalAuth(email=None, username=None, lowerCaseUsername=None, has_password=None), timestamps=LocalTimestamps(created=None, loggedin=None, updated=None), facebook=None, google=None, apple=None), achievements=AchievementsUser(ultimateGearSets=UltimateGearSetsAchievments(healer=None, wizard=None, rogue=None, warrior=None), streak=None, challenges=[], perfect=None, quests=QuestsAchievments(bewilder=None, burnout=None, stressbeast=None, harpy=None, atom3=None, vice3=None, vice1=None, gryphon=None, evilsanta2=None, evilsanta=None, dilatory_derby=None, dilatory=None, atom2=None, atom1=None, dysheartener=None), backToBasics=None, dustDevil=None, primedForPainting=None, completedTask=None, createdTask=None, fedPet=None, hatchedPet=None, purchasedEquipment=None, tickledPink=None, goodAsGold=None, boneCollector=None, seeingRed=None, violetsAreBlue=None, shadyCustomer=None, joinedGuild=None, joinedChallenge=None, partyUp=None), backer=BackerUser(tier=None, npc=None, tokensApplied=None), contributor=ContributorUser(contributions=None, level=None, text=None), permissions=PermissionsUser(fullAccess=None, news=None, userSupport=None, challengeAdmin=None, moderator=None, coupons=None), purchased=PurchasedUser(plan=PlanPurchased(consecutive=ConsecutivePlan(trinkets=None, gemCapExtra=None, offset=None, count=None), mysteryItems=[], gemsBought=None, extraMonths=None, dateUpdated=None, perkMonthCount=None, quantity=None), txnCount=None, background={}, shirt={}, hair={}, skin={}, ads=None, mobileChat=None), history=HistoryUser(todos=[], exp=[]), invitations=InvitationsUser(party={}, guilds=[], parties=[]), party=PartyUser(quest=QuestParty(progress=ProgressQuest(up=None, down=None, collect={}, collectedItems=None), RSVPNeeded=None, key=None, completed=None), order=None, orderAscending=None, _id=None), profile=ProfileUser(blurb=None, imageUrl=None, name=None), notifications=[], tags=[], inbox=InboxUser(newMessages=None, optOut=None, blocks=[], messages={}), tasksOrder=TasksOrderUser(habits=[], dailys=[], todos=[], rewards=[]), extra={}, pushDevices=[], webhooks=[], loginIncentives=None, invitesSent=None, pinnedItems=[], pinnedItemsOrder=[], unpinnedItems=[], secret=None, balance=None, lastCron=None, needsCron=None, challenges=[], guilds=[], newMessages={}), tasks=[]))
File without changes
File without changes