Skip to content

Instantly share code, notes, and snippets.

@jedi4ever
Last active July 24, 2024 16:31
Show Gist options
  • Save jedi4ever/f101d21650430f1abc8859c10f812c0c to your computer and use it in GitHub Desktop.
Save jedi4ever/f101d21650430f1abc8859c10f812c0c to your computer and use it in GitHub Desktop.
Appscript to create & read Keynote files
#!/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()
#!/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