Passed
Push — main ( 076e2b...0b9149 )
by Máté
01:19
created

main.create_article()   A

Complexity

Conditions 3

Size

Total Lines 31
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 25
nop 5
dl 0
loc 31
rs 9.28
c 0
b 0
f 0
1
from argparse import ArgumentParser, Namespace
2
import logging
3
from pathlib import Path
4
import time
5
from urllib.parse import urlencode
6
import webbrowser
7
8
# future: delete the comment below when stubs for the package below are available
9
import pyperclip  # type: ignore
10
11
# future: report false positive to JetBrains developers
12
# noinspection PyPackages
13
from .grading_types import GradingType  # type: ignore
14
15
# noinspection PyPackages
16
from .quiz import Quiz  # type: ignore
17
18
# noinspection PyPackages
19
from .quiz_helpers import clear_terminal  # type: ignore
20
21
22
def main() -> None:
23
    args = parse_arguments()
24
    configure_logging(args.verbose)
25
    logging.getLogger(__name__).debug("Program started...")
26
27
    quiz_title = get_desired_name_of_quiz(args.new)
28
    quiz = Quiz(
29
        parent_article=get_name_of_parent_article(),
30
        title=quiz_title,
31
        grading=get_grading(),
32
    )
33
    absolute_source_path: Path = args.source_path.resolve()
34
    quiz.import_files(
35
        path=absolute_source_path,
36
        recursively=args.recursive,
37
    )
38
39
    quiz_wikitext = str(quiz)
40
    wiki_domain = "https://test.vik.wiki"
41
    webbrowser.open_new_tab(f"{wiki_domain}/index.php?title=Speciális:Belépés")
42
    input("Please log in to the wiki then press Enter to continue...")
43
    parameters_for_opening_edit = {
44
        "action": "edit",
45
        "summary": "Kvíz bővítése "
46
        "a https://github.com/gy-mate/moodle-to-vikwikiquiz segítségével importált Moodle-kvíz(ek)ből",
47
        "preload": "Sablon:Előbetöltés",
48
        "preloadparams[]": "<!-- Töröld ki ezt és a következő sort, majd illeszd be a vágólapodra másolt tartalmat! -->",
49
    }
50
    clear_terminal()
51
    create_article(
52
        args, parameters_for_opening_edit, quiz_title, quiz_wikitext, wiki_domain
53
    )
54
    logging.getLogger(__name__).debug("Program finished!")
55
56
57
def parse_arguments() -> Namespace:
58
    parser = ArgumentParser()
59
    parser.add_argument(
60
        "-v", "--verbose", action="store_true", help="increase output verbosity"
61
    )
62
    parser.add_argument(
63
        "-n",
64
        "--new",
65
        action="store_true",
66
        help="create a new quiz on vik.wiki by automatically opening an edit page for the new article",
67
    )
68
    parser.add_argument(
69
        "-r",
70
        "--recursive",
71
        action="store_true",
72
        help="import HTML files from the current directory recursively",
73
    )
74
    parser.add_argument(
75
        "source_path",
76
        type=Path,
77
        help="The absolute or relative path of the file or directory where the Moodle quiz HTML files are located. "
78
        "These HTML files should contain the 'Review' page of the quizzes.",
79
    )
80
    return parser.parse_args()
81
82
83
def configure_logging(verbose: bool) -> None:
84
    if verbose:
85
        logging.basicConfig(
86
            encoding="utf-8",
87
            format='%(asctime)s [%(levelname)s] "%(pathname)s:%(lineno)d": %(message)s',
88
            level=logging.DEBUG,
89
        )
90
    else:
91
        logging.basicConfig(
92
            encoding="utf-8",
93
            format="[%(levelname)s]: %(message)s",
94
            level=logging.INFO,
95
        )
96
97
98
def get_name_of_parent_article() -> str:
99
    while True:
100
        try:
101
            input_name = input(
102
                f"\nPlease enter the name of the vik.wiki article on the corresponding course on then press Enter: "
103
            )
104
            if not input_name:
105
                raise ValueError("Nothing was entered!")
106
            return input_name
107
        except ValueError as error:
108
            print(error)
109
110
111
def get_desired_name_of_quiz(new: bool) -> str:
112
    while True:
113
        try:
114
            print(
115
                "\nPlease enter how the quiz should be named on vik.wiki then press Enter!"
116
                "\nThis is usually in the following form: `[course name] kvíz – [exam name]`. (The ` – [exam name]` can be omitted.)"
117
            )
118
            if not new:
119
                print("This might be an existing article name.")
120
            input_name = input()
121
            if not input_name:
122
                raise ValueError("Nothing was entered!")
123
            return input_name
124
        except ValueError as error:
125
            print(error)
126
127
128
def get_grading() -> GradingType:
129
    while True:
130
        try:
131
            grading_symbol = input(
132
                "\nPlease enter `+` or `-` as the grading type of the quiz then press Enter!"
133
                "\nSee https://vik.wiki/wiki/Segítség:Kvíz#Pontozás for further info.\n"
134
            )
135
            return GradingType(grading_symbol)
136
        except ValueError:
137
            print("This is not a valid grading type!")
138
        finally:
139
            clear_terminal()
140
141
142
def create_article(
143
    args: Namespace,
144
    parameters_for_opening_edit: dict,
145
    quiz_title: str,
146
    quiz_wikitext: str,
147
    wiki_domain: str,
148
) -> None:
149
    if args.new:
150
        parameters_for_opening_edit_with_paste = parameters_for_opening_edit.copy()
151
        parameters_for_opening_edit_with_paste.update(
152
            {
153
                "preload": "Sablon:Előbetöltés",
154
                "preloadparams[]": quiz_wikitext,
155
            }
156
        )
157
        parameters_for_opening_edit_with_paste["summary"] = (
158
            parameters_for_opening_edit_with_paste["summary"].replace(
159
                "bővítése", "létrehozása"
160
            )
161
        )
162
        url = f"{wiki_domain}/wiki/{quiz_title}?{urlencode(parameters_for_opening_edit_with_paste)}"
163
        if len(url) < 2048:
164
            return open_article_paste_text(args, quiz_wikitext, url)
165
        else:
166
            open_article(args, parameters_for_opening_edit, url)
167
    pyperclip.copy(quiz_wikitext)
168
    print("The wikitext of the quiz has been copied to the clipboard!")
169
    url = f"{wiki_domain}/wiki/{quiz_title}?{urlencode(parameters_for_opening_edit)}"
170
    webbrowser.open_new_tab(url)
171
    print(
172
        "The edit page of the quiz article has been opened in your browser! "
173
        "Please paste the wikitext and upload illustrations (if any) there manually."
174
    )
175
176
177
def open_article_paste_text(args: Namespace, quiz_wikitext: str, url: str) -> None:
178
    pyperclip.copy(quiz_wikitext)
179
    print(
180
        "The wikitext of the quiz has been copied to the clipboard! "
181
        "This will be overwritten but you may recall it later if you use an app like Pastebot."
182
    )
183
    wait_for_pastebot_to_recognize_copy()
184
    if args.verbose:
185
        pyperclip.copy(url)
186
        print("The URL has been copied to the clipboard!")
187
    webbrowser.open_new_tab(url)
188
    print(
189
        "The edit page of the new quiz article has been opened in your browser with the wikitext pre-filled! "
190
        "Please upload illustrations manually, if there are any."
191
    )
192
    return
193
194
195
def open_article(args: Namespace, parameters_for_opening_edit: dict, url: str) -> None:
196
    logging.getLogger(__name__).warning(
197
        "I can't create the article automatically "
198
        "because the URL would be too long for some browsers (or the server)."
199
    )
200
    if args.verbose:
201
        pyperclip.copy(url)
202
        print(
203
            "This URL has been copied to the clipboard! "
204
            "It will be overwritten but you may recall it later if you use an app like Pastebot."
205
        )
206
        wait_for_pastebot_to_recognize_copy()
207
    parameters_for_opening_edit["summary"] = parameters_for_opening_edit[
208
        "summary"
209
    ].replace("bővítése", "létrehozása")
210
211
212
def wait_for_pastebot_to_recognize_copy() -> None:
213
    print("Waiting 2 seconds for Pastebot to recognize it...")
214
    time.sleep(2)
215
    print("...done!")
216
217
218
if __name__ == "__main__":
219
    main()
220