will9512

email_random_photo_from_album

Jul 8th, 2024 (edited)
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.79 KB | None | 0 0
  1. import os
  2. import requests
  3. import smtplib
  4. from email.mime.multipart import MIMEMultipart
  5. from email.mime.text import MIMEText
  6. from email.mime.base import MIMEBase
  7. from email import encoders
  8. import logging
  9. from datetime import datetime, timedelta
  10. import random
  11. import json
  12. import uuid
  13. from PIL import Image
  14.  
  15. # Configure logging
  16. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  17.  
  18. # Load sensitive data from environment variables
  19. SERVER_URL = "http://default.server.url"
  20. EMAIL = "default_email@example.com"
  21. PASSWORD = "default_password" #immich password
  22. SMTP_PASSWORD = "default_smtp_password"
  23. TRACKED_IMAGES_FILE = 'tracked_images.txt' # file to keep track of whats been sent
  24. PERSON_ID = 'default_person_id'
  25.  
  26. recipient_emails = [
  27.     "recipient1@example.com", "recipient2@example.com",
  28.     "recipient3@example.com", "recipient4@example.com",
  29.     "recipient5@example.com"
  30. ]
  31.  
  32. def compress_image(file_path, quality=85, output_folder='compressed_images'):
  33.     original_size = os.path.getsize(file_path)
  34.     max_size = 25 * 1024 * 1024  # 25 MB
  35.  
  36.     if original_size > max_size:
  37.         os.makedirs(output_folder, exist_ok=True)
  38.         image = Image.open(file_path)
  39.         original_basename = os.path.basename(file_path)
  40.         new_file_path = os.path.join(output_folder, f"compressed_{original_basename}")
  41.  
  42.         image.save(new_file_path, format='JPEG', quality=quality)
  43.  
  44.         if os.path.exists(new_file_path):
  45.             os.remove(file_path)
  46.             return new_file_path
  47.         else:
  48.             return file_path
  49.     else:
  50.         return file_path
  51.  
  52. def download_asset(server_url, photo_id, token, query_key=None):
  53.     file_path = f'{photo_id}.jpg'
  54.     if not os.path.exists(file_path):
  55.         logging.info(f"Downloading image: {photo_id}")
  56.         download_url = f"{server_url}/api/assets/{photo_id}/original"
  57.         headers = {'Authorization': f'Bearer {token}', 'Accept': 'application/octet-stream'}
  58.         params = {'key': query_key} if query_key else {}
  59.  
  60.         try:
  61.             response = requests.get(download_url, headers=headers, params=params)
  62.             if response.status_code == 200:
  63.                 content_type = response.headers.get('Content-Type')
  64.                 extension = content_type.split('/')[-1]
  65.                 file_path = f"{photo_id}.{extension}"
  66.                
  67.                 with open(file_path, 'wb') as f:
  68.                     for chunk in response.iter_content(chunk_size=8192):
  69.                         f.write(chunk)
  70.                 logging.info(f"Image downloaded: {photo_id}")
  71.             else:
  72.                 logging.error(f"Failed to download image. Status code: {response.status_code}")
  73.                 return None
  74.         except requests.exceptions.RequestException as e:
  75.             logging.error(f"Error during image download: {e}")
  76.             return None
  77.     else:
  78.         logging.info(f"Image already exists: {photo_id}")
  79.  
  80.     file_path = compress_image(file_path) if 'image' in content_type else file_path
  81.     return file_path
  82.  
  83. def login_to_api(server_url, email, password):
  84.     logging.info("Attempting to log in...")
  85.     login_url = f"{server_url}/api/auth/login"
  86.     login_payload = json.dumps({"email": email, "password": password})
  87.     login_headers = {'Content-Type': 'application/json'}
  88.  
  89.     try:
  90.         response = requests.post(login_url, headers=login_headers, data=login_payload)
  91.         if response.status_code in [200, 201]:
  92.             logging.info("Login successful")
  93.             return response.json()
  94.         else:
  95.             logging.error(f"Failed to login. Status code: {response.status_code}")
  96.             return None
  97.     except requests.exceptions.RequestException as e:
  98.         logging.error(f"Error during login: {e}")
  99.         return None
  100.  
  101. def validate_token(server_url, token):
  102.     url = f"{server_url}/api/auth/validateToken"
  103.     headers = {'Authorization': f'Bearer {token}', 'Accept': 'application/json'}
  104.  
  105.     try:
  106.         response = requests.post(url, headers=headers)
  107.         if response.status_code == 200:
  108.             return response.json().get('authStatus', False)
  109.         else:
  110.             logging.error(f"Failed to validate token. Status code: {response.status_code}")
  111.             return False
  112.     except requests.exceptions.RequestException as e:
  113.         logging.error(f"Error during token validation: {e}")
  114.         return False
  115.  
  116. def get_time_buckets(server_url, token, user_id, size='MONTH'):
  117.     logging.info("Fetching time buckets...")
  118.     url = f"{server_url}/api/timeline/buckets"
  119.     headers = {'Authorization': f'Bearer {token}', 'Accept': 'application/json'}
  120.     params = {'userId': user_id, 'size': size}
  121.  
  122.     try:
  123.         response = requests.get(url, headers=headers, params=params)
  124.         if response.status_code == 200:
  125.             logging.info("Time buckets fetched successfully.")
  126.             return response.json()
  127.         else:
  128.             logging.error(f"Failed to fetch time buckets. Status code: {response.status_code}")
  129.             return []
  130.     except requests.exceptions.RequestException as e:
  131.         logging.error(f"Error fetching time buckets: {e}")
  132.         return []
  133.  
  134. def fetch_assets(server_url, token, person_id):
  135.     logging.info("Fetching assets...")
  136.     url = f"{server_url}/api/people/{person_id}/assets"
  137.     headers = {'Authorization': f'Bearer {token}', 'Accept': 'application/json'}
  138.  
  139.     try:
  140.         response = requests.get(url, headers=headers)
  141.         if response.status_code == 200:
  142.             logging.info("Assets fetched successfully")
  143.             assets = response.json()
  144.             last_month_date = datetime.now() - timedelta(days=30)
  145.             format_str = '%Y-%m-%dT%H:%M:%S.%fZ'
  146.             recent_assets = [
  147.                 asset for asset in assets
  148.                 if datetime.strptime(asset['fileCreatedAt'], format_str) >= last_month_date
  149.             ]
  150.             return recent_assets
  151.         else:
  152.             logging.error(f"Failed to fetch assets. Status code: {response.status_code}")
  153.             return []
  154.     except requests.exceptions.RequestException as e:
  155.         logging.error(f"Error fetching assets: {e}")
  156.         return []
  157.  
  158. def record_downloaded_image(image_id):
  159.     with open(TRACKED_IMAGES_FILE, 'a') as file:
  160.         file.write(f"{image_id}\n")
  161.     logging.info(f"Recorded image {image_id} as downloaded")
  162.  
  163. def has_image_been_downloaded(image_id):
  164.     if os.path.exists(TRACKED_IMAGES_FILE):
  165.         with open(TRACKED_IMAGES_FILE, 'r') as file):
  166.             downloaded_images = {line.strip() for line in file}
  167.         return image_id in downloaded_images
  168.     return False
  169.  
  170. def send_email_with_attachment(subject, body, recipient_emails, attachment_path):
  171.     msg = MIMEMultipart()
  172.     msg['From'] = EMAIL
  173.     msg['To'] = ', '.join(recipient_emails)
  174.     msg['Subject'] = subject
  175.     msg.attach(MIMEText(body, 'plain'))
  176.  
  177.     with open(attachment_path, 'rb') as file:
  178.         part = MIMEBase('application', 'octet-stream')
  179.         part.set_payload(file.read())
  180.         encoders.encode_base64(part)
  181.         part.add_header('Content-Disposition', f"attachment; filename= {os.path.basename(attachment_path)}")
  182.         msg.attach(part)
  183.  
  184.     try:
  185.         with smtplib.SMTP('smtp.gmail.com', 587) as server:
  186.             server.starttls()
  187.             server.login(EMAIL, SMTP_PASSWORD)
  188.             server.send_message(msg)
  189.             logging.info(f"Email sent to {', '.join(recipient_emails)}")
  190.     except smtplib.SMTPException as e:
  191.         logging.error(f"Error sending email: {e}")
  192.  
  193. def cleanup_file(file_path):
  194.     os.remove(file_path)
  195.     logging.info(f"Deleted file {file_path}")
  196.  
  197. # Example usage
  198. if __name__ == "__main__":
  199.     login_data = login_to_api(SERVER_URL, EMAIL, PASSWORD)
  200.     if login_data:
  201.         token = login_data.get('accessToken')
  202.         user_id = login_data.get('userId')
  203.         buckets = get_time_buckets(SERVER_URL, token, user_id)
  204.         if buckets:
  205.             latest_bucket = max(buckets, key=lambda b: b['timeBucket'])
  206.             assets = fetch_assets(SERVER_URL, token, PERSON_ID)
  207.             logging.info(f"Assets fetched successfully. Number of assets: {len(assets)}")
  208.  
  209.         if assets:
  210.             selected_asset = random.choice(assets)
  211.             if not has_image_been_downloaded(selected_asset['id']):
  212.                 file_path = download_asset(SERVER_URL, selected_asset['id'], token)
  213.                 if file_path:
  214.                     send_email_with_attachment("Random Photo", "Here's a random photo.", recipient_emails, file_path)
  215.                     cleanup_file(file_path)
  216.                     record_downloaded_image(selected_asset['id'])
  217.                 else:
  218.                     logging.error("Failed to process the image due to download issues")
  219.     else:
  220.         logging.error("Unable to login and perform operations")
  221.  
Add Comment
Please, Sign In to add comment