spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / plugins / slack-quote-formatter / hooks / format_slack_quotes.py
185 lines · 6.1 KBRaw
1#!/usr/bin/env python3
2"""
3Slack Quote Formatter - UserPromptSubmit Hook
4
5Transforms plain Slack forwarded/quoted messages into visually distinctive
6formatted blocks with Unicode box characters and better layout.
7
8Before:
9 [Forwarded Message]
10 From: John Doe
11 Message: Here is some text...
12
13After:
14 ╔═══════════════════════════════════════════════════════════╗
15 ║ FORWARDED MESSAGE ║
16 ╠═══════════════════════════════════════════════════════════╣
17 ║ From: John Doe ║
18 ╟───────────────────────────────────────────────────────────╢
19 ║ Here is some text... ║
20 ╚═══════════════════════════════════════════════════════════╝
21"""
22
23import json
24import re
25import sys
26
27
28def format_forwarded_message(from_line: str, message_content: str) -> str:
29 """Format a single forwarded message with visual box styling."""
30
31 # Box drawing characters
32 TOP_LEFT = "╔"
33 TOP_RIGHT = "╗"
34 BOTTOM_LEFT = "╚"
35 BOTTOM_RIGHT = "╝"
36 HORIZONTAL = "═"
37 VERTICAL = "║"
38 LEFT_T = "╠"
39 RIGHT_T = "╣"
40 LEFT_LIGHT = "╟"
41 RIGHT_LIGHT = "╢"
42 LIGHT_HORIZONTAL = "─"
43
44 # Configuration
45 BOX_WIDTH = 70
46 INNER_WIDTH = BOX_WIDTH - 4 # Account for "║ " and " ║"
47
48 def pad_line(text: str, width: int = INNER_WIDTH) -> str:
49 """Pad a line to fill the box width."""
50 if len(text) > width:
51 return text[:width]
52 return text + " " * (width - len(text))
53
54 def wrap_text(text: str, width: int) -> list:
55 """Wrap text to fit within the specified width."""
56 words = text.split()
57 lines = []
58 current_line = []
59 current_length = 0
60
61 for word in words:
62 word_len = len(word)
63 if current_length + word_len + (1 if current_line else 0) <= width:
64 current_line.append(word)
65 current_length += word_len + (1 if len(current_line) > 1 else 0)
66 else:
67 if current_line:
68 lines.append(" ".join(current_line))
69 current_line = [word]
70 current_length = word_len
71
72 if current_line:
73 lines.append(" ".join(current_line))
74
75 return lines if lines else [""]
76
77 lines = []
78
79 # Top border with header
80 lines.append(f"{TOP_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{TOP_RIGHT}")
81
82 # Header line
83 header = "FORWARDED MESSAGE"
84 lines.append(f"{VERTICAL} {pad_line(header)}{VERTICAL}")
85
86 # Separator after header
87 lines.append(f"{LEFT_T}{HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_T}")
88
89 # From line
90 from_display = from_line.strip()
91 lines.append(f"{VERTICAL} {pad_line(from_display)}{VERTICAL}")
92
93 # Light separator before message
94 lines.append(f"{LEFT_LIGHT}{LIGHT_HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_LIGHT}")
95
96 # Message content (indented and wrapped)
97 message_lines = message_content.strip().split("\n")
98 for msg_line in message_lines:
99 # Handle each line, wrapping if necessary
100 wrapped = wrap_text(msg_line, INNER_WIDTH - 2) # Extra indent
101 for wrapped_line in wrapped:
102 indented = " " + wrapped_line # Add indent for quote appearance
103 lines.append(f"{VERTICAL} {pad_line(indented)}{VERTICAL}")
104
105 # Bottom border
106 lines.append(f"{BOTTOM_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{BOTTOM_RIGHT}")
107
108 return "\n".join(lines)
109
110
111def transform_slack_context(text: str) -> str:
112 """
113 Find and transform [Forwarded Message] blocks in the text.
114
115 Matches patterns like:
116 [Forwarded Message]
117 From: Name Here
118 Message: Content here that may span
119 multiple lines until we hit the next section
120 """
121
122 # Pattern to match forwarded message blocks
123 # This handles the common format from Slack context
124 pattern = r'\[Forwarded Message\]\s*\n\s*From:\s*([^\n]+)\s*\nMessage:\s*(.+?)(?=\n\s*\[|\n\[pnkfelix\]|\n<|\Z)'
125
126 def replace_match(match):
127 from_name = match.group(1).strip()
128 message = match.group(2).strip()
129
130 formatted = format_forwarded_message(f"From: {from_name}", message)
131 return f"\n{formatted}\n"
132
133 # Apply transformation
134 result = re.sub(pattern, replace_match, text, flags=re.DOTALL)
135
136 return result
137
138
139def main():
140 """Main entry point for the UserPromptSubmit hook."""
141 try:
142 # Read input from stdin
143 input_data = json.load(sys.stdin)
144
145 # Get the user prompt if available
146 user_prompt = input_data.get("user_prompt", "")
147
148 if not user_prompt:
149 # No prompt to transform, just pass through
150 print(json.dumps({}))
151 sys.exit(0)
152
153 # Check if there are forwarded messages to format
154 if "[Forwarded Message]" not in user_prompt:
155 # Nothing to transform
156 print(json.dumps({}))
157 sys.exit(0)
158
159 # Transform the prompt
160 transformed_prompt = transform_slack_context(user_prompt)
161
162 # If we made changes, return the transformed prompt
163 if transformed_prompt != user_prompt:
164 result = {
165 "transformedPrompt": transformed_prompt
166 }
167 print(json.dumps(result))
168 else:
169 print(json.dumps({}))
170
171 except json.JSONDecodeError:
172 # No valid JSON input, pass through
173 print(json.dumps({}))
174 except Exception as e:
175 # Log error but don't block
176 error_output = {
177 "systemMessage": f"[slack-quote-formatter] Warning: {str(e)}"
178 }
179 print(json.dumps(error_output))
180
181 sys.exit(0)
182
183
184if __name__ == "__main__":
185 main()