44import logging
55from copy import deepcopy
66from datetime import datetime , timedelta
7+ from hashlib import md5
78from typing import Any , Dict , List , Optional
89
910import aiohttp
@@ -49,6 +50,17 @@ def __init__(
4950 self ._about : FireflyiiiAbout = FireflyiiiAbout ()
5051 self ._preferences : FireflyiiiPreferences = FireflyiiiPreferences ()
5152 self ._timerange : Optional [DateTimeRange ] = timerange
53+ self ._default_currency : Optional [FireflyiiiCurrency ] = None
54+ self .clear_cache ()
55+
56+ def clear_cache (self ):
57+ """Clears cache"""
58+ self ._api_cache = {}
59+
60+ def _set_max_limit (self , params : dict ):
61+ """Sets max limits to avoid paging"""
62+ if "limit" not in params :
63+ params ["limit" ] = 9999999999
5264
5365 @property
5466 async def version (self ) -> str :
@@ -83,6 +95,10 @@ def host_api(self) -> str:
8395 @property
8496 async def default_currency (self ) -> FireflyiiiCurrency :
8597 """Get FireflyIII Default Currency"""
98+
99+ if self ._default_currency :
100+ return self ._default_currency
101+
86102 default_currency = await self ._request_api ("GET" , "/currencies/default" )
87103 if not "data" in default_currency :
88104 _LOGGER .error (
@@ -110,7 +126,7 @@ async def default_currency(self) -> FireflyiiiCurrency:
110126 enabled = attributes .get ("enabled" , True ),
111127 decimal_places = attributes .get ("decimal_places" , 2 ),
112128 )
113-
129+ self . _default_currency = default_currency
114130 return default_currency
115131
116132 @property
@@ -216,7 +232,10 @@ async def accounts(
216232
217233 account_list = FireflyiiiObjectBaseList (type = FireflyiiiObjectType .ACCOUNTS )
218234
219- accounts = await self ._request_api ("GET" , "/accounts" )
235+ params : dict = {}
236+ self ._set_max_limit (params )
237+
238+ accounts = await self ._request_api ("GET" , "/accounts" , params )
220239 if not "data" in accounts :
221240 _LOGGER .error (
222241 "Invalid response from server on accounts, "
@@ -353,7 +372,10 @@ async def categories(self, ids=None, currency=None) -> FireflyiiiObjectBaseList:
353372 """Get FireflyIII categories"""
354373 _LOGGER .debug ("Updating FireflyIII categories" )
355374
356- categories = await self ._request_api ("GET" , "/categories" )
375+ params : dict = {}
376+ self ._set_max_limit (params )
377+
378+ categories = await self ._request_api ("GET" , "/categories" , params )
357379 if not "data" in categories :
358380 _LOGGER .error (
359381 "Invalid response from server on categories, "
@@ -498,7 +520,10 @@ async def piggy_banks(self, ids=None) -> FireflyiiiObjectBaseList:
498520 type = FireflyiiiObjectType .PIGGY_BANKS
499521 )
500522
501- piggy_banks = await self ._request_api ("GET" , "/piggy-banks" )
523+ params : dict = {}
524+ self ._set_max_limit (params )
525+
526+ piggy_banks = await self ._request_api ("GET" , "/piggy-banks" , params )
502527 if not "data" in piggy_banks :
503528 _LOGGER .error (
504529 "Invalid response from server on piggy banks, "
@@ -555,18 +580,19 @@ async def budgets(self, ids=None, currency=None) -> FireflyiiiObjectBaseList:
555580
556581 budgets_list = FireflyiiiObjectBaseList (type = FireflyiiiObjectType .BUDGETS )
557582
558- date_range = {}
583+ params = {}
559584 if (
560585 self ._timerange
561586 and self ._timerange .start_datetime
562587 and self ._timerange .end_datetime
563588 ):
564- date_range = {
589+ params = {
565590 "start" : self ._timerange .start_datetime .strftime ("%Y-%m-%d" ),
566591 "end" : self ._timerange .end_datetime .strftime ("%Y-%m-%d" ),
567592 }
568593
569- budgets = await self ._request_api ("GET" , "/budgets" , date_range )
594+ self ._set_max_limit (params )
595+ budgets = await self ._request_api ("GET" , "/budgets" , params )
570596 if not "data" in budgets :
571597 _LOGGER .error (
572598 "Invalid response from server on budgets, "
@@ -588,7 +614,7 @@ async def budgets(self, ids=None, currency=None) -> FireflyiiiObjectBaseList:
588614 continue
589615
590616 budget_limits = await self ._request_api (
591- "GET" , f"/budgets/{ budget_id } /limits" , date_range
617+ "GET" , f"/budgets/{ budget_id } /limits" , params
592618 )
593619 if not "data" in budget_limits or len (budget_limits ["data" ]) < 1 :
594620 budget_limits = None
@@ -656,20 +682,22 @@ async def bills(
656682 )
657683 get_timerange .set_end_datetime (end_date )
658684
659- date_range = {}
685+ params = {}
660686 if (
661687 get_timerange
662688 and get_timerange .start_datetime
663689 and get_timerange .end_datetime
664690 ):
665- date_range = {
691+ params = {
666692 "start" : get_timerange .start_datetime .strftime ("%Y-%m-%d" ),
667693 "end" : get_timerange .end_datetime .strftime ("%Y-%m-%d" ),
668694 }
669695
670696 bill_list = FireflyiiiObjectBaseList (type = FireflyiiiObjectType .BILLS )
671697
672- bills = await self ._request_api ("GET" , "/bills" , date_range )
698+ self ._set_max_limit (params )
699+
700+ bills = await self ._request_api ("GET" , "/bills" , params )
673701 if not "data" in bills :
674702 _LOGGER .error (
675703 "Invalid response from server on bills, "
@@ -897,6 +925,16 @@ def _set_headers(self, header=None):
897925 header ["Content-Type" ] = "application/json"
898926 header ["Accept" ] = "application/json"
899927
928+ def _request_hash (self , path : str , params : Optional [dict ] = None ):
929+ hash_key = md5 (
930+ (
931+ md5 (path .encode ("utf-8" )).hexdigest ()
932+ + md5 (json .dumps (params ).encode ("utf-8" )).hexdigest ()
933+ ).encode ("utf-8" )
934+ ).hexdigest ()
935+
936+ return hash_key
937+
900938 async def _request_api (
901939 self ,
902940 method = "GET" ,
@@ -906,6 +944,15 @@ async def _request_api(
906944 timeout = 10 ,
907945 ):
908946 """Request FireflyIII API"""
947+ hash_key = None
948+
949+ if method .upper () == "GET" :
950+ hash_key = self ._request_hash (path , params )
951+ if hash_key in self ._api_cache :
952+ _LOGGER .debug ("FireflyIII api response from cache for '%s' ok" , path )
953+ return self ._api_cache [hash_key ]
954+
955+ _LOGGER .debug ("Requesting FireflyIII api '%s'" , path )
909956
910957 url = f"{ self .host_api } { path } "
911958
@@ -918,8 +965,6 @@ async def _request_api(
918965
919966 message = None
920967
921- _LOGGER .debug ("Requesting FireflyIII api '%s'" , path )
922-
923968 async with aiohttp .ClientSession () as session :
924969 http_method = getattr (session , method )
925970
@@ -958,6 +1003,9 @@ async def _request_api(
9581003 await session .close ()
9591004
9601005 _LOGGER .debug ("FireflyIII api response for '%s' ok" , path )
1006+ if hash_key :
1007+ self ._api_cache [hash_key ] = message
1008+
9611009 return message
9621010 except (TimeoutError , ServerTimeoutError ):
9631011 _LOGGER .error ("Error in server api call, timeout" )
0 commit comments