-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathscript.py
More file actions
156 lines (127 loc) · 5.65 KB
/
script.py
File metadata and controls
156 lines (127 loc) · 5.65 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
from omniscope.api import OmniscopeApi
import json, pandas as pd, requests, os
import re, time
from urllib.parse import quote
def slack_api_get(url, params, auth_token):
headers = {"Authorization": f"Bearer {auth_token}"}
r = requests.get(url, params=params, headers=headers)
if not r.ok:
raise Exception(f"Slack HTTP error {r.status_code}: {r.text}")
data = r.json()
if not data.get("ok", False):
raise Exception(f"Slack API error {data.get('error')}: {data}")
return data
def slackify_links(text):
if not text:
return text
url_pattern = r'(https?://[^\s]+(?: [^\s]+)*)'
def repl(match):
raw_url = match.group(0)
encoded = quote(raw_url, safe=':/?=&%#.')
return f"<{encoded}|{raw_url}>"
return re.sub(url_pattern, repl, text)
omniscope_api = OmniscopeApi()
postMessageUrl = "https://slack.com/api/chat.postMessage"
def slack_post_json(url, payload, auth_token):
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json; charset=utf-8",
}
r = requests.post(url, data=json.dumps(payload), headers=headers)
if not r.ok:
raise Exception(f"Slack HTTP error {r.status_code}: {r.text}")
data = r.json()
if not data.get("ok", False):
raise Exception(f"Slack API error {data.get('error')}: {data}")
return data
def slack_upload_file_with_comment(channel_id, initial_comment, file_path, auth_token, display_name):
"""
Uploads a file and posts it into a channel with initial_comment.
This results in ONE channel post that contains the attachment + message.
Slack Web API flow:
1) files.getUploadURLExternal
2) POST bytes to upload_url
3) files.completeUploadExternal (share to channel + initial_comment)
"""
file_path = (str(file_path) if file_path is not None else "").strip()
if not file_path:
raise Exception("Attachment file path is empty.")
if not os.path.isfile(file_path):
raise Exception(f"Attachment file not found: {file_path}")
filename = os.path.basename(file_path)
title = display_name if display_name else filename
length = os.path.getsize(file_path)
headers_auth = {"Authorization": f"Bearer {auth_token}"}
# 1) Get upload URL + file_id
r1 = requests.post(
"https://slack.com/api/files.getUploadURLExternal",
headers=headers_auth,
files={
"filename": (None, filename),
"length": (None, str(length)),
},
)
if not r1.ok:
raise Exception(f"Slack HTTP error {r1.status_code}: {r1.text}")
data1 = r1.json()
if not data1.get("ok", False):
raise Exception(f"Slack API error {data1.get('error')}: {data1}")
upload_url = data1["upload_url"]
file_id = data1["file_id"]
# 2) Upload raw bytes
with open(file_path, "rb") as f:
r2 = requests.post(upload_url, headers={"Content-Type": "application/octet-stream"}, data=f)
if not r2.ok:
raise Exception(f"Upload bytes failed {r2.status_code}: {r2.text}")
# 3) Complete + share to channel with initial_comment
files_payload = json.dumps([{"id": file_id, "title": title}])
r3 = requests.post(
"https://slack.com/api/files.completeUploadExternal",
headers=headers_auth,
files={
"files": (None, files_payload),
"channel_id": (None, channel_id),
"initial_comment": (None, initial_comment or ""),
},
)
if not r3.ok:
raise Exception(f"Slack HTTP error {r3.status_code}: {r3.text}")
data3 = r3.json()
if not data3.get("ok", False):
raise Exception(f"Slack API error {data3.get('error')}: {data3}")
return data3
messagesToSend = []
responses = []
input_data = omniscope_api.read_input_records(input_number=0)
input_data.fillna("", inplace=True)
# These options should be column names OR literal values (same for all rows)
message_opt = omniscope_api.get_option("message")
attach_opt = omniscope_api.get_option("attachmentPath")
attach_name_opt = omniscope_api.get_option("attachmentName")
channel_id = omniscope_api.get_option("channelID")
authToken = omniscope_api.get_option("authToken")
for idx, row in input_data.iterrows():
# resolve message (column or literal)
msg_val = row[message_opt] if message_opt in input_data.columns else message_opt
message = (str(msg_val) if msg_val is not None else "").strip()
message = slackify_links(message)
# resolve file path (column or literal)
attach_val = row[attach_opt] if attach_opt in input_data.columns else attach_opt
attach_path = (str(attach_val) if attach_val is not None else "").strip()
name_val = row[attach_name_opt] if attach_name_opt in input_data.columns else attach_name_opt
attach_display_name = (str(name_val) if name_val is not None else "").strip()
messagesToSend.append({"Row": idx, "Message": message, "AttachmentPath": attach_path})
if not message and not attach_path:
responses.append({"Row": idx, "Action": "skip"})
continue
if attach_path:
resp = slack_upload_file_with_comment(channel_id, message, attach_path, authToken, attach_display_name)
responses.append({"Row": idx, "Action": "upload_with_comment", "Response": resp})
else:
resp = slack_post_json(postMessageUrl, {"channel": channel_id, "text": message}, authToken)
responses.append({"Row": idx, "Action": "postMessage", "Response": resp})
output_data = pd.DataFrame(messagesToSend)
output_data_2 = pd.DataFrame(responses)
omniscope_api.write_output_records(output_data, output_number=0)
omniscope_api.write_output_records(output_data_2, output_number=1)
omniscope_api.close()