# Updating Modules for Automatic Output Generation This guide outlines the process of updating existing xLEAPP modules to use the new automatic output generator. This update simplifies module code and ensures consistent output across all artifacts. ## Key Changes 1. Update the `__artifacts_v2__` block 2. Modify imports 3. Add the `@artifact_processor` decorator 4. Adjust the main function 5. Remove manual report generation code 6. Use a distinct data_list for HTML report (if needed) 7. Handling Media Files with the Media Manager (New 2025-05-10) 8. Add chat parameters if the artifact should support a threaded type view 9. Update Device Information Collection ## Detailed Process ### 1. Update the `__artifacts_v2__` block Ensure the `__artifacts_v2__` dictionary includes all required fields, especially the `output_types` field. This dictionary should be the very first thing in the script, before any imports or other code. The key in this dictionary must exactly match the name of the function that processes the artifact. If there are double asterisk marks at the start of the search pattern in the paths key, replace them with only one asterisk mark. ```python __artifacts_v2__ = { "function_name": { # This should match exactly the function name in the script "name": "Human-readable Artifact Name", "description": "Brief description of what the artifact does", "author": "@AuthorUsername", "creation_date": "2023-05-24", "last_update_date": "2024-12-17", "requirements": "none", "category": "Artifact Category", "notes": "", "paths": ('Path/to/artifact/files',), "output_types": "all" # or "standard" or ["html", "tsv", "timeline", "kml", "lava"], "artifact_icon": "feather-icon-name" } } ``` Read [Artifact Info Block Structure](./artifact_info_block.md) for more info about `__artifacts_v2__` block ### 2. Modify imports Remove imports related to manual report generation (ArtifactHtmlReport, tsv, kml, timeline) and unused ones, then add the artifact processor and any necessary media manager functions: #### Remove this import ```python from scripts.artifact_report import ArtifactHtmlReport ``` #### Modify this import ```python from scripts.ilapfuncs import artifact_processor, get_file_path # After (ensure all needed functions are imported) from scripts.ilapfuncs import ( artifact_processor, check_in_media, # For media files on disk check_in_embedded_media, # For media stored as blobs/binary data # ... other necessary ilapfuncs ... ) import os # Often needed for path joining ``` ### 3. Add the `@artifact_processor` decorator Add the decorator to the main function: ```python @artifact_processor def artifactname(context): # ... function body ... ``` ### 4. Adjust the main function Modify the function to return data instead of generating reports: ```python def artifactname(context): # if artifact needs to iterate through found files found_files = context.get_files_found() source_path = context.get_source_file_path("filename") data_list = [] # ... Get file contents and process data ... # PList file pl = get_plist_file_content(source_path) for key, val in pl.items(): data_list.append((key, val)) # SQLite database query = '''SQL query''' db_records = get_sqlite_db_records(db_file, query) for record in db_records: timestamp = convert_cocoa_core_data_ts_to_utc(record[0]) data_list.append((record[0], record[1], record[2],)) data_headers = (('Column1', 'datetime'), 'Column2', 'Column3') return data_headers, data_list, source_path ``` [Avoid using SQL Reserved Words in Column Names](#avoiding-sql-reserved-words-in-column-names). Be sure to mark columns with their data type if they are one of the special handler types. It's ok if all data in a marked column doesn't conform to the marked type, as it will be tested and displayed as provided if it doesn't match. Currently the special handler types are: - `datetime` - `date` - `phonenumber` - `media` (See section: [Handling Media Files with the Media Manager](#7-handling-media-files-with-the-media-manager)) #### Timestamps If the artifact is added to the timeline, be sure that the first column is a datetime or date type. For timestamps in SQLite databases, these functions are actually used to convert timestamps in UTC in human readable format. ```python start_time = convert_unix_ts_to_utc(record[0]) # Unix timestamp: e.g. 1733161051 start_time = convert_cocoa_core_data_ts_to_utc(record[0]) # Cocoa Core Data timestamp: e.g. 754853889 ``` For plist files, convert_plist_date_to_utc function has been added to ilapfuncs.py to process the datetime objects (e.g. '2023-05-08T18:22:10Z'). ```python last_modified_date = convert_plist_date_to_utc(last_modified_date) ``` ### 5. Remove manual report generation code Delete any code related to manual report generation, including: - Creating `ArtifactHtmlReport` objects - Calling `report.start_artifact_report` - Writing data to TSV files - Generating timeline or KML files - Any print or logging statements about no data being available: `print()` or `logdev()` ### 6. Use a distinct data_list for HTML report Some artifacts contain data with HTML elements that can be rendered in the HTML report but are not of particular interest for other types of output. For that particular case, you must generate a distinct data_list_html and return a tuple containing the normal data_list in first position and data_list_html in second position. Example from splitwiseNotifications artifact: ```python for record in db_records: created_ts = convert_unix_ts_to_utc(record[0]) data_list_html.append((created_ts, record[1], record[2], record[3])) if '' and '' in record[1]: remove_html = record[1].replace('', '').replace('', '') data_list.append((created_ts, remove_html, record[2], record[3])) return data_headers, (data_list, data_list_html), source_path ``` You also have to indicate in `__artifact_v2__` block which columns contain HTML code to render it properly in the HTML report. Example from splitwiseNotifications artifact: ```python __artifacts_v2__ = { "splitwiseNotifications": { # Usual key information about the artifact "html_columns": ['Notification'] } } ``` ### 7. Handling Media Files with the Media Manager If your artifact processes or references media files (images, videos, audio), use the centralized Media Manager to handle them. This ensures deduplication, consistent display, and proper linking in HTML & LAVA. **Key Functions:** - `check_in_media()`: For media files located on the filesystem within the extraction. - `check_in_embedded_media()`: For media content extracted as binary data (e.g., from a database BLOB). Both functions will copy/link the media to a central data location in the report, add entries to the LAVA database for media items and their references, and return a `media_ref_id` (a string). This ID is what you'll put in your `data_list`. **Steps:** 1. **Call `check_in_media` or `check_in_embedded_media`**: * **For files on disk (`check_in_media`):** ```python current_file_path = "**/path/to/image.jpg" # dummy for example media_file_on_disk = context.get_source_file_path(current_file_path) if media_file_on_disk: media_ref_id = check_in_media( file_path=media_file_on_disk, name='if-different-than-name-in-path' # optional ) if media_ref_id: data_list.append((timestamp_column, text_column, media_ref_id)) ``` * **For embedded binary data (`check_in_embedded_media`):** ```python original_source_path_of_db = "*/path/to/sqlite.db" # dummy for example binary_image_data = db.msg_record.imagedata # dummy for example if binary_image_data and original_source_path_of_db: media_ref_id = check_in_embedded_media( source_file=original_source_path_of_db, data=binary_image_data, name=db.msg_record.imagename # optional but good idea if name is available ) if media_ref_id: data_list.append((timestamp_column, description_column, media_ref_id)) ``` 2. **Update `data_headers`**: Mark the column containing `media_ref_id` with the type `'media'`. ```python data_headers = ( ('Timestamp', 'datetime'), 'Description', ('Photo', 'media') # Basic media column # Or with custom style for the HTML display: # ('Thumbnail', 'media', 'max-width:100px; max-height:100px;') ) ``` 3. **Return**: The `artifact_processor` will use the `media_ref_id` and the `'media'` type in `data_headers` to automatically: * Generate correct HTML tags (``, `