-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathslack_agent.py
More file actions
200 lines (170 loc) · 7.79 KB
/
Copy pathslack_agent.py
File metadata and controls
200 lines (170 loc) · 7.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
import os
import re
import json
import time
import requests
from datetime import datetime
from google import genai
class SlackReporterAgent:
GITHUB_REPORT_BASE_URL = "https://github.com/Parimal195/MAS/blob/main/reports"
def __init__(self, webhook_url, gemini_api_key):
self.webhook_url = webhook_url
self.genai_client = genai.Client(api_key=gemini_api_key)
self.reports_dir = "reports"
self.state_file = os.path.join(self.reports_dir, "slack_state.json")
# ------------------------------------------------------------------ state
def _load_state(self):
if os.path.exists(self.state_file):
try:
with open(self.state_file, "r") as f:
return json.load(f)
except Exception as e:
print(f"[SlackReporter] Error loading state: {e}")
return {"sent_reports": []}
def _save_state(self, state):
os.makedirs(self.reports_dir, exist_ok=True)
try:
with open(self.state_file, "w") as f:
json.dump(state, f, indent=2)
except Exception as e:
print(f"[SlackReporter] Error saving state: {e}")
# --------------------------------------------------------- report helpers
def _get_today_report_filename(self):
"""Construct the report filename for today in dd-mm-yy format."""
return datetime.now().strftime("report-%d-%m-%y.pdf")
def _report_exists(self, filename):
"""Check if the report file exists locally."""
path = os.path.join(self.reports_dir, filename)
return os.path.isfile(path)
def _get_github_url(self, filename):
"""Build the GitHub URL for a given report filename."""
return f"{self.GITHUB_REPORT_BASE_URL}/{filename}"
# -------------------------------------------------------- Gemini summary
def _summarize_pdf(self, pdf_path):
print(f"[SlackReporter] Extracting summary from {pdf_path}...")
try:
import pypdf
reader = pypdf.PdfReader(pdf_path)
text = ""
for page in reader.pages:
extracted = page.extract_text()
if extracted:
text += extracted + "\n"
# Look for the Trend summary or general summary section
# The prompt asks for: "Trend summary (macro shifts)"
import re
# Attempt to find the Trend Summary or Summary heading and capture the following text
# until the next major heading (which typically starts with a capital letter and has a colon or is a number)
# We use a non-greedy match until the end of the string or another possible heading
match = re.search(r'(?i)(?:Trend Summary|Macro Shifts).*?\n(.*?)(?=\n[A-Z0-9].*?:|\n#|\Z)', text, re.DOTALL)
if match and match.group(1).strip():
summary_text = match.group(1).strip()
# Clean up lines
lines = [line.strip() for line in summary_text.split('\n') if line.strip()]
extracted_summary = " ".join(lines)
if len(extracted_summary) > 500:
extracted_summary = extracted_summary[:497] + "..."
return extracted_summary
# If no specific Trend Summary is found, just grab the first few meaningful lines after the title
lines = [line.strip() for line in text.split('\n') if line.strip()]
# Skip the first line assuming it's the title/date
if len(lines) > 1:
extracted_summary = " ".join(lines[1:6])
else:
extracted_summary = " ".join(lines)
if len(extracted_summary) > 500:
extracted_summary = extracted_summary[:497] + "..."
return extracted_summary
except Exception as e:
print(f"[SlackReporter] Error reading PDF: {e}")
return "Summary unavailable due to an error reading the PDF."
# ---------------------------------------------------- Slack webhook send
def _send_to_slack(self, filename, github_url, summary):
"""Send a rich message to Slack via Incoming Webhook."""
print(f"[SlackReporter] Sending {filename} to Slack via webhook...")
try:
title = filename.replace(".pdf", "").replace("-", " ").title()
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
payload = {
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": f"📄 {title}",
"emoji": True
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*Generated at:* {timestamp}"
}
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*Summary:*\n{summary}"
}
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"📎 *<{github_url}|View Full Report on GitHub>*"
}
}
]
}
response = requests.post(
self.webhook_url,
json=payload,
headers={"Content-Type": "application/json"},
timeout=10
)
if response.status_code == 200 and response.text == "ok":
return True
else:
print(f"[SlackReporter] Webhook returned: {response.status_code} – {response.text}")
return False
except requests.exceptions.RequestException as e:
print(f"[SlackReporter] Network error sending to Slack: {e}")
return False
except Exception as e:
print(f"[SlackReporter] Unexpected error sending to Slack: {e}")
return False
# ------------------------------------------------------------------- run
def run(self):
print("[SlackReporter] Starting agent run...")
filename = self._get_today_report_filename()
print(f"[SlackReporter] Looking for today's report: {filename}")
if not self._report_exists(filename):
print(f"[SlackReporter] Today's report ({filename}) does not exist yet. Nothing to send.")
return
# Check if already sent
state = self._load_state()
sent_reports = set(state.get("sent_reports", []))
if filename in sent_reports:
print(f"[SlackReporter] Today's report ({filename}) was already sent. Skipping.")
return
# Summarize and send
pdf_path = os.path.join(self.reports_dir, filename)
summary = self._summarize_pdf(pdf_path)
github_url = self._get_github_url(filename)
success = self._send_to_slack(filename, github_url, summary)
if success:
print(f"[SlackReporter] Successfully sent {filename}")
sent_reports.add(filename)
state["sent_reports"] = list(sent_reports)
self._save_state(state)
else:
print(f"[SlackReporter] Failed to send {filename}. Will retry next time.")
print("[SlackReporter] Run completed.")