mirror of
https://gitlab.com/chicken-riders/RcGcDb.git
synced 2025-02-23 00:54:09 +00:00
Merge branch 'wiki-rate-limiting'
# Conflicts: # src/formatters/discussions.py # src/i18n.py
This commit is contained in:
commit
2cea8a8724
|
@ -3,7 +3,6 @@ RcGcDb is a backend for handling webhooks to which recent changes of MediaWiki w
|
|||
|
||||
### Dependencies ###
|
||||
* **Python 3.6>**
|
||||
* requests 2.18.4>
|
||||
* beautifulsoup 4.6.0>
|
||||
* aiohttp 3.6.2>
|
||||
* lxml 4.2.1>
|
||||
|
|
BIN
locale/de/LC_MESSAGES/discord.mo
Normal file
BIN
locale/de/LC_MESSAGES/discord.mo
Normal file
Binary file not shown.
35
locale/de/LC_MESSAGES/discord.po
Normal file
35
locale/de/LC_MESSAGES/discord.po
Normal file
|
@ -0,0 +1,35 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the RcGcDd package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: RcGcDd\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 16:46+0200\n"
|
||||
"PO-Revision-Date: 2020-08-10 01:50+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3.1\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/discord.py:25
|
||||
msgid "wiki deletion"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:25 src/discord.py:26
|
||||
msgid "wiki becoming inaccessible"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:27
|
||||
msgid "unknown error"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:28
|
||||
msgid "The webhook for {} has been removed due to {}."
|
||||
msgstr ""
|
BIN
locale/de/LC_MESSAGES/discussion_formatters.mo
Normal file
BIN
locale/de/LC_MESSAGES/discussion_formatters.mo
Normal file
Binary file not shown.
171
locale/de/LC_MESSAGES/discussion_formatters.po
Normal file
171
locale/de/LC_MESSAGES/discussion_formatters.po
Normal file
|
@ -0,0 +1,171 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 16:45+0200\n"
|
||||
"PO-Revision-Date: 2020-08-10 16:41+0000\n"
|
||||
"Last-Translator: MarkusRost <sukramxro@gmail.com>\n"
|
||||
"Language-Team: German <https://weblate.frisk.space/projects/rcgcdw/"
|
||||
"discussion_formatters-1/de/>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.1.1\n"
|
||||
|
||||
#: src/formatters/discussions.py:21
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) erstellte [{title}](<{url}f/p/{threadId}>) in "
|
||||
"{forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:23
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) erstellte eine Umfrage [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:28
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) erstellte eine [Antwork](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) zu [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:30 src/formatters/discussions.py:38
|
||||
#: src/formatters/discussions.py:96 src/formatters/discussions.py:108
|
||||
msgid "unknown"
|
||||
msgstr "Unbekannt"
|
||||
|
||||
#: src/formatters/discussions.py:34
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}>) on [{user}'s Message Wall](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) erstellte [{title}](<{wikiurl}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}>) auf der [Nachrichtenseite von {user}]"
|
||||
"(<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
|
||||
#: src/formatters/discussions.py:36
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}#{replyId}>) to [{title}](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadId}) on [{user}'s Message Wall]"
|
||||
"(<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) erstellte eine [Antwort](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}#{replyId}>) auf [{title}](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadId}>) auf der [Nachrichtenseite von "
|
||||
"{user}](<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
|
||||
#: src/formatters/discussions.py:40
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [comment](<{url}wiki/{article}?"
|
||||
"threadId={threadId}>) on [{article}](<{url}wiki/{article}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) erstellte ein [Kommentar](<{url}wiki/{article}?"
|
||||
"commentId={commentId}>) zu [{article}](<{url}wiki/{article}>)"
|
||||
|
||||
#: src/formatters/discussions.py:42
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}wiki/{article}?"
|
||||
"threadId={threadId}) to a [comment](<{url}wiki/{article}?threadId={threadId}"
|
||||
"#{replyId}>) on [{article}](<{url}wiki/{article}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) erstellte eine [Antwort](<{url}wiki/{article}?"
|
||||
"threadId={threadId}>) auf ein [Kommentar](<{url}wiki/{article}?"
|
||||
"commentId={commentId}&replyId={replyId}>) zu [{article}](<{url}wiki/{article}"
|
||||
">)"
|
||||
|
||||
#: src/formatters/discussions.py:48
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Unknown event `{event}` by [{author}]({author_url}), report it on the "
|
||||
"[support server](<{support}>)."
|
||||
msgstr ""
|
||||
"Unbekanntes Event `{event}` von [{author}]({author_url}), melde es auf dem "
|
||||
"[Support-Server](<{support}>)."
|
||||
|
||||
#: src/formatters/discussions.py:74
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\""
|
||||
msgstr "Erstellte „{title}“"
|
||||
|
||||
#: src/formatters/discussions.py:79
|
||||
#, python-brace-format
|
||||
msgid "Created a poll \"{title}\""
|
||||
msgstr "Erstellte eine Umfrage „{title}“"
|
||||
|
||||
#: src/formatters/discussions.py:84
|
||||
msgid "Option {}"
|
||||
msgstr "Option {}"
|
||||
|
||||
#: src/formatters/discussions.py:85
|
||||
#, python-brace-format
|
||||
msgid "__[View image]({image_url})__"
|
||||
msgstr "__[Bild öffnen]({image_url})__"
|
||||
|
||||
#: src/formatters/discussions.py:93
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\""
|
||||
msgstr "Antwortete auf „{title}“"
|
||||
|
||||
#: src/formatters/discussions.py:102
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Erstellte „{title}“ auf der Nachrichtenseite von {user}"
|
||||
|
||||
#: src/formatters/discussions.py:106
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Antwortete auf „{title}“ auf der Nachrichtenseite von {user}"
|
||||
|
||||
#: src/formatters/discussions.py:112
|
||||
#, python-brace-format
|
||||
msgid "Commented on {article}"
|
||||
msgstr "Kommentierte zu „{article}“"
|
||||
|
||||
#: src/formatters/discussions.py:116
|
||||
#, python-brace-format
|
||||
msgid "Replied to a comment on {article}"
|
||||
msgstr "Antwortete auf ein Kommentar zu „{article}“"
|
||||
|
||||
#: src/formatters/discussions.py:120
|
||||
#, python-brace-format
|
||||
msgid "Unknown event `{event}`"
|
||||
msgstr "Unbekanntes Event `{event}`"
|
||||
|
||||
#: src/formatters/discussions.py:125 src/formatters/discussions.py:127
|
||||
msgid "Report this on the support server"
|
||||
msgstr "Melde es auf dem Support-Server"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid ""
|
||||
#~ "[{author}]({author_url}) created a quiz [{title}](<{url}f/p/{threadId}>) "
|
||||
#~ "in {forumName}"
|
||||
#~ msgstr ""
|
||||
#~ "[{author}]({author_url}) erstellte ein Quiz [{title}](<{url}f/p/{threadId}"
|
||||
#~ ">) in {forumName}"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "Created a quiz \"{title}\""
|
||||
#~ msgstr "Erstellte ein Quiz „{title}“"
|
Binary file not shown.
|
@ -1,105 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-04 00:58+0200\n"
|
||||
"PO-Revision-Date: 2020-07-04 01:04+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: discussions.py:56
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\""
|
||||
msgstr "Antwortete auf „{title}“"
|
||||
|
||||
#: discussions.py:63 discussions.py:79 discussions.py:127 discussions.py:143
|
||||
msgid "unknown"
|
||||
msgstr "Unbekannt"
|
||||
|
||||
#: discussions.py:68
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Antwortete auf „{title}“ auf der Nachrichtenseite von {user}"
|
||||
|
||||
#: discussions.py:72
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\""
|
||||
msgstr "Erstellte „{title}“"
|
||||
|
||||
#: discussions.py:86
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Erstellte „{title}“ auf der Nachrichtenseite von {user}"
|
||||
|
||||
#: discussions.py:99
|
||||
#, python-brace-format
|
||||
msgid "Created a poll titled \"{title}\""
|
||||
msgstr "Erstellte eine Umfrage „{title}“"
|
||||
|
||||
#: discussions.py:104
|
||||
msgid "Option {}"
|
||||
msgstr "Option {}"
|
||||
|
||||
#: discussions.py:105
|
||||
#, python-brace-format
|
||||
msgid "__[View image]({image_url})__"
|
||||
msgstr "__[Bild öffnen]({image_url})__"
|
||||
|
||||
#: discussions.py:121
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) erstellte [{title}](<{url}f/p/{threadId}"
|
||||
">) in {forumName}"
|
||||
|
||||
#: discussions.py:130
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}>) on {user}'s Message Wall"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) erstellte [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}>) auf der Nachrichtenseite von "
|
||||
"{user}"
|
||||
|
||||
#: discussions.py:136
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) erstellte eine [Antwork](<{url}f/p/"
|
||||
"{threadId}/r/{postId}>) zu [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
|
||||
#: discussions.py:147
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) replied to [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}#{replyId}>) on {user}'s Message "
|
||||
"Wall"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) antwortete auf [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}#{replyId}>) auf der "
|
||||
"Nachrichtenseite von {user}"
|
||||
|
||||
#: discussions.py:153
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) erstellte eine Umfrage [{title}](<{url}f/"
|
||||
"p/{threadId}>) in {forumName}"
|
Binary file not shown.
|
@ -1,24 +1,83 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-20 17:18+0200\n"
|
||||
"PO-Revision-Date: 2019-05-20 17:25+0200\n"
|
||||
"Language-Team: \n"
|
||||
"POT-Creation-Date: 2020-08-10 00:59+0200\n"
|
||||
"PO-Revision-Date: 2020-08-03 13:44+0000\n"
|
||||
"Last-Translator: MarkusRost <sukramxro@gmail.com>\n"
|
||||
"Language-Team: German <https://weblate.frisk.space/projects/rcgcdw/main/de/"
|
||||
">\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.1\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: de\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.1.1\n"
|
||||
"X-Loco-Source-Locale: de_DE\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Loco-Parser: loco_parse_po\n"
|
||||
|
||||
#: misc.py:76
|
||||
#: src/misc.py:96
|
||||
msgid "Location"
|
||||
msgstr "Wohnort"
|
||||
|
||||
#: src/misc.py:96
|
||||
msgid "About me"
|
||||
msgstr "„Über mich“-Abschnitt"
|
||||
|
||||
#: src/misc.py:97
|
||||
msgid "Google link"
|
||||
msgstr "Google-Link"
|
||||
|
||||
#: src/misc.py:97
|
||||
msgid "Facebook link"
|
||||
msgstr "Facebook-Link"
|
||||
|
||||
#: src/misc.py:98
|
||||
msgid "Twitter link"
|
||||
msgstr "Twitter-Link"
|
||||
|
||||
#: src/misc.py:98
|
||||
msgid "Reddit link"
|
||||
msgstr "Reddit-Link"
|
||||
|
||||
#: src/misc.py:99
|
||||
msgid "Twitch link"
|
||||
msgstr "Twitch-Link"
|
||||
|
||||
#: src/misc.py:99
|
||||
msgid "PSN link"
|
||||
msgstr "PSN-Link"
|
||||
|
||||
#: src/misc.py:100
|
||||
msgid "VK link"
|
||||
msgstr "VK-Link"
|
||||
|
||||
#: src/misc.py:100
|
||||
msgid "XBL link"
|
||||
msgstr "Xbox-Live-Link"
|
||||
|
||||
#: src/misc.py:101
|
||||
msgid "Steam link"
|
||||
msgstr "Steam-Link"
|
||||
|
||||
#: src/misc.py:101
|
||||
msgid "Discord handle"
|
||||
msgstr "Discord-Link"
|
||||
|
||||
#: src/misc.py:102
|
||||
msgid "Battle.net handle"
|
||||
msgstr "Battle.net-Link"
|
||||
|
||||
#: src/misc.py:108
|
||||
msgid "Unknown"
|
||||
msgstr "Unbekannt"
|
||||
|
||||
#: src/misc.py:110
|
||||
msgid "unknown"
|
||||
msgstr "unbekannt"
|
||||
|
||||
#: src/misc.py:121
|
||||
msgid ""
|
||||
"\n"
|
||||
"__And more__"
|
||||
|
|
BIN
locale/de/LC_MESSAGES/rc_formatters.mo
Normal file
BIN
locale/de/LC_MESSAGES/rc_formatters.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
BIN
locale/de/LC_MESSAGES/wiki.mo
Normal file
BIN
locale/de/LC_MESSAGES/wiki.mo
Normal file
Binary file not shown.
37
locale/de/LC_MESSAGES/wiki.po
Normal file
37
locale/de/LC_MESSAGES/wiki.po
Normal file
|
@ -0,0 +1,37 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 01:01+0200\n"
|
||||
"PO-Revision-Date: 2020-08-03 13:44+0000\n"
|
||||
"Last-Translator: MarkusRost <sukramxro@gmail.com>\n"
|
||||
"Language-Team: German <https://weblate.frisk.space/projects/rcgcdw/main/de/"
|
||||
">\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.1.1\n"
|
||||
"X-Loco-Source-Locale: de_DE\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Loco-Parser: loco_parse_po\n"
|
||||
|
||||
#: src/wiki.py:207
|
||||
msgid "~~hidden~~"
|
||||
msgstr "~~versteckt~~"
|
||||
|
||||
#: src/wiki.py:212
|
||||
msgid "hidden"
|
||||
msgstr "versteckt"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "Connection to {wiki} seems to be stable now."
|
||||
#~ msgstr "{wiki} scheint wieder erreichbar zu sein."
|
||||
|
||||
#~ msgid "Connection status"
|
||||
#~ msgstr "Verbindungsstatus"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "{wiki} seems to be down or unreachable."
|
||||
#~ msgstr "Das {wiki} scheint unerreichbar zu sein."
|
Binary file not shown.
|
@ -1,90 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-06-23 14:54+0200\n"
|
||||
"PO-Revision-Date: 2020-06-23 14:57+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: discussions.py:56
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\""
|
||||
msgstr "Replied to \"{title}\""
|
||||
|
||||
#: discussions.py:63 discussions.py:79
|
||||
msgid "unknown"
|
||||
msgstr "unknown"
|
||||
|
||||
#: discussions.py:68
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
|
||||
#: discussions.py:72
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\""
|
||||
msgstr "Created \"{title}\""
|
||||
|
||||
#: discussions.py:86
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Created \"{title}\" on {user}'s Message Wall"
|
||||
|
||||
#: discussions.py:99
|
||||
#, python-brace-format
|
||||
msgid "Created a poll titled \"{title}\""
|
||||
msgstr "Created a poll titled \"{title}\""
|
||||
|
||||
#: discussions.py:104
|
||||
msgid "Option {}"
|
||||
msgstr "Option {}"
|
||||
|
||||
#: discussions.py:105
|
||||
#, python-brace-format
|
||||
msgid "__[View image]({image_url})__"
|
||||
msgstr "__[View image]({image_url})__"
|
||||
|
||||
#: discussions.py:118
|
||||
#, python-brace-format
|
||||
#| msgid ""
|
||||
#| "[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}"
|
||||
#| ">) in ${forumName}"
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
|
||||
#: discussions.py:121
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
|
||||
#: discussions.py:126
|
||||
#, python-brace-format
|
||||
#| msgid ""
|
||||
#| "[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}"
|
||||
#| ">) in ${forumName}"
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
Binary file not shown.
|
@ -1,27 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-20 17:18+0200\n"
|
||||
"PO-Revision-Date: 2019-05-20 17:32+0200\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.1\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Language: en\n"
|
||||
|
||||
#: misc.py:76
|
||||
msgid ""
|
||||
"\n"
|
||||
"__And more__"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"__And more__"
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
BIN
locale/pl/LC_MESSAGES/discord.mo
Normal file
BIN
locale/pl/LC_MESSAGES/discord.mo
Normal file
Binary file not shown.
36
locale/pl/LC_MESSAGES/discord.po
Normal file
36
locale/pl/LC_MESSAGES/discord.po
Normal file
|
@ -0,0 +1,36 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the RcGcDd package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: RcGcDd\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 16:46+0200\n"
|
||||
"PO-Revision-Date: 2020-08-10 01:55+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3.1\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 "
|
||||
"|| n%100>14) ? 1 : 2);\n"
|
||||
|
||||
#: src/discord.py:25
|
||||
msgid "wiki deletion"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:25 src/discord.py:26
|
||||
msgid "wiki becoming inaccessible"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:27
|
||||
msgid "unknown error"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:28
|
||||
msgid "The webhook for {} has been removed due to {}."
|
||||
msgstr ""
|
BIN
locale/pl/LC_MESSAGES/discussion_formatters.mo
Normal file
BIN
locale/pl/LC_MESSAGES/discussion_formatters.mo
Normal file
Binary file not shown.
175
locale/pl/LC_MESSAGES/discussion_formatters.po
Normal file
175
locale/pl/LC_MESSAGES/discussion_formatters.po
Normal file
|
@ -0,0 +1,175 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 16:45+0200\n"
|
||||
"PO-Revision-Date: 2020-08-10 16:41+0000\n"
|
||||
"Last-Translator: Frisk The Evil Goat Overlord <piotrex43@protonmail.ch>\n"
|
||||
"Language-Team: Polish <https://weblate.frisk.space/projects/rcgcdw/"
|
||||
"discussion_formatters-1/pl/>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.1.1\n"
|
||||
|
||||
#: src/formatters/discussions.py:21
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) utworzył(a) [{title}](<{url}f/p/{threadId}>) w "
|
||||
"{forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:23
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) utworzył(a) ankietę [{title}](<{url}f/p/{threadId}"
|
||||
">) w {forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:28
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) utworzył(a) [odpowiedź](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) pod tematem [{title}](<{url}f/p/{threadId}>) w {forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:30 src/formatters/discussions.py:38
|
||||
#: src/formatters/discussions.py:96 src/formatters/discussions.py:108
|
||||
msgid "unknown"
|
||||
msgstr "nieznany"
|
||||
|
||||
#: src/formatters/discussions.py:34
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}>) on [{user}'s Message Wall](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) utworzył(a) [{title}](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}>) na [tablicy wiadomości użytkownika/"
|
||||
"użytkowniczki {user}](<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
|
||||
#: src/formatters/discussions.py:36
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}#{replyId}>) to [{title}](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadId}) on [{user}'s Message Wall]"
|
||||
"(<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) stworzył(-a) [odpowiedź](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}#{replyId}>) do [{title}](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadId}>) na [tablicy wiadomości {user}]"
|
||||
"(<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
|
||||
#: src/formatters/discussions.py:40
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [comment](<{url}wiki/{article}?"
|
||||
"threadId={threadId}>) on [{article}](<{url}wiki/{article}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) utworzył(-a) [komentarz](<{url}wiki/{article}?"
|
||||
"commentId={commentId}>) w [{article}](<{url}wiki/{article}>)"
|
||||
|
||||
#: src/formatters/discussions.py:42
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}wiki/{article}?"
|
||||
"threadId={threadId}) to a [comment](<{url}wiki/{article}?threadId={threadId}"
|
||||
"#{replyId}>) on [{article}](<{url}wiki/{article}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) utworzył(-a) [odpowiedź](<{url}wiki/{article}?"
|
||||
"threadId={threadId}) na [komentarz](<{url}wiki/{article}?"
|
||||
"commentId={commentId}&replyId={replyId}>) w artykule [{article}](<{url}wiki/"
|
||||
"{article}>)"
|
||||
|
||||
#: src/formatters/discussions.py:48
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Unknown event `{event}` by [{author}]({author_url}), report it on the "
|
||||
"[support server](<{support}>)."
|
||||
msgstr ""
|
||||
"Nieznane wydarzenie `{event}` wykonane przez [{author}]({author_url}), zgłoś "
|
||||
"je na [serwerze wsparcia](<{support}>)."
|
||||
|
||||
#: src/formatters/discussions.py:74
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\""
|
||||
msgstr "Utworzył(a) „{title}”"
|
||||
|
||||
#: src/formatters/discussions.py:79
|
||||
#, python-brace-format
|
||||
msgid "Created a poll \"{title}\""
|
||||
msgstr "Utworzył(a) ankietę zatytułowaną „{title}”"
|
||||
|
||||
#: src/formatters/discussions.py:84
|
||||
msgid "Option {}"
|
||||
msgstr "Opcja {}"
|
||||
|
||||
#: src/formatters/discussions.py:85
|
||||
#, python-brace-format
|
||||
msgid "__[View image]({image_url})__"
|
||||
msgstr "__[Zobacz zdjęcie]({image_url})__"
|
||||
|
||||
#: src/formatters/discussions.py:93
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\""
|
||||
msgstr "Odpowiedział(a) w „{title}”"
|
||||
|
||||
#: src/formatters/discussions.py:102
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\" on {user}'s Message Wall"
|
||||
msgstr ""
|
||||
"Utworzył(a) „{title}” na tablicy wiadomości użytkownika/użytkowniczki {user}"
|
||||
|
||||
#: src/formatters/discussions.py:106
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
msgstr ""
|
||||
"Odpowiedział(a) na „{title}” z tablicy wiadomości użytkownika/użytkowniczki "
|
||||
"{user}"
|
||||
|
||||
#: src/formatters/discussions.py:112
|
||||
#, python-brace-format
|
||||
msgid "Commented on {article}"
|
||||
msgstr "Skomentował(a) „{article}”"
|
||||
|
||||
#: src/formatters/discussions.py:116
|
||||
#, python-brace-format
|
||||
msgid "Replied to a comment on {article}"
|
||||
msgstr "Odpowiedział(a) na komentarz w „{article}”"
|
||||
|
||||
#: src/formatters/discussions.py:120
|
||||
#, python-brace-format
|
||||
msgid "Unknown event `{event}`"
|
||||
msgstr "Nieznane wydarzenie `{event}`"
|
||||
|
||||
#: src/formatters/discussions.py:125 src/formatters/discussions.py:127
|
||||
msgid "Report this on the support server"
|
||||
msgstr "Zgłoś to na serwerze wsparcia"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid ""
|
||||
#~ "[{author}]({author_url}) created a quiz [{title}](<{url}f/p/{threadId}>) "
|
||||
#~ "in {forumName}"
|
||||
#~ msgstr ""
|
||||
#~ "[{author}]({author_url}) utworzył(a) quiz [{title}](<{url}f/p/{threadId}"
|
||||
#~ ">) w {forumName}"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "Created a quiz \"{title}\""
|
||||
#~ msgstr "Utworzył(a) quiz „{title}”"
|
Binary file not shown.
|
@ -1,110 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-04 00:58+0200\n"
|
||||
"PO-Revision-Date: 2020-07-04 01:12+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 "
|
||||
"|| n%100>14) ? 1 : 2);\n"
|
||||
|
||||
#: discussions.py:56
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\""
|
||||
msgstr "Odpowiedział(a) w „{title}”"
|
||||
|
||||
#: discussions.py:63 discussions.py:79 discussions.py:127 discussions.py:143
|
||||
msgid "unknown"
|
||||
msgstr "nieznany"
|
||||
|
||||
#: discussions.py:68
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
msgstr ""
|
||||
"Odpowiedział(a) na „{title}” z tablicy wiadomości użytkownika/użytkowniczki "
|
||||
"{user}"
|
||||
|
||||
#: discussions.py:72
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\""
|
||||
msgstr "Utworzył(a) „{title}”"
|
||||
|
||||
#: discussions.py:86
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\" on {user}'s Message Wall"
|
||||
msgstr ""
|
||||
"Utworzył(a) „{title}” na tablicy wiadomości użytkownika/użytkowniczki {user}"
|
||||
|
||||
#: discussions.py:99
|
||||
#, python-brace-format
|
||||
msgid "Created a poll titled \"{title}\""
|
||||
msgstr "Utworzył(a) ankietę zatytułowaną „{title}”"
|
||||
|
||||
#: discussions.py:104
|
||||
msgid "Option {}"
|
||||
msgstr "Opcja {}"
|
||||
|
||||
#: discussions.py:105
|
||||
#, python-brace-format
|
||||
msgid "__[View image]({image_url})__"
|
||||
msgstr "__[Zobacz zdjęcie]({image_url})__"
|
||||
|
||||
#: discussions.py:121
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) utworzył(a) [{title}](<{url}f/p/{threadId}"
|
||||
">) w {forumName}"
|
||||
|
||||
#: discussions.py:130
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}>) on {user}'s Message Wall"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) utworzył(a) [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}>) na tablicy wiadomości "
|
||||
"użytkownika/użytkowniczki {user}"
|
||||
|
||||
#: discussions.py:136
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) utworzył(a) [odpowiedź](<{url}f/p/"
|
||||
"{threadId}/r/{postId}>) pod tematem [{title}](<{url}f/p/{threadId}>) w "
|
||||
"{forumName}"
|
||||
|
||||
#: discussions.py:147
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) replied to [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}#{replyId}>) on {user}'s Message "
|
||||
"Wall"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) odpowiedział(a) na[{title}](<{wikiurl}"
|
||||
"wiki/Message_Wall:{user_wall}?threadId={threadid}#{replyId}>) na tablicy "
|
||||
"wiadomości użytkownika/użytkowniczki {user}"
|
||||
|
||||
#: discussions.py:153
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) utworzył(a) ankietę [{title}](<{url}f/p/"
|
||||
"{threadId}>) w {forumName}"
|
Binary file not shown.
|
@ -1,24 +1,85 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Copyright (C) YEAR ORGANIZATION
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Project-Id-Version: RcGcDw\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-20 17:18+0200\n"
|
||||
"PO-Revision-Date: 2019-05-20 17:23+0200\n"
|
||||
"POT-Creation-Date: 2020-08-10 00:59+0200\n"
|
||||
"PO-Revision-Date: 2020-03-17 20:57+0100\n"
|
||||
"Last-Translator: Frisk <piotrex43@protonmail.ch>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.1\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
|
||||
"Language: pl\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: misc.py:76
|
||||
#: src/misc.py:96
|
||||
msgid "Location"
|
||||
msgstr "Lokacja"
|
||||
|
||||
#: src/misc.py:96
|
||||
msgid "About me"
|
||||
msgstr "O mnie"
|
||||
|
||||
#: src/misc.py:97
|
||||
msgid "Google link"
|
||||
msgstr "link Google"
|
||||
|
||||
#: src/misc.py:97
|
||||
msgid "Facebook link"
|
||||
msgstr "link Facebook"
|
||||
|
||||
#: src/misc.py:98
|
||||
msgid "Twitter link"
|
||||
msgstr "link Twitter"
|
||||
|
||||
#: src/misc.py:98
|
||||
msgid "Reddit link"
|
||||
msgstr "link Reddit"
|
||||
|
||||
#: src/misc.py:99
|
||||
msgid "Twitch link"
|
||||
msgstr "link Twitch"
|
||||
|
||||
#: src/misc.py:99
|
||||
msgid "PSN link"
|
||||
msgstr "link PSN"
|
||||
|
||||
#: src/misc.py:100
|
||||
msgid "VK link"
|
||||
msgstr "link VK"
|
||||
|
||||
#: src/misc.py:100
|
||||
msgid "XBL link"
|
||||
msgstr "link XBL"
|
||||
|
||||
#: src/misc.py:101
|
||||
msgid "Steam link"
|
||||
msgstr "link Steam"
|
||||
|
||||
#: src/misc.py:101
|
||||
msgid "Discord handle"
|
||||
msgstr "konto Discord"
|
||||
|
||||
#: src/misc.py:102
|
||||
msgid "Battle.net handle"
|
||||
msgstr "konto Battle.net"
|
||||
|
||||
#: src/misc.py:108
|
||||
msgid "Unknown"
|
||||
msgstr "Nieznana"
|
||||
|
||||
#: src/misc.py:110
|
||||
msgid "unknown"
|
||||
msgstr "nieznana sekcja"
|
||||
|
||||
#: src/misc.py:121
|
||||
msgid ""
|
||||
"\n"
|
||||
"__And more__"
|
||||
|
|
BIN
locale/pl/LC_MESSAGES/rc_formatters.mo
Normal file
BIN
locale/pl/LC_MESSAGES/rc_formatters.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
BIN
locale/pl/LC_MESSAGES/wiki.mo
Normal file
BIN
locale/pl/LC_MESSAGES/wiki.mo
Normal file
Binary file not shown.
39
locale/pl/LC_MESSAGES/wiki.po
Normal file
39
locale/pl/LC_MESSAGES/wiki.po
Normal file
|
@ -0,0 +1,39 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR ORGANIZATION
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: RcGcDw\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 01:01+0200\n"
|
||||
"PO-Revision-Date: 2020-03-17 20:57+0100\n"
|
||||
"Last-Translator: Frisk <piotrex43@protonmail.ch>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: src/wiki.py:207
|
||||
msgid "~~hidden~~"
|
||||
msgstr "~~ukryte~~"
|
||||
|
||||
#: src/wiki.py:212
|
||||
msgid "hidden"
|
||||
msgstr "ukryte"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "Connection to {wiki} seems to be stable now."
|
||||
#~ msgstr "Połączenie z {wiki} wygląda na stabilne."
|
||||
|
||||
#~ msgid "Connection status"
|
||||
#~ msgstr "Problem z połączeniem"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "{wiki} seems to be down or unreachable."
|
||||
#~ msgstr "{wiki} nie działa lub jest nieosiągalna."
|
BIN
locale/pt-br/LC_MESSAGES/discord.mo
Normal file
BIN
locale/pt-br/LC_MESSAGES/discord.mo
Normal file
Binary file not shown.
35
locale/pt-br/LC_MESSAGES/discord.po
Normal file
35
locale/pt-br/LC_MESSAGES/discord.po
Normal file
|
@ -0,0 +1,35 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the RcGcDd package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: RcGcDd\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 16:46+0200\n"
|
||||
"PO-Revision-Date: 2020-08-10 01:53+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3.1\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: src/discord.py:25
|
||||
msgid "wiki deletion"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:25 src/discord.py:26
|
||||
msgid "wiki becoming inaccessible"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:27
|
||||
msgid "unknown error"
|
||||
msgstr ""
|
||||
|
||||
#: src/discord.py:28
|
||||
msgid "The webhook for {} has been removed due to {}."
|
||||
msgstr ""
|
BIN
locale/pt-br/LC_MESSAGES/discussion_formatters.mo
Normal file
BIN
locale/pt-br/LC_MESSAGES/discussion_formatters.mo
Normal file
Binary file not shown.
168
locale/pt-br/LC_MESSAGES/discussion_formatters.po
Normal file
168
locale/pt-br/LC_MESSAGES/discussion_formatters.po
Normal file
|
@ -0,0 +1,168 @@
|
|||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Frisk <piotrex43@protonmail.ch>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 16:45+0200\n"
|
||||
"PO-Revision-Date: 2020-08-10 14:11+0000\n"
|
||||
"Last-Translator: Eduaddad <duduaddad@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://weblate.frisk.space/projects/"
|
||||
"rcgcdw/discussion_formatters-1/pt_BR/>\n"
|
||||
"Language: pt-br\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Weblate 4.1.1\n"
|
||||
|
||||
#: src/formatters/discussions.py:21
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
msgstr ""
|
||||
"Criado [{title}](<{url}f/p/{threadId}>) por [{author}](<{url}f/u/{creatorId}"
|
||||
">) no {forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:23
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}](<{url}f/u/{creatorId}>)criou uma enquete [{title}](<{url}f/p/"
|
||||
"{threadId}>) no {forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:28
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) criou uma [resposta](<{url}f/p/{threadId}/r/{postId}"
|
||||
">) para [{title}](<{url}f/p/{threadId}>) em {forumName}"
|
||||
|
||||
#: src/formatters/discussions.py:30 src/formatters/discussions.py:38
|
||||
#: src/formatters/discussions.py:96 src/formatters/discussions.py:108
|
||||
msgid "unknown"
|
||||
msgstr "desconhecido"
|
||||
|
||||
#: src/formatters/discussions.py:34
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}>) on [{user}'s Message Wall](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) criou [{title}](<{url}wiki/Message_Wall:{user_wall}?"
|
||||
"threadId={threadId}>) no mural de mensagens de [{user}(<{url}wiki/"
|
||||
"Message_Wall:{user_wall}>)"
|
||||
|
||||
#: src/formatters/discussions.py:36
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}#{replyId}>) to [{title}](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadId}) on [{user}'s Message Wall]"
|
||||
"(<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) criou uma [resposta](<{url}wiki/Message_Wall:"
|
||||
"{user_wall}?threadId={threadId}#{replyId}>) para [{title}](<{url}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadId}>) no mural de mensagens de "
|
||||
"[{user}](<{url}wiki/Message_Wall:{user_wall}>)"
|
||||
|
||||
#: src/formatters/discussions.py:40
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [comment](<{url}wiki/{article}?"
|
||||
"threadId={threadId}>) on [{article}](<{url}wiki/{article}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url})criou um [comentário](<{url}wiki/{article}?"
|
||||
"commentId={commentId}>) no [{article}](<{url}wiki/{article}>)"
|
||||
|
||||
#: src/formatters/discussions.py:42
|
||||
#, fuzzy, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}wiki/{article}?"
|
||||
"threadId={threadId}) to a [comment](<{url}wiki/{article}?threadId={threadId}"
|
||||
"#{replyId}>) on [{article}](<{url}wiki/{article}>)"
|
||||
msgstr ""
|
||||
"[{author}]({author_url}) criou uma [resposta](<{url}wiki/{article}?"
|
||||
"threadId={threadId}) para um [comentário](<{url}wiki/{article}?"
|
||||
"commentId={commentId}&replyId={replyId}>) no [{article}](<{url}wiki/{article}"
|
||||
">)"
|
||||
|
||||
#: src/formatters/discussions.py:48
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Unknown event `{event}` by [{author}]({author_url}), report it on the "
|
||||
"[support server](<{support}>)."
|
||||
msgstr ""
|
||||
|
||||
#: src/formatters/discussions.py:74
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\""
|
||||
msgstr "Criado \"{title}\""
|
||||
|
||||
#: src/formatters/discussions.py:79
|
||||
#, python-brace-format
|
||||
msgid "Created a poll \"{title}\""
|
||||
msgstr "Criou uma enquete \"{title}\""
|
||||
|
||||
#: src/formatters/discussions.py:84
|
||||
msgid "Option {}"
|
||||
msgstr "Option {}"
|
||||
|
||||
#: src/formatters/discussions.py:85
|
||||
#, python-brace-format
|
||||
msgid "__[View image]({image_url})__"
|
||||
msgstr "__[Ver imagem]({image_url})__"
|
||||
|
||||
#: src/formatters/discussions.py:93
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\""
|
||||
msgstr "Respondido o \"{title}\""
|
||||
|
||||
#: src/formatters/discussions.py:102
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Criado \"{title}\" no mural de mensagem de {user}"
|
||||
|
||||
#: src/formatters/discussions.py:106
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Respondeu a \"{title}\" no mural de mensagem de {user}"
|
||||
|
||||
#: src/formatters/discussions.py:112
|
||||
#, python-brace-format
|
||||
msgid "Commented on {article}"
|
||||
msgstr "Comentou em {article}"
|
||||
|
||||
#: src/formatters/discussions.py:116
|
||||
#, python-brace-format
|
||||
msgid "Replied to a comment on {article}"
|
||||
msgstr "Respondeu a um comentário em {article}"
|
||||
|
||||
#: src/formatters/discussions.py:120
|
||||
#, python-brace-format
|
||||
msgid "Unknown event `{event}`"
|
||||
msgstr ""
|
||||
|
||||
#: src/formatters/discussions.py:125 src/formatters/discussions.py:127
|
||||
msgid "Report this on the support server"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy, python-brace-format
|
||||
#~ msgid ""
|
||||
#~ "[{author}]({author_url}) created a quiz [{title}](<{url}f/p/{threadId}>) "
|
||||
#~ "in {forumName}"
|
||||
#~ msgstr ""
|
||||
#~ "[{author}](<{url}f/u/{creatorId}>)criou uma enquete [{title}](<{url}f/p/"
|
||||
#~ "{threadId}>) no {forumName}"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "Created a quiz \"{title}\""
|
||||
#~ msgstr "Criou uma enquete \"{title}\""
|
Binary file not shown.
|
@ -1,106 +0,0 @@
|
|||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Frisk <piotrex43@protonmail.ch>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-07-04 00:58+0200\n"
|
||||
"PO-Revision-Date: 2020-07-04 01:09+0200\n"
|
||||
"Last-Translator: Frisk <piotrex43@protonmail.ch>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: en_US\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
|
||||
#: discussions.py:56
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\""
|
||||
msgstr "Respondido o \"{title}\""
|
||||
|
||||
#: discussions.py:63 discussions.py:79 discussions.py:127 discussions.py:143
|
||||
msgid "unknown"
|
||||
msgstr "desconhecido"
|
||||
|
||||
#: discussions.py:68
|
||||
#, python-brace-format
|
||||
msgid "Replied to \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Respondeu a \"{title}\" no mural de mensagem de {user}"
|
||||
|
||||
#: discussions.py:72
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\""
|
||||
msgstr "Criado \"{title}\""
|
||||
|
||||
#: discussions.py:86
|
||||
#, python-brace-format
|
||||
msgid "Created \"{title}\" on {user}'s Message Wall"
|
||||
msgstr "Criado \"{title}\" no mural de mensagem de {user}"
|
||||
|
||||
#: discussions.py:99
|
||||
#, python-brace-format
|
||||
msgid "Created a poll titled \"{title}\""
|
||||
msgstr ""
|
||||
|
||||
#: discussions.py:104
|
||||
msgid "Option {}"
|
||||
msgstr ""
|
||||
|
||||
#: discussions.py:105
|
||||
#, python-brace-format
|
||||
msgid "__[View image]({image_url})__"
|
||||
msgstr ""
|
||||
|
||||
#: discussions.py:121
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}>) "
|
||||
"in {forumName}"
|
||||
msgstr ""
|
||||
"Criado [{title}](<{url}f/p/{threadId}>) por [{author}](<{url}f/u/{creatorId}"
|
||||
">) no {forumName}"
|
||||
|
||||
#: discussions.py:130
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid ""
|
||||
#| "[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}"
|
||||
#| ">) in {forumName}"
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}>) on {user}'s Message Wall"
|
||||
msgstr ""
|
||||
"Criado [{title}](<{url}f/p/{threadId}>) por [{author}](<{url}f/u/{creatorId}"
|
||||
">) no {forumName}"
|
||||
|
||||
#: discussions.py:136
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a [reply](<{url}f/p/{threadId}/r/"
|
||||
"{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msgstr ""
|
||||
"[Responder](<{url}f/p/{threadId}/r/{postId}>) por [{author}](<{url}f/u/"
|
||||
"{creatorId}>) do [{title}](<{url}f/p/{threadId}>) do {forumName}"
|
||||
|
||||
#: discussions.py:147
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid ""
|
||||
#| "[{author}](<{url}f/u/{creatorId}>) created [{title}](<{url}f/p/{threadId}"
|
||||
#| ">) in {forumName}"
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) replied to [{title}](<{wikiurl}wiki/"
|
||||
"Message_Wall:{user_wall}?threadId={threadid}#{replyId}>) on {user}'s Message "
|
||||
"Wall"
|
||||
msgstr ""
|
||||
"Criado [{title}](<{url}f/p/{threadId}>) por [{author}](<{url}f/u/{creatorId}"
|
||||
">) no {forumName}"
|
||||
|
||||
#: discussions.py:153
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"[{author}](<{url}f/u/{creatorId}>) created a poll [{title}](<{url}f/p/"
|
||||
"{threadId}>) in {forumName}"
|
||||
msgstr ""
|
Binary file not shown.
|
@ -7,18 +7,79 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-20 17:18+0200\n"
|
||||
"PO-Revision-Date: 2019-05-21 01:22+0200\n"
|
||||
"Language-Team: \n"
|
||||
"POT-Creation-Date: 2020-08-10 00:59+0200\n"
|
||||
"PO-Revision-Date: 2020-08-04 09:51+0000\n"
|
||||
"Last-Translator: Eduaddad <duduaddad@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://weblate.frisk.space/projects/"
|
||||
"rcgcdw/main/pt_BR/>\n"
|
||||
"Language: pt-br\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.2.1\n"
|
||||
"Last-Translator: \n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"Language: pt\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.1.1\n"
|
||||
|
||||
#: misc.py:76
|
||||
#: src/misc.py:96
|
||||
msgid "Location"
|
||||
msgstr "Localização"
|
||||
|
||||
#: src/misc.py:96
|
||||
msgid "About me"
|
||||
msgstr "Sobre mim"
|
||||
|
||||
#: src/misc.py:97
|
||||
msgid "Google link"
|
||||
msgstr "Link do Google"
|
||||
|
||||
#: src/misc.py:97
|
||||
msgid "Facebook link"
|
||||
msgstr "Facebook link"
|
||||
|
||||
#: src/misc.py:98
|
||||
msgid "Twitter link"
|
||||
msgstr "Link do Twitter"
|
||||
|
||||
#: src/misc.py:98
|
||||
msgid "Reddit link"
|
||||
msgstr "Link do Reddit"
|
||||
|
||||
#: src/misc.py:99
|
||||
msgid "Twitch link"
|
||||
msgstr "Link do Twitch"
|
||||
|
||||
#: src/misc.py:99
|
||||
msgid "PSN link"
|
||||
msgstr "Link do PSN"
|
||||
|
||||
#: src/misc.py:100
|
||||
msgid "VK link"
|
||||
msgstr "Link do VK"
|
||||
|
||||
#: src/misc.py:100
|
||||
msgid "XBL link"
|
||||
msgstr "Link do XBL"
|
||||
|
||||
#: src/misc.py:101
|
||||
msgid "Steam link"
|
||||
msgstr "Link do Steam"
|
||||
|
||||
#: src/misc.py:101
|
||||
msgid "Discord handle"
|
||||
msgstr "Link do Discord"
|
||||
|
||||
#: src/misc.py:102
|
||||
msgid "Battle.net handle"
|
||||
msgstr "Link do Battle.net"
|
||||
|
||||
#: src/misc.py:108
|
||||
msgid "Unknown"
|
||||
msgstr "Desconhecido"
|
||||
|
||||
#: src/misc.py:110
|
||||
msgid "unknown"
|
||||
msgstr "desconhecido"
|
||||
|
||||
#: src/misc.py:121
|
||||
msgid ""
|
||||
"\n"
|
||||
"__And more__"
|
||||
|
|
BIN
locale/pt-br/LC_MESSAGES/rc_formatters.mo
Normal file
BIN
locale/pt-br/LC_MESSAGES/rc_formatters.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
BIN
locale/pt-br/LC_MESSAGES/wiki.mo
Normal file
BIN
locale/pt-br/LC_MESSAGES/wiki.mo
Normal file
Binary file not shown.
39
locale/pt-br/LC_MESSAGES/wiki.po
Normal file
39
locale/pt-br/LC_MESSAGES/wiki.po
Normal file
|
@ -0,0 +1,39 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-10 01:01+0200\n"
|
||||
"PO-Revision-Date: 2020-08-04 09:51+0000\n"
|
||||
"Last-Translator: Eduaddad <duduaddad@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://weblate.frisk.space/projects/"
|
||||
"rcgcdw/main/pt_BR/>\n"
|
||||
"Language: pt-br\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.1.1\n"
|
||||
|
||||
#: src/wiki.py:207
|
||||
msgid "~~hidden~~"
|
||||
msgstr "~~ocultado~~"
|
||||
|
||||
#: src/wiki.py:212
|
||||
msgid "hidden"
|
||||
msgstr "oculto"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "Connection to {wiki} seems to be stable now."
|
||||
#~ msgstr "A conexão com {wiki} parece estar estável agora."
|
||||
|
||||
#~ msgid "Connection status"
|
||||
#~ msgstr "Status da conexão"
|
||||
|
||||
#, python-brace-format
|
||||
#~ msgid "{wiki} seems to be down or unreachable."
|
||||
#~ msgstr "{wiki} parece estar inativo ou inacessível."
|
|
@ -1,4 +1,3 @@
|
|||
beautifulsoup4 >= 4.6.0; python_version >= '3.6'
|
||||
requests >= 2.18.4
|
||||
aiohttp >= 3.6.2
|
||||
lxml >= 4.2.1
|
18
scripts/generate_translations.sh
Normal file
18
scripts/generate_translations.sh
Normal file
|
@ -0,0 +1,18 @@
|
|||
cd ..
|
||||
xgettext -L Python --package-name=RcGcDb -o locale/templates/discussion_formatters.pot src/formatters/discussions.py
|
||||
xgettext -L Python --package-name=RcGcDb -o locale/templates/rc_formatters.pot src/formatters/rc.py
|
||||
xgettext -L Python --package-name=RcGcDb -o locale/templates/wiki.pot src/wiki.py
|
||||
xgettext -L Python --package-name=RcGcDb -o locale/templates/discord.pot src/discord.py
|
||||
xgettext -L Python --package-name=RcGcDb -o locale/templates/misc.pot src/misc.py
|
||||
|
||||
declare -a StringArray=("discussion_formatters" "rc_formatters" "discord" "wiki" "misc")
|
||||
for language in de pl pt-br
|
||||
do
|
||||
for file in ${StringArray[@]}; do
|
||||
msgmerge -U locale/$language/LC_MESSAGES/$file.po locale/templates/$file.pot
|
||||
done
|
||||
msgmerge -o locale/$language/LC_MESSAGES/discussion_formatters.po ~/PycharmProjects/RcGcDw/locale/$language/LC_MESSAGES/discussion_formatters.po locale/$language/LC_MESSAGES/discussion_formatters.po
|
||||
msgmerge -o locale/$language/LC_MESSAGES/rc_formatters.po ~/PycharmProjects/RcGcDw/locale/$language/LC_MESSAGES/rc_formatters.po locale/$language/LC_MESSAGES/rc_formatters.po
|
||||
msgmerge -o locale/$language/LC_MESSAGES/wiki.po ~/PycharmProjects/RcGcDw/locale/$language/LC_MESSAGES/rc.po locale/$language/LC_MESSAGES/wiki.po
|
||||
msgmerge -o locale/$language/LC_MESSAGES/misc.po ~/PycharmProjects/RcGcDw/locale/$language/LC_MESSAGES/misc.po locale/$language/LC_MESSAGES/misc.po
|
||||
done
|
337
src/bot.py
337
src/bot.py
|
@ -2,21 +2,21 @@ import aiohttp
|
|||
import asyncio
|
||||
import logging.config
|
||||
import signal
|
||||
import sys
|
||||
import traceback
|
||||
from collections import defaultdict
|
||||
|
||||
import requests
|
||||
from collections import defaultdict, namedtuple
|
||||
from typing import Generator
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
from src.argparser import command_line_args
|
||||
from src.config import settings
|
||||
from src.database import db_cursor
|
||||
from src.exceptions import *
|
||||
from src.misc import get_paths
|
||||
from src.misc import get_paths, get_domain
|
||||
from src.msgqueue import messagequeue
|
||||
from src.queue_handler import DBHandler
|
||||
from src.wiki import Wiki, process_cats, process_mwmsgs, essential_info, essential_feeds
|
||||
from src.discord import DiscordMessage, formatter_exception_logger, msg_sender_exception_logger
|
||||
from src.discord import DiscordMessage, generic_msg_sender_exception_logger
|
||||
from src.wiki_ratelimiter import RateLimiter
|
||||
|
||||
logging.config.dictConfig(settings["logging"])
|
||||
logger = logging.getLogger("rcgcdb.bot")
|
||||
|
@ -34,20 +34,135 @@ mw_msgs: dict = {} # will have the type of id: tuple
|
|||
# Reasons for this: 1. we require amount of wikis to calculate the cooldown between requests
|
||||
# 2. Easier to code
|
||||
|
||||
for wiki in db_cursor.execute('SELECT DISTINCT wiki FROM rcgcdw'):
|
||||
all_wikis[wiki] = Wiki()
|
||||
for db_wiki in db_cursor.execute('SELECT wiki, rcid FROM rcgcdw GROUP BY wiki ORDER BY ROWID'):
|
||||
all_wikis[db_wiki["wiki"]] = Wiki() # populate all_wikis
|
||||
all_wikis[db_wiki["wiki"]].rc_active = db_wiki["rcid"]
|
||||
|
||||
queue_limit = settings.get("queue_limit", 30)
|
||||
QueuedWiki = namedtuple("QueuedWiki", ['url', 'amount'])
|
||||
|
||||
class LimitedList(list):
|
||||
def __init__(self, *args):
|
||||
list.__init__(self, *args)
|
||||
|
||||
def append(self, object) -> None:
|
||||
if len(self) < queue_limit:
|
||||
self.insert(len(self), object)
|
||||
return
|
||||
raise ListFull
|
||||
|
||||
|
||||
class RcQueue:
|
||||
def __init__(self):
|
||||
self.domain_list = {}
|
||||
self.to_remove = []
|
||||
|
||||
async def start_group(self, group, initial_wikis):
|
||||
"""Starts a task for given domain group"""
|
||||
if group not in self.domain_list:
|
||||
self.domain_list[group] = {"task": asyncio.create_task(scan_group(group), name=group), "last_rowid": 0, "query": LimitedList(initial_wikis), "rate_limiter": RateLimiter()}
|
||||
else:
|
||||
raise KeyError
|
||||
|
||||
async def remove_wiki_from_group(self, wiki):
|
||||
"""Removes a wiki from query of given domain group"""
|
||||
logger.debug(f"Removing {wiki} from group queue.")
|
||||
group = get_domain(wiki)
|
||||
self[group]["query"] = [x for x in self[group]["query"] if x.url == wiki]
|
||||
if not self[group]["query"]: # if there is no wiki left in the queue, get rid of the task
|
||||
logger.debug(f"{group} no longer has any wikis queued!")
|
||||
all_wikis[wiki].rc_active = -1
|
||||
self[group]["task"].cancel()
|
||||
del self.domain_list[group]
|
||||
|
||||
@asynccontextmanager
|
||||
async def retrieve_next_queued(self, group) -> Generator[QueuedWiki, None, None]:
|
||||
"""Retrives next wiki in the queue for given domain"""
|
||||
try:
|
||||
yield self.domain_list[group]["query"][0]
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except:
|
||||
if command_line_args.debug:
|
||||
logger.exception("RC Group exception")
|
||||
shutdown(asyncio.get_event_loop())
|
||||
else:
|
||||
logger.exception("Group task returned error")
|
||||
await generic_msg_sender_exception_logger(traceback.format_exc(), "Group task error logger", Group=group)
|
||||
else:
|
||||
self.domain_list[group]["query"].pop(0)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def filter_rc_active(wiki_obj):
|
||||
return wiki_obj[1].rc_active > -1
|
||||
|
||||
async def update_queues(self):
|
||||
"""Makes a round on rcgcdw DB and looks for updates to the queues in self.domain_list"""
|
||||
try:
|
||||
fetch_all = db_cursor.execute(
|
||||
'SELECT ROWID, webhook, wiki, lang, display, wikiid, rcid FROM rcgcdw WHERE rcid != -1 GROUP BY wiki ORDER BY ROWID')
|
||||
self.to_remove = [x[0] for x in filter(self.filter_rc_active, all_wikis.items())] # first populate this list and remove wikis that are still in the db, clean up the rest
|
||||
full = []
|
||||
for db_wiki in fetch_all.fetchall():
|
||||
domain = get_domain(db_wiki["wiki"])
|
||||
try:
|
||||
if db_wiki["wiki"] not in all_wikis:
|
||||
raise AssertionError
|
||||
self.to_remove.remove(db_wiki["wiki"])
|
||||
except AssertionError:
|
||||
all_wikis[db_wiki["wiki"]] = Wiki()
|
||||
all_wikis[db_wiki["wiki"]].rc_active = db_wiki["rcid"]
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
current_domain: dict = self[domain]
|
||||
if not db_wiki["ROWID"] < current_domain["last_rowid"]:
|
||||
current_domain["query"].append(QueuedWiki(db_wiki["wiki"], 20))
|
||||
except KeyError:
|
||||
await self.start_group(domain, db_wiki)
|
||||
logger.info("A new domain group has been added since last time, adding it to the domain_list and starting a task...")
|
||||
except ListFull:
|
||||
full.append(domain)
|
||||
current_domain["last_rowid"] = db_wiki["ROWID"]
|
||||
continue
|
||||
for wiki in self.to_remove:
|
||||
await self.remove_wiki_from_group(wiki)
|
||||
for group, data in self.domain_list.items():
|
||||
if group not in full:
|
||||
self[group]["last_rowid"] = 0 # iter reached the end without being stuck on full list
|
||||
logger.debug("Current domain_list structure: {}".format(self.domain_list))
|
||||
except:
|
||||
if command_line_args.debug:
|
||||
logger.exception("Queue error!")
|
||||
shutdown(asyncio.get_event_loop())
|
||||
else:
|
||||
logger.exception("Exception on queue updater")
|
||||
await generic_msg_sender_exception_logger(traceback.format_exc(), "Queue updator")
|
||||
|
||||
|
||||
def __getitem__(self, item):
|
||||
"""Returns the query of given domain group"""
|
||||
return self.domain_list[item]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.domain_list[key] = value
|
||||
|
||||
|
||||
rcqueue = RcQueue()
|
||||
|
||||
|
||||
# Start queueing logic
|
||||
|
||||
|
||||
def calculate_delay() -> float:
|
||||
def calculate_delay_for_group(group_length: int) -> float:
|
||||
"""Calculate the delay between fetching each wiki to avoid rate limits"""
|
||||
min_delay = 60 / settings["max_requests_per_minute"]
|
||||
if (len(all_wikis) * min_delay) < settings["minimal_cooldown_per_wiki_in_sec"]:
|
||||
return settings["minimal_cooldown_per_wiki_in_sec"] / len(all_wikis)
|
||||
if group_length == 0:
|
||||
group_length = 1
|
||||
if (group_length * min_delay) < settings["minimal_cooldown_per_wiki_in_sec"]:
|
||||
return settings["minimal_cooldown_per_wiki_in_sec"] / group_length
|
||||
else:
|
||||
return min_delay
|
||||
return 0.0
|
||||
|
||||
|
||||
def generate_targets(wiki_url: str) -> defaultdict:
|
||||
|
@ -62,29 +177,31 @@ def generate_targets(wiki_url: str) -> defaultdict:
|
|||
return combinations
|
||||
|
||||
|
||||
async def wiki_scanner():
|
||||
"""Wiki scanner is spawned as a task which purpose is to continuously run over wikis in the DB, fetching recent changes
|
||||
to add messages based on the changes to message queue later handled by message_sender coroutine."""
|
||||
try:
|
||||
while True:
|
||||
calc_delay = calculate_delay()
|
||||
fetch_all = db_cursor.execute(
|
||||
'SELECT webhook, wiki, lang, display, wikiid, rcid, postid FROM rcgcdw GROUP BY wiki')
|
||||
async def generate_domain_groups():
|
||||
"""Generate a list of wikis per domain (fandom.com, wikipedia.org etc.)"""
|
||||
domain_wikis = defaultdict(list)
|
||||
fetch_all = db_cursor.execute('SELECT ROWID, webhook, wiki, lang, display, wikiid, rcid FROM rcgcdw WHERE rcid != -1 GROUP BY wiki ORDER BY ROWID ASC')
|
||||
for db_wiki in fetch_all.fetchall():
|
||||
logger.debug("Wiki {}".format(db_wiki["wiki"]))
|
||||
if db_wiki["wiki"] not in all_wikis:
|
||||
logger.info("Registering new wiki locally: {}".format(db_wiki["wiki"]))
|
||||
all_wikis[db_wiki["wiki"]] = Wiki()
|
||||
local_wiki = all_wikis[db_wiki["wiki"]] # set a reference to a wiki object from memory
|
||||
if db_wiki["rcid"] != -1:
|
||||
domain_wikis[get_domain(db_wiki["wiki"])].append(QueuedWiki(db_wiki["wiki"], 20))
|
||||
for group, db_wikis in domain_wikis.items():
|
||||
yield group, db_wikis
|
||||
|
||||
|
||||
async def scan_group(group: str):
|
||||
rate_limiter = rcqueue[group]["rate_limiter"]
|
||||
while True:
|
||||
try:
|
||||
async with rcqueue.retrieve_next_queued(group) as queued_wiki: # acquire next wiki in queue
|
||||
logger.debug("Wiki {}".format(queued_wiki.url))
|
||||
local_wiki = all_wikis[queued_wiki.url] # set a reference to a wiki object from memory
|
||||
extended = False
|
||||
if local_wiki.mw_messages is None:
|
||||
extended = True
|
||||
async with aiohttp.ClientSession(headers=settings["header"],
|
||||
timeout=aiohttp.ClientTimeout(3.0)) as session:
|
||||
try:
|
||||
wiki_response = await local_wiki.fetch_wiki(extended, db_wiki["wiki"], session)
|
||||
await local_wiki.check_status(db_wiki["wiki"], wiki_response.status)
|
||||
wiki_response = await local_wiki.fetch_wiki(extended, queued_wiki.url, session, rate_limiter, amount=queued_wiki.amount)
|
||||
await local_wiki.check_status(queued_wiki.url, wiki_response.status)
|
||||
except (WikiServerError, WikiError):
|
||||
logger.error("Exeption when fetching the wiki")
|
||||
continue # ignore this wiki if it throws errors
|
||||
|
@ -93,52 +210,110 @@ async def wiki_scanner():
|
|||
if "error" in recent_changes_resp or "errors" in recent_changes_resp:
|
||||
error = recent_changes_resp.get("error", recent_changes_resp["errors"])
|
||||
if error["code"] == "readapidenied":
|
||||
await local_wiki.fail_add(db_wiki["wiki"], 410)
|
||||
await local_wiki.fail_add(queued_wiki.url, 410)
|
||||
continue
|
||||
raise WikiError
|
||||
recent_changes = recent_changes_resp['query']['recentchanges']
|
||||
recent_changes.reverse()
|
||||
except aiohttp.ContentTypeError:
|
||||
logger.exception("Wiki seems to be resulting in non-json content.")
|
||||
await local_wiki.fail_add(db_wiki["wiki"], 410)
|
||||
await local_wiki.fail_add(queued_wiki.url, 410)
|
||||
continue
|
||||
except:
|
||||
logger.exception("On loading json of response.")
|
||||
continue
|
||||
if extended:
|
||||
await process_mwmsgs(recent_changes_resp, local_wiki, mw_msgs)
|
||||
if db_wiki["rcid"] is None: # new wiki, just get the last rc to not spam the channel
|
||||
if local_wiki.rc_active == 0: # new wiki, just get the last rc to not spam the channel
|
||||
if len(recent_changes) > 0:
|
||||
DBHandler.add(db_wiki["wiki"], recent_changes[-1]["rcid"])
|
||||
local_wiki.rc_active = recent_changes[-1]["rcid"]
|
||||
DBHandler.add(queued_wiki.url, recent_changes[-1]["rcid"])
|
||||
else:
|
||||
DBHandler.add(db_wiki["wiki"], 0)
|
||||
local_wiki.rc_active = 0
|
||||
DBHandler.add(queued_wiki.url, 0)
|
||||
DBHandler.update_db()
|
||||
continue
|
||||
categorize_events = {}
|
||||
targets = generate_targets(db_wiki["wiki"])
|
||||
paths = get_paths(db_wiki["wiki"], recent_changes_resp)
|
||||
targets = generate_targets(queued_wiki.url)
|
||||
paths = get_paths(queued_wiki.url, recent_changes_resp)
|
||||
new_events = 0
|
||||
for change in recent_changes:
|
||||
if change["rcid"] > local_wiki.rc_active and queued_wiki.amount != 450:
|
||||
new_events += 1
|
||||
if new_events == 20:
|
||||
# call the function again with max limit for more results, ignore the ones in this request
|
||||
logger.debug("There were too many new events, queuing wiki with 450 limit.")
|
||||
rcqueue[group]["query"].insert(1, QueuedWiki(queued_wiki.url, 450))
|
||||
break
|
||||
await process_cats(change, local_wiki, mw_msgs, categorize_events)
|
||||
else: # If we broke from previous loop (too many changes) don't execute sending messages here
|
||||
for change in recent_changes: # Yeah, second loop since the categories require to be all loaded up
|
||||
if change["rcid"] > db_wiki["rcid"]:
|
||||
if change["rcid"] > local_wiki.rc_active:
|
||||
for target in targets.items():
|
||||
try:
|
||||
await essential_info(change, categorize_events, local_wiki, db_wiki,
|
||||
target, paths, recent_changes_resp)
|
||||
await essential_info(change, categorize_events, local_wiki, target, paths,
|
||||
recent_changes_resp, rate_limiter)
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except:
|
||||
if command_line_args.debug:
|
||||
raise # reraise the issue
|
||||
logger.exception("Exception on RC formatter")
|
||||
raise
|
||||
else:
|
||||
logger.exception("Exception on RC formatter")
|
||||
await formatter_exception_logger(db_wiki["wiki"], change, traceback.format_exc())
|
||||
await generic_msg_sender_exception_logger(traceback.format_exc(), "Exception in RC formatter", Wiki=queued_wiki.url, Change=str(change)[0:1000])
|
||||
if recent_changes:
|
||||
DBHandler.add(db_wiki["wiki"], change["rcid"])
|
||||
await asyncio.sleep(delay=2.0) # temporary measure until rate limiting is not implemented
|
||||
if db_wiki["wikiid"] is not None:
|
||||
local_wiki.rc_active = change["rcid"]
|
||||
DBHandler.add(queued_wiki.url, change["rcid"])
|
||||
delay_between_wikis = calculate_delay_for_group(len(rcqueue[group]["query"])) # TODO Find a way to not execute it every wiki
|
||||
await asyncio.sleep(delay_between_wikis)
|
||||
DBHandler.update_db()
|
||||
except asyncio.CancelledError:
|
||||
return
|
||||
|
||||
|
||||
async def wiki_scanner():
|
||||
"""Wiki scanner is spawned as a task which purpose is to continuously run over wikis in the DB, fetching recent changes
|
||||
to add messages based on the changes to message queue later handled by message_sender coroutine."""
|
||||
try:
|
||||
async for group, db_wikis in generate_domain_groups(): # First scan
|
||||
await rcqueue.start_group(group, db_wikis)
|
||||
while True:
|
||||
await asyncio.sleep(20.0)
|
||||
await rcqueue.update_queues()
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
|
||||
|
||||
async def message_sender():
|
||||
"""message_sender is a coroutine responsible for handling Discord messages and their sending to Discord"""
|
||||
try:
|
||||
while True:
|
||||
await messagequeue.resend_msgs()
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
except:
|
||||
if command_line_args.debug:
|
||||
logger.exception("Exception on DC message sender")
|
||||
shutdown(loop=asyncio.get_event_loop())
|
||||
else:
|
||||
logger.exception("Exception on DC message sender")
|
||||
await generic_msg_sender_exception_logger(traceback.format_exc(), "Message sender exception")
|
||||
|
||||
async def discussion_handler():
|
||||
try:
|
||||
while True:
|
||||
fetch_all = db_cursor.execute(
|
||||
'SELECT wiki, wikiid, postid FROM rcgcdw WHERE wikiid IS NOT NULL')
|
||||
for db_wiki in fetch_all.fetchall():
|
||||
header = settings["header"]
|
||||
header["Accept"] = "application/hal+json"
|
||||
async with aiohttp.ClientSession(headers=header,
|
||||
timeout=aiohttp.ClientTimeout(3.0)) as session:
|
||||
try:
|
||||
local_wiki = all_wikis[db_wiki["wiki"]] # set a reference to a wiki object from memory
|
||||
except KeyError:
|
||||
local_wiki = all_wikis[db_wiki["wiki"]] = Wiki()
|
||||
try:
|
||||
feeds_response = await local_wiki.fetch_feeds(db_wiki["wikiid"], session)
|
||||
except (WikiServerError, WikiError):
|
||||
|
@ -164,9 +339,9 @@ async def wiki_scanner():
|
|||
continue
|
||||
if db_wiki["postid"] is None: # new wiki, just get the last post to not spam the channel
|
||||
if len(discussion_feed) > 0:
|
||||
DBHandler.add(db_wiki["wiki"], discussion_feed[-1]["id"], True)
|
||||
DBHandler.add(db_wiki["wikiid"], discussion_feed[-1]["id"], True)
|
||||
else:
|
||||
DBHandler.add(db_wiki["wiki"], "0", True)
|
||||
DBHandler.add(db_wiki["wikiid"], "0", True)
|
||||
DBHandler.update_db()
|
||||
continue
|
||||
targets = generate_targets(db_wiki["wiki"])
|
||||
|
@ -175,54 +350,51 @@ async def wiki_scanner():
|
|||
for target in targets.items():
|
||||
try:
|
||||
await essential_feeds(post, db_wiki, target)
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except:
|
||||
if command_line_args.debug:
|
||||
logger.exception("Exception on Feeds formatter")
|
||||
shutdown(loop=asyncio.get_event_loop())
|
||||
else:
|
||||
logger.exception("Exception on Feeds formatter")
|
||||
await generic_msg_sender_exception_logger(traceback.format_exc(), "Exception in feed formatter", Post=str(post)[0:1000], Wiki=db_wiki["wiki"])
|
||||
if discussion_feed:
|
||||
DBHandler.add(db_wiki["wikiid"], post["id"], True)
|
||||
await asyncio.sleep(delay=2.0) # hardcoded really doesn't need much more
|
||||
DBHandler.update_db()
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
except:
|
||||
if command_line_args.debug:
|
||||
raise # reraise the issue
|
||||
else:
|
||||
logger.exception("Exception on Feeds formatter")
|
||||
await formatter_exception_logger(db_wiki["wiki"], post, traceback.format_exc())
|
||||
if discussion_feed:
|
||||
DBHandler.add(db_wiki["wiki"], post["id"], True)
|
||||
await asyncio.sleep(delay=calc_delay)
|
||||
DBHandler.update_db()
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
await generic_msg_sender_exception_logger(traceback.format_exc(), "Discussion handler task exception", Wiki=db_wiki["wiki"])
|
||||
|
||||
|
||||
async def message_sender():
|
||||
"""message_sender is a coroutine responsible for handling Discord messages and their sending to Discord"""
|
||||
try:
|
||||
while True:
|
||||
await messagequeue.resend_msgs()
|
||||
except:
|
||||
if command_line_args.debug:
|
||||
logger.exception("Exception on DC message sender")
|
||||
raise # reraise the issue
|
||||
else:
|
||||
logger.exception("Exception on DC message sender")
|
||||
await msg_sender_exception_logger(traceback.format_exc())
|
||||
|
||||
|
||||
def shutdown(loop, signal=None):
|
||||
DBHandler.update_db()
|
||||
if len(messagequeue) > 0:
|
||||
logger.warning("Some messages are still queued!")
|
||||
loop.stop()
|
||||
logger.info("Script has shut down due to signal {}.".format(signal))
|
||||
for task in asyncio.all_tasks(loop):
|
||||
logger.debug("Killing task {}".format(task.get_name()))
|
||||
task.cancel()
|
||||
sys.exit(0)
|
||||
loop.run_until_complete(asyncio.gather(*asyncio.all_tasks(loop)))
|
||||
loop.stop()
|
||||
logger.info("Script has shut down due to signal {}.".format(signal))
|
||||
# sys.exit(0)
|
||||
|
||||
|
||||
def global_exception_handler(loop, context):
|
||||
"""Global exception handler for asyncio, lets us know when something crashes"""
|
||||
msg = context.get("exception", context["message"])
|
||||
logger.error("Global exception handler: {}".format(msg))
|
||||
if command_line_args.debug is False:
|
||||
requests.post("https://discord.com/api/webhooks/"+settings["monitoring_webhook"], data=repr(DiscordMessage("compact", "monitoring", [settings["monitoring_webhook"]], wiki=None, content="[RcGcDb] Global exception handler: {}".format(msg))), headers={'Content-Type': 'application/json'})
|
||||
else:
|
||||
shutdown(loop)
|
||||
# def global_exception_handler(loop, context):
|
||||
# """Global exception handler for asyncio, lets us know when something crashes"""
|
||||
# msg = context.get("exception", context["message"])
|
||||
# logger.error("Global exception handler: {}".format(msg))
|
||||
# if command_line_args.debug is False:
|
||||
# requests.post("https://discord.com/api/webhooks/"+settings["monitoring_webhook"], data=repr(DiscordMessage("compact", "monitoring", [settings["monitoring_webhook"]], wiki=None, content="[RcGcDb] Global exception handler: {}".format(msg))), headers={'Content-Type': 'application/json'})
|
||||
# else:
|
||||
# shutdown(loop)
|
||||
|
||||
|
||||
async def main_loop():
|
||||
|
@ -235,14 +407,15 @@ async def main_loop():
|
|||
except AttributeError:
|
||||
logger.info("Running on Windows, some things may not work as they should.")
|
||||
signals = (signal.SIGBREAK, signal.SIGTERM, signal.SIGINT)
|
||||
loop.set_exception_handler(global_exception_handler)
|
||||
# loop.set_exception_handler(global_exception_handler)
|
||||
try:
|
||||
task1 = asyncio.create_task(wiki_scanner())
|
||||
task2 = asyncio.create_task(message_sender())
|
||||
task1 = asyncio.create_task(wiki_scanner(), name="Wiki RC scanner")
|
||||
task2 = asyncio.create_task(message_sender(), name="Discord message sender")
|
||||
task3 = asyncio.create_task(discussion_handler(), name="Discussion handler")
|
||||
await task1
|
||||
await task2
|
||||
await task3
|
||||
except KeyboardInterrupt:
|
||||
shutdown(loop)
|
||||
|
||||
|
||||
asyncio.run(main_loop(), debug=command_line_args.debug)
|
||||
asyncio.run(main_loop(), debug=False)
|
||||
|
|
|
@ -21,9 +21,7 @@ default_header["X-RateLimit-Precision"] = "millisecond"
|
|||
# User facing webhook functions
|
||||
async def wiki_removal(wiki_url, status):
|
||||
for observer in db_cursor.execute('SELECT webhook, lang FROM rcgcdw WHERE wiki = ?', (wiki_url,)):
|
||||
def _(string: str) -> str:
|
||||
"""Our own translation string to make it compatible with async"""
|
||||
return langs[observer["lang"]].gettext(string)
|
||||
_ = langs[observer["lang"]]["discord"].gettext
|
||||
reasons = {410: _("wiki deletion"), 404: _("wiki deletion"), 401: _("wiki becoming inaccessible"),
|
||||
402: _("wiki becoming inaccessible"), 403: _("wiki becoming inaccessible")}
|
||||
reason = reasons.get(status, _("unknown error"))
|
||||
|
@ -110,23 +108,13 @@ async def wiki_removal_monitor(wiki_url, status):
|
|||
await send_to_discord_webhook_monitoring(DiscordMessage("compact", "webhook/remove", content="Removing {} because {}.".format(wiki_url, status), webhook_url=[None], wiki=None))
|
||||
|
||||
|
||||
async def formatter_exception_logger(wiki_url, change, exception):
|
||||
"""Creates a Discord message reporting a crash in RC formatter area"""
|
||||
async def generic_msg_sender_exception_logger(exception: str, title: str, **kwargs):
|
||||
"""Creates a Discord message reporting a crash"""
|
||||
message = DiscordMessage("embed", "bot/exception", [None], wiki=None)
|
||||
message["description"] = exception
|
||||
message["title"] = "RC Exception Report"
|
||||
change = str(change)[0:1000]
|
||||
message.add_field("Wiki URL", wiki_url)
|
||||
message.add_field("Change", change)
|
||||
message.finish_embed()
|
||||
await send_to_discord_webhook_monitoring(message)
|
||||
|
||||
|
||||
async def msg_sender_exception_logger(exception):
|
||||
"""Creates a Discord message reporting a crash in RC formatter area"""
|
||||
message = DiscordMessage("embed", "bot/exception", [None], wiki=None)
|
||||
message["description"] = exception
|
||||
message["title"] = "MSGSENDER Exception Report"
|
||||
message["title"] = title
|
||||
for key, value in kwargs:
|
||||
message.add_field(key, value)
|
||||
message.finish_embed()
|
||||
await send_to_discord_webhook_monitoring(message)
|
||||
|
||||
|
|
|
@ -15,3 +15,9 @@ class WikiUnauthorizedError(Exception):
|
|||
|
||||
class OtherWikiError(Exception):
|
||||
pass
|
||||
|
||||
class QueueEmpty(Exception):
|
||||
pass
|
||||
|
||||
class ListFull(Exception):
|
||||
pass
|
|
@ -6,12 +6,14 @@ from src.config import settings
|
|||
from src.misc import link_formatter, create_article_path, escape_formatting
|
||||
from src.discord import DiscordMessage
|
||||
from src.msgqueue import send_to_discord
|
||||
from src.i18n import langs
|
||||
|
||||
|
||||
logger = logging.getLogger("rcgcdw.discussion_formatters")
|
||||
|
||||
async def feeds_compact_formatter(post_type, post, message_target, wiki, _):
|
||||
async def feeds_compact_formatter(post_type, post, message_target, wiki):
|
||||
"""Compact formatter for Fandom discussions."""
|
||||
_ = langs[message_target[0][0]]["discussion_formatters"].gettext
|
||||
message = None
|
||||
if post_type == "FORUM":
|
||||
author = post["createdBy"]["name"]
|
||||
|
@ -25,14 +27,14 @@ async def feeds_compact_formatter(post_type, post, message_target, wiki, _):
|
|||
if post_type == "FORUM":
|
||||
if not post["isReply"]:
|
||||
thread_funnel = post.get("funnel")
|
||||
msg_text = "[{author}]({author_url}) created [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msg_text = _("[{author}]({author_url}) created [{title}](<{url}f/p/{threadId}>) in {forumName}")
|
||||
if thread_funnel == "POLL":
|
||||
msg_text = "[{author}]({author_url}) created a poll [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msg_text = _("[{author}]({author_url}) created a poll [{title}](<{url}f/p/{threadId}>) in {forumName}")
|
||||
elif thread_funnel == "QUIZ":
|
||||
msg_text = "[{author}]({author_url}) created a quiz [{title}](<{url}f/p/{threadId}>) in {forumName}"
|
||||
msg_text = _("[{author}]({author_url}) created a quiz [{title}](<{url}f/p/{threadId}>) in {forumName}")
|
||||
elif thread_funnel != "TEXT":
|
||||
logger.warning("No entry for {event} with params: {params}".format(event=thread_funnel, params=post))
|
||||
message = _(msg_text).format(author=author, author_url=author_url, title=post["title"], url=wiki, threadId=post["threadId"], forumName=post["forumName"])
|
||||
message = msg_text.format(author=author, author_url=author_url, title=post["title"], url=wiki, threadId=post["threadId"], forumName=post["forumName"])
|
||||
else:
|
||||
message = _("[{author}]({author_url}) created a [reply](<{url}f/p/{threadId}/r/{postId}>) to [{title}](<{url}f/p/{threadId}>) in {forumName}").format(author=author, author_url=author_url, url=wiki, threadId=post["threadId"], postId=post["id"], title=post["_embedded"]["thread"][0]["title"], forumName=post["forumName"])
|
||||
elif post_type == "WALL":
|
||||
|
@ -58,8 +60,9 @@ async def feeds_compact_formatter(post_type, post, message_target, wiki, _):
|
|||
await send_to_discord(DiscordMessage("compact", "discussion", message_target[1], content=message, wiki=wiki))
|
||||
|
||||
|
||||
async def feeds_embed_formatter(post_type, post, message_target, wiki, _):
|
||||
async def feeds_embed_formatter(post_type, post, message_target, wiki):
|
||||
"""Embed formatter for Fandom discussions."""
|
||||
_ = langs[message_target[0][0]]["discussion_formatters"].gettext
|
||||
embed = DiscordMessage("embed", "discussion", message_target[1], wiki=wiki)
|
||||
if post_type == "FORUM":
|
||||
embed.set_author(post["createdBy"]["name"], "{url}f/u/{creatorId}".format(url=wiki, creatorId=post["creatorId"]), icon_url=post["createdBy"]["avatarUrl"])
|
||||
|
|
|
@ -9,6 +9,7 @@ from src.config import settings
|
|||
from src.misc import link_formatter, create_article_path, parse_link, profile_field_name, ContentParser
|
||||
from src.discord import DiscordMessage
|
||||
from src.msgqueue import send_to_discord
|
||||
from src.i18n import langs
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
@ -18,9 +19,11 @@ if 1 == 2: # additional translation strings in unreachable code
|
|||
print(_("director"), _("bot"), _("editor"), _("directors"), _("sysop"), _("bureaucrat"), _("reviewer"),
|
||||
_("autoreview"), _("autopatrol"), _("wiki_guardian"), ngettext("second", "seconds", 1), ngettext("minute", "minutes", 1), ngettext("hour", "hours", 1), ngettext("day", "days", 1), ngettext("week", "weeks", 1), ngettext("month", "months",1), ngettext("year", "years", 1), ngettext("millennium", "millennia", 1), ngettext("decade", "decades", 1), ngettext("century", "centuries", 1))
|
||||
|
||||
async def compact_formatter(action, change, parsed_comment, categories, recent_changes, message_target, _, ngettext, paths,
|
||||
async def compact_formatter(action, change, parsed_comment, categories, recent_changes, message_target, paths, rate_limiter,
|
||||
additional_data=None):
|
||||
"""Recent Changes compact formatter, part of RcGcDw"""
|
||||
_ = langs[message_target[0][0]]["rc_formatters"].gettext
|
||||
ngettext = langs[message_target[0][0]]["rc_formatters"].ngettext
|
||||
if additional_data is None:
|
||||
additional_data = {"namespaces": {}, "tags": {}}
|
||||
WIKI_API_PATH = paths[0]
|
||||
|
@ -185,7 +188,7 @@ async def compact_formatter(action, change, parsed_comment, categories, recent_c
|
|||
content = _("[{author}]({author_url}) edited the {field} on {target} profile. *({desc})*").format(author=author,
|
||||
author_url=author_url,
|
||||
target=target,
|
||||
field=profile_field_name(change["logparams"]['4:section'], False, _),
|
||||
field=profile_field_name(change["logparams"]['4:section'], False, message_target[0][0]),
|
||||
desc=BeautifulSoup(change["parsedcomment"], "lxml").get_text())
|
||||
elif action in ("rights/rights", "rights/autopromote"):
|
||||
link = link_formatter(create_article_path("User:{user}".format(user=change["title"].split(":")[1]), WIKI_ARTICLE_PATH))
|
||||
|
@ -330,8 +333,10 @@ async def compact_formatter(action, change, parsed_comment, categories, recent_c
|
|||
await send_to_discord(DiscordMessage("compact", action, message_target[1], content=content, wiki=WIKI_SCRIPT_PATH))
|
||||
|
||||
|
||||
async def embed_formatter(action, change, parsed_comment, categories, recent_changes, message_target, _, ngettext, paths, additional_data=None):
|
||||
async def embed_formatter(action, change, parsed_comment, categories, recent_changes, message_target, paths, rate_limiter, additional_data=None):
|
||||
"""Recent Changes embed formatter, part of RcGcDw"""
|
||||
_ = langs[message_target[0][0]]["rc_formatters"].gettext
|
||||
ngettext = langs[message_target[0][0]]["rc_formatters"].ngettext
|
||||
if additional_data is None:
|
||||
additional_data = {"namespaces": {}, "tags": {}}
|
||||
WIKI_API_PATH = paths[0]
|
||||
|
@ -374,14 +379,14 @@ async def embed_formatter(action, change, parsed_comment, categories, recent_cha
|
|||
changed_content = await recent_changes.safe_request(
|
||||
"{wiki}?action=compare&format=json&fromtext=&torev={diff}&topst=1&prop=diff".format(
|
||||
wiki=WIKI_API_PATH, diff=change["revid"]
|
||||
), "compare", "*")
|
||||
), rate_limiter, "compare", "*")
|
||||
else:
|
||||
changed_content = await recent_changes.safe_request(
|
||||
"{wiki}?action=compare&format=json&fromrev={oldrev}&torev={diff}&topst=1&prop=diff".format(
|
||||
wiki=WIKI_API_PATH, diff=change["revid"],oldrev=change["old_revid"]
|
||||
), "compare", "*")
|
||||
), rate_limiter, "compare", "*")
|
||||
if changed_content:
|
||||
EditDiff = ContentParser(_)
|
||||
EditDiff = ContentParser(message_target[0][0])
|
||||
EditDiff.feed(changed_content)
|
||||
if EditDiff.small_prev_del:
|
||||
if EditDiff.small_prev_del.replace("~~", "").isspace():
|
||||
|
@ -404,7 +409,7 @@ async def embed_formatter(action, change, parsed_comment, categories, recent_cha
|
|||
license = None
|
||||
urls = await recent_changes.safe_request(
|
||||
"{wiki}?action=query&format=json&prop=imageinfo&list=&meta=&titles={filename}&iiprop=timestamp%7Curl%7Carchivename&iilimit=5".format(
|
||||
wiki=WIKI_API_PATH, filename=change["title"]), "query", "pages")
|
||||
wiki=WIKI_API_PATH, filename=change["title"]), rate_limiter, "query", "pages")
|
||||
link = create_article_path(change["title"], WIKI_ARTICLE_PATH)
|
||||
additional_info_retrieved = False
|
||||
if urls is not None:
|
||||
|
@ -520,21 +525,21 @@ async def embed_formatter(action, change, parsed_comment, categories, recent_cha
|
|||
embed["title"] = _("Unblocked {blocked_user}").format(blocked_user=user)
|
||||
elif action == "curseprofile/comment-created":
|
||||
if settings["appearance"]["embed"]["show_edit_changes"]:
|
||||
parsed_comment = await recent_changes.pull_comment(change["logparams"]["4:comment_id"], WIKI_API_PATH)
|
||||
parsed_comment = await recent_changes.pull_comment(change["logparams"]["4:comment_id"], WIKI_API_PATH, rate_limiter)
|
||||
link = create_article_path("Special:CommentPermalink/{commentid}".format(commentid=change["logparams"]["4:comment_id"]), WIKI_ARTICLE_PATH)
|
||||
embed["title"] = _("Left a comment on {target}'s profile").format(target=change["title"].split(':')[1]) if change["title"].split(':')[1] != \
|
||||
change["user"] else _(
|
||||
"Left a comment on their own profile")
|
||||
elif action == "curseprofile/comment-replied":
|
||||
if settings["appearance"]["embed"]["show_edit_changes"]:
|
||||
parsed_comment = await recent_changes.pull_comment(change["logparams"]["4:comment_id"], WIKI_API_PATH)
|
||||
parsed_comment = await recent_changes.pull_comment(change["logparams"]["4:comment_id"], WIKI_API_PATH, rate_limiter)
|
||||
link = create_article_path("Special:CommentPermalink/{commentid}".format(commentid=change["logparams"]["4:comment_id"]), WIKI_ARTICLE_PATH)
|
||||
embed["title"] = _("Replied to a comment on {target}'s profile").format(target=change["title"].split(':')[1]) if change["title"].split(':')[1] != \
|
||||
change["user"] else _(
|
||||
"Replied to a comment on their own profile")
|
||||
elif action == "curseprofile/comment-edited":
|
||||
if settings["appearance"]["embed"]["show_edit_changes"]:
|
||||
parsed_comment = await recent_changes.pull_comment(change["logparams"]["4:comment_id"], WIKI_API_PATH)
|
||||
parsed_comment = await recent_changes.pull_comment(change["logparams"]["4:comment_id"], WIKI_API_PATH, rate_limiter)
|
||||
link = create_article_path("Special:CommentPermalink/{commentid}".format(commentid=change["logparams"]["4:comment_id"]), WIKI_ARTICLE_PATH)
|
||||
embed["title"] = _("Edited a comment on {target}'s profile").format(target=change["title"].split(':')[1]) if change["title"].split(':')[1] != \
|
||||
change["user"] else _(
|
||||
|
@ -543,9 +548,9 @@ async def embed_formatter(action, change, parsed_comment, categories, recent_cha
|
|||
link = create_article_path("UserProfile:{target}".format(target=change["title"].split(':')[1]), WIKI_ARTICLE_PATH)
|
||||
embed["title"] = _("Edited {target}'s profile").format(target=change["title"].split(':')[1]) if change["user"] != change["title"].split(':')[1] else _("Edited their own profile")
|
||||
if not change["parsedcomment"]: # If the field is empty
|
||||
parsed_comment = _("Cleared the {field} field").format(field=profile_field_name(change["logparams"]['4:section'], True, _))
|
||||
parsed_comment = _("Cleared the {field} field").format(field=profile_field_name(change["logparams"]['4:section'], True, message_target[0][0]))
|
||||
else:
|
||||
parsed_comment = _("{field} field changed to: {desc}").format(field=profile_field_name(change["logparams"]['4:section'], True, _), desc=BeautifulSoup(change["parsedcomment"], "lxml").get_text())
|
||||
parsed_comment = _("{field} field changed to: {desc}").format(field=profile_field_name(change["logparams"]['4:section'], True, message_target[0][0]), desc=BeautifulSoup(change["parsedcomment"], "lxml").get_text())
|
||||
elif action == "curseprofile/comment-purged":
|
||||
link = create_article_path("Special:CommentPermalink/{commentid}".format(commentid=change["logparams"]["4:comment_id"]), WIKI_ARTICLE_PATH)
|
||||
embed["title"] = _("Purged a comment on {target}'s profile").format(target=change["title"].split(':')[1])
|
||||
|
|
20
src/i18n.py
20
src/i18n.py
|
@ -1,19 +1,17 @@
|
|||
import sys, logging, gettext
|
||||
from collections import defaultdict
|
||||
|
||||
logger = logging.getLogger("rcgcdb.i18n")
|
||||
supported_languages = ('de', 'pl', 'pt-br')
|
||||
translated_files = ('wiki', 'misc', 'discord', 'rc_formatters', 'discussion_formatters')
|
||||
|
||||
try:
|
||||
en = gettext.translation('rcgcdw', localedir='locale', languages=["en"])
|
||||
de = gettext.translation('rcgcdw', localedir='locale', languages=["de"])
|
||||
pl = gettext.translation('rcgcdw', localedir='locale', languages=["pl"])
|
||||
ptbr = gettext.translation('rcgcdw', localedir='locale', languages=["pt-br"])
|
||||
#ru = gettext.translation('rcgcdw', localedir='locale', languages=["ru"])
|
||||
#uk = gettext.translation('rcgcdw', localedir='locale', languages=["uk"])
|
||||
#fr = gettext.translation('rcgcdw', localedir='locale', languages=["fr"])
|
||||
langs = {"en": en, "de": de, "pl": pl, "pt-br": ptbr}
|
||||
#langs = {"en": en, "de": de, "pl": pl, "pt-br": ptbr, "ru": ru, "uk": uk, "fr": fr}
|
||||
langs = defaultdict(dict)
|
||||
for lang in supported_languages:
|
||||
for file in translated_files:
|
||||
langs[lang][file] = gettext.translation(file, localedir='locale', languages=[lang])
|
||||
for file in translated_files:
|
||||
langs["en"][file] = gettext.NullTranslations()
|
||||
except FileNotFoundError:
|
||||
logger.critical("No language files have been found. Make sure locale folder is located in the directory.")
|
||||
sys.exit(1)
|
||||
|
||||
#ngettext = en.ngettext
|
14
src/misc.py
14
src/misc.py
|
@ -3,6 +3,7 @@ import base64, re
|
|||
|
||||
import logging
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
from src.i18n import langs
|
||||
|
||||
logger = logging.getLogger("rcgcdw.misc")
|
||||
|
||||
|
@ -17,6 +18,12 @@ def get_paths(wiki: str, request) -> tuple:
|
|||
return WIKI_API_PATH, WIKI_SCRIPT_PATH, WIKI_ARTICLE_PATH, WIKI_JUST_DOMAIN
|
||||
|
||||
|
||||
def get_domain(url: str) -> str:
|
||||
"""Get domain of given URL"""
|
||||
parsed_url = urlparse(url)
|
||||
return ".".join(urlunparse((*parsed_url[0:2], "", "", "", "")).split(".")[-2:]) # something like gamepedia.com, fandom.com
|
||||
|
||||
|
||||
class LinkParser(HTMLParser):
|
||||
|
||||
new_string = ""
|
||||
|
@ -84,7 +91,8 @@ def create_article_path(article: str, WIKI_ARTICLE_PATH: str) -> str:
|
|||
return WIKI_ARTICLE_PATH.replace("$1", article)
|
||||
|
||||
|
||||
def profile_field_name(name, embed, _):
|
||||
def profile_field_name(name, embed, lang):
|
||||
_ = langs[lang]["misc"].gettext
|
||||
profile_fields = {"profile-location": _("Location"), "profile-aboutme": _("About me"),
|
||||
"profile-link-google": _("Google link"), "profile-link-facebook": _("Facebook link"),
|
||||
"profile-link-twitter": _("Twitter link"), "profile-link-reddit": _("Reddit link"),
|
||||
|
@ -108,9 +116,9 @@ class ContentParser(HTMLParser):
|
|||
small_prev_del = ""
|
||||
added = False
|
||||
|
||||
def __init__(self, _):
|
||||
def __init__(self, lang):
|
||||
super().__init__()
|
||||
self.more = _("\n__And more__")
|
||||
self.more = langs[lang]["misc"].gettext("\n__And more__")
|
||||
self.ins_length = len(self.more)
|
||||
self.del_length = len(self.more)
|
||||
|
||||
|
|
|
@ -16,8 +16,11 @@ class UpdateDB:
|
|||
|
||||
def update_db(self):
|
||||
for update in self.updated:
|
||||
update_type = "postid" if update[2] is not None else "rcid"
|
||||
db_cursor.execute("UPDATE rcgcdw SET {} = ? WHERE wiki = ?".format(update_type), (update[1],update[0],))
|
||||
if update[2] is None:
|
||||
sql = "UPDATE rcgcdw SET rcid = ? WHERE wiki = ? AND rcid != -1"
|
||||
else:
|
||||
sql = "UPDATE rcgcdw SET postid = ? WHERE wikiid = ?"
|
||||
db_cursor.execute(sql, (update[1], update[0],))
|
||||
db_connection.commit()
|
||||
self.clear_list()
|
||||
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import aiohttp
|
||||
import logging
|
||||
from src.config import settings
|
||||
|
||||
logger = logging.getLogger("rcgcdb.request_tracking")
|
||||
|
||||
class WikiRequestTracking:
|
||||
def __init__(self):
|
||||
self.current_timeout = 0
|
||||
|
||||
async def add_timeout(self, time: float):
|
||||
self.current_timeout += time
|
||||
|
||||
def is_fandom(self, url):
|
||||
if any(x in url for x in ("fandom.com", "gamepedia.com", "wikia.org")):
|
||||
return True
|
||||
return False
|
||||
|
||||
async def on_request_start(session, trace_config_ctx, params):
|
||||
if
|
||||
|
||||
trace_config = aiohttp.TraceConfig()
|
||||
trace_config.on_request_start.append(on_request_start)
|
37
src/wiki.py
37
src/wiki.py
|
@ -7,6 +7,7 @@ from src.formatters.rc import embed_formatter, compact_formatter
|
|||
from src.formatters.discussions import feeds_embed_formatter, feeds_compact_formatter
|
||||
from src.misc import parse_link
|
||||
from src.i18n import langs
|
||||
from src.wiki_ratelimiter import RateLimiter
|
||||
import src.discord
|
||||
import asyncio
|
||||
from src.config import settings
|
||||
|
@ -23,12 +24,12 @@ class Wiki:
|
|||
mw_messages: int = None
|
||||
fail_times: int = 0 # corresponding to amount of times connection with wiki failed for client reasons (400-499)
|
||||
session: aiohttp.ClientSession = None
|
||||
|
||||
rc_active: int = 0
|
||||
|
||||
@staticmethod
|
||||
async def fetch_wiki(extended, script_path, session: aiohttp.ClientSession) -> aiohttp.ClientResponse:
|
||||
async def fetch_wiki(extended, script_path, session: aiohttp.ClientSession, ratelimiter: RateLimiter, amount=20) -> aiohttp.ClientResponse:
|
||||
await ratelimiter.timeout_wait()
|
||||
url_path = script_path + "api.php"
|
||||
amount = 20
|
||||
if extended:
|
||||
params = {"action": "query", "format": "json", "uselang": "content", "list": "tags|recentchanges",
|
||||
"meta": "allmessages|siteinfo",
|
||||
|
@ -45,6 +46,7 @@ class Wiki:
|
|||
"rclimit": amount, "rctype": "edit|new|log|categorize", "siprop": "namespaces|general"}
|
||||
try:
|
||||
response = await session.get(url_path, params=params)
|
||||
ratelimiter.timeout_add(1.0)
|
||||
except (aiohttp.ClientConnectionError, aiohttp.ServerTimeoutError, asyncio.TimeoutError):
|
||||
logger.exception("A connection error occurred while requesting {}".format(url_path))
|
||||
raise WikiServerError
|
||||
|
@ -63,10 +65,12 @@ class Wiki:
|
|||
return response
|
||||
|
||||
@staticmethod
|
||||
async def safe_request(url, *keys):
|
||||
async def safe_request(url, ratelimiter, *keys):
|
||||
await ratelimiter.timeout_wait()
|
||||
try:
|
||||
async with aiohttp.ClientSession(headers=settings["header"], timeout=aiohttp.ClientTimeout(3.0)) as session:
|
||||
request = await session.get(url, allow_redirects=False)
|
||||
ratelimiter.timeout_add(1.0)
|
||||
request.raise_for_status()
|
||||
json_request = await request.json(encoding="UTF-8")
|
||||
except (aiohttp.ClientConnectionError, aiohttp.ServerTimeoutError, asyncio.TimeoutError):
|
||||
|
@ -108,11 +112,11 @@ class Wiki:
|
|||
logger.warning('{} rows affected by DELETE FROM rcgcdw WHERE wiki = "{}"'.format(db_cursor.rowcount, wiki_url))
|
||||
db_connection.commit()
|
||||
|
||||
async def pull_comment(self, comment_id, WIKI_API_PATH):
|
||||
async def pull_comment(self, comment_id, WIKI_API_PATH, rate_limiter):
|
||||
try:
|
||||
comment = await self.safe_request(
|
||||
"{wiki}?action=comment&do=getRaw&comment_id={comment}&format=json".format(wiki=WIKI_API_PATH,
|
||||
comment=comment_id), "text")
|
||||
comment=comment_id), rate_limiter, "text")
|
||||
logger.debug("Got the following comment from the API: {}".format(comment))
|
||||
if comment is None:
|
||||
raise TypeError
|
||||
|
@ -186,20 +190,16 @@ async def process_mwmsgs(wiki_response: dict, local_wiki: Wiki, mw_msgs: dict):
|
|||
local_wiki.mw_messages = key
|
||||
|
||||
# db_wiki: webhook, wiki, lang, display, wikiid, rcid, postid
|
||||
async def essential_info(change: dict, changed_categories, local_wiki: Wiki, db_wiki: tuple, target: tuple, paths: tuple, request: dict):
|
||||
async def essential_info(change: dict, changed_categories, local_wiki: Wiki, target: tuple, paths: tuple, request: dict,
|
||||
rate_limiter: RateLimiter):
|
||||
"""Prepares essential information for both embed and compact message format."""
|
||||
def _(string: str) -> str:
|
||||
"""Our own translation string to make it compatible with async"""
|
||||
return lang.gettext(string)
|
||||
|
||||
lang = langs[target[0][0]]
|
||||
ngettext = lang.ngettext
|
||||
_ = langs[target[0][0]]["wiki"].gettext
|
||||
# recent_changes = RecentChangesClass() # TODO Look into replacing RecentChangesClass with local_wiki
|
||||
changed_categories = changed_categories.get(change["revid"], None)
|
||||
logger.debug("List of categories in essential_info: {}".format(changed_categories))
|
||||
appearance_mode = embed_formatter if target[0][1] > 0 else compact_formatter
|
||||
if "actionhidden" in change or "suppressed" in change: # if event is hidden using suppression
|
||||
await appearance_mode("suppressed", change, "", changed_categories, local_wiki, target, _, ngettext, paths)
|
||||
await appearance_mode("suppressed", change, "", changed_categories, local_wiki, target, paths, rate_limiter)
|
||||
return
|
||||
if "commenthidden" not in change:
|
||||
parsed_comment = parse_link(paths[3], change["parsedcomment"])
|
||||
|
@ -223,16 +223,11 @@ async def essential_info(change: dict, changed_categories, local_wiki: Wiki, db_
|
|||
additional_data["tags"][tag["name"]] = (BeautifulSoup(tag["displayname"], "lxml")).get_text()
|
||||
except KeyError:
|
||||
additional_data["tags"][tag["name"]] = None # Tags with no displ
|
||||
await appearance_mode(identification_string, change, parsed_comment, changed_categories, local_wiki, target, _, ngettext, paths, additional_data=additional_data)
|
||||
await appearance_mode(identification_string, change, parsed_comment, changed_categories, local_wiki, target, paths, rate_limiter, additional_data=additional_data)
|
||||
|
||||
|
||||
async def essential_feeds(change: dict, db_wiki: tuple, target: tuple):
|
||||
"""Prepares essential information for both embed and compact message format."""
|
||||
def _(string: str) -> str:
|
||||
"""Our own translation string to make it compatible with async"""
|
||||
return lang.gettext(string)
|
||||
|
||||
lang = langs[target[0][0]]
|
||||
appearance_mode = feeds_embed_formatter if target[0][1] > 0 else feeds_compact_formatter
|
||||
identification_string = change["_embedded"]["thread"][0]["containerType"]
|
||||
await appearance_mode(identification_string, change, target, db_wiki["wiki"], _)
|
||||
await appearance_mode(identification_string, change, target, db_wiki["wiki"])
|
||||
|
|
19
src/wiki_ratelimiter.py
Normal file
19
src/wiki_ratelimiter.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
import logging, time, asyncio
|
||||
|
||||
logger = logging.getLogger("rcgcdw.ratelimiter")
|
||||
|
||||
class RateLimiter:
|
||||
def __init__(self):
|
||||
self.timeout_until = 0
|
||||
|
||||
def timeout_add(self, timeout: float):
|
||||
"""This function sets a new timeout"""
|
||||
self.timeout_until = time.time() + timeout
|
||||
logger.debug("Added {} timeout".format(timeout))
|
||||
|
||||
async def timeout_wait(self):
|
||||
"""This awaitable calculates the time to wait according to timeout_until, does not wait if it's past the timeout to not skip a cycle"""
|
||||
calculated_timeout = self.timeout_until - time.time()
|
||||
logger.debug("Waiting {}".format(calculated_timeout))
|
||||
if calculated_timeout > 0:
|
||||
await asyncio.sleep(calculated_timeout)
|
Loading…
Reference in a new issue