Skip to content

Commit 94af30b

Browse files
committed
Added experimental Webdav upload
1 parent 4b26b50 commit 94af30b

File tree

7 files changed

+109
-31
lines changed

7 files changed

+109
-31
lines changed

photobooth/defaults.cfg

+12
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,15 @@ user =
116116
password =
117117
# SSL connection
118118
use_tls = False
119+
120+
[UploadWebdav]
121+
# Enable/disable webdav upload
122+
enable = False
123+
# URL at webdav server where files should be uploaded
124+
url = https://example.com/remote.php/webdav/Photobooth/
125+
# Webdav server requires authentication
126+
use_auth = True
127+
# Webdav username
128+
user =
129+
# Webdav password
130+
password =

photobooth/worker/PictureList.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1919

2020
import logging
21-
import os
2221

2322
from glob import glob
2423

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

3837
# Set basename and suffix
39-
self.basename = basename
38+
self._basename = basename
4039
self.suffix = '.jpg'
4140
self.count_width = 5
4241

43-
# Ensure directory exists
44-
dirname = os.path.dirname(self.basename)
45-
if not os.path.exists(dirname):
46-
os.makedirs(dirname)
47-
4842
self.findExistingFiles()
4943

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

65+
@property
66+
def basename(self):
67+
"""Return the basename for the files"""
68+
return self._basename
69+
7170
def getFilename(self, count):
7271
"""Return the file name for a given file number"""
7372
return self.basename + str(count).zfill(self.count_width) + self.suffix

photobooth/worker/PictureMailer.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@
2626
from email.utils import formatdate
2727
from email import encoders
2828

29+
from pathlib import Path
30+
2931
from .WorkerTask import WorkerTask
3032

3133

32-
def send_mail(send_from, send_to, subject, message, picture,
34+
def send_mail(send_from, send_to, subject, message, picture, filename,
3335
server, port, is_auth, username, password, is_tls):
3436
"""Compose and send email with provided info and attachments.
3537
@@ -41,6 +43,7 @@ def send_mail(send_from, send_to, subject, message, picture,
4143
subject (str): message title
4244
message (str): message body
4345
picture (jpg byte_data): ByteIO data of the JPG picture
46+
filename (str): Filename of picture
4447
server (str): mail server host name
4548
port (int): port number
4649
is_auth (bool): server requires authentication
@@ -60,7 +63,7 @@ def send_mail(send_from, send_to, subject, message, picture,
6063
part.set_payload(picture.getbuffer())
6164
encoders.encode_base64(part)
6265
part.add_header('Content-Disposition',
63-
'attachment; filename="photobooth.jpg"')
66+
'attachment; filename="{}"'.format(filename))
6467
msg.attach(part)
6568

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

93-
def do(self, picture):
96+
def do(self, picture, filename):
9497

9598
logging.info('Sending picture to %s', self._recipient)
9699
send_mail(self._sender, self._recipient, self._subject, self._message,
97-
picture, self._server, self._port, self._is_auth, self._user,
98-
self._password, self._is_tls)
100+
picture, Path(filename).name, self._server, self._port,
101+
self._is_auth, self._user, self._password, self._is_tls)

photobooth/worker/PictureSaver.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1919

2020
import logging
21+
import os
2122

2223
from .WorkerTask import WorkerTask
23-
from .PictureList import PictureList
2424

2525

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

3030
super().__init__()
3131

32-
self._pic_list = PictureList(basename)
32+
# Ensure directory exists
33+
dirname = os.path.dirname(basename)
34+
if not os.path.exists(dirname):
35+
os.makedirs(dirname)
3336

34-
def do(self, picture):
37+
def do(self, picture, filename):
3538

36-
filename = self._pic_list.getNext()
3739
logging.info('Saving picture as %s', filename)
3840
with open(filename, 'wb') as f:
3941
f.write(picture.getbuffer())
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
# Photobooth - a flexible photo booth software
5+
# Copyright (C) 2018 Balthasar Reuter <photobooth at re - web dot eu>
6+
#
7+
# This program is free software: you can redistribute it and/or modify
8+
# it under the terms of the GNU Affero General Public License as published by
9+
# the Free Software Foundation, either version 3 of the License, or
10+
# (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU Affero General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Affero General Public License
18+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
20+
import logging
21+
import requests
22+
23+
from pathlib import Path
24+
25+
from .WorkerTask import WorkerTask
26+
27+
28+
class PictureUploadWebdav(WorkerTask):
29+
30+
def __init__(self, config):
31+
32+
super().__init__()
33+
34+
self._baseurl = config.get('UploadWebdav', 'url')
35+
if config.getBool('UploadWebdav', 'use_auth'):
36+
self._auth = (config.get('UploadWebdav', 'user'),
37+
config.get('UploadWebdav', 'password'))
38+
else:
39+
self._auth = None
40+
41+
def do(self, picture, filename):
42+
43+
url = self._baseurl + '/' + Path(filename).name
44+
logging.info('Uploading picture as %s', url)
45+
46+
r = requests.put(url, data=picture.getbuffer(), auth=self._auth)
47+
if r.status_code != requests.codes.created:
48+
logging.warn(('PictureUploadWebdav: Upload failed with '
49+
'status code {}').format(r.status_code))

photobooth/worker/__init__.py

+26-14
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@
2424
from .. import StateMachine
2525
from ..Threading import Workers
2626

27+
from .PictureList import PictureList
2728
from .PictureMailer import PictureMailer
2829
from .PictureSaver import PictureSaver
30+
from .PictureUploadWebdav import PictureUploadWebdav
2931

3032

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

3537
self._comm = comm
3638

39+
# Picture list for assembled pictures
40+
path = os.path.join(config.get('Storage', 'basedir'),
41+
config.get('Storage', 'basename'))
42+
basename = strftime(path, localtime())
43+
self._pic_list = PictureList(basename)
44+
45+
# Picture list for individual shots
46+
path = os.path.join(config.get('Storage', 'basedir'),
47+
config.get('Storage', 'basename') + '_shot_')
48+
basename = strftime(path, localtime())
49+
self._shot_list = PictureList(basename)
50+
3751
self.initPostprocessTasks(config)
3852
self.initPictureTasks(config)
3953

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

4458
# PictureSaver for assembled pictures
45-
path = os.path.join(config.get('Storage', 'basedir'),
46-
config.get('Storage', 'basename'))
47-
basename = strftime(path, localtime())
48-
self._postprocess_tasks.append(PictureSaver(basename))
59+
self._postprocess_tasks.append(PictureSaver(self._pic_list.basename))
4960

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

65+
# PictureUploadWebdav to upload pictures to a webdav storage
66+
if config.getBool('UploadWebdav', 'enable'):
67+
self._postprocess_tasks.append(PictureUploadWebdav(config))
68+
5469
def initPictureTasks(self, config):
5570

5671
self._picture_tasks = []
5772

5873
# PictureSaver for single shots
59-
path = os.path.join(config.get('Storage', 'basedir'),
60-
config.get('Storage', 'basename') + '_shot_')
61-
basename = strftime(path, localtime())
62-
self._picture_tasks.append(PictureSaver(basename))
74+
self._picture_tasks.append(PictureSaver(self._shot_list.basename))
6375

6476
def run(self):
6577

@@ -73,23 +85,23 @@ def handleState(self, state):
7385
if isinstance(state, StateMachine.TeardownState):
7486
self.teardown(state)
7587
elif isinstance(state, StateMachine.ReviewState):
76-
self.doPostprocessTasks(state.picture)
88+
self.doPostprocessTasks(state.picture, self._pic_list.getNext())
7789
elif isinstance(state, StateMachine.CameraEvent):
7890
if state.name == 'capture':
79-
self.doPictureTasks(state.picture)
91+
self.doPictureTasks(state.picture, self._shot_list.getNext())
8092
else:
8193
raise ValueError('Unknown CameraEvent "{}"'.format(state))
8294

8395
def teardown(self, state):
8496

8597
pass
8698

87-
def doPostprocessTasks(self, picture):
99+
def doPostprocessTasks(self, picture, filename):
88100

89101
for task in self._postprocess_tasks:
90-
task.do(picture)
102+
task.do(picture, filename)
91103

92-
def doPictureTasks(self, picture):
104+
def doPictureTasks(self, picture, filename):
93105

94106
for task in self._picture_tasks:
95-
task.do(picture)
107+
task.do(picture, filename)

setup.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ def get_mo_files(basedir, installdir):
188188
'Pillow',
189189
'gpiozero',
190190
'gphoto2',
191-
'pycups'
191+
'pycups',
192+
'requests'
192193
],
193194

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

0 commit comments

Comments
 (0)