Passed
Push — master ( 5bf913...3115ce )
by torrua
01:36
created

app.bot.telegram.models.TelegramWord._keyboard_data()   A

Complexity

Conditions 1

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 20
rs 9.85
c 0
b 0
f 0
cc 1
nop 1
1
# -*- coding: utf-8 -*-
2
"""Model of LOD database for Telegram"""
3
4
from collections import defaultdict
5
6
from loglan_core.addons.definition_selector import DefinitionSelector
7
from loglan_core.addons.word_selector import WordSelector
8
from loglan_core import Word, Definition
9
10
from app.bot.telegram.keyboards import WordKeyboard
11
12
13
class TelegramDefinition(Definition):
14
    """Definition class extensions for Telegram"""
15
16
    def export(self):
17
        """
18
        Convert definition's data to str for sending as a telegram messages
19
        :return: Adopted for posting in telegram string
20
        """
21
        d_usage = f"<b>{self.usage.replace('%', '—')}</b> " if self.usage else ""
22
        d_grammar = (
23
            f"({self.slots if self.slots is not None else ''}{self.grammar_code}) "
24
        )
25
        d_body = (
26
            self.body.replace("<", "&#60;")
27
            .replace(">", "&#62;")
28
            .replace("«", "<i>")
29
            .replace("»", "</i>")
30
            .replace("{", "<code>")
31
            .replace("}", "</code>")
32
            .replace("....", "….")
33
            .replace("...", "…")
34
        )
35
36
        d_case_tags = f" [{self.case_tags}]" if self.case_tags else ""
37
        return f"{d_usage}{d_grammar}{d_body}{d_case_tags}"
38
39
40
class TelegramWord(Word):
41
    """Word class extensions for Telegram"""
42
43
    def format_affixes(self):
44
        return (
45
            f" ({' '.join([w.name for w in self.affixes]).strip()})"
46
            if self.affixes
47
            else ""
48
        )
49
50
    def format_year(self):
51
        return "'" + str(self.year.year)[-2:] + " " if self.year else ""
52
53
    def format_origin(self):
54
        if self.origin or self.origin_x:
55
            return (
56
                f"\n<i>&#60;{self.origin}"
57
                f"{' = ' + self.origin_x if self.origin_x else ''}&#62;</i>"
58
            )
59
        return ""
60
61
    def format_authors(self):
62
        return (
63
            "/".join([a.abbreviation for a in self.authors]) + " "
64
            if self.authors
65
            else ""
66
        )
67
68
    def format_rank(self):
69
        return self.rank + " " if self.rank else ""
70
71
    def export_as_str(self, session) -> str:
72
        """
73
        Convert word's data to str for sending as a telegram messages
74
        :return: List of str with technical info, definitions, used_in part
75
        """
76
        w_affixes = self.format_affixes()
77
        w_match = self.match + " " if self.match else ""
78
        w_year = self.format_year()
79
        w_orig = self.format_origin()
80
        w_authors = self.format_authors()
81
        w_type = self.type.type + " "
82
        w_rank = self.format_rank()
83
84
        word_str = (
85
            f"<b>{self.name}</b>{w_affixes},"
86
            f"\n{w_match}{w_type}{w_authors}{w_year}{w_rank}{w_orig}"
87
        )
88
        return f"{word_str}\n\n{self.get_definitions(session=session)}"
89
90
    def get_definitions(self, session) -> str:
91
        """
92
        Get all definitions of the word
93
        :param session: Session
94
        :return: List of Definition objects ordered by position
95
        """
96
97
        definitions = (
98
            DefinitionSelector(class_=TelegramDefinition)
99
            .filter(TelegramDefinition.word_id == self.id)
100
            .order_by(TelegramDefinition.position.asc())
101
            .all(session=session)
102
        )
103
104
        return "\n\n".join([d.export() for d in definitions])
105
106
    @classmethod
107
    def translation_by_key(cls, session, request: str, language: str = None) -> str:
108
        """
109
        We get information about loglan words by key in a foreign language
110
        :param session: Session
111
        :param request: Requested string
112
        :param language: Key language
113
        :return: Search results string formatted for sending to Telegram
114
        """
115
116
        result = defaultdict(list)
117
        definitions = (
118
            DefinitionSelector(class_=TelegramDefinition)
119
            .by_key(key=request, language=language)
120
            .all(session=session)
121
        )
122
123
        for definition in definitions:
124
            result[definition.source_word.name].append(definition.export())
125
126
        new = "\n"
127
        word_items = [
128
            f"/{word_name},\n{new.join(definitions)}\n"
129
            for word_name, definitions in result.items()
130
        ]
131
        return new.join(word_items).strip()
132
133
    async def send_card_to_user(self, session, bot, user_id: int | str):
134
        """
135
        :param session:
136
        :param bot:
137
        :param user_id:
138
        :return:
139
        """
140
        await bot.send_message(
141
            chat_id=user_id,
142
            text=self.export_as_str(session),
143
            reply_markup=WordKeyboard(self).keyboard_cpx(),
144
        )
145
146
    @classmethod
147
    def by_request(cls, session, request: str) -> list:
148
        """
149
        :param session:
150
        :param request:
151
        :return:
152
        """
153
        if isinstance(request, int):
154
            return [
155
                cls.get_by_id(session, request),
156
            ]
157
        return WordSelector(TelegramWord).by_name(request).all(session)
158