Compare commits

...

4 Commits

Author SHA1 Message Date
Md Bayazid Bostame
bf46bdf2fe env file updated 2024-10-09 11:00:35 +02:00
Md Bayazid Bostame
fbf423dfdf minor bug fixes 2024-10-09 10:57:15 +02:00
Md Bayazid Bostame
79c8aa7c68 Session method used in the nextcloud configuration and login to efficiently handling it and avoid performance issue 2024-10-09 10:50:10 +02:00
Md Bayazid Bostame
bd5ccc0d16 process diagram added 2024-10-09 10:48:50 +02:00
4 changed files with 82 additions and 32 deletions

7
env/.env vendored
View File

@@ -17,3 +17,10 @@ ONBOARDED_DIR=onboarded_person
TEMP_PDF_DIR=temp_pdf TEMP_PDF_DIR=temp_pdf
EMAIL_TEXT_DIR=email_text EMAIL_TEXT_DIR=email_text
#Nextcloud Information
NEXTCLOUD_BASE_URL=
NEXTCLOUD_USERNAME=
NEXTCLOUD_PASSWORD=
NEXTCLOUD_DIRECTORY=
SYNC_INTERVAL=30 # Check every 60 seconds

View File

@@ -19,6 +19,10 @@ import re
# Load environment variables from .env file # Load environment variables from .env file
load_dotenv(dotenv_path=Path(__file__).parent / 'env' / '.env') load_dotenv(dotenv_path=Path(__file__).parent / 'env' / '.env')
# Load the sync interval from the environment or set a default (in seconds)
SYNC_INTERVAL = int(os.getenv('SYNC_INTERVAL', 60)) # Default is 60 seconds
# Retrieve secret credentials and directories from environment variables # Retrieve secret credentials and directories from environment variables
IMAP_SERVER = os.getenv('IMAP_SERVER') IMAP_SERVER = os.getenv('IMAP_SERVER')
SMTP_SERVER = os.getenv('SMTP_SERVER') SMTP_SERVER = os.getenv('SMTP_SERVER')
@@ -273,4 +277,4 @@ def countdown_timer(seconds):
# Continuously check for new emails every 30 seconds # Continuously check for new emails every 30 seconds
while True: while True:
check_email_for_csv() check_email_for_csv()
countdown_timer(30) countdown_timer(SYNC_INTERVAL)

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,19 +1,21 @@
import os import os
import requests import requests
import time import time
import json
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
from dotenv import load_dotenv from dotenv import load_dotenv
from pathlib import Path from pathlib import Path
from urllib.parse import unquote
# Load environment variables from .env file securely # Load environment variables from .env file securely
env_path = Path(__file__).parent / 'env' / '.env' env_path = Path(__file__).parent / 'env' / '.env'
load_dotenv(dotenv_path=env_path) load_dotenv(dotenv_path=env_path)
# Load Nextcloud credentials and base information from the .env file # Load Nextcloud credentials and base information from the .env file
NEXTCLOUD_BASE_URL = os.getenv('NEXTCLOUD_BASE_URL').rstrip('/') # Remove trailing slash if any NEXTCLOUD_BASE_URL = os.getenv('NEXTCLOUD_BASE_URL').rstrip('/')
NEXTCLOUD_USERNAME = os.getenv('NEXTCLOUD_USERNAME') NEXTCLOUD_USERNAME = os.getenv('NEXTCLOUD_USERNAME')
NEXTCLOUD_PASSWORD = os.getenv('NEXTCLOUD_PASSWORD') NEXTCLOUD_PASSWORD = os.getenv('NEXTCLOUD_PASSWORD')
NEXTCLOUD_DIRECTORY = os.getenv('NEXTCLOUD_DIRECTORY').strip('/') # Ensure no leading/trailing slashes NEXTCLOUD_DIRECTORY = os.getenv('NEXTCLOUD_DIRECTORY').strip('/')
# Load the sync interval from the environment or set a default (in seconds) # Load the sync interval from the environment or set a default (in seconds)
SYNC_INTERVAL = int(os.getenv('SYNC_INTERVAL', 60)) # Default is 60 seconds SYNC_INTERVAL = int(os.getenv('SYNC_INTERVAL', 60)) # Default is 60 seconds
@@ -24,11 +26,27 @@ local_folders = {
'onboarded_person': 'onboarded_person' 'onboarded_person': 'onboarded_person'
} }
def get_nextcloud_files(folder_name): # Local file tracking for uploads
TRACKING_FILE = 'file_tracking.json'
def load_tracking_data():
"""Load the file tracking data from the tracking file."""
if os.path.exists(TRACKING_FILE):
with open(TRACKING_FILE, 'r') as f:
return json.load(f)
return {}
def save_tracking_data(data):
"""Save the file tracking data to the tracking file."""
with open(TRACKING_FILE, 'w') as f:
json.dump(data, f, indent=4)
def get_nextcloud_files(session, folder_name):
""" """
Get a list of files from a specific Nextcloud folder (e.g., 'attachments' or 'onboarded_person'). Get a list of files from a specific Nextcloud folder using a persistent session.
Args: Args:
session (requests.Session): The persistent session object.
folder_name (str): The subfolder name under the group folder on Nextcloud. folder_name (str): The subfolder name under the group folder on Nextcloud.
Returns: Returns:
@@ -39,22 +57,20 @@ def get_nextcloud_files(folder_name):
print(f"Connecting to Nextcloud folder: {nextcloud_url}") print(f"Connecting to Nextcloud folder: {nextcloud_url}")
# Make a PROPFIND request to list files in the Nextcloud directory # Make a PROPFIND request to list files in the Nextcloud directory
headers = { headers = {'Depth': '1'}
'Depth': '1', # Depth header to get all files in the directory response = session.request("PROPFIND", nextcloud_url, headers=headers)
}
response = requests.request("PROPFIND", nextcloud_url, auth=HTTPBasicAuth(NEXTCLOUD_USERNAME, NEXTCLOUD_PASSWORD), headers=headers)
if response.status_code != 207: if response.status_code != 207:
raise Exception(f"Failed to list Nextcloud files in {folder_name}. Status code: {response.status_code}") raise Exception(f"Failed to list Nextcloud files in {folder_name}. Status code: {response.status_code}")
print(f"Successfully retrieved file list from Nextcloud folder: {folder_name}.") print(f"Successfully retrieved file list from Nextcloud folder: {folder_name}.")
# Extract filenames from the XML response
files = [] files = []
for line in response.text.split('\n'): for line in response.text.split('\n'):
if '<d:href>' in line: if '<d:href>' in line:
filename = line.split('<d:href>')[1].split('</d:href>')[0].split('/')[-1] filename = line.split('<d:href>')[1].split('</d:href>')[0].split('/')[-1]
if filename: # Avoid empty strings filename = unquote(filename).strip()
if filename:
files.append(filename) files.append(filename)
print(f"Nextcloud '{folder_name}' contains {len(files)} files: {files}") print(f"Nextcloud '{folder_name}' contains {len(files)} files: {files}")
@@ -64,11 +80,12 @@ def get_nextcloud_files(folder_name):
print(f"Error retrieving files from Nextcloud folder {folder_name}: {e}") print(f"Error retrieving files from Nextcloud folder {folder_name}: {e}")
return [] return []
def upload_file_to_nextcloud(file_path, filename, folder_name): def upload_file_to_nextcloud(session, file_path, filename, folder_name):
""" """
Upload a file to a specific Nextcloud folder (e.g., 'attachments' or 'onboarded_person'). Upload a file to a specific Nextcloud folder using a persistent session.
Args: Args:
session (requests.Session): The persistent session object.
file_path (str): The full path to the file to upload. file_path (str): The full path to the file to upload.
filename (str): The name of the file being uploaded. filename (str): The name of the file being uploaded.
folder_name (str): The Nextcloud subfolder where the file should be uploaded. folder_name (str): The Nextcloud subfolder where the file should be uploaded.
@@ -78,43 +95,57 @@ def upload_file_to_nextcloud(file_path, filename, folder_name):
print(f"Uploading file: {filename} to Nextcloud folder: {folder_name}...") print(f"Uploading file: {filename} to Nextcloud folder: {folder_name}...")
with open(file_path, 'rb') as f: with open(file_path, 'rb') as f:
response = requests.put(nextcloud_url, data=f, auth=HTTPBasicAuth(NEXTCLOUD_USERNAME, NEXTCLOUD_PASSWORD)) response = session.put(nextcloud_url, data=f)
if response.status_code not in [200, 201, 204]: # 204 is a valid status code for success if response.status_code not in [200, 201, 204]: # 204 is a valid status code for success
raise Exception(f"Failed to upload {filename}. Status code: {response.status_code}") raise Exception(f"Failed to upload {filename}. Status code: {response.status_code}")
else: else:
print(f"Successfully uploaded {filename} to Nextcloud folder: {folder_name}.") print(f"Successfully uploaded {filename} to Nextcloud folder: {folder_name}.")
return True
except Exception as e: except Exception as e:
print(f"Error uploading file {filename} to Nextcloud folder {folder_name}: {e}") print(f"Error uploading file {filename} to Nextcloud folder {folder_name}: {e}")
return False
def check_for_new_files(local_folder, nextcloud_files, nextcloud_folder): def check_for_new_files(session, local_folder, nextcloud_files, nextcloud_folder, tracking_data):
""" """
Check for new files in the local folder and upload them to Nextcloud. Check for new files in the local folder and upload them to Nextcloud using a persistent session.
Args: Args:
session (requests.Session): The persistent session object.
local_folder (str): The local folder to check for new files. local_folder (str): The local folder to check for new files.
nextcloud_files (list): The list of files already present in the Nextcloud folder. nextcloud_files (list): The list of files already present in the Nextcloud folder.
nextcloud_folder (str): The corresponding Nextcloud folder to upload new files to. nextcloud_folder (str): The corresponding Nextcloud folder to upload new files to.
tracking_data (dict): The dictionary containing tracked files and their modification times.
""" """
try: try:
local_files = os.listdir(local_folder) local_files = os.listdir(local_folder)
print(f"Files found in local folder '{local_folder}': {local_files}") print(f"Files found in local folder '{local_folder}': {local_files}")
for file in local_files: for file in local_files:
if file not in nextcloud_files:
file_path = os.path.join(local_folder, file) file_path = os.path.join(local_folder, file)
print(f"New file detected: {file} (from {local_folder})") file_mtime = os.path.getmtime(file_path)
upload_file_to_nextcloud(file_path, file, nextcloud_folder)
# Check if the file is new or modified
if file not in nextcloud_files and (file not in tracking_data or tracking_data[file] != file_mtime):
print(f"New or modified file detected: {file} (from {local_folder})")
if upload_file_to_nextcloud(session, file_path, file, nextcloud_folder):
# Update tracking data after successful upload
tracking_data[file] = file_mtime
else: else:
print(f"File {file} already exists in Nextcloud folder {nextcloud_folder}. Skipping...") print(f"File {file} already exists in Nextcloud folder {nextcloud_folder} or has not been modified. Skipping...")
except Exception as e: except Exception as e:
print(f"Error checking for new files in {local_folder}: {e}") print(f"Error checking for new files in {local_folder}: {e}")
def sync_folders(): def sync_folders(session):
""" """
Check local folders for new files and upload them to the corresponding Nextcloud folders. Check local folders for new files and upload them to the corresponding Nextcloud folders using a persistent session.
Args:
session (requests.Session): The persistent session object.
""" """
tracking_data = load_tracking_data()
try: try:
for local_folder, nextcloud_folder in local_folders.items(): for local_folder, nextcloud_folder in local_folders.items():
print(f"Checking local folder: {local_folder} for new files...") print(f"Checking local folder: {local_folder} for new files...")
@@ -126,10 +157,13 @@ def sync_folders():
continue continue
# Get a list of files in the corresponding Nextcloud folder # Get a list of files in the corresponding Nextcloud folder
nextcloud_files = get_nextcloud_files(nextcloud_folder) nextcloud_files = get_nextcloud_files(session, nextcloud_folder)
# Check for new files in the local folder and upload them # Check for new files in the local folder and upload them
check_for_new_files(local_folder, nextcloud_files, nextcloud_folder) check_for_new_files(session, local_folder, nextcloud_files, nextcloud_folder, tracking_data)
# Save updated tracking data
save_tracking_data(tracking_data)
except Exception as e: except Exception as e:
print(f"Error during folder synchronization: {e}") print(f"Error during folder synchronization: {e}")
@@ -151,12 +185,17 @@ def start_periodic_sync():
Start the periodic synchronization of local folders to Nextcloud. Start the periodic synchronization of local folders to Nextcloud.
The synchronization interval is specified in the .env file or defaults to 60 seconds. The synchronization interval is specified in the .env file or defaults to 60 seconds.
""" """
# Use a persistent session for Nextcloud requests
with requests.Session() as session:
# Set up authentication for the session
session.auth = HTTPBasicAuth(NEXTCLOUD_USERNAME, NEXTCLOUD_PASSWORD)
while True: while True:
print("Starting folder synchronization...") print("Starting folder synchronization...")
sync_folders() sync_folders(session)
print("Synchronization complete.") print("Synchronization complete.")
countdown_timer(SYNC_INTERVAL) # Wait for the specified sync interval countdown_timer(SYNC_INTERVAL) # Wait for the specified sync interval
if __name__ == "__main__": if __name__ == "__main__":
print("Starting periodic folder synchronization service...") print("Starting periodic folder synchronization service with a persistent session...")
start_periodic_sync() start_periodic_sync()