# 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 (``, `