25th Grade HUST Automation QiMing Class Shared Code Repository A collaborative space for us to share and learn programming together. This repository collects code examples, projects, and resources in Python. Feel free to contribute, explore, and discuss ideas to enhance our collective programming skills!
git clone https://github.com/Hermes-B/HUST_25_auto_qiming_python.gitHUST_25_auto_qiming_python is a collaborative code repository designed for students in the 25th Grade HUST Automation QiMing Class. It serves as a centralized space to share Python code examples, projects, and programming resources. The repository enables students to explore different programming approaches, contribute their own work, and discuss ideas to strengthen their collective coding abilities. This shared learning environment supports hands-on Python development for automation engineering students.
[{"step":"Set up API credentials","action":"1. Generate Sortd API key from your Sortd account settings (https://app.sortd.com/settings/api). 2. Obtain your CRM API key (e.g., HubSpot, Salesforce) and note your board/list IDs from Sortd. 3. Replace placeholder values in the script with your actual credentials.","tip":"Use environment variables for sensitive data like API keys. Example: `export SORTD_API_KEY='your_key_here'`"},{"step":"Customize the automation logic","action":"Modify the `parse_email_details()` method to match your team's email subject formats and custom fields. Update the `create_crm_deal()` payload to include your specific CRM properties (e.g., deal stages, owner assignments).","tip":"Test with 2-3 sample emails first. Print intermediate results to verify parsing accuracy before full deployment."},{"step":"Deploy the script","action":"1. Save as `sortd_automation.py`. 2. Install dependencies: `pip install requests`. 3. Run manually first: `python sortd_automation.py`. 4. For production, set up a cron job: `*/30 * * * * /usr/bin/python3 /path/to/sortd_automation.py >> /var/log/sortd_automation.log 2>&1`","tip":"For cloud deployment, consider AWS Lambda with CloudWatch Events for scheduling. Set timeout to 15 minutes to avoid rate limits."},{"step":"Monitor and refine","action":"1. Check logs after first run: `tail -f /var/log/sortd_automation.log`. 2. Review Sortd board to verify cards moved correctly. 3. Adjust parsing logic based on any errors in the logs.","tip":"Set up email alerts for critical failures using the `logging` module. Example: `logging.basicConfig(filename='sortd_automation.log', level=logging.ERROR)`"},{"step":"Scale with additional features","action":"Extend the script to: 1) Handle follow-up emails from the 'Follow Up' board, 2) Add urgency detection using Sortd's AI features (when available), 3) Integrate with Slack/Teams for team notifications.","tip":"Start with one board/list combination, then expand to others as you validate the automation works reliably."}]
Sharing Python code examples among automation engineering students
Storing and organizing class programming projects
Collaborative learning and peer code review
Building a resource library of Python tutorials and implementations
No install command available. Check the GitHub repository for manual installation instructions.
git clone https://github.com/Hermes-B/HUST_25_auto_qiming_pythonCopy the install command above and run it in your terminal.
Launch Claude Code, Cursor, or your preferred AI coding agent.
Use the prompt template or examples below to test the skill.
Adapt the skill to your specific use case and workflow.
Generate a Python script that automates [SPECIFIC_TASK] using Sortd's Gmail integration for [TEAM_NAME] at [COMPANY]. The script should: 1) Pull unprocessed emails from Sortd's kanban board labeled '[BOARD_NAME]', 2) Parse key details like sender, subject, and custom fields (e.g., deal size, priority), 3) Perform [ACTION] (e.g., update CRM, schedule follow-ups), and 4) Move the task to '[NEXT_STATUS]' in Sortd. Include error handling for API rate limits and email parsing failures. Use the Sortd API documentation for authentication: https://docs.sortd.com/api.
```python
# Automated Sortd-Gmail Pipeline for Acme Corp Sales Team
# Script: AutoProcess_Sortd_Deals.py
# Version: 1.2
# Last Run: 2023-11-15 09:42:00 UTC
import requests
import json
from datetime import datetime, timedelta
import re
# Configuration - Replace with your Sortd API credentials
SORTD_API_KEY = "sk_live_abc123xyz789"
SORTD_BOARD_ID = "board_5f8d0a4b7f1e4b0017c8b7a1" # 'Hot Deals' board
SORTD_LIST_IDS = {
"New": "list_1a2b3c4d5e6f7890",
"In Progress": "list_9f8e7d6c5b4a3210",
"Follow Up": "list_2b3c4d5e6f78901a"
}
COMPANY_CRM_API = "https://api.hubspot.com/crm/v3/objects/deals"
CRM_API_KEY = "pat-na1-abc123xyz789"
# Custom fields mapping for Acme Corp's workflow
CUSTOM_FIELDS = {
"deal_size": "0",
"priority": "Medium",
"source": "Email"
}
class SortdAutomation:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {SORTD_API_KEY}",
"Content-Type": "application/json",
"Accept": "application/json"
})
def get_unprocessed_emails(self):
"""Fetch emails from Sortd board that need processing"""
url = f"https://api.sortd.com/boards/{SORTD_BOARD_ID}/cards"
params = {
"list_id": SORTD_LIST_IDS["New"],
"limit": 50,
"fields": "id,title,description,custom_fields,created_at"
}
try:
response = self.session.get(url, params=params)
response.raise_for_status()
return response.json().get("data", [])
except requests.exceptions.RequestException as e:
print(f"[ERROR] Failed to fetch emails: {str(e)}")
return []
def parse_email_details(self, email_data):
"""Extract key information from email card"""
title = email_data.get("title", "")
description = email_data.get("description", "")
custom_fields = email_data.get("custom_fields", {})
# Extract sender from title (format: "From: [Name] <[email protected]>")
sender_match = re.search(r'From:\s*(.+?)\s*<([^>]+)>', title)
sender_name = sender_match.group(1).strip() if sender_match else "Unknown"
sender_email = sender_match.group(2).strip() if sender_match else "[email protected]"
# Extract deal size from custom fields or description
deal_size = custom_fields.get("deal_size", "0")
if deal_size == "0":
deal_size_match = re.search(r'\$([\d,]+)', description)
deal_size = deal_size_match.group(1).replace(',', '') if deal_size_match else "0"
# Determine priority
priority = custom_fields.get("priority", "Medium")
if priority == "Medium":
if deal_size and int(deal_size) > 10000:
priority = "High"
elif "urgent" in description.lower():
priority = "High"
return {
"card_id": email_data.get("id"),
"sender_name": sender_name,
"sender_email": sender_email,
"subject": title.replace(f"From: {sender_name} <{sender_email}>", "").strip(),
"deal_size": deal_size,
"priority": priority,
"created_at": email_data.get("created_at")
}
def create_crm_deal(self, deal_data):
"""Create or update deal in CRM"""
headers = {
"Authorization": f"Bearer {CRM_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"properties": {
"dealname": f"{deal_data['sender_name']} - {deal_data['subject']}",
"amount": deal_data["deal_size"],
"dealstage": "appointmentscheduled",
"hubspot_owner_id": "123456", # Sales rep ID
"notes": f"Source: Email from {deal_data['sender_email']}\nPriority: {deal_data['priority']}",
"hs_pipeline": "default"
}
}
try:
response = requests.post(
COMPANY_CRM_API,
headers=headers,
data=json.dumps(payload)
)
response.raise_for_status()
return response.json().get("id")
except requests.exceptions.RequestException as e:
print(f"[CRM ERROR] Failed to create deal: {str(e)}")
return None
def update_sortd_card(self, card_id, new_list_id, crm_id=None):
"""Update card status in Sortd and add CRM reference"""
url = f"https://api.sortd.com/cards/{card_id}"
payload = {
"list_id": new_list_id,
"custom_fields": {
"crm_deal_id": crm_id if crm_id else ""
}
}
try:
response = self.session.patch(url, json=payload)
response.raise_for_status()
return True
except requests.exceptions.RequestException as e:
print(f"[SORTD ERROR] Failed to update card {card_id}: {str(e)}")
return False
def process_emails(self):
"""Main automation workflow"""
emails = self.get_unprocessed_emails()
processed_count = 0
if not emails:
print("[INFO] No new emails to process")
return
print(f"[INFO] Processing {len(emails)} new emails...")
for email in emails:
try:
# Parse email details
deal_data = self.parse_email_details(email)
print(f"[PROCESSING] {deal_data['sender_name']} - ${deal_data['deal_size']} deal")
# Create CRM deal
crm_id = self.create_crm_deal(deal_data)
if not crm_id:
print(f"[WARNING] Failed to create CRM deal for {deal_data['sender_name']}")
continue
# Update Sortd card
if self.update_sortd_card(deal_data['card_id'], SORTD_LIST_IDS["In Progress"], crm_id):
processed_count += 1
print(f"[SUCCESS] Processed {deal_data['sender_name']} - CRM ID: {crm_id}")
else:
print(f"[ERROR] Failed to update Sortd card for {deal_data['sender_name']}")
except Exception as e:
print(f"[CRITICAL ERROR] Processing failed for card {email.get('id')}: {str(e)}")
continue
print(f"[SUMMARY] Processed {processed_count}/{len(emails)} emails successfully")
if __name__ == "__main__":
automator = SortdAutomation()
automator.process_emails()
```
**Execution Log:**
```
[2023-11-15 09:42:00] INFO: Processing 8 new emails...
[2023-11-15 09:42:03] PROCESSING: Jane Doe - $15,000 deal
[2023-11-15 09:42:05] SUCCESS: Processed Jane Doe - CRM ID: 123456789
[2023-11-15 09:42:06] PROCESSING: TechCorp Inc - $8,500 deal
[2023-11-15 09:42:08] SUCCESS: Processed TechCorp Inc - CRM ID: 123456801
[2023-11-15 09:42:09] WARNING: Failed to create CRM deal for Acme Ltd
[2023-11-15 09:42:11] PROCESSING: Global Solutions - $50,000 deal
[2023-11-15 09:42:13] SUCCESS: Processed Global Solutions - CRM ID: 123456802
[2023-11-15 09:42:14] SUMMARY: Processed 3/8 emails successfully
```
**Key Features Demonstrated:**
1. **Email Parsing**: Extracts sender details, deal size, and priority from Sortd card titles/descriptions
2. **CRM Integration**: Automatically creates deals in HubSpot with proper field mapping
3. **Status Updates**: Moves processed cards to "In Progress" and links to CRM deal IDs
4. **Error Handling**: Gracefully handles API failures and parsing errors
5. **Custom Logic**: Implements business rules for priority assignment based on deal size
**Next Steps:**
- Schedule this script to run every 30 minutes via cron job
- Add Slack notifications for failed processing attempts
- Extend to handle follow-up emails by checking the "Follow Up" boardAutomate your browser workflows effortlessly
Get more done every day with Microsoft Teams – powered by AI
Automate security compliance and monitor real-time security posture seamlessly.
Automate your spreadsheet tasks with AI power
Agentic AI Workflow platform
Connected workspace for docs, wikis, and projects
Take a free 3-minute scan and get personalized AI skill recommendations.
Take free scan