linkToPDF2.py 16.9 KB
Newer Older
Dominik Woiwode's avatar
Dominik Woiwode committed
1
2
3
import datetime
import hashlib
import os
Dominik Woiwode's avatar
Dominik Woiwode committed
4
from dataclasses import dataclass
Dominik Woiwode's avatar
Dominik Woiwode committed
5
from pathlib import Path
6
from typing import Optional, Dict, List, Iterator, Tuple
Dominik Woiwode's avatar
Dominik Woiwode committed
7
8
9

import requests

10
11
import config
from pterClasses import Gremium, GREMIUM_FR, GREMIUM_FSR, MailParticipant, sendFRMail, SemesterPart
Dominik Woiwode's avatar
Dominik Woiwode committed
12

13
opt = config.Config()
Jakob Marten's avatar
Jakob Marten committed
14
15


Dominik Woiwode's avatar
Dominik Woiwode committed
16
17
18
19
@dataclass(unsafe_hash=True)
class Semester:
    year: int
    part: SemesterPart
Jakob Marten's avatar
Jakob Marten committed
20

Dominik Woiwode's avatar
Dominik Woiwode committed
21
22
    def __post_init__(self):
        self.displayName = f"{self.part.value} {self.year}"
Fjen Undso's avatar
Fjen Undso committed
23
        self.gravPath = Path(opt.GIT_REPO_PATH) / opt.GRAV_PROTOCOL_PATH / self._gravName() / "protocol_semester.de.md"
Dominik Woiwode's avatar
Dominik Woiwode committed
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

    def _gravName(self):
        return f"{self.year - 2000}{self.part.short()}"

    @classmethod
    def fromDate(cls, date: datetime.datetime) -> "Semester":
        if 4 <= date.month < 10:
            # Summer
            return Semester(date.year, SemesterPart.Summer)
        elif date.month >= 10:
            # Winter
            return Semester(date.year, SemesterPart.Winter)
        else:
            # Winter
            return Semester(date.year - 1, SemesterPart.Winter)
Jakob Marten's avatar
Jakob Marten committed
39
40

    def uploadToGrav(self):
Fjen Undso's avatar
Fjen Undso committed
41
        if self.gravPath.exists():
42
            return
Jakob Marten's avatar
Jakob Marten committed
43

44
        git = opt.git
Fjen Undso's avatar
Fjen Undso committed
45
46
        self.gravPath.parent.mkdir(parents=True, exist_ok=True)
        with self.gravPath.open("w") as d:
Dominik Woiwode's avatar
Dominik Woiwode committed
47
            d.write(f"---\ntitle: {self.displayName}\n---")
Jakob Marten's avatar
Jakob Marten committed
48

49
        git.add(opt.GRAV_PROTOCOL_PATH)
Dominik Woiwode's avatar
Dominik Woiwode committed
50
51
        git.commit(f"Added {self.part.value} {self.year}")
        git.push()
Jakob Marten's avatar
Jakob Marten committed
52
53


Dominik Woiwode's avatar
Dominik Woiwode committed
54
# === Source Types ===
Dominik Woiwode's avatar
Dominik Woiwode committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class SourceTypes:
    def __init__(self, url: str):
        self.url: str = url

    def __repr__(self):
        return f"{self.__class__.__name__}({self.url})"

    def retrieveContent(self):
        raise NotImplementedError()


class Etherpad(SourceTypes):
    def retrieveContent(self):
        url = f"{self.url}.txt"
        response = requests.get(url)
        return response.content.decode("utf-8")

72
73
74
75
76
    @classmethod
    def fitUrl(cls, url: str) -> bool:
        # TODO: Maybe improve filter
        return "/p/" in url

Dominik Woiwode's avatar
Dominik Woiwode committed
77
78
79
80
81
82
83

class CodiMD(SourceTypes):
    def retrieveContent(self):
        url = f"{self.url}/download"
        response = requests.get(url)
        return response.content.decode("utf-8")

84
85
86
87
88
    @classmethod
    def fitUrl(cls, url: str) -> bool:
        # TODO: Maybe improve filter
        return "/p/" not in url

Dominik Woiwode's avatar
Dominik Woiwode committed
89
90

class LocalCache(SourceTypes):
91
92
93
94
    def __init__(self, url: str, localPath: str = None):
        super().__init__(url)
        self.localPath = localPath or hashlib.md5(url.encode("utf-8"))

Dominik Woiwode's avatar
Dominik Woiwode committed
95
    def retrieveContent(self):
96
        with open(self.localPath, "r", encoding="utf-8") as d:
Dominik Woiwode's avatar
Dominik Woiwode committed
97
98
            return d.read()

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
    def asOnlinePad(self) -> SourceTypes:
        if Etherpad.fitUrl(self.url):
            return Etherpad(self.url)
        if CodiMD.fitUrl(self.url):
            return CodiMD(self.url)


class CachedEtherPad(Etherpad):
    def __init__(self, url: str):
        super().__init__(url)
        self._cache = None

    def retrieveContent(self):
        if self._cache is None:
            self._cache = super().retrieveContent()
        return self._cache


class CachedCodiMD(CodiMD):
    def __init__(self, url: str):
        super().__init__(url)
        self._cache = None

    def retrieveContent(self):
        if self._cache is None:
            self._cache = super().retrieveContent()
        return self._cache

Dominik Woiwode's avatar
Dominik Woiwode committed
127
128
129

# === Pad Types ===
class BasePad:
130
131
    def __init__(self, source: SourceTypes, *_, displayName: str = None, date: datetime.datetime, isApproved: bool,
                 **kwargs):
Dominik Woiwode's avatar
Dominik Woiwode committed
132
133
        self.source = source
        self.metadata = kwargs
Jakob Marten's avatar
Jakob Marten committed
134
        self.folder = ""
135
136
137
138
        self.date = date
        self.isApproved = isApproved

        self.displayName = displayName or self.DEFAULT_DISPLAY_NAME()
Dominik Woiwode's avatar
Dominik Woiwode committed
139
140
141
142

    def __repr__(self):
        return f"{self.__class__.__name__}({self.source})"

Dominik Woiwode's avatar
Dominik Woiwode committed
143
144
145
    def DEFAULT_DISPLAY_NAME(self):
        return self.source.url

146
147
    @property
    def rawPath(self) -> Path:
Fjen Undso's avatar
Fjen Undso committed
148
        return Path(opt.DATA_FOLDER).absolute() / "raw" / f"{self.displayName}.md"
Dominik Woiwode's avatar
Dominik Woiwode committed
149

150
151
    @property
    def compiledPath(self) -> Path:
Fjen Undso's avatar
Fjen Undso committed
152
        return Path(opt.DATA_FOLDER).absolute() / "result" / f"{self.displayName}.pdf"
Dominik Woiwode's avatar
Dominik Woiwode committed
153

154
    def download(self, override=True):
Dominik Woiwode's avatar
Dominik Woiwode committed
155
        content = self.source.retrieveContent()
Fjen Undso's avatar
Fjen Undso committed
156
157
158
159
        if not override and self.rawPath.exists():
            raise FileExistsError(f"{self.rawPath} already exists!")
        self.rawPath.parent.mkdir(parents=True, exist_ok=True)
        with self.rawPath.open("w", encoding="utf-8") as d:
Dominik Woiwode's avatar
Dominik Woiwode committed
160
            d.write(content)
Fjen Undso's avatar
Fjen Undso committed
161
        self.source = LocalCache(self.source.url, str(self.rawPath))
162
163

    def compile(self, template: str = None) -> int:
Fjen Undso's avatar
Fjen Undso committed
164
        self.compiledPath.parent.mkdir(parents=True, exist_ok=True)
165
166
        metadataStr = (" " +
                       " ".join([f'-M {key}="{val}"' for key, val in self.metadata.items()]))
Dominik Woiwode's avatar
Dominik Woiwode committed
167
        templateStr = ""
Dominik Woiwode's avatar
Dominik Woiwode committed
168
169
170
171
        if template is None and hasattr(self, "gremium"):
            templateStr = f' --template="{getattr(self, "gremium").fullTemplate()}" '
        elif template != "":
            templateStr = f' --template="{template}" '
172
        cmd = f'pandoc "{self.rawPath}" {metadataStr}{templateStr}-o "{str(self.compiledPath)}"'
Dominik Woiwode's avatar
Dominik Woiwode committed
173
        ret = os.system(cmd)
174
175
        if ret != 0:
            raise RuntimeWarning(f"Non-Zero Returncode ({ret})")
Dominik Woiwode's avatar
Dominik Woiwode committed
176
        return ret
Dominik Woiwode's avatar
Dominik Woiwode committed
177
178
179


class ProtocolPad(BasePad):
Dominik Woiwode's avatar
Dominik Woiwode committed
180
    def __init__(self, source: SourceTypes, *_, date: datetime.datetime = None,
Dominik Woiwode's avatar
Dominik Woiwode committed
181
                 isFachgruppenvollversammlung: bool = False, isApproved: bool = False, gremium: Gremium = None):
182
        self.gremium = gremium or opt.GREMIUM
Dominik Woiwode's avatar
Dominik Woiwode committed
183
        self.isFachgruppenvollversammlung = isFachgruppenvollversammlung
Jakob Marten's avatar
Jakob Marten committed
184
        self.semester = None
185
186

        super().__init__(source, date=date, isApproved=isApproved)
Dominik Woiwode's avatar
Dominik Woiwode committed
187
188
189
190

    def __repr__(self):
        return super(ProtocolPad, self).__repr__()[:-1] + f", {self.date})"

Dominik Woiwode's avatar
Dominik Woiwode committed
191
    def DEFAULT_DISPLAY_NAME(self):
Dominik Woiwode's avatar
Dominik Woiwode committed
192
        return f"Protokoll {self.gremium.name} {self.date.strftime('%Y-%m-%d')}" + " - Fachgruppenvollversammlung" * self.isFachgruppenvollversammlung
Dominik Woiwode's avatar
Dominik Woiwode committed
193

194
195
    @property
    def gravPath(self) -> Path:
Fjen Undso's avatar
Fjen Undso committed
196
197
198
        return Path(
            opt.GIT_REPO_PATH).absolute() / opt.GRAV_PROTOCOL_PATH / self.semester._gravName() / self.date.strftime(
            "%Y-%m-%d") / str("-fgvv" * self.isFachgruppenvollversammlung) / "default.de.md"
Dominik Woiwode's avatar
Dominik Woiwode committed
199
200
201
202
203
204

    def parseTops(self):
        # TODO: better top filter?
        lines = self.source.retrieveContent().split("\n")
        tops = []
        for l in lines:
205
            # TODO: Change to regex?
Dominik Woiwode's avatar
Dominik Woiwode committed
206
207
208
209
210
211
212
            # import re
            # res = re.match("^## ([\w\d &!\"'§$%/\-+äöüß]+)\w*(\(\d\d:\d\d Uhr\))?", l)
            # if res is not None:
            #     top = res.group(1)

            if l.startswith("## "):
                top = l.strip("#").rsplit("(")[0].strip()
213
                if any(top in t or t in top for t in opt.IGNORED_TOPS):
Dominik Woiwode's avatar
Dominik Woiwode committed
214
215
216
                    continue
                tops.append(top)
        return tops
Jakob Marten's avatar
Jakob Marten committed
217

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    def cleanedRaw(self):
        linesNew = []
        ignore = False
        for l in self.source.retrieveContent().split("\n"):
            if l.startswith("######"):  # tags 'fr'
                continue
            if l == "---":
                ignore = True
                continue
            if l == "...":
                ignore = False
                continue
            if ignore:
                continue
            linesNew.append(l)
233
        return "\n".join(linesNew)
234
235
236
237

    def sendMailAsPreliminary(self) -> bool:
        sender = MailParticipant(opt.LDAP_MAIL, opt.MAIL_DISPLAY_NAME)
        receivers = opt.PRELIMINARY_MAIL_RECEIVER
Dominik Woiwode's avatar
Dominik Woiwode committed
238
239
240
        text = (f"Hallo zusammen,\n\n"
                f"anbei das vorläufige Protokoll der Fachrats-Sitzung vom {self.date.strftime('%d.%m.%Y')}.\n\n"
                f"Änderungswünsche bitte direkt an mich, bzw. mir kurz Bescheid geben, wenn ihr was im Pad geändert habt.\n\n"
241
                f"Falls es Probleme mit dieser Mail gibt, meldet euch bitte bei mir. Diese Mail wurde automatisch erstellt.\n\n"
Dominik Woiwode's avatar
Dominik Woiwode committed
242
                f"Viele Grüße\n"
243
                f"{opt.MAIL_DISPLAY_NAME}\n")
Dominik Woiwode's avatar
Dominik Woiwode committed
244
245
        subject = f"Vorläufiges Protokoll der FR-Sitzung vom {self.date.strftime('%d.%m.%Y')}"
        try:
246
            sendFRMail(text, subject, sender, receivers, attachment=self, ldapPassword=opt.LDAP_PASSWORD)
Dominik Woiwode's avatar
Dominik Woiwode committed
247
248
249
250
251
252
253
254
        except Exception:
            return False
        return True

    def sendMailAsApproved(self) -> bool:
        if not self.isApproved:
            print("Protocol is not approved yet!")
            raise PermissionError("Protocol is not approved yet!")
255
256
        sender = MailParticipant(opt.LDAP_MAIL, opt.MAIL_DISPLAY_NAME)
        receivers = opt.APPROVED_MAIL_RECEIVER
Dominik Woiwode's avatar
Dominik Woiwode committed
257
258
259
260
261
        text = (f"Hallo zusammen,\n\n"
                f"anbei das Protokoll der Fachrats-Sitzung vom {self.date.strftime('%d.%m.%Y')}.\n\n"
                f"Alle Protokolle sind zu finden unter:\n"
                f"https://cloud.finf.uni-hannover.de/index.php/s/Erw9Cbta0PruqZI\n\n"
                f"Viele Grüße\n"
262
                f"{opt.MAIL_DISPLAY_NAME}\n")
Dominik Woiwode's avatar
Dominik Woiwode committed
263
264
        subject = f"Protokoll der FR-Sitzung vom {self.date.strftime('%d.%m.%Y')}"
        try:
265
            sendFRMail(text, subject, sender, receivers, attachment=self, ldapPassword=opt.LDAP_PASSWORD)
Dominik Woiwode's avatar
Dominik Woiwode committed
266
267
268
        except Exception:
            return False
        return True
Dominik Woiwode's avatar
Dominik Woiwode committed
269

Jakob Marten's avatar
Jakob Marten committed
270
    def uploadToCloud(self):
Dominik Woiwode's avatar
Dominik Woiwode committed
271
272
        pass

Jakob Marten's avatar
Jakob Marten committed
273
    def uploadToGrav(self):
Dominik Woiwode's avatar
Dominik Woiwode committed
274
        # Init semester
Jakob Marten's avatar
Jakob Marten committed
275
        # TODO: better file management
Jakob Marten's avatar
Jakob Marten committed
276
        self.semester.uploadToGrav()
Fjen Undso's avatar
Fjen Undso committed
277
        if not self.rawPath.exists():
Dominik Woiwode's avatar
Dominik Woiwode committed
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
            raise FileNotFoundError(f"{self.rawPath} doesn't exist")

        # TODO: move conversion to another method?
        # Tops
        tops = self.parseTops()
        tops_text = ", ".join(tops)

        # Header
        if self.isFachgruppenvollversammlung:
            name = "der Fachgruppenvollversammlung"
        else:
            name = f"des {self.gremium.fullName}"
        header = ("---\n"
                  f"title: Protokoll {name} am {self.date.strftime('%d.%m.%Y')}\n"
                  f"date: {self.date.strftime('%d.%m.%Y')}\n"
                  f"tops: {tops_text}\n"
                  "---\n\n"
                  "[MINITOC]\n\n")
        # Upload
Fjen Undso's avatar
Fjen Undso committed
297
298
        self.gravPath.parent.mkdir(parents=True, exist_ok=True)
        with self.gravPath.open("w", encoding="utf-8") as f:
299
            f.write(header + self.cleanedRaw())
Dominik Woiwode's avatar
Dominik Woiwode committed
300

301
302
        git = opt.git
        git.add(opt.GRAV_PROTOCOL_PATH)
Dominik Woiwode's avatar
Dominik Woiwode committed
303
304
        git.commit(f"Added protocol {self.displayName}")
        git.push()
Dominik Woiwode's avatar
Dominik Woiwode committed
305
306
307


class AttachementPad(BasePad):
Dominik Woiwode's avatar
Dominik Woiwode committed
308
    def __init__(self, source: SourceTypes, name: str, date: datetime.datetime = None, version=0, isApproved=False):
309
        super().__init__(source, date=date, isApproved=isApproved)
Dominik Woiwode's avatar
Dominik Woiwode committed
310
311
        self.name = name
        self.version = version
Dominik Woiwode's avatar
Dominik Woiwode committed
312
313
314
315


class PadCollection(BasePad):
    def __init__(self, source: SourceTypes):
316
317
318
319
320
321
322
323
324
325
        super().__init__(source, isApproved=False, date=datetime.datetime.now())
        self._pads: Dict[str, List[BasePad]] = dict()
        self.__retrieved = False

    def __iter__(self) -> Iterator[Tuple[str, BasePad]]:
        """ Iter (folder, pad) """
        pads = self.pads
        for folder in pads:
            for pad in pads[folder]:
                yield folder, pad
Dominik Woiwode's avatar
Dominik Woiwode committed
326

Dominik Woiwode's avatar
Dominik Woiwode committed
327
328
329
    def DEFAULT_DISPLAY_NAME(self):
        return f"PadCollection"

330
331
332
333
334
335
336
337
338
339
340
341
342
343
    def addPads(self, folder: str, pads: List[BasePad]):
        self._pads[folder] = pads

    def clearAllPads(self):
        self._pads = dict()

    @property
    def pads(self):
        if not self.__retrieved:
            self._pads.update(self.getPads())
            self.__retrieved = True

        return self._pads

Dominik Woiwode's avatar
Dominik Woiwode committed
344
    def getPads(self) -> Dict[str, List[BasePad]]:
Dominik Woiwode's avatar
Dominik Woiwode committed
345
346
347
        """
        Parsing the protocollink-Pad for urls.
        """
Dominik Woiwode's avatar
Dominik Woiwode committed
348
        pads = dict()
Jakob Marten's avatar
Jakob Marten committed
349
        semesters = dict()
Dominik Woiwode's avatar
Dominik Woiwode committed
350
        currentFolder = ""
Dominik Woiwode's avatar
Dominik Woiwode committed
351
        for line in self.source.retrieveContent().split("\n"):
Dominik Woiwode's avatar
Dominik Woiwode committed
352
353
354
            if line.startswith("# "):
                currentFolder = line.split("#")[1].strip()
                continue
Dominik Woiwode's avatar
Dominik Woiwode committed
355
356
357
            pad = self.parsePad(line)
            if pad is None:
                continue
Dominik Woiwode's avatar
Dominik Woiwode committed
358
359
            if currentFolder not in pads:
                pads[currentFolder] = list()
Dominik Woiwode's avatar
Dominik Woiwode committed
360
361
362
363
364
            if isinstance(pad, ProtocolPad) and pad.date is not None:
                semester = Semester.fromDate(pad.date)
                if semester not in semesters:
                    semesters[semester] = semester
                pad.semester = semester
Jakob Marten's avatar
Jakob Marten committed
365
            pad.folder = currentFolder
Dominik Woiwode's avatar
Dominik Woiwode committed
366
            pads[currentFolder].append(pad)
Dominik Woiwode's avatar
Dominik Woiwode committed
367
368
369

        return pads

370
371
    @classmethod
    def parsePad(cls, line: str, prefixes=None) -> Optional[BasePad]:
Dominik Woiwode's avatar
Dominik Woiwode committed
372
        url, *comment = line.split("#")
373
        if not url.strip():  # Only whitespace
Dominik Woiwode's avatar
Dominik Woiwode committed
374
            return None
375
376
377
378
379
380
381
382
383
        allPrefixes, url = url.split("https://")
        if prefixes is not None:
            allPrefixes += prefixes
        url = f"https://{url}".strip()

        if Etherpad.fitUrl(url):
            retrieveClass = CachedEtherPad
        elif CodiMD.fitUrl(url):
            retrieveClass = CachedCodiMD
Dominik Woiwode's avatar
Dominik Woiwode committed
384
        else:
385
386
            raise ValueError("Cannot retrieve SourceType class")
        src = retrieveClass(url)
Dominik Woiwode's avatar
Dominik Woiwode committed
387

388
389
390
        isAttachement = opt.ATTACHMENT_SIGN in allPrefixes
        isFachgrupenvollversammlung = opt.FACHGRUPPENVOLLVERSAMMLUNG_SIGN in allPrefixes
        isApproved = opt.NOT_APPROVED_SIGN not in allPrefixes
Dominik Woiwode's avatar
Dominik Woiwode committed
391
392
393
394
395
396
397
398
399
400
401
402

        kwargs = dict()
        if isAttachement:
            padType = AttachementPad
            kwargs["date"] = None
            kwargs["name"] = None
            kwargs["version"] = None
            kwargs["isApproved"] = isApproved
        else:
            padType = ProtocolPad
            kwargs["isApproved"] = isApproved
            try:
403
                date = datetime.datetime.strptime(comment[0].strip(), "%d.%m.%Y")
Dominik Woiwode's avatar
Dominik Woiwode committed
404
405
406
407
408
409
410
411
412
            except Exception:
                dateStr = url.split("protokoll")[-1][:8]
                date = datetime.datetime.strptime(dateStr, "%Y%m%d")

            kwargs["date"] = date
            kwargs["isFachgruppenvollversammlung"] = isFachgrupenvollversammlung

        return padType(src, **kwargs)

413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
    def removeApproved(self):
        oldPads = self.pads
        self.clearAllPads()
        for folder in oldPads:
            folderPads = list()
            for pad in oldPads[folder]:
                if not pad.isApproved:
                    folderPads.append(pad)
            if folderPads:
                self.addPads(folder, folderPads)

    def removeOld(self):
        oldPads = self.pads
        self.clearAllPads()
        for folder in oldPads:
            folderPads = list()
            for pad in oldPads[folder]:
                if not isinstance(pad, Etherpad):
                    folderPads.append(pad)
            if folderPads:
                self.addPads(folder, folderPads)
        return self.pads

    def downloadPads(self, forceDownload=False):
        for folder, pad in self:
            pad.download(forceDownload)

    def compilePads(self, template: str = None):
        for folder, pad in self:
            pad.compile(template)

    def createTopics(self):
        raise NotImplementedError()
Jakob Marten's avatar
Jakob Marten committed
446
447


Dominik Woiwode's avatar
Dominik Woiwode committed
448
449
450
if __name__ == '__main__':
    import argparse

451
452
453
    opt = config.Config()
    parser = argparse.ArgumentParser(description="Download and convert finf/fsr-protocols using pandoc")

Dominik Woiwode's avatar
Dominik Woiwode committed
454
455
456
457
458
459
    parser.add_argument("-urls", nargs="+", type=str, default=[])
    parser.add_argument("-pad", type=str, default=None)
    # parser.add_argument("--prefixes", type=str, default="",
    #                     help=f"Add additional information to pad:\n"
    #                          f"Not approved: {NOT_APPROVED_SIGN}\n"
    #                          f"Fachschaftenvollversammlung: {FACHSCHAFTENVERSAMMLUNG_SIGN}\n"
460
    #                          f"Attachement: {ATTACHMENT_SIGN}\n")
Dominik Woiwode's avatar
Dominik Woiwode committed
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
    parser.add_argument("--finf", action="store_true")
    parser.add_argument("--topics", action="store_true")
    parser.add_argument("--fsr", action="store_true")
    parser.add_argument("--download", action="store_true")
    parser.add_argument("--ignoreOld", action="store_true")
    parser.add_argument("--compile", action="store_true")
    parser.add_argument("--newOnly", action="store_true")
    parser.add_argument("--override", action="store_true")
    parser.add_argument("--mail", action="store_true")

    parsed = parser.parse_args()

    urls = parsed.urls
    if not urls and parsed.pad is None:
        parser.print_usage()
        exit()

    if parsed.finf and parsed.fsr:
        raise AttributeError("Cannot have --finf AND --fsr")

    if parsed.finf:
482
        opt.GREMIUM = GREMIUM_FR
Dominik Woiwode's avatar
Dominik Woiwode committed
483
    if parsed.fsr:
484
        opt.GREMIUM = GREMIUM_FSR
Dominik Woiwode's avatar
Dominik Woiwode committed
485
486

    if parsed.override:
487
        opt.OVERRIDE_ACCEPTED = True
Dominik Woiwode's avatar
Dominik Woiwode committed
488

489
490
    pads = PadCollection(CodiMD(parsed.pad))
    pads.addPads("unsorted", [PadCollection.parsePad(url, prefixes=parsed.prefixes) for url in urls])
Dominik Woiwode's avatar
Dominik Woiwode committed
491
492

    if parsed.newOnly:
493
        pads.removeApproved()
Dominik Woiwode's avatar
Dominik Woiwode committed
494
    if parsed.ignoreOld:
495
        pads.removeOld()
Dominik Woiwode's avatar
Dominik Woiwode committed
496
497

    if parsed.download:
498
        pads.downloadPads(opt.OVERRIDE_ACCEPTED)
Dominik Woiwode's avatar
Dominik Woiwode committed
499

500
501
    if parsed.topics:
        pads.createTopics()
Dominik Woiwode's avatar
Dominik Woiwode committed
502
503

    if parsed.compile:
504
        pads.compilePads()