| 2 января, суббота, 2021 | 00:46:54

Скопировано в буфер обмена!  Копировать Боковая панель Переносы строк Сырой код
1import dataclasses
2import mimetypes
3import os
4from datetime import datetime
5from functools import cached_property
6from typing import Optional, Tuple
7from urllib.parse import urlparse
8
9from feed_proxy.utils import make_hash_tags
10
11MISSING = object()
12TYPES_MAPPING = {
13 bool: 'getboolean',
14 float: 'getfloat',
15 int: 'getint',
16 tuple: 'gettuple',
17}
18OPTIONS_MAPPING = {
19 'post_template': 'gettemplate',
20 'keys_mapping': 'getmapping',
21}
22
23
24@dataclasses.dataclass(frozen=True)
25class Source:
26 name: str
27 url: str
28 receiver: str
29 post_template: str
30 check_processed_until_first_match: bool = True
31 disable_link_preview: bool = False
32 tags: tuple = tuple()
33 id_field: str = 'id'
34 url_field: str = 'link'
35 encoding: Optional[str] = None
36
37 @cached_property
38 def hash_tags(self) -> tuple:
39 return tuple(make_hash_tags(self.tags))
40
41 @classmethod
42 def from_config(cls, config):
43 fields = [(f.name, f.type) for f in dataclasses.fields(cls) if f.init and f.name != 'name']
44 values = {'name': config.name}
45
46 for name, type_ in fields:
47 converter = OPTIONS_MAPPING.get(name) or TYPES_MAPPING.get(type_) or 'get'
48 value = getattr(config, converter)(name, MISSING)
49 if value is not MISSING:
50 values[name] = value
51 return cls(**values)
52
53
54@dataclasses.dataclass(frozen=True)
55class Author:
56 name: str
57 href: str = ''
58 email: str = ''
59
60
61@dataclasses.dataclass(frozen=True)
62class Attachment:
63 href: str
64 type: str
65 length: int
66
67 @cached_property
68 def is_audio(self) -> bool:
69 return self.type.startswith('audio/')
70
71 def guess_extension(self) -> Optional[str]:
72 if from_mime := mimetypes.guess_extension(self.type):
73 return from_mime
74
75 path = urlparse(self.href).path
76 return os.path.splitext(path)[1] or None
77
78
79@dataclasses.dataclass(frozen=True)
80class Post:
81 author: str
82 authors: Tuple[Author, ...]
83 id: str
84 url: str
85 summary: str
86 title: str
87 source: Source
88
89 tags: Tuple[str, ...] = tuple()
90 attachments: Tuple[Attachment, ...] = tuple()
91 published: Optional[datetime] = None
92
93 def has_audio(self) -> bool:
94 return any(item.is_audio for item in self.attachments)
95
96 @cached_property
97 def audio(self) -> Optional[Attachment]:
98 return next((item for item in self.attachments if item.is_audio), None)
99
100 @cached_property
101 def hash_tags(self) -> tuple:
102 return tuple(make_hash_tags(self.tags))
103
104 @cached_property
105 def message_text(self) -> str:
106 source_tags = ' '.join(self.source.hash_tags)
107 post_tags = ' '.join(self.hash_tags)
108 published = ''
109 if self.published:
110 published = self.published.strftime('%d-%m-%Y %H:%M:%S')
111
112 return self.source.post_template.format(
113 all_tags=f'{source_tags} {post_tags}',
114 source_tags=source_tags,
115 post_tags=post_tags,
116 source_name=self.source.name,
117 author=self.author,
118 url=self.url,
119 summary=self.summary,
120 title=self.title,
121 published=published,
122 ).strip()
```
Язык
Библиотека
VM
Скорость
JavaScript 20.3.0
Highlight.js 10.4.1
GraalVM
Быстро
Ruby 2.6.6
Rouge 3.26.0
GraalVM
Приемлемо
Время рендеринга подсветки синтаксиса на сервере: 18ms.
```
Версия Code Polyglot: 1.0.0, 40b65db_190, 19-Jan-2021 15:55:44