11"""This module contains an implementation of a Matomo API client for python."""
2- from typing import Iterator , List , Union
3- from dlt .common .typing import DictStrAny , DictStrStr , TDataItem , TDataItems
2+ from typing import Iterator , List
3+
4+ from dlt .common .typing import DictStrAny , TDataItem , TDataItems
45from dlt .sources .helpers .requests import client
56
67
@@ -17,34 +18,50 @@ class MatomoAPIClient:
1718 API client used to make requests to Matomo API.
1819 """
1920
20- def __init__ (self , api_token : str , url : str ) -> None :
21+ def __init__ (self , api_token : str , url : str , call_method : str = "GET" ) -> None :
2122 """
2223 Initializes the client.
2324
2425 Args:
2526 api_token (str): Token used to authenticate for Matomo API.
2627 url (str): URL of the Matomo website.
28+ call_method (str): HTTP method for API calls, related to authentication
2729 """
2830
2931 self .base_url = url
3032 self .auth_token = api_token
33+ if call_method .upper () not in ["GET" , "POST" ]:
34+ raise ValueError ("call_method must be either 'GET' or 'POST'" )
35+ self .call_method = call_method
3136
32- def _request (self , params : DictStrAny ) -> TDataItem :
37+ def _request (
38+ self , base_params : DictStrAny , detailed_params : DictStrAny
39+ ) -> TDataItem :
3340 """
3441 Helper method that retrieves data and returns the JSON response from the API.
3542
3643 Args:
37- params (DictStrAny): Parameters for the API request.
44+ base_params (DictStrAny): Parameters for the API request.
45+ detailed_params (DictStrAny): Detailed parameters for the API request.
3846
3947 Returns:
4048 TDataItem: JSON response from the API.
4149 """
4250
4351 # loop through all the pages
4452 # the total number of rows is received after the first request, for the first request to be sent through, initializing the row_count to 1 would suffice
45- headers = { "Content-type" : "application/json" }
53+
4654 url = f"{ self .base_url } /index.php"
47- response = client .get (url = url , headers = headers , params = params )
55+ if self .call_method .upper () == "POST" :
56+ headers = {"Content-type" : "application/x-www-form-urlencoded" }
57+ response = client .post (
58+ url = url , headers = headers , data = detailed_params , params = base_params
59+ )
60+ else :
61+ headers = {"Content-type" : "application/json" }
62+ final_params = base_params .copy ()
63+ final_params .update (detailed_params )
64+ response = client .get (url = url , headers = headers , params = final_params )
4865 response .raise_for_status ()
4966 json_response = response .json ()
5067 # matomo returns error with HTTP 200
@@ -78,20 +95,22 @@ def get_query(
7895 # Set up the API URL and parameters
7996 if not extra_params :
8097 extra_params = {}
81- params = {
98+ base_params = {
8299 "module" : "API" ,
83100 "method" : "API.getBulkRequest" ,
84101 "format" : "json" ,
102+ }
103+ detailed_params = {
85104 "token_auth" : self .auth_token ,
86105 }
87106 for i , method in enumerate (methods ):
88- params [
107+ detailed_params [
89108 f"urls[{ i } ]"
90109 ] = f"method={ method } &idSite={ site_id } &period={ period } &date={ date } "
91110 # Merge the additional parameters into the request parameters
92- params .update (extra_params )
111+ detailed_params .update (extra_params )
93112 # Send the API request
94- return self ._request (params = params )
113+ return self ._request (base_params = base_params , detailed_params = detailed_params )
95114
96115 def get_method (
97116 self ,
@@ -112,32 +131,39 @@ def get_method(
112131 Yields:
113132 Iterator[TDataItems]: JSON data from the response.
114133 """
115-
116- # Set up the API URL and parameters
117134 if not extra_params :
118135 extra_params = {}
136+
119137 filter_offset = 0
120- params = {
138+
139+ base_params = {
121140 "module" : "API" ,
122141 "method" : "API.getBulkRequest" ,
123142 "format" : "json" ,
124- "token_auth" : self .auth_token ,
125- "urls[0]" : f"method={ method } &idSite={ site_id } &filter_limit={ rows_per_page } &filter_offset={ filter_offset } " ,
126143 }
127- # Merge the additional parameters into the request parameters
128- params .update (extra_params )
129- # Send the API request
130- method_data = self ._request (params = params )[0 ]
131- while len (method_data ):
132- yield method_data
133- filter_offset += len (method_data )
134- params [
135- "urls[0]"
136- ] = f"method={ method } &idSite={ site_id } &filter_limit={ rows_per_page } &filter_offset={ filter_offset } "
137- method_data = self ._request (params = params )[0 ]
144+
145+ while True :
146+ detailed_params = {
147+ "urls[0]" : f"method={ method } &idSite={ site_id } &filter_limit={ rows_per_page } &filter_offset={ filter_offset } " ,
148+ "token_auth" : self .auth_token ,
149+ }
150+ detailed_params .update (extra_params )
151+ response_data = self ._request (
152+ base_params = base_params , detailed_params = detailed_params
153+ )
154+ if not response_data or not isinstance (response_data , list ):
155+ break
156+ batch = response_data [0 ] if len (response_data ) > 0 else []
157+ if not batch :
158+ break
159+ yield batch
160+ filter_offset += len (batch )
138161
139162 def get_visitors_batch (
140- self , visitor_list : List [str ], site_id : int , extra_params : DictStrAny = None
163+ self ,
164+ visitor_list : List [str ],
165+ site_id : int ,
166+ extra_params : DictStrAny = None ,
141167 ) -> TDataItems :
142168 """
143169 Gets visitors for Matomo.
@@ -152,19 +178,19 @@ def get_visitors_batch(
152178 """
153179 if not extra_params :
154180 extra_params = {}
155- params = {
181+ base_params = {
156182 "module" : "API" ,
157183 "method" : "API.getBulkRequest" ,
158184 "format" : "json" ,
159185 "site_id" : site_id ,
160- "token_auth" : self .auth_token ,
161186 }
162- params .update (
163- {
164- f"urls[{ i } ]" : f"method=Live.getVisitorProfile&idSite={ site_id } &visitorId={ visitor_list [i ]} "
165- for i in range (len (visitor_list ))
166- }
187+ detailed_params = {
188+ f"urls[{ i } ]" : f"method=Live.getVisitorProfile&idSite={ site_id } &visitorId={ visitor_list [i ]} "
189+ for i in range (len (visitor_list ))
190+ }
191+ detailed_params ["token_auth" ] = self .auth_token
192+ detailed_params .update (extra_params )
193+ method_data = self ._request (
194+ base_params = base_params , detailed_params = detailed_params
167195 )
168- params .update (extra_params )
169- method_data = self ._request (params = params )
170196 return method_data
0 commit comments