| name | document-metadata-extraction |
| description | Extract author, reviewer, and feedback information from structured documents and their associated discussions. |
Document Metadata Extraction
Overview
This skill covers extracting metadata (author, date, type, reviewers, feedback) from documents and correlating them with discussion threads and review feedback.
Document Structure Analysis
Identifying Document Metadata
def analyze_document_structure(doc):
"""Extract all metadata from a document"""
metadata = {
'type': doc.get('type'),
'id': doc.get('id'),
'author': doc.get('author'),
'date': doc.get('date'),
'feedback': doc.get('feedback'),
'document_link': doc.get('document_link'),
'content_preview': doc.get('content', '')[:200],
}
return metadata
Understanding Document Feedback Format
def extract_feedback_insights(feedback):
"""Parse feedback string for reviewer comments"""
if isinstance(feedback, str):
lines = feedback.split('\n')
suggestions = [line.strip('- ').strip() for line in lines if line.strip()]
return suggestions
elif isinstance(feedback, dict):
return feedback.get('comments', [])
elif isinstance(feedback, list):
return feedback
return []
Identifying Reviewers
Strategy 1: Slack Document Share Discussions
def find_reviewers_in_slack(slack_msgs, doc_id, doc_type):
"""Find who reviewed/commented on a document in Slack"""
reviewers = set()
for msg in slack_msgs:
msg_text = msg.get('Message', {}).get('User', {}).get('text', '')
msg_user = msg.get('Message', {}).get('User', {}).get('userId', '')
if doc_id in msg_text or doc_type.lower() in msg_text.lower():
if 'shared' in msg_text.lower() or 'shared the' in msg_text.lower():
author = msg_user
for reply in msg.get('ThreadReplies', []):
reply_user = reply.get('userId', '')
if reply_user and reply_user != 'slack_admin_bot' and reply_user != author:
reviewers.add(reply_user)
return list(reviewers)
Strategy 2: Updated Document Notifications
def extract_reviewers_from_updates(slack_msgs, doc_id):
"""When document is updated with "thank you everyone", find recent participants"""
reviewers = set()
thank_you_msgs = []
for i, msg in enumerate(slack_msgs):
msg_text = msg.get('Message', {}).get('User', {}).get('text', '')
if 'thank you everyone' in msg_text.lower() and doc_id in msg_text:
thank_you_msgs.append(i)
for thank_you_idx in thank_you_msgs:
for j in range(thank_you_idx - 1, max(0, thank_you_idx - 50), -1):
msg = slack_msgs[j]
msg_text = msg.get('Message', {}).get('User', {}).get('text', '')
msg_user = msg.get('Message', {}).get('User', {}).get('userId', '')
if doc_id in msg_text and 'shared' in msg_text.lower():
reply msg.get(, []):
reply_user = reply.get(, )
reply_user reply_user != :
reviewers.add(reply_user)
(reviewers)
Strategy 3: Meeting Participation
def find_reviewers_in_meetings(meetings, document_type):
"""Find reviewers from meeting attendance on document-related meetings"""
reviewers = set()
for meeting in meetings:
meeting_id = meeting.get('id', '').lower()
if 'contentforce' in meeting_id and 'product_dev' in meeting_id:
participants = meeting.get('participants', [])
reviewers.update(participants)
return list(reviewers)
Document Type Handling
Distinguishing Document Versions
def identify_document_versions(docs):
"""Find original and updated versions of documents"""
documents = {}
for doc in docs:
doc_id = doc.get('id', '')
if 'final_' in doc_id:
base_id = doc_id.replace('final_', '')
if base_id not in documents:
documents[base_id] = {}
documents[base_id]['final'] = doc
else:
if doc_id not in documents:
documents[doc_id] = {}
documents[doc_id]['original'] = doc
return documents
Correlating Versions
def correlate_document_versions(docs, slack_msgs):
"""Find both original and updated versions, track reviewers"""
result = {}
versioned = identify_document_versions(docs)
for base_id, versions in versioned.items():
if 'original' in versions:
author = versions['original'].get('author')
reviewers = find_reviewers_in_slack(slack_msgs, base_id, '')
result[base_id] = {
'author': author,
'original_version': versions.get('original'),
'final_version': versions.get('final'),
'reviewers': reviewers
}
return result
Practical Workflow
def analyze_documents_completely(docs, slack_data, meetings):
"""Complete analysis pipeline"""
results = {}
for doc in docs:
doc_id = doc.get('id')
if 'final_' not in doc_id:
results[doc_id] = {
'metadata': analyze_document_structure(doc),
'author': doc.get('author'),
}
for doc_id, data in results.items():
slack_reviewers = find_reviewers_in_slack(slack_data, doc_id, data['metadata']['type'])
meeting_reviewers = find_reviewers_in_meetings(meetings, data['metadata']['type'])
all_reviewers = list(set(slack_reviewers + meeting_reviewers))
author = data['author']
data['reviewers'] = [r for r in all_reviewers if r != author]
return results
Tips
- Document IDs are key - Use them to correlate across Slack and other sources
- Multiple versions - Always check for both original and "final_" versions
- Feedback is metadata - The feedback field often contains reviewer suggestions
- Slack share dates - Look for the specific share message to find review threads
- Meeting attendance - Cross-check with meeting participants for validation
- Remove duplicates - Use sets to deduplicate across different discovery methods