GuglielmoTor commited on
Commit
9e34c6c
·
verified ·
1 Parent(s): 7a270f0

Create mentions_dashboard.py

Browse files
Files changed (1) hide show
  1. mentions_dashboard.py +121 -0
mentions_dashboard.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # mentions_dashboard.py
2
+
3
+ import json
4
+ import time
5
+ import re
6
+ import os
7
+ from datetime import datetime
8
+
9
+ from urllib.parse import quote
10
+ from requests_oauthlib import OAuth2Session
11
+ from textblob import TextBlob
12
+ import matplotlib.pyplot as plt
13
+
14
+
15
+ def extract_text_from_commentary(commentary):
16
+ return re.sub(r"{.*?}", "", commentary).strip()
17
+
18
+
19
+ def analyze_sentiment(text):
20
+ return TextBlob(text).sentiment.polarity
21
+
22
+
23
+ def generate_mentions_dashboard(comm_client_id, comm_token_dict):
24
+ linkedin = OAuth2Session(comm_client_id, token=comm_token_dict)
25
+
26
+ org_urn = "urn:li:organization:19010008"
27
+ encoded_urn = quote(org_urn, safe='')
28
+
29
+ linkedin.headers.update({
30
+ "LinkedIn-Version": "202502",
31
+ "X-Restli-Protocol-Version": "2.0.0"
32
+ })
33
+
34
+ base_url = (
35
+ "https://api.linkedin.com/rest/organizationalEntityNotifications"
36
+ "?q=criteria"
37
+ "&actions=List(COMMENT,SHARE_MENTION)"
38
+ f"&organizationalEntity={encoded_urn}"
39
+ "&count=50"
40
+ )
41
+
42
+ all_notifications = []
43
+ start = 0
44
+
45
+ while True:
46
+ url = f"{base_url}&start={start}"
47
+ resp = linkedin.get(url)
48
+ if resp.status_code != 200:
49
+ break
50
+
51
+ data = resp.json()
52
+ elements = data.get("elements", [])
53
+ all_notifications.extend(elements)
54
+
55
+ if len(elements) < data.get("paging", {}).get("count", 0):
56
+ break
57
+
58
+ start += len(elements)
59
+ time.sleep(0.5)
60
+
61
+ # Extract mentions and their share URNs
62
+ mention_shares = [e.get("generatedActivity") for e in all_notifications if e.get("action") == "SHARE_MENTION"]
63
+ mention_data = []
64
+
65
+ for share_urn in mention_shares:
66
+ if not share_urn:
67
+ continue
68
+ encoded_share_urn = quote(share_urn, safe='')
69
+ share_url = f"https://api.linkedin.com/rest/posts/{encoded_share_urn}"
70
+ response = linkedin.get(share_url)
71
+
72
+ if response.status_code != 200:
73
+ continue
74
+
75
+ post = response.json()
76
+ commentary_raw = post.get("commentary", "")
77
+ if not commentary_raw:
78
+ continue
79
+
80
+ commentary = extract_text_from_commentary(commentary_raw)
81
+ sentiment = analyze_sentiment(commentary)
82
+ timestamp = post.get("createdAt", 0)
83
+ dt = datetime.fromtimestamp(timestamp / 1000.0)
84
+
85
+ mention_data.append({
86
+ "date": dt,
87
+ "text": commentary,
88
+ "sentiment": sentiment
89
+ })
90
+
91
+ # Save HTML
92
+ html_parts = ["<h2 style='text-align:center;'>📣 Mentions Sentiment Dashboard</h2>"]
93
+ for mention in mention_data:
94
+ html_parts.append(f"""
95
+ <div style='border:1px solid #ccc; border-radius:10px; padding:15px; margin:10px;'>
96
+ <p><strong>Date:</strong> {mention["date"].strftime('%Y-%m-%d')}</p>
97
+ <p>{mention["text"]}</p>
98
+ <p><strong>Sentiment:</strong> {mention["sentiment"]:.2f}</p>
99
+ </div>
100
+ """)
101
+
102
+ html_path = "mentions_dashboard.html"
103
+ with open(html_path, "w", encoding="utf-8") as f:
104
+ f.write("\n".join(html_parts))
105
+
106
+ # Plot
107
+ if mention_data:
108
+ dates = [m["date"] for m in mention_data]
109
+ sentiments = [m["sentiment"] for m in mention_data]
110
+
111
+ plt.figure(figsize=(10, 5))
112
+ plt.plot(dates, sentiments, marker='o', linestyle='-', color='blue')
113
+ plt.title("Sentiment Over Time")
114
+ plt.xlabel("Date")
115
+ plt.ylabel("Sentiment")
116
+ plt.grid(True)
117
+ plt.tight_layout()
118
+ plt.savefig("mentions_sentiment_plot.png")
119
+ plt.close()
120
+
121
+ return html_path