Skip to content

Commit

Permalink
Added experimental Webdav upload
Browse files Browse the repository at this point in the history
  • Loading branch information
reuterbal committed Jun 21, 2019
1 parent 4b26b50 commit 94af30b
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 31 deletions.
12 changes: 12 additions & 0 deletions photobooth/defaults.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,15 @@ user =
password =
# SSL connection
use_tls = False

[UploadWebdav]
# Enable/disable webdav upload
enable = False
# URL at webdav server where files should be uploaded
url = https://example.com/remote.php/webdav/Photobooth/
# Webdav server requires authentication
use_auth = True
# Webdav username
user =
# Webdav password
password =
13 changes: 6 additions & 7 deletions photobooth/worker/PictureList.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import logging
import os

from glob import glob

Expand All @@ -36,15 +35,10 @@ def __init__(self, basename):
"""

# Set basename and suffix
self.basename = basename
self._basename = basename
self.suffix = '.jpg'
self.count_width = 5

# Ensure directory exists
dirname = os.path.dirname(self.basename)
if not os.path.exists(dirname):
os.makedirs(dirname)

self.findExistingFiles()

def findExistingFiles(self):
Expand All @@ -68,6 +62,11 @@ def findExistingFiles(self):
logging.info('Saving pictures as "%s%s.%s"', self.basename,
self.count_width * 'X', 'jpg')

@property
def basename(self):
"""Return the basename for the files"""
return self._basename

def getFilename(self, count):
"""Return the file name for a given file number"""
return self.basename + str(count).zfill(self.count_width) + self.suffix
Expand Down
13 changes: 8 additions & 5 deletions photobooth/worker/PictureMailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
from email.utils import formatdate
from email import encoders

from pathlib import Path

from .WorkerTask import WorkerTask


def send_mail(send_from, send_to, subject, message, picture,
def send_mail(send_from, send_to, subject, message, picture, filename,
server, port, is_auth, username, password, is_tls):
"""Compose and send email with provided info and attachments.
Expand All @@ -41,6 +43,7 @@ def send_mail(send_from, send_to, subject, message, picture,
subject (str): message title
message (str): message body
picture (jpg byte_data): ByteIO data of the JPG picture
filename (str): Filename of picture
server (str): mail server host name
port (int): port number
is_auth (bool): server requires authentication
Expand All @@ -60,7 +63,7 @@ def send_mail(send_from, send_to, subject, message, picture,
part.set_payload(picture.getbuffer())
encoders.encode_base64(part)
part.add_header('Content-Disposition',
'attachment; filename="photobooth.jpg"')
'attachment; filename="{}"'.format(filename))
msg.attach(part)

smtp = smtplib.SMTP(server, port)
Expand Down Expand Up @@ -90,9 +93,9 @@ def __init__(self, config):
self._password = config.get('Mailer', 'password')
self._is_tls = config.getBool('Mailer', 'use_tls')

def do(self, picture):
def do(self, picture, filename):

logging.info('Sending picture to %s', self._recipient)
send_mail(self._sender, self._recipient, self._subject, self._message,
picture, self._server, self._port, self._is_auth, self._user,
self._password, self._is_tls)
picture, Path(filename).name, self._server, self._port,
self._is_auth, self._user, self._password, self._is_tls)
10 changes: 6 additions & 4 deletions photobooth/worker/PictureSaver.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import logging
import os

from .WorkerTask import WorkerTask
from .PictureList import PictureList


class PictureSaver(WorkerTask):
Expand All @@ -29,11 +29,13 @@ def __init__(self, basename):

super().__init__()

self._pic_list = PictureList(basename)
# Ensure directory exists
dirname = os.path.dirname(basename)
if not os.path.exists(dirname):
os.makedirs(dirname)

def do(self, picture):
def do(self, picture, filename):

filename = self._pic_list.getNext()
logging.info('Saving picture as %s', filename)
with open(filename, 'wb') as f:
f.write(picture.getbuffer())
49 changes: 49 additions & 0 deletions photobooth/worker/PictureUploadWebdav.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Photobooth - a flexible photo booth software
# Copyright (C) 2018 Balthasar Reuter <photobooth at re - web dot eu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import logging
import requests

from pathlib import Path

from .WorkerTask import WorkerTask


class PictureUploadWebdav(WorkerTask):

def __init__(self, config):

super().__init__()

self._baseurl = config.get('UploadWebdav', 'url')
if config.getBool('UploadWebdav', 'use_auth'):
self._auth = (config.get('UploadWebdav', 'user'),
config.get('UploadWebdav', 'password'))
else:
self._auth = None

def do(self, picture, filename):

url = self._baseurl + '/' + Path(filename).name
logging.info('Uploading picture as %s', url)

r = requests.put(url, data=picture.getbuffer(), auth=self._auth)
if r.status_code != requests.codes.created:
logging.warn(('PictureUploadWebdav: Upload failed with '
'status code {}').format(r.status_code))
40 changes: 26 additions & 14 deletions photobooth/worker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
from .. import StateMachine
from ..Threading import Workers

from .PictureList import PictureList
from .PictureMailer import PictureMailer
from .PictureSaver import PictureSaver
from .PictureUploadWebdav import PictureUploadWebdav


class Worker:
Expand All @@ -34,6 +36,18 @@ def __init__(self, config, comm):

self._comm = comm

# Picture list for assembled pictures
path = os.path.join(config.get('Storage', 'basedir'),
config.get('Storage', 'basename'))
basename = strftime(path, localtime())
self._pic_list = PictureList(basename)

# Picture list for individual shots
path = os.path.join(config.get('Storage', 'basedir'),
config.get('Storage', 'basename') + '_shot_')
basename = strftime(path, localtime())
self._shot_list = PictureList(basename)

self.initPostprocessTasks(config)
self.initPictureTasks(config)

Expand All @@ -42,24 +56,22 @@ def initPostprocessTasks(self, config):
self._postprocess_tasks = []

# PictureSaver for assembled pictures
path = os.path.join(config.get('Storage', 'basedir'),
config.get('Storage', 'basename'))
basename = strftime(path, localtime())
self._postprocess_tasks.append(PictureSaver(basename))
self._postprocess_tasks.append(PictureSaver(self._pic_list.basename))

# PictureMailer for assembled pictures
if config.getBool('Mailer', 'enable'):
self._postprocess_tasks.append(PictureMailer(config))

# PictureUploadWebdav to upload pictures to a webdav storage
if config.getBool('UploadWebdav', 'enable'):
self._postprocess_tasks.append(PictureUploadWebdav(config))

def initPictureTasks(self, config):

self._picture_tasks = []

# PictureSaver for single shots
path = os.path.join(config.get('Storage', 'basedir'),
config.get('Storage', 'basename') + '_shot_')
basename = strftime(path, localtime())
self._picture_tasks.append(PictureSaver(basename))
self._picture_tasks.append(PictureSaver(self._shot_list.basename))

def run(self):

Expand All @@ -73,23 +85,23 @@ def handleState(self, state):
if isinstance(state, StateMachine.TeardownState):
self.teardown(state)
elif isinstance(state, StateMachine.ReviewState):
self.doPostprocessTasks(state.picture)
self.doPostprocessTasks(state.picture, self._pic_list.getNext())
elif isinstance(state, StateMachine.CameraEvent):
if state.name == 'capture':
self.doPictureTasks(state.picture)
self.doPictureTasks(state.picture, self._shot_list.getNext())
else:
raise ValueError('Unknown CameraEvent "{}"'.format(state))

def teardown(self, state):

pass

def doPostprocessTasks(self, picture):
def doPostprocessTasks(self, picture, filename):

for task in self._postprocess_tasks:
task.do(picture)
task.do(picture, filename)

def doPictureTasks(self, picture):
def doPictureTasks(self, picture, filename):

for task in self._picture_tasks:
task.do(picture)
task.do(picture, filename)
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ def get_mo_files(basedir, installdir):
'Pillow',
'gpiozero',
'gphoto2',
'pycups'
'pycups',
'requests'
],

# List additional groups of dependencies here (e.g. development
Expand Down

0 comments on commit 94af30b

Please sign in to comment.