PaferaPy Async 0.1
ASGI framework focused on simplicity and efficiency
Loading...
Searching...
No Matches
__init__.py
Go to the documentation of this file.
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# Very simple script to detect video files in a directory, create
5# thumbnails, and display them. It also serves as a good tutorial
6# on how a basic Pafera app works.
7#
8# The JavaScript used is kept intentionally simple so older
9# devices can view the page.
10
11import json
12import os
13import traceback
14import types
15import importlib
16import shutil
17import base64
18import random
19
20from dateutil.parser import parse as ParseDate
21
22from flask import Response
23
24from pafera.types import *
25from pafera.db import *
26
27# =====================================================================
28def index(g):
29
30 filelist = []
31
32 michaelsbirthday = ParseDate('2013-01-18')
33
34 for root, dirs, files in os.walk('static/michael'):
35 for f in files:
36 basename, extension = os.path.splitext(f)
37
38 if extension != '.mp4':
39 continue
40
41 fullpath = os.path.join(root, f)
42
43 stats = os.stat(fullpath)
44
45 date, description = basename.split(' - ')
46
47 thumbfile = os.path.join(root, basename) + '.webp'
48
49 if not os.path.exists(thumbfile):
50 subprocess.run([
51 'ffmpegthumbnailer',
52 '-i',
53 fullpath,
54 '-o',
55 thumbfile,
56 '-s',
57 '256',
58 '-a',
59 ])
60
61 currentage = ParseDate(date)
62
63 age = (currentage.replace(tzinfo = None) - michaelsbirthday).days / 365.25
64
65 filelist.append({
66 'filename': f,
67 'dirname': root,
68 'size': stats.st_size,
69 'extension': extension,
70 'thumbnail': basename + '.webp',
71 'date': date,
72 'age': f'{age:0.1f}',
73 'description': description,
74 })
75
76 filelist.sort(key = lambda x: x['date'])
77
78 ls = []
79
80 for f in filelist:
81 ls.append(f"""
82 <a class="VideoLink" href="/michael/{f['filename']}">
83 <figure>
84 <img class="Square600" src="/michael/{f['thumbnail']}">
85 <figcaption>
86 <div class="Description">{f['description']}<div>
87 <div class="FileDate">{f['date'][0:10]}</div>
88 <div class="Age">{f['age']} years old</div>
89 </figcaption>
90 </figure>
91 </a>
92 """)
93
94 filelist = '\n'.join(ls)
95
96 return f"""
97<!DOCTYPE html>
98<html>
99 <head>
100 <meta charset="UTF-8">
101 <meta name="apple-mobile-web-app-capable" content="yes" />
102 <meta name="mobile-web-app-capable" content="yes" />
103 <meta name="viewport" content="width=device-width,initial-scale=1">
104
105 <link rel="manifest" href="/manifest.json">
106
107 <title>Michael's Videos</title>
108
109 <link rel="stylesheet" type="text/css" href="/system/normalize.css" />
110 <link rel="stylesheet" type="text/css" href="/system/colors.css" />
111 <link rel="stylesheet" type="text/css" href="/system/common.css" />
112 <link rel="stylesheet" type="text/css" href="/system/paferalib.css" />
113 <link rel="stylesheet" type="text/css" href="/system/pafera.css" />
114
115<style>
116
117
118body
119{{
120 margin: 0em;
121 padding: 0em;
122}}
123
124h1
125{{
126 margin: 0em;
127 padding: 0.5em;
128 color: #fff;
129 background-color: #00f;
130 background-image: linear-gradient(#00c, #009, #00c);
131}}
132
133h1 img
134{{
135 width: 2em;
136 height: 1.5em;
137 position: relative;
138 top: -0.2em;
139 padding-right: 0.5em;
140}}
141
142.Clear
143{{
144 clear: both;
145}}
146
147.Center
148{{
149 text-align: center;
150}}
151
152.ImageCenter
153{{
154 text-align: center;
155}}
156
157.Videos
158{{
159 display: flex;
160 text-align: center;
161 align-items: center;
162 justify-content: center;
163 flex-wrap: wrap;
164 flex-flow: center;
165}}
166
167.Videos > a
168{{
169 display: block;
170 flex: auto;
171 padding: 1em;
172 color: white;
173 width: 16em;
174}}
175
176.Videos img
177{{
178 width: 12em;
179 height: 9em;
180}}
181
182.Description
183{{
184 color: white;
185}}
186
187.FileDate
188{{
189 color: #6f6;
190 font-size: 0.8em;
191}}
192
193.Age
194{{
195 color: #ff6;
196 font-size: 0.8em;
197}}
198
199</style>
200
201<script>
202
203function IsString(v)
204{{
205 return (typeof v == 'string' || v instanceof String);
206}}
207
208function IsArray(v)
209{{
210 return Array.isArray(v);
211}}
212
213window.E = function(selector)
214{{
215 return IsString(selector)
216 ? document.querySelector(selector)
217 : selector;
218}}
219
220window.L = console.log;
221
222window.Q = function(selector)
223{{
224 if (IsString(selector))
225 {{
226 if (selector[0] == '#')
227 return [ I(selector.substr(1)) ];
228
229 return document.querySelectorAll(selector);
230 }}
231
232 if (IsArray(selector) || selector instanceof NodeList)
233 return selector;
234
235 if (selector)
236 return [selector];
237
238 return [];
239}}
240
241function SearchVideos()
242{{
243 let filter = E('.videosearch').value.toLowerCase();
244 let videos = Q('.VideoLink');
245
246 for (let i = 0, l = videos.length; i < l; i++)
247 {{
248 let item = videos[i];
249 let description = item.querySelector('.Description').innerText;
250 let filedate = item.querySelector('.FileDate').innerText;
251
252 if ((description.toLowerCase().indexOf(filter) != -1)
253 || (filedate.indexOf(filter) != -1)
254 )
255 {{
256 item.style.display = 'block';
257 }} else
258 {{
259 item.style.display = 'none';
260 }}
261 }}
262}}
263
264</script>
265
266 </head>
267 <body>
268
269 <h1>
270 <img src="logo.webp">
271 Michael's Videos
272 </h1>
273
274 <div class="ButtonBar">
275 <input type="text" class="videosearch">
276 <a class="Color3" onclick="SearchVideos()">Search</a>
277 </div>
278
279 <div class="Videos">
280 {filelist}
281 </div>
282
283 </body>
284</html>
285"""
286
287# *********************************************************************
288ROUTES = {
289 'index': index,
290}
def index(g)
Definition: __init__.py:28
Definition: db.py:1