Habiticalib 0.1.0a0__py3-none-any.whl → 0.1.0a2__py3-none-any.whl

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.
habiticalib/__init__.py CHANGED
@@ -1,12 +1,69 @@
1
1
  """Modern asynchronous Python client library for the Habitica API."""
2
2
 
3
- from .exceptions import HabiticaException, NotAuthorizedError, NotFoundError
3
+ from .const import ASSETS_URL, DEFAULT_URL, __version__
4
+ from .exceptions import (
5
+ BadRequestError,
6
+ HabiticaException,
7
+ NotAuthorizedError,
8
+ NotFoundError,
9
+ )
4
10
  from .lib import Habitica
11
+ from .types import (
12
+ Attributes,
13
+ Class,
14
+ Direction,
15
+ Frequency,
16
+ HabiticaClassSystemResponse,
17
+ HabiticaErrorResponse,
18
+ HabiticaLoginResponse,
19
+ HabiticaResponse,
20
+ HabiticaScoreResponse,
21
+ HabiticaStatsResponse,
22
+ HabiticaTagResponse,
23
+ HabiticaTagsResponse,
24
+ HabiticaTaskOrderResponse,
25
+ HabiticaTaskResponse,
26
+ HabiticaTasksResponse,
27
+ HabiticaUserExport,
28
+ HabiticaUserResponse,
29
+ Language,
30
+ Skill,
31
+ Task,
32
+ TaskFilter,
33
+ TaskType,
34
+ UserStyles,
35
+ )
5
36
 
6
- __version__ = "0.1.0a0"
7
37
  __all__ = [
38
+ "__version__",
39
+ "ASSETS_URL",
40
+ "Attributes",
41
+ "BadRequestError",
42
+ "Class",
43
+ "DEFAULT_URL",
44
+ "Direction",
45
+ "Frequency",
8
46
  "Habitica",
47
+ "HabiticaClassSystemResponse",
48
+ "HabiticaErrorResponse",
9
49
  "HabiticaException",
50
+ "HabiticaLoginResponse",
51
+ "HabiticaResponse",
52
+ "HabiticaScoreResponse",
53
+ "HabiticaStatsResponse",
54
+ "HabiticaTagResponse",
55
+ "HabiticaTagsResponse",
56
+ "HabiticaTaskOrderResponse",
57
+ "HabiticaTaskResponse",
58
+ "HabiticaTasksResponse",
59
+ "HabiticaUserExport",
60
+ "HabiticaUserResponse",
61
+ "Language",
10
62
  "NotAuthorizedError",
11
63
  "NotFoundError",
64
+ "Skill",
65
+ "Task",
66
+ "TaskFilter",
67
+ "TaskType",
68
+ "UserStyles",
12
69
  ]
habiticalib/const.py CHANGED
@@ -1,5 +1,7 @@
1
1
  """Constants for Habiticalib."""
2
2
 
3
+ __version__ = "0.1.0a2"
4
+
3
5
  DEFAULT_URL = "https://habitica.com/"
4
6
  ASSETS_URL = "https://habitica-assets.s3.amazonaws.com/mobileApp/images/"
5
7
 
habiticalib/exceptions.py CHANGED
@@ -2,15 +2,25 @@
2
2
 
3
3
  from typing import Self
4
4
 
5
+ from multidict import CIMultiDictProxy
6
+
5
7
  from habiticalib.types import HabiticaErrorResponse
6
8
 
7
9
 
8
10
  class HabiticaException(Exception): # noqa: N818
9
11
  """Base class for Habitica errors."""
10
12
 
11
- def __init__(self: Self, error: HabiticaErrorResponse) -> None:
13
+ def __init__(
14
+ self: Self,
15
+ error: HabiticaErrorResponse,
16
+ headers: CIMultiDictProxy,
17
+ ) -> None:
12
18
  """Initialize the Exception."""
13
19
  self.error = error
20
+ self.rate_limit = headers.get("x-ratelimit-limit")
21
+ self.rate_limit_remaining = headers.get("x-ratelimit-remaining")
22
+ self.rate_limit_reset = headers.get("x-ratelimit-reset")
23
+ self.retry_after = headers.get("retry-after")
14
24
 
15
25
  super().__init__(error.message)
16
26
 
@@ -25,3 +35,7 @@ class NotFoundError(HabiticaException):
25
35
 
26
36
  class BadRequestError(HabiticaException):
27
37
  """BadRequest error."""
38
+
39
+
40
+ class TooManyRequestsError(HabiticaException):
41
+ """TooManyRequests error."""
habiticalib/helpers.py CHANGED
@@ -1,13 +1,12 @@
1
1
  """Helper functions for Habiticalib."""
2
2
 
3
3
  from dataclasses import asdict
4
- from importlib.metadata import version
5
4
  import platform
6
5
  import uuid
7
6
 
8
7
  import aiohttp
9
8
 
10
- from .const import DEVELOPER_ID
9
+ from .const import DEVELOPER_ID, __version__
11
10
  from .types import HabiticaUserResponse, UserData, UserStyles
12
11
 
13
12
 
@@ -58,7 +57,7 @@ def get_user_agent() -> str:
58
57
  os_info = f"{os_name} {os_release} ({os_version}); {arch}"
59
58
 
60
59
  return (
61
- f"Habiticalib/{version("habiticalib")} ({os_info}) "
60
+ f"Habiticalib/{__version__} ({os_info}) "
62
61
  f"aiohttp/{aiohttp.__version__} Python/{platform.python_version()} "
63
62
  " +https://github.com/tr4nt0r/habiticalib)"
64
63
  )
@@ -106,7 +105,7 @@ def get_x_client(x_client: str | None = None) -> str:
106
105
 
107
106
  return x_client
108
107
 
109
- return f"{DEVELOPER_ID} - Habiticalib/{version("habiticalib")}"
108
+ return f"{DEVELOPER_ID} - Habiticalib/{__version__}"
110
109
 
111
110
 
112
111
  def extract_user_styles(user_data: HabiticaUserResponse) -> UserStyles:
habiticalib/lib.py CHANGED
@@ -13,7 +13,12 @@ from PIL import Image
13
13
  from yarl import URL
14
14
 
15
15
  from .const import ASSETS_URL, BACKER_ONLY_GEAR, DEFAULT_URL
16
- from .exceptions import BadRequestError, NotAuthorizedError, NotFoundError
16
+ from .exceptions import (
17
+ BadRequestError,
18
+ NotAuthorizedError,
19
+ NotFoundError,
20
+ TooManyRequestsError,
21
+ )
17
22
  from .helpers import extract_user_styles, get_user_agent, get_x_client, join_fields
18
23
  from .types import (
19
24
  Attributes,
@@ -50,10 +55,7 @@ class Habitica:
50
55
  """Modern asynchronous Python client library for the Habitica API."""
51
56
 
52
57
  _close_session: bool = False
53
- _headers: dict[str, str]
54
- _assets_cache: dict[str, IO[bytes]]
55
58
  _cache_size = 32
56
- _cache_order: list[str]
57
59
 
58
60
  def __init__(
59
61
  self,
@@ -66,7 +68,8 @@ class Habitica:
66
68
  """Initialize the Habitica API client."""
67
69
  client_headers = {"X-CLIENT": get_x_client(x_client)}
68
70
  user_agent = {"User-Agent": get_user_agent()}
69
- self._headers = {}
71
+ self._headers: dict[str, str] = {}
72
+
70
73
  if session:
71
74
  self._session = session
72
75
  if "User-Agent" not in session.headers:
@@ -89,7 +92,10 @@ class Habitica:
89
92
  msg = "Both 'api_user' and 'api_key' must be provided together."
90
93
  raise ValueError(msg)
91
94
 
92
- self.url = URL(url if url else DEFAULT_URL) / "api"
95
+ self.url = URL(url if url else DEFAULT_URL)
96
+
97
+ self._assets_cache: dict[str, IO[bytes]] = {}
98
+ self._cache_order: list[str] = []
93
99
 
94
100
  async def _request(self, method: str, url: URL, **kwargs) -> str:
95
101
  """Handle API request."""
@@ -101,15 +107,19 @@ class Habitica:
101
107
  ) as r:
102
108
  if r.status == HTTPStatus.UNAUTHORIZED:
103
109
  raise NotAuthorizedError(
104
- HabiticaErrorResponse.from_json(await r.text()),
110
+ HabiticaErrorResponse.from_json(await r.text()), r.headers
105
111
  )
106
112
  if r.status == HTTPStatus.NOT_FOUND:
107
113
  raise NotFoundError(
108
- HabiticaErrorResponse.from_json(await r.text()),
114
+ HabiticaErrorResponse.from_json(await r.text()), r.headers
109
115
  )
110
116
  if r.status == HTTPStatus.BAD_REQUEST:
111
117
  raise BadRequestError(
112
- HabiticaErrorResponse.from_json(await r.text()),
118
+ HabiticaErrorResponse.from_json(await r.text()), r.headers
119
+ )
120
+ if r.status == HTTPStatus.TOO_MANY_REQUESTS:
121
+ raise TooManyRequestsError(
122
+ HabiticaErrorResponse.from_json(await r.text()), r.headers
113
123
  )
114
124
  r.raise_for_status()
115
125
  return await r.text()
@@ -168,7 +178,7 @@ class Habitica:
168
178
  >>> response.data.apiToken
169
179
  'api-token'
170
180
  """
171
- url = self.url / "v3/user/auth/local/login"
181
+ url = self.url / "api/v3/user/auth/local/login"
172
182
  data = {
173
183
  "username": username,
174
184
  "password": password,
@@ -228,7 +238,7 @@ class Habitica:
228
238
  >>> response = await habitica.get_user(user_fields="achievements,items.mounts")
229
239
  >>> response.data # Access the returned data from the response
230
240
  """
231
- url = self.url / "v3/user"
241
+ url = self.url / "api/v3/user"
232
242
  params = {}
233
243
 
234
244
  if user_fields:
@@ -289,7 +299,7 @@ class Habitica:
289
299
 
290
300
  >>> await habitica.get_tasks(TaskType.HABITS, due_date=datetime(2024, 10, 15))
291
301
  """
292
- url = self.url / "v3/tasks/user"
302
+ url = self.url / "api/v3/tasks/user"
293
303
  params = {}
294
304
 
295
305
  if task_type:
@@ -333,7 +343,7 @@ class Habitica:
333
343
  >>> task_response = await habitica.get_task(task_id)
334
344
  >>> print(task_response.data) # Displays the retrieved task information
335
345
  """
336
- url = self.url / "v3/tasks" / str(task_id)
346
+ url = self.url / "api/v3/tasks" / str(task_id)
337
347
 
338
348
  return HabiticaTaskResponse.from_json(
339
349
  await self._request("get", url=url),
@@ -372,7 +382,7 @@ class Habitica:
372
382
  >>> create_response = await habitica.create_task(new_task)
373
383
  >>> print(create_response.data) # Displays the created task information
374
384
  """
375
- url = self.url / "v3/tasks/user"
385
+ url = self.url / "api/v3/tasks/user"
376
386
 
377
387
  return HabiticaTaskResponse.from_json(
378
388
  await self._request("post", url=url, json=task.to_dict()),
@@ -415,7 +425,7 @@ class Habitica:
415
425
  >>> update_response = await habitica.update_task(task_id, updated_task)
416
426
  >>> print(update_response.data) # Displays the updated task information
417
427
  """
418
- url = self.url / "v3/tasks" / str(task_id)
428
+ url = self.url / "api/v3/tasks" / str(task_id)
419
429
 
420
430
  return HabiticaTaskResponse.from_json(
421
431
  await self._request("put", url=url, json=task.to_dict()),
@@ -454,7 +464,7 @@ class Habitica:
454
464
  >>> delete_response = await habitica.delete_task(task_id)
455
465
  >>> print(delete_response.success) # True if successfully deleted
456
466
  """
457
- url = self.url / "v3/tasks" / str(task_id)
467
+ url = self.url / "api/v3/tasks" / str(task_id)
458
468
 
459
469
  return HabiticaResponse.from_json(
460
470
  await self._request("delete", url=url),
@@ -496,7 +506,7 @@ class Habitica:
496
506
  >>> reorder_response = await habitica.reorder_task(task_id, 2)
497
507
  >>> print(reorder_response.data) # Displays a list of task IDs in the new order
498
508
  """
499
- url = self.url / "v3/tasks" / str(task_id) / "move/to" / str(to)
509
+ url = self.url / "api/v3/tasks" / str(task_id) / "move/to" / str(to)
500
510
 
501
511
  return HabiticaTaskOrderResponse.from_json(
502
512
  await self._request("post", url=url),
@@ -530,7 +540,7 @@ class Habitica:
530
540
  TimeoutError
531
541
  If the connection times out.
532
542
  """
533
- url = self.url.parent / "export/userdata.json"
543
+ url = self.url / "export/userdata.json"
534
544
 
535
545
  return HabiticaUserExport.from_json(
536
546
  await self._request("get", url=url),
@@ -575,7 +585,7 @@ class Habitica:
575
585
  TimeoutError
576
586
  If the connection times out.
577
587
  """
578
- url = self.url / "v3/content"
588
+ url = self.url / "api/v3/content"
579
589
  params = {}
580
590
 
581
591
  if language:
@@ -611,7 +621,7 @@ class Habitica:
611
621
  TimeoutError
612
622
  If the connection times out.
613
623
  """
614
- url = self.url / "v3/cron"
624
+ url = self.url / "api/v3/cron"
615
625
  return HabiticaResponse.from_json(await self._request("post", url=url))
616
626
 
617
627
  async def allocate_single_stat_point(
@@ -655,7 +665,7 @@ class Habitica:
655
665
  Allocate a single stat point to Strength (default):
656
666
  >>> await habitica.allocate_single_stat_point()
657
667
  """
658
- url = self.url / "v3/user/allocate"
668
+ url = self.url / "api/v3/user/allocate"
659
669
  params = {"stat": stat}
660
670
 
661
671
  return HabiticaStatsResponse.from_json(
@@ -689,7 +699,7 @@ class Habitica:
689
699
  TimeoutError
690
700
  If the connection times out.
691
701
  """
692
- url = self.url / "v3/user/allocate-now"
702
+ url = self.url / "api/v3/user/allocate-now"
693
703
 
694
704
  return HabiticaStatsResponse.from_json(
695
705
  await self._request("post", url=url),
@@ -742,7 +752,7 @@ class Habitica:
742
752
  Allocate 2 points to INT and 1 point to STR:
743
753
  >>> await allocate_bulk_stat_points(int_points=2, str_points=1)
744
754
  """
745
- url = self.url / "v3/user/allocate-bulk"
755
+ url = self.url / "api/v3/user/allocate-bulk"
746
756
  json = {
747
757
  "stats": {
748
758
  "int": int_points,
@@ -781,7 +791,7 @@ class Habitica:
781
791
  TimeoutError
782
792
  If the connection times out.
783
793
  """
784
- url = self.url / "v3/user/buy-health-potion"
794
+ url = self.url / "api/v3/user/buy-health-potion"
785
795
 
786
796
  return HabiticaStatsResponse.from_json(
787
797
  await self._request("post", url=url),
@@ -822,7 +832,7 @@ class Habitica:
822
832
  TimeoutError
823
833
  If the connection times out.
824
834
  """
825
- url = self.url / "v3/class/cast" / spell
835
+ url = self.url / "api/v3/class/cast" / spell
826
836
  params = {}
827
837
 
828
838
  if target_id:
@@ -853,7 +863,7 @@ class Habitica:
853
863
  TimeoutError
854
864
  If the connection times out.
855
865
  """
856
- url = self.url / "v3/user/sleep"
866
+ url = self.url / "api/v3/user/sleep"
857
867
 
858
868
  return HabiticaResponse.from_json(await self._request("post", url=url))
859
869
 
@@ -875,7 +885,7 @@ class Habitica:
875
885
  TimeoutError
876
886
  If the connection times out.
877
887
  """
878
- url = self.url / "v3/user/revive"
888
+ url = self.url / "api/v3/user/revive"
879
889
 
880
890
  return HabiticaResponse.from_json(await self._request("post", url=url))
881
891
 
@@ -914,7 +924,7 @@ class Habitica:
914
924
  >>> change_response = await habitica.change_class(new_class)
915
925
  >>> print(change_response.data.stats) # Displays the user's stats after class change
916
926
  """
917
- url = self.url / "v3/user/change-class"
927
+ url = self.url / "api/v3/user/change-class"
918
928
  params = {"class": Class.value}
919
929
 
920
930
  return HabiticaClassSystemResponse.from_json(
@@ -947,7 +957,7 @@ class Habitica:
947
957
  >>> disable_response = await habitica.disable_classes()
948
958
  >>> print(disable_response.data.stats) # Displays the user's stats after disabling the class system
949
959
  """
950
- url = self.url / "v3/user/disable-classes"
960
+ url = self.url / "api/v3/user/disable-classes"
951
961
 
952
962
  return HabiticaClassSystemResponse.from_json(
953
963
  await self._request("post", url=url)
@@ -980,7 +990,7 @@ class Habitica:
980
990
  >>> delete_response = await habitica.delete_completed_todos()
981
991
  >>> print(delete_response.success) # True if successfully cleared completed to-dos
982
992
  """
983
- url = self.url / "v3/tasks/clearCompletedTodos"
993
+ url = self.url / "api/v3/tasks/clearCompletedTodos"
984
994
 
985
995
  return HabiticaClassSystemResponse.from_json(
986
996
  await self._request("post", url=url)
@@ -1022,7 +1032,7 @@ class Habitica:
1022
1032
  TimeoutError
1023
1033
  If the connection times out.
1024
1034
  """
1025
- url = self.url / "v3/tasks" / str(task_id) / "score" / direction.value
1035
+ url = self.url / "api/v3/tasks" / str(task_id) / "score" / direction.value
1026
1036
 
1027
1037
  return HabiticaScoreResponse.from_json(
1028
1038
  await self._request("post", url=url),
@@ -1055,7 +1065,7 @@ class Habitica:
1055
1065
  >>> tags_response = await habitica.get_tags()
1056
1066
  >>> print(tags_response.data)
1057
1067
  """
1058
- url = self.url / "v3/tags"
1068
+ url = self.url / "api/v3/tags"
1059
1069
 
1060
1070
  return HabiticaTagsResponse.from_json(
1061
1071
  await self._request("post", url=url),
@@ -1093,7 +1103,7 @@ class Habitica:
1093
1103
  >>> tag_response = await habitica.get_tag()
1094
1104
  >>> print(tag_response.data)
1095
1105
  """
1096
- url = self.url / "v3/tags" / str(tag_id)
1106
+ url = self.url / "api/v3/tags" / str(tag_id)
1097
1107
 
1098
1108
  return HabiticaTagResponse.from_json(
1099
1109
  await self._request("post", url=url),
@@ -1132,7 +1142,7 @@ class Habitica:
1132
1142
  >>> delete_response = await habitica.delete_tag(tag_id)
1133
1143
  >>> print(delete_response.success) # True if successfully deleted
1134
1144
  """
1135
- url = self.url / "v3/tags" / str(tag_id)
1145
+ url = self.url / "api/v3/tags" / str(tag_id)
1136
1146
 
1137
1147
  return HabiticaTagResponse.from_json(
1138
1148
  await self._request("delete", url=url),
@@ -1171,7 +1181,7 @@ class Habitica:
1171
1181
  >>> new_tag_response = await habitica.create_tag("New Tag Name")
1172
1182
  >>> print(new_tag_response.data.id) # Displays the id of the new tag
1173
1183
  """
1174
- url = self.url / "v3/tags"
1184
+ url = self.url / "api/v3/tags"
1175
1185
  json = {"name": name}
1176
1186
  return HabiticaTagResponse.from_json(
1177
1187
  await self._request("post", url=url, json=json),
@@ -1212,7 +1222,7 @@ class Habitica:
1212
1222
  >>> update_response = await habitica.update_tag(tag_id, "New Tag Name")
1213
1223
  >>> print(update_response.data) # Displays the updated tag information
1214
1224
  """
1215
- url = self.url / "v3/tags" / str(tag_id)
1225
+ url = self.url / "api/v3/tags" / str(tag_id)
1216
1226
  json = {"name": name}
1217
1227
  return HabiticaTagResponse.from_json(
1218
1228
  await self._request("put", url=url, json=json),
@@ -1253,7 +1263,7 @@ class Habitica:
1253
1263
  >>> reorder_response = await habitica.reorder_tag(tag_id, 2)
1254
1264
  >>> print(reorder_response.success) # True if reorder is successful
1255
1265
  """
1256
- url = self.url / "v3/reorder-tags"
1266
+ url = self.url / "api/v3/reorder-tags"
1257
1267
  json = {"tagId": str(tag_id), "to": to}
1258
1268
 
1259
1269
  return HabiticaTagResponse.from_json(
habiticalib/types.py CHANGED
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
 
6
6
  from dataclasses import dataclass, field
7
7
  from datetime import UTC, datetime
8
- from enum import StrEnum
8
+ from enum import Enum, StrEnum
9
9
  from typing import Any
10
10
  from uuid import UUID # noqa: TCH003
11
11
 
@@ -17,13 +17,14 @@ from mashumaro.mixins.orjson import DataClassORJSONMixin
17
17
  def serialize_datetime(date: str | int | None) -> datetime | None:
18
18
  """Convert an iso date to a datetime.date object."""
19
19
  if isinstance(date, int):
20
- datetime.fromtimestamp(date / 1000, tz=UTC)
20
+ return datetime.fromtimestamp(date / 1000, tz=UTC)
21
21
  if isinstance(date, str):
22
22
  try:
23
23
  return datetime.fromisoformat(date)
24
24
  except ValueError:
25
25
  # sometimes nextDue dates are JavaScript datetime strings
26
26
  # instead of iso: "Mon May 06 2024 00:00:00 GMT+0200"
27
+ # This was fixed in Habitica v5.28.9, nextDue dates are now isoformat
27
28
  try:
28
29
  return datetime.strptime(date, "%a %b %d %Y %H:%M:%S %Z%z")
29
30
  except ValueError:
@@ -865,10 +866,10 @@ class Task(DataClassORJSONMixin):
865
866
  tags: list[UUID] | None = None
866
867
  collapseChecklist: bool | None = None
867
868
  date: datetime | None = None
868
- priority: float | None = None
869
+ priority: TaskPriority | None = None
869
870
  reminders: list[Reminders] | None = None
870
871
  checklist: list[str] | None = None
871
- task_type: TaskType | None = None
872
+ Type: TaskType | None = field(default=None, metadata=field_options(alias="type"))
872
873
  up: bool | None = None
873
874
  down: bool | None = None
874
875
  counterUp: int | None = None
@@ -894,7 +895,7 @@ class TaskData:
894
895
  notes: str | None = None
895
896
  tags: list[UUID] | None = None
896
897
  value: float | None = None
897
- priority: float | None = None
898
+ priority: TaskPriority | None = None
898
899
  attribute: Attributes | None = None
899
900
  byHabitica: bool | None = None
900
901
  createdAt: datetime | None = None
@@ -1200,3 +1201,12 @@ class Direction(StrEnum):
1200
1201
 
1201
1202
  UP = "up"
1202
1203
  DOWN = "down"
1204
+
1205
+
1206
+ class TaskPriority(Enum):
1207
+ """Task difficulties."""
1208
+
1209
+ TRIVIAL = 0.1
1210
+ EASY = 1
1211
+ MEDIUM = 1.5
1212
+ HARD = 2
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.3
2
+ Name: Habiticalib
3
+ Version: 0.1.0a2
4
+ Summary: Asynchronous Python client library for the Habitica API
5
+ Project-URL: Documentation, https://tr4nt0r.github.io/habiticalib/
6
+ Project-URL: Source, https://github.com/tr4nt0r/habiticalib
7
+ Author-email: Manfred Dennerlein Rodelo <manfred@dennerlein.name>
8
+ License: MIT License
9
+ License-File: LICENSE
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Requires-Python: >=3.12
14
+ Requires-Dist: aiohttp~=3.9
15
+ Requires-Dist: mashumaro~=3.13
16
+ Requires-Dist: orjson~=3.10
17
+ Requires-Dist: pillow~=10.4
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Habiticalib
21
+
22
+ <p align="center">
23
+ <em>Modern asynchronous Python client library for the Habitica API</em>
24
+ </p>
25
+
26
+ [![build](https://github.com/tr4nt0r/habiticalib/workflows/Build/badge.svg)](https://github.com/tr4nt0r/habiticalib/actions)
27
+ [![codecov](https://codecov.io/gh/tr4nt0r/habiticalib/graph/badge.svg?token=iEsZ1Ktj7d)](https://codecov.io/gh/tr4nt0r/habiticalib)
28
+ [![PyPI version](https://badge.fury.io/py/habiticalib.svg)](https://badge.fury.io/py/habiticalib)
29
+
30
+ **Habiticalib** is a Python library for interacting with the [Habitica API](https://habitica.com). It provides an organized, typed interface to work with Habitica’s features, including tasks, user data, and avatars. The goal of this library is to simplify integration with Habitica.
31
+
32
+ ## Key features
33
+
34
+ - **Asynchronous**: The library is fully asynchronous, allowing non-blocking API calls.
35
+ - **Fully typed with Dataclasses**: The library is fully typed using Python `dataclasses`. It handles serialization with `mashumaro` and `orjson` for efficient conversion between Habitica API JSON data and Python objects.
36
+ - **Dynamic avatar image generation**: Habiticalib can fetch all necessary assets (like equipped items, pets, and mounts) and combine them into a single avatar image. This image can be saved to disk or returned as a byte buffer for further processing.
37
+ **Fetch user data**: Retrieve and manage user data such as stats, preferences, and items. User data is structured with dataclasses to make it easy to work with.
38
+ - **Task management**: Support for creating, updating, and retrieving Habitica tasks (to-dos, dailies, habits, rewards) is provided.
39
+ - **Task status updates**: The library allows updates for task statuses, habit scoring, and daily completion.
40
+ - **Tags**: Habiticalib supports the creation, updating and deletion of tags.
41
+ - **Stat allocation, class cystem and sleep**: The library offers methods for stat point allocation and switching between Habitica classes. It also provides the ability to disable the class system and pausing damage(resting in the inn)
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install habiticalib
47
+ ```
48
+
49
+ ## Getting started
50
+ Here’s an example to demonstrate basic usage:
51
+
52
+ ```python
53
+ import asyncio
54
+
55
+ from aiohttp import ClientSession
56
+
57
+ from habiticalib import Habitica, TaskType
58
+
59
+
60
+ async def main():
61
+ async with ClientSession() as session:
62
+ habitica = Habitica(session)
63
+
64
+ # Login to Habitica
65
+ habitica.login(username="your_username", password="your_password")
66
+
67
+ # Fetch user data
68
+ user_data = await habitica.user()
69
+ print(f"Your current health: {user_data.stats.hp}")
70
+
71
+ # Fetch all tasks (to-dos, dailies, habits, and rewards)
72
+ tasks = await habitica.get_tasks()
73
+ print("All tasks:")
74
+ for task in tasks:
75
+ print(f"- {task.text} (type: {task.type})")
76
+
77
+ # Fetch only to-dos
78
+ todos = await habitica.get_tasks(task_type=TaskType.TODO)
79
+ print("\nTo-Do tasks:")
80
+ for todo in todos:
81
+ print(f"- {todo.text} (due: {todo.date})")
82
+
83
+ # Fetch only dailies
84
+ dailies = await habitica.tasks(task_type=TaskType.DAILY)
85
+ print("\nDailies:")
86
+ for daily in dailies:
87
+ print(f"- {daily.text}")
88
+
89
+ asyncio.run(main())
90
+ ```
91
+
92
+ ## Documentation
93
+
94
+ For full documentation and detailed usage examples, please visit the [Habiticalib documentation](https://tr4nt0r.github.io/habiticalib/).
95
+
96
+ ## License
97
+
98
+ This project is licensed under the terms of the MIT license.
@@ -0,0 +1,11 @@
1
+ habiticalib/__init__.py,sha256=_RUFLOZSqQWr_j3TnhHhtD5szaf59HR-sS7aOpE4NTg,1491
2
+ habiticalib/const.py,sha256=NsbZeJ3Z_OuZcGzFZESInj9vpyYzjjCpJnVhGmu30vw,609
3
+ habiticalib/exceptions.py,sha256=Db7lDDdT97FsK4S9N45gcusiMMWiqeIcab0H8i7xTtE,1032
4
+ habiticalib/helpers.py,sha256=Y7lAlufK2isnNp7ybcqcWLG9xkWltouCiXaBeLOkobg,3479
5
+ habiticalib/lib.py,sha256=F_tqIULUC8mhYXLak2RYGA_AeaFuAQY6Ie8NImslv_g,54130
6
+ habiticalib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ habiticalib/types.py,sha256=zF9HzSXkuUYwuUv9F8fXfg6sxWy0nlfUo9hFqQG8eGA,32825
8
+ habiticalib-0.1.0a2.dist-info/METADATA,sha256=3hI8OP0ECfHdmYPaZ9zGyX0Nx04kRly2635ll4yfrYY,4178
9
+ habiticalib-0.1.0a2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
+ habiticalib-0.1.0a2.dist-info/licenses/LICENSE,sha256=oIinIOSJ49l1iVIRI3XGXFWt6SF7a83kEFBAY8ORwNI,1084
11
+ habiticalib-0.1.0a2.dist-info/RECORD,,
@@ -1,92 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: Habiticalib
3
- Version: 0.1.0a0
4
- Summary: Asynchronous Python client library for the Habitica API
5
- Project-URL: Documentation, https://tr4nt0r.github.io/habiticalib/
6
- Project-URL: Source, https://github.com/tr4nt0r/habiticalib
7
- Author-email: Manfred Dennerlein Rodelo <manfred@dennerlein.name>
8
- License: MIT License
9
- License-File: LICENSE
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Operating System :: OS Independent
12
- Classifier: Programming Language :: Python :: 3 :: Only
13
- Requires-Python: >=3.12
14
- Requires-Dist: aiohttp~=3.9
15
- Requires-Dist: mashumaro~=3.13
16
- Requires-Dist: orjson~=3.10
17
- Requires-Dist: pillow~=10.4
18
- Description-Content-Type: text/markdown
19
-
20
- # Habiticalib
21
-
22
- <p align="center">
23
- <em>Modern asynchronous Python client library for the Habitica API</em>
24
- </p>
25
-
26
- [![build](https://github.com/tr4nt0r/habiticalib/workflows/Build/badge.svg)](https://github.com/tr4nt0r/habiticalib/actions)
27
- [![codecov](https://codecov.io/gh/tr4nt0r/habiticalib/branch/master/graph/badge.svg)](https://codecov.io/gh/tr4nt0r/habiticalib)
28
- [![PyPI version](https://badge.fury.io/py/habiticalib.svg)](https://badge.fury.io/py/habiticalib)
29
-
30
- ---
31
-
32
- **Documentation**: <a href="https://tr4nt0r.github.io/habiticalib/" target="_blank">https://tr4nt0r.github.io/habiticalib/</a>
33
-
34
- **Source Code**: <a href="https://github.com/tr4nt0r/habiticalib" target="_blank">https://github.com/tr4nt0r/habiticalib</a>
35
-
36
- ---
37
-
38
- ## Development
39
-
40
- ### Setup environment
41
-
42
- We use [Hatch](https://hatch.pypa.io/latest/install/) to manage the development environment and production build. Ensure it's installed on your system.
43
-
44
- ### Run unit tests
45
-
46
- You can run all the tests with:
47
-
48
- ```bash
49
- hatch run test
50
- ```
51
-
52
- ### Format the code
53
-
54
- Execute the following command to apply linting and check typing:
55
-
56
- ```bash
57
- hatch run lint
58
- ```
59
-
60
- ### Publish a new version
61
-
62
- You can bump the version, create a commit and associated tag with one command:
63
-
64
- ```bash
65
- hatch version patch
66
- ```
67
-
68
- ```bash
69
- hatch version minor
70
- ```
71
-
72
- ```bash
73
- hatch version major
74
- ```
75
-
76
- Your default Git text editor will open so you can add information about the release.
77
-
78
- When you push the tag on GitHub, the workflow will automatically publish it on PyPi and a GitHub release will be created as draft.
79
-
80
- ## Serve the documentation
81
-
82
- You can serve the Mkdocs documentation with:
83
-
84
- ```bash
85
- hatch run docs-serve
86
- ```
87
-
88
- It'll automatically watch for changes in your code.
89
-
90
- ## License
91
-
92
- This project is licensed under the terms of the MIT license.
@@ -1,11 +0,0 @@
1
- habiticalib/__init__.py,sha256=veWNJO9Y1tearAF3GXOM3PZgGxqE1Ku3vpMcuFpQWIk,301
2
- habiticalib/const.py,sha256=HeIl1dPAeAxt1V-9PkPCt60ThAJJWkUKpCzMEEAR-ik,584
3
- habiticalib/exceptions.py,sha256=V7QAPQM4HbGxq7-BYDSdG9Zi2u9F2w3tX8XwualJbWM,601
4
- habiticalib/helpers.py,sha256=1PEq8tjOgotMnGRUcRcFcLCEa7jFWUORD9ZPHEVH2sU,3527
5
- habiticalib/lib.py,sha256=FlQUFX1jvbznJLcd1M7xQ7YxAXuU2GAl3R4KMZwefJM,53749
6
- habiticalib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- habiticalib/types.py,sha256=r_5pCRdfZRv7whryAgVOUnqv4qUGfokgq9GqdkdK_y8,32549
8
- habiticalib-0.1.0a0.dist-info/METADATA,sha256=7rJ5r71bY1A5mz50twmXizvs9pX5xpCvivJWqaoXIUs,2471
9
- habiticalib-0.1.0a0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
- habiticalib-0.1.0a0.dist-info/licenses/LICENSE,sha256=oIinIOSJ49l1iVIRI3XGXFWt6SF7a83kEFBAY8ORwNI,1084
11
- habiticalib-0.1.0a0.dist-info/RECORD,,