-
Notifications
You must be signed in to change notification settings - Fork 5
/
day.py
140 lines (111 loc) · 4.33 KB
/
day.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# -*- coding: utf-8 -*-
# gthnk (c) Ian Dennis Miller
import puremagic
import re
from PyPDF2 import PdfFileReader, PdfFileWriter
from flask_diamond.mixins.crud import CRUDMixin
from sqlalchemy import desc
from sqlalchemy.ext.orderinglist import ordering_list
from PIL import Image
from .. import db
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
class Day(db.Model, CRUDMixin):
"""
A Day consists of the Entry objects that were created on that day.
This is just a convenient way of referring to Entry objects in the database.
This object is also capable of creating a string that is parsable by the JournalBuffer
"""
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.Date, unique=True)
pages = db.relationship("Page", order_by="Page.sequence",
collection_class=ordering_list('sequence', reorder_on_append=True),
backref=db.backref("day"))
def add_page(self, binary):
from page import Page
page = Page.create(day=self)
page.set_image(binary=binary)
self.pages.append(page)
self.pages.reorder()
db.session.commit()
return(page)
def attach(self, binary):
# determine the format of the file
ext = puremagic.from_string(binary)
page = None
# if the attachment is a PDF
if ext == ".pdf":
# use PyPDF2 to read the stream
pdf = PdfFileReader(StringIO(binary))
# if it is a multi-page PDF
if pdf.getNumPages() > 1:
# add the pages individually
for pdf_page in pdf.pages:
output = PdfFileWriter()
output.addPage(pdf_page)
pdf_page_buf = StringIO()
output.write(pdf_page_buf)
page = self.add_page(pdf_page_buf.getvalue())
# if it is just a single page PDF
else:
# then add the original bytestream
page = self.add_page(binary)
# if the attachment is a recognized image
elif ext in [".png", ".jfif", ".gif", ".jpeg", ".jpg"]:
page = self.add_page(binary)
# could not recognize file
else:
pass
if page:
return(page)
def render_pdf(self):
outpdf = PdfFileWriter()
for page in self.pages:
if page.extension == "pdf":
# the page is already a PDF so append directly
outpdf.addPage(PdfFileReader(StringIO(page.binary)).getPage(0))
else:
# otherwise, the page is an image that needs to be converted to PDF first
buf = StringIO()
img = Image.open(StringIO(page.binary))
img.convert("RGB").save(buf, format="pdf")
# once image is PDF, it can be appended
outpdf.addPage(PdfFileReader(buf).getPage(0))
pdf_page_buf = StringIO()
outpdf.write(pdf_page_buf)
return(pdf_page_buf.getvalue())
def yesterday(self):
return(self.query.filter(Day.date < self.date).order_by(desc(Day.date)).first())
def tomorrow(self):
return(self.query.filter(Day.date > self.date).order_by(Day.date).first())
def render(self):
from .entry import Entry
buf = self.date.strftime("%Y-%m-%d")
for entry in self.entries.order_by(Entry.timestamp).all():
buf += str(entry)
buf += "\n\n"
return(buf)
def render_markdown(self):
buf = self.render()
buf = re.sub(r'(\d\d\d\d-\d\d-\d\d)\n', '# \g<1>\n', buf)
buf = re.sub(r'(\d\d\d\d)\n', '## \g<1>\n', buf)
img_fmt = "[![{sequence}](../thumbnail/{attachment})](../attachment/{attachment})\n"
if len(self.pages) > 0:
buf += "# Attachments\n\n"
for page in self.pages:
buf += img_fmt.format(
sequence=page.sequence,
thumbnail=page.filename(extension="jpg"),
attachment=page.filename()
)
return buf
def __repr__(self):
return("<Day: {}>".format(self.date))
def __unicode__(self):
return(self.render())
def __str__(self):
return(self.__unicode__())
def latest():
return(Day.query.order_by(desc(Day.date)).first())