157 lines
4.3 KiB
Python
157 lines
4.3 KiB
Python
""" get shared comments associated with a photo """
|
|
|
|
import datetime
|
|
import sys
|
|
from dataclasses import dataclass
|
|
|
|
import osxphotos
|
|
from osxphotos._constants import TIME_DELTA
|
|
|
|
|
|
@dataclass
|
|
class Comment:
|
|
"""Class for shared photo comments"""
|
|
|
|
uuid: str
|
|
sort_fok: int
|
|
datetime: datetime.datetime
|
|
user: str
|
|
ismine: bool
|
|
text: str
|
|
|
|
|
|
@dataclass
|
|
class Like:
|
|
"""Class for shared photo likes"""
|
|
|
|
uuid: str
|
|
sort_fok: int
|
|
datetime: datetime.datetime
|
|
user: str
|
|
ismine: bool
|
|
|
|
|
|
def get_shared_person_info(photosdb, hashed_person_id):
|
|
"""returns tuple of (first name, last name, full name)
|
|
for person invited to shared album with
|
|
ZINVITEEHASHEDPERSONID = hashed_person_id
|
|
|
|
Args:
|
|
photosdb: a osxphotos.PhotosDB object
|
|
hashed_person_id: str, value of ZINVITEEHASHEDPERSONID to lookup
|
|
"""
|
|
|
|
conn, _ = photosdb.get_db_connection()
|
|
results = conn.execute(
|
|
"""
|
|
SELECT
|
|
ZINVITEEHASHEDPERSONID,
|
|
ZINVITEEFIRSTNAME,
|
|
ZINVITEELASTNAME,
|
|
ZINVITEEFULLNAME
|
|
FROM
|
|
ZCLOUDSHAREDALBUMINVITATIONRECORD
|
|
WHERE
|
|
ZINVITEEHASHEDPERSONID = ?
|
|
LIMIT 1
|
|
""",
|
|
([hashed_person_id]),
|
|
).fetchall()
|
|
|
|
if results:
|
|
row = results[0]
|
|
return (row[1], row[2], row[3])
|
|
else:
|
|
return (None, None, None)
|
|
|
|
|
|
def get_comments(photosdb, uuid):
|
|
"""return comments and likes, if any, for photo with uuid
|
|
|
|
Args:
|
|
photosdb: a osxphotos.PhotosDB object
|
|
uuid: uuid of the photo
|
|
|
|
Returns:
|
|
tuple of (list of comments as Comment objects or [] if no comments, list of likes as Like objects or [] if no likes)
|
|
"""
|
|
conn, _ = photosdb.get_db_connection()
|
|
|
|
results = conn.execute(
|
|
"""
|
|
SELECT
|
|
ZGENERICASSET.ZUUID, --0: UUID of the photo
|
|
ZCLOUDSHAREDCOMMENT.ZISLIKE, --1: comment is actually a "like"
|
|
ZCLOUDSHAREDCOMMENT.Z_FOK_COMMENTEDASSET, --2: sort order for comments on a photo
|
|
ZCLOUDSHAREDCOMMENT.ZCOMMENTDATE, --3: date of comment
|
|
ZCLOUDSHAREDCOMMENT.ZCOMMENTTEXT, --4: text of comment
|
|
ZCLOUDSHAREDCOMMENT.ZCOMMENTERHASHEDPERSONID, --5: hashed ID of person who made comment/like
|
|
ZCLOUDSHAREDCOMMENT.ZISMYCOMMENT --6: is my (this user's) comment
|
|
FROM ZCLOUDSHAREDCOMMENT
|
|
JOIN ZGENERICASSET ON
|
|
ZGENERICASSET.Z_PK = ZCLOUDSHAREDCOMMENT.ZCOMMENTEDASSET
|
|
OR
|
|
ZGENERICASSET.Z_PK = ZCLOUDSHAREDCOMMENT.ZLIKEDASSET
|
|
WHERE ZGENERICASSET.ZUUID = ?
|
|
""",
|
|
([uuid]),
|
|
).fetchall()
|
|
|
|
comments = []
|
|
likes = []
|
|
for row in results:
|
|
photo_uuid = row[0]
|
|
sort_fok = row[2] or 0 # sort_fok is Null/None for likes
|
|
is_like = bool(row[1])
|
|
text = row[4]
|
|
user_info = get_shared_person_info(photosdb, row[5])
|
|
try:
|
|
dt = datetime.datetime.fromtimestamp(row[3] + TIME_DELTA)
|
|
except:
|
|
dt = datetime.datetime(1970, 1, 1)
|
|
ismine = bool(row[6])
|
|
if is_like:
|
|
# it's a like
|
|
likes.append(Like(photo_uuid, sort_fok, dt, user_info[2], ismine))
|
|
elif text:
|
|
# comment
|
|
comments.append(
|
|
Comment(photo_uuid, sort_fok, dt, user_info[2], ismine, text)
|
|
)
|
|
if likes:
|
|
likes.sort(key=lambda x: x.datetime)
|
|
if comments:
|
|
comments.sort(key=lambda x: x.sort_fok)
|
|
return (comments, likes)
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) > 1:
|
|
# library as first argument
|
|
photosdb = osxphotos.PhotosDB(dbfile=sys.argv[1])
|
|
else:
|
|
# open default library
|
|
photosdb = osxphotos.PhotosDB()
|
|
|
|
# shared albums
|
|
shared_albums = photosdb.album_info_shared
|
|
for album in shared_albums:
|
|
print(f"Processing album {album.title}")
|
|
# only shared albums can have comments
|
|
for photo in album.photos:
|
|
comments, likes = get_comments(photosdb, photo.uuid)
|
|
if comments or likes:
|
|
print(f"{photo.uuid}, {photo.original_filename}: ")
|
|
if likes:
|
|
print("Likes:")
|
|
for like in likes:
|
|
print(like)
|
|
if comments:
|
|
print("Comments:")
|
|
for comment in comments:
|
|
print(comment)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|