Last active
July 24, 2024 16:31
-
-
Save jedi4ever/f101d21650430f1abc8859c10f812c0c to your computer and use it in GitHub Desktop.
Appscript to create & read Keynote files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import appscript | |
import os | |
from contextlib import closing | |
import itertools | |
# appscript | |
# https://appscript.sourceforge.io/py-appscript/index.html | |
# https://github.com/HBehrens/pyKeynoteTweet/blob/ba17624a8ae5ee51013541c1d0aa705602d002a1/pyKeynoteTweet.py#L77 | |
# https://github.com/shaunabanana/SquashNote/blob/1a2dfb9143ee9ef6df0505b7a83d5b297b678266/squash.py#L97 | |
# https://github.com/Loyale/powerglove/blob/561eab828d32318b4327225f8c61ba5ba13d79fd/src/pgKeynote.py#L8 | |
# master slides | |
# https://github.com/JXA-userland/JXA | |
# https://github.com/macintoshhelper/keynote-js/blob/master/src/document.ts | |
# https://stackoverflow.com/questions/44422191/how-to-create-or-edit-keynote-master-slides-using-javascript-for-automation | |
def create_slides(): | |
keynote = appscript.app('Keynote') | |
# Create a new doc | |
k = appscript.k | |
# List themes | |
themes = keynote.themes.get() | |
my_theme = None | |
for t in themes: | |
theme = t.get() | |
theme_name = theme.name.get() | |
# Select the theme to create the doc | |
if theme_name == "Black": | |
print(theme_name) | |
my_theme = t | |
# Add a doc with defaults | |
#doc = keynote.make(new=appscript.k.document) | |
# Add a doc with a theme | |
doc = keynote.make(new=appscript.k.document,with_properties={ | |
k.document_theme :my_theme, | |
k.width: 1024, | |
k.height: 768 | |
}) | |
print(doc.get()) | |
# List master slides | |
# It's called slide_layouts , not masters !!!! | |
# found it through AS Translate of script ! | |
masters= doc.slide_layouts.get() | |
# print("master",masters.name) | |
for m in masters: | |
print("master", m.get().name.get()) | |
# Find the right master slide | |
print("our master",keynote.documents[1].slide_layouts['Title - Centre'].get().name.get()) | |
# app('Keynote').documents[1].current_slide.base_layout.set(app.documents[1].slide_layouts['Title - Center']) | |
# Add a new slide | |
doc.make(new=appscript.k.slide) | |
# Get the slides | |
slides = doc.slides.get() | |
# Set the text for the first slide | |
slide1 = slides[0].get() | |
# Set title | |
title=slide1.default_title_item.get() | |
title.object_text.set("MAAAA") | |
# Set body | |
body = slide1.default_body_item.get() | |
body.object_text.set("WOOOOO") | |
# https://github.com/macintoshhelper/keynote-js/blob/master/src/slide.ts#L130 | |
# font & color - TODO | |
# Set the notes | |
slide1.presenter_notes.set("NOTES") | |
# print("base",slide1.base_layout().get()) | |
# Add a text item | |
slide1.make(new=k.text_item, with_properties={k.object_text: "WOEF"}) | |
# Add a imaged item | |
imagepath = appscript.mactypes.File("image.jpeg") | |
slide1.make(new=k.image,with_properties={k.description:"THE IMAHE",k.file :imagepath, k.width: 100, k.height: 100}) | |
# Add video item | |
videopath = appscript.mactypes.File("movie.mov") | |
# https://iworkautomation.com/keynote/media-items-movie.html | |
# Keynote does not have a movie item to add , use the image type | |
# hmm used to work, but not after switching the theme?? | |
slide1.make(new=k.image,with_properties={k.file:videopath, k.width: 100, k.height: 100}) | |
# k.rotation: 90 - not working | |
# Get the text items | |
items = slide1.text_items.get() | |
# Change them | |
#for item in items: | |
# item.object_text.set("hello") | |
doc.save(in_=appscript.mactypes.File(os.path.abspath("bla2.key"))) | |
def export_slides(): | |
filename="bla2.key" | |
filename = os.path.abspath(filename) | |
slidesDir="p" | |
keynote = appscript.app('Keynote') | |
outpath = appscript.mactypes.File(slidesDir) | |
k = appscript.k | |
keynote_file = appscript.mactypes.File(filename) | |
with closing(keynote.open(keynote_file)) as doc: | |
slides = doc.slides.get() | |
for s in slides: | |
print("slide",s.get().slide_number.get()) | |
images = s.get().images.get() | |
for i in images: | |
image = i.get() | |
print("desc",image.description.get()) | |
#print("object description",image.object_description) | |
# Id , file_name , description | |
# https://appscript.sourceforge.io/py-appscript/doc_3x/mactypes-manual/03_fileclass.html | |
# print("file id",str(image.file.id)) | |
# print("file des",str(image.file.description)) | |
# print("file file_name",str(image.file.file_name)) | |
print("reflection showing",image.reflection_showing.get()) | |
print("width",image.width.get()) | |
print("image file name",image.file_name.get()) | |
notes = doc.slides.presenter_notes() | |
skipped = doc.slides.skipped() | |
notes = list(itertools.compress(notes, [not s for s in skipped])) | |
doc.export(as_=k.slide_images, to=outpath, with_properties = { | |
k.export_style: k.IndividualSlides, | |
k.compression_factor: 0.9, | |
k.image_format: k.JPEG, | |
k.all_stages: True, | |
k.skipped_slides: False | |
}) | |
create_slides() | |
export_slides() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import appscript | |
import os | |
from contextlib import closing | |
import itertools | |
# appscript | |
# https://appscript.sourceforge.io/py-appscript/index.html | |
# https://github.com/HBehrens/pyKeynoteTweet/blob/ba17624a8ae5ee51013541c1d0aa705602d002a1/pyKeynoteTweet.py#L77 | |
# https://github.com/shaunabanana/SquashNote/blob/1a2dfb9143ee9ef6df0505b7a83d5b297b678266/squash.py#L97 | |
# https://github.com/Loyale/powerglove/blob/561eab828d32318b4327225f8c61ba5ba13d79fd/src/pgKeynote.py#L8 | |
# master slides | |
# https://github.com/JXA-userland/JXA | |
# https://github.com/macintoshhelper/keynote-js/blob/master/src/document.ts | |
# https://stackoverflow.com/questions/44422191/how-to-create-or-edit-keynote-master-slides-using-javascript-for-automation | |
class MyTextItem: | |
def __init__(self, text_item): | |
self._text_item = text_item | |
def get_text(self): | |
return self._text_item.object_text.get() | |
def get_height(self): | |
return self._text_item.height.get() | |
def get_width(self): | |
return self._text_item.width.get() | |
# color | |
# font | |
# size | |
width = property(get_width) | |
height = property(get_height) | |
text = property(get_text) | |
class MyMovie: | |
def __init__(self, movie): | |
self._movie = movie | |
def get_file_name(self): | |
return self._movie.file_name.get() | |
def get_height(self): | |
return self._movie.height.get() | |
def get_width(self): | |
return self._movie.width.get() | |
width = property(get_width) | |
height = property(get_height) | |
file_name = property(get_file_name) | |
class MyImage: | |
def __init__(self, image): | |
self._image = image | |
def get_file_name(self): | |
return self._image.file_name.get() | |
def get_height(self): | |
return self._image.height.get() | |
def get_width(self): | |
return self._image.width.get() | |
width = property(get_width) | |
height = property(get_height) | |
file_name = property(get_file_name) | |
class MySlide: | |
def __init__(self, slide): | |
self._slide = slide | |
def get_name(self): | |
return self._slide.name.get() | |
def get_title(self): | |
return self._slide.default_title_item.get().object_text.get() | |
def get_body(self): | |
return self._slide.default_body_item.get().object_text.get() | |
def set_title(self,title): | |
_title=self._slide.default_title_item.get() | |
_title.object_text.set(title) | |
def set_body(self,body): | |
_body=self._slide.default_body_item.get() | |
_body.object_text.set(body) | |
def get_notes(self): | |
return self._slide.presenter_notes.get() | |
def get_slide_number(self): | |
return self._slide.get().slide_number.get() | |
def set_notes(self, notes): | |
self._slide.presenter_notes.set(notes) | |
def get_images(self): | |
images = [] | |
for i in self._slide.images.get(): | |
images.append(MyImage(i)) | |
return images | |
def get_movies(self): | |
movies = [] | |
for v in self._slide.movies.get(): | |
movies.append(MyMovie(v)) | |
return movies | |
def get_text_items(self): | |
text_items = [] | |
for t in self._slide.text_items.get(): | |
text_items.append(MyTextItem(t)) | |
return text_items | |
def new_image(self, file_path): | |
# Add a imaged item | |
k = appscript.k | |
imagepath = appscript.mactypes.File(file_path) | |
self._slide.make(new=k.image,with_properties={ | |
k.description:"THE IMAHE",k.file :imagepath, | |
k.width: 100, k.height: 100 | |
}) | |
def new_movie(self, file_path): | |
# Add a imaged item | |
k = appscript.k | |
moviepath = appscript.mactypes.File(file_path) | |
self._slide.make(new=k.image,with_properties={ | |
k.description:"THE IMAHE",k.file :moviepath, | |
k.width: 100, k.height: 100 | |
}) | |
slide_number = property(get_slide_number) | |
notes = property(get_notes, set_notes) | |
name = property(get_name) | |
title = property(get_title, set_title) | |
body = property(get_body, set_body) | |
images = property(get_images) | |
movies = property(get_movies) | |
text_items = property(get_text_items) | |
class MyLayout: | |
def __init__(self, layout): | |
self._layout = layout | |
def get_name(self): | |
return self._layout.name.get() | |
name = property(get_name) | |
class MyDoc: | |
def __init__(self, doc): | |
self._doc = doc | |
def get_slides(self): | |
slides = [] | |
for s in self._doc.slides.get(): | |
slides.append(MySlide(s)) | |
return slides | |
def get_layouts(self): | |
layouts = [] | |
for l in self._doc.slide_layouts.get(): | |
layouts.append(MyLayout(l)) | |
return layouts | |
def new_slide(self): | |
k = appscript.k | |
slide = self._doc.make(new=k.slide) | |
return MySlide(slide) | |
def save(self, file_path): | |
filepath = appscript.mactypes.File(os.path.abspath(file_path)) | |
self._doc.save(in_=filepath) | |
def export_as_images(self,slides_dir): | |
k = appscript.k | |
outpath = appscript.mactypes.File(slides_dir) | |
self._doc.export(as_=k.slide_images, to=outpath, with_properties = { | |
k.export_style: k.IndividualSlides, | |
k.compression_factor: 0.9, | |
k.image_format: k.JPEG, | |
k.all_stages: True, | |
k.skipped_slides: False | |
}) | |
def export_as_pdf(self,file_path): | |
print("exporting as pdf") | |
# k = appscript.k | |
# outpath = appscript.mactypes.File(file_path) | |
# self._doc.export(as_=k.PDF, to=outpath, with_properties = { | |
# k.all_stages: True, | |
# k.skipped_slides: False | |
# }) | |
# quit ? | |
# close ? | |
slides = property(get_slides) | |
layouts = property(get_layouts) | |
class MyKeynote: | |
def __init__(self): | |
keynote = appscript.app('Keynote') | |
self._keynote = keynote | |
def get_docs(self): | |
docs = [] | |
for d in self._keynote.documents.get(): | |
docs.append(MyDoc(d)) | |
return docs | |
def get_themes(self): | |
themes=[] | |
for t in self._keynote.themes.get(): | |
themes.append(MyTheme(t)) | |
return themes | |
def new_doc(self): | |
doc = self._keynote.make(new=appscript.k.document,with_properties={ | |
# k.document_theme :my_theme, | |
# k.width: 1024, | |
# k.height: 768 | |
}) | |
return MyDoc(doc) | |
docs = property(get_docs) | |
themes = property(get_themes) | |
class MyTheme: | |
def __init__(self, theme): | |
self._theme = theme | |
def get_name(self): | |
return self._theme.name.get() | |
name = property(get_name) | |
def doit(): | |
keynote = MyKeynote() | |
for t in keynote.themes: | |
print("theme",t.name) | |
for d in keynote.docs: | |
#for l in d.layouts: | |
# print("layout",l.name) | |
#print(d.name) | |
for s in d.slides: | |
# print(s.name) | |
print("slide nr",s.slide_number) | |
print("title",s.title) | |
print("body",s.body) | |
print("notes",s.notes) | |
for t in s.text_items: | |
print("text text", t.text) | |
print("text width",t.width) | |
print("text height",t.height) | |
for i in s.images: | |
print("image file name",i.file_name) | |
print("image width",i.width) | |
print("image height",i.height) | |
for m in s.movies: | |
print("movie file name",m.file_name) | |
print("movie width",m.width) | |
print("movie height",m.height) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment