Spaces:
Running
Running
Update linkedin_follower_stats.py
Browse files- linkedin_follower_stats.py +32 -12
linkedin_follower_stats.py
CHANGED
@@ -224,12 +224,17 @@ def _parse_urn_to_id(urn_string):
|
|
224 |
|
225 |
# --- Follower Data Fetching Functions ---
|
226 |
|
227 |
-
def fetch_monthly_follower_gains(
|
|
|
|
|
|
|
228 |
now_utc = datetime.now(timezone.utc)
|
|
|
229 |
start_of_reporting_period = (now_utc - timedelta(days=365)).replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
230 |
start_ms = int(start_of_reporting_period.timestamp() * 1000)
|
231 |
|
232 |
base_url = f"{api_rest_base_url}/organizationalEntityFollowerStatistics"
|
|
|
233 |
time_intervals_value = f"(timeRange:(start:{start_ms}),timeGranularityType:MONTH)"
|
234 |
|
235 |
api_params = {
|
@@ -238,30 +243,45 @@ def fetch_monthly_follower_gains(session, org_urn, api_rest_base_url):
|
|
238 |
"timeIntervals": time_intervals_value
|
239 |
}
|
240 |
|
241 |
-
logging.info(f"Preparing to fetch monthly follower gains for {org_urn}.")
|
242 |
logging.debug(f"API Parameters for monthly gains: {json.dumps(api_params)}")
|
|
|
|
|
|
|
243 |
|
244 |
results = []
|
245 |
request_url_for_logging = "Not constructed"
|
246 |
response_obj = None
|
247 |
|
248 |
try:
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
254 |
else:
|
255 |
-
logging.warning("
|
|
|
256 |
|
257 |
req = requests.Request('GET', base_url, params=api_params)
|
258 |
-
prepared_req =
|
259 |
request_url_for_logging = prepared_req.url
|
260 |
|
261 |
logging.info(f"Requesting monthly follower gains from URL: {request_url_for_logging}")
|
262 |
-
logging
|
|
|
|
|
263 |
|
264 |
-
|
|
|
265 |
response_obj.raise_for_status()
|
266 |
data = response_obj.json()
|
267 |
|
@@ -513,7 +533,7 @@ def get_linkedin_follower_stats(comm_client_id, community_token, org_urn):
|
|
513 |
|
514 |
all_follower_data = []
|
515 |
|
516 |
-
monthly_gains = fetch_monthly_follower_gains(
|
517 |
all_follower_data.extend(monthly_gains)
|
518 |
|
519 |
demographics = fetch_follower_demographics(session, org_urn, functions_map, seniorities_map) # Pass session
|
|
|
224 |
|
225 |
# --- Follower Data Fetching Functions ---
|
226 |
|
227 |
+
def fetch_monthly_follower_gains(comm_client_id, token_dict, org_urn, api_rest_base_url):
|
228 |
+
"""
|
229 |
+
Fetches monthly follower gains using a dedicated OAuth2Session for REST API calls.
|
230 |
+
"""
|
231 |
now_utc = datetime.now(timezone.utc)
|
232 |
+
# Calculate start of the month, approximately 12 months ago
|
233 |
start_of_reporting_period = (now_utc - timedelta(days=365)).replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
234 |
start_ms = int(start_of_reporting_period.timestamp() * 1000)
|
235 |
|
236 |
base_url = f"{api_rest_base_url}/organizationalEntityFollowerStatistics"
|
237 |
+
# Using the same timeIntervals format as in the original failing log, as it's standard for REST
|
238 |
time_intervals_value = f"(timeRange:(start:{start_ms}),timeGranularityType:MONTH)"
|
239 |
|
240 |
api_params = {
|
|
|
243 |
"timeIntervals": time_intervals_value
|
244 |
}
|
245 |
|
246 |
+
logging.info(f"Preparing to fetch monthly follower gains for {org_urn} using a dedicated session.")
|
247 |
logging.debug(f"API Parameters for monthly gains: {json.dumps(api_params)}")
|
248 |
+
logging.debug(f"Received client_id for dedicated session: {comm_client_id}")
|
249 |
+
logging.debug(f"Received token_dict for dedicated session (access_token type): {type(token_dict.get('access_token')) if token_dict else 'N/A'}")
|
250 |
+
|
251 |
|
252 |
results = []
|
253 |
request_url_for_logging = "Not constructed"
|
254 |
response_obj = None
|
255 |
|
256 |
try:
|
257 |
+
# Create a new session specifically for this REST API call
|
258 |
+
# This session will not have X-Restli-Protocol-Version header by default from OAuth2Session
|
259 |
+
# It will also not inherit any potentially problematic headers from a shared session.
|
260 |
+
rest_session = OAuth2Session(client_id=comm_client_id, token=token_dict)
|
261 |
+
rest_session.headers.update({
|
262 |
+
"LinkedIn-Version": LINKEDIN_API_VERSION,
|
263 |
+
"Accept-Language": "en_US"
|
264 |
+
# DO NOT ADD "X-Restli-Protocol-Version": "2.0.0" here for /rest/ endpoints
|
265 |
+
})
|
266 |
+
logging.info(f"Dedicated REST session created for monthly gains (id: {id(rest_session)}).")
|
267 |
+
logging.debug(f"Dedicated REST session token (type): {type(rest_session.token)}, Authorized: {rest_session.authorized}")
|
268 |
+
if rest_session.token and 'access_token' in rest_session.token:
|
269 |
+
logging.debug(f"Dedicated REST session access token (partial): {str(rest_session.token['access_token'])[:20]}...")
|
270 |
else:
|
271 |
+
logging.warning("Dedicated REST session: token is None or 'access_token' key is missing.")
|
272 |
+
|
273 |
|
274 |
req = requests.Request('GET', base_url, params=api_params)
|
275 |
+
prepared_req = rest_session.prepare_request(req) # Use the dedicated session
|
276 |
request_url_for_logging = prepared_req.url
|
277 |
|
278 |
logging.info(f"Requesting monthly follower gains from URL: {request_url_for_logging}")
|
279 |
+
# Log only essential headers, avoid logging full token if present in headers directly
|
280 |
+
headers_to_log = {k: v for k, v in prepared_req.headers.items() if k.lower() != 'authorization'}
|
281 |
+
logging.debug(f"Request Headers for monthly gains (excluding Authorization): {json.dumps(headers_to_log, indent=2)}")
|
282 |
|
283 |
+
|
284 |
+
response_obj = rest_session.send(prepared_req, timeout=30) # Use the dedicated session
|
285 |
response_obj.raise_for_status()
|
286 |
data = response_obj.json()
|
287 |
|
|
|
533 |
|
534 |
all_follower_data = []
|
535 |
|
536 |
+
monthly_gains = fetch_monthly_follower_gains(comm_client_id, token_dict, org_urn, API_REST_BASE)
|
537 |
all_follower_data.extend(monthly_gains)
|
538 |
|
539 |
demographics = fetch_follower_demographics(session, org_urn, functions_map, seniorities_map) # Pass session
|