##// END OF EJS Templates
Added statistics management command
neko259 -
r1727:2927138c default
parent child Browse files
Show More
@@ -0,0 +1,28 b''
1 from django.core.management import BaseCommand
2
3 from boards.models import Attachment
4 from boards.utils import get_domain
5
6
7 class Command(BaseCommand):
8 help = 'Gather board statistics'
9
10 def handle(self, *args, **options):
11 domains = {}
12 for attachment in Attachment.objects.exclude(url=None):
13 full_domain = attachment.url.split('/')[2]
14 domain = get_domain(full_domain)
15 if domain in domains:
16 domains[domain] += 1
17 else:
18 domains[domain] = 1
19
20 print('* Domains and their usage')
21 for domain in domains:
22 print('{}: {}'.format(domain, domains[domain]))
23
24 print('* Overall numbers')
25 print('{} attachments in the system, {} of them as URLs'.format(
26 Attachment.objects.count(),
27 Attachment.objects.exclude(url=None).count()))
28
@@ -1,192 +1,193 b''
1 import re
1 import re
2
2
3 from django.contrib.staticfiles import finders
3 from django.contrib.staticfiles import finders
4 from django.contrib.staticfiles.templatetags.staticfiles import static
4 from django.contrib.staticfiles.templatetags.staticfiles import static
5 from django.core.files.images import get_image_dimensions
5 from django.core.files.images import get_image_dimensions
6 from django.template.defaultfilters import filesizeformat
6 from django.template.defaultfilters import filesizeformat
7
7
8 from boards.utils import get_domain
8 from boards.utils import get_domain
9
9
10
10
11 FILE_STUB_IMAGE = 'images/file.png'
11 FILE_STUB_IMAGE = 'images/file.png'
12 FILE_STUB_URL = 'url'
12 FILE_STUB_URL = 'url'
13
13
14
14 FILE_TYPES_VIDEO = (
15 FILE_TYPES_VIDEO = (
15 'webm',
16 'webm',
16 'mp4',
17 'mp4',
17 'mpeg',
18 'mpeg',
18 'ogv',
19 'ogv',
19 )
20 )
20 FILE_TYPE_SVG = 'svg'
21 FILE_TYPE_SVG = 'svg'
21 FILE_TYPES_AUDIO = (
22 FILE_TYPES_AUDIO = (
22 'ogg',
23 'ogg',
23 'mp3',
24 'mp3',
24 'opus',
25 'opus',
25 )
26 )
26 FILE_TYPES_IMAGE = (
27 FILE_TYPES_IMAGE = (
27 'jpeg',
28 'jpeg',
28 'jpg',
29 'jpg',
29 'png',
30 'png',
30 'bmp',
31 'bmp',
31 'gif',
32 'gif',
32 )
33 )
33
34
34 PLAIN_FILE_FORMATS = {
35 PLAIN_FILE_FORMATS = {
35 'pdf': 'pdf',
36 'pdf': 'pdf',
36 'djvu': 'djvu',
37 'djvu': 'djvu',
37 'txt': 'txt',
38 'txt': 'txt',
38 'tex': 'tex',
39 'tex': 'tex',
39 'xcf': 'xcf',
40 'xcf': 'xcf',
40 'zip': 'archive',
41 'zip': 'archive',
41 'tar': 'archive',
42 'tar': 'archive',
42 'gz': 'archive',
43 'gz': 'archive',
43 }
44 }
44
45
45 URL_PROTOCOLS = {
46 URL_PROTOCOLS = {
46 'magnet': 'magnet',
47 'magnet': 'magnet',
47 }
48 }
48
49
49 CSS_CLASS_IMAGE = 'image'
50 CSS_CLASS_IMAGE = 'image'
50 CSS_CLASS_THUMB = 'thumb'
51 CSS_CLASS_THUMB = 'thumb'
51
52
52
53
53 def get_viewers():
54 def get_viewers():
54 return AbstractViewer.__subclasses__()
55 return AbstractViewer.__subclasses__()
55
56
56
57
57 def get_static_dimensions(filename):
58 def get_static_dimensions(filename):
58 file_path = finders.find(filename)
59 file_path = finders.find(filename)
59 return get_image_dimensions(file_path)
60 return get_image_dimensions(file_path)
60
61
61
62
62 # TODO Move this to utils
63 # TODO Move this to utils
63 def file_exists(filename):
64 def file_exists(filename):
64 return finders.find(filename) is not None
65 return finders.find(filename) is not None
65
66
66
67
67 class AbstractViewer:
68 class AbstractViewer:
68 def __init__(self, file, file_type, hash, url):
69 def __init__(self, file, file_type, hash, url):
69 self.file = file
70 self.file = file
70 self.file_type = file_type
71 self.file_type = file_type
71 self.hash = hash
72 self.hash = hash
72 self.url = url
73 self.url = url
73
74
74 @staticmethod
75 @staticmethod
75 def supports(file_type):
76 def supports(file_type):
76 return True
77 return True
77
78
78 def get_view(self):
79 def get_view(self):
79 return '<div class="image">'\
80 return '<div class="image">'\
80 '{}'\
81 '{}'\
81 '<div class="image-metadata"><a href="{}" download >{}, {}</a></div>'\
82 '<div class="image-metadata"><a href="{}" download >{}, {}</a></div>'\
82 '</div>'.format(self.get_format_view(), self.file.url,
83 '</div>'.format(self.get_format_view(), self.file.url,
83 self.file_type, filesizeformat(self.file.size))
84 self.file_type, filesizeformat(self.file.size))
84
85
85 def get_format_view(self):
86 def get_format_view(self):
86 if self.file_type in PLAIN_FILE_FORMATS:
87 if self.file_type in PLAIN_FILE_FORMATS:
87 image = 'images/fileformats/{}.png'.format(
88 image = 'images/fileformats/{}.png'.format(
88 PLAIN_FILE_FORMATS[self.file_type])
89 PLAIN_FILE_FORMATS[self.file_type])
89 else:
90 else:
90 image = FILE_STUB_IMAGE
91 image = FILE_STUB_IMAGE
91
92
92 w, h = get_static_dimensions(image)
93 w, h = get_static_dimensions(image)
93
94
94 return '<a href="{}">'\
95 return '<a href="{}">'\
95 '<img class="url-image" src="{}" width="{}" height="{}"/>'\
96 '<img class="url-image" src="{}" width="{}" height="{}"/>'\
96 '</a>'.format(self.file.url, static(image), w, h)
97 '</a>'.format(self.file.url, static(image), w, h)
97
98
98
99
99 class VideoViewer(AbstractViewer):
100 class VideoViewer(AbstractViewer):
100 @staticmethod
101 @staticmethod
101 def supports(file_type):
102 def supports(file_type):
102 return file_type in FILE_TYPES_VIDEO
103 return file_type in FILE_TYPES_VIDEO
103
104
104 def get_format_view(self):
105 def get_format_view(self):
105 return '<video width="200" height="150" controls src="{}"></video>'\
106 return '<video width="200" height="150" controls src="{}"></video>'\
106 .format(self.file.url)
107 .format(self.file.url)
107
108
108
109
109 class AudioViewer(AbstractViewer):
110 class AudioViewer(AbstractViewer):
110 @staticmethod
111 @staticmethod
111 def supports(file_type):
112 def supports(file_type):
112 return file_type in FILE_TYPES_AUDIO
113 return file_type in FILE_TYPES_AUDIO
113
114
114 def get_format_view(self):
115 def get_format_view(self):
115 return '<audio controls src="{}"></audio>'.format(self.file.url)
116 return '<audio controls src="{}"></audio>'.format(self.file.url)
116
117
117
118
118 class SvgViewer(AbstractViewer):
119 class SvgViewer(AbstractViewer):
119 @staticmethod
120 @staticmethod
120 def supports(file_type):
121 def supports(file_type):
121 return file_type == FILE_TYPE_SVG
122 return file_type == FILE_TYPE_SVG
122
123
123 def get_format_view(self):
124 def get_format_view(self):
124 return '<a class="thumb" href="{}">'\
125 return '<a class="thumb" href="{}">'\
125 '<img class="post-image-preview" width="200" height="150" src="{}" />'\
126 '<img class="post-image-preview" width="200" height="150" src="{}" />'\
126 '</a>'.format(self.file.url, self.file.url)
127 '</a>'.format(self.file.url, self.file.url)
127
128
128
129
129 class ImageViewer(AbstractViewer):
130 class ImageViewer(AbstractViewer):
130 @staticmethod
131 @staticmethod
131 def supports(file_type):
132 def supports(file_type):
132 return file_type in FILE_TYPES_IMAGE
133 return file_type in FILE_TYPES_IMAGE
133
134
134 def get_format_view(self):
135 def get_format_view(self):
135 metadata = '{}, {}'.format(self.file.name.split('.')[-1],
136 metadata = '{}, {}'.format(self.file.name.split('.')[-1],
136 filesizeformat(self.file.size))
137 filesizeformat(self.file.size))
137 width, height = get_image_dimensions(self.file.file)
138 width, height = get_image_dimensions(self.file.file)
138 preview_path = self.file.path.replace('.', '.200x150.')
139 preview_path = self.file.path.replace('.', '.200x150.')
139 pre_width, pre_height = get_image_dimensions(preview_path)
140 pre_width, pre_height = get_image_dimensions(preview_path)
140
141
141 split = self.file.url.rsplit('.', 1)
142 split = self.file.url.rsplit('.', 1)
142 w, h = 200, 150
143 w, h = 200, 150
143 thumb_url = '%s.%sx%s.%s' % (split[0], w, h, split[1])
144 thumb_url = '%s.%sx%s.%s' % (split[0], w, h, split[1])
144
145
145 return '<a class="{}" href="{full}">' \
146 return '<a class="{}" href="{full}">' \
146 '<img class="post-image-preview"' \
147 '<img class="post-image-preview"' \
147 ' src="{}"' \
148 ' src="{}"' \
148 ' alt="{}"' \
149 ' alt="{}"' \
149 ' width="{}"' \
150 ' width="{}"' \
150 ' height="{}"' \
151 ' height="{}"' \
151 ' data-width="{}"' \
152 ' data-width="{}"' \
152 ' data-height="{}" />' \
153 ' data-height="{}" />' \
153 '</a>' \
154 '</a>' \
154 .format(CSS_CLASS_THUMB,
155 .format(CSS_CLASS_THUMB,
155 thumb_url,
156 thumb_url,
156 self.hash,
157 self.hash,
157 str(pre_width),
158 str(pre_width),
158 str(pre_height), str(width), str(height),
159 str(pre_height), str(width), str(height),
159 full=self.file.url, image_meta=metadata)
160 full=self.file.url, image_meta=metadata)
160
161
161
162
162 class UrlViewer(AbstractViewer):
163 class UrlViewer(AbstractViewer):
163 @staticmethod
164 @staticmethod
164 def supports(file_type):
165 def supports(file_type):
165 return file_type is None
166 return file_type is None
166
167
167 def get_view(self):
168 def get_view(self):
168 return '<div class="image">' \
169 return '<div class="image">' \
169 '{}' \
170 '{}' \
170 '</div>'.format(self.get_format_view())
171 '</div>'.format(self.get_format_view())
171
172
172 def get_format_view(self):
173 def get_format_view(self):
173 protocol = self.url.split('://')[0]
174 protocol = self.url.split('://')[0]
174 full_domain = self.url.split('/')[2]
175 full_domain = self.url.split('/')[2]
175 domain = get_domain(full_domain)
176 domain = get_domain(full_domain)
176
177
177 if protocol in URL_PROTOCOLS:
178 if protocol in URL_PROTOCOLS:
178 url_image_name = URL_PROTOCOLS.get(protocol)
179 url_image_name = URL_PROTOCOLS.get(protocol)
179 else:
180 else:
180 filename = 'images/domains/{}.png'.format(domain)
181 filename = 'images/domains/{}.png'.format(domain)
181 if file_exists(filename):
182 if file_exists(filename):
182 url_image_name = 'domains/' + domain
183 url_image_name = 'domains/' + domain
183 else:
184 else:
184 url_image_name = FILE_STUB_URL
185 url_image_name = FILE_STUB_URL
185
186
186 image_path = 'images/{}.png'.format(url_image_name)
187 image_path = 'images/{}.png'.format(url_image_name)
187 image = static(image_path)
188 image = static(image_path)
188 w, h = get_static_dimensions(image_path)
189 w, h = get_static_dimensions(image_path)
189
190
190 return '<a href="{}">' \
191 return '<a href="{}">' \
191 '<img class="url-image" src="{}" width="{}" height="{}"/>' \
192 '<img class="url-image" src="{}" width="{}" height="{}"/>' \
192 '</a>'.format(self.url, image, w, h)
193 '</a>'.format(self.url, image, w, h)
General Comments 0
You need to be logged in to leave comments. Login now