Compare commits

...

274 Commits

Author SHA1 Message Date
Harvey Tindall
0fe72b41bf lowercase lang 2021-10-03 16:45:51 +01:00
xarmadigi
a1d93cd6af Translated using Weblate (Spanish)
Currently translated at 83.3% (5 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/chat-bots/es/
2021-10-03 17:37:22 +02:00
Luis Rhenals
53ac01eda4 Translated using Weblate (Spanish)
Currently translated at 88.8% (8 of 9 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/password-reset-links/es/
2021-10-03 17:37:22 +02:00
Luis Rhenals
4cea755065 translation from Weblate (Spanish)
Currently translated at 100.0% (168 of 168 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/admin/es/
2021-10-03 17:37:22 +02:00
Luis Rhenals
be4e83d69c Translated using Weblate (Spanish)
Currently translated at 85.0% (17 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/common-strings/es/
2021-10-03 17:37:22 +02:00
xarmadigi
1e58a33c68 Translated using Weblate (Spanish)
Currently translated at 85.0% (17 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/common-strings/es/
2021-10-03 17:37:22 +02:00
xarmadigi
15e1766920 Added translation using Weblate (Spanish) 2021-10-03 17:37:22 +02:00
Harvey Tindall
a220ba8dfb fix NewEmptyLogger
for #151.
Dumb bug, I really need unit tests.
2021-10-03 15:59:58 +01:00
Harvey Tindall
b29c24a405 merge lang 2021-09-18 13:44:54 +01:00
Harvey Tindall
fbe3553b25 fix missing last log line
Sometimes calls to app.err.Fatalf would fail to print the error to the
console, and fail to show "A crash report has been saves to...". Both of
these should be fixed now.
2021-09-18 13:43:11 +01:00
xarmadigi
f727e2c5b2 translation from Weblate (Spanish)
Currently translated at 88.0% (148 of 168 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/admin/es/
2021-09-04 23:09:56 +02:00
XCQi
6c6af623a6 translation from Weblate (Chinese (Simplified))
Currently translated at 100.0% (168 of 168 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/admin/zh_Hans/
2021-08-28 21:55:25 +02:00
Harvey Tindall
548dceda28 don't give smtp plainauth if no username & password
for #141, just a guess
2021-08-26 21:03:02 +01:00
Harvey Tindall
e67b2e91fb invite: auto-append /invite if missing to url_base 2021-08-26 18:53:22 +01:00
Harvey Tindall
412fe31da6 invite: fix email confirmation jwt
same issue as with auth.go, expiry was a string causing the library to
see it as expired.
2021-08-26 18:39:50 +01:00
Harvey Tindall
1bfec54c93 print error and include in txt log on crash; fix email migration 2021-08-25 18:10:06 +01:00
Harvey Tindall
5b319d6612 auth: int for refresh token as well 2021-08-22 15:00:20 +01:00
Harvey Tindall
626d623841 auth: don't store jwt expiry as string
caused the jwt library to class all tokens as invalid, now stored as
int64 and converted into a float64 by the library.
2021-08-22 14:13:44 +01:00
Harvey Tindall
08343298fb lowercase lang 2021-08-22 14:13:30 +01:00
Harvey Tindall
7a343bbc08 merge lang 2021-08-22 13:54:44 +01:00
Harvey Tindall
2be34ed063 quote jellyfin URL for censoring in logs 2021-08-22 13:54:39 +01:00
XCQi
7e32c8c4f0 translation from Weblate (Chinese (Simplified))
Currently translated at 43.4% (73 of 168 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/admin/zh_Hans/
2021-08-22 14:45:55 +02:00
XCQi
a0871e7c47 Translated using Weblate (Chinese (Simplified))
Currently translated at 98.0% (50 of 51 strings)

Translation: jfa-go/Emails
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/emails/zh_Hans/
2021-08-22 14:45:55 +02:00
XCQi
f6834ee63d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/chat-bots/zh_Hans/
2021-08-22 14:45:55 +02:00
XCQi
54b8e30cff Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (9 of 9 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/password-reset-links/zh_Hans/
2021-08-22 14:45:55 +02:00
XCQi
504d3e39de Translated using Weblate (Chinese (Simplified))
Currently translated at 95.4% (104 of 109 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/setup/zh_Hans/
2021-08-22 14:45:55 +02:00
XCQi
4e2dce7f18 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (20 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/common-strings/zh_Hans/
2021-08-22 14:45:55 +02:00
XCQi
b31506d94e translation from Weblate (Chinese (Simplified))
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/form/zh_Hans/
2021-08-22 14:45:55 +02:00
XCQi
5961bc6086 add translation from Weblate (Chinese (Simplified)) 2021-08-22 14:45:55 +02:00
XCQi
b0ffa457df Added translation using Weblate (Chinese (Simplified)) 2021-08-22 14:45:55 +02:00
XCQi
9e3fa0ea9a Added translation using Weblate (Chinese (Simplified)) 2021-08-22 14:45:55 +02:00
XCQi
ff69d0ba6d Added translation using Weblate (Chinese (Simplified)) 2021-08-22 14:45:55 +02:00
XCQi
cf25472746 Added translation using Weblate (Chinese (Simplified)) 2021-08-22 14:45:55 +02:00
XCQi
5e651d7b08 Added translation using Weblate (Chinese (Simplified)) 2021-08-22 14:45:55 +02:00
XCQi
bcd1011b68 add translation from Weblate (Chinese (Simplified)) 2021-08-22 14:45:55 +02:00
vaheeD khoshnouD
f8f0715a3b Translated using Weblate (Persian)
Currently translated at 100.0% (9 of 9 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/password-reset-links/fa/
2021-08-22 14:45:55 +02:00
vaheeD khoshnouD
e27e08bfd7 Translated using Weblate (Persian)
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/chat-bots/fa/
2021-08-22 14:45:55 +02:00
vaheeD khoshnouD
ae4d47af43 Translated using Weblate (Persian)
Currently translated at 100.0% (20 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/common-strings/fa/
2021-08-22 14:45:54 +02:00
vaheeD khoshnouD
b32271e375 translation from Weblate (Persian)
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/form/fa/
2021-08-22 14:45:54 +02:00
mLgz0rn
753e233e27 translation from Weblate (Danish)
Currently translated at 100.0% (168 of 168 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/admin/da/
2021-08-22 14:45:54 +02:00
mLgz0rn
d6669bfa70 Translated using Weblate (Danish)
Currently translated at 100.0% (109 of 109 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/setup/da/
2021-08-22 14:45:54 +02:00
mLgz0rn
94b288671d translation from Weblate (Danish)
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/form/da/
2021-08-22 14:45:54 +02:00
ClankJake
a444e53a99 translation from Weblate (Portuguese (Brazil))
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/form/pt_BR/
2021-08-22 14:45:54 +02:00
vaheeD khoshnouD
792846f727 Added translation using Weblate (Persian) 2021-08-22 14:45:54 +02:00
vaheeD khoshnouD
6b9fa7bf8a Added translation using Weblate (Persian) 2021-08-22 14:45:54 +02:00
vaheeD khoshnouD
c4378d19db Added translation using Weblate (Persian) 2021-08-22 14:45:54 +02:00
vaheeD khoshnouD
bdebd97dc0 add translation from Weblate (Persian) 2021-08-22 14:45:54 +02:00
Richard de Boer
cf2bd6c095 Translated using Weblate (Dutch)
Currently translated at 100.0% (9 of 9 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/password-reset-links/nl/
2021-08-22 14:45:54 +02:00
ClankJake
08f3675f71 translation from Weblate (Portuguese (Brazil))
Currently translated at 100.0% (168 of 168 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/admin/pt_BR/
2021-08-22 14:45:54 +02:00
ClankJake
8d53ddcf93 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (105 of 105 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/setup/pt_BR/
2021-08-22 14:45:54 +02:00
Richard de Boer
c20dc24ccf translation from Weblate (Dutch)
Currently translated at 100.0% (168 of 168 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/admin/nl/
2021-08-22 14:45:54 +02:00
Richard de Boer
b60be0db6d Added translation using Weblate (Dutch) 2021-08-22 14:45:54 +02:00
Harvey Tindall
756e7345cf tray: remove systray dep in non-tray builds 2021-08-18 17:25:16 +01:00
Harvey Tindall
eb3489b34f tray: fix crashlogs, restart from web 2021-08-16 23:01:08 +01:00
Harvey Tindall
9693ce3dcd settings: add redundant URL base for pwr
having it under "Invite Emails" when they weren't in use was confusing.
If only one is set in the config file, it'll be used for both.
2021-07-27 16:53:16 +01:00
Harvey Tindall
6e88c1f4fc setup: MkdirAll config dir if necessary
some have had this issue in the past on new systems/users where ~/.config
doesn't exist yet.
2021-07-27 10:54:52 +01:00
Harvey Tindall
67c60cb677 fix 'jfa-go systemd' layout
lines were printing out-of-order for some reason, so i added time.Sleep
between them.
2021-07-27 10:47:07 +01:00
Harvey Tindall
1a6b0d2b6e upgrade vulnerable deps
upgrade gin and switch dgrijalva/jwt-go to golang-jwt/jwt.
2021-07-27 10:08:01 +01:00
Harvey Tindall
5aaab7904f update contributing
also now hosted on wiki.jfa-go.com.
2021-07-25 01:13:57 +01:00
Harvey Tindall
9885c25a2e email: cleanup; allow re-enabling of custom email without changes 2021-07-24 19:49:08 +01:00
Harvey Tindall
27ad7a4cf7 setup: add descriptive "test connection" messages; disable next button
for #129.
2021-07-24 14:15:10 +01:00
Harvey Tindall
6551eeb938 setup: also respect -host 2021-07-21 17:24:06 +01:00
Harvey Tindall
36c23c1e4f setup: respect -p/-port
fixes #128.
2021-07-21 17:17:59 +01:00
Harvey Tindall
6b4d4da455 accounts: show cog when user known for disabled chatbot 2021-07-20 15:45:00 +01:00
Harvey Tindall
aa2891fc87 matrix: fix instant crash with e2ee
also some more attempts at fixing it, so far all i've found is that if
we don't delete the cryptoStore, the matrix client also gets the same
error we do if it send s a message to us (no session with given ID
found).
2021-07-20 15:34:39 +01:00
Harvey Tindall
db526fc611 exit: improve line number, include stack 2021-07-20 14:57:48 +01:00
Harvey Tindall
a869acd5dc exit: include file/line with error 2021-07-20 14:39:20 +01:00
Harvey Tindall
f763cfb53a announcements: fix [] on {{ .username }} 2021-07-16 20:57:11 +01:00
Harvey Tindall
25a8d3807e announcements: {{ .username }} 2021-07-16 19:46:05 +01:00
Harvey Tindall
b10b558358 announcements: add {username}
also works in the subject.
2021-07-16 19:39:06 +01:00
Harvey Tindall
504b602c0b Merge pull request #127 from hrfee/mautrix
fix external fs; switch to mautrix over gomatrix
2021-07-16 17:17:07 +01:00
Harvey Tindall
f04411e137 matrix: remove crypto dep in main file 2021-07-16 17:11:17 +01:00
Harvey Tindall
1336a87ae2 drone: use custom container for pr builds 2021-07-16 16:50:31 +01:00
Harvey Tindall
872c366384 go mod tidy 2021-07-16 15:51:27 +01:00
Harvey Tindall
762d5325fb matrix: E2EE as build option
since this is so broken and requires CGO deps, E2EE support is now only
included with "make E2EE=on ...". The option to enable will then appear
in settings.
2021-07-16 15:44:14 +01:00
Harvey Tindall
7f37633423 fix external fs 2021-07-16 15:39:22 +01:00
Harvey Tindall
8ec4031ba3 matrix: refactor crypto sections 2021-07-16 14:33:51 +01:00
Harvey Tindall
4c10996c09 matrix: ugly hack to fix encryption after restarts
with a persistent crypto.Store, element reports "** Unable to decrypt:
The secure channel with the sender was corrupted. **", and others
clients just fail. Deleting it before reinitialising the OlmMachine
stops this, although the first message to a user takes a while as i
guess it has re-establish a session (idk, this is above me).
2021-07-14 17:55:26 +01:00
Harvey Tindall
4d3acb2c4c settings: include custom email template setting 2021-07-14 16:48:50 +01:00
Harvey Tindall
833d02b032 matrix: end-to-end encryption by default
Existing chats will remain unencrypted but new ones will be.
2021-07-13 19:02:16 +01:00
Harvey Tindall
30198fab87 matrix: switch to mautrix-go
hopefully this can be used to support end-to-end encryption.
2021-07-13 14:53:33 +01:00
Richard de Boer
51768958c6 Translated using Weblate (Dutch)
Currently translated at 100.0% (105 of 105 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.jfa-go.com/projects/jfa-go/setup/nl/
2021-07-13 15:25:34 +02:00
Harvey Tindall
3e55cd1e31 accounts: add templates for announcements
you can now save announcements as templates, and then use them later by
hovering over the "Announce" button, as well as delete them.
2021-07-10 16:43:27 +01:00
Harvey Tindall
35f0fead53 site: add explanation of release channels 2021-07-09 16:09:23 +01:00
Harvey Tindall
a95d8bff29 site: add syntax highlighting for code 2021-06-30 18:25:51 +01:00
Harvey Tindall
48332a4ffa lowercase lang 2021-06-30 18:10:04 +01:00
Harvey Tindall
2266bbc320 merge translations 2021-06-30 18:06:45 +01:00
Harvey Tindall
b682685a3b update weblate link 2021-06-30 18:06:31 +01:00
mLgz0rn
91411437e2 translation from Weblate (Danish)
Currently translated at 100.0% (163 of 163 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
119bed7024 translation from Weblate (Danish)
Currently translated at 52.1% (85 of 163 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
6d70a5b24b Translated using Weblate (Danish)
Currently translated at 100.0% (9 of 9 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/password-reset-links/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
a99ee04aca Translated using Weblate (Danish)
Currently translated at 100.0% (20 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
3ca2315290 Translated using Weblate (Danish)
Currently translated at 99.0% (100 of 101 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/setup/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
d4bcf229e9 Translated using Weblate (Danish)
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/chat-bots/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
3950455a3f Translated using Weblate (Danish)
Currently translated at 94.1% (48 of 51 strings)

Translation: jfa-go/Emails
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/emails/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
7e8e242db0 translation from Weblate (Danish)
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
cda90f20af add translation from Weblate (Danish) 2021-06-30 18:57:11 +02:00
mLgz0rn
8ba393ebc0 Added translation using Weblate (Danish) 2021-06-30 18:57:11 +02:00
mLgz0rn
2de1570a98 Translated using Weblate (Danish)
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/chat-bots/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
6b01e0d44d Translated using Weblate (Danish)
Currently translated at 94.1% (48 of 51 strings)

Translation: jfa-go/Emails
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/emails/da/
2021-06-30 18:57:11 +02:00
mLgz0rn
af4dcd1e2a Added translation using Weblate (Danish) 2021-06-30 18:57:11 +02:00
mLgz0rn
a8ce68959d Added translation using Weblate (Danish) 2021-06-30 18:57:11 +02:00
mLgz0rn
05bc38565c Added translation using Weblate (Danish) 2021-06-30 18:57:11 +02:00
mLgz0rn
574ca4734d Added translation using Weblate (Danish) 2021-06-30 18:57:11 +02:00
mLgz0rn
0957dd58c2 add translation from Weblate (Danish) 2021-06-30 18:57:11 +02:00
thomasl78
4db5d96bb1 Translated using Weblate (French)
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/chat-bots/fr/
2021-06-30 18:57:11 +02:00
thomasl78
76c19731cb Translated using Weblate (French)
Currently translated at 100.0% (9 of 9 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/password-reset-links/fr/
2021-06-30 18:57:11 +02:00
thomasl78
fea368aaae Translated using Weblate (French)
Currently translated at 100.0% (20 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/fr/
2021-06-30 18:57:11 +02:00
thomasl78
1f8bc027c8 translation from Weblate (French)
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/fr/
2021-06-30 18:57:11 +02:00
thomasl78
f2240ebf0d translation from Weblate (French)
Currently translated at 99.3% (162 of 163 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/fr/
2021-06-30 18:57:11 +02:00
thomasl78
9b9f34ae96 Added translation using Weblate (French) 2021-06-30 18:57:11 +02:00
thomasl78
86559d5c76 Added translation using Weblate (French) 2021-06-30 18:57:11 +02:00
Harvey Tindall
40ec5b9933 site: update vulnerable build deps 2021-06-30 14:28:20 +01:00
Harvey Tindall
fbb9f20026 site: fix docker; modal with 'make all' 2021-06-30 01:17:08 +01:00
Harvey Tindall
d5a33cf242 site: fix uncss in make all 2021-06-30 00:48:37 +01:00
Harvey Tindall
c35fdc2cbe site: remove reference to 404 & favicon 2021-06-30 00:38:44 +01:00
Harvey Tindall
84d5bc8f67 site: fix dev dependency 2021-06-30 00:37:31 +01:00
Harvey Tindall
b8d9d22545 add landing page for jfa-go.com; move wiki
located in `site/`. Wiki now @ wiki.jfa-go.com.
2021-06-30 00:32:03 +01:00
Harvey Tindall
788afa1025 config: automatically add http://
for #124, apparently the stdlib needs it.
2021-06-27 01:10:08 +01:00
Harvey Tindall
6ca3ab899c bump mb to 0.3.5 2021-06-26 15:23:39 +01:00
Harvey Tindall
d4096d0062 pwr: trim suffix, not prefix for links 2021-06-24 14:24:08 +01:00
Harvey Tindall
306ede47d6 log: move accidental log message 2021-06-24 02:22:44 +01:00
Harvey Tindall
fc0e86ffd8 change wiki mentions to new location
now at jfa-go.com.
2021-06-23 22:31:11 +01:00
Harvey Tindall
729fc7baf7 Setup: add messages, set password via link
Also changed some section names to use "messages" instead of "emails".
Since I haven't added Discord/Telegram/Matrix bot setup, I mentioned you
can do these later and linked to the setup guides. Sections related to
email mostly now depend on [messages]/enabled now too. Set password via
link has been added to password resets.
2021-06-23 15:44:48 +01:00
Harvey Tindall
2d83e9ff7e add inline to Dockerfile 2021-06-20 20:01:04 +01:00
ClankJake
a0af76364a Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (7 of 7 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/password-reset-links/pt_BR/
2021-06-20 19:02:08 +02:00
ClankJake
169622bf95 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/chat-bots/pt_BR/
2021-06-20 19:02:08 +02:00
ClankJake
78b5136b9a Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (51 of 51 strings)

Translation: jfa-go/Emails
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/emails/pt_BR/
2021-06-20 19:02:08 +02:00
ClankJake
e546f50141 translation from Weblate (Portuguese (Brazil))
Currently translated at 99.3% (162 of 163 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/pt_BR/
2021-06-20 19:02:08 +02:00
ClankJake
e35fe8d425 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (20 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/pt_BR/
2021-06-20 19:02:08 +02:00
ClankJake
6ed2f7aaa6 translation from Weblate (Portuguese (Brazil))
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/pt_BR/
2021-06-20 19:02:08 +02:00
ClankJake
084e8ec432 Added translation using Weblate (Portuguese (Brazil)) 2021-06-20 19:02:08 +02:00
ClankJake
fd7f74682b Added translation using Weblate (Portuguese (Brazil)) 2021-06-20 19:02:08 +02:00
Harvey Tindall
9950c158a1 move copy button to right, don't uncss when DEBUG=on
keep unused css when DEBUG=on by skipping the uncss step.
2021-06-13 16:31:40 +01:00
Harvey Tindall
21125033ff Add copy button to crash page 2021-06-13 15:36:36 +01:00
Harvey Tindall
1dc0b2234a switch to normal npm mirror in package-lock
was using cnpm as i'd added it to help a user who was having problems
(ended up being internet-related, not blocking).
2021-06-11 23:46:01 +01:00
Harvey Tindall
0ea5c7fdc0 remove inline-css-cli build dep
unnecessary (inline-source-cli already includes its functionality) and a
dependency of it had a high-severity CVE (wouldn't have affected anyone,
but w/e).
2021-06-11 23:39:38 +01:00
Harvey Tindall
b538922c05 Show log on log.Fatal calls, provide "sanitized" version, fix goreleaser
Sanitization means change anything in double quotes to "CENSORED". A
notice is included telling the user to check for themselves as well.
2021-06-11 23:28:21 +01:00
Harvey Tindall
f0f4e8118e Generate crash report txt and webpage
The last 100 lines of logs are now cached, and when a crash occurs, they
are saved to a file in the temp directory ("/tmp" on *nix), and pretty
HTML version is also created and opened in the browser.
* Currently only handles panics, will be included in more places soon
* Copy button and button to generate a GH issue will be added
2021-06-11 21:56:53 +01:00
Harvey Tindall
2f501697db merge translations 2021-06-07 13:58:53 +01:00
Harvey Tindall
0a71d5b216 PWR: Add option to set new password from magic link
For #103. Enable in Settings > Password Resets. Also changes the user's
ombi password.
2021-06-07 13:49:05 +01:00
Harvey Tindall
0014db44f0 form: module-ize password validator 2021-06-05 22:17:10 +01:00
Harvey Tindall
885d2ebf0f admin: fix telegram/discord/matrix enabled varnames 2021-06-05 22:16:57 +01:00
Richard de Boer
6d089a9818 Translated using Weblate (Dutch)
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/chat-bots/nl/
2021-06-02 14:39:37 +02:00
Richard de Boer
de81c7e29f Added translation using Weblate (Dutch) 2021-06-02 14:39:37 +02:00
Harvey Tindall
e49996c401 Setup: Don't break if setup not completed, fix restart
Since an invalid example config was created on first run, if the app restarted
before setup was completed, it would crash on the next start. The
example now has a "first_run" flag in it, which is only set to false
when the config is modified. Also fixed restart at the end of setup for
tray builds.
2021-06-01 19:54:13 +01:00
Malte
aa40a72075 Translated using Weblate (German)
Currently translated at 100.0% (6 of 6 strings)

Translation: jfa-go/Telegram/Matrix/Discord bots
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/chat-bots/de/
2021-06-01 18:29:10 +02:00
Richard de Boer
19b7341e80 Translated using Weblate (Dutch)
Currently translated at 100.0% (20 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/nl/
2021-06-01 18:29:10 +02:00
Malte
73645a7569 Translated using Weblate (German)
Currently translated at 100.0% (20 of 20 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/de/
2021-06-01 18:29:10 +02:00
Malte
a9dac8c04c translation from Weblate (German)
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/de/
2021-06-01 18:29:09 +02:00
Malte
43fbbbcd16 translation from Weblate (German)
Currently translated at 100.0% (163 of 163 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/de/
2021-06-01 18:29:09 +02:00
Richard de Boer
fc57a8c97f translation from Weblate (Dutch)
Currently translated at 100.0% (37 of 37 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/nl/
2021-06-01 18:29:07 +02:00
Richard de Boer
1fb2ef5675 translation from Weblate (Dutch)
Currently translated at 100.0% (163 of 163 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/nl/
2021-06-01 18:29:06 +02:00
Malte
e0d994c35c Added translation using Weblate (German) 2021-06-01 17:21:53 +02:00
hrfee
cab30eb628 Added translation using Weblate (English (United Kingdom)) 2021-06-01 17:13:56 +02:00
Harvey Tindall
71df011556 merge translations 2021-06-01 16:13:28 +01:00
Levi
b2828110e3 Translated using Weblate (Swedish)
Currently translated at 100.0% (101 of 101 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/setup/sv/
2021-06-01 17:07:49 +02:00
Levi
50eb05776a translation from Weblate (Swedish)
Currently translated at 100.0% (32 of 32 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/sv/
2021-06-01 17:07:49 +02:00
Harvey Tindall
19715f25f6 Move all migrations to separate file
Also fixed some inconsistent uses of snake case.
2021-06-01 14:18:49 +01:00
Harvey Tindall
d41a281d53 mention tray icon in issue template 2021-06-01 00:54:22 +01:00
Harvey Tindall
a8229631bd mention matrix in readme 2021-06-01 00:06:35 +01:00
Harvey Tindall
0a2cf6132f merge matrix into local changes 2021-05-31 22:13:52 +01:00
Harvey Tindall
d7ab01063a apt: Use commit count to fix version comparisons
previous fix only worked because the numerical portion of the commit
hash happened to be greater. This should do properly fix it.
2021-05-31 22:11:43 +01:00
Harvey Tindall
6fb8f1ed7f Merge pull request #112 from hrfee/matrix
Matrix Integration
2021-05-31 21:12:57 +01:00
Harvey Tindall
a9b11012bc Matrix: Add example images 2021-05-31 20:56:29 +01:00
Harvey Tindall
e7cb1f516b Mention wiki in Telegram/Discord/Matrix settings descriptions 2021-05-31 20:32:16 +01:00
Harvey Tindall
555d5abf59 bump browserslist version 2021-05-31 18:53:21 +01:00
Harvey Tindall
93937ec3b5 drone: use pre-made image with dependencies
a cron job builds hrfee/jfa-go-build-docker daily, which includes the
apt dependencies for building.
2021-05-31 14:58:20 +01:00
Harvey Tindall
93c7a6e31b apt: Change versioning to hopefully fix updates
0.0.0-{commit} didn't register as updates to the previously installed
  versions, but it looks like 0{commit} works.
2021-05-31 14:13:41 +01:00
Harvey Tindall
a9cabe3d74 apt: also remove jfa-go-tray 2021-05-30 23:37:17 +01:00
Harvey Tindall
d6fd1d6894 apt: remove last unstable before adding
kind of a hack, since all versions have version number 0.0.0, reprepro
skips adding new files.
2021-05-30 23:26:50 +01:00
Harvey Tindall
375022ba95 Matrix: Add token generation wizard
Pressing the "+" next to matrix in settings allows you to enter a
homeserver, username and password to enable matrix and generate an
access token.
2021-05-30 23:09:20 +01:00
Harvey Tindall
75fdf6ec3d Matrix: Connect on accounts tab, customizable chat topic 2021-05-30 11:47:41 +01:00
Harvey Tindall
561c461a18 PWR: TrimPrefix instead of Replace for PWR links 2021-05-30 00:07:18 +01:00
Harvey Tindall
59ebf52fe2 Matrix: Show matrix on accounts page 2021-05-30 00:05:46 +01:00
Harvey Tindall
89fb3fa619 Matrix: Notifications 2021-05-29 21:05:12 +01:00
Harvey Tindall
9bd6abadf4 Matrix: Fix user storage 2021-05-29 19:50:33 +01:00
Harvey Tindall
953a66ec47 Password Resets: Ignore magic link visits from bots
For #108. Literally just searches the useragent for "Bot", seems good
enough for Telegram atleast.
2021-05-29 19:24:00 +01:00
Harvey Tindall
4e826f4167 Matrix: Store user on sign-up 2021-05-29 18:51:43 +01:00
Harvey Tindall
e97b90d4d7 Matrix: Setup bot, add PIN verification
PIN is verified but not used currently. Works a little different than
the others, you input your matrix user ID and then the PIN is sent to
you. The bot doesn't support E2EE, so the bot being the first one to
message ensures the chat is unencrypted.
2021-05-29 17:43:11 +01:00
Harvey Tindall
fb6256d1ed Telegram: Escape all necessary characters
Fixes #108.
2021-05-25 23:03:13 +01:00
Harvey Tindall
7035a3fe9c Tray: Add button to open logs 2021-05-25 20:16:42 +01:00
Harvey Tindall
62c29d55cc Log output to TEMP/jfa-go.log when Tray enabled
-H=windowsgui completely disables Stdout/Stderr on Windows, so logging
is enabled.
2021-05-25 17:59:41 +01:00
Harvey Tindall
a83dbcf3ab debian/ubuntu, not just debian 2021-05-25 01:33:58 +01:00
Harvey Tindall
e48bdcc45b README: change install section layout
Downloads at the top also now link to parts in the install section.
2021-05-24 22:58:11 +01:00
Harvey Tindall
0b473ef01f don't put .debs on buildrone; link to instructions at top of README 2021-05-24 20:30:31 +01:00
Harvey Tindall
e03525a1d1 separate codenames for stable & unstable
templates don't work in name_template as i though, so this should work
instead.
2021-05-24 19:53:53 +01:00
Harvey Tindall
087172c79e fix package naming to avoid conflicts 2021-05-24 18:46:54 +01:00
Harvey Tindall
8fd919bf04 remove chglog, add steps to upload to apt.hrfee.dev
chglog isn't actually needed. Packages are uploaded as jfa-go(-git) and
jfa-go-tray(-git).
2021-05-24 18:37:26 +01:00
Harvey Tindall
2ad84db482 add inaccurate chglog
not really correct, tagged as v0.3.6 despite the few extra commits.
2021-05-24 16:33:20 +01:00
Harvey Tindall
85536ff79e expand CONTRIBUTING, print if tray enabled on startup 2021-05-24 15:58:43 +01:00
Harvey Tindall
8b62c91d13 Mention TrayIcon deps in README 2021-05-23 23:49:48 +01:00
Harvey Tindall
e7d1693517 Enable updater for Tray builds 2021-05-23 23:20:14 +01:00
Harvey Tindall
e78b4882b3 Fix updater for zip files
Forgot to change this when I switched, oops.
2021-05-23 23:05:40 +01:00
Harvey Tindall
e01144950b Mention Discord in README 2021-05-23 22:41:39 +01:00
Harvey Tindall
86ef665b12 Discord: Try to avoid more race conditions
also added RACE=on to Makefile to enable go's race detector.
2021-05-23 22:26:56 +01:00
Harvey Tindall
f419a57e6d Fixed loaded message, Tray by default 2021-05-23 22:12:47 +01:00
Harvey Tindall
d7e8ec95de add missing perms, fix order 2021-05-23 20:48:17 +01:00
Harvey Tindall
5a9bc1c66f Merge Discord branch
Discord Integration, Accounts UI improvements
2021-05-23 20:25:15 +01:00
Harvey Tindall
1f9af8df89 Discord: Add option to provide server invite
When enabled, a temporary one-use invite is created and shown to the
user on the account creation form.
2021-05-23 19:50:03 +01:00
Harvey Tindall
0676b6c41f Discord: Display channel on account creation form 2021-05-23 17:31:20 +01:00
ClankJake
ac842e6273 translation from Weblate (Portuguese (Brazil))
Currently translated at 100.0% (32 of 32 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/pt_BR/
2021-05-23 18:23:21 +02:00
Harvey Tindall
ce8cdced4d Discord: Fix GetUsers, add invite messages
The "Send to" box on the invite tab now accepts username#discriminator,
and a search icon has been added which opens a search window similar to
the one on the accounts tab. DiscordDaemon.GetUsers was also very broken
and wouldn't work with full username#discriminator, that's been fixed.
2021-05-23 16:16:31 +01:00
Harvey Tindall
b8e3fc636c Accounts: Fix cog on telegram when no discord linked
Also, disable telegram & discord if an auth/initialization error occurs.
2021-05-23 14:48:36 +01:00
Harvey Tindall
519a5615cc Accounts: Fix email check on dropdown 2021-05-23 14:35:01 +01:00
Harvey Tindall
168b217553 Discord: fix user links 2021-05-23 14:32:35 +01:00
Harvey Tindall
7d698d63e3 Discord: split discord search into own module
Will also be used for "Send to" on the invite page.
2021-05-23 14:22:18 +01:00
Harvey Tindall
035dbde819 last image 2021-05-23 02:11:48 +01:00
Harvey Tindall
c373d8b2d6 add final oauth tab image 2021-05-23 02:08:02 +01:00
Harvey Tindall
8698c3c6a4 add oauth2 section to bot instructions 2021-05-23 02:03:55 +01:00
Harvey Tindall
0edd2ba68b add settings image for bot setup 2021-05-23 01:51:59 +01:00
Harvey Tindall
b91f0b5a18 Discord: add images for bot creation instructions 2021-05-23 01:38:40 +01:00
Harvey Tindall
24fa841c0d Discord: Wait for non-nil pointer to bot data
While testing others things, I had quite a few nil pointer dereference
errors from accessing bot data right after initializing. A for loop now
waits until the first of the pointers is non-nil, which should
hopefully avoid crashes.
2021-05-23 01:09:03 +01:00
Harvey Tindall
44558b8109 Discord: Remove extra newlines around links
Since links are converted into embeds, links put on their own line often
lead to extra newlines that looks pretty weird. They should now be
stripped.
2021-05-23 01:05:53 +01:00
Harvey Tindall
478b40d0ff Telegram: Escape exclamation marks, remove for images
![alt](link) becomes [alt](link), telegram seems to pick up that they're
images anyway.
2021-05-22 23:38:21 +01:00
Harvey Tindall
8b816dc725 merge translations 2021-05-22 23:26:49 +01:00
Harvey Tindall
81a58f628b Add -H=windowsgui in goreleaser 2021-05-22 23:26:13 +01:00
Harvey Tindall
e98c9b46f1 Accounts: no wrapping for contact dropdown 2021-05-22 23:18:43 +01:00
Harvey Tindall
b3ce7acfcb Accounts: Always inline icons, only one settings cog
Admin chip, email edit bot and contact method cog icon are now always inline.
Only one cog icon is shown now.
2021-05-22 23:05:53 +01:00
Harvey Tindall
9fac79b1f0 Discord: Add users via accounts tab
Doesn't require a PIN like Telegram, as we can access a list of guild
users with the GuildMembers intent set. This has to be enabled under
Bot > Priviliged Gateway intents on the developer portal.
2021-05-22 21:42:15 +01:00
Harvey Tindall
591e3c5ca1 Discord: embed images
![alt](image link) is now converted to an image embed.
2021-05-22 15:32:51 +01:00
Harvey Tindall
35d407afef Discord: remove @ from username 2021-05-22 15:31:25 +01:00
Harvey Tindall
a6447165b7 add email notify enable/disable; remove (de)hyphening
hyphen/dehyphen conflicted with new migration for email contact
preference, and it's been a while since this has been an issue so i've
just commented it out for now.
2021-05-21 22:46:46 +01:00
Malte
23800bb892 Translated using Weblate (German)
Currently translated at 100.0% (7 of 7 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/password-reset-links/de/
2021-05-21 23:02:50 +02:00
Malte
b47cb91f55 Translated using Weblate (German)
Currently translated at 100.0% (101 of 101 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/setup/de/
2021-05-21 23:02:50 +02:00
Malte
2d9e3fbc1d Translated using Weblate (German)
Currently translated at 100.0% (16 of 16 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/de/
2021-05-21 23:02:50 +02:00
Malte
bf67e27737 Translated using Weblate (German)
Currently translated at 100.0% (51 of 51 strings)

Translation: jfa-go/Emails
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/emails/de/
2021-05-21 23:02:50 +02:00
Malte
3427c97e3e translation from Weblate (German)
Currently translated at 100.0% (32 of 32 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/de/
2021-05-21 23:02:50 +02:00
Malte
81e69a7166 translation from Weblate (German)
Currently translated at 100.0% (156 of 156 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/de/
2021-05-21 23:02:50 +02:00
Malte
564098b9d8 Added translation using Weblate (German) 2021-05-21 23:02:50 +02:00
ClankJake
ec659174fb translation from Weblate (Portuguese (Brazil))
Currently translated at 100.0% (156 of 156 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/pt_BR/
2021-05-21 23:02:50 +02:00
ClankJake
1a42d8280c Translated using Weblate (Portuguese (Brazil))
Currently translated at 93.7% (15 of 16 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/pt_BR/
2021-05-21 23:02:50 +02:00
ClankJake
b14f10d79d translation from Weblate (Portuguese (Brazil))
Currently translated at 100.0% (32 of 32 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/pt_BR/
2021-05-21 23:02:50 +02:00
Cornichon420
ee8facd1bf Translated using Weblate (French)
Currently translated at 100.0% (16 of 16 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/fr/
2021-05-21 23:02:50 +02:00
Cornichon420
811657b553 Translated using Weblate (French)
Currently translated at 100.0% (51 of 51 strings)

Translation: jfa-go/Emails
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/emails/fr/
2021-05-21 23:02:50 +02:00
Cornichon420
95936f7c29 translation from Weblate (French)
Currently translated at 100.0% (32 of 32 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/fr/
2021-05-21 23:02:50 +02:00
Cornichon420
613d4cd9af translation from Weblate (French)
Currently translated at 100.0% (156 of 156 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/fr/
2021-05-21 23:02:50 +02:00
Richard de Boer
7beb3d9974 Translated using Weblate (Dutch)
Currently translated at 100.0% (16 of 16 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/nl/
2021-05-21 23:02:50 +02:00
Richard de Boer
6f2bb7f0b5 Translated using Weblate (Dutch)
Currently translated at 100.0% (51 of 51 strings)

Translation: jfa-go/Emails
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/emails/nl/
2021-05-21 23:02:50 +02:00
Richard de Boer
315b5fda91 translation from Weblate (Dutch)
Currently translated at 100.0% (32 of 32 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/nl/
2021-05-21 23:02:50 +02:00
Richard de Boer
a6aa89e502 translation from Weblate (Dutch)
Currently translated at 100.0% (156 of 156 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/nl/
2021-05-21 23:02:50 +02:00
Harvey Tindall
3bf722c5fe Discord: send links as embeds
Kind of janky but works. This kind of messes up the layout if you write
links in-line.
2021-05-21 21:59:50 +01:00
Harvey Tindall
e931c09a34 add message when web ui is loaded
a lack of output after "Loading routes" was a little confusing.
2021-05-21 21:39:32 +01:00
Harvey Tindall
f8f5f35cc1 PIN verification, notifications, multiple notif providers
Discord, Email & Telegram can be enabled, although email is always
enabled right now (will fix). Also apparently markdown hyperlinks don't
work in Discord, eventually will implement something to convert them to
embeds.
2021-05-21 21:35:25 +01:00
Harvey Tindall
524941da0c fix heading size with sm 2021-05-21 21:10:32 +01:00
Harvey Tindall
22bba922f9 Discord: Add !lang command 2021-05-18 18:41:42 +01:00
Harvey Tindall
d928df7ab2 Discord: Start bot, add !start and pin validity check
The bot should be created by the admin and added to a discord server
mutual to the intended new user(s). On !start in the server,
communication is moved to DMs. Currently !start works, and validity of a
given PIN is checked although nothing it done with this yet.
2021-05-17 23:42:33 +01:00
Harvey Tindall
4b11bbe21f remove leaked telegram token
token has been revoked, but it doesn't look like it was used anyway.
2021-05-17 11:43:58 +01:00
Harvey Tindall
18bcd55972 remove debug println 2021-05-17 01:32:22 +01:00
Harvey Tindall
057f306ed9 hide/ignore ssl_cert when on windows
x509.SystemCertPool is unavailable on windows, so any value is ignored
and the setting is hidden on the web UI.
2021-05-17 01:16:59 +01:00
Harvey Tindall
76bbb3f147 consistent naming for tray builds 2021-05-16 23:02:09 +01:00
Harvey Tindall
0f3ad8bb69 fix generate_ini for multiline descriptions 2021-05-16 23:00:37 +01:00
Harvey Tindall
1d47b9074f change notray/tray naming, add deb/rpm/apk
Since Tray support requires dependencies, it won't be the default for
releases. deb/rpm/apk support may be broken still.
2021-05-16 22:44:04 +01:00
Harvey Tindall
5167fde080 change tar.gz to zip in drone 2021-05-16 21:12:18 +01:00
Harvey Tindall
a62648ee68 fix cross compilation in goreleaser/drone
Necessary for go-autostart to work on windows. Tray will be enabled by
default for x86_64 windows/linux binaries.
2021-05-16 21:01:31 +01:00
Harvey Tindall
5dee414596 add "autostart on login" option to tray 2021-05-16 17:40:03 +01:00
Harvey Tindall
8cf9b1f905 add basic tray functionality
enable with `make TRAY=on ...`. Cross compilation apparently should work
from linux to linux & windows.
2021-05-16 16:23:28 +01:00
Harvey Tindall
6bf1920160 merge dependabot bump 2021-05-16 15:00:30 +01:00
Harvey Tindall
33f8070e57 cleanup; fix stripping with DEBUG=on 2021-05-16 15:00:13 +01:00
Harvey Tindall
4d2a018032 Merge pull request #98 from hrfee/dependabot/npm_and_yarn/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21
2021-05-14 14:48:41 +01:00
dependabot[bot]
ca7fb540ee Bump lodash from 4.17.20 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 21:24:34 +00:00
ClankJake
beb0712ce9 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (101 of 101 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/setup/pt_BR/
2021-05-09 20:59:31 +02:00
woosade
a081b14794 Translated using Weblate (Spanish)
Currently translated at 100.0% (7 of 7 strings)

Translation: jfa-go/Password Reset Links
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/password-reset-links/es/
2021-05-09 20:59:30 +02:00
woosade
e416acf6bd translation from Weblate (Spanish)
Currently translated at 100.0% (152 of 152 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/es/
2021-05-09 20:59:30 +02:00
woosade
bf94f76509 Translated using Weblate (Spanish)
Currently translated at 100.0% (101 of 101 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/setup/es/
2021-05-09 20:59:30 +02:00
Richard de Boer
ac239a309c translation from Weblate (Dutch)
Currently translated at 100.0% (152 of 152 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/nl/
2021-05-09 20:59:30 +02:00
Richard de Boer
0f12586166 Translated using Weblate (Dutch)
Currently translated at 100.0% (101 of 101 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/setup/nl/
2021-05-09 20:59:30 +02:00
Cornichon420
b1b50ce561 Translated using Weblate (French)
Currently translated at 100.0% (101 of 101 strings)

Translation: jfa-go/Setup
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/setup/fr/
2021-05-09 20:59:30 +02:00
Cornichon420
8e2bf48ab4 Translated using Weblate (French)
Currently translated at 100.0% (13 of 13 strings)

Translation: jfa-go/Common Strings
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/common-strings/fr/
2021-05-09 20:59:30 +02:00
Cornichon420
6ec5022a0d translation from Weblate (French)
Currently translated at 100.0% (28 of 28 strings)

Translation: jfa-go/Account Creation Form
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/form/fr/
2021-05-09 20:59:30 +02:00
Cornichon420
ef97e0ac76 translation from Weblate (French)
Currently translated at 100.0% (152 of 152 strings)

Translation: jfa-go/Admin Page
Translate-URL: https://weblate.hrfee.dev/projects/jfa-go/admin/fr/
2021-05-09 20:59:30 +02:00
Harvey Tindall
30736a055d add example bot settings for wiki 2021-05-08 16:37:40 +01:00
Harvey Tindall
d0905a29be add example bot creation for wiki 2021-05-08 16:29:16 +01:00
Harvey Tindall
fe5cf69b7a Merge Telegram support
For #94.
2021-05-08 16:15:41 +01:00
154 changed files with 22933 additions and 3271 deletions

View File

@@ -9,23 +9,28 @@ steps:
commands:
- git fetch --tags
- name: release
image: golang:latest
image: hrfee/jfa-go-build-docker:latest
volumes:
- name: ssh_key
path: /id_rsa
environment:
BUILDRONE_KEY:
from_secret: BUILDRONE_KEY
GITHUB_TOKEN:
from_secret: github_token
commands:
- apt-get update -y
- apt-get install build-essential python3-pip curl software-properties-common sed upx -y
- (curl -sL https://deb.nodesource.com/setup_14.x | bash -)
- apt-get install nodejs
- curl -sL https://git.io/goreleaser > ../goreleaser
- chmod +x ../goreleaser
- ./scripts/version.sh ../goreleaser
- wget https://builds.hrfee.pw/upload.py -P ../
- pip3 install requests
- bash -c 'sftp -P 2022 -i /id_rsa -o StrictHostKeyChecking=no root@161.97.102.153:/repo/incoming <<< $"put dist/*.deb"'
- bash -c 'ssh -i /id_rsa root@161.97.102.153 -p 2022 "repo-process-deb trusty"'
- bash -c 'python3 ../upload.py https://builds.hrfee.pw hrfee jfa-go --tag internal=true'
volumes:
- name: ssh_key
host:
path: /root/.ssh/id_rsa_packaging
trigger:
event:
- tag
@@ -71,22 +76,29 @@ type: docker
steps:
- name: build
image: golang:latest
image: hrfee/jfa-go-build-docker:latest
volumes:
- name: ssh_key
path: /id_rsa
commands:
- apt-get update -y
- apt-get install build-essential python3-pip curl software-properties-common sed upx -y
- (curl -sL https://deb.nodesource.com/setup_14.x | bash -)
- apt-get install nodejs
- curl -sL https://git.io/goreleaser > goreleaser
- chmod +x goreleaser
- ./scripts/version.sh ./goreleaser --snapshot --skip-publish --rm-dist
- wget https://builds.hrfee.pw/upload.py
- pip3 install requests
- bash -c 'python3 upload.py https://builds.hrfee.pw hrfee jfa-go --upload ./dist/*.tar.gz --tag internal-git=true'
- bash -c 'sftp -P 2022 -i /id_rsa -o StrictHostKeyChecking=no root@161.97.102.153:/repo/incoming <<< $"put dist/*.deb"'
# - bash -c 'ssh -i /id_rsa root@161.97.102.153 -p 2022 "reprepro -Vb /repo remove trusty-unstable jfa-go"'
# - bash -c 'ssh -i /id_rsa root@161.97.102.153 -p 2022 "reprepro -Vb /repo remove trusty-unstable jfa-go-tray"'
- bash -c 'ssh -i /id_rsa root@161.97.102.153 -p 2022 "repo-process-deb trusty"'
- bash -c 'python3 upload.py https://builds.hrfee.pw hrfee jfa-go --upload ./dist/*.zip ./dist/*.rpm ./dist/*.apk --tag internal-git=true'
environment:
BUILDRONE_KEY:
from_secret: BUILDRONE_KEY
volumes:
- name: ssh_key
host:
path: /root/.ssh/id_rsa_packaging
trigger:
branch:
- main
@@ -141,12 +153,8 @@ type: docker
steps:
- name: build
image: golang:latest
image: hrfee/jfa-go-build-docker:latest
commands:
- apt-get update -y
- apt-get install build-essential python3-pip curl software-properties-common sed upx -y
- (curl -sL https://deb.nodesource.com/setup_14.x | bash -)
- apt-get install nodejs
- curl -sL https://git.io/goreleaser > goreleaser
- chmod +x goreleaser
- ./scripts/version.sh ./goreleaser --snapshot --skip-publish --rm-dist

View File

@@ -19,8 +19,11 @@ What to do to reproduce the problem.
**Logs**
**If you're using a build with a tray icon, right-click on it and press "Open logs" to access your logs.**
When you notice the problem, check the output of `jfa-go`. If the problem is not obvious (e.g a panic (red text) or 'ERROR' log), re-run jfa-go with the `-debug` argument and reproduce the problem. You should then take a screenshot of the output, or paste it here, preferably between \`\`\` tags (e.g \`\`\``Log here`\`\`\`). Remember to censor any personal information.
If nothing catches your eye in the log, access the admin page via your browser, go into the console (Right click > Inspect Element > Console), refresh, reproduce the problem then paste the output here in the same way as above.
**Configuration**

4
.gitignore vendored
View File

@@ -1,4 +1,6 @@
node_modules/
site/node_modules/
site/out/
mail/*.html
dist/
build/
@@ -15,3 +17,5 @@ server.crt
instructions-debian.txt
cl.md
./telegram/
mautrix/
matacc.txt

View File

@@ -25,24 +25,81 @@ before:
- npx esbuild --bundle ts/pwr.ts --outfile=./data/web/js/pwr.js --minify
- npx esbuild --bundle ts/form.ts --outfile=./data/web/js/form.js --minify
- npx esbuild --bundle ts/setup.ts --outfile=./data/web/js/setup.js --minify
- npx esbuild --bundle ts/crash.ts --outfile=./data/crash.js --minify
- cp html/crash.html data/
- npx uncss data/crash.html --csspath web/css --output data/bundle.css
- npx inline-source --root data data/crash.html data/crash.html
- rm data/bundle.css
- mv data/crash.html data/html/
- go get -u github.com/swaggo/swag/cmd/swag
- swag init -g main.go
builds:
- dir: ./
- id: notray
dir: ./
env:
- CGO_ENABLED=0
ldflags:
- -s -w -X main.version={{.Env.JFA_GO_VERSION}} -X main.commit={{.ShortCommit}} -X main.updater=binary
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm
- arm64
- amd64
- id: windows-tray
dir: ./
env:
- CGO_ENABLED=1
- CC=x86_64-w64-mingw32-gcc
- CXX=x86_64-w64-mingw32-g++
flags:
- -tags=tray
ldflags:
- -s -w -X main.version={{.Env.JFA_GO_VERSION}} -X main.commit={{.ShortCommit}} -X main.updater=binary -H=windowsgui
goos:
- windows
goarch:
- amd64
- id: linux-tray
dir: ./
env:
- CGO_ENABLED=1
flags:
- -tags=tray
ldflags:
- -s -w -X main.version={{.Env.JFA_GO_VERSION}} -X main.commit={{.ShortCommit}} -X main.updater=binary
goos:
- linux
goarch:
- amd64
archives:
- replacements:
- id: windows-tray
builds:
- windows-tray
format: zip
name_template: "{{ .ProjectName }}_{{ .Version }}_TrayIcon_{{ .Os }}_{{ .Arch }}"
replacements:
darwin: macOS
linux: Linux
windows: Windows
amd64: x86_64
- id: linux-tray
builds:
- linux-tray
format: zip
name_template: "{{ .ProjectName }}_{{ .Version }}_TrayIcon_{{ .Os }}_{{ .Arch }}"
replacements:
darwin: macOS
linux: Linux
windows: Windows
amd64: x86_64
- id: notray
builds:
- notray
format: zip
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
replacements:
darwin: macOS
linux: Linux
windows: Windows
@@ -50,10 +107,61 @@ archives:
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "git-{{.ShortCommit}}"
name_template: "0.0.0-{{ .Env.JFA_GO_NFPM_EPOCH }}"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
nfpms:
- id: notray
file_name_template: '{{ .ProjectName }}{{ if .IsSnapshot }}-git{{ end }}_{{ .Arch }}_{{ if .IsSnapshot }}{{ .ShortCommit }}{{ else }}v{{ .Version }}{{ end }}'
package_name: jfa-go
homepage: https://github.com/hrfee/jfa-go
description: A web app for managing users on Jellyfin
maintainer: Harvey Tindall <hrfee@hrfee.dev>
license: MIT
vendor: hrfee.dev
version_metadata: git
builds:
- notray
contents:
- src: ./LICENSE
dst: /usr/share/licenses/jfa-go
formats:
- apk
- deb
- rpm
- id: tray
file_name_template: '{{ .ProjectName }}{{ if .IsSnapshot }}-git{{ end }}_TrayIcon_{{ .Arch }}_{{ if .IsSnapshot }}{{ .ShortCommit }}{{ else }}v{{ .Version }}{{ end }}'
package_name: jfa-go-tray
homepage: https://github.com/hrfee/jfa-go
description: A web app for managing users on Jellyfin
maintainer: Harvey Tindall <hrfee@hrfee.dev>
license: MIT
vendor: hrfee.dev
version_metadata: git
builds:
- linux-tray
contents:
- src: ./LICENSE
dst: /usr/share/licenses/jfa-go
formats:
- apk
- deb
- rpm
overrides:
deb:
conflicts:
- jfa-go
replaces:
- jfa-go
dependencies:
- libappindicator3-1
rpm:
dependencies:
- libappindicator-gtk3
apk:
dependencies:
- libappindicator

View File

@@ -1,15 +1,44 @@
#### Code
---
title: "Building/Contributing for developers"
date: 2021-07-25T00:33:36+01:00
draft: false
---
# Code
I use 4 spaces for indentation. Go should ideally be formatted with `goimports` and/or `gofmt`. I don't use a formatter on typescript, so don't worry about that.
#### Compiling
Code in Go should ideally use `PascalCase` for exported values, and `camelCase` for non-exported, JSON for transferring data should use `snake_case`, and Typescript should use `camelCase`. Forgive me for my many inconsistencies in this, and feel free to fix them if you want.
Prefix each of these with `make DEBUG=on INTERNAL=off `:
Functions in Go that need to access `*appContext` should be generally be receivers, except when the behaviour could be seen as somewhat independent from it (`email.go` is the best example, its behaviour is broadly independent from the main app except from a couple config values).
# Compiling
The Makefile is more suited towards development than other build methods, and provides separate build stages to speed up compilation when only making changes to specific aspects of the project.
Prefix each of these with `make DEBUG=on `:
* `all` will download deps and build everything. The executable and data will be placed in `build`. This is only necessary the first time.
* `npm` will download all node.js build-time dependencies.
* `compile` will only compile go code into the `build/jfa-go` executable.
* `typescript` will compile typescript w/ sourcemaps into `build/data/web/js`.
* `bundle-css` will bundle CSS and place it in `build/data/web/css`.
* `inline` will inline the css and javascript used in the single-file crash report webpage.
* `configuration` will generate the `config-base.json` (used to render settings in the web ui) and `config-default.ini` and put them in `build/data`.
* `email` will compile email mjml, and copy the text versions in to `build/data`.
* `swagger`: generates swagger documentation for the API.
* `copy` will copy iconography, html, language files and static data into `build/data`.
See the [wiki](https://github.com/hrfee/jfa-go/wiki/Build) for more info.
## Environment variables
* `DEBUG=on/off`: If on, compiles with type-checking for typescript, sourcemaps, non-minified css and no symbol stripping.
* `INTERNAL=on/off`: Whether or not to embed file assets into the binary itself, or store them separately beside the binary.
* `UPDATER=on/off/docker`: Enable/Disable the updater, or set a special update type (currently only docker, which disables self-updating the binary).
* `TRAY=on/off`: Enable/disable the tray icon, which lets you start/stop/autostart on login. For linux, requires `libappindicator3-dev` for debian or the equivalent on other distributions.
* `GOESBUILD=on`: Use a locally installed `esbuild` binary. NPM doesn't provide builds for all os/architectures, so `npx esbuild` might not work for you, so the binary is compiled/installed with `go get`.
* `GOBINARY=<path to go>`: Alternative path to go executable. Useful for testing with unstable go releases.
* `VERSION=v<semver>`: Alternative verision number, useful to test update functionality.
* `COMMIT=<short commit>`: Self explanatory.
* `LDFLAGS=<ldflags>`: Passed to `go build -ldflags`.
* `E2EE=on/off`: Enable/disable end-to-end encryption support for Matrix, which is currently very broken. Must subsequently be enabled (with Advanced settings enabled) in Settings > Matrix.
* `TAGS=<tags>`: Passed to `go build -tags`.
* `OS=<os>`: Unrelated to GOOS, if set to `windows`, `-H=windowsgui` is passed to ldflags, which stops a windows terminal popping up when run.
* `RACE=on/off`: If on, compiles with the go race detector included.

View File

@@ -6,7 +6,7 @@ RUN apt-get update -y \
&& apt-get install build-essential python3-pip curl software-properties-common sed -y \
&& (curl -sL https://deb.nodesource.com/setup_14.x | bash -) \
&& apt-get install nodejs \
&& (cd /opt/build; make configuration npm email typescript bundle-css swagger copy INTERNAL=off GOESBUILD=on) \
&& (cd /opt/build; make configuration npm email typescript bundle-css inline swagger copy INTERNAL=off GOESBUILD=on) \
&& sed -i 's#id="password_resets-watch_directory" placeholder="/config/jellyfin"#id="password_resets-watch_directory" value="/jf" disabled#g' /opt/build/build/data/html/setup.html

View File

@@ -1,3 +1,5 @@
---jfa-go---
MIT License
Copyright (c) 2021 Harvey Tindall
@@ -19,3 +21,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -18,26 +18,55 @@ else ifneq ($(UPDATER), off)
LDFLAGS := $(LDFLAGS) -X main.updater=$(UPDATER)
endif
INTERNAL ?= on
TRAY ?= off
E2EE ?= off
TAGS := -tags "
ifeq ($(INTERNAL), on)
TAGS :=
DATA := data
else
DATA := build/data
TAGS := -tags external
TAGS := $(TAGS) external
endif
ifeq ($(TRAY), on)
TAGS := $(TAGS) tray
endif
ifeq ($(E2EE), on)
TAGS := $(TAGS) e2ee
endif
TAGS := $(TAGS)"
OS := $(shell go env GOOS)
ifeq ($(TRAY)$(OS), onwindows)
LDFLAGS := $(LDFLAGS) -H=windowsgui
endif
DEBUG ?= off
ifeq ($(DEBUG), on)
LDFLAGS := -s -w $(LDFLAGS)
SOURCEMAP := --sourcemap
TYPECHECK := tsc -noEmit --project ts/tsconfig.json
# jank
COPYTS := rm -r $(DATA)/web/js/ts; cp -r ts $(DATA)/web/js
UNCSS := cp $(DATA)/web/css/bundle.css $(DATA)/bundle.css
else
LDFLAGS := -s -w $(LDFLAGS)
SOURCEMAP :=
COPYTS :=
TYPECHECK :=
UNCSS := npx uncss $(DATA)/crash.html --csspath web/css --output $(DATA)/bundle.css
endif
RACE ?= off
ifeq ($(RACE), on)
RACEDETECTOR := -race
else
RACEDETECTOR :=
endif
npm:
@@ -68,6 +97,7 @@ typescript:
-$(ESBUILD) --bundle ts/pwr.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/pwr.js --minify
-$(ESBUILD) --bundle ts/form.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/form.js --minify
-$(ESBUILD) --bundle ts/setup.ts $(SOURCEMAP) --outfile=./$(DATA)/web/js/setup.js --minify
-$(ESBUILD) --bundle ts/crash.ts --outfile=./$(DATA)/crash.js --minify
$(COPYTS)
swagger:
@@ -79,7 +109,7 @@ compile:
$(GOBINARY) mod download
$(info Building)
mkdir -p build
CGO_ENABLED=0 $(GOBINARY) build -ldflags="-s -w $(LDFLAGS)" $(TAGS) -o build/jfa-go
$(GOBINARY) build $(RACEDETECTOR) -ldflags="$(LDFLAGS)" $(TAGS) -o build/jfa-go
compress:
upx --lzma build/jfa-go
@@ -89,11 +119,18 @@ bundle-css:
$(info bundling css)
$(ESBUILD) --bundle css/base.css --outfile=$(DATA)/web/css/bundle.css --external:remixicon.css --minify
inline:
cp html/crash.html $(DATA)/crash.html
$(UNCSS)
npx inline-source --root $(DATA) $(DATA)/crash.html $(DATA)/crash.html
rm $(DATA)/bundle.css
copy:
$(info copying fonts)
cp -r node_modules/remixicon/fonts/remixicon.css node_modules/remixicon/fonts/remixicon.woff2 $(DATA)/web/css/
$(info copying html)
cp -r html $(DATA)/
mv $(DATA)/crash.html $(DATA)/html/
$(info copying static data)
-mkdir -p $(DATA)/web
cp -r static/* $(DATA)/web/
@@ -122,4 +159,4 @@ clean:
-rm docs/docs.go docs/swagger.json docs/swagger.yaml
go clean
all: configuration npm email typescript bundle-css swagger copy compile
all: configuration npm email typescript bundle-css inline swagger copy compile

View File

@@ -1,15 +1,19 @@
![jfa-go](images/banner.svg)
[![Build Status](https://drone.hrfee.dev/api/badges/hrfee/jfa-go/status.svg?ref=refs/heads/main)](https://drone.hrfee.dev/hrfee/jfa-go)
[![Docker Hub](https://img.shields.io/docker/pulls/hrfee/jfa-go?label=docker)](https://hub.docker.com/r/hrfee/jfa-go)
[![Translation status](https://weblate.hrfee.pw/widgets/jfa-go/-/svg-badge.svg)](https://weblate.hrfee.pw/engage/jfa-go/)
[![Translation status](https://weblate.jfa-go.com/widgets/jfa-go/-/svg-badge.svg)](https://weblate.jfa-go.com/engage/jfa-go/)
[![Docs/Wiki](https://img.shields.io/static/v1?label=documentation&message=jfa-go.com&color=informational)](https://wiki.jfa-go.com)
##### Downloads:
##### [dockerhub](https://hub.docker.com/r/hrfee/jfa-go) | [stable](https://github.com/hrfee/jfa-go/releases) | [nightly](https://builds.hrfee.pw/view/hrfee/jfa-go) | [aur stable](https://aur.archlinux.org/packages/jfa-go) | [aur binary](https://aur.archlinux.org/packages/jfa-go-bin) | [aur nightly](https://aur.archlinux.org/packages/jfa-go-git)
##### [docker](#docker) | [debian/ubuntu](#debian) | [arch (aur)](#aur) | [other platforms](#other-platforms)
---
jfa-go is a user management app for [Jellyfin](https://github.com/jellyfin/jellyfin) (and now [Emby](https://emby.media/)) that provides invite-based account creation as well as other features that make one's instance much easier to manage.
a rewrite of [jellyfin-accounts](https://github.com/hrfee/jellyfin-accounts) (original naming for both, ik
😂).
#### Features
* 🧑 Invite based account creation: Sends invites to your friends or family, and let them choose their own username and password without relying on you.
* 🧑 Invite based account creation: Send invites to your friends or family, and let them choose their own username and password without relying on you.
* Send invites via a link and/or email
* Granular control over invites: Validity period as well as number of uses can be specified.
* Account profiles: Assign settings profiles to invites so new users have your predefined permissions, homescreen layout, etc. applied to their account on creation.
@@ -17,7 +21,7 @@ jfa-go is a user management app for [Jellyfin](https://github.com/jellyfin/jelly
* ⌛ User expiry: Specify a validity period, and new users accounts will be disabled/deleted after it. The period can be manually extended too.
* 🔗 Ombi Integration: Automatically creates Ombi accounts for new users using their email address and login details, and your own defined set of permissions.
* Account management: Apply settings to your users individually or en masse, and delete users, optionally sending them an email notification with a reason.
* Telegram Integration: Verify users via telegram, and send Password Resets, Announcements, etc. through it.
* Telegram/Discord/Matrix Integration: Verify users via a chat bot, and send Password Resets, Announcements, etc. through it.
* 📨 Email storage: Add your existing users email addresses through the UI, and jfa-go will ask new users for them on account creation.
* Email addresses can optionally be used instead of usernames
* 🔑 Password resets: When users forget their passwords and request a change in Jellyfin, jfa-go reads the PIN from the created file and sends it straight to the user via email/telegram.
@@ -43,7 +47,9 @@ jfa-go is a user management app for [Jellyfin](https://github.com/jellyfin/jelly
#### Install
The [Docker](https://hub.docker.com/r/hrfee/jfa-go) image is your best bet.
**Note**: `TrayIcon` builds include a tray icon to start/stop/restart, and an option to automatically start when you log-in to your computer. For Linux users, these builds depend on the `libappindicator3-1`/`libappindicator-gtk3`/`libappindicator` package for Debian/Ubuntu, Fedora, and Alpine respectively.
##### [Docker](https://hub.docker.com/r/hrfee/jfa-go)
```sh
docker create \
--name "jfa-go" \ # Whatever you want to name it
@@ -54,9 +60,41 @@ docker create \
-v /etc/localtime:/etc/localtime:ro \ # Makes sure time is correct
hrfee/jfa-go # hrfee/jfa-go:unstable for latest build from git
```
Available on the AUR as [jfa-go](https://aur.archlinux.org/packages/jfa-go/), [jfa-go-bin](https://aur.archlinux.org/packages/jfa-go) or [jfa-go-git](https://aur.archlinux.org/packages/jfa-go-git/).
For other platforms, grab an archive from the release section for your platform (or nightly builds [here](https://builds.hrfee.dev/view/hrfee/jfa-go)), and extract the `jfa-go` executable to somewhere useful.
##### [Debian/Ubuntu](https://apt.hrfee.dev)
```sh
sudo apt-get update && sudo apt-get install curl apt-transport-https gnupg
curl https://apt.hrfee.dev/hrfee.pubkey.gpg | sudo apt-key add -
# For stable releases
echo "deb https://apt.hrfee.dev trusty main" | sudo tee /etc/apt/sources.list.d/hrfee.list
# ------
# For unstable releases
echo "deb https://apt.hrfee.dev trusty-unstable main" | sudo tee /etc/apt/sources.list.d/hrfee.list
# ------
sudo apt-get update
# For servers
sudo apt-get install jfa-go
# ------
# For desktops/servers with GUI (has dependencies)
sudo apt-get install jfa-go-tray
# ------
```
##### Arch
Available on the AUR as:
* [jfa-go](https://aur.archlinux.org/packages/jfa-go/) (stable)
* [jfa-go-bin](https://aur.archlinux.org/packages/jfa-go) (pre-compiled, stable)
* [jfa-go-git](https://aur.archlinux.org/packages/jfa-go-git/) (nightly)
##### Other platforms
Download precompiled binaries from:
* [The releases section](https://github.com/hrfee/jfa-go/releases) (stable)
* [Buildrone](https://builds.hrfee.dev/view/hrfee/jfa-go) (nightly)
unzip the `jfa-go`/`jfa-go.exe` executable to somewhere useful.
* For \*nix/macOS users, `chmod +x jfa-go` then place it somewhere in your PATH like `/usr/bin`.
Run the executable to start.
@@ -65,23 +103,34 @@ Run the executable to start.
#### Build from source
If you're using docker, a Dockerfile is provided that builds from source.
Otherwise, full build instructions can be found [here](https://github.com/hrfee/jfa-go/wiki/Build).
Otherwise, full build instructions can be found [here](https://wiki.jfa-go.com/docs/build/).
#### Usage
Simply run `jfa-go` to start the application. A setup wizard will start on `localhost:8056` (or your own specified address). Upon completion, refresh the page.
```
Usage of ./jfa-go:
-config string
alternate path to config file. (default "~/.config/jfa-go/config.ini")
-data string
alternate path to data directory. (default "~/.config/jfa-go")
Usage of jfa-go:
start
start jfa-go as a daemon and run in the background.
stop
stop a daemonized instance of jfa-go.
systemd
generate a systemd .service file.
-config, -c string
alternate path to config file. (default "/home/hrfee/.config/jfa-go/config.ini")
-data, -d string
alternate path to data directory. (default "/home/hrfee/.config/jfa-go")
-debug
Enables debug logging and exposes pprof.
Enables debug logging.
-help, -h
prints this message.
-host string
alternate address to host web ui on.
-port int
-port, -p int
alternate port to host web ui on.
-pprof
Exposes pprof profiler on /debug/pprof.
-swagger
Enable swagger at /swagger/index.html
```
@@ -102,6 +151,6 @@ If you're switching from jellyfin-accounts, copy your existing `~/.jf-accounts`
#### Contributing
See [CONTRIBUTING.md](https://github.com/hrfee/jfa-go/blob/main/CONTRIBUTING.md).
##### Translation
[![Translation status](https://weblate.hrfee.pw/widgets/jfa-go/-/multi-auto.svg)](https://weblate.hrfee.pw/engage/jfa-go/)
[![Translation status](https://weblate.jfa-go.com/widgets/jfa-go/-/multi-auto.svg)](https://weblate.jfa-go.com/engage/jfa-go/)
For translations, use the weblate instance [here](https://weblate.hrfee.pw/engage/jfa-go/). You can login with github.
For translations, use the weblate instance [here](https://weblate.jfa-go.com/engage/jfa-go/). You can login with github.

1017
api.go

File diff suppressed because it is too large Load Diff

12
auth.go
View File

@@ -4,12 +4,11 @@ import (
"encoding/base64"
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt"
"github.com/lithammer/shortuuid/v3"
)
@@ -23,17 +22,16 @@ func CreateToken(userId, jfId string) (string, string, error) {
claims := jwt.MapClaims{
"valid": true,
"id": userId,
"exp": strconv.FormatInt(time.Now().Add(time.Minute*20).Unix(), 10),
"exp": time.Now().Add(time.Minute * 20).Unix(),
"jfid": jfId,
"type": "bearer",
}
tk := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := tk.SignedString([]byte(os.Getenv("JFA_SECRET")))
if err != nil {
return "", "", err
}
claims["exp"] = strconv.FormatInt(time.Now().Add(time.Hour*24).Unix(), 10)
claims["exp"] = time.Now().Add(time.Hour * 24).Unix()
claims["type"] = "refresh"
tk = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
refresh, err = tk.SignedString([]byte(os.Getenv("JFA_SECRET")))
@@ -58,7 +56,7 @@ func (app *appContext) authenticate(gc *gin.Context) {
return
}
claims, ok := token.Claims.(jwt.MapClaims)
expiryUnix, err := strconv.ParseInt(claims["exp"].(string), 10, 64)
expiryUnix := int64(claims["exp"].(float64))
if err != nil {
app.debug.Printf("Auth denied: %s", err)
respond(401, "Unauthorized", gc)
@@ -200,7 +198,7 @@ func (app *appContext) getTokenRefresh(gc *gin.Context) {
return
}
claims, ok := token.Claims.(jwt.MapClaims)
expiryUnix, err := strconv.ParseInt(claims["exp"].(string), 10, 64)
expiryUnix := int64(claims["exp"].(float64))
if err != nil {
app.debug.Printf("getTokenRefresh: Invalid token expiry: %s", err)
respond(401, "Invalid token", gc)

69
autostart.go Normal file
View File

@@ -0,0 +1,69 @@
// +build tray
package main
import (
"log"
"os"
"path/filepath"
"github.com/emersion/go-autostart"
"github.com/getlantern/systray"
)
type Autostart struct {
as *autostart.App
enabled bool
menuitem *systray.MenuItem
clicked chan bool
}
func NewAutostart(name, displayname, trayName, trayTooltip string) *Autostart {
a := &Autostart{
as: &autostart.App{
Name: name,
DisplayName: displayname,
},
enabled: true,
clicked: make(chan bool),
}
a.menuitem = systray.AddMenuItemCheckbox(trayName, trayTooltip, a.as.IsEnabled())
command := os.Args
command[0], _ = filepath.Abs(command[0])
// Make sure to replace any relative paths with absolute ones
pathArgs := []string{"-d", "-data", "-c", "-config"}
for i := 1; i < len(command); i++ {
isPath := false
for _, p := range pathArgs {
if command[i-1] == p {
isPath = true
break
}
}
if isPath {
command[i], _ = filepath.Abs(command[i])
}
}
a.as.Exec = command
return a
}
func (a *Autostart) HandleCheck() {
for range a.menuitem.ClickedCh {
if !a.menuitem.Checked() {
if err := a.as.Enable(); err != nil {
log.Printf("Failed to enable autostart on login: %v", err)
} else {
a.menuitem.Check()
log.Printf("Enabled autostart")
}
} else {
if err := a.as.Disable(); err != nil {
log.Printf("Failed to disable autostart on login: %v", err)
} else {
a.menuitem.Uncheck()
log.Printf("Disabled autostart")
}
}
}
}

View File

@@ -12,7 +12,7 @@ type TimeoutHandler func()
func NewTimeoutHandler(name, addr string, noFail bool) TimeoutHandler {
return func() {
if r := recover(); r != nil {
out := fmt.Sprintf("Failed to authenticate with %s @ %s: Timed out", name, addr)
out := fmt.Sprintf("Failed to authenticate with %s @ \"%s\": Timed out", name, addr)
if noFail {
log.Print(out)
} else {

View File

@@ -14,6 +14,8 @@ import (
var emailEnabled = false
var messagesEnabled = false
var telegramEnabled = false
var discordEnabled = false
var matrixEnabled = false
func (app *appContext) GetPath(sect, key string) (fs.FS, string) {
val := app.config.Section(sect).Key(key).MustString("")
@@ -42,9 +44,12 @@ func (app *appContext) loadConfig() error {
key.SetValue(key.MustString(filepath.Join(app.dataPath, (key.Name() + ".json"))))
}
}
for _, key := range []string{"user_configuration", "user_displayprefs", "user_profiles", "ombi_template", "invites", "emails", "user_template", "custom_emails", "users", "telegram_users"} {
for _, key := range []string{"user_configuration", "user_displayprefs", "user_profiles", "ombi_template", "invites", "emails", "user_template", "custom_emails", "users", "telegram_users", "discord_users", "matrix_users", "announcements"} {
app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".json"))))
}
for _, key := range []string{"matrix_sql"} {
app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".db"))))
}
app.URLBase = strings.TrimSuffix(app.config.Section("ui").Key("url_base").MustString(""), "/")
app.config.Section("email").Key("no_username").SetValue(strconv.FormatBool(app.config.Section("email").Key("no_username").MustBool(false)))
@@ -66,6 +71,11 @@ func (app *appContext) loadConfig() error {
app.MustSetValue("deletion", "email_html", "jfa-go:"+"deleted.html")
app.MustSetValue("deletion", "email_text", "jfa-go:"+"deleted.txt")
jfUrl := app.config.Section("jellyfin").Key("server").String()
if !(strings.HasPrefix(jfUrl, "http://") || strings.HasPrefix(jfUrl, "https://")) {
app.config.Section("jellyfin").Key("server").SetValue("http://" + jfUrl)
}
// Deletion template is good enough for these as well.
app.MustSetValue("disable_enable", "disabled_html", "jfa-go:"+"deleted.html")
app.MustSetValue("disable_enable", "disabled_text", "jfa-go:"+"deleted.txt")
@@ -82,20 +92,33 @@ func (app *appContext) loadConfig() error {
app.MustSetValue("user_expiry", "email_html", "jfa-go:"+"user-expired.html")
app.MustSetValue("user_expiry", "email_text", "jfa-go:"+"user-expired.txt")
app.MustSetValue("matrix", "topic", "Jellyfin notifications")
app.config.Section("jellyfin").Key("version").SetValue(version)
app.config.Section("jellyfin").Key("device").SetValue("jfa-go")
app.config.Section("jellyfin").Key("device_id").SetValue(fmt.Sprintf("jfa-go-%s-%s", version, commit))
// These two settings are pretty much the same
url1 := app.config.Section("invite_emails").Key("url_base").String()
url2 := app.config.Section("password_resets").Key("url_base").String()
app.MustSetValue("password_resets", "url_base", strings.TrimSuffix(url1, "/invite"))
app.MustSetValue("invite_emails", "url_base", url2)
messagesEnabled = app.config.Section("messages").Key("enabled").MustBool(false)
telegramEnabled = app.config.Section("telegram").Key("enabled").MustBool(false)
discordEnabled = app.config.Section("discord").Key("enabled").MustBool(false)
matrixEnabled = app.config.Section("matrix").Key("enabled").MustBool(false)
if !messagesEnabled {
emailEnabled = false
telegramEnabled = false
discordEnabled = false
matrixEnabled = false
} else if app.config.Section("email").Key("method").MustString("") == "" {
emailEnabled = false
} else {
emailEnabled = true
}
if !emailEnabled && !telegramEnabled {
if !emailEnabled && !telegramEnabled && !discordEnabled && !matrixEnabled {
messagesEnabled = false
}
@@ -143,28 +166,3 @@ func (app *appContext) loadConfig() error {
return nil
}
func (app *appContext) migrateEmailConfig() {
tempConfig, _ := ini.Load(app.configPath)
fmt.Println(warning("Part of your email configuration will be migrated to the new \"messages\" section.\nA backup will be made."))
err := tempConfig.SaveTo(app.configPath + "_" + commit + ".bak")
if err != nil {
app.err.Fatalf("Failed to backup config: %v", err)
return
}
for _, setting := range []string{"use_24h", "date_format", "message"} {
if val := app.config.Section("email").Key(setting).Value(); val != "" {
tempConfig.Section("email").Key(setting).SetValue("")
tempConfig.Section("messages").Key(setting).SetValue(val)
}
}
if app.config.Section("messages").Key("enabled").MustBool(false) || app.config.Section("telegram").Key("enabled").MustBool(false) {
tempConfig.Section("messages").Key("enabled").SetValue("true")
}
err = tempConfig.SaveTo(app.configPath)
if err != nil {
app.err.Fatalf("Failed to save config: %v", err)
return
}
app.loadConfig()
}

View File

@@ -124,7 +124,7 @@
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default Account Form Language. Visit weblate.hrfee.dev if you'd like to translate."
"description": "Default Account Form Language. Visit weblate.jfa-go.com if you'd like to translate."
},
"language-admin": {
"name": "Default Admin Language",
@@ -135,7 +135,7 @@
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default Admin page Language. Settings has not been translated. Visit weblate.hrfee.dev if you'd like to translate."
"description": "Default Admin page Language. Settings has not been translated. Visit weblate.jfa-go.com if you'd like to translate."
},
"theme": {
"name": "Default Look",
@@ -246,7 +246,7 @@
"requires_restart": true,
"type": "text",
"value": "",
"description": "URL base for when running jfa-go with a reverse proxy in a subfolder."
"description": "URL base for when running jfa-go with a reverse proxy in a subfolder. include preceding /, e.g \"/accounts\"."
}
}
},
@@ -546,11 +546,94 @@
}
}
},
"discord": {
"order": [],
"meta": {
"name": "Discord",
"description": "Settings for Discord invites/signup/notifications"
},
"settings": {
"enabled": {
"name": "Enabled",
"required": false,
"requires_restart": true,
"type": "bool",
"value": false,
"description": "Enable signup verification through Discord and the sending of notifications through it.\nSee the jfa-go wiki for setting up a bot."
},
"required": {
"name": "Require on sign-up",
"required": false,
"required_restart": true,
"depends_true": "enabled",
"type": "bool",
"value": false,
"description": "Require Discord connection on sign-up. See the jfa-go wiki for info on setting this up."
},
"token": {
"name": "API Token",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Discord Bot API Token."
},
"start_command": {
"name": "Start command",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "!start",
"description": "Command to start the user verification process."
},
"channel": {
"name": "Channel to monitor",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Only listen to commands in specified channel. Leave blank to monitor all."
},
"provide_invite": {
"name": "Provide server invite",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "bool",
"value": false,
"description": "Generate a one-time discord server invite for the account creation form. Required Bot permission \"Create instant invite\", you may need to re-add the bot to your server after."
},
"invite_channel": {
"name": "Invite channel",
"required": false,
"requires_restart": true,
"depends_true": "provide_invite",
"type": "text",
"value": "",
"description": "Channel to invite new users to."
},
"language": {
"name": "Language",
"required": false,
"requires_restart": false,
"depends_true": "enabled",
"type": "select",
"options": [
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default Discord message language. Visit weblate if you'd like to translate."
}
}
},
"telegram": {
"order": [],
"meta": {
"name": "Telegram",
"description": "Settings for Telegram signup/notifications"
"description": "Settings for Telegram signup/notifications. See the jfa-go wiki for info on setting this up."
},
"settings": {
"enabled": {
@@ -565,6 +648,7 @@
"name": "Require on sign-up",
"required": false,
"required_restart": true,
"depends_true": "enabled",
"type": "bool",
"value": false,
"description": "Require telegram connection on sign-up."
@@ -592,6 +676,90 @@
}
}
},
"matrix": {
"order": [],
"meta": {
"name": "Matrix",
"description": "Settings for Matrix invites/signup/notifications. See the jfa-go wiki for info on setting this up."
},
"settings": {
"enabled": {
"name": "Enabled",
"required": false,
"requires_restart": true,
"type": "bool",
"value": false,
"description": "Enable signup verification through Matrix and the sending of notifications through it.\nSee the jfa-go wiki for setting up a bot."
},
"required": {
"name": "Require on sign-up",
"required": false,
"required_restart": true,
"depends_true": "enabled",
"type": "bool",
"value": false,
"description": "Require Matrix connection on sign-up."
},
"homeserver": {
"name": "Home Server URL",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Matrix Home server URL."
},
"token": {
"name": "Access Token",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Matrix Bot API Token."
},
"user_id": {
"name": "Bot User ID",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "User ID of bot account (Example: @jfa-bot:riot.im)"
},
"topic": {
"name": "Chat topic",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "Jellyfin notifications",
"description": "Topic of Matrix private chats."
},
"language": {
"name": "Language",
"required": false,
"requires_restart": false,
"depends_true": "enabled",
"type": "select",
"options": [
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default Matrix message language. Visit weblate if you'd like to translate."
},
"encryption": {
"name": "End-to-end encryption (experimental)",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"advanced": true,
"type": "bool",
"value": false,
"description": "Enable end-to-end encryption for messages. Very experimental, currently does not support receiving commands (e.g !lang)."
}
}
},
"password_resets": {
"order": [],
"meta": {
@@ -626,6 +794,24 @@
"value": false,
"description": "Send users a link to reset their password instead of a PIN. Must be enabled to reset Ombi password at the same time as the Jellyfin password."
},
"set_password": {
"name": "Set password through link",
"required": false,
"requires_restart": true,
"depends_true": "link_reset",
"type": "bool",
"value": false,
"description": "Instead of automatically setting the user's password to the PIN, allow them to set a new password through the reset link."
},
"url_base": {
"name": "URL Base",
"required": true,
"requires_restart": false,
"depends_true": "link_reset",
"type": "text",
"value": "http://accounts.jellyf.in:8056",
"description": "Base URL for jfa-go. You can leave this if you have one set in \"Invite Emails\". This is necessary because using a reverse proxy means the program has no way of knowing the URL itself."
},
"language": {
"name": "Default reset link language",
"required": false,
@@ -719,11 +905,41 @@
"requires_restart": false,
"depends_true": "enabled",
"type": "text",
"value": "http://accounts.jellyf.in:8056/invite",
"value": "http://accounts.jellyf.in:8056",
"description": "Base URL for jfa-go. This is necessary because using a reverse proxy means the program has no way of knowing the URL itself."
}
}
},
"template_email": {
"order": [],
"meta": {
"name": "Custom email template",
"description": "Settings for the template used for announcements & custom messages. HTML should include {{ .text }}, Plaintext should include {{ .plaintext }}, and either can have {{ .message }} to include the contact message.",
"advanced": true
},
"settings": {
"email_html": {
"name": "Custom template email (HTML)",
"required": false,
"requires_restart": false,
"advanced": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Path to custom email HTML template for announcements/custom messages."
},
"email_text": {
"name": "Custom template email (plaintext)",
"required": false,
"requires_restart": false,
"advanced": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Path to custom email text template for announcements/custom messages."
}
}
},
"notifications": {
"order": [],
"meta": {
@@ -1077,6 +1293,14 @@
"value": "",
"description": "Location of stored invites (json)."
},
"password_resets": {
"name": "Password Resets",
"required": false,
"requires_restart": true,
"type": "text",
"value": "",
"description": "Location of stored non-Jellyfin password resets (json)."
},
"emails": {
"name": "Email Addresses",
"required": false,
@@ -1140,6 +1364,38 @@
"type": "text",
"value": "",
"description": "Stores telegram user IDs and language preferences."
},
"matrix_users": {
"name": "Matrix users",
"required": false,
"requires_restart": false,
"type": "text",
"value": "",
"description": "Stores matrix user IDs and language preferences."
},
"matrix_sql": {
"name": "Matrix encryption DB",
"required": false,
"requires_restart": false,
"type": "text",
"value": "",
"description": "Stores cryptographic material for Matrix end-to-end encryption."
},
"discord_users": {
"name": "Discord users",
"required": false,
"requires_restart": false,
"type": "text",
"value": "",
"description": "Stores discord user IDs and language preferences."
},
"announcements": {
"name": "Announcement templates",
"required": false,
"requires_restart": false,
"type": "text",
"value": "",
"description": "Stores custom announcement templates."
}
}
}

View File

@@ -30,12 +30,12 @@
}
}
@media screen and (max-width: 750px) {
@media screen and (max-width: 1000px) {
:root {
font-size: 0.9rem;
}
.table-responsive table {
min-width: 660px;
min-width: 800px;
}
}
@@ -130,6 +130,14 @@ div.card:contains(section.banner.footer) {
text-align: center;
}
.w-100 {
width: 100%;
}
.h-100 {
height: 100%;
}
.inline-block {
display: inline-block;
}
@@ -172,7 +180,7 @@ div.card:contains(section.banner.footer) {
}
p.sm,
span.sm {
span.sm:not(.heading) {
font-size: 0.75rem;
}
@@ -424,6 +432,7 @@ p.top {
.table-responsive {
overflow-x: auto;
font-size: 0.9rem;
}
#notification-box {
@@ -438,6 +447,10 @@ p.top {
margin-bottom: -0.5rem;
}
.dropdown-display.lg {
white-space: nowrap;
}
pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
@@ -483,3 +496,44 @@ a:hover:not(.lang-link):not(.\~urge), a:active:not(.lang-link):not(.\~urge) {
max-width: 15rem;
min-width: 10rem;
}
td.img-circle {
width: 32px;
height: 32px;
}
span.img-circle.lg {
width: 64px;
height: 64px;
}
span.shield.img-circle {
padding: 0.2rem;
}
img.img-circle {
border-radius: 50%;
vertical-align: middle;
}
.table td.sm {
padding-top: 0.1rem;
padding-bottom: 0.1rem;
}
.table-inline {
display: flex !important;
align-items: center;
}
div.card:contains(section.banner.footer) {
padding-bottom: 0px;
}
.card.sectioned {
padding: 0px;
}
.card.sectioned .section {
padding: var(--spacing-4, 1rem);
}

410
discord.go Normal file
View File

@@ -0,0 +1,410 @@
package main
import (
"fmt"
"strings"
dg "github.com/bwmarrin/discordgo"
)
type DiscordDaemon struct {
Stopped bool
ShutdownChannel chan string
bot *dg.Session
username string
tokens []string
verifiedTokens map[string]DiscordUser // Map of tokens to discord users.
channelID, channelName, inviteChannelID, inviteChannelName string
guildID string
serverChannelName, serverName string
users map[string]DiscordUser // Map of user IDs to users. Added to on first interaction, and loaded from app.storage.discord on start.
app *appContext
}
func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) {
token := app.config.Section("discord").Key("token").String()
if token == "" {
return nil, fmt.Errorf("token was blank")
}
bot, err := dg.New("Bot " + token)
if err != nil {
return nil, err
}
dd := &DiscordDaemon{
Stopped: false,
ShutdownChannel: make(chan string),
bot: bot,
tokens: []string{},
verifiedTokens: map[string]DiscordUser{},
users: map[string]DiscordUser{},
app: app,
}
for _, user := range app.storage.discord {
dd.users[user.ID] = user
}
return dd, nil
}
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
func (d *DiscordDaemon) NewAuthToken() string {
pin := genAuthToken()
d.tokens = append(d.tokens, pin)
return pin
}
func (d *DiscordDaemon) NewUnknownUser(channelID, userID, discrim, username string) DiscordUser {
user := DiscordUser{
ChannelID: channelID,
ID: userID,
Username: username,
Discriminator: discrim,
}
return user
}
func (d *DiscordDaemon) MustGetUser(channelID, userID, discrim, username string) DiscordUser {
if user, ok := d.users[userID]; ok {
return user
}
return d.NewUnknownUser(channelID, userID, discrim, username)
}
func (d *DiscordDaemon) run() {
d.bot.AddHandler(d.messageHandler)
d.bot.Identify.Intents = dg.IntentsGuildMessages | dg.IntentsDirectMessages | dg.IntentsGuildMembers | dg.IntentsGuildInvites
if err := d.bot.Open(); err != nil {
d.app.err.Printf("Discord: Failed to start daemon: %v", err)
return
}
// Wait for everything to populate, it's slow sometimes.
for d.bot.State == nil {
continue
}
for d.bot.State.User == nil {
continue
}
d.username = d.bot.State.User.Username
for d.bot.State.Guilds == nil {
continue
}
// Choose the last guild (server), for now we don't really support multiple anyway
d.guildID = d.bot.State.Guilds[len(d.bot.State.Guilds)-1].ID
guild, err := d.bot.Guild(d.guildID)
if err != nil {
d.app.err.Printf("Discord: Failed to get guild: %v", err)
}
d.serverChannelName = guild.Name
d.serverName = guild.Name
if channel := d.app.config.Section("discord").Key("channel").String(); channel != "" {
d.channelName = channel
d.serverChannelName += "/" + channel
}
if d.app.config.Section("discord").Key("provide_invite").MustBool(false) {
if invChannel := d.app.config.Section("discord").Key("invite_channel").String(); invChannel != "" {
d.inviteChannelName = invChannel
}
}
defer d.bot.Close()
<-d.ShutdownChannel
d.ShutdownChannel <- "Down"
return
}
// NewTempInvite creates an invite link, and returns the invite URL, as well as the URL for the server icon.
func (d *DiscordDaemon) NewTempInvite(ageSeconds, maxUses int) (inviteURL, iconURL string) {
var inv *dg.Invite
var err error
if d.inviteChannelName == "" {
d.app.err.Println("Discord: Cannot create invite without channel specified in settings.")
return
}
if d.inviteChannelID == "" {
channels, err := d.bot.GuildChannels(d.guildID)
if err != nil {
d.app.err.Printf("Discord: Couldn't get channel list: %v", err)
return
}
found := false
for _, channel := range channels {
// channel, err := d.bot.Channel(ch.ID)
// if err != nil {
// d.app.err.Printf("Discord: Couldn't get channel: %v", err)
// return
// }
if channel.Name == d.inviteChannelName {
d.inviteChannelID = channel.ID
found = true
break
}
}
if !found {
d.app.err.Printf("Discord: Couldn't find invite channel \"%s\"", d.inviteChannelName)
return
}
}
// channel, err := d.bot.Channel(d.inviteChannelID)
// if err != nil {
// d.app.err.Printf("Discord: Couldn't get invite channel: %v", err)
// return
// }
inv, err = d.bot.ChannelInviteCreate(d.inviteChannelID, dg.Invite{
// Guild: d.bot.State.Guilds[len(d.bot.State.Guilds)-1],
// Channel: channel,
// Inviter: d.bot.State.User,
MaxAge: ageSeconds,
MaxUses: maxUses,
Temporary: false,
})
if err != nil {
d.app.err.Printf("Discord: Failed to create invite: %v", err)
return
}
inviteURL = "https://discord.gg/" + inv.Code
guild, err := d.bot.Guild(d.guildID)
if err != nil {
d.app.err.Printf("Discord: Failed to get guild: %v", err)
return
}
iconURL = guild.IconURL()
return
}
// Returns the user(s) roughly corresponding to the username (if they are in the guild).
// if no discriminator (#xxxx) is given in the username and there are multiple corresponding users, a list of all matching users is returned.
func (d *DiscordDaemon) GetUsers(username string) []*dg.Member {
members, err := d.bot.GuildMembers(
d.guildID,
"",
1000,
)
if err != nil {
d.app.err.Printf("Discord: Failed to get members: %v", err)
return nil
}
hasDiscriminator := strings.Contains(username, "#")
var users []*dg.Member
for _, member := range members {
if hasDiscriminator {
if member.User.Username+"#"+member.User.Discriminator == username {
return []*dg.Member{member}
}
}
if strings.Contains(member.User.Username, username) {
users = append(users, member)
}
}
return users
}
func (d *DiscordDaemon) NewUser(ID string) (user DiscordUser, ok bool) {
u, err := d.bot.User(ID)
if err != nil {
d.app.err.Printf("Discord: Failed to get user: %v", err)
return
}
user.ID = ID
user.Username = u.Username
user.Contact = true
user.Discriminator = u.Discriminator
channel, err := d.bot.UserChannelCreate(ID)
if err != nil {
d.app.err.Printf("Discord: Failed to create DM channel: %v", err)
return
}
user.ChannelID = channel.ID
ok = true
return
}
func (d *DiscordDaemon) Shutdown() {
d.Stopped = true
d.ShutdownChannel <- "Down"
<-d.ShutdownChannel
close(d.ShutdownChannel)
}
func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) {
if m.GuildID != "" && d.channelName != "" {
if d.channelID == "" {
channel, err := s.Channel(m.ChannelID)
if err != nil {
d.app.err.Printf("Discord: Couldn't get channel, will monitor all: %v", err)
d.channelName = ""
}
if channel.Name == d.channelName {
d.channelID = channel.ID
}
}
if d.channelID != m.ChannelID {
d.app.debug.Printf("Discord: Ignoring message as not in specified channel")
return
}
}
if m.Author.ID == s.State.User.ID {
return
}
sects := strings.Split(m.Content, " ")
if len(sects) == 0 {
return
}
lang := d.app.storage.lang.chosenTelegramLang
if user, ok := d.users[m.Author.ID]; ok {
if _, ok := d.app.storage.lang.Telegram[user.Lang]; ok {
lang = user.Lang
}
}
switch msg := sects[0]; msg {
case d.app.config.Section("discord").Key("start_command").MustString("!start"):
d.commandStart(s, m, lang)
case "!lang":
d.commandLang(s, m, sects, lang)
default:
d.commandPIN(s, m, sects, lang)
}
}
func (d *DiscordDaemon) commandStart(s *dg.Session, m *dg.MessageCreate, lang string) {
channel, err := s.UserChannelCreate(m.Author.ID)
if err != nil {
d.app.err.Printf("Discord: Failed to create private channel with \"%s\": %v", m.Author.Username, err)
return
}
user := d.MustGetUser(channel.ID, m.Author.ID, m.Author.Discriminator, m.Author.Username)
d.users[m.Author.ID] = user
content := d.app.storage.lang.Telegram[lang].Strings.get("startMessage") + "\n"
content += d.app.storage.lang.Telegram[lang].Strings.template("languageMessage", tmpl{"command": "!lang"})
_, err = s.ChannelMessageSend(channel.ID, content)
if err != nil {
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
return
}
}
func (d *DiscordDaemon) commandLang(s *dg.Session, m *dg.MessageCreate, sects []string, lang string) {
if len(sects) == 1 {
list := "!lang <lang>\n"
for code := range d.app.storage.lang.Telegram {
list += fmt.Sprintf("%s: %s\n", code, d.app.storage.lang.Telegram[code].Meta.Name)
}
_, err := s.ChannelMessageSendReply(
m.ChannelID,
list,
m.Reference(),
)
if err != nil {
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
}
return
}
if _, ok := d.app.storage.lang.Telegram[sects[1]]; ok {
var user DiscordUser
for jfID, user := range d.app.storage.discord {
if user.ID == m.Author.ID {
user.Lang = sects[1]
d.app.storage.discord[jfID] = user
if err := d.app.storage.storeDiscordUsers(); err != nil {
d.app.err.Printf("Failed to store Discord users: %v", err)
}
break
}
}
d.users[m.Author.ID] = user
}
}
func (d *DiscordDaemon) commandPIN(s *dg.Session, m *dg.MessageCreate, sects []string, lang string) {
if _, ok := d.users[m.Author.ID]; ok {
channel, err := s.Channel(m.ChannelID)
if err != nil {
d.app.err.Printf("Discord: Failed to get channel: %v", err)
return
}
if channel.Type != dg.ChannelTypeDM {
d.app.debug.Println("Discord: Ignoring message as not a DM")
return
}
} else {
d.app.debug.Println("Discord: Ignoring message as user was not found")
return
}
tokenIndex := -1
for i, token := range d.tokens {
if sects[0] == token {
tokenIndex = i
break
}
}
if tokenIndex == -1 {
_, err := s.ChannelMessageSend(
m.ChannelID,
d.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"),
)
if err != nil {
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
}
return
}
_, err := s.ChannelMessageSend(
m.ChannelID,
d.app.storage.lang.Telegram[lang].Strings.get("pinSuccess"),
)
if err != nil {
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
}
d.verifiedTokens[sects[0]] = d.users[m.Author.ID]
d.tokens[len(d.tokens)-1], d.tokens[tokenIndex] = d.tokens[tokenIndex], d.tokens[len(d.tokens)-1]
d.tokens = d.tokens[:len(d.tokens)-1]
}
func (d *DiscordDaemon) SendDM(message *Message, userID ...string) error {
channels := make([]string, len(userID))
for i, id := range userID {
channel, err := d.bot.UserChannelCreate(id)
if err != nil {
return err
}
channels[i] = channel.ID
}
return d.Send(message, channels...)
}
func (d *DiscordDaemon) Send(message *Message, channelID ...string) error {
msg := ""
var embeds []*dg.MessageEmbed
if message.Markdown != "" {
msg, embeds = StripAltText(message.Markdown, true)
} else {
msg = message.Text
}
for _, id := range channelID {
var err error
if len(embeds) != 0 {
_, err = d.bot.ChannelMessageSendComplex(
id,
&dg.MessageSend{
Content: msg,
Embed: embeds[0],
},
)
if err != nil {
return err
}
for i := 1; i < len(embeds); i++ {
_, err := d.bot.ChannelMessageSendEmbed(id, embeds[i])
if err != nil {
return err
}
}
} else {
_, err := d.bot.ChannelMessageSend(
id,
msg,
)
if err != nil {
return err
}
}
}
return nil
}

102
email.go
View File

@@ -25,7 +25,9 @@ import (
"github.com/mailgun/mailgun-go/v4"
)
// implements email sending, right now via smtp or mailgun.
var renderer = html.NewRenderer(html.RendererOptions{Flags: html.Smartypants})
// EmailClient implements email sending, right now via smtp, mailgun or a dummy client.
type EmailClient interface {
Send(fromName, fromAddr string, message *Message, address ...string) error
}
@@ -37,7 +39,7 @@ func (dc *DummyClient) Send(fromName, fromAddr string, email *Message, address .
return nil
}
// Mailgun client implements emailClient.
// Mailgun client implements EmailClient.
type Mailgun struct {
client *mailgun.MailgunImpl
}
@@ -59,7 +61,7 @@ func (mg *Mailgun) Send(fromName, fromAddr string, email *Message, address ...st
return err
}
// SMTP supports SSL/TLS and STARTTLS; implements emailClient.
// SMTP supports SSL/TLS and STARTTLS; implements EmailClient.
type SMTP struct {
sslTLS bool
server string
@@ -139,9 +141,9 @@ func NewEmailer(app *appContext) *Emailer {
}
method := app.config.Section("email").Key("method").String()
if method == "smtp" {
sslTls := false
sslTLS := false
if app.config.Section("smtp").Key("encryption").String() == "ssl_tls" {
sslTls = true
sslTLS = true
}
username := ""
if u := app.config.Section("smtp").Key("username").MustString(""); u != "" {
@@ -149,7 +151,7 @@ func NewEmailer(app *appContext) *Emailer {
} else {
username = emailer.fromAddr
}
err := emailer.NewSMTP(app.config.Section("smtp").Key("server").String(), app.config.Section("smtp").Key("port").MustInt(465), username, app.config.Section("smtp").Key("password").String(), sslTls, app.config.Section("smtp").Key("ssl_cert").MustString(""))
err := emailer.NewSMTP(app.config.Section("smtp").Key("server").String(), app.config.Section("smtp").Key("port").MustInt(465), username, app.config.Section("smtp").Key("password").String(), sslTLS, app.config.Section("smtp").Key("ssl_cert").MustString(""))
if err != nil {
app.err.Printf("Error while initiating SMTP mailer: %v", err)
}
@@ -177,6 +179,23 @@ func (emailer *Emailer) NewMailgun(url, key string) {
// NewSMTP returns an SMTP emailClient.
func (emailer *Emailer) NewSMTP(server string, port int, username, password string, sslTLS bool, certPath string) (err error) {
// x509.SystemCertPool is unavailable on windows
if PLATFORM == "windows" {
sender := &SMTP{
server: server,
port: port,
sslTLS: sslTLS,
tlsConfig: &tls.Config{
InsecureSkipVerify: false,
ServerName: server,
},
}
if username != "" || password != "" {
sender.auth = smtp.PlainAuth("", username, password, server)
}
emailer.sender = sender
return
}
rootCAs, err := x509.SystemCertPool()
if rootCAs == nil || err != nil {
rootCAs = x509.NewCertPool()
@@ -188,8 +207,7 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri
err = errors.New("Failed to append cert to pool")
}
}
emailer.sender = &SMTP{
auth: smtp.PlainAuth("", username, password, server),
sender := &SMTP{
server: server,
port: port,
sslTLS: sslTLS,
@@ -199,6 +217,10 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri
RootCAs: rootCAs,
},
}
if username != "" || password != "" {
sender.auth = smtp.PlainAuth("", username, password, server)
}
emailer.sender = sender
return
}
@@ -215,9 +237,8 @@ func (emailer *Emailer) construct(app *appContext, section, keyFragment string,
}
var keys []string
plaintext := app.config.Section("email").Key("plaintext").MustBool(false)
telegram := app.config.Section("telegram").Key("enabled").MustBool(false)
if plaintext {
if telegram {
if telegramEnabled || discordEnabled {
keys = []string{"text"}
text, markdown = "", ""
} else {
@@ -225,7 +246,7 @@ func (emailer *Emailer) construct(app *appContext, section, keyFragment string,
text = ""
}
} else {
if telegram {
if telegramEnabled || discordEnabled {
keys = []string{"html", "text", "markdown"}
} else {
keys = []string{"html", "text"}
@@ -291,6 +312,9 @@ func (emailer *Emailer) confirmationValues(code, username, key string, app *appC
} else {
message := app.config.Section("messages").Key("message").String()
inviteLink := app.config.Section("invite_emails").Key("url_base").String()
if !strings.HasSuffix(inviteLink, "/invite") {
inviteLink += "/invite"
}
inviteLink = fmt.Sprintf("%s/%s?key=%s", inviteLink, code, key)
template["helloUser"] = emailer.lang.Strings.template("helloUser", tmpl{"username": username})
template["confirmationURL"] = inviteLink
@@ -322,19 +346,27 @@ func (emailer *Emailer) constructConfirmation(code, username, key string, app *a
return email, nil
}
func (emailer *Emailer) constructTemplate(subject, md string, app *appContext) (*Message, error) {
// username is optional, but should only be passed once.
func (emailer *Emailer) constructTemplate(subject, md string, app *appContext, username ...string) (*Message, error) {
if len(username) != 0 {
md = templateEmail(md, []string{"{username}"}, nil, map[string]interface{}{"username": username[0]})
subject = templateEmail(subject, []string{"{username}"}, nil, map[string]interface{}{"username": username[0]})
}
email := &Message{Subject: subject}
renderer := html.NewRenderer(html.RendererOptions{Flags: html.Smartypants})
html := markdown.ToHTML([]byte(md), nil, renderer)
text := stripMarkdown(md)
message := app.config.Section("messages").Key("message").String()
var err error
email.HTML, email.Text, email.Markdown, err = emailer.construct(app, "template_email", "email_", map[string]interface{}{
data := map[string]interface{}{
"text": template.HTML(html),
"plaintext": text,
"message": message,
"md": md,
})
}
if len(username) != 0 {
data["username"] = username[0]
}
email.HTML, email.Text, email.Markdown, err = emailer.construct(app, "template_email", "email_", data)
if err != nil {
return nil, err
}
@@ -346,6 +378,9 @@ func (emailer *Emailer) inviteValues(code string, invite Invite, app *appContext
d, t, expiresIn := emailer.formatExpiry(expiry, false, app.datePattern, app.timePattern)
message := app.config.Section("messages").Key("message").String()
inviteLink := app.config.Section("invite_emails").Key("url_base").String()
if !strings.HasSuffix(inviteLink, "/invite") {
inviteLink += "/invite"
}
inviteLink = fmt.Sprintf("%s/%s", inviteLink, code)
template := map[string]interface{}{
"hello": emailer.lang.InviteEmail.get("hello"),
@@ -517,17 +552,17 @@ func (emailer *Emailer) resetValues(pwr PasswordReset, app *appContext, noSub bo
} else {
template["helloUser"] = emailer.lang.Strings.template("helloUser", tmpl{"username": pwr.Username})
template["codeExpiry"] = emailer.lang.PasswordReset.template("codeExpiry", tmpl{"date": d, "time": t, "expiresInMinutes": expiresIn})
inviteLink := app.config.Section("invite_emails").Key("url_base").String()
url := app.config.Section("password_resets").Key("url_base").String()
if linkResetEnabled {
if inviteLink != "" {
if url != "" {
// Strip /invite form end of this URL, ik its ugly.
template["link_reset"] = true
pinLink := fmt.Sprintf("%s/reset?pin=%s", strings.Replace(inviteLink, "/invite", "", 1), pwr.Pin)
pinLink := fmt.Sprintf("%s/reset?pin=%s", url, pwr.Pin)
template["pin"] = pinLink
// Only used in html email.
template["pin_code"] = pwr.Pin
} else {
app.info.Println("Password Reset link disabled as no URL Base provided. Set in Settings > Invite Emails.")
app.info.Println("Password Reset link disabled as no URL Base provided. Set in Settings > Password Resets.")
template["pin"] = pwr.Pin
}
} else {
@@ -576,6 +611,7 @@ func (emailer *Emailer) deletedValues(reason string, app *appContext, noSub bool
template["reason"] = reason
template["message"] = app.config.Section("messages").Key("message").String()
}
fmt.Println("TTTT", template)
return template
}
@@ -794,8 +830,27 @@ func (app *appContext) sendByID(email *Message, ID ...string) error {
var err error
if tgChat, ok := app.storage.telegram[id]; ok && tgChat.Contact && telegramEnabled {
err = app.telegram.Send(email, tgChat.ChatID)
} else if address, ok := app.storage.emails[id]; ok {
err = app.email.send(email, address.(string))
if err != nil {
return err
}
}
if dcChat, ok := app.storage.discord[id]; ok && dcChat.Contact && discordEnabled {
err = app.discord.Send(email, dcChat.ChannelID)
if err != nil {
return err
}
}
if mxChat, ok := app.storage.matrix[id]; ok && mxChat.Contact && matrixEnabled {
err = app.matrix.Send(email, mxChat)
if err != nil {
return err
}
}
if address, ok := app.storage.emails[id]; ok && address.Contact && emailEnabled {
err = app.email.send(email, address.Addr)
if err != nil {
return err
}
}
if err != nil {
return err
@@ -805,11 +860,14 @@ func (app *appContext) sendByID(email *Message, ID ...string) error {
}
func (app *appContext) getAddressOrName(jfID string) string {
if dcChat, ok := app.storage.discord[jfID]; ok && dcChat.Contact && discordEnabled {
return dcChat.Username + "#" + dcChat.Discriminator
}
if tgChat, ok := app.storage.telegram[jfID]; ok && tgChat.Contact && telegramEnabled {
return "@" + tgChat.Username
}
if addr, ok := app.storage.emails[jfID]; ok {
return addr.(string)
return addr.Addr
}
return ""
}

87
exit.go Normal file
View File

@@ -0,0 +1,87 @@
package main
import (
"fmt"
"html/template"
"log"
"os"
"path/filepath"
"runtime"
"runtime/debug"
"strings"
"time"
"github.com/pkg/browser"
)
// https://gist.github.com/swdunlop/9629168
func identifyPanic() string {
var name, file string
var line int
var pc [16]uintptr
n := runtime.Callers(4, pc[:])
for _, pc := range pc[:n] {
fn := runtime.FuncForPC(pc)
if fn == nil {
continue
}
file, line = fn.FileLine(pc)
name = fn.Name()
if !strings.HasPrefix(name, "runtime.") {
break
}
}
switch {
case name != "":
return fmt.Sprintf("%v:%v", name, line)
case file != "":
return fmt.Sprintf("%v:%v", file, line)
}
return fmt.Sprintf("pc:%x", pc)
}
// Exit dumps the last 100 lines of output to a crash file in /tmp (or equivalent), and generates a prettier HTML file containing it that is opened in the browser if possible.
func Exit(err interface{}) {
tmpl, err2 := template.ParseFS(localFS, "html/crash.html", "html/header.html")
if err2 != nil {
log.Fatalf("Failed to load template: %v", err)
}
logCache := lineCache.String()
if err != nil {
fmt.Println(err)
logCache += "\n" + fmt.Sprint(err)
}
logCache += "\n" + string(debug.Stack())
sanitized := sanitizeLog(logCache)
data := map[string]interface{}{
"Log": logCache,
"SanitizedLog": sanitized,
}
if err != nil {
data["Err"] = fmt.Sprintf("%s %v", identifyPanic(), err)
}
fpath := filepath.Join(temp, "jfa-go-crash-"+time.Now().Local().Format("2006-01-02T15:04:05"))
err2 = os.WriteFile(fpath+".txt", []byte(logCache), 0666)
if err2 != nil {
log.Fatalf("Failed to write crash dump file: %v", err2)
}
log.Printf("\n------\nA crash report has been saved to \"%s\".\n------", fpath+".txt")
f, err2 := os.OpenFile(fpath+".html", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err2 != nil {
log.Fatalf("Failed to open crash dump file: %v", err2)
}
defer f.Close()
err2 = tmpl.Execute(f, data)
if err2 != nil {
log.Fatalf("Failed to execute template: %v", err2)
}
browser.OpenFile(fpath + ".html")
if TRAY {
QuitTray()
} else {
os.Exit(1)
}
}

View File

@@ -12,8 +12,8 @@ import (
const binaryType = "external"
var localFS fs.FS
var langFS fs.FS
var localFS dirFS
var langFS dirFS
// When using os.DirFS, even on Windows the separator seems to be '/'.
// func FSJoin(elem ...string) string { return filepath.Join(elem...) }
@@ -29,9 +29,23 @@ func FSJoin(elem ...string) string {
return strings.TrimSuffix(path, sep)
}
type dirFS string
func (dir dirFS) Open(name string) (fs.File, error) {
return os.Open(string(dir) + "/" + name)
}
func (dir dirFS) ReadFile(name string) ([]byte, error) {
return os.ReadFile(string(dir) + "/" + name)
}
func (dir dirFS) ReadDir(name string) ([]fs.DirEntry, error) {
return os.ReadDir(string(dir) + "/" + name)
}
func loadFilesystems() {
log.Println("Using external storage")
executable, _ := os.Executable()
localFS = os.DirFS(filepath.Join(filepath.Dir(executable), "data"))
langFS = os.DirFS(filepath.Join(filepath.Dir(executable), "data", "lang"))
localFS = dirFS(filepath.Join(filepath.Dir(executable), "data"))
langFS = dirFS(filepath.Join(filepath.Dir(executable), "data", "lang"))
}

78
go.mod
View File

@@ -10,41 +10,65 @@ replace github.com/hrfee/jfa-go/ombi => ./ombi
replace github.com/hrfee/jfa-go/logger => ./logger
replace github.com/hrfee/jfa-go/linecache => ./linecache
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fatih/color v1.10.0
github.com/bwmarrin/discordgo v0.23.2
github.com/elazarl/go-bindata-assetfs v1.0.0 // indirect
github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a
github.com/fatih/color v1.12.0
github.com/fsnotify/fsnotify v1.4.9
github.com/getlantern/golog v0.0.0-20210606115803-bce9f9fe5a5f // indirect
github.com/getlantern/hidden v0.0.0-20201229170000-e66e7f878730 // indirect
github.com/getlantern/ops v0.0.0-20200403153110-8476b16edcd6 // indirect
github.com/getlantern/systray v1.1.0
github.com/gin-contrib/pprof v1.3.0
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e
github.com/gin-gonic/gin v1.6.3
github.com/go-openapi/spec v0.20.3 // indirect
github.com/gin-contrib/static v0.0.1
github.com/gin-gonic/gin v1.7.4
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
github.com/golang/protobuf v1.4.3 // indirect
github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd
github.com/google/uuid v1.1.2 // indirect
github.com/hrfee/jfa-go/common v0.0.0-20210105184019-fdc97b4e86cc
github.com/hrfee/jfa-go/docs v0.0.0-20201112212552-b6f3cd7c1f71
github.com/hrfee/jfa-go/logger v0.0.0-00010101000000-000000000000
github.com/hrfee/jfa-go/ombi v0.0.0-20201112212552-b6f3cd7c1f71
github.com/hrfee/mediabrowser v0.3.3
github.com/itchyny/timefmt-go v0.1.2
github.com/go-playground/validator/v10 v10.9.0 // indirect
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/protobuf v1.5.2 // indirect
github.com/gomarkdown/markdown v0.0.0-20210514010506-3b9f47219fe7
github.com/google/uuid v1.3.0 // indirect
github.com/hrfee/jfa-go/common v0.0.0-20210816220108-eb3489b34f9e
github.com/hrfee/jfa-go/docs v0.0.0-20210816220108-eb3489b34f9e
github.com/hrfee/jfa-go/linecache v0.0.0-20210816220108-eb3489b34f9e
github.com/hrfee/jfa-go/logger v0.0.0-20210816220108-eb3489b34f9e
github.com/hrfee/jfa-go/ombi v0.0.0-20210816220108-eb3489b34f9e
github.com/hrfee/mediabrowser v0.3.5
github.com/itchyny/timefmt-go v0.1.3
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
github.com/lithammer/shortuuid/v3 v3.0.4
github.com/mailgun/mailgun-go/v4 v4.5.1
github.com/json-iterator/go v1.1.11 // indirect
github.com/lib/pq v1.10.2 // indirect
github.com/lithammer/shortuuid/v3 v3.0.7
github.com/mailgun/mailgun-go/v4 v4.5.2
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/mattn/go-sqlite3 v1.14.7 // indirect
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2
github.com/pkg/errors v0.9.1 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14
github.com/swaggo/gin-swagger v1.3.0
github.com/swaggo/swag v1.7.0 // indirect
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2
github.com/swaggo/gin-swagger v1.3.1
github.com/swaggo/swag v1.7.1 // indirect
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
github.com/ugorji/go v1.2.0 // indirect
github.com/tidwall/gjson v1.8.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tidwall/sjson v1.1.7 // indirect
github.com/ugorji/go v1.2.6 // indirect
github.com/writeas/go-strip-markdown v2.0.1+incompatible
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 // indirect
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c // indirect
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 // indirect
golang.org/x/tools v0.1.0 // indirect
google.golang.org/protobuf v1.25.0 // indirect
golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e // indirect
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.5 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/go-playground/validator.v9 v9.29.1 // indirect
gopkg.in/ini.v1 v1.62.0
maunium.net/go/maulogger/v2 v2.3.0 // indirect
maunium.net/go/mautrix v0.9.19
)

332
go.sum
View File

@@ -1,6 +1,3 @@
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
@@ -9,27 +6,31 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4=
github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473 h1:4cmBvAEBNJaGARUEs3/suWRyfyBfhf7I60WBZq+bv2w=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:M88ob4TyDnEqNuL3PgsE/p3bDujfspnulR+0dQWNYZs=
github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:buzQsO8HHkZX2Q45fdfGH1xejPjuDQaXH8btcYMFzPM=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
@@ -38,8 +39,33 @@ github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQD
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 h1:6uJ+sZ/e03gkbqZ0kUG6mfKoqDb4XMAzMIwlajq19So=
github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
github.com/getlantern/errors v1.0.1 h1:XukU2whlh7OdpxnkXhNH9VTLVz0EVPGKDV5K0oWhvzw=
github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7 h1:guBYzEaLz0Vfc/jv0czrr2z7qyzTOGC9hiQ0VC+hKjk=
github.com/getlantern/golog v0.0.0-20190830074920-4ef2e798c2d7/go.mod h1:zx/1xUUeYPy3Pcmet8OSXLbF47l+3y6hIPpyLWoR9oc=
github.com/getlantern/golog v0.0.0-20210606115803-bce9f9fe5a5f h1:wsVt3P/boVKkPFEZkWxgNgRq/+mD7sWHc17+Vw2PgH8=
github.com/getlantern/golog v0.0.0-20210606115803-bce9f9fe5a5f/go.mod h1:ZyIjgH/1wTCl+B+7yH1DqrWp6MPJqESmwmEQ89ZfhvA=
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0=
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc=
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
github.com/getlantern/hidden v0.0.0-20201229170000-e66e7f878730 h1:oKJVQbWZ2CAJ71jYnm6A3+e6h5bkPJ0okIMwkaYB5HI=
github.com/getlantern/hidden v0.0.0-20201229170000-e66e7f878730/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
github.com/getlantern/ops v0.0.0-20200403153110-8476b16edcd6 h1:QthAQCekS1YOeYWSvoHI6ZatlG4B+GBDLxV/2ZkBsTA=
github.com/getlantern/ops v0.0.0-20200403153110-8476b16edcd6/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
github.com/getlantern/systray v1.1.0 h1:U0wCEqseLi2ok1fE6b88gJklzriavPJixZysZPkZd/Y=
github.com/getlantern/systray v1.1.0/go.mod h1:AecygODWIsBquJCJFop8MEQcJbWFfw/1yWbVabNgpCM=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.1 h1:ezvKOL6jH+jlzdHNE4h9h8q8uMpDQjyl0NN0Jd7jozc=
@@ -52,12 +78,18 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e h1:8bZpGwoPxkaivQPrAbWl+7zjjUcbFUnYp7yQcx2r2N0=
github.com/gin-contrib/static v0.0.0-20200916080430-d45d9a37d28e/go.mod h1:VhW/Ch/3FhimwZb8Oj+qJmdMmoB8r7lmJ5auRjm50oQ=
github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U=
github.com/gin-contrib/static v0.0.1/go.mod h1:CSxeF+wep05e0kCOsqWdAWbSszmc31zTIbD8TvWl7Hs=
github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM=
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
@@ -67,18 +99,16 @@ github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.14/go.mod h1:gwrgJS15eCUgjLpMjBJmbZezCsw88LmgeEip0M63doA=
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.11/go.mod h1:Uc0gKkdR+ojzsEpjh39QChyu92vPgIr72POcgHMAgSY=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
@@ -87,78 +117,101 @@ github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvSc
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.8.0 h1:1kAa0fCrnpv+QYdkdcRzrRM7AyYs5o8+jZdJCz9xj6k=
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A=
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd h1:0b8AqsWQb6A0jjx80UXLG/uMTXQkGD0IGuXWqsrNz1M=
github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/gomarkdown/markdown v0.0.0-20210514010506-3b9f47219fe7 h1:oKYOfNR7Hp6XpZ4JqolL5u642Js5Z0n7psPVl+S5heo=
github.com/gomarkdown/markdown v0.0.0-20210514010506-3b9f47219fe7/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/hrfee/mediabrowser v0.3.3 h1:7E05uiol8hh2ytKn3WVLrUIvHAyifYEIy3Y5qtuNh8I=
github.com/hrfee/mediabrowser v0.3.3/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hrfee/mediabrowser v0.3.5 h1:bOJlI2HLvw7v0c7mcRw5XDRMUHReQzk5z0EJYRyYjpo=
github.com/hrfee/mediabrowser v0.3.5/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
github.com/itchyny/timefmt-go v0.1.2 h1:q0Xa4P5it6K6D7ISsbLAMwx1PnWlixDcJL6/sFs93Hs=
github.com/itchyny/timefmt-go v0.1.2/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
github.com/itchyny/timefmt-go v0.1.3 h1:7M3LGVDsqcd0VZH2U+x393obrzZisp7C0uEe921iRkU=
github.com/itchyny/timefmt-go v0.1.3/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5 h1:hyz3dwM5QLc1Rfoz4FuWJQG5BN7tc6K1MndAUnGpQr4=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lithammer/shortuuid/v3 v3.0.4 h1:uj4xhotfY92Y1Oa6n6HUiFn87CdoEHYUlTy0+IgbLrs=
github.com/lithammer/shortuuid/v3 v3.0.4/go.mod h1:RviRjexKqIzx/7r1peoAITm6m7gnif/h+0zmolKJjzw=
github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8=
github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts=
github.com/mailgun/mailgun-go/v4 v4.5.1 h1:XrQQ/ZgqFvINRKy+eBqowLl7k3pQO6OCLpKphliMOFs=
github.com/mailgun/mailgun-go/v4 v4.5.1/go.mod h1:FJlF9rI5cQT+mrwujtJjPMbIVy3Ebor9bKTVsJ0QU40=
github.com/mailgun/mailgun-go/v4 v4.5.2 h1:6289rnnSn8pKFR8TS5pwWOqFcY/HdWpqhvnQ+J7IVQc=
github.com/mailgun/mailgun-go/v4 v4.5.2/go.mod h1:FJlF9rI5cQT+mrwujtJjPMbIVy3Ebor9bKTVsJ0QU40=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -171,8 +224,12 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA=
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -181,53 +238,86 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pkg/browser v0.0.0-20210606212950-a7b7a6107d32 h1:K3WnH8Ka32vWygzmjKEhz1zAVqckNoWDqX3azMxuiSA=
github.com/pkg/browser v0.0.0-20210606212950-a7b7a6107d32/go.mod h1:yvwcBfzEX4m+eTgxPBbNYytaWFv4PSQzBaeYjxp8Iik=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14 h1:PyYN9JH5jY9j6av01SpfRMb+1DWg/i3MbGOKPxJ2wjM=
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2 h1:+iNTcqQJy0OZ5jk6a5NLib47eqXK8uYcPX+O4+cBpEM=
github.com/swaggo/files v0.0.0-20210815190702-a29dd2bc99b2/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w=
github.com/swaggo/gin-swagger v1.2.0/go.mod h1:qlH2+W7zXGZkczuL+r2nEBR2JTT+/lX05Nn6vPhc7OI=
github.com/swaggo/gin-swagger v1.3.0 h1:eOmp7r57oUgZPw2dJOjcGNMse9cvXcI4tTqBcnZtPsI=
github.com/swaggo/gin-swagger v1.3.0/go.mod h1:oy1BRA6WvgtCp848lhxce7BnWH4C8Bxa0m5SkWx+cS0=
github.com/swaggo/gin-swagger v1.3.1 h1:mO9MU8O99WX+RM3jekzOV54g9Fo+Nbkk7rgrN1u9irM=
github.com/swaggo/gin-swagger v1.3.1/go.mod h1:Z6NtRBK2PRig0EUmy1Xu75CnCEs6vGYu9QZd/QWRYKU=
github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
github.com/swaggo/swag v1.6.7/go.mod h1:xDhTyuFIujYiN3DKWC/H/83xcfHp+UE/IzWWampG7Zc=
github.com/swaggo/swag v1.7.0 h1:5bCA/MTLQoIqDXXyHfOpMeDvL9j68OY/udlK4pQoo4E=
github.com/swaggo/swag v1.7.0/go.mod h1:BdPIL73gvS9NBsdi7M1JOxLvlbfvNRaBP8m6WT6Aajo=
github.com/swaggo/swag v1.7.1 h1:gY9ZakXlNWg/i/v5bQBic7VMZ4teq4m89lpiao74p/s=
github.com/swaggo/swag v1.7.1/go.mod h1:gAiHxNTb9cIpNmA/VEGUP+CyZMCP/EW7mdtc8Bny+p8=
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
github.com/tidwall/gjson v1.6.8 h1:CTmXMClGYPAmln7652e69B7OLXfTi5ABcPPwjIWUv7w=
github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU=
github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.1.5 h1:wsUceI/XDyZk3J1FUvuuYlK62zJv2HO2Pzb8A5EWdUE=
github.com/tidwall/sjson v1.1.5/go.mod h1:VuJzsZnTowhSxWdOgsAnb886i4AjEyTkk7tNtsL7EYE=
github.com/tidwall/sjson v1.1.7 h1:sgVPwu/yygHJ2m1pJDLgGM/h+1F5odx5Q9ljG3imRm8=
github.com/tidwall/sjson v1.1.7/go.mod h1:w/yG+ezBeTdUxiKs5NcPicO9diP38nk96QBAbIIGeFs=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc=
github.com/ugorji/go v1.2.0 h1:6eXlzYLLwZwXroJx9NyqbYcbv/d93twiOzQLDewE6qM=
github.com/ugorji/go v1.2.0/go.mod h1:1ny++pKMXhLWrwWV5Nf+CbOuZJhMoaFD+0GMFfd8fEc=
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/ugorji/go/codec v1.2.0 h1:As6RccOIlbm9wHuWYMlB30dErcI+4WiKWsYsmPkyrUw=
github.com/ugorji/go/codec v1.2.0/go.mod h1:dXvG35r7zTX6QImXOSFhGMmKtX+wJ7VTWzGvYQGIjBs=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
@@ -235,29 +325,27 @@ github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/writeas/go-strip-markdown v2.0.1+incompatible h1:IIqxTM5Jr7RzhigcL6FkrCNfXkvbR+Nbu1ls48pXYcw=
github.com/writeas/go-strip-markdown v2.0.1+incompatible/go.mod h1:Rsyu10ZhbEK9pXdk8V6MVnZmTzRG0alMNLMwa0J01fE=
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead h1:jeP6FgaSLNTMP+Yri3qjlACywQLye+huGLmNGhBzm6k=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e h1:VvfwVmMH40bpMeizC9/K7ipM5Qjucuu16RWfneFPyhQ=
golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -266,19 +354,22 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c h1:KHUzaHIpjWVlVVNh65G3hhuj3KB1HnjY6Cq5cTvRQT8=
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20210716203947-853a461950ff h1:j2EK/QoxYNBsXI4R7fQkkRUk8y6wnOBI+6hgPdP/6Ds=
golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -287,73 +378,68 @@ golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0=
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201120155355-20be4ac4bd6e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -364,6 +450,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/maulogger/v2 v2.2.4 h1:oV2GDeM4fx1uRysdpDC0FcrPg+thFicSd9XzPcYMbVY=
maunium.net/go/maulogger/v2 v2.2.4/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
maunium.net/go/maulogger/v2 v2.3.0 h1:TMCcO65fLk6+pJXo7sl38tzjzW0KBFgc6JWJMBJp4GE=
maunium.net/go/maulogger/v2 v2.3.0/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A=
maunium.net/go/mautrix v0.9.15 h1:9EJMALSxvy5LkQh5zjaMhbhm/grzVHv3xoA/2pfxpek=
maunium.net/go/mautrix v0.9.15/go.mod h1:7IzKfWvpQtN+W2Lzxc0rLvIxFM3ryKX6Ys3S/ZoWbg8=
maunium.net/go/mautrix v0.9.19 h1:8ZoDuijJOKxgEOMDoBN2B6at0Ba7EJpsqWA/5jV7ELw=
maunium.net/go/mautrix v0.9.19/go.mod h1:7IzKfWvpQtN+W2Lzxc0rLvIxFM3ryKX6Ys3S/ZoWbg8=

View File

@@ -5,8 +5,10 @@
<script>
window.URLBase = "{{ .urlBase }}";
window.notificationsEnabled = {{ .notifications }};
window.emailEnabled = {{ .email_enabled }};
window.telegramEnabled = {{ .telegram_enabled }};
window.emailEnabled = {{ .emailEnabled }};
window.telegramEnabled = {{ .telegramEnabled }};
window.discordEnabled = {{ .discordEnabled }};
window.matrixEnabled = {{ .matrixEnabled }};
window.ombiEnabled = {{ .ombiEnabled }};
window.usernameEnabled = {{ .username }};
window.langFile = JSON.parse({{ .language }});
@@ -161,15 +163,28 @@
<span class="heading"><span id="header-announce"></span> <span class="modal-close">&times;</span></span>
<div class="row">
<div class="col flex-col content mt-half">
<label class="label supra" for="announce-subject"> {{ .strings.subject }}</label>
<input type="text" id="announce-subject" class="input ~neutral !normal mb-1 mt-half">
<label class="label supra" for="textarea-announce">{{ .strings.message }}</label>
<textarea id="textarea-announce" class="textarea full-width ~neutral !normal mt-half monospace"></textarea>
<p class="support mt-half mb-1">{{ .strings.markdownSupported }}</p>
<label>
<input type="submit" class="unfocused">
<span class="button ~urge !normal full-width center supra submit">{{ .strings.submit }}</span>
<div id="announce-details">
<span class="label supra" for="editor-variables" id="label-editor-variables">{{ .strings.variables }}</span>
<div id="announce-variables">
<span class="button ~urge !normal mb-1 mt-half" id="announce-variables-username" style="margin-left: 0.25rem; margin-right: 0.25rem;"><span class="monospace">{username}</span></span>
</div>
<label class="label supra" for="announce-subject"> {{ .strings.subject }}</label>
<input type="text" id="announce-subject" class="input ~neutral !normal mb-1 mt-half">
<label class="label supra" for="textarea-announce">{{ .strings.message }}</label>
<textarea id="textarea-announce" class="textarea full-width ~neutral !normal mt-half monospace"></textarea>
<p class="support mt-half mb-1">{{ .strings.markdownSupported }}</p>
</div>
<label class="label unfocused" id="announce-name"><p class="supra">{{ .strings.name }}</p>
<input type="text" class="input ~neutral !normal mb-1 mt-half">
<p class="support">{{ .strings.templateEnterName }}</p>
</label>
<div class="row flex-expand">
<label>
<input type="submit" class="unfocused">
<span class="button ~urge !normal center supra submit">{{ .strings.send }}</span>
</label>
<span class="button ~info !normal center supra" id="save-announce">{{ .strings.saveAsTemplate }}</span>
</div>
</div>
<div class="col card ~neutral !low">
<span class="subheading supra">{{ .strings.preview }}</span>
@@ -309,7 +324,7 @@
<span class="button ~urge !normal full-width center" id="update-update">{{ .strings.update }}</span>
</div>
</div>
{{ if .telegram_enabled }}
{{ if .telegramEnabled }}
<div id="modal-telegram" class="modal">
<div class="modal-content card">
<span class="heading mb-1">{{ .strings.linkTelegram }}</span>
@@ -327,6 +342,31 @@
</div>
</div>
{{ end }}
{{ if .discordEnabled }}
<div id="modal-discord" class="modal">
<div class="modal-content card">
<span class="heading mb-1"><span id="discord-header"></span><span class="modal-close">&times;</span></span>
<p class="content mb-1" id="discord-description"></p>
<div class="row">
<input type="search" class="col sm field ~neutral !normal input" id="discord-search" placeholder="user#1234">
</div>
<table class="table"><tbody id="discord-list"></tbody></table>
</div>
</div>
{{ end }}
<div id="modal-matrix" class="modal">
<form class="modal-content card" id="form-matrix" href="">
<span class="heading">{{ .strings.linkMatrix }}</span>
<p class="content">{{ .strings.linkMatrixDescription }}</p>
<input type="text" class="field input ~neutral !high mt-half mb-1" placeholder="{{ .strings.matrixHomeServer }}" id="matrix-homeserver">
<input type="text" class="field input ~neutral !high mt-half mb-1" placeholder="{{ .strings.username }}" id="matrix-user">
<input type="password" class="field input ~neutral !high mt-half mb-1" placeholder="{{ .strings.password }}" id="matrix-password">
<label>
<input type="submit" class="unfocused">
<span class="button ~urge !normal full-width center supra submit">{{ .strings.submit }}</span>
</label>
</form>
</div>
<div id="notification-box"></div>
<span class="dropdown" tabindex="0" id="lang-dropdown">
<span class="button ~urge dropdown-button">
@@ -488,7 +528,14 @@
<div id="create-send-to-container">
<label class="label supra">{{ .strings.inviteSendToEmail }}</label>
<div class="flex-expand mb-1 mt-half">
{{ if .discordEnabled }}
<input type="text" id="create-send-to" class="input ~neutral !normal mr-1" placeholder="example@example.com | user#1234">
<span id="create-send-to-search" class="button ~neutral !normal mr-1">
<i class="icon ri-search-2-line" title="{{ .strings.search }}"></i>
</span>
{{ else }}
<input type="email" id="create-send-to" class="input ~neutral !normal mr-1" placeholder="example@example.com">
{{ end }}
<label for="create-send-to-enabled" class="button ~neutral !normal">
<input type="checkbox" id="create-send-to-enabled" aria-label="Send to address enabled">
</label>
@@ -508,7 +555,15 @@
</div>
<div class="row">
<span class="col sm button ~neutral !normal center mb-half" id="accounts-add-user">{{ .quantityStrings.addUser.Singular }}</span>
<span class="col sm button ~info !normal center mb-half" id="accounts-announce">{{ .strings.announce }}</span>
<div id="accounts-announce-dropdown" class="col sm dropdown" tabindex="0">
<span class="h-100 sm button ~info !normal center mb-half" id="accounts-announce">{{ .strings.announce }}</span>
<div class="dropdown-display">
<div class="card ~neutral !low">
<span class="supra sm">{{ .strings.templates }}</span>
<div id="accounts-announce-templates"></div>
</div>
</div>
</div>
<span class="col sm button ~urge !normal center mb-half" id="accounts-modify-user">{{ .strings.modifySettings }}</span>
<span class="col sm button ~warning !normal center mb-half" id="accounts-extend-expiry">{{ .strings.extendExpiry }}</span>
<span class="col sm button ~positive !normal center mb-half" id="accounts-disable-enable">{{ .strings.disable }}</span>
@@ -522,9 +577,15 @@
<th><input type="checkbox" value="" id="accounts-select-all"></th>
<th>{{ .strings.username }}</th>
<th>{{ .strings.emailAddress }}</th>
{{ if .telegram_enabled }}
{{ if .telegramEnabled }}
<th>Telegram</th>
{{ end }}
{{ if .matrixEnabled }}
<th>Matrix</th>
{{ end }}
{{ if .discordEnabled }}
<th>Discord</th>
{{ end }}
<th>{{ .strings.expiry }}</th>
<th>{{ .strings.lastActiveTime }}</th>
</tr>

49
html/crash.html Normal file
View File

@@ -0,0 +1,49 @@
<!doctype html>
<html lang="en">
<head>
<link inline rel="stylesheet" type="text/css" href="bundle.css">
{{ template "header.html" . }}
<title>Crash report</title>
</head>
<body>
<div class="page-container">
<div class="row">
<div class="col">
<div class="card ~critical sectioned">
<section class="section ~critical">
<span class="heading">Crash report for jfa-go</span>
{{ if .Err }}
<div class="monospace pre-line mt-1 mb-1">
Error: {{ .Err }}
</div>
{{ end }}
<a class="button ~critical mb-1" target="_blank" href="https://github.com/hrfee/jfa-go/issues/new/choose">Create an Issue</a>
</section>
<section class="section ~neutral !low">
<div class="flex-expand">
<span class="subheading">Full Log</span>
<span class="button ~urge ml-half" id="copy-log">Copy</span>
</div>
<div class="row mb-1">
<label class="col mr-1">
<span class="button ~neutral !high supra full-width center" id="button-log-normal">Normal</span>
</label>
<label class="col mr-1">
<span class="button ~neutral !normal supra full-width center" id="button-log-sanitized">Sanitized</span>
</label>
</div>
<div id="log-normal">
<pre class="monospace pre-line">{{ .Log }}</pre>
</div>
<div id="log-sanitized" class="unfocused">
<p class="subheading">An attempt has been made to remove sensitive info, but make sure to check yourself.</p>
<pre class="monospace pre-line">{{ .SanitizedLog }}</pre>
</div>
</section>
</div>
</div>
</div>
</div>
<script inline src="crash.js"></script>
</body>
</html>

View File

@@ -17,6 +17,18 @@
window.telegramEnabled = {{ .telegramEnabled }};
window.telegramRequired = {{ .telegramRequired }};
window.telegramPIN = "{{ .telegramPIN }}";
window.discordEnabled = {{ .discordEnabled }};
window.discordRequired = {{ .discordRequired }};
window.discordPIN = "{{ .discordPIN }}";
window.discordInviteLink = {{ .discordInviteLink }};
window.discordServerName = "{{ .discordServerName }}";
window.matrixEnabled = {{ .matrixEnabled }};
window.matrixRequired = {{ .matrixRequired }};
window.matrixUserID = "{{ .matrixUser }}";
</script>
{{ if .passwordReset }}
<script src="js/pwr.js" type="module"></script>
{{ else }}
<script src="js/form.js" type="module"></script>
{{ end }}
{{ end }}

View File

@@ -3,7 +3,13 @@
<head>
<link rel="stylesheet" type="text/css" href="css/bundle.css">
{{ template "header.html" . }}
<title>{{ .strings.pageTitle }}</title>
<title>
{{ if .passwordReset }}
{{ .strings.passwordReset }}
{{ else }}
{{ .strings.pageTitle }}
{{ end }}
</title>
</head>
<body class="max-w-full overflow-x-hidden section">
<div id="modal-success" class="modal">
@@ -37,6 +43,35 @@
</div>
</div>
{{ end }}
{{ if .discordEnabled }}
<div id="modal-discord" class="modal">
<div class="modal-content card">
<span class="heading mb-1">{{ .strings.linkDiscord }}</span>
<p class="content mb-1"> {{ .discordSendPINMessage }}</p>
<h1 class="ac">{{ .discordPIN }}</h1>
<a id="discord-invite"></a>
<span class="button ~info !normal full-width center mt-1" id="discord-waiting">{{ .strings.success }}</span>
</div>
</div>
{{ end }}
{{ if .matrixEnabled }}
<div id="modal-matrix" class="modal">
<div class="modal-content card">
<span class="heading mb-1">{{ .strings.linkMatrix }}</span>
<p class="content mb-1"> {{ .strings.matrixEnterUser }}</p>
<input type="text" class="input ~neutral !high" placeholder="@user:riot.im" id="matrix-userid">
<div class="subheading link-center mt-1">
<span class="shield ~info mr-1">
<span class="icon">
<i class="ri-chat-3-line"></i>
</span>
</span>
{{ .matrixUser }}
</div>
<span class="button ~info !normal full-width center mt-1" id="matrix-send">{{ .strings.submit }}</span>
</div>
</div>
{{ end }}
<span class="dropdown" tabindex="0" id="lang-dropdown">
<span class="button ~urge dropdown-button">
<i class="ri-global-line"></i>
@@ -51,8 +86,20 @@
<div class="page-container">
<div class="card ~neutral !low">
<div class="row baseline">
<span class="col heading">{{ .strings.createAccountHeader }}</span>
<span class="col subheading"> {{ .helpMessage }}</span>
<span class="col heading">
{{ if .passwordReset }}
{{ .strings.passwordReset }}
{{ else }}
{{ .strings.createAccountHeader }}
{{ end }}
</span>
<span class="col subheading">
{{ if .passwordReset }}
{{ .strings.enterYourPassword }}
{{ else }}
{{ .helpMessage }}
{{ end }}
</span>
</div>
<div class="row">
<div class="col">
@@ -60,6 +107,7 @@
<aside class="col aside sm ~warning" id="user-expiry-message"></aside>
{{ end }}
<form class="card ~neutral !normal" id="form-create" href="">
{{ if not .passwordReset }}
<label class="label supra">
{{ .strings.username }}
<input type="text" class="input ~neutral !high mt-half mb-1" placeholder="{{ .strings.username }}" id="create-username" aria-label="{{ .strings.username }}">
@@ -69,15 +117,36 @@
<input type="email" class="input ~neutral !high mt-half mb-1" placeholder="{{ .strings.emailAddress }}" id="create-email" aria-label="{{ .strings.emailAddress }}" value="{{ .email }}">
{{ if .telegramEnabled }}
<span class="button ~info !normal full-width center mb-1" id="link-telegram">{{ .strings.linkTelegram }}</span>
{{ end }}
{{ if .discordEnabled }}
<span class="button ~info !normal full-width center mb-1" id="link-discord">{{ .strings.linkDiscord }}</span>
{{ end }}
{{ if .matrixEnabled }}
<span class="button ~info !normal full-width center mb-1" id="link-matrix">{{ .strings.linkMatrix }}</span>
{{ end }}
{{ if or (.telegramEnabled) (or .discordEnabled .matrixEnabled) }}
<div id="contact-via" class="unfocused">
<label class="row switch pb-1">
<input type="radio" name="contact-via" value="email"><span>Contact through Email</span>
</label>
{{ if .telegramEnabled }}
<label class="row switch pb-1">
<input type="radio" name="contact-via" value="telegram" id="contact-via-telegram"><span>Contact through Telegram</span>
</label>
{{ end }}
{{ if .discordEnabled }}
<label class="row switch pb-1">
<input type="radio" name="contact-via" value="discord" id="contact-via-discord"><span>Contact through Discord</span>
</label>
{{ end }}
{{ if .matrixEnabled }}
<label class="row switch pb-1">
<input type="radio" name="contact-via" value="matrix" id="contact-via-matrix"><span>Contact through Matrix</span>
</label>
{{ end }}
</div>
{{ end }}
{{ end }}
<label class="label supra" for="create-password">{{ .strings.password }}</label>
<input type="password" class="input ~neutral !high mt-half mb-1" placeholder="{{ .strings.password }}" id="create-password" aria-label="{{ .strings.password }}">
@@ -85,7 +154,13 @@
<input type="password" class="input ~neutral !high mt-half mb-1" placeholder="{{ .strings.password }}" id="create-reenter-password" aria-label="{{ .strings.reEnterPassword }}">
<label>
<input type="submit" class="unfocused">
<span class="button ~urge !normal full-width center supra submit">{{ .strings.createAccountButton }}</span>
<span class="button ~urge !normal full-width center supra submit">
{{ if .passwordReset }}
{{ .strings.reset }}
{{ else }}
{{ .strings.createAccountButton }}
{{ end }}
</span>
</label>
</form>
</div>
@@ -110,4 +185,3 @@
{{ template "form-base" . }}
</body>
</html>

View File

@@ -40,6 +40,6 @@
</div>
<i class="content">{{ .contactMessage }}</i>
</div>
<script src="{{ .urlBase }}/js/pwr.js" type="module"></script>
<script src="{{ .urlBase }}/js/pwr-pin.js" type="module"></script>
</body>
</html>

View File

@@ -233,85 +233,92 @@
</section>
</div>
<div class="card ~neutral !low mb-1 unfocused">
<span class="heading">{{ .lang.Email.title }}</span>
<p class="content" id="email-description"></p>
<div class="row">
<div class="col">
<label class="label">
<span>{{ .lang.Email.method }}</span>
<div class="select ~neutral !normal mt-half mb-1">
<select id="email-method">
<option value="">{{ .lang.Strings.disabled }}</option>
<option value="smtp">SMTP</option>
<option value="mailgun">Mailgun</option>
</select>
</div>
</label>
<label class="row switch">
<input type="checkbox" id="email-no_username"><span>{{ .lang.Email.useEmailAsUsername }}</span>
<p class="support mb-1">{{ .lang.Email.useEmailAsUsernameNotice }}</p>
</label>
<label class="label">
<span class="mt-half">{{ .lang.Email.fromAddress }}</span>
<input type="email" class="input ~neutral !normal mt-half mb-1" id="email-address" placeholder="mail@jellyf.in">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Email.senderName }}</span>
<input type="text" class="input ~neutral !normal mt-half mb-1" id="email-from" value="Jellyfin">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Email.dateFormat }}</span>
<input type="text" class="input ~neutral !normal mt-half" id="email-date_format" value="%d/%m/%y">
<p class="support mb-1" id="email-dateformat-notice"></p>
</label>
<div>
<label class="row switch pb-1">
<input type="radio" name="email-24h" value="true" checked><span>{{ .lang.Strings.time24h }}</span>
</label>
<label class="row switch pb-1">
<input type="radio" name="email-24h" value="false"><span>{{ .lang.Strings.time12h }}</span>
</label>
</div>
</div>
<div class="col">
<div id="email-smtp">
<p class="subheading">SMTP</p>
<span class="heading">{{ .lang.Messages.title }}</span>
<p class="content" id="messages-description"></p>
<label class="row switch pb-1">
<input type="checkbox" id="messages-enabled" checked><span>{{ .lang.Strings.enabled }}</span>
</label>
<label class="label">
<span class="mt-half">{{ .lang.Email.dateFormat }}</span>
<input type="text" class="input ~neutral !normal mt-half" id="email-date_format" value="%d/%m/%y">
<p class="support mb-1" id="email-dateformat-notice"></p>
</label>
<div>
<label class="row switch pb-1">
<input type="radio" name="email-24h" value="true" checked><span>{{ .lang.Strings.time24h }}</span>
</label>
<label class="row switch pb-1">
<input type="radio" name="email-24h" value="false"><span>{{ .lang.Strings.time12h }}</span>
</label>
</div>
<div id="email-sect">
<span class="heading">{{ .lang.Email.title }}</span>
<p class="content" id="email-description"></p>
<div class="row">
<div class="col">
<label class="label">
<span>{{ .lang.Email.encryption }}</span>
<span>{{ .lang.Email.method }}</span>
<div class="select ~neutral !normal mt-half mb-1">
<select id="smtp-encryption">
<option value="starttls">STARTTLS ({{ .lang.Strings.port }} 587)</option>
<option value="ssl_tls">SSL/TLS ({{ .lang.Strings.port }} 465)</option>
<select id="email-method">
<option value="">{{ .lang.Strings.disabled }}</option>
<option value="smtp">SMTP</option>
<option value="mailgun">Mailgun</option>
</select>
</div>
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.serverAddress }}</span>
<input type="url" class="input ~neutral !normal mt-half mb-1" id="smtp-server" placeholder="smtp.jellyf.in">
<label class="row switch">
<input type="checkbox" id="email-no_username"><span>{{ .lang.Email.useEmailAsUsername }}</span>
<p class="support mb-1">{{ .lang.Email.useEmailAsUsernameNotice }}</p>
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.port }}</span>
<input type="number" class="input ~neutral !normal mt-half mb-1" id="smtp-port" placeholder="587">
<span class="mt-half">{{ .lang.Email.fromAddress }}</span>
<input type="email" class="input ~neutral !normal mt-half mb-1" id="email-address" placeholder="mail@jellyf.in">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.username }}</span>
<input type="text" class="input ~neutral !normal mt-half mb-1" id="smtp-username">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.password }}</span>
<input type="password" class="input ~neutral !normal mt-half mb-1" id="smtp-password">
<span class="mt-half">{{ .lang.Email.senderName }}</span>
<input type="text" class="input ~neutral !normal mt-half mb-1" id="email-from" value="Jellyfin">
</label>
</div>
<div id="email-mailgun">
<p class="subheading">Mailgun</p>
<label class="label">
<span class="mt-half">{{ .lang.Email.mailgunApiURL }}</span>
<input type="url" class="input ~neutral !normal mt-half mb-1" id="mailgun-api_url" placeholder="https://api.eu.mailgun.net/v3/mail.jellyf.in/messages">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.apiKey }}</span>
<input type="text" class="input ~neutral !normal mt-half mb-1" id="mailgun-api_key">
</label>
<div class="col">
<div id="email-smtp">
<p class="subheading">SMTP</p>
<label class="label">
<span>{{ .lang.Email.encryption }}</span>
<div class="select ~neutral !normal mt-half mb-1">
<select id="smtp-encryption">
<option value="starttls">STARTTLS ({{ .lang.Strings.port }} 587)</option>
<option value="ssl_tls">SSL/TLS ({{ .lang.Strings.port }} 465)</option>
</select>
</div>
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.serverAddress }}</span>
<input type="url" class="input ~neutral !normal mt-half mb-1" id="smtp-server" placeholder="smtp.jellyf.in">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.port }}</span>
<input type="number" class="input ~neutral !normal mt-half mb-1" id="smtp-port" placeholder="587">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.username }}</span>
<input type="text" class="input ~neutral !normal mt-half mb-1" id="smtp-username">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.password }}</span>
<input type="password" class="input ~neutral !normal mt-half mb-1" id="smtp-password">
</label>
</div>
<div id="email-mailgun">
<p class="subheading">Mailgun</p>
<label class="label">
<span class="mt-half">{{ .lang.Email.mailgunApiURL }}</span>
<input type="url" class="input ~neutral !normal mt-half mb-1" id="mailgun-api_url" placeholder="https://api.eu.mailgun.net/v3/mail.jellyf.in/messages">
</label>
<label class="label">
<span class="mt-half">{{ .lang.Strings.apiKey }}</span>
<input type="text" class="input ~neutral !normal mt-half mb-1" id="mailgun-api_key">
</label>
</div>
</div>
</div>
</div>
@@ -380,7 +387,11 @@
<input type="checkbox" id="password_resets-link_reset"><span>{{ .lang.PasswordResets.resetLinks }}</span>
<p class="support mb-1">{{ .lang.PasswordResets.resetLinksNotice }}</p>
</label>
<label class="row label">
<label class="switch">
<input type="checkbox" id="password_resets-set_password"><span>{{ .lang.PasswordResets.setPassword }}</span>
<p class="support mb-1">{{ .lang.PasswordResets.setPasswordNotice }}</p>
</label>
<label class="label">
<p class="mt-half">{{ .lang.PasswordResets.resetLinksLanguage }}</p>
<div class="select ~neutral !normal mt-half mb-1">
<select id="password_resets-language">

BIN
images/discord/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
images/discord/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
images/discord/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
images/discord/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
images/discord/5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
images/discord/6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

BIN
images/discord/7.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
images/discord/8.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
images/matrix/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
images/matrix/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

BIN
images/matrix/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
images/matrix/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
images/tg-settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/tg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -42,7 +42,7 @@ func (rt *inviteDaemon) run() {
}
}
func (rt *inviteDaemon) shutdown() {
func (rt *inviteDaemon) Shutdown() {
rt.Stopped = true
rt.ShutdownChannel <- "Down"
<-rt.ShutdownChannel

View File

@@ -117,6 +117,7 @@ type setupLang struct {
JellyfinEmby langSection `json:"jellyfinEmby"`
Ombi langSection `json:"ombi"`
Email langSection `json:"email"`
Messages langSection `json:"messages"`
Notifications langSection `json:"notifications"`
WelcomeEmails langSection `json:"welcomeEmails"`
PasswordResets langSection `json:"passwordResets"`

204
lang/admin/da-dk.json Normal file
View File

@@ -0,0 +1,204 @@
{
"meta": {
"name": "Dansk"
},
"strings": {
"invites": "Invitationer",
"accounts": "Konti",
"settings": "Indstillinger",
"inviteMonths": "Måneder",
"inviteDays": "Dage",
"inviteHours": "Timer",
"inviteMinutes": "Minutter",
"inviteNumberOfUses": "Antal anvendelser",
"inviteDuration": "Invitations varighed",
"warning": "Advarsel",
"inviteInfiniteUsesWarning": "invitationer med uendelig brug kan blive misbrugt",
"inviteSendToEmail": "Send til",
"login": "Log på",
"logout": "Log ud",
"create": "Opret",
"apply": "Anvend",
"delete": "Slet",
"add": "Tilføj",
"select": "Vælg",
"name": "Navn",
"date": "Dato",
"enabled": "Aktiveret",
"disabled": "Deaktiveret",
"reEnable": "Genaktiver",
"disable": "Deaktiver",
"admin": "Administrator",
"updates": "Opdateringer",
"update": "Opdatering",
"download": "Hent",
"search": "Søg",
"advancedSettings": "Avanceret Indstillinger",
"lastActiveTime": "Sidst Aktiv",
"from": "Fra",
"user": "Bruger",
"expiry": "Udløb",
"userExpiry": "Brugerens Udløb",
"userExpiryDescription": "En specificeret tid efter hver tilmelding, sletter/deaktiverer jfa-go kontoen. Du kan ændre denne adfærd i indstillingerne.",
"aboutProgram": "Om",
"version": "Version",
"commitNoun": "Commit",
"newUser": "Ny Bruger",
"profile": "Profil",
"unknown": "Ukendt",
"label": "Etiket",
"announce": "Annoncere",
"subject": "Emne",
"message": "Meddelelse",
"variables": "Variabler",
"conditionals": "Betingelser",
"preview": "Eksempel",
"reset": "Nulstil",
"edit": "Rediger",
"donate": "Doner",
"contactThrough": "Kontakt gennem:",
"extendExpiry": "Forlæng udløb",
"customizeMessages": "Tilpas Meddelelser",
"customizeMessagesDescription": "Hvis du ikke vil bruge jfa-go's meddelelses skabeloner, kan du oprette din egen ved hjælp af Markdown.",
"markdownSupported": "Markdown understøttes.",
"modifySettings": "Rediger indstillinger",
"modifySettingsDescription": "Anvend indstillinger fra en eksisterende profil, eller hent dem direkte fra en bruger.",
"applyHomescreenLayout": "Anvend startskærmens layout",
"sendDeleteNotificationEmail": "Send notifikations meddelelse",
"sendDeleteNotifiationExample": "Din konto er blevet slettet.",
"settingsRestart": "Genstart",
"settingsRestarting": "Genstarter…",
"settingsRestartRequired": "Genstart nødvendig",
"settingsRestartRequiredDescription": "En genstart er nødvendig for at anvende nogle indstillinger du har ændret. Genstart nu eller senere?",
"settingsApplyRestartLater": "Anvend, genstart senere",
"settingsApplyRestartNow": "Anvend & genstart",
"settingsApplied": "Indstillingerne anvendt.",
"settingsRefreshPage": "Opdater siden om få sekunder.",
"settingsRequiredOrRestartMessage": "Bemærk: {n} angiver et obligatorisk felt, {n} angiver at ændringer kræver genstart.",
"settingsSave": "Gem",
"ombiUserDefaults": "Ombi bruger standarder",
"ombiUserDefaultsDescription": "Opret en Ombi bruger og konfigurer den, vælg den derefter nedenfor. Brugerens indstillinger/tilladelser gemmes og anvendes på nye Ombi brugere oprettet af jfa-go",
"userProfiles": "Bruger Profiler",
"userProfilesDescription": "Profiler anvendes på brugere når de opretter en konto. En profil inkluderer adgangsrettigheder til biblioteket og layout på startskærmen.",
"userProfilesIsDefault": "Standard",
"userProfilesLibraries": "Biblioteker",
"addProfile": "Tilføj Profil",
"addProfileDescription": "Opret en Jellyfin bruger og konfigurer den, vælg den derefter nedenfor. Når denne profil anvendes på en invitation, oprettes nye brugere med indstillingerne.",
"addProfileNameOf": "Profil Navn",
"addProfileStoreHomescreenLayout": "Gem startskærmens layout",
"inviteNoUsersCreated": "Ingen endnu!",
"inviteUsersCreated": "Oprettet brugere",
"inviteNoProfile": "Ingen Profil",
"inviteDateCreated": "Oprettet",
"inviteRemainingUses": "Resterende anvendelser",
"inviteNoInvites": "Ingen",
"inviteExpiresInTime": "Udløber om {n}",
"notifyEvent": "Meddel den:",
"notifyInviteExpiry": "Ved udløb",
"notifyUserCreation": "Ved oprettelse af brugere",
"sendPIN": "Bed brugeren om at sende pinkoden nedenfor til botten.",
"searchDiscordUser": "Begynd at skrive Discord brugernavnet for at finde brugeren.",
"findDiscordUser": "Find Discord bruger",
"linkMatrixDescription": "Indtast brugernavnet og adgangskoden til den bruger der skal bruges som en bot. Når indsendt, genstarter appen.",
"matrixHomeServer": "Hjemme server adresse",
"saveAsTemplate": "Gem som skabelon",
"templates": "Skabeloner",
"deleteTemplate": "Slet skabelon",
"templateEnterName": "Indtast et navn for at gemme denne skabelon."
},
"notifications": {
"changedEmailAddress": "Ændret e-mail adresse på {n}.",
"userCreated": "Bruger {n} oprettet.",
"createProfile": "Oprettede profil {n}.",
"saveSettings": "Indstillingerne blev gemt",
"saveEmail": "E-mail gemt.",
"sentAnnouncement": "Meddelelse sendt.",
"setOmbiDefaults": "Ombi standarder gemt.",
"updateApplied": "Opdatering anvendt, genstart.",
"updateAppliedRefresh": "Opdatering anvendt, genindlæs venligst siden.",
"telegramVerified": "Telegram konto verificeret.",
"accountConnected": "Konto tilsluttet.",
"errorConnection": "Kunne ikke oprette forbindelse til jfa-go.",
"error401Unauthorized": "Adgang nægtet. Prøv at genindlæse siden.",
"errorSettingsAppliedNoHomescreenLayout": "Indstillingerne blev anvendt, men anvendelse af startskærmens layout mislykkedes muligvis.",
"errorHomescreenAppliedNoSettings": "Startskærmens layout blev anvendt, men anvendelsen af indstillingerne mislykkedes muligvis.",
"errorSettingsFailed": "Ansøgningen mislykkedes.",
"errorLoginBlank": "Brugernavnet og/eller adgangskoden blev efterladt tomme.",
"errorUnknown": "Ukendt fejl.",
"errorSaveEmail": "Kunne ikke gemme e-mail.",
"errorBlankFields": "Felter blev efterladt tomme",
"errorDeleteProfile": "Kunne ikke slette profilen {n}",
"errorLoadProfiles": "Profiler kunne ikke indlæses.",
"errorCreateProfile": "Kunne ikke oprette profilen {n}",
"errorSetDefaultProfile": "Standard profilen kunne ikke indstilles.",
"errorLoadUsers": "Kunne ikke indlæse brugere.",
"errorSaveSettings": "Kunne ikke gemme indstillingerne.",
"errorLoadSettings": "Indstillingerne kunne ikke indlæses.",
"errorSetOmbiDefaults": "Ombi standarderne kunne ikke gemmes.",
"errorLoadOmbiUsers": "Kunne ikke indlæse ombi brugere.",
"errorChangedEmailAddress": "Kunne ikke ændre e-mail adressen på {n}.",
"errorFailureCheckLogs": "Mislykkedes (tjek konsol/logfiler)",
"errorPartialFailureCheckLogs": "Delvis fejl (tjek konsol/logfiler)",
"errorUserCreated": "Kunne ikke oprette bruger {n}.",
"errorSendWelcomeEmail": "Kunne ikke sende velkomst meddelelse (tjek konsol/logfiler",
"errorApplyUpdate": "Kunne ikke anvende opdateringen, prøv manuelt.",
"errorCheckUpdate": "Kunne ikke kontrollere for opdatering.",
"updateAvailable": "En ny opdatering er tilgængelig, tjek indstillingerne.",
"noUpdatesAvailable": "Ingen nye opdateringer tilgængelige.",
"savedAnnouncement": "Meddelelse gemt."
},
"quantityStrings": {
"modifySettingsFor": {
"singular": "Rediger indstillinger for {n} bruger",
"plural": "Rediger indstillinger for {n} brugere"
},
"deleteNUsers": {
"singular": "Slet {n} bruger",
"plural": "Slet {n} brugere"
},
"disableUsers": {
"singular": "Deaktiver {n} bruger",
"plural": "Deaktiver {n} brugere"
},
"reEnableUsers": {
"singular": "Genaktiver {n} bruger",
"plural": "Genaktiver {n} brugere"
},
"addUser": {
"singular": "Tilføj bruger",
"plural": "Tilføj brugere"
},
"deleteUser": {
"singular": "Slet bruger",
"plural": "Slet brugere"
},
"deletedUser": {
"singular": "Slettede {n} bruger.",
"plural": "Slettede {n} brugere."
},
"disabledUser": {
"singular": "Deaktiveret {n} bruger.",
"plural": "Deaktiverede {n} brugere."
},
"enabledUser": {
"singular": "Aktiveret {n} bruger.",
"plural": "Aktiveret {n} brugere."
},
"announceTo": {
"singular": "Annoncer til {n} bruger",
"plural": "Annoncer til {n} brugere"
},
"appliedSettings": {
"singular": "Anvendte indstillinger til {n} bruger.",
"plural": "Anvendte indstillinger til {n} brugere."
},
"extendExpiry": {
"singular": "Forlæng udløbet for {n} bruger",
"plural": "Forlæng udløbet for {n} brugere"
},
"extendedExpiry": {
"singular": "Forlængede udløb for {n} bruger.",
"plural": "Forlængede udløb for {n} brugere."
}
}
}

View File

@@ -32,7 +32,7 @@
"modifySettings": "Einstellungen ändern",
"modifySettingsDescription": "Wende Einstellungen von einem bestehenden Profil an, oder beziehe sie direkt von einem Benutzer.",
"applyHomescreenLayout": "Startbildschirmlayout anwenden",
"sendDeleteNotificationEmail": "Benachrichtigungs-E-Mail senden",
"sendDeleteNotificationEmail": "Benachrichtigung senden",
"sendDeleteNotifiationExample": "Dein Konto wurde gelöscht.",
"settingsRestartRequired": "Neustart erforderlich",
"settingsRestartRequiredDescription": "Ein Neustart ist notwendig, um einige Einstellungen anzuwenden, die du geändert hast. Jetzt oder später neu starten?",
@@ -72,7 +72,7 @@
"customizeMessages": "E-Mails anpassen",
"customizeMessagesDescription": "Wenn du jfa-go's E-Mail-Vorlagen nicht benutzen willst, kannst du deinen eigenen unter Verwendung von Markdown erstellen.",
"announce": "Ankündigen",
"subject": "E-Mail-Betreff",
"subject": "Betreff",
"message": "Nachricht",
"markdownSupported": "Markdown wird unterstützt.",
"advancedSettings": "Erweiterte Einstellungen",
@@ -87,7 +87,20 @@
"update": "Aktualisieren",
"updates": "Aktualisierungen",
"expiry": "Ablaufdatum",
"extendExpiry": "Ablaufdatum verlängern"
"extendExpiry": "Ablaufdatum verlängern",
"reEnable": "Wieder aktivieren",
"disable": "Deaktivieren",
"donate": "Spenden",
"conditionals": "Bedingungen",
"contactThrough": "Kontakt über:",
"sendPIN": "Bitte den Benutzer, die unten stehende PIN an den Bot zu senden.",
"inviteMonths": "Monate",
"add": "Hinzufügen",
"select": "Auswählen",
"searchDiscordUser": "Gib den Discord-Benutzername ein, um den Benutzer zu finden.",
"findDiscordUser": "Suche Discord-Benutzer",
"linkMatrixDescription": "Gib den Benutzernamen und das Passwort des Benutzers ein, der als Bot verwendet werden soll. Nach dem Absenden wird die App neu gestartet.",
"matrixHomeServer": "Adresse des Homeservers"
},
"notifications": {
"changedEmailAddress": "E-Mail-Adresse von {n} geändert.",
@@ -116,7 +129,7 @@
"errorFailureCheckLogs": "Fehlgeschlagen (überprüfe die Konsole/Logs)",
"errorPartialFailureCheckLogs": "Teilweiser Fehlschlag (überprüfe die Konsole/Logs)",
"errorUserCreated": "Fehler beim Erstellen des Benutzers {n}.",
"errorSendWelcomeEmail": "Fehler beim Senden der Willkommens-E-Mail (überprüfe die Konsole/Logs)",
"errorSendWelcomeEmail": "Fehler beim Senden der Willkommensnachricht (überprüfe die Konsole/Logs)",
"saveEmail": "E-Mail gespeichert.",
"errorSaveEmail": "Fehler beim Speichern der E-Mail.",
"sentAnnouncement": "Ankündigung gesendet.",
@@ -124,7 +137,10 @@
"errorApplyUpdate": "Fehler beim Anwenden der Aktualisierung, versuche es manuell.",
"errorCheckUpdate": "Fehler beim Suchen nach Aktualisierungen.",
"updateAvailable": "Eine neue Aktualisierung ist verfügbar, überprüfe die Einstellungen.",
"noUpdatesAvailable": "Keinen neuen Aktualisierungen verfügbar."
"noUpdatesAvailable": "Keinen neuen Aktualisierungen verfügbar.",
"updateAppliedRefresh": "Update angewendet, bitte aktualisieren.",
"telegramVerified": "Telegram-Konto verifiziert.",
"accountConnected": "Konto verbunden."
},
"quantityStrings": {
"modifySettingsFor": {
@@ -162,6 +178,22 @@
"extendedExpiry": {
"singular": "Ablaufdatum für {n} Benutzer verlängern.",
"plural": "Ablaufdatum für {n} Benutzer verlängern."
},
"disabledUser": {
"plural": "Benutzer {n} Deaktiviert.",
"singular": "Benutzer {n} Deaktiviert."
},
"enabledUser": {
"singular": "Benutzer {n} Aktiviert.",
"plural": "Benutzer {n} Aktiviert."
},
"disableUsers": {
"singular": "Benutzer {n} deaktivieren",
"plural": "Deaktiviere {n} Benutzer"
},
"reEnableUsers": {
"singular": "Benutzer {n} wieder aktivieren",
"plural": "Benutzer {n} wieder aktivieren"
}
}
}

View File

@@ -20,6 +20,8 @@
"create": "Create",
"apply": "Apply",
"delete": "Delete",
"add": "Add",
"select": "Select",
"name": "Name",
"date": "Date",
"enabled": "Enabled",
@@ -46,6 +48,7 @@
"unknown": "Unknown",
"label": "Label",
"announce": "Announce",
"templates": "Templates",
"subject": "Subject",
"message": "Message",
"variables": "Variables",
@@ -94,7 +97,14 @@
"notifyEvent": "Notify on:",
"notifyInviteExpiry": "On expiry",
"notifyUserCreation": "On user creation",
"sendPIN": "Ask the user to send the PIN below to the bot."
"sendPIN": "Ask the user to send the PIN below to the bot.",
"searchDiscordUser": "Start typing the Discord username to find the user.",
"findDiscordUser": "Find Discord user",
"linkMatrixDescription": "Enter the username and password of the user to use as a bot. Once submitted, the app will restart.",
"matrixHomeServer": "Home server address",
"saveAsTemplate": "Save as template",
"deleteTemplate": "Delete template",
"templateEnterName": "Enter a name to save this template."
},
"notifications": {
"changedEmailAddress": "Changed email address of {n}.",
@@ -103,10 +113,12 @@
"saveSettings": "Settings were saved",
"saveEmail": "Email saved.",
"sentAnnouncement": "Announcement sent.",
"savedAnnouncement": "Announcement saved.",
"setOmbiDefaults": "Stored ombi defaults.",
"updateApplied": "Update applied, please restart.",
"updateAppliedRefresh": "Update applied, please refresh.",
"telegramVerified": "Telegram account verified.",
"accountConnected": "Account connected.",
"errorConnection": "Couldn't connect to jfa-go.",
"error401Unauthorized": "Unauthorized. Try refreshing the page.",
"errorSettingsAppliedNoHomescreenLayout": "Settings were applied, but applying homescreen layout may have failed.",

View File

@@ -17,7 +17,7 @@
"inviteSendToEmail": "Enviar a",
"login": "Acceso",
"logout": "Cerrar sesión",
"create": "Cerrar sesión",
"create": "Crear",
"apply": "Aplicar",
"delete": "Eliminar",
"name": "Nombre",
@@ -91,7 +91,20 @@
"notifyEvent": "Notificar en:",
"notifyInviteExpiry": "Al vencimiento",
"notifyUserCreation": "Sobre la creación de usuarios",
"conditionals": "Condicionales"
"conditionals": "Condicionales",
"donate": "Donar",
"add": "Añadir",
"templates": "Plantillas",
"contactThrough": "Contactar a través de:",
"select": "Seleccionar",
"sendPIN": "Pídale al usuario que envíe el PIN a continuación al bot.",
"searchDiscordUser": "Comienza a escribir el nombre de usuario de Discord para encontrar a la usuario.",
"findDiscordUser": "Encontrar usuario de Discord",
"linkMatrixDescription": "Ingrese el nombre de usuario y la contraseña para usar como bot. Una vez enviada, la aplicación se reiniciará",
"matrixHomeServer": "Dirección del servidor de inicio",
"saveAsTemplate": "Guardar plantilla",
"deleteTemplate": "Eliminar plantilla",
"templateEnterName": "Ingrese un nombre para guardar esta plantilla."
},
"notifications": {
"changedEmailAddress": "Se cambió la dirección de correo electrónico de {n}.",
@@ -124,11 +137,15 @@
"errorFailureCheckLogs": "Fallido (ver consola / registros)",
"errorPartialFailureCheckLogs": "Fallo parcial (ver consola / registros)",
"errorUserCreated": "No se pudo crear el usuario {n}.",
"errorSendWelcomeEmail": "No se pudo enviar el correo electrónico de bienvenida (verifique la consola / registros)",
"errorSendWelcomeEmail": "No se pudo enviar el mensaje de bienvenida (verifique la consola / registros)",
"errorApplyUpdate": "No se pudo aplicar la actualización, intente manualmente.",
"errorCheckUpdate": "No se pudo comprobar la actualización.",
"updateAvailable": "Hay una nueva actualización disponible, verifique la configuración.",
"noUpdatesAvailable": "No hay nuevas actualizaciones disponibles."
"noUpdatesAvailable": "No hay nuevas actualizaciones disponibles.",
"updateAppliedRefresh": "Actualización aplicada, actualice.",
"accountConnected": "Cuenta conectada.",
"savedAnnouncement": "Anuncio guardado.",
"telegramVerified": "Cuenta de Telegram verificada."
},
"quantityStrings": {
"modifySettingsFor": {

View File

@@ -34,7 +34,7 @@
"modifySettings": "Modifier les paramètres",
"modifySettingsDescription": "Appliquez les paramètres à partir d'un profil existant ou obtenez-les directement auprès d'un utilisateur.",
"applyHomescreenLayout": "Appliquer la disposition de l'écran d'accueil",
"sendDeleteNotificationEmail": "Envoyer un e-mail de notification",
"sendDeleteNotificationEmail": "Envoyer un message de notification",
"sendDeleteNotifiationExample": "Votre compte a été supprimé.",
"settingsRestartRequired": "Redémarrage nécessaire",
"settingsRestartRequiredDescription": "Un redémarrage est nécessaire pour appliquer certains paramètres que vous avez modifiés. Redémarrer maintenant ou plus tard ?",
@@ -74,7 +74,7 @@
"customizeMessagesDescription": "Si vous ne souhaitez pas utiliser les modèles d'e-mails de jfa-go, vous pouvez créer les vôtres à l'aide de Markdown.",
"variables": "Variables",
"preview": "Aperçu",
"reset": "Réinitialiser",
"reset": "Réinitialisation",
"edit": "Éditer",
"customizeMessages": "Personnaliser les e-mails",
"inviteDuration": "Durée de l'invitation",
@@ -90,7 +90,18 @@
"update": "Mise à jour",
"download": "Téléchargement",
"search": "Recherche",
"conditionals": "Conditions"
"conditionals": "Conditions",
"userExpiryDescription": "Un laps de temps spécifié après chaque inscription, jfa-go supprimera / désactivera le compte. Vous pouvez modifier ce comportement dans les paramètres.",
"donate": "Faire un don",
"extendExpiry": "Prolonger l'expiration",
"contactThrough": "Contacté par :",
"sendPIN": "Demandez à l'utilisateur d'envoyer le code PIN ci-dessous au bot.",
"add": "Ajouter",
"select": "Sélectionner",
"findDiscordUser": "Trouver l'utilisateur Discord",
"linkMatrixDescription": "Entrez le nom d'utilisateur et le mot de passe de l'utilisateur pour lutilisateur comme bot. Une fois soumis, l'application va redémarrer.",
"searchDiscordUser": "Commencez à taper le nom d'utilisateur Discord pour trouver l'utilisateur.",
"matrixHomeServer": "Adresse du serveur"
},
"notifications": {
"changedEmailAddress": "Adresse e-mail modifiée de {n}.",
@@ -119,11 +130,18 @@
"errorFailureCheckLogs": "Échec (vérifier la console / les journaux)",
"errorPartialFailureCheckLogs": "Panne partielle (vérifier la console / les journaux)",
"errorUserCreated": "Echec lors de la création de l'utilisateur {n}.",
"errorSendWelcomeEmail": "Echec lors de l'envoi du mail de bienvenue (vérifier la console/les journaux)",
"errorSendWelcomeEmail": "Echec lors de l'envoi du message de bienvenue (vérifier la console/les journaux)",
"sentAnnouncement": "Annonce envoyée.",
"saveEmail": "Email enregistré.",
"errorSaveEmail": "Échec de l'enregistrement de l'e-mail.",
"updateApplied": "Mise à jour appliquée, veuillez redémarrer."
"updateApplied": "Mise à jour appliquée, veuillez redémarrer.",
"errorApplyUpdate": "Échec de l'application de la mise à jour, essayez manuellement.",
"errorCheckUpdate": "Échec de la vérification de la mise à jour.",
"updateAvailable": "Une nouvelle mise à jour est disponible, vérifiez les paramètres.",
"noUpdatesAvailable": "Aucune nouvelle mise à jour disponible.",
"telegramVerified": "Compte Telegram vérifié.",
"updateAppliedRefresh": "Mise à jour appliquée, veuillez actualiser.",
"accountConnected": "Compte connecté."
},
"quantityStrings": {
"modifySettingsFor": {
@@ -153,6 +171,30 @@
"announceTo": {
"singular": "Annonce à {n} utilisateur",
"plural": "Annonce à {n} utilisateurs"
},
"enabledUser": {
"plural": "{n} utilisateurs activés.",
"singular": "{n} utilisateur activé."
},
"extendExpiry": {
"singular": "Prolonger l'expiration pour {n} utilisateur",
"plural": "Prolonger l'expiration pour {n} utilisateurs"
},
"extendedExpiry": {
"singular": "Expiration prolongée pour {n} utilisateur.",
"plural": "Expiration prolongée pour {n} utilisateurs."
},
"disableUsers": {
"singular": "Désactiver {n} utilisateur",
"plural": "Désactiver {n} utilisateurs"
},
"reEnableUsers": {
"singular": "Ré-activer {n} utilisateur",
"plural": "Ré-activer {n} utilisateurs"
},
"disabledUser": {
"singular": "{n} utilisateur désactivé.",
"plural": "{n} utilisateurs désactivés."
}
}
}

View File

@@ -32,7 +32,7 @@
"modifySettings": "Instellingen aanpassen",
"modifySettingsDescription": "Pas instellingen van een bestaand profiel toe, of neem ze direct over van een gebruiker.",
"applyHomescreenLayout": "Sla startpagina indeling op",
"sendDeleteNotificationEmail": "Stuur meldingse-mail",
"sendDeleteNotificationEmail": "Stuur melding",
"sendDeleteNotifiationExample": "Je account is verwijderd.",
"settingsRestartRequired": "Herstart nodig",
"settingsRestartRequiredDescription": "Er is een herstart nodig om de wijzigingen door te voeren. Herstart nu of later?",
@@ -67,12 +67,12 @@
"settingsRestarting": "Aan het herstarten…",
"announce": "Aankondiging",
"markdownSupported": "Markdown wordt ondersteund.",
"subject": "E-mailonderwerp",
"subject": "Onderwerp",
"message": "Bericht",
"variables": "Variabelen",
"customizeMessagesDescription": "Als je de e-mailsjablonen van jfa-go niet wilt gebruiken, kun je met gebruik van Markdown je eigen aanmaken.",
"preview": "Voorbeeld",
"reset": "Resetten",
"reset": "Reset",
"edit": "Bewerken",
"customizeMessages": "E-mails aanpassen",
"inviteDuration": "Geldigheidsduur uitnodiging",
@@ -91,7 +91,20 @@
"inviteMonths": "Maanden",
"reEnable": "Opnieuw inschakelen",
"disable": "Uitschakelen",
"conditionals": "Voorwaarden"
"conditionals": "Voorwaarden",
"donate": "Doneer",
"contactThrough": "Stuur bericht via:",
"sendPIN": "Vraag de gebruiker om onderstaande pincode naar de bot te sturen.",
"add": "Voeg toe",
"searchDiscordUser": "Begin de Discord gebruikersnaam te typen om de gebruiker te vinden.",
"linkMatrixDescription": "Vul de gebruikersnaam en wachtwoord in van de gebruiker om als bot te gebruiken. De app start zodra ze zijn verstuurd.",
"select": "Selecteer",
"findDiscordUser": "Zoek Discord gebruiker",
"matrixHomeServer": "Adres home server",
"templates": "Sjablonen",
"templateEnterName": "Voer een naam in om dit sjabloon op te slaan.",
"saveAsTemplate": "Sla op als sjabloon",
"deleteTemplate": "Verwijder sjabloon"
},
"notifications": {
"changedEmailAddress": "E-mailadres van {n} gewijzigd.",
@@ -119,7 +132,7 @@
"errorChangedEmailAddress": "Wijzigen van e-mailadres van {n} mislukt.",
"errorFailureCheckLogs": "Mislukt (controleer console/logbestanden)",
"errorPartialFailureCheckLogs": "Gedeeltelijke fout (controleer console/logbestanden)",
"errorSendWelcomeEmail": "Versturen van welkomste-mail is mislukt (zie console/logs)",
"errorSendWelcomeEmail": "Versturen van welkomstbericht is mislukt (zie console/logs)",
"errorUserCreated": "Aanmaken van gebruiker {n} is mislukt.",
"sentAnnouncement": "Aankondiging verzonden.",
"saveEmail": "E-mail opgeslagen.",
@@ -128,7 +141,11 @@
"errorApplyUpdate": "Installatie van update mislukt, probeer handmatig.",
"errorCheckUpdate": "Controleren op update mislukt.",
"updateAvailable": "Er is een nieuwe update beschikbaar, kijk bij instellingen.",
"noUpdatesAvailable": "Geen nieuwe updates beschikbaar."
"noUpdatesAvailable": "Geen nieuwe updates beschikbaar.",
"telegramVerified": "Telegram-account goedgekeurd.",
"updateAppliedRefresh": "Update toegepast, ververs alsjeblieft.",
"accountConnected": "Account gekoppeld.",
"savedAnnouncement": "Aankondiging opgeslagen."
},
"quantityStrings": {
"modifySettingsFor": {

View File

@@ -33,7 +33,7 @@
"modifySettings": "Modificar configurações",
"modifySettingsDescription": "Aplique as configurações de um perfil existente ou obtenha-as diretamente de um usuário.",
"applyHomescreenLayout": "Aplicar layout na tela inicial",
"sendDeleteNotificationEmail": "Enviar email de notificação",
"sendDeleteNotificationEmail": "Enviar mensagem de notificação",
"sendDeleteNotifiationExample": "Sua conta foi deletada.",
"settingsRestartRequired": "Necessário reiniciar",
"settingsRestartRequiredDescription": "É necessário reiniciar para aplicar algumas configurações alteradas. Deseja reiniciar agora ou mais tarde?",
@@ -66,7 +66,7 @@
"settingsRestart": "Reiniciar",
"settingsRestarting": "Reiniciando…",
"announce": "Anunciar",
"subject": "Assunto do email",
"subject": "Assunto",
"message": "Mensagem",
"markdownSupported": "Suporte a Markdown.",
"customizeMessagesDescription": "Se não quiser usar os modelos de email do jfa-go, você pode criar o seu próprio usando o Markdown.",
@@ -91,7 +91,20 @@
"inviteMonths": "Meses",
"reEnable": "Reativar",
"disable": "Desativar",
"conditionals": "Condicionais"
"conditionals": "Condicionais",
"donate": "Doar",
"contactThrough": "Contato através:",
"sendPIN": "Peça ao usuário para enviar o PIN abaixo para o bot.",
"searchDiscordUser": "Digite o nome de usuário do Discord.",
"findDiscordUser": "Encontrar usuário Discord",
"add": "Adicionar",
"linkMatrixDescription": "Digite o nome de usuário e a senha para usar como bot. Depois de enviado, o aplicativo será reiniciado.",
"select": "Selecionar",
"templates": "Modelos",
"matrixHomeServer": "Endereço do servidor local",
"saveAsTemplate": "Salvar o modelo",
"deleteTemplate": "Deletar modelo",
"templateEnterName": "Digite um nome para salvar este modelo."
},
"notifications": {
"changedEmailAddress": "Endereço de e-mail alterado de {n}.",
@@ -120,7 +133,7 @@
"errorFailureCheckLogs": "Falha (verificar console/logs)",
"errorPartialFailureCheckLogs": "Falha parcial (verificar console/logs)",
"errorUserCreated": "Falha ao criar o usuário {n}.",
"errorSendWelcomeEmail": "Falha ao enviar e-mail de boas-vindas (verifique console/logs)",
"errorSendWelcomeEmail": "Falha ao enviar mensagem de boas-vindas (verifique console/logs)",
"sentAnnouncement": "Comunicado enviado.",
"saveEmail": "Email salvo.",
"errorSaveEmail": "Falha ao salvar o email.",
@@ -128,7 +141,11 @@
"errorApplyUpdate": "Falha ao aplicar a atualização, tente manualmente.",
"updateAvailable": "Uma nova atualização está disponível, verifique as configurações.",
"errorCheckUpdate": "Falha ao verificar atualizações.",
"noUpdatesAvailable": "Nenhuma atualização disponível."
"noUpdatesAvailable": "Nenhuma atualização disponível.",
"telegramVerified": "Conta do Telegram verificada.",
"updateAppliedRefresh": "Atualização instalada, atualize.",
"accountConnected": "Conta conectada.",
"savedAnnouncement": "Anúncio salvo."
},
"quantityStrings": {
"modifySettingsFor": {

204
lang/admin/zh-hans.json Normal file
View File

@@ -0,0 +1,204 @@
{
"meta": {
"name": "简体中文(CN)"
},
"strings": {
"invites": "邀请",
"accounts": "用户",
"settings": "设置",
"inviteMonths": "月",
"inviteDays": "日",
"inviteHours": "小时",
"inviteMinutes": "分钟",
"inviteNumberOfUses": "使用次数",
"inviteDuration": "邀请时长",
"warning": "警告",
"inviteInfiniteUsesWarning": "无限使用次数的邀请码可能被滥用",
"inviteSendToEmail": "发送到",
"login": "登录",
"logout": "登出",
"create": "创建",
"apply": "申请",
"delete": "删除",
"add": "添加",
"select": "选择",
"name": "名称",
"date": "日期",
"enabled": "已启用",
"disabled": "已禁用",
"reEnable": "重新启用",
"disable": "禁用",
"admin": "管理员",
"updates": "更新",
"update": "更新",
"download": "下载",
"search": "搜索",
"advancedSettings": "高级设置",
"lastActiveTime": "上次活动",
"from": "从",
"user": "用户",
"expiry": "到期",
"userExpiry": "用户到期",
"userExpiryDescription": "每次注册后的指定时间jfa-go 将删除/禁用该帐户。您可以在设置中更改此行为。",
"aboutProgram": "关于",
"version": "版本",
"commitNoun": "提交",
"newUser": "新用户",
"profile": "个人资料",
"unknown": "未知",
"label": "标签",
"announce": "宣布",
"templates": "模板",
"subject": "主题",
"message": "信息",
"variables": "变量",
"conditionals": "条件性条款",
"preview": "预览",
"reset": "重设",
"edit": "编辑",
"donate": "捐助",
"contactThrough": "联系方式:",
"extendExpiry": "延长有效期",
"customizeMessages": "自定义消息",
"customizeMessagesDescription": "如果不想使用 jfa-go 的消息模板,可以使用 Markdown 创建自己的消息模板。",
"markdownSupported": "已支持Markdown。",
"modifySettings": "修改设置",
"modifySettingsDescription": "应用现有配置文件中的设置,或直接从用户处获取设置。",
"applyHomescreenLayout": "应用主屏幕布局",
"sendDeleteNotificationEmail": "发送通知消息",
"sendDeleteNotifiationExample": "您的帐户已被删除。",
"settingsRestart": "重启",
"settingsRestarting": "正在重启……",
"settingsRestartRequired": "需要重启",
"settingsRestartRequiredDescription": "需要重新启动才能应用您更改的某些设置。现在重启还是稍后重启?",
"settingsApplyRestartLater": "应用,稍后重启",
"settingsApplyRestartNow": "应用并重启",
"settingsApplied": "已应用设置。",
"settingsRefreshPage": "几秒钟后刷新页面。",
"settingsRequiredOrRestartMessage": "注意:{n} 表示必填字段,{n} 表示更改需要重新启动。",
"settingsSave": "保存",
"ombiUserDefaults": "Ombi 用户默认值",
"ombiUserDefaultsDescription": "创建并配置 Ombi 用户,然后在下面选择它。它的设置/权限将被存储并应用于由 jfa-go 创建的新 Ombi 用户",
"userProfiles": "用户档案",
"userProfilesDescription": "配置文件在用户创建帐户时应用于用户。配置文件包括库访问权限和主屏幕布局。",
"userProfilesIsDefault": "默认",
"userProfilesLibraries": "库",
"addProfile": "添加档案",
"addProfileDescription": "创建一个 Jellyfin 用户并配置它,然后在下面选择它。将此配置文件应用于邀请时,将使用这些设置创建新用户。",
"addProfileNameOf": "配置文件名称",
"addProfileStoreHomescreenLayout": "保存主屏幕布局",
"inviteNoUsersCreated": "暂时不!",
"inviteUsersCreated": "已创建的用户",
"inviteNoProfile": "没有个人资料",
"inviteDateCreated": "已创建",
"inviteRemainingUses": "剩余使用次数",
"inviteNoInvites": "无",
"inviteExpiresInTime": "在 {n} 到期",
"notifyEvent": "通知:",
"notifyInviteExpiry": "在到期时",
"notifyUserCreation": "在创建用户时",
"sendPIN": "要求用户将下面的 PIN 发送给机器人。",
"searchDiscordUser": "开始输入 Discord 用户名以查找用户。",
"findDiscordUser": "查找 Discord 用户",
"linkMatrixDescription": "输入要用作机器人的用户的用户名和密码。一旦提交,应用程序将重新启动。",
"matrixHomeServer": "主服务器地址",
"saveAsTemplate": "保存为模板",
"deleteTemplate": "删除模板",
"templateEnterName": "输入名称以保存此模板。"
},
"notifications": {
"changedEmailAddress": "更改了 {n} 的电子邮件地址。",
"userCreated": "用户 {n} 已创建。",
"createProfile": "创建了配置文件{n}。",
"saveSettings": "设置已保存",
"saveEmail": "电子邮件已保存。",
"sentAnnouncement": "公告已发出。",
"savedAnnouncement": "公告已保存。",
"setOmbiDefaults": "存储的ombi默认值。",
"updateApplied": "已应用更新,请重新启动。",
"updateAppliedRefresh": "已应用更新,请刷新。",
"telegramVerified": "Telegram账户已验证。",
"accountConnected": "帐户已连接。",
"errorConnection": "无法连接到 jfa-go。",
"error401Unauthorized": "无授权。尝试刷新页面。",
"errorSettingsAppliedNoHomescreenLayout": "已应用设置,但应用主屏幕布局可能失败。",
"errorHomescreenAppliedNoSettings": "已应用主屏幕布局,但应用设置可能失败。",
"errorSettingsFailed": "应用失败。",
"errorLoginBlank": "用户名/密码留空。",
"errorUnknown": "未知错误。",
"errorSaveEmail": "电子邮箱保存失败。",
"errorBlankFields": "字段留空",
"errorDeleteProfile": "删除配置文件{n}失败",
"errorLoadProfiles": "加载配置文件失败。",
"errorCreateProfile": "创建配置文件{n}失败",
"errorSetDefaultProfile": "设置默认配置文件失败。",
"errorLoadUsers": "加载用户列表失败。",
"errorSaveSettings": "无法保存设置。",
"errorLoadSettings": "加载配置列表失败。",
"errorSetOmbiDefaults": "存储Ombi默认值失败。",
"errorLoadOmbiUsers": "加载ombi用户列表失败。",
"errorChangedEmailAddress": "无法更改 {n} 的电子邮件地址。",
"errorFailureCheckLogs": "失败(检查控制台/日志)",
"errorPartialFailureCheckLogs": "部分失败(检查控制台/日志)",
"errorUserCreated": "创建用户{n}失败。",
"errorSendWelcomeEmail": "发送欢迎消息失败(检查控制台/日志)",
"errorApplyUpdate": "无法应用更新,请手动尝试。",
"errorCheckUpdate": "检查更新失败。",
"updateAvailable": "有新更新可用,请检查设置。",
"noUpdatesAvailable": "没有可用的更新。"
},
"quantityStrings": {
"modifySettingsFor": {
"singular": "修改{n}用户的设置",
"plural": "修改{n}用户列表的设置"
},
"deleteNUsers": {
"singular": "删除 {n} 个用户",
"plural": "删除 {n} 个用户"
},
"disableUsers": {
"singular": "禁用 {n} 个用户",
"plural": "禁用 {n} 个用户"
},
"reEnableUsers": {
"singular": "重新启用 {n} 个用户",
"plural": "重新启用 {n} 个用户"
},
"addUser": {
"singular": "添加用户",
"plural": "添加用户"
},
"deleteUser": {
"singular": "删除用户",
"plural": "删除用户"
},
"deletedUser": {
"singular": "删除了 {n} 个用户。",
"plural": "删除了 {n} 个用户。"
},
"disabledUser": {
"singular": "禁用 了{n} 个用户。",
"plural": "禁用 了{n} 个用户。"
},
"enabledUser": {
"singular": "启用了{n} 个用户。",
"plural": "启用了{n} 个用户。"
},
"announceTo": {
"singular": "通知 {n} 位用户",
"plural": "通知 {n} 位用户"
},
"appliedSettings": {
"singular": "将设置应用到 {n} 个用户。",
"plural": "将设置应用到 {n} 个用户。"
},
"extendExpiry": {
"singular": "延长 {n} 个用户的有效期",
"plural": "延长 {n} 个用户的有效期"
},
"extendedExpiry": {
"singular": "延长了 {n} 个用户的有效期。",
"plural": "延长了 {n} 个用户的有效期。"
}
}
}

26
lang/common/da-dk.json Normal file
View File

@@ -0,0 +1,26 @@
{
"meta": {
"name": "Dansk"
},
"strings": {
"username": "Brugernavn",
"password": "Adgangskode",
"emailAddress": "E-mail Adresse",
"name": "Navn",
"submit": "Indsend",
"send": "Send",
"success": "Succes",
"error": "Fejl",
"copy": "Kopiér",
"copied": "Kopiret",
"time24h": "24 timers tid",
"time12h": "12 timers tid",
"linkTelegram": "Link Telegram",
"contactEmail": "Kontakt gennem E-mail",
"contactTelegram": "Kontakt gennem Telegram",
"linkDiscord": "Link Discord",
"linkMatrix": "Link Matrix",
"contactDiscord": "Kontakt gennem Discord",
"theme": "Tema"
}
}

View File

@@ -14,6 +14,13 @@
"theme": "Thema",
"time24h": "24h-Format",
"time12h": "12h-Format",
"copied": "Kopiert"
"copied": "Kopiert",
"linkTelegram": "Link Telegram",
"contactEmail": "Kontakt über E-Mail",
"contactTelegram": "Kontakt über Telegram",
"linkDiscord": "Link Discord",
"linkMatrix": "Link Matrix",
"send": "Senden",
"contactDiscord": "Kontakt über Discord"
}
}

View File

@@ -8,6 +8,7 @@
"emailAddress": "Email Address",
"name": "Name",
"submit": "Submit",
"send": "Send",
"success": "Success",
"error": "Error",
"copy": "Copy",
@@ -17,6 +18,9 @@
"linkTelegram": "Link Telegram",
"contactEmail": "Contact through Email",
"contactTelegram": "Contact through Telegram",
"linkDiscord": "Link Discord",
"linkMatrix": "Link Matrix",
"contactDiscord": "Contact through Discord",
"theme": "Theme"
}
}

View File

@@ -13,7 +13,11 @@
"copy": "Copiar",
"copied": "Copiado",
"time24h": "24 horas",
"time12h": "24 horas",
"theme": "Tema"
"time12h": "12 horas",
"theme": "Tema",
"send": "Enviar",
"contactDiscord": "Contacta a través de Discord",
"contactEmail": "Contacta a través de email",
"contactTelegram": "Contacta a través de Telegram"
}
}

26
lang/common/fa-ir.json Normal file
View File

@@ -0,0 +1,26 @@
{
"meta": {
"name": "انگلیسی"
},
"strings": {
"username": "نام کاربری",
"password": "کلمه عبور",
"emailAddress": "پست الکترونیک",
"name": "نام",
"submit": "تایید",
"send": "ارسال",
"success": "موفقیت",
"error": "خطا",
"copy": "کپی",
"copied": "کپی شد",
"time24h": "ساعت 24 ساعت",
"time12h": "ساعت 12 ساعت",
"linkTelegram": "لینک تلگرام",
"contactEmail": "تماس از طریق ایمیل",
"contactTelegram": "تماس از طریق تلگرام",
"linkDiscord": "پیوند دیسکورد",
"linkMatrix": "پیوند ماتریکس",
"contactDiscord": "از طریق دیسکورد تماس بگیرید",
"theme": "موضوع"
}
}

View File

@@ -14,6 +14,14 @@
"copy": "Copier",
"time24h": "Temps 24h",
"time12h": "Temps 12h",
"theme": "Thème"
"theme": "Thème",
"copied": "Copié",
"linkTelegram": "Lien Telegram",
"contactEmail": "Contact par e-mail",
"contactTelegram": "Contact par Telegram",
"linkDiscord": "Lier Discord",
"linkMatrix": "Lier Matrix",
"send": "Envoyer",
"contactDiscord": "Contacter par Discord"
}
}

View File

@@ -8,12 +8,19 @@
"password": "Wachtwoord",
"emailAddress": "E-mailadres",
"submit": "Verstuur",
"success": "Success",
"success": "Succes",
"error": "Fout",
"copy": "Kopiëer",
"theme": "Thema",
"time24h": "24u-formaat",
"time12h": "12u-formaat",
"copied": "Gekopieerd"
"copied": "Gekopieerd",
"linkTelegram": "Koppel Telegram",
"contactEmail": "Stuur e-mailbericht",
"contactTelegram": "Stuur Telegram-bericht",
"send": "Verstuur",
"linkDiscord": "Koppel Discord",
"linkMatrix": "Koppel Matrix",
"contactDiscord": "Stuur Discord bericht"
}
}

View File

@@ -14,6 +14,13 @@
"theme": "Tema",
"time24h": "Horário 24h",
"time12h": "Horário 12h",
"copied": "Copiado"
"copied": "Copiado",
"linkTelegram": "Link do Telegram",
"contactEmail": "Contato por Email",
"contactTelegram": "Contato pelo Telegram",
"send": "Enviar",
"linkDiscord": "Link do Discord",
"linkMatrix": "Link do Matrix",
"contactDiscord": "Contato através do Discord"
}
}

26
lang/common/zh-hans.json Normal file
View File

@@ -0,0 +1,26 @@
{
"meta": {
"name": "简体中文(CN)"
},
"strings": {
"username": "用户名",
"password": "密码",
"emailAddress": "电子邮箱",
"name": "名称",
"submit": "提交",
"send": "发送",
"success": "成功",
"error": "错误",
"copy": "复制",
"copied": "已复制",
"time24h": "24小时制",
"time12h": "12小时制",
"linkTelegram": "关联Telegram",
"contactEmail": "通过邮件联系",
"contactTelegram": "通过Telegram联系",
"linkDiscord": "关联Discord",
"linkMatrix": "关联Matrix",
"contactDiscord": "通过Discord联系",
"theme": "主题"
}
}

77
lang/email/da-dk.json Normal file
View File

@@ -0,0 +1,77 @@
{
"meta": {
"name": "Dansk"
},
"strings": {
"ifItWasNotYou": "Ignorer venligst hvis dette ikke var dig.",
"helloUser": "Hej {username},",
"reason": "Grund"
},
"userCreated": {
"name": "Bruger oprettet",
"title": "Meddelelse: Bruger oprettet",
"aUserWasCreated": "En bruger blev oprettet med koden {code}.",
"time": "Tid",
"notificationNotice": "Meddelelse: Notifikations e-mails kan blive ændret på admin-siden."
},
"inviteExpiry": {
"name": "Invitationens udløb",
"title": "Meddelelse: Invitation udløbet",
"inviteExpired": "Invitation udløbet.",
"expiredAt": "Koden {code} udløber om {time}.",
"notificationNotice": "Meddelelse: Notifikations e-mails kan blive ændret på admin-siden."
},
"passwordReset": {
"name": "Nulstil Adgangskode",
"title": "Nulstilling af adgangskode anmodet - Jellyfin",
"someoneHasRequestedReset": "Nogen har for nylig anmodet om nulstilling af din adgangskode på Jellyfin.",
"ifItWasYou": "Hvis dette var dig, så indtast venligst pinkoden nedenunder ind i prompten.",
"ifItWasYouLink": "Hvis dette var dig, så tryk på linket nedenunder.",
"codeExpiry": "Koden udløber den {date}, klokken {time} UTC, hvilket er om {expiresInMinutes}.",
"pin": "PINKODE"
},
"userDeleted": {
"name": "Sletning af bruger",
"title": "Din konto blev slettet - Jellyfin",
"yourAccountWasDeleted": "Din Jellyfin konto blev slettet."
},
"userDisabled": {
"name": "Bruger deaktiveret",
"title": "Din konto er blevet deaktiveret - Jellyfin",
"yourAccountWasDisabled": "Din konto blev deaktiveret."
},
"userEnabled": {
"name": "Bruger aktiveret",
"title": "Din konto er blevet genaktiveret - Jellyfin",
"yourAccountWasEnabled": "Din konto blev genaktiveret."
},
"inviteEmail": {
"name": "Invitations e-mail",
"title": "Invitation - Jellyfin",
"hello": "Hej",
"youHaveBeenInvited": "Du er blevet inviteret til Jellyfin.",
"toJoin": "Tilmeld dig med linket nedenfor.",
"inviteExpiry": "Invitationen vil udløbe den {date} kl. {time}, hvilket er om {expiresInMinutes}, så skynd dig.",
"linkButton": "Opsæt din konto"
},
"welcomeEmail": {
"name": "Velkommen",
"title": "Velkommen til Jellyfin",
"welcome": "Velkommen til Jellyfin!",
"youCanLoginWith": "Du kan logge ind med nedenstående oplysninger",
"yourAccountWillExpire": "Din konto udløber den {date}.",
"jellyfinURL": "URL"
},
"emailConfirmation": {
"name": "Bekræftelses e-mail",
"title": "Bekræft din e-mail - Jellyfin",
"clickBelow": "Klik på linket nedenunder for at bekræfte din e-mail adresse og start med at bruge Jellyfin.",
"confirmEmail": "Bekræft E-mail"
},
"userExpired": {
"name": "Brugerens udløb",
"title": "Din konto er udløbet - Jellyfin",
"yourAccountHasExpired": "Din konto er udløbet.",
"contactTheAdmin": "Kontakt administratoren for mere information."
}
}

View File

@@ -3,7 +3,7 @@
"name": "Deutsch (DE)"
},
"strings": {
"ifItWasNotYou": "Wenn du das nicht warst, ignoriere bitte diese E-Mail.",
"ifItWasNotYou": "Wenn du das nicht warst, ignoriere bitte dies.",
"reason": "Grund",
"helloUser": "Hallo {username},"
},
@@ -27,7 +27,8 @@
"ifItWasYou": "Wenn du das warst, gib die PIN unten in die Eingabeaufforderung ein.",
"codeExpiry": "Der Code wird am {date}, um {time} UTC ablaufen, was in {expiresInMinutes} ist.",
"pin": "PIN",
"name": "Passwortzurücksetzung"
"name": "Passwortzurücksetzung",
"ifItWasYouLink": "Wenn du das warst, klick auf den Link unten."
},
"userDeleted": {
"title": "Dein Konto wurde gelöscht - Jellyfin",
@@ -48,7 +49,8 @@
"welcome": "Willkommen bei Jellyfin!",
"youCanLoginWith": "Du kannst dich mit den mit den untenstehenden Zugangsdaten anmelden",
"jellyfinURL": "URL",
"name": "Willkommens-E-Mail"
"name": "Willkommen",
"yourAccountWillExpire": "Dein Konto läuft am {date} ab."
},
"emailConfirmation": {
"title": "Bestätige deine E-Mail - Jellyfin",
@@ -61,5 +63,15 @@
"title": "Dein Konto ist abgelaufen - Jellyfin",
"yourAccountHasExpired": "Dein Konto ist abgelaufen.",
"contactTheAdmin": "Kontaktiere den Administrator für weitere Informationen."
},
"userDisabled": {
"name": "Benutzer deaktiviert",
"title": "Dein Konto wurde deaktiviert - Jellyfin",
"yourAccountWasDisabled": "Dein Konto wurde deaktiviert."
},
"userEnabled": {
"name": "Benutzer aktiviert",
"title": "Dein Konto wurde wieder freigeschaltet - Jellyfin",
"yourAccountWasEnabled": "Dein Konto wurde wieder aktiviert."
}
}

View File

@@ -4,7 +4,7 @@
"author": "https://github.com/Cornichon420"
},
"strings": {
"ifItWasNotYou": "Si ce n'était pas toi, tu peux ignorer ce mail.",
"ifItWasNotYou": "Si ce n'était pas toi, tu peux ignorer ceci.",
"reason": "Motif",
"helloUser": "Salut {username},"
},
@@ -50,7 +50,7 @@
"title": "Bienvenue sur Jellyfin",
"welcome": "Bienvenue sur Jellyfin !",
"jellyfinURL": "URL",
"name": "Courriel de bienvenue",
"name": "Bienvenue",
"yourAccountWillExpire": "Ton compte expirera le {date}."
},
"emailConfirmation": {

View File

@@ -3,7 +3,7 @@
"name": "Nederlands (NL)"
},
"strings": {
"ifItWasNotYou": "Als jij dit niet was, negeer dan alsjeblieft deze email.",
"ifItWasNotYou": "Als jij dit niet was, negeer dit dan alsjeblieft.",
"reason": "Reden",
"helloUser": "Hoi {username},"
},
@@ -49,7 +49,7 @@
"welcome": "Welkom bij Jellyfin!",
"youCanLoginWith": "Je kunt inloggen met onderstaande gegevens",
"jellyfinURL": "URL",
"name": "Welkomste-mail",
"name": "Welkom",
"yourAccountWillExpire": "Je account verloopt op {date}."
},
"emailConfirmation": {

View File

@@ -3,7 +3,7 @@
"name": "Português (BR)"
},
"strings": {
"ifItWasNotYou": "Se não foi você, ignore este e-mail.",
"ifItWasNotYou": "Se não foi você, ignore.",
"reason": "Razão",
"helloUser": "Ola {username},"
},
@@ -49,7 +49,7 @@
"welcome": "Bem vindo ao Jellyfin!",
"youCanLoginWith": "Abaixo está os detalhes para fazer o login",
"jellyfinURL": "URL",
"name": "Email de Boas vindas",
"name": "Bem-vindo",
"yourAccountWillExpire": "Sua conta irá expirar em {date}."
},
"emailConfirmation": {

77
lang/email/zh-hans.json Normal file
View File

@@ -0,0 +1,77 @@
{
"meta": {
"name": "简体中文(CN)"
},
"strings": {
"ifItWasNotYou": "如果这不是您,请忽略本邮件。",
"helloUser": "你好{username}",
"reason": "原因"
},
"userCreated": {
"name": "创建用户",
"title": "注意:用户已创建",
"aUserWasCreated": "使用代码{code}创建了一个用户。",
"time": "时间",
"notificationNotice": "注意:通知邮件可以在管理仪表板上进行切换。"
},
"inviteExpiry": {
"name": "邀请到期",
"title": "注意:邀请已过期",
"inviteExpired": "邀请已过期。",
"expiredAt": "代码 {code} 已于 {time} 过期。",
"notificationNotice": "注意:通知邮件可以在管理仪表板上进行切换。"
},
"passwordReset": {
"name": "重设密码",
"title": "要求重设密码 - Jellyfin",
"someoneHasRequestedReset": "最近在Jellyfin上有一个重设密码的请求。",
"ifItWasYou": "如果这是您请在提示中输入下面的PIN。",
"ifItWasYouLink": "如果这是您,请单击下面的链接。",
"codeExpiry": "该代码将在UTC时间{日期} {时间}到期,也就是{expires In Minutes}。",
"pin": "PIN"
},
"userDeleted": {
"name": "删除用户",
"title": "您的账户已被删除 - Jellyfin",
"yourAccountWasDeleted": "您的 Jellyfin 帐户已被删除。"
},
"userDisabled": {
"name": "用户禁用",
"title": "您的帐户已被禁用 - Jellyfin",
"yourAccountWasDisabled": "您的帐户已被禁用。"
},
"userEnabled": {
"name": "用户已启用",
"title": "您的帐户已重新启用 - Jellyfin",
"yourAccountWasEnabled": "您的帐户已重新启用。"
},
"inviteEmail": {
"name": "邀请邮件",
"title": "邀请 - Jellyfin",
"hello": "您好",
"youHaveBeenInvited": "您已受邀注册 Jellyfin。",
"toJoin": "若要加入,请点击以下链接。",
"inviteExpiry": "此邀请将于 {date} 的 {time} 到期,即 {expires In Minutes},因此请迅速行动。",
"linkButton": "设置您的帐户"
},
"welcomeEmail": {
"name": "欢迎",
"title": "欢迎使用Jellyfin",
"welcome": "欢迎使用Jellyfin",
"youCanLoginWith": "您可以使用以下信息登录",
"yourAccountWillExpire": "您的帐户将于 {date}到期。",
"jellyfinURL": "链接"
},
"emailConfirmation": {
"name": "确认邮件",
"title": "确认您的电子邮件 - Jellyfin",
"clickBelow": "单击下面的链接以确认您的电子邮件地址并开始使用 Jellyfin。",
"confirmEmail": "确认电子邮件"
},
"userExpired": {
"name": "用户到期",
"title": "您的帐户已过期 - Jellyfin",
"yourAccountHasExpired": "您的帐户已过期。",
"contactTheAdmin": "请联系管理员了解更多信息。"
}
}

57
lang/form/da-dk.json Normal file
View File

@@ -0,0 +1,57 @@
{
"meta": {
"name": "Dansk"
},
"strings": {
"pageTitle": "Opret Jellyfin Konto",
"createAccountHeader": "Opret Konto",
"accountDetails": "Detaljer",
"emailAddress": "E-mail",
"username": "Brugernavn",
"password": "Adgangskode",
"reEnterPassword": "Genindtast Adgangskode",
"reEnterPasswordInvalid": "Adgangskoderne er ikke ens.",
"createAccountButton": "Opret Konto",
"passwordRequirementsHeader": "Adgangskodekrav",
"successHeader": "Succes!",
"successContinueButton": "Fortsæt",
"confirmationRequired": "E-mail bekræftelse er påkrævet",
"confirmationRequiredMessage": "Tjek venligst din e-mail indbakke for at verificere din adresse.",
"yourAccountIsValidUntil": "Din konto er gyldig indtil {date}.",
"sendPIN": "Send nedenstående pinkode til botten, og kom derefter tilbage her for at linke din konto.",
"sendPINDiscord": "Skriv {command} i {server_channel} på Discord, og send PIN-koden nedenfor via. DM til boten.",
"matrixEnterUser": "Skriv dit Bruger ID, tryk Indsend, og en PIN-kode vil blive sendt til dig. Skriv den her efter for at fortsætte."
},
"notifications": {
"errorUserExists": "Brugeren eksistere allerede.",
"errorInvalidCode": "Ugyldig invitations kode.",
"errorTelegramVerification": "Telegram verifikation påkrævet.",
"errorDiscordVerification": "Discord verifikation påkrævet.",
"errorMatrixVerification": "Matrix verifikation påkrævet.",
"errorInvalidPIN": "PIN-koden er ugyldig.",
"errorUnknown": "Ukendt fejl.",
"verified": "konto verificeret."
},
"validationStrings": {
"length": {
"singular": "Skal mindst have {n} tegn",
"plural": "Skal mindst have {n} tegn"
},
"uppercase": {
"singular": "Skal mindst have {n} store bogstaver",
"plural": "Skal mindst have {n} store bogstaver"
},
"lowercase": {
"singular": "Skal mindst have {n} små bogstaver",
"plural": "Skal mindst have {n} små bogstaver"
},
"number": {
"singular": "Skal mindst have {n} tal",
"plural": "Skal mindst have {n} tal"
},
"special": {
"singular": "Skal mindst have {n} specialtegn",
"plural": "Skal mindst have {n} specialtegn"
}
}
}

View File

@@ -17,7 +17,10 @@
"successContinueButton": "Weiter",
"confirmationRequired": "E-Mail-Bestätigung erforderlich",
"confirmationRequiredMessage": "Bitte überprüfe dein Posteingang und bestätige deine E-Mail-Adresse.",
"yourAccountIsValidUntil": "Dein Konto wird bis zum {date} gültig sein."
"yourAccountIsValidUntil": "Dein Konto wird bis zum {date} gültig sein.",
"sendPIN": "Sende die untenstehende PIN an den Bot und komm dann hierher zurück, um dein Konto zu verbinden.",
"sendPINDiscord": "Gib auf Discord {command} in {server_channel} ein und sende die untenstehende PIN als DM an den Bot.",
"matrixEnterUser": "Gib deine Benutzer-ID ein und drücke auf Absenden. Anschließend erhälst du ein PIN, die hier eingegeben wird um fortzufahren."
},
"validationStrings": {
"length": {
@@ -43,6 +46,13 @@
},
"notifications": {
"errorUserExists": "Benutzer existiert bereits.",
"errorInvalidCode": "Ungültiger Invite-Code."
"errorInvalidCode": "Ungültiger Invite-Code.",
"telegramVerified": "Telegram-Konto verifiziert.",
"errorTelegramVerification": "Verifizierung von Telegram erforderlich.",
"errorInvalidPIN": "PIN ist ungültig.",
"errorDiscordVerification": "Discord-Verifizierung erforderlich.",
"errorMatrixVerification": "Matrix-Verifizierung erforderlich.",
"errorUnknown": "Unbekannter Fehler.",
"verified": "Konto verifiziert."
}
}

View File

@@ -18,14 +18,19 @@
"confirmationRequired": "Email confirmation required",
"confirmationRequiredMessage": "Please check your email inbox to verify your address.",
"yourAccountIsValidUntil": "Your account will be valid until {date}.",
"sendPIN": "Send the PIN below to the bot, then come back here to link your account."
"sendPIN": "Send the PIN below to the bot, then come back here to link your account.",
"sendPINDiscord": "Type {command} in {server_channel} on Discord, then send the PIN below via DM to the bot.",
"matrixEnterUser": "Enter your User ID, press submit, and a PIN will be sent to you. Enter it here to continue."
},
"notifications": {
"errorUserExists": "User already exists.",
"errorInvalidCode": "Invalid invite code.",
"errorTelegramVerification": "Telegram verification required.",
"errorInvalidPIN": "Telegram PIN is invalid.",
"telegramVerified": "Telegram account verified."
"errorDiscordVerification": "Discord verification required.",
"errorMatrixVerification": "Matrix verification required.",
"errorInvalidPIN": "PIN is invalid.",
"errorUnknown": "Unknown error.",
"verified": "Account verified."
},
"validationStrings": {
"length": {

57
lang/form/fa-ir.json Normal file
View File

@@ -0,0 +1,57 @@
{
"meta": {
"name": "انگلیسی"
},
"strings": {
"pageTitle": "ساختن حساب کاربری",
"createAccountHeader": "ساخت اکانت",
"accountDetails": "جزئیات",
"emailAddress": "پست الکترونیک",
"username": "نام کاربری",
"password": "کلمه عبور",
"reEnterPassword": "کلمه عبور را دوباره وارد کنید",
"reEnterPasswordInvalid": "کلمه های عبور یکسان نیستند.",
"createAccountButton": "ساخت حساب کاربری",
"passwordRequirementsHeader": "کلمه عبور لازم است",
"successHeader": "موفقیت!",
"successContinueButton": "ادامه دادن",
"confirmationRequired": "تایید ایمیل لازم است",
"confirmationRequiredMessage": "لطفاً برای تأیید آدرس خود ، صندوق پستی ایمیل خود را بررسی کنید.",
"yourAccountIsValidUntil": "حساب شما تا {date} معتبر خواهد بود.",
"sendPIN": "پین زیر را به ربات ارسال کنید ، سپس برای پیوند حساب خود به اینجا برگردید.",
"sendPINDiscord": "در Discord {command} را در {server_channel} تایپ کنید ، سپس پین زیر را از طریق DM به ربات ارسال کنید.",
"matrixEnterUser": "شناسه کاربری خود را وارد کرده ، submit را فشار دهید و یک پین برای شما ارسال می شود. برای ادامه آن را اینجا وارد کنید."
},
"notifications": {
"errorUserExists": "کاربر قبلاً وجود دارد.",
"errorInvalidCode": "کد دعوت نامعتبر است.",
"errorTelegramVerification": "تایید تلگرام الزامی است.",
"errorDiscordVerification": "تأیید دیسکورد مورد نیاز است.",
"errorMatrixVerification": "تأیید ماتریکس مورد نیاز است.",
"errorInvalidPIN": "پین نامعتبر است.",
"errorUnknown": "خطای ناشناخته.",
"verified": "حساب تأیید شد."
},
"validationStrings": {
"length": {
"singular": "باید حداقل {n} نویسه داشته باشد",
"plural": "باید حداقل {n} نویسه داشته باشد"
},
"uppercase": {
"singular": "باید حداقل {n} نویسه بزرگ داشته باشد",
"plural": "باید حداقل {n} نویسه بزرگ داشته باشد"
},
"lowercase": {
"singular": "باید حداقل {n} نویسه کوچک داشته باشد",
"plural": "باید حداقل {n} نویسه کوچک داشته باشد"
},
"number": {
"singular": "باید حداقل {n} شماره داشته باشد",
"plural": "باید حداقل {n} شماره داشته باشد"
},
"special": {
"singular": "باید حداقل {n} نویسه خاص داشته باشد",
"plural": "باید حداقل {n} نویسه خاص داشته باشد"
}
}
}

View File

@@ -14,10 +14,14 @@
"reEnterPasswordInvalid": "Les mots de passe ne correspondent pas.",
"createAccountButton": "Créer le compte",
"passwordRequirementsHeader": "Mot de passe requis",
"successHeader": "Succes!",
"successHeader": "Succès!",
"successContinueButton": "Continuer",
"confirmationRequired": "Confirmation de l'adresse e-mail requise",
"confirmationRequiredMessage": "Veuillez vérifier votre boite de réception pour confirmer votre adresse e-mail."
"confirmationRequiredMessage": "Veuillez vérifier votre boite de réception pour confirmer votre adresse e-mail.",
"yourAccountIsValidUntil": "Votre compte sera valide jusqu'au {date}.",
"sendPIN": "Envoyez le code PIN ci-dessous au bot, puis revenez ici pour lier votre compte.",
"sendPINDiscord": "Écrivez {command} dans le salon {server_channel} sur Discord puis envoyez le PIN en message privé au bot.",
"matrixEnterUser": "Entrez votre nom d'utilisateur, appuyez sur soumettre et un code PIN vous sera envoyé. Cliquez ici pour continuez."
},
"validationStrings": {
"length": {
@@ -43,6 +47,13 @@
},
"notifications": {
"errorUserExists": "Utilisateur déjà existant.",
"errorInvalidCode": "Code dinvitation non valide."
"errorInvalidCode": "Code dinvitation non valide.",
"errorTelegramVerification": "Vérification Telegram requise.",
"errorInvalidPIN": "PIN Telegram invalide.",
"telegramVerified": "Compte Telegram vérifié.",
"errorDiscordVerification": "Vérification Discord requise.",
"errorMatrixVerification": "Vérification Matrix requise.",
"errorUnknown": "Erreur inconnue.",
"verified": "Compte vérifié."
}
}

View File

@@ -17,7 +17,10 @@
"successContinueButton": "Doorgaan",
"confirmationRequired": "Bevestiging van e-mailadres verplicht",
"confirmationRequiredMessage": "Controleer je e-mail inbox om je adres te bevestigen.",
"yourAccountIsValidUntil": "Je account zal geldig zijn tot {date}."
"yourAccountIsValidUntil": "Je account zal geldig zijn tot {date}.",
"sendPIN": "Stuur onderstaande pincode naar de bot, en kom daarna hier terug om je account te koppelen.",
"matrixEnterUser": "Voer je gebruikers ID in, druk op versturen, en er wordt je een pincode toegestuurd. Vul die hier in om door te gaan.",
"sendPINDiscord": "Typ {command} in {server_channel} op Discord, stuur daarna onderstaande pincode via DM naar de bot."
},
"validationStrings": {
"length": {
@@ -43,6 +46,13 @@
},
"notifications": {
"errorUserExists": "Gebruiker bestaat al.",
"errorInvalidCode": "Ongeldige uitnodigingscode."
"errorInvalidCode": "Ongeldige uitnodigingscode.",
"telegramVerified": "Telegram-account goedgekeurd.",
"errorTelegramVerification": "Telegram-verificatie nodig.",
"errorInvalidPIN": "Pincode is ongeldig.",
"errorDiscordVerification": "Discord-verificatie vereist.",
"errorUnknown": "Onbekende fout.",
"errorMatrixVerification": "Matrix-verificatie vereist.",
"verified": "Account geverifieerd."
}
}

View File

@@ -13,15 +13,25 @@
"reEnterPasswordInvalid": "Senha não Coincidem. Tentar novamente.",
"createAccountButton": "Criar Conta",
"passwordRequirementsHeader": "Requisitos da Senha",
"successHeader": "Sucesso!",
"successHeader": "Concluído!",
"successContinueButton": "Continuar",
"confirmationRequired": "Necessária confirmação de e-mail",
"confirmationRequired": "Confirmação por e-mail",
"confirmationRequiredMessage": "Verifique sua caixa de email para finalizar o cadastro.",
"yourAccountIsValidUntil": "Sua conta é válida até {date}."
"yourAccountIsValidUntil": "Sua conta é válida até {date}.",
"sendPIN": "Envie o PIN abaixo para o bot e volte aqui para vincular sua conta.",
"sendPINDiscord": "Digite {command} em {server_channel} no Discord e envie o PIN abaixo via DM para o bot.",
"matrixEnterUser": "Digite sua ID de usuário, pressione enviar e um PIN será enviado. E digite aqui para continuar."
},
"notifications": {
"errorUserExists": "Esse usuário já existe.",
"errorInvalidCode": "Código do convite invalido."
"errorInvalidCode": "Código do convite invalido.",
"telegramVerified": "Conta do Telegram verificada.",
"errorInvalidPIN": "PIN inválido.",
"errorTelegramVerification": "Requer a verificação do telegram.",
"errorDiscordVerification": "Necessária verificação pelo Discord.",
"errorMatrixVerification": "Necessária verificação Matrix.",
"errorUnknown": "Erro desconhecido.",
"verified": "Conta verificada."
},
"validationStrings": {
"length": {

View File

@@ -17,11 +17,15 @@
"successContinueButton": "Fortsätt",
"confirmationRequired": "E-postbekräftelse krävs",
"confirmationRequiredMessage": "Kontrollera din e-postkorg för att verifiera din adress.",
"yourAccountIsValidUntil": "Ditt konto är giltigt fram tills {date}."
"yourAccountIsValidUntil": "Ditt konto är giltigt fram tills {date}.",
"sendPIN": "Skicka PIN-koden nedan till botten, återvänd sedan till den här sidan för att länka ditt konto."
},
"notifications": {
"errorUserExists": "Användare finns redan.",
"errorInvalidCode": "Ogiltig inbjudningskod."
"errorInvalidCode": "Ogiltig inbjudningskod.",
"errorInvalidPIN": "Telegram-PIN är ogiltig.",
"errorTelegramVerification": "Telegram-verifiering krävs.",
"telegramVerified": "Telegram-konto verifierades."
},
"validationStrings": {
"length": {

57
lang/form/zh-hans.json Normal file
View File

@@ -0,0 +1,57 @@
{
"meta": {
"name": "简体中文(CN)"
},
"strings": {
"pageTitle": "创建Jellyfin账户",
"createAccountHeader": "创建账户",
"accountDetails": "账户详情",
"emailAddress": "电子邮箱",
"username": "用户名",
"password": "密码",
"reEnterPassword": "再次输入密码",
"reEnterPasswordInvalid": "两次输入的密码不相同。",
"createAccountButton": "创建账户",
"passwordRequirementsHeader": "密码格式要求",
"successHeader": "成功!",
"successContinueButton": "继续",
"confirmationRequired": "需要邮件确认",
"confirmationRequiredMessage": "请登录您的邮箱收件箱来验证您的地址。",
"yourAccountIsValidUntil": "您的账户将在 {date} 之前有效。",
"sendPIN": "把PIN码发送给下面的bot然后回到这里来关联您的账户。",
"sendPINDiscord": "在 Discord 上,在 {server_channel} 中输入 {command} 并将下面的 PIN 码作为 DM 发送给机器人。",
"matrixEnterUser": "输入您的用户ID并点击提交将发送给您的PIN码输入到这里并继续。"
},
"notifications": {
"errorUserExists": "用户已经存在。",
"errorInvalidCode": "无效的邀请码",
"errorTelegramVerification": "需要Telegram验证",
"errorDiscordVerification": "需要Discord验证。",
"errorMatrixVerification": "需要Matrix验证。",
"errorInvalidPIN": "无效的PIN码",
"errorUnknown": "未知错误。",
"verified": "账户已验证。"
},
"validationStrings": {
"length": {
"singular": "必须至少包含 {n} 个字符",
"plural": "必须至少包含 {n} 个字符"
},
"uppercase": {
"singular": "必须至少包含 {n} 个大写字母",
"plural": "必须至少包含 {n} 个大写字母"
},
"lowercase": {
"singular": "必须至少包含 {n} 个小写字母",
"plural": "必须至少包含 {n} 个小写字母"
},
"number": {
"singular": "必须至少包含 {n} 个数字",
"plural": "必须至少包含 {n} 个数字"
},
"special": {
"singular": "必须至少包含 {n} 个特殊字符",
"plural": "必须至少包含 {n} 个特殊字符"
}
}
}

15
lang/pwreset/da-dk.json Normal file
View File

@@ -0,0 +1,15 @@
{
"meta": {
"name": "Dansk"
},
"strings": {
"passwordReset": "Nulstil adgangskode",
"reset": "Nulstil",
"resetFailed": "Nulstilling af adgangskode fejlede",
"tryAgain": "Prøv venligst igen.",
"youCanLogin": "Du kan nu logge ind med koden nedenfor som din adgangskode.",
"youCanLoginOmbi": "Du kan nu logge ind på Jellyfin & Ombi med koden nedenfor som din adgangskode.",
"changeYourPassword": "Sørg for at ændre din adgangskode, når du har logget ind.",
"enterYourPassword": "Indtast din nye adgangskode nedenfor."
}
}

13
lang/pwreset/de-de.json Normal file
View File

@@ -0,0 +1,13 @@
{
"meta": {
"name": "Deutsch (DE)"
},
"strings": {
"passwordReset": "Passwort zurücksetzen",
"resetFailed": "Zurücksetzen des Passworts fehlgeschlagen",
"tryAgain": "Bitte versuche es erneut.",
"youCanLogin": "Du kannst dich nun mit dem unten stehenden Code als Passwort anmelden.",
"youCanLoginOmbi": "Du kannst dich jetzt bei Jellyfin und Ombi mit dem unten stehenden Code als Passwort anmelden.",
"changeYourPassword": "Achte darauf, dass du dein Passwort nach der Anmeldung änderst."
}
}

13
lang/pwreset/en-gb.json Normal file
View File

@@ -0,0 +1,13 @@
{
"meta": {
"name": ""
},
"strings": {
"passwordReset": "",
"resetFailed": "",
"tryAgain": "",
"youCanLogin": "",
"youCanLoginOmbi": "",
"changeYourPassword": ""
}
}

View File

@@ -4,10 +4,12 @@
},
"strings": {
"passwordReset": "Password reset",
"reset": "Reset",
"resetFailed": "Password reset failed",
"tryAgain": "Please try again.",
"youCanLogin": "You can now log in with the below code as your password.",
"youCanLoginOmbi": "You can now log in to Jellyfin & Ombi with the below code as your password.",
"changeYourPassword": "Make sure to change your password after you log in."
"changeYourPassword": "Make sure to change your password after you log in.",
"enterYourPassword": "Enter your new password below."
}
}

View File

@@ -7,6 +7,8 @@
"resetFailed": "Error al cambiar contraseña",
"tryAgain": "Por favor intente nuevamente.",
"youCanLogin": "Ahora puedes logearte con el codigo como contraseña.",
"changeYourPassword": "Recuerda cambiar tu contraseña luego de iniciar sesión."
"changeYourPassword": "Recuerda cambiar tu contraseña luego de iniciar sesión.",
"youCanLoginOmbi": "Ahora puede iniciar sesión en Jellyfin & Ombi con el siguiente código como contraseña.",
"reset": "Reiniciar"
}
}

15
lang/pwreset/fa-ir.json Normal file
View File

@@ -0,0 +1,15 @@
{
"meta": {
"name": "انگلیسی"
},
"strings": {
"passwordReset": "تنظیم مجدد رمز عبور",
"reset": "بازنشانی",
"resetFailed": "بازنشانی گذرواژه ناموفق بود",
"tryAgain": "لطفا دوباره تلاش کنید.",
"youCanLogin": "اکنون می توانید با کد زیر به عنوان رمز عبور خود وارد شوید.",
"youCanLoginOmbi": "اکنون می توانید با کد زیر به عنوان رمز عبور وارد شوید.",
"changeYourPassword": "اطمینان حاصل کنید که پس از ورود به سیستم رمز عبور خود را تغییر دهید.",
"enterYourPassword": "رمز عبور جدید خود را در زیر وارد کنید."
}
}

15
lang/pwreset/fr-fr.json Normal file
View File

@@ -0,0 +1,15 @@
{
"meta": {
"name": "Français (FR)"
},
"strings": {
"passwordReset": "Réinitialisation du mot de passe",
"reset": "Réinitialisation",
"resetFailed": "Réinitialisation du mot de passe échouée",
"tryAgain": "Veuillez réessayer.",
"youCanLogin": "Vous pouvez maintenant vous connecter en utilisant ce code comme mot de passe.",
"youCanLoginOmbi": "Vous pouvez maintenant vous connecter à Jellyfin et Ombi en utilisant ce mot de passe.",
"changeYourPassword": "Assurez-vous de changer votre mot de passe après s'être connecté.",
"enterYourPassword": "Entrez votre nouveau mot de passe ici."
}
}

15
lang/pwreset/nl-nl.json Normal file
View File

@@ -0,0 +1,15 @@
{
"meta": {
"name": "Nederlands (NL)"
},
"strings": {
"passwordReset": "Wachtwoordreset",
"reset": "Reset",
"resetFailed": "Wachtwoordreset mislukt",
"tryAgain": "Probeer het alsjeblieft nog een keer.",
"youCanLogin": "Je kunt nu inloggen met onderstaande code als wachtwoord.",
"youCanLoginOmbi": "Je kunt nu inloggen bij Jellyfin & Ombi met onderstaande code als wachtwoord.",
"changeYourPassword": "Denk eraan je wachtwoord te wijzigen nadat je bent ingelogd.",
"enterYourPassword": "Voer hieronder je nieuwe wachtwoord in."
}
}

13
lang/pwreset/pt-br.json Normal file
View File

@@ -0,0 +1,13 @@
{
"meta": {
"name": "Português (BR)"
},
"strings": {
"passwordReset": "Redefinir senha",
"resetFailed": "Falha ao redefinir a senha",
"tryAgain": "Tente novamente.",
"youCanLogin": "Agora você pode fazer login com o código abaixo como senha.",
"youCanLoginOmbi": "Agora você pode fazer login no Jellyfin & Ombi com o código abaixo como senha.",
"changeYourPassword": "Certifique-se de alterar sua senha depois de fazer o login."
}
}

15
lang/pwreset/zh-hans.json Normal file
View File

@@ -0,0 +1,15 @@
{
"meta": {
"name": "简体中文(CN)"
},
"strings": {
"passwordReset": "重设密码",
"reset": "重设",
"resetFailed": "重设密码失败",
"tryAgain": "请重试。",
"youCanLogin": "您现在可以使用下面的代码作为您的密码进行登录。",
"youCanLoginOmbi": "您现在可以使用下面的代码作为您的密码登录Jellyfin和Ombi。",
"changeYourPassword": "确保在登录状态下修改您的密码。",
"enterYourPassword": "在下面输入您的新密码。"
}
}

147
lang/setup/da-dk.json Normal file
View File

@@ -0,0 +1,147 @@
{
"meta": {
"name": "Dansk"
},
"strings": {
"pageTitle": "Opsæt - jfa-go",
"next": "Næste",
"back": "Tilbage",
"optional": "Valgfri",
"serverType": "Servertype",
"disabled": "Deaktiveret",
"enabled": "Aktiveret",
"port": "Port",
"message": "Meddelelse",
"serverAddress": "Serveradresse",
"emailSubject": "E-mail emne",
"URL": "URL",
"apiKey": "API Nøgle",
"errorNotAdmin": "Brugeren har ikke tilladelse til at administrere server.",
"errorInvalidUserPass": "Ugyldigt brugernavn/adgangskode.",
"errorUserDisabled": "Bruger kan være deaktiveret.",
"error404": "404, tjek den interne URL."
},
"startPage": {
"welcome": "Velkommen!",
"pressStart": "Du bliver nødt til at gøre et par ting for at konfigurere jfa-go. Tryk på start for at fortsætte.",
"httpsNotice": "Sørg for, at du tilgår denne side via HTTPS eller på et privat netværk.",
"start": "Start"
},
"endPage": {
"finished": "Færdig!",
"restartMessage": "Du kan konfigurere Discord/Telegram/Matrix bots, tilpasse dine meddelelser og mere i Indstillinger. Klik herunder for at genstarte, og opdater siden.",
"refreshPage": "Opdater"
},
"language": {
"title": "Sprog",
"description": "Fællesskabsoversættelser er tilgængelige for de fleste dele af jfa-go. Du kan vælge standardsprogene nedenfor, men brugere kan stadig ændre det, hvis de ønsker det. Hvis du vil hjælpe med at oversætte, skal du tilmelde dig til {n} for at begynde at bidrage!",
"defaultAdminLang": "Standard administrator sprog",
"defaultFormLang": "Standard kontooprettelses sprog",
"defaultEmailLang": "Standard e-mail sprog"
},
"general": {
"title": "Generel",
"listenAddress": "Listen Adresse",
"urlBase": "URL-base",
"urlBaseNotice": "Kun nødvendigt hvis du bruger en omvendt proxy på et underdomæne (f.eks. 'Jellyf.in/accounts').",
"lightTheme": "Lys",
"darkTheme": "Mørk",
"useHTTPS": "Brug HTTPS",
"httpsPort": "HTTPS Port",
"useHTTPSNotice": "Anbefales kun hvis du ikke bruger en omvendt proxy.",
"pathToCertificate": "Sti til certifikat",
"pathToKeyFile": "Sti til nøglefil"
},
"updates": {
"title": "Opdateringer",
"description": "Få besked når nye opdateringer er tilgængelige. jfa-go kontrollerer {n} hvert 30 minut. Ingen IP'er eller personlige identificerbare oplysninger indsamles.",
"updateChannel": "Opdaterings Kanal",
"stable": "Stabil",
"unstable": "Ustabil"
},
"login": {
"title": "Log på",
"description": "For at få adgang til admin-siden skal du logge ind med nedenstående metode:",
"authorizeWithJellyfin": "Autoriser med Jellyfin/Emby: Loginoplysninger deles med Jellyfin, hvilket giver mulighed for flere brugere.",
"authorizeManual": "Brugernavn og adgangskode: indtast brugernavn og adgangskode manuelt.",
"adminOnly": "Kun administratorbrugere (anbefalet)",
"emailNotice": "Din e-mail adresse kan bruges til at modtage underretninger."
},
"jellyfinEmby": {
"title": "Jellyfin/Emby",
"description": "En administratorkonto er nødvendig fordi API'en ikke tillader oprettelse af brugere ved hjælp af en API-nøgle. Du skal oprette en separat konto og markere 'Tillad denne bruger at administrere serveren'. Du kan deaktivere alt andet. Når du er færdig, skal du indtaste loginoplysningerne her.",
"embyNotice": "Emby support er begrænset og understøtter ikke nulstilling af adgangskode.",
"internal": "Intern",
"external": "Ekstern",
"replaceJellyfin": "Server navn",
"replaceJellyfinNotice": "Hvis angivet, vil dette erstatte enhver forekomst af 'Jellyfin' i appen.",
"addressExternalNotice": "Lad det være tomt for at bruge den samme adresse.",
"testConnection": "Test forbindelse"
},
"ombi": {
"title": "Ombi",
"description": "Ved at oprette forbindelse til Ombi, oprettes både en Jellyfin og Ombi konto når en bruger tilmelder sig via jfa-go. Når installationen er afsluttet, skal du gå til Indstillinger for at indstille en standardprofil til nye Ombi brugere.",
"apiKeyNotice": "Find dette i den første fane i Ombi indstillinger."
},
"email": {
"title": "E-mail",
"description": "jfa-go kan sende PIN-koder til nulstilling af adgangskoder og forskellige meddelelser via e-mail. Du kan oprette forbindelse til en SMTP-server eller bruge {n} API.",
"method": "Afsendelsesmetode",
"useEmailAsUsername": "Brug e-mail adresser som brugernavn",
"useEmailAsUsernameNotice": "Hvis aktiveret, logger nye brugere på Jellyfin/Emby med deres e-mail adresse i stedet for et brugernavn.",
"fromAddress": "Fra adresse",
"senderName": "Afsender navn",
"dateFormat": "Datoformat",
"dateFormatNotice": "Dato følger strftime formatet. For flere oplysninger, besøg {n}.",
"encryption": "Kryptering",
"mailgunApiURL": "API-URL"
},
"notifications": {
"title": "Admin Meddelelser",
"description": "Hvis aktiveret, kan du vælge (pr. Invitation) at modtage besked når en invitation udløber, eller når en bruger oprettes. Hvis du ikke valgte Jellyfin login metoden, skal du sørge for at angive din e-mail adresse, eller tilføje en anden kontakt metode senere."
},
"welcomeEmails": {
"title": "Velkomst beskeder",
"description": "Hvis aktiveret, sendes en besked til nye brugere med Jellyfin/Emby URL'en og deres brugernavn."
},
"inviteEmails": {
"title": "Invitations Beskeder",
"description": "Hvis aktiveret, kan du sende invitationer direkte til en brugers e-mail adresse, Discord eller Matrix bruger. Fordi du muligvis bruger en omvendt proxy, skal du angive en URL, invitationer tilgås fra. Skriv din URL-base, og tilføj '/invite'."
},
"passwordResets": {
"title": "Nulstilling af Adgangskoder",
"description": "Når en bruger forsøger at nulstille deres adgangskode, opretter Jellyfin en fil med navnet 'passwordreset - *. Json', som indeholder en PIN-kode. jfa-go læser filen og sender PIN-koden til brugeren.",
"pathToJellyfin": "Sti til Jellyfin's konfigurations mappe",
"pathToJellyfinNotice": "Hvis du ikke ved hvor dette er, kan du prøve at nulstille din adgangskode i Jellyfin. En popup med '<sti til jellyfin>/passwordreset - *. Json' vises.",
"resetLinks": "Send et link i stedet for en PIN-kode",
"resetLinksNotice": "Hvis Ombi integration er aktiveret, skal du bruge denne til at synkronisere nulstilling af Jellyfin's adgangskode med Ombi.",
"resetLinksLanguage": "Standard sprog til nulstillings link",
"setPassword": "Angiv adgangskode gennem link",
"setPasswordNotice": "Aktivering af dette betyder at brugeren ikke behøver at ændre sin adgangskode væk fra pinkoden efter nulstillingen. Adgangskodevalidering håndhæves også."
},
"passwordValidation": {
"title": "Validering af adgangskode",
"description": "Hvis aktiveret, vises et sæt adgangskrav på siden til oprettelse af konto, såsom minimumslængde, store/små bogstaver osv.",
"length": "Længde",
"uppercase": "Store bogstaver",
"lowercase": "Små bogstaver",
"numbers": "Tal",
"special": "Specialtegn (%, * osv.)"
},
"helpMessages": {
"title": "Hjælpe Meddelelser",
"description": "Disse meddelelser vises på siden til oprettelse af konto og i nogle e-mails.",
"contactMessage": "Kontakt Meddelelse",
"contactMessageNotice": "Vises nederst på alle sider undtagen admin-siden.",
"helpMessage": "Hjælpe Meddelelse",
"helpMessageNotice": "Vises på siden til oprettelse af konto.",
"successMessage": "Succes Meddelelse",
"successMessageNotice": "Vises når en bruger opretter sin konto.",
"emailMessage": "E-mail Meddelelse",
"emailMessageNotice": "Vises i bunden af e-mails."
},
"messages": {
"title": "Beskeder",
"description": "jfa-go kan sende nulstilling af adgangskoder og forskellige meddelelser via E-mail, Discord, Telegram og/eller Matrix. Du kan konfigurere E-mail herunder, og de andre kan konfigureres i Indstillinger senere. Instruktioner kan findes på {n}. Hvis du ikke har brug for dette, kan du deaktivere disse funktioner her."
}
}

View File

@@ -101,7 +101,10 @@
"title": "Passwortzurücksetzungen",
"description": "Wenn ein Benutzer versucht sein Passwort zurückzusetzen, erstellt Jellyfin eine Datei namens 'passwordreset-*.json', welche eine PIN enthält. jfa-go liest die Datei und sendet die PIN an den Benutzer.",
"pathToJellyfin": "Pfad zum Jellyfin-Konfigurationsverzeichnis",
"pathToJellyfinNotice": "Wenn du nicht weißt, wo das ist, versuche dein Passwort in Jellyfin zurückzusetzen. Ein Popup mit '<Pfad zu Jellyfin>/passwordreset-*.json' wird angezeigt werden."
"pathToJellyfinNotice": "Wenn du nicht weißt, wo das ist, versuche dein Passwort in Jellyfin zurückzusetzen. Ein Popup mit '<Pfad zu Jellyfin>/passwordreset-*.json' wird angezeigt werden.",
"resetLinks": "Einen Link statt einer PIN senden",
"resetLinksNotice": "Wenn die Ombi-Integration aktiviert ist, verwende dies, um zurückgesetzte Passwörter von Jellyfin mit Ombi zu synchronisieren.",
"resetLinksLanguage": "Standardsprache für den Link zum Zurücksetzen des Passworts"
},
"passwordValidation": {
"title": "Passwortüberprüfung",

View File

@@ -15,7 +15,11 @@
"serverAddress": "Server Address",
"emailSubject": "Email Subject",
"URL": "URL",
"apiKey": "API Key"
"apiKey": "API Key",
"errorInvalidUserPass": "Invalid username/password.",
"errorNotAdmin": "User is not allowed to manage server.",
"errorUserDisabled": "User may be disabled.",
"error404": "404, check the internal URL."
},
"startPage": {
"welcome": "Welcome!",
@@ -25,7 +29,7 @@
},
"endPage": {
"finished": "Finished!",
"restartMessage": "There are more settings you can configure on the admin page. Click below to restart, then refresh the page.",
"restartMessage": "You can configure Discord/Telegram/Matrix bots, customize your messages and more in Settings. Click below to restart, then refresh the page.",
"refreshPage": "Refresh"
},
"language": {
@@ -79,6 +83,10 @@
"description": "By connecting to Ombi, both a Jellyfin and Ombi account will be created when a user joins through jfa-go. After setup is finished, go to Settings to set a default profile for new ombi users.",
"apiKeyNotice": "Find this in the first tab of Ombi settings."
},
"messages": {
"title": "Messages",
"description": "jfa-go can send password resets and various messages through Email, Discord, Telegram, and/or Matrix. You can set up email below, and the others can be configured in Settings later. Instructions can be found on the {n}. If you don't need this, you can disable these features here."
},
"email": {
"title": "Email",
"description": "jfa-go can send password reset PINs and various notifications through email. You can connect to an SMTP server, or use the {n} API.",
@@ -93,16 +101,16 @@
"mailgunApiURL": "API URL"
},
"notifications": {
"title": "Notifications",
"description": "If enabled, you can choose (per invite) to receive an email when an invite expires, or a user is created. If you didn't choose the Jellyfin login method, make sure you provided your email address."
"title": "Admin Notifications",
"description": "If enabled, you can choose (per invite) to receive an message when an invite expires, or a user is created. If you didn't choose the Jellyfin login method, make sure you provided your email address, or add another contact method later."
},
"welcomeEmails": {
"title": "Welcome emails",
"description": "If enabled, an email will be sent to new users with the Jellyfin/Emby URL and their username."
"title": "Welcome messages",
"description": "If enabled, an message will be sent to new users with the Jellyfin/Emby URL and their username."
},
"inviteEmails": {
"title": "Invite Emails",
"description": "If enabled, you can send invites directly to a user's email address. Because you might be using a reverse proxy, you need to provide the URL invites are accessed from. Write your URL Base, and append '/invite'."
"title": "Invite Messages",
"description": "If enabled, you can send invites directly to a user's email address, Discord or Matrix user. Because you might be using a reverse proxy, you need to provide the URL invites are accessed from. Write your URL Base, and append '/invite'."
},
"passwordResets": {
"title": "Password Resets",
@@ -111,7 +119,9 @@
"pathToJellyfinNotice": "If you don't know where this is, try resetting your password in Jellyfin. A popup with '<path to jellyfin>/passwordreset-*.json' will appear.",
"resetLinks": "Send a link instead of a PIN",
"resetLinksNotice": "If Ombi integration is enabled, use this to sync Jellyfin password resets with Ombi.",
"resetLinksLanguage": "Default reset link language"
"resetLinksLanguage": "Default reset link language",
"setPassword": "Set password through link",
"setPasswordNotice": "Enabling this means the user doesn't have to change their password from the PIN after the reset. Password validation will also be enforced."
},
"passwordValidation": {
"title": "Password Validation",

View File

@@ -108,7 +108,10 @@
"title": "Restablecimiento de contraseña",
"description": "Cuando un usuario intenta restablecer su contraseña, Jellyfin crea un archivo llamado 'passwordreset - *. Json' que contiene un PIN. jfa-go lee el archivo y envía el PIN al usuario.",
"pathToJellyfin": "Ruta al directorio de configuración de Jellyfin",
"pathToJellyfinNotice": "Si no sabe dónde está, intente restablecer su contraseña en Jellyfin. Aparecerá una ventana emergente con '<ruta a jellyfin>/passwordreset-. Json'."
"pathToJellyfinNotice": "Si no sabe dónde está, intente restablecer su contraseña en Jellyfin. Aparecerá una ventana emergente con '<ruta a jellyfin>/passwordreset-. Json'.",
"resetLinks": "Envía un enlace en lugar de un PIN",
"resetLinksNotice": "Si la integración de Ombi está habilitada, utilícela para sincronizar los restablecimientos de contraseña de Jellyfin con Ombi.",
"resetLinksLanguage": "Enlace de restablecimiento predeterminado"
},
"passwordValidation": {
"title": "Validación de contraseña",

View File

@@ -101,7 +101,10 @@
"title": "Réinitialisation de mot de passe",
"description": "Lorsqu'un utilisateur essaie de réinitialiser son mot de passe, Jellyfin créé un fichier nommé 'passwordreset-*.json' qui contient le code PIN. jfa-go lit le fichier et envoie le code PIN à l'utilisateur.",
"pathToJellyfin": "Chemin du dossier de configuration de Jellyfin",
"pathToJellyfinNotice": "Si vous ne savez pas où c'est, essayez de réinitialiser votre mot de passe dans Jellyfin. Une popup avec '<path to jellyfin>/passwordreset-*.json' apparaitra."
"pathToJellyfinNotice": "Si vous ne savez pas où c'est, essayez de réinitialiser votre mot de passe dans Jellyfin. Une popup avec '<path to jellyfin>/passwordreset-*.json' apparaitra.",
"resetLinks": "Envoyer un lien plutôt qu'un PIN",
"resetLinksNotice": "Si l'intégration est activée, utilisez ceci pour synchroniser les réinitialisations de mots de passe Jellyfin avec Ombi.",
"resetLinksLanguage": "Langue du lien de réinitialisation par défaut"
},
"passwordValidation": {
"title": "Validation du mot de passe",
@@ -123,5 +126,12 @@
"successMessageNotice": "S'affiche lorsqu'un utilisateur crée son compte.",
"emailMessage": "Message de l'e-mail",
"emailMessageNotice": "S'affiche au bas des e-mails."
},
"updates": {
"title": "Mises à jour",
"description": "Activez pour être averti lorsque de nouvelles mises à jour sont disponibles. jfa-go vérifiera {n} toutes les 30 minutes. Aucune adresse IP ou information personnellement identifiable n'est collectée.",
"updateChannel": "Mettre à jour la chaîne",
"stable": "Stable",
"unstable": "Instable"
}
}

View File

@@ -25,7 +25,7 @@
},
"endPage": {
"finished": "Klaar!",
"restartMessage": "Er staan meer instellingen op de beheerderspagina. Druk op de knop hieronder om opnieuw op te starten, en ververs daarna de pagina.",
"restartMessage": "Je kunt Discord/Telegram/Matrix bots instellen, berichten aanpassen en meer bij Instellingen. Klik hieronder om te herstarten, en ververs de pagina.",
"refreshPage": "Verversen"
},
"language": {
@@ -69,12 +69,12 @@
},
"ombi": {
"title": "Ombi",
"description": "Bij verbinding met Ombi, worden voor nieuwe gebruikers via jfa-go zowel een Jellyfin als een Ombi account aangemaakt. Ga nadat de setup voltooid is naar instellingen om een standaardprofiel voor nieuwe Ombi-gebruikers te kiezen.",
"description": "Bij verbinding met Ombi, wordt voor nieuwe gebruikers via jfa-go zowel een Jellyfin als een Ombi account aangemaakt. Ga nadat de setup voltooid is naar instellingen om een standaardprofiel voor nieuwe Ombi-gebruikers te kiezen.",
"apiKeyNotice": "Te vinden op het eerste tabblad van de Ombi-instellingen."
},
"email": {
"title": "E-mail",
"description": "jfa-go kan wachtwoord reset PINs en meldingen via e-mail versturen. Je kunt verbinding maken met een SMTP server, of de {n} API gebruiken.",
"description": "jfa-go kan wachtwoord reset pincodes en meldingen via e-mail versturen. Je kunt verbinding maken met een SMTP server, of de {n} API gebruiken.",
"method": "Verstuurmethode",
"useEmailAsUsername": "Gebruik e-mailadres als gebruikersnaam",
"useEmailAsUsernameNotice": "Indien ingeschakeld wordt voor nieuwe Jellyfin/Emby-gebruikers hun e-mailadres in plaats van gebruikersnaam gebruikt.",
@@ -86,22 +86,27 @@
"mailgunApiURL": "API-URL"
},
"notifications": {
"title": "Meldingen",
"description": "Indien ingeschakeld kun je er (per uitnodiging) voor kiezen om een e-mail te ontvangen wanneer een uitnodiging verloopt of er een gebruiker wordt aangemaakt. Als je niet inlogt via Jellyfin, controleer dan dat je je e-mailadres hebt ingevuld."
"title": "Beheersmeldingen",
"description": "Indien ingeschakeld kun je er (per uitnodiging) voor kiezen om een bericht te ontvangen wanneer een uitnodiging verloopt of er een gebruiker wordt aangemaakt. Als je niet inlogt via Jellyfin, controleer dan dat je je e-mailadres hebt ingevuld, of voeg later een andere contactmethode toe."
},
"welcomeEmails": {
"title": "Welkomste-mails",
"description": "Indien ingeschakeld wordt er een e-mail gestuurd aan nieuwe gebruikers met de Jellyfin/Emby-URL en hun gebruikersnaam."
"title": "Welkomstberichten",
"description": "Indien ingeschakeld wordt er een bericht gestuurd aan nieuwe gebruikers met de Jellyfin/Emby-URL en hun gebruikersnaam."
},
"inviteEmails": {
"title": "Uitnodigingse-mails",
"description": "Indien ingeschakeld kun je uitnodigingen direct naar het e-mailadres van gebruikers sturen. Omdat je misschien een reverse proxy gebruikt moet je het URL opgeven waarlangs uitnodigingen geopend worden. Geef de URL-basis op, gevolgd door '/invite'."
"title": "Uitnodigingsbericht",
"description": "Indien ingeschakeld kun je uitnodigingen direct naar het e-mailadres, Discord- of Matrix-account van gebruikers sturen. Omdat je misschien een reverse proxy gebruikt moet je het URL opgeven waarlangs uitnodigingen geopend worden. Geef de URL-basis op, gevolgd door '/invite'."
},
"passwordResets": {
"title": "Wachtwoordresets",
"description": "Wanneer een gebruiker een wachtwoordreset aanvraagt, maakt Jellyfin een bestand aan dat 'passwordreset-*.json' heet en een PIN bevat. jfa-go leest dit bestand uit en stuurt de PIN naar de gebruiker.",
"description": "Wanneer een gebruiker een wachtwoordreset aanvraagt, maakt Jellyfin een bestand aan dat 'passwordreset-*.json' heet en een pincode bevat. jfa-go leest dit bestand uit en stuurt de pincode naar de gebruiker.",
"pathToJellyfin": "Pad naar Jellyfin configuratiemap",
"pathToJellyfinNotice": "Als je niet weet waar dit is, probeer de je wachtwoord te resetten in Jellyfin. Er verschijnt dan een popup met '<path to jellyfin>/passwordreset-*.json'."
"pathToJellyfinNotice": "Als je niet weet waar dit is, probeer de je wachtwoord te resetten in Jellyfin. Er verschijnt dan een popup met '<path to jellyfin>/passwordreset-*.json'.",
"resetLinks": "Stuur een link in plaats van een pincode",
"resetLinksNotice": "Als Ombi-integratie is ingeschakeld, gebruik dan dit om Jellyfin wachtwoordresets te synchroniseren met Ombi.",
"resetLinksLanguage": "Standaard reset-link taal",
"setPassword": "Stel wachtwoord in via link",
"setPasswordNotice": "Als dit aanstaat hoeft de gebruiker het wachtwoord niet te wijzigen van de PINcode na de reset. Wachtwoordvalidatie wordt ook afgedwongen."
},
"passwordValidation": {
"title": "Wachtwoordvalidatie",
@@ -130,5 +135,9 @@
"stable": "Stabiel",
"title": "Updates",
"description": "Vink aan om een melding te krijgen wanneer nieuwe updates beschikbaar zijn. jfa-go controleert {n} elke 30 minuten. Er worden geen IPs of persoonsgegevens verzameld."
},
"messages": {
"title": "Berichten",
"description": "jfa-go kan wachtwoordresets en verschillende berichten sturen via E-mail, Discord, Telegram, en/of Matrix. Je kunt e-mail hieronder instellen, en de rest kan later bij Instellingen aangepast worden. Instructies staan op de {n}. Als je dit niet nodig hebt, kun je deze onderdelen hier uitschakelen."
}
}

View File

@@ -25,7 +25,7 @@
},
"endPage": {
"finished": "Finalizado!",
"restartMessage": "Existem mais opções que você pode definir na página do administrador. Clique abaixo para reiniciar e atualize a página.",
"restartMessage": "Você pode configurar os bots Discord/Telegram/Matrix, personalizar suas mensagens e muito mais em Configurações. Clique abaixo para reiniciar e, em seguida, atualize a página.",
"refreshPage": "Atualizar"
},
"language": {
@@ -86,22 +86,27 @@
"mailgunApiURL": "API URL"
},
"notifications": {
"title": "Notificações",
"description": "Se ativado, você pode escolher (por convite) receber um email quando um convite expirar ou um usuário for criado. Se você não escolheu o método de login Jellyfin, certifique-se de fornecer seu endereço de e-mail."
"title": "Notificações do Administrador",
"description": "Se ativado, você pode escolher (por convite) receber uma mensagem quando um convite expirar ou um usuário for criado. Se você não escolheu o método de login Jellyfin, certifique-se de fornecer seu endereço de e-mail ou adicione outro método de contato posteriormente."
},
"welcomeEmails": {
"title": "Email de boas-vindas",
"description": "Se habilitado, um email será enviado para os novos usuários Jellyfin/Emby."
"title": "Mensagens de boas vindas",
"description": "Se habilitado, uma mensagem será enviada para novos usuários com a URL Jellyfin/Emby e seu nome de usuário."
},
"inviteEmails": {
"title": "Convidar por Emails",
"description": "Se ativado, você pode enviar convites diretamente para o endereço de email do usuário. Como você pode estar usando um proxy reverso, é necessário fornecer a URL de onde os convites são acessados. Escreva a sua URL Base e acrescente '/invite'."
"title": "Convite por Mensagens",
"description": "Se ativado, você pode enviar convites diretamente para o endereço de e-mail do usuário, Discord ou Matrix. Como você pode estar usando um proxy reverso, é necessário fornecer a URL de onde os convites são acessados. Escreva a sua base de URL e acrescente '/ invite'."
},
"passwordResets": {
"title": "Redefinir Senha",
"description": "Quando um usuário tenta redefinir sua senha, o Jellyfin cria um arquivo chamado 'passwordreset-*.json' que contém um PIN. jfa-go lê o arquivo e envia o PIN ao usuário.",
"pathToJellyfin": "Local do diretório de configuração do Jellyfin",
"pathToJellyfinNotice": "Se você não sabe o local onde fica, tente redefinir sua senha no Jellyfin. Um pop-up com '<path to jellyfin>/passwordreset-*.json' aparecerá."
"pathToJellyfinNotice": "Se você não sabe o local onde fica, tente redefinir sua senha no Jellyfin. Um pop-up com '<path to jellyfin>/passwordreset-*.json' aparecerá.",
"resetLinks": "Envie um link em vez de um PIN",
"resetLinksNotice": "Se a integração do Ombi estiver habilitada, use para sincronizar as redefinições de senha do Jellyfin com o Ombi.",
"resetLinksLanguage": "Idioma do link de redefinição padrão",
"setPassword": "Definir a senha por meio de link",
"setPasswordNotice": "Se habilitar significa que o usuário não precisa alterar a senha do PIN após a redefinição. A validação de senha também será aplicada."
},
"passwordValidation": {
"title": "Validar Senha",
@@ -130,5 +135,9 @@
"updateChannel": "Canal de Atualização",
"stable": "Estável",
"unstable": "Instável"
},
"messages": {
"title": "Mensagens",
"description": "jfa-go pode enviar redefinições de senha e várias mensagens por e-mail, Discord, Telegram e/ou Matrix. Você pode configurar o e-mail abaixo e os outros podem ser configurados em Configurações posteriormente. As instruções podem ser encontradas em {n}. Se você não precisar, pode desativar esses recursos aqui."
}
}

View File

@@ -69,7 +69,7 @@
},
"ombi": {
"title": "Ombi",
"description": "Genom att ansluta till Ombi skapas både ett Jellyfin- och Ombi-konto när en användare går med genom jfa-go. Efter installationen, om du är klar, gå till Inställningar för att ställa in en standardprofil för nya ombi-användare.",
"description": "Genom att ansluta till Ombi skapas både ett Jellyfin- och Ombi-konto när en användare går med genom jfa-go. Efter installationen är klar, gå till Inställningar för att ställa in en standardprofil för nya ombi-användare.",
"apiKeyNotice": "Hitta detta i den första fliken i Ombi-inställningarna."
},
"email": {
@@ -101,7 +101,10 @@
"title": "Lösenordsåterställningar",
"description": "När en användare försöker återställa sitt lösenord skapar Jellyfin en fil med namnet 'passwordreset-*.json' som innehåller en PIN-kod. jfa-go läser filen och skickar PIN-koden till användaren.",
"pathToJellyfin": "Sökväg till Jellyfin-konfigurationskatalogen",
"pathToJellyfinNotice": "Om du inte vet var det är, försök återställa lösenordet i Jellyfin. En popup med '<sökväg till jellyfin>/passwordreset-*.json' kommer då visas."
"pathToJellyfinNotice": "Om du inte vet var det är, försök återställa lösenordet i Jellyfin. En popup med '<sökväg till jellyfin>/passwordreset-*.json' kommer då visas.",
"resetLinks": "Skicka en länk istället för en PIN",
"resetLinksNotice": "Om Ombi-integrationen är aktiverad, använd den för att synkronisera lösenordsåterställningar med Ombi.",
"resetLinksLanguage": "Förvalt språk för återställningslänk"
},
"passwordValidation": {
"title": "Validering av lösenord",
@@ -123,5 +126,12 @@
"successMessageNotice": "Visas när en användare skapar sitt konto.",
"emailMessage": "E-postmeddelande",
"emailMessageNotice": "Visas längst ner i e-postmeddelanden."
},
"updates": {
"title": "Uppdateringar",
"updateChannel": "Uppdateringskanal",
"description": "Aktivera för att få notifikation när nya uppdateringar finns tillgängliga. jfa-go kollar {n} var 30:e minut. Inga IP-adresser eller personligt identifierande handlingar samlas in.",
"stable": "Stabil",
"unstable": "Ostabil"
}
}

147
lang/setup/zh-hans.json Normal file
View File

@@ -0,0 +1,147 @@
{
"meta": {
"name": "简体中文(CN)"
},
"strings": {
"pageTitle": "设置 - jfa-go",
"next": "下一步",
"back": "上一步",
"optional": "可选的",
"serverType": "服务类型",
"disabled": "已禁用",
"enabled": "已启用",
"port": "端口",
"message": "信息",
"serverAddress": "服务地址",
"emailSubject": "邮件主题",
"URL": "链接",
"apiKey": "API Key",
"errorInvalidUserPass": "无效的用户名/密码。",
"errorNotAdmin": "此用户不允许管理服务。",
"errorUserDisabled": "此永固可能已被禁用。",
"error404": "404请检查内部URL。"
},
"startPage": {
"welcome": "欢迎!",
"pressStart": "您需要完成几个步骤来设置jfa-go。点击开始来继续。",
"httpsNotice": "请确保您仅通过HTTPS或者局域网访问本页面。",
"start": "开始"
},
"endPage": {
"finished": "完成!",
"restartMessage": "您可以设置Discord/Telegram/Matrix机器人在 \"设置 \"中自定义你的信息和其他内容。点击下方重新启动,然后刷新页面。",
"refreshPage": "刷新"
},
"language": {
"title": "语言",
"description": "jfa-go 的大部分内容都有社区翻译。您可以选择下面的默认语言,但用户仍然可以根据自己的意愿进行更改。如果您想帮助翻译,请在{n}注册并开始贡献您的力量!",
"defaultAdminLang": "默认管理语言",
"defaultFormLang": "默认帐户创建语言",
"defaultEmailLang": "默认电子邮件语言"
},
"general": {
"title": "常规",
"listenAddress": "监听端口",
"urlBase": "URL Base",
"urlBaseNotice": "仅在子域上使用反向代理时才需要例如“jellyf.in/accounts”。",
"lightTheme": "明亮",
"darkTheme": "暗黑",
"useHTTPS": "使用HTTPS",
"httpsPort": "HTTPS端口",
"useHTTPSNotice": "仅在不使用反向代理时推荐使用。",
"pathToCertificate": "证书文件路径",
"pathToKeyFile": "密钥文件路径"
},
"updates": {
"title": "更新",
"description": "fa-go将每隔30分钟检查一次{n}以便在有新更新时得到通知。不会收集IP或个人身份信息。",
"updateChannel": "更新通道",
"stable": "稳定版",
"unstable": "非稳定版"
},
"login": {
"title": "登录",
"description": "要访问管理页面,您需要使用以下方法登录:",
"authorizeWithJellyfin": "从Jellyfin/Emby 授权:登录信息与 Jellyfin 同步,允许使用多个用户。",
"authorizeManual": "用户名和密码:手动设置用户名和密码。",
"adminOnly": "仅允许管理员账户(推荐)",
"emailNotice": "您的电子邮件地址可以用来接收通知。"
},
"jellyfinEmby": {
"title": "Jellyfin/Emby",
"description": "需要使用管理员帐户,因为 API 不允许使用 API 密钥创建用户。您可以创建一个单独的帐户并选中“允许此用户管理服务器”并禁用其余所有功能。完成后,在此处输入登录信息。",
"embyNotice": "对Emby提供有限支持不支持密码重置功能。",
"internal": "内部",
"external": "外部",
"replaceJellyfin": "服务名称",
"replaceJellyfinNotice": "如果填写则将替换应用程序中出现的所有 \"Jellyfin\"字样。",
"addressExternalNotice": "留空以使用相同的地址。",
"testConnection": "测试连接"
},
"ombi": {
"title": "Ombi",
"description": "连接到 Ombi当用户通过 jfa-go 创建账户时,将同时创建 Jellyfin 和 Ombi 帐户。设置完成后,转到设置为新 Ombi 用户设置默认配置文件。",
"apiKeyNotice": "在Ombi设置的第一个选项卡中找到这个选项。"
},
"messages": {
"title": "信息",
"description": "jfa-go 可以通过电子邮件、Discord、Telegram 和/或 Matrix 发送密码重置和各种消息。您可以在下面设置电子邮件,其他的可以稍后在设置中进行配置。说明可以在 {n} 上找到。如果您不需要此功能,可以在此处禁用这些功能。"
},
"email": {
"title": "电子邮箱",
"description": "jfa-go 可以通过电子邮件发送密码重置 PIN 和各种通知。您可以连接到 SMTP 服务器,或使用 {n} API。",
"method": "发送方式",
"useEmailAsUsername": "使用电子邮件地址作为用户名",
"useEmailAsUsernameNotice": "如果启用,新用户将使用他们的电子邮件地址而不是用户名登录 Jellyfin/Emby。",
"fromAddress": "发件人地址",
"senderName": "发件人姓名",
"dateFormat": "日期格式",
"dateFormatNotice": "日期遵循 strftime 格式。如需更多信息,请访问 {n}。",
"encryption": "加密",
"mailgunApiURL": "API URL"
},
"notifications": {
"title": "管理员通知",
"description": "如果启用,您可以选择(每个邀请)在邀请到期或创建用户时收到通知。如果您没有选择 Jellyfin 登录方式,请确保您提供了电子邮件地址,或稍后添加其他联系方式。"
},
"welcomeEmails": {
"title": "欢迎信息",
"description": "如果启用,将向新用户发送带有 Jellyfin/Emby URL 及其用户名的消息。"
},
"inviteEmails": {
"title": "邀请通知",
"description": "如果启用您可以直接向用户的电子邮件地址、Discord 或 Matrix 用户发送邀请。因为您可能正在使用反向代理,所以需要提供访问邀请的 URL。写下您的 URL Base并附加“/invite”。"
},
"passwordResets": {
"title": "重置密码",
"description": "当用户尝试重置密码时Jellyfin 会创建一个名为“passwordreset-*.json”的文件其中包含一个 PIN码。jfa-go 会读取该文件并将 PIN 码发送给用户。",
"pathToJellyfin": "Jellyfin 配置目录的路径",
"pathToJellyfinNotice": "如果您找不到它在哪,请尝试在 Jellyfin 中重置您的密码。将出现一个带有 '<path to jellyfin>/passwordreset-*.json' 的弹出窗口。",
"resetLinks": "发送链接而不是PIN码",
"resetLinksNotice": "如果启用了 Ombi 集成,请使用它与 Ombi 同步 Jellyfin 密码重置。",
"resetLinksLanguage": "默认重置链接语言",
"setPassword": "通过链接设置密码",
"setPasswordNotice": "启用此功能意味着用户无需在重置后通过 PIN 更改其密码。并将强制执行密码验证。"
},
"passwordValidation": {
"title": "密码验证",
"description": "如果启用,则在创建帐户页面上会显示一组密码要求,例如最小长度、大写/小写字符等。",
"length": "长度",
"uppercase": "大写字母",
"lowercase": "小写字母",
"numbers": "数字",
"special": "特殊字符 (%, *, etc.)"
},
"helpMessages": {
"title": "帮助信息",
"description": "这些消息将显示在帐户创建页面和某些电子邮件中。",
"contactMessage": "联系方式",
"contactMessageNotice": "显示在除 admin 之外的所有页面的底部。",
"helpMessage": "帮助信息",
"helpMessageNotice": "显示在帐户创建页面上。",
"successMessage": "成功信息",
"successMessageNotice": "在用户创建账户时显示。",
"emailMessage": "电子邮件",
"emailMessageNotice": "显示在电子邮件的底部。"
}
}

12
lang/telegram/da-dk.json Normal file
View File

@@ -0,0 +1,12 @@
{
"meta": {
"name": "Dansk"
},
"strings": {
"startMessage": "Hej!\nIndtast din Jellyfin PIN-kode her for at verificere din konto.",
"matrixStartMessage": "Hej!\nIndtast PIN-koden under ind i Jellyfin tilmeldingssiden for at verificere din konto.",
"invalidPIN": "Den PIN-kode var ugyldig, prøv igen.",
"pinSuccess": "Sådan! Du kan nu gå tilbage til tilmeldingssiden.",
"languageMessage": "Meddelelse: Se tilgængelige sprog med {command}, og vælg sprog med {command} <sprog kode>."
}
}

12
lang/telegram/de-de.json Normal file
View File

@@ -0,0 +1,12 @@
{
"meta": {
"name": "Deutsch (DE)"
},
"strings": {
"startMessage": "Hallo,\ngib deinen Jellyfin-PIN-Code ein, um dein Konto zu verifizieren.",
"matrixStartMessage": "Hallo,\ngib den untenstehenden PIN auf der Anmeldeseite von Jellyfin ein, um dein Konto zu verifizieren.",
"invalidPIN": "Diese PIN war ungültig, versuche es erneut.",
"pinSuccess": "Erfolg! Du kannst nun zur Anmeldeseite zurückkehren.",
"languageMessage": "Hinweis: Zeige verfügbare Sprachen mit {command} an und stelle mit {command} <Sprachcode> die gewünschte ein."
}
}

View File

@@ -4,8 +4,9 @@
},
"strings": {
"startMessage": "Hi!\nEnter your Jellyfin PIN code here to verify your account.",
"matrixStartMessage": "Hi\nEnter the below PIN in the Jellyfin sign-up page to verify your account.",
"invalidPIN": "That PIN was invalid, try again.",
"pinSuccess": "Success! You can now return to the sign-up page.",
"languageMessage": "Note: See available languages with /lang, and set language with /lang <language code>."
"languageMessage": "Note: See available languages with {command}, and set language with {command} <language code>."
}
}

12
lang/telegram/es-es.json Normal file
View File

@@ -0,0 +1,12 @@
{
"meta": {
"name": ""
},
"strings": {
"startMessage": "¡Hola!\nIntroduce tu código PIN de Jellyfin para verificar tu cuenta.",
"matrixStartMessage": "Hola,\nIntroduce el PIN de abajo para logarte en la página de Jellyfin y verificar tu cuenta.",
"invalidPIN": "El PIN es inváido, inténtalo de nuevo.",
"pinSuccess": "Ok! Ya puedes volver a la página de login.",
"languageMessage": "Nota: Ver los idiomas disponibles con {command}, y ajusta el idioma con {command} <language code>."
}
}

12
lang/telegram/fa-ir.json Normal file
View File

@@ -0,0 +1,12 @@
{
"meta": {
"name": "انگلیسی"
},
"strings": {
"startMessage": "سلام!\nبرای تأیید حساب خود ، کد PIN خود را در اینجا وارد کنید.",
"matrixStartMessage": "سلام\nبرای تأیید حساب خود ، پین زیر را در صفحه ثبت نام وارد کنید.",
"invalidPIN": "آن پین نامعتبر بود ، دوباره امتحان کنید.",
"pinSuccess": "موفقیت! اکنون می توانید به صفحه ثبت نام بازگردید.",
"languageMessage": "توجه: زبانهای موجود با {command} را مشاهده کرده و زبان را با {command} <code code> تنظیم کنید."
}
}

Some files were not shown because too many files have changed in this diff Show More