Add exif metadata to json

main
bashrc 2026-01-26 11:53:20 +00:00
parent 477ca609a8
commit b9d9accb14
6 changed files with 101 additions and 14 deletions

View File

@ -2959,9 +2959,10 @@ def profile_edit(self, calling_domain: str, cookie: str,
if self.server.low_bandwidth:
convert_image_to_low_bandwidth(filename)
exif_json: list[dict] = []
process_meta_data(base_dir, nickname, domain,
filename, post_image_filename, city,
content_license_url)
content_license_url, exif_json)
if os.path.isfile(post_image_filename):
print('profile update POST ' + m_type +
' image, zip or font saved to ' +

View File

@ -64,6 +64,7 @@ from cache import remove_person_from_cache
from cache import get_person_from_cache
from shares import add_shares_to_actor
from person import get_actor_update_json
from maps import geocoords_to_osm_link
NEW_POST_SUCCESS = 1
NEW_POST_FAILED = -1
@ -1860,6 +1861,7 @@ def _receive_new_post_process(self, post_type: str, path: str, headers: {},
else:
print('DEBUG: no media filename in POST')
exif_json: list[dict] = []
if filename:
if is_image_file(filename):
# convert to low bandwidth if needed
@ -1875,10 +1877,11 @@ def _receive_new_post_process(self, post_type: str, path: str, headers: {},
city = get_spoofed_city(city, base_dir, nickname, domain)
process_meta_data(base_dir, nickname, domain,
filename, post_image_filename, city,
content_license_url)
content_license_url, exif_json)
if os.path.isfile(post_image_filename):
print('POST media saved to ' + post_image_filename)
else:
exif_json = []
print('ERROR: POST media could not be saved to ' +
post_image_filename)
else:
@ -1953,6 +1956,33 @@ def _receive_new_post_process(self, post_type: str, path: str, headers: {},
fields['eventEndTime'] = None
if not fields.get('location'):
fields['location'] = None
if exif_json:
# convert the exif geolocation into an OSM link
latitude = None
longitude = None
for property_dict in exif_json:
if not isinstance(property_dict, dict):
continue
if not property_dict.get('name') or \
not property_dict.get('value'):
continue
if not isinstance(property_dict['name'], str):
continue
if property_dict['name'] == "GPSLongitude":
longitude = property_dict['value']
if not isinstance(longitude, float):
longitude = float(longitude)
if property_dict['name'] == "GPSLatitude":
latitude = property_dict['value']
if not isinstance(latitude, float):
longitude = float(latitude)
if latitude is not None and \
longitude is not None:
osm_domain = 'osm.org'
zoom = 17
fields['location'] = \
geocoords_to_osm_link(osm_domain, zoom,
latitude, longitude)
if not fields.get('locationAddress'):
fields['locationAddress'] = None
if not fields.get('languagesDropdown'):

12
maps.py
View File

@ -25,8 +25,8 @@ from timeFunctions import date_utcnow
from session import get_resolved_url
def _geocoords_to_osm_link(osm_domain: str, zoom: int,
latitude: float, longitude: float) -> str:
def geocoords_to_osm_link(osm_domain: str, zoom: int,
latitude: float, longitude: float) -> str:
"""Returns an OSM link for the given geocoordinates
"""
return 'https://www.' + osm_domain + '/#map=' + \
@ -280,9 +280,9 @@ def get_location_from_post(post_json_object: {}) -> str:
# location geocoordinate
osm_domain = 'osm.org'
zoom = 17
locn = _geocoords_to_osm_link(osm_domain, zoom,
locn2['latitude'],
locn2['longitude'])
locn = geocoords_to_osm_link(osm_domain, zoom,
locn2['latitude'],
locn2['longitude'])
elif locn_url:
# location name and link
if locn:
@ -814,7 +814,7 @@ def html_open_street_map(url: str,
return ''
if not zoom:
return ''
osm_url = _geocoords_to_osm_link(osm_domain, zoom, latitude, longitude)
osm_url = geocoords_to_osm_link(osm_domain, zoom, latitude, longitude)
html_str = \
'<iframe width="' + width + '" height="' + height + \
'" frameborder="0" ' + \

View File

@ -318,7 +318,8 @@ def _remove_meta_data(image_filename: str, output_filename: str) -> None:
def _spoof_meta_data(base_dir: str, nickname: str, domain: str,
output_filename: str, spoof_city: str,
content_license_url: str) -> None:
content_license_url: str,
exif_json: list[dict]) -> None:
"""Spoof image metadata using a decoy model for a given city
"""
if not os.path.isfile(output_filename):
@ -372,6 +373,52 @@ def _spoof_meta_data(base_dir: str, nickname: str, domain: str,
'-Comment="" ' +
output_filename) != 0: # nosec
print('ERROR: exiftool failed to run')
else:
# FEP-ee3a
# https://codeberg.org/fediverse/fep/src/branch/main/
# fep/ee3a/fep-ee3a.md
exif_json += [
{
"@type": "PropertyValue",
"name": "DateTime",
"value": published
},
{
"@type": "PropertyValue",
"name": "GPSLongitudeRef",
"value": longitude_ref
},
{
"@type": "PropertyValue",
"name": "GPSLongitude",
"value": str(longitude)
},
{
"@type": "PropertyValue",
"name": "GPSLatitudeRef",
"value": latitude_ref
},
{
"@type": "PropertyValue",
"name": "GPSLatitude",
"value": str(latitude)
},
{
"@type": "PropertyValue",
"name": "Make",
"value": cam_make
},
{
"@type": "PropertyValue",
"name": "Model",
"value": cam_model
},
{
"@type": "PropertyValue",
"name": "PhotographicSensitivity",
"value": "400"
}
]
else:
print('ERROR: exiftool is not installed')
return
@ -469,7 +516,8 @@ def convert_image_to_low_bandwidth(image_filename: str) -> None:
def process_meta_data(base_dir: str, nickname: str, domain: str,
image_filename: str, output_filename: str,
city: str, content_license_url: str) -> None:
city: str, content_license_url: str,
exif_json: list[dict]) -> None:
"""Handles image metadata. This tries to spoof the metadata
if possible, but otherwise just removes it
"""
@ -478,7 +526,7 @@ def process_meta_data(base_dir: str, nickname: str, domain: str,
# now add some spoofed data to misdirect surveillance capitalists
_spoof_meta_data(base_dir, nickname, domain, output_filename, city,
content_license_url)
content_license_url, exif_json)
def _is_media(image_filename: str) -> bool:
@ -707,9 +755,15 @@ def attach_media(base_dir: str, http_prefix: str,
if media_type.startswith('image/'):
if low_bandwidth:
convert_image_to_low_bandwidth(image_filename)
exif_json: list[dict] = []
process_meta_data(base_dir, nickname, domain,
image_filename, media_filename, city,
content_license_url)
content_license_url, exif_json)
if exif_json:
# FEP-ee3a
# https://codeberg.org/fediverse/fep/src/branch/main/
# fep/ee3a/fep-ee3a.md
attachment_json['exifData'] = exif_json
else:
copyfile(image_filename, media_filename)
_log_uploaded_media(base_dir, nickname, domain, media_filename)

View File

@ -172,9 +172,10 @@ def set_profile_image(base_dir: str, http_prefix: str,
' -size ' + resolution + ' -quality 50 ' + \
safe_system_string(profile_filename)
subprocess.call(cmd, shell=True)
exif_json: list[dict] = []
process_meta_data(base_dir, nickname, domain,
profile_filename, profile_filename, city,
content_license_url)
content_license_url, exif_json)
return True
return False

View File

@ -393,9 +393,10 @@ def add_share(base_dir: str,
continue
if low_bandwidth:
convert_image_to_low_bandwidth(image_filename)
exif_json: list[dict] = []
process_meta_data(base_dir, nickname, domain,
image_filename, item_idfile + '.' + ext,
city, content_license_url)
city, content_license_url, exif_json)
if move_image:
try:
os.remove(image_filename)