Habiticalib 0.3.7rc0__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.7rc0 → habiticalib-0.4.0rc0}/PKG-INFO +1 -1
  2. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/pyproject.toml +5 -5
  3. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/__init__.py +34 -6
  4. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/const.py +1 -1
  5. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/lib.py +110 -0
  6. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/typedefs.py +174 -25
  7. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_serialize.ambr +15 -0
  8. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_user.ambr +1 -1
  9. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.cruft.json +0 -0
  10. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.editorconfig +0 -0
  11. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/FUNDING.yml +0 -0
  12. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/dependabot.yml +0 -0
  13. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/labels.yml +0 -0
  14. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/release-drafter.yml +0 -0
  15. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/workflows/build.yml +0 -0
  16. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/workflows/documentation.yml +0 -0
  17. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/workflows/draft.yml +0 -0
  18. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.github/workflows/labeler.yml +0 -0
  19. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.gitignore +0 -0
  20. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.pre-commit-config.yaml +0 -0
  21. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/.vscode/settings.json +0 -0
  22. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/LICENSE +0 -0
  23. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/README.md +0 -0
  24. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/docs/index.md +0 -0
  25. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/docs/reference/habiticalib.md +0 -0
  26. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/mkdocs.yml +0 -0
  27. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/exceptions.py +0 -0
  28. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/ha.py +0 -0
  29. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/helpers.py +0 -0
  30. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/src/habiticalib/py.typed +0 -0
  31. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__init__.py +0 -0
  32. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar.png +0 -0
  33. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[animated_background].png +0 -0
  34. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[default].png +0 -0
  35. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[kickstarter_backer_gear].png +0 -0
  36. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[kickstarter_pet_mount].png +0 -0
  37. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[seafoam].png +0 -0
  38. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[shinySeed].png +0 -0
  39. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[sleeping].png +0 -0
  40. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[snowball].png +0 -0
  41. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[special_0].png +0 -0
  42. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[special_1].png +0 -0
  43. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[spookySparkles].png +0 -0
  44. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[weapon_critical].png +0 -0
  45. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_from_styles[with_chair].png +0 -0
  46. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar/test_generate_avatar_to_file.png +0 -0
  47. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_avatar.ambr +0 -0
  48. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_login.ambr +0 -0
  49. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/__snapshots__/test_tasks.ambr +0 -0
  50. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/conftest.py +0 -0
  51. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/empty_data.json +0 -0
  52. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/login.json +0 -0
  53. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/task.json +0 -0
  54. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/task_order.json +0 -0
  55. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/tasks.json +0 -0
  56. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user.json +0 -0
  57. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_anonymized.json +0 -0
  58. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles.json +0 -0
  59. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_animated_background.json +0 -0
  60. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_kickstarter.json +0 -0
  61. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_kickstarter_pets.json +0 -0
  62. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_seafoam.json +0 -0
  63. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_shinySeed.json +0 -0
  64. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_sleeping.json +0 -0
  65. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_snowball.json +0 -0
  66. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_special_0.json +0 -0
  67. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_special_1.json +0 -0
  68. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_spookySparkles.json +0 -0
  69. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_weapon_critical.json +0 -0
  70. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/fixtures/user_styles_with_chair.json +0 -0
  71. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/test_avatar.py +0 -0
  72. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/test_login.py +0 -0
  73. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/test_serialize.py +0 -0
  74. {habiticalib-0.3.7rc0 → habiticalib-0.4.0rc0}/tests/test_tasks.py +0 -0
  75. {habiticalib-0.3.7rc0 → 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.7rc0
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.7rc0"
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
- from mashumaro.config import BaseConfig
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:
@@ -37,7 +38,7 @@ def serialize_datetime(date: str | int | None) -> datetime | None:
37
38
  class BaseModel(DataClassORJSONMixin):
38
39
  """Base config for dataclasses."""
39
40
 
40
- class Config(BaseConfig):
41
+ class Config:
41
42
  """Configuration for TaskData."""
42
43
 
43
44
  aliases = { # noqa: RUF012
@@ -51,6 +52,7 @@ class BaseModel(DataClassORJSONMixin):
51
52
  }
52
53
  serialize_by_alias = True
53
54
  omit_none = True
55
+ code_generation_options = [TO_DICT_ADD_OMIT_NONE_FLAG] # noqa: RUF012
54
56
 
55
57
  def __eq__(self, value: object) -> bool:
56
58
  """Check if two instances are equal."""
@@ -775,48 +777,187 @@ class PushDevicesUser(BaseModel):
775
777
  updatedAt: datetime
776
778
 
777
779
 
778
- class WebhooksType(StrEnum):
780
+ class WebhookType(StrEnum):
779
781
  """Webhook types."""
780
782
 
781
783
  TASK_ACTIVITY = "taskActivity"
782
784
  USER_ACTIVITY = "userActivity"
783
785
  QUEST_ACTIVITY = "questActivity"
784
786
  GROUP_CHAT_RECEIVED = "groupChatReceived"
787
+ GLOBAL_ACTIVITY = "globalActivity"
785
788
 
786
789
 
787
790
  @dataclass(kw_only=True)
788
- class WebhooksOptions(BaseModel):
789
- """Webhooks options data."""
791
+ class QuestActivityOptions(BaseModel):
792
+ """Quest activity options."""
790
793
 
791
- created: bool | None = None
792
- updated: bool | None = None
793
- deleted: bool | None = None
794
- scored: bool | None = None
795
- questStarted: bool | None = None
796
- questFinished: bool | None = None
797
- questInvited: bool | None = None
798
- petHatched: bool | None = None
799
- mountRaised: bool | None = None
800
- leveledUp: bool | None = None
801
- groupId: UUID | None = None
794
+ questStarted: bool = False
795
+ questFinished: bool = False
796
+ questInvited: bool = False
802
797
 
803
798
 
804
799
  @dataclass(kw_only=True)
805
- class WebhooksUser(BaseModel):
806
- """Webhooks user data."""
800
+ class UserActivityOptions(BaseModel):
801
+ """User activity options."""
802
+
803
+ petHatched: bool = False
804
+ mountRaised: bool = False
805
+ leveledUp: bool = False
807
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
808
833
  id: UUID | None = None
809
- Type: WebhooksType = WebhooksType.TASK_ACTIVITY
810
- url: str | None = None
811
- 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
+
812
918
  failures: int = 0
813
- label: str = ""
814
- options = WebhooksOptions
815
919
  lastFailureAt: datetime | None = None
816
920
  createdAt: datetime | None = None
817
921
  updatedAt: datetime | None = None
818
922
 
819
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
+
820
961
  @dataclass(kw_only=True)
821
962
  class PinnedItemsUser(BaseModel):
822
963
  """PinnedItems user data."""
@@ -850,7 +991,15 @@ class UserData(Avatar, BaseModel):
850
991
  tasksOrder: TasksOrderUser = field(default_factory=TasksOrderUser)
851
992
  extra: dict = field(default_factory=dict)
852
993
  pushDevices: list[PushDevicesUser] = field(default_factory=list)
853
- 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)
854
1003
  loginIncentives: int | None = None
855
1004
  invitesSent: int | None = None
856
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