mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2025-01-11 01:35:28 +00:00
Merge branch 'main' into import-limit
This commit is contained in:
commit
7e7966987b
71 changed files with 13041 additions and 3774 deletions
|
@ -34,6 +34,7 @@ REDIS_ACTIVITY_PASSWORD=redispassword345
|
||||||
# REDIS_ACTIVITY_DB_INDEX=0
|
# REDIS_ACTIVITY_DB_INDEX=0
|
||||||
|
|
||||||
# Redis as celery broker
|
# Redis as celery broker
|
||||||
|
REDIS_BROKER_HOST=redis_broker
|
||||||
REDIS_BROKER_PORT=6379
|
REDIS_BROKER_PORT=6379
|
||||||
REDIS_BROKER_PASSWORD=redispassword123
|
REDIS_BROKER_PASSWORD=redispassword123
|
||||||
# Optional, use a different redis database (defaults to 0)
|
# Optional, use a different redis database (defaults to 0)
|
||||||
|
|
|
@ -318,6 +318,10 @@ def add_status_on_create_command(sender, instance, created):
|
||||||
if instance.published_date < timezone.now() - timedelta(
|
if instance.published_date < timezone.now() - timedelta(
|
||||||
days=1
|
days=1
|
||||||
) or instance.created_date < instance.published_date - timedelta(days=1):
|
) or instance.created_date < instance.published_date - timedelta(days=1):
|
||||||
|
# a backdated status from a local user is an import, don't add it
|
||||||
|
if instance.user.local:
|
||||||
|
return
|
||||||
|
# an out of date remote status is a low priority but should be added
|
||||||
priority = LOW
|
priority = LOW
|
||||||
|
|
||||||
add_status_task.apply_async(
|
add_status_task.apply_async(
|
||||||
|
|
48
bookwyrm/management/commands/compile_themes.py
Normal file
48
bookwyrm/management/commands/compile_themes.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
""" Our own command to all scss themes """
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
|
||||||
|
import sass
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from sass_processor.apps import APPS_INCLUDE_DIRS
|
||||||
|
from sass_processor.processor import SassProcessor
|
||||||
|
from sass_processor.utils import get_custom_functions
|
||||||
|
|
||||||
|
from bookwyrm import settings
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""command-line options"""
|
||||||
|
|
||||||
|
help = "SCSS compile all BookWyrm themes"
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
"""compile"""
|
||||||
|
themes_dir = os.path.join(
|
||||||
|
settings.BASE_DIR, "bookwyrm", "static", "css", "themes", "*.scss"
|
||||||
|
)
|
||||||
|
for theme_scss in glob.glob(themes_dir):
|
||||||
|
basename, _ = os.path.splitext(theme_scss)
|
||||||
|
theme_css = f"{basename}.css"
|
||||||
|
self.compile_sass(theme_scss, theme_css)
|
||||||
|
|
||||||
|
def compile_sass(self, sass_path, css_path):
|
||||||
|
compile_kwargs = {
|
||||||
|
"filename": sass_path,
|
||||||
|
"include_paths": SassProcessor.include_paths + APPS_INCLUDE_DIRS,
|
||||||
|
"custom_functions": get_custom_functions(),
|
||||||
|
"precision": getattr(settings, "SASS_PRECISION", 8),
|
||||||
|
"output_style": getattr(
|
||||||
|
settings,
|
||||||
|
"SASS_OUTPUT_STYLE",
|
||||||
|
"nested" if settings.DEBUG else "compressed",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
content = sass.compile(**compile_kwargs)
|
||||||
|
with open(css_path, "w") as f:
|
||||||
|
f.write(content)
|
||||||
|
self.stdout.write("Compiled SASS/SCSS file: '{0}'\n".format(sass_path))
|
|
@ -0,0 +1,40 @@
|
||||||
|
""" Remove preview images for remote users """
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from bookwyrm import models, preview_images
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""Remove preview images for remote users"""
|
||||||
|
|
||||||
|
help = "Remove preview images for remote users"
|
||||||
|
|
||||||
|
# pylint: disable=no-self-use,unused-argument
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
"""generate preview images"""
|
||||||
|
self.stdout.write(
|
||||||
|
" | Hello! I will be removing preview images from remote users."
|
||||||
|
)
|
||||||
|
self.stdout.write(
|
||||||
|
"🧑🚒 ⎨ This might take quite long if your instance has a lot of remote users."
|
||||||
|
)
|
||||||
|
self.stdout.write(" | ✧ Thank you for your patience ✧")
|
||||||
|
|
||||||
|
users = models.User.objects.filter(local=False).exclude(
|
||||||
|
Q(preview_image="") | Q(preview_image=None)
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(users) > 0:
|
||||||
|
self.stdout.write(
|
||||||
|
f" → Remote user preview images ({len(users)}): ", ending=""
|
||||||
|
)
|
||||||
|
for user in users:
|
||||||
|
preview_images.remove_user_preview_image_task.delay(user.id)
|
||||||
|
self.stdout.write(".", ending="")
|
||||||
|
self.stdout.write(" OK 🖼")
|
||||||
|
else:
|
||||||
|
self.stdout.write(f" | There was no remote users with preview images.")
|
||||||
|
|
||||||
|
self.stdout.write("🧑🚒 ⎨ I’m all done! ✧ Enjoy ✧")
|
631
bookwyrm/migrations/0171_alter_user_preferred_timezone.py
Normal file
631
bookwyrm/migrations/0171_alter_user_preferred_timezone.py
Normal file
|
@ -0,0 +1,631 @@
|
||||||
|
# Generated by Django 3.2.16 on 2022-12-19 15:30
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0170_merge_0168_auto_20221205_2331_0169_auto_20221206_0902"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="user",
|
||||||
|
name="preferred_timezone",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("Africa/Abidjan", "Africa/Abidjan"),
|
||||||
|
("Africa/Accra", "Africa/Accra"),
|
||||||
|
("Africa/Addis_Ababa", "Africa/Addis_Ababa"),
|
||||||
|
("Africa/Algiers", "Africa/Algiers"),
|
||||||
|
("Africa/Asmara", "Africa/Asmara"),
|
||||||
|
("Africa/Asmera", "Africa/Asmera"),
|
||||||
|
("Africa/Bamako", "Africa/Bamako"),
|
||||||
|
("Africa/Bangui", "Africa/Bangui"),
|
||||||
|
("Africa/Banjul", "Africa/Banjul"),
|
||||||
|
("Africa/Bissau", "Africa/Bissau"),
|
||||||
|
("Africa/Blantyre", "Africa/Blantyre"),
|
||||||
|
("Africa/Brazzaville", "Africa/Brazzaville"),
|
||||||
|
("Africa/Bujumbura", "Africa/Bujumbura"),
|
||||||
|
("Africa/Cairo", "Africa/Cairo"),
|
||||||
|
("Africa/Casablanca", "Africa/Casablanca"),
|
||||||
|
("Africa/Ceuta", "Africa/Ceuta"),
|
||||||
|
("Africa/Conakry", "Africa/Conakry"),
|
||||||
|
("Africa/Dakar", "Africa/Dakar"),
|
||||||
|
("Africa/Dar_es_Salaam", "Africa/Dar_es_Salaam"),
|
||||||
|
("Africa/Djibouti", "Africa/Djibouti"),
|
||||||
|
("Africa/Douala", "Africa/Douala"),
|
||||||
|
("Africa/El_Aaiun", "Africa/El_Aaiun"),
|
||||||
|
("Africa/Freetown", "Africa/Freetown"),
|
||||||
|
("Africa/Gaborone", "Africa/Gaborone"),
|
||||||
|
("Africa/Harare", "Africa/Harare"),
|
||||||
|
("Africa/Johannesburg", "Africa/Johannesburg"),
|
||||||
|
("Africa/Juba", "Africa/Juba"),
|
||||||
|
("Africa/Kampala", "Africa/Kampala"),
|
||||||
|
("Africa/Khartoum", "Africa/Khartoum"),
|
||||||
|
("Africa/Kigali", "Africa/Kigali"),
|
||||||
|
("Africa/Kinshasa", "Africa/Kinshasa"),
|
||||||
|
("Africa/Lagos", "Africa/Lagos"),
|
||||||
|
("Africa/Libreville", "Africa/Libreville"),
|
||||||
|
("Africa/Lome", "Africa/Lome"),
|
||||||
|
("Africa/Luanda", "Africa/Luanda"),
|
||||||
|
("Africa/Lubumbashi", "Africa/Lubumbashi"),
|
||||||
|
("Africa/Lusaka", "Africa/Lusaka"),
|
||||||
|
("Africa/Malabo", "Africa/Malabo"),
|
||||||
|
("Africa/Maputo", "Africa/Maputo"),
|
||||||
|
("Africa/Maseru", "Africa/Maseru"),
|
||||||
|
("Africa/Mbabane", "Africa/Mbabane"),
|
||||||
|
("Africa/Mogadishu", "Africa/Mogadishu"),
|
||||||
|
("Africa/Monrovia", "Africa/Monrovia"),
|
||||||
|
("Africa/Nairobi", "Africa/Nairobi"),
|
||||||
|
("Africa/Ndjamena", "Africa/Ndjamena"),
|
||||||
|
("Africa/Niamey", "Africa/Niamey"),
|
||||||
|
("Africa/Nouakchott", "Africa/Nouakchott"),
|
||||||
|
("Africa/Ouagadougou", "Africa/Ouagadougou"),
|
||||||
|
("Africa/Porto-Novo", "Africa/Porto-Novo"),
|
||||||
|
("Africa/Sao_Tome", "Africa/Sao_Tome"),
|
||||||
|
("Africa/Timbuktu", "Africa/Timbuktu"),
|
||||||
|
("Africa/Tripoli", "Africa/Tripoli"),
|
||||||
|
("Africa/Tunis", "Africa/Tunis"),
|
||||||
|
("Africa/Windhoek", "Africa/Windhoek"),
|
||||||
|
("America/Adak", "America/Adak"),
|
||||||
|
("America/Anchorage", "America/Anchorage"),
|
||||||
|
("America/Anguilla", "America/Anguilla"),
|
||||||
|
("America/Antigua", "America/Antigua"),
|
||||||
|
("America/Araguaina", "America/Araguaina"),
|
||||||
|
(
|
||||||
|
"America/Argentina/Buenos_Aires",
|
||||||
|
"America/Argentina/Buenos_Aires",
|
||||||
|
),
|
||||||
|
("America/Argentina/Catamarca", "America/Argentina/Catamarca"),
|
||||||
|
(
|
||||||
|
"America/Argentina/ComodRivadavia",
|
||||||
|
"America/Argentina/ComodRivadavia",
|
||||||
|
),
|
||||||
|
("America/Argentina/Cordoba", "America/Argentina/Cordoba"),
|
||||||
|
("America/Argentina/Jujuy", "America/Argentina/Jujuy"),
|
||||||
|
("America/Argentina/La_Rioja", "America/Argentina/La_Rioja"),
|
||||||
|
("America/Argentina/Mendoza", "America/Argentina/Mendoza"),
|
||||||
|
(
|
||||||
|
"America/Argentina/Rio_Gallegos",
|
||||||
|
"America/Argentina/Rio_Gallegos",
|
||||||
|
),
|
||||||
|
("America/Argentina/Salta", "America/Argentina/Salta"),
|
||||||
|
("America/Argentina/San_Juan", "America/Argentina/San_Juan"),
|
||||||
|
("America/Argentina/San_Luis", "America/Argentina/San_Luis"),
|
||||||
|
("America/Argentina/Tucuman", "America/Argentina/Tucuman"),
|
||||||
|
("America/Argentina/Ushuaia", "America/Argentina/Ushuaia"),
|
||||||
|
("America/Aruba", "America/Aruba"),
|
||||||
|
("America/Asuncion", "America/Asuncion"),
|
||||||
|
("America/Atikokan", "America/Atikokan"),
|
||||||
|
("America/Atka", "America/Atka"),
|
||||||
|
("America/Bahia", "America/Bahia"),
|
||||||
|
("America/Bahia_Banderas", "America/Bahia_Banderas"),
|
||||||
|
("America/Barbados", "America/Barbados"),
|
||||||
|
("America/Belem", "America/Belem"),
|
||||||
|
("America/Belize", "America/Belize"),
|
||||||
|
("America/Blanc-Sablon", "America/Blanc-Sablon"),
|
||||||
|
("America/Boa_Vista", "America/Boa_Vista"),
|
||||||
|
("America/Bogota", "America/Bogota"),
|
||||||
|
("America/Boise", "America/Boise"),
|
||||||
|
("America/Buenos_Aires", "America/Buenos_Aires"),
|
||||||
|
("America/Cambridge_Bay", "America/Cambridge_Bay"),
|
||||||
|
("America/Campo_Grande", "America/Campo_Grande"),
|
||||||
|
("America/Cancun", "America/Cancun"),
|
||||||
|
("America/Caracas", "America/Caracas"),
|
||||||
|
("America/Catamarca", "America/Catamarca"),
|
||||||
|
("America/Cayenne", "America/Cayenne"),
|
||||||
|
("America/Cayman", "America/Cayman"),
|
||||||
|
("America/Chicago", "America/Chicago"),
|
||||||
|
("America/Chihuahua", "America/Chihuahua"),
|
||||||
|
("America/Ciudad_Juarez", "America/Ciudad_Juarez"),
|
||||||
|
("America/Coral_Harbour", "America/Coral_Harbour"),
|
||||||
|
("America/Cordoba", "America/Cordoba"),
|
||||||
|
("America/Costa_Rica", "America/Costa_Rica"),
|
||||||
|
("America/Creston", "America/Creston"),
|
||||||
|
("America/Cuiaba", "America/Cuiaba"),
|
||||||
|
("America/Curacao", "America/Curacao"),
|
||||||
|
("America/Danmarkshavn", "America/Danmarkshavn"),
|
||||||
|
("America/Dawson", "America/Dawson"),
|
||||||
|
("America/Dawson_Creek", "America/Dawson_Creek"),
|
||||||
|
("America/Denver", "America/Denver"),
|
||||||
|
("America/Detroit", "America/Detroit"),
|
||||||
|
("America/Dominica", "America/Dominica"),
|
||||||
|
("America/Edmonton", "America/Edmonton"),
|
||||||
|
("America/Eirunepe", "America/Eirunepe"),
|
||||||
|
("America/El_Salvador", "America/El_Salvador"),
|
||||||
|
("America/Ensenada", "America/Ensenada"),
|
||||||
|
("America/Fort_Nelson", "America/Fort_Nelson"),
|
||||||
|
("America/Fort_Wayne", "America/Fort_Wayne"),
|
||||||
|
("America/Fortaleza", "America/Fortaleza"),
|
||||||
|
("America/Glace_Bay", "America/Glace_Bay"),
|
||||||
|
("America/Godthab", "America/Godthab"),
|
||||||
|
("America/Goose_Bay", "America/Goose_Bay"),
|
||||||
|
("America/Grand_Turk", "America/Grand_Turk"),
|
||||||
|
("America/Grenada", "America/Grenada"),
|
||||||
|
("America/Guadeloupe", "America/Guadeloupe"),
|
||||||
|
("America/Guatemala", "America/Guatemala"),
|
||||||
|
("America/Guayaquil", "America/Guayaquil"),
|
||||||
|
("America/Guyana", "America/Guyana"),
|
||||||
|
("America/Halifax", "America/Halifax"),
|
||||||
|
("America/Havana", "America/Havana"),
|
||||||
|
("America/Hermosillo", "America/Hermosillo"),
|
||||||
|
("America/Indiana/Indianapolis", "America/Indiana/Indianapolis"),
|
||||||
|
("America/Indiana/Knox", "America/Indiana/Knox"),
|
||||||
|
("America/Indiana/Marengo", "America/Indiana/Marengo"),
|
||||||
|
("America/Indiana/Petersburg", "America/Indiana/Petersburg"),
|
||||||
|
("America/Indiana/Tell_City", "America/Indiana/Tell_City"),
|
||||||
|
("America/Indiana/Vevay", "America/Indiana/Vevay"),
|
||||||
|
("America/Indiana/Vincennes", "America/Indiana/Vincennes"),
|
||||||
|
("America/Indiana/Winamac", "America/Indiana/Winamac"),
|
||||||
|
("America/Indianapolis", "America/Indianapolis"),
|
||||||
|
("America/Inuvik", "America/Inuvik"),
|
||||||
|
("America/Iqaluit", "America/Iqaluit"),
|
||||||
|
("America/Jamaica", "America/Jamaica"),
|
||||||
|
("America/Jujuy", "America/Jujuy"),
|
||||||
|
("America/Juneau", "America/Juneau"),
|
||||||
|
("America/Kentucky/Louisville", "America/Kentucky/Louisville"),
|
||||||
|
("America/Kentucky/Monticello", "America/Kentucky/Monticello"),
|
||||||
|
("America/Knox_IN", "America/Knox_IN"),
|
||||||
|
("America/Kralendijk", "America/Kralendijk"),
|
||||||
|
("America/La_Paz", "America/La_Paz"),
|
||||||
|
("America/Lima", "America/Lima"),
|
||||||
|
("America/Los_Angeles", "America/Los_Angeles"),
|
||||||
|
("America/Louisville", "America/Louisville"),
|
||||||
|
("America/Lower_Princes", "America/Lower_Princes"),
|
||||||
|
("America/Maceio", "America/Maceio"),
|
||||||
|
("America/Managua", "America/Managua"),
|
||||||
|
("America/Manaus", "America/Manaus"),
|
||||||
|
("America/Marigot", "America/Marigot"),
|
||||||
|
("America/Martinique", "America/Martinique"),
|
||||||
|
("America/Matamoros", "America/Matamoros"),
|
||||||
|
("America/Mazatlan", "America/Mazatlan"),
|
||||||
|
("America/Mendoza", "America/Mendoza"),
|
||||||
|
("America/Menominee", "America/Menominee"),
|
||||||
|
("America/Merida", "America/Merida"),
|
||||||
|
("America/Metlakatla", "America/Metlakatla"),
|
||||||
|
("America/Mexico_City", "America/Mexico_City"),
|
||||||
|
("America/Miquelon", "America/Miquelon"),
|
||||||
|
("America/Moncton", "America/Moncton"),
|
||||||
|
("America/Monterrey", "America/Monterrey"),
|
||||||
|
("America/Montevideo", "America/Montevideo"),
|
||||||
|
("America/Montreal", "America/Montreal"),
|
||||||
|
("America/Montserrat", "America/Montserrat"),
|
||||||
|
("America/Nassau", "America/Nassau"),
|
||||||
|
("America/New_York", "America/New_York"),
|
||||||
|
("America/Nipigon", "America/Nipigon"),
|
||||||
|
("America/Nome", "America/Nome"),
|
||||||
|
("America/Noronha", "America/Noronha"),
|
||||||
|
("America/North_Dakota/Beulah", "America/North_Dakota/Beulah"),
|
||||||
|
("America/North_Dakota/Center", "America/North_Dakota/Center"),
|
||||||
|
(
|
||||||
|
"America/North_Dakota/New_Salem",
|
||||||
|
"America/North_Dakota/New_Salem",
|
||||||
|
),
|
||||||
|
("America/Nuuk", "America/Nuuk"),
|
||||||
|
("America/Ojinaga", "America/Ojinaga"),
|
||||||
|
("America/Panama", "America/Panama"),
|
||||||
|
("America/Pangnirtung", "America/Pangnirtung"),
|
||||||
|
("America/Paramaribo", "America/Paramaribo"),
|
||||||
|
("America/Phoenix", "America/Phoenix"),
|
||||||
|
("America/Port-au-Prince", "America/Port-au-Prince"),
|
||||||
|
("America/Port_of_Spain", "America/Port_of_Spain"),
|
||||||
|
("America/Porto_Acre", "America/Porto_Acre"),
|
||||||
|
("America/Porto_Velho", "America/Porto_Velho"),
|
||||||
|
("America/Puerto_Rico", "America/Puerto_Rico"),
|
||||||
|
("America/Punta_Arenas", "America/Punta_Arenas"),
|
||||||
|
("America/Rainy_River", "America/Rainy_River"),
|
||||||
|
("America/Rankin_Inlet", "America/Rankin_Inlet"),
|
||||||
|
("America/Recife", "America/Recife"),
|
||||||
|
("America/Regina", "America/Regina"),
|
||||||
|
("America/Resolute", "America/Resolute"),
|
||||||
|
("America/Rio_Branco", "America/Rio_Branco"),
|
||||||
|
("America/Rosario", "America/Rosario"),
|
||||||
|
("America/Santa_Isabel", "America/Santa_Isabel"),
|
||||||
|
("America/Santarem", "America/Santarem"),
|
||||||
|
("America/Santiago", "America/Santiago"),
|
||||||
|
("America/Santo_Domingo", "America/Santo_Domingo"),
|
||||||
|
("America/Sao_Paulo", "America/Sao_Paulo"),
|
||||||
|
("America/Scoresbysund", "America/Scoresbysund"),
|
||||||
|
("America/Shiprock", "America/Shiprock"),
|
||||||
|
("America/Sitka", "America/Sitka"),
|
||||||
|
("America/St_Barthelemy", "America/St_Barthelemy"),
|
||||||
|
("America/St_Johns", "America/St_Johns"),
|
||||||
|
("America/St_Kitts", "America/St_Kitts"),
|
||||||
|
("America/St_Lucia", "America/St_Lucia"),
|
||||||
|
("America/St_Thomas", "America/St_Thomas"),
|
||||||
|
("America/St_Vincent", "America/St_Vincent"),
|
||||||
|
("America/Swift_Current", "America/Swift_Current"),
|
||||||
|
("America/Tegucigalpa", "America/Tegucigalpa"),
|
||||||
|
("America/Thule", "America/Thule"),
|
||||||
|
("America/Thunder_Bay", "America/Thunder_Bay"),
|
||||||
|
("America/Tijuana", "America/Tijuana"),
|
||||||
|
("America/Toronto", "America/Toronto"),
|
||||||
|
("America/Tortola", "America/Tortola"),
|
||||||
|
("America/Vancouver", "America/Vancouver"),
|
||||||
|
("America/Virgin", "America/Virgin"),
|
||||||
|
("America/Whitehorse", "America/Whitehorse"),
|
||||||
|
("America/Winnipeg", "America/Winnipeg"),
|
||||||
|
("America/Yakutat", "America/Yakutat"),
|
||||||
|
("America/Yellowknife", "America/Yellowknife"),
|
||||||
|
("Antarctica/Casey", "Antarctica/Casey"),
|
||||||
|
("Antarctica/Davis", "Antarctica/Davis"),
|
||||||
|
("Antarctica/DumontDUrville", "Antarctica/DumontDUrville"),
|
||||||
|
("Antarctica/Macquarie", "Antarctica/Macquarie"),
|
||||||
|
("Antarctica/Mawson", "Antarctica/Mawson"),
|
||||||
|
("Antarctica/McMurdo", "Antarctica/McMurdo"),
|
||||||
|
("Antarctica/Palmer", "Antarctica/Palmer"),
|
||||||
|
("Antarctica/Rothera", "Antarctica/Rothera"),
|
||||||
|
("Antarctica/South_Pole", "Antarctica/South_Pole"),
|
||||||
|
("Antarctica/Syowa", "Antarctica/Syowa"),
|
||||||
|
("Antarctica/Troll", "Antarctica/Troll"),
|
||||||
|
("Antarctica/Vostok", "Antarctica/Vostok"),
|
||||||
|
("Arctic/Longyearbyen", "Arctic/Longyearbyen"),
|
||||||
|
("Asia/Aden", "Asia/Aden"),
|
||||||
|
("Asia/Almaty", "Asia/Almaty"),
|
||||||
|
("Asia/Amman", "Asia/Amman"),
|
||||||
|
("Asia/Anadyr", "Asia/Anadyr"),
|
||||||
|
("Asia/Aqtau", "Asia/Aqtau"),
|
||||||
|
("Asia/Aqtobe", "Asia/Aqtobe"),
|
||||||
|
("Asia/Ashgabat", "Asia/Ashgabat"),
|
||||||
|
("Asia/Ashkhabad", "Asia/Ashkhabad"),
|
||||||
|
("Asia/Atyrau", "Asia/Atyrau"),
|
||||||
|
("Asia/Baghdad", "Asia/Baghdad"),
|
||||||
|
("Asia/Bahrain", "Asia/Bahrain"),
|
||||||
|
("Asia/Baku", "Asia/Baku"),
|
||||||
|
("Asia/Bangkok", "Asia/Bangkok"),
|
||||||
|
("Asia/Barnaul", "Asia/Barnaul"),
|
||||||
|
("Asia/Beirut", "Asia/Beirut"),
|
||||||
|
("Asia/Bishkek", "Asia/Bishkek"),
|
||||||
|
("Asia/Brunei", "Asia/Brunei"),
|
||||||
|
("Asia/Calcutta", "Asia/Calcutta"),
|
||||||
|
("Asia/Chita", "Asia/Chita"),
|
||||||
|
("Asia/Choibalsan", "Asia/Choibalsan"),
|
||||||
|
("Asia/Chongqing", "Asia/Chongqing"),
|
||||||
|
("Asia/Chungking", "Asia/Chungking"),
|
||||||
|
("Asia/Colombo", "Asia/Colombo"),
|
||||||
|
("Asia/Dacca", "Asia/Dacca"),
|
||||||
|
("Asia/Damascus", "Asia/Damascus"),
|
||||||
|
("Asia/Dhaka", "Asia/Dhaka"),
|
||||||
|
("Asia/Dili", "Asia/Dili"),
|
||||||
|
("Asia/Dubai", "Asia/Dubai"),
|
||||||
|
("Asia/Dushanbe", "Asia/Dushanbe"),
|
||||||
|
("Asia/Famagusta", "Asia/Famagusta"),
|
||||||
|
("Asia/Gaza", "Asia/Gaza"),
|
||||||
|
("Asia/Harbin", "Asia/Harbin"),
|
||||||
|
("Asia/Hebron", "Asia/Hebron"),
|
||||||
|
("Asia/Ho_Chi_Minh", "Asia/Ho_Chi_Minh"),
|
||||||
|
("Asia/Hong_Kong", "Asia/Hong_Kong"),
|
||||||
|
("Asia/Hovd", "Asia/Hovd"),
|
||||||
|
("Asia/Irkutsk", "Asia/Irkutsk"),
|
||||||
|
("Asia/Istanbul", "Asia/Istanbul"),
|
||||||
|
("Asia/Jakarta", "Asia/Jakarta"),
|
||||||
|
("Asia/Jayapura", "Asia/Jayapura"),
|
||||||
|
("Asia/Jerusalem", "Asia/Jerusalem"),
|
||||||
|
("Asia/Kabul", "Asia/Kabul"),
|
||||||
|
("Asia/Kamchatka", "Asia/Kamchatka"),
|
||||||
|
("Asia/Karachi", "Asia/Karachi"),
|
||||||
|
("Asia/Kashgar", "Asia/Kashgar"),
|
||||||
|
("Asia/Kathmandu", "Asia/Kathmandu"),
|
||||||
|
("Asia/Katmandu", "Asia/Katmandu"),
|
||||||
|
("Asia/Khandyga", "Asia/Khandyga"),
|
||||||
|
("Asia/Kolkata", "Asia/Kolkata"),
|
||||||
|
("Asia/Krasnoyarsk", "Asia/Krasnoyarsk"),
|
||||||
|
("Asia/Kuala_Lumpur", "Asia/Kuala_Lumpur"),
|
||||||
|
("Asia/Kuching", "Asia/Kuching"),
|
||||||
|
("Asia/Kuwait", "Asia/Kuwait"),
|
||||||
|
("Asia/Macao", "Asia/Macao"),
|
||||||
|
("Asia/Macau", "Asia/Macau"),
|
||||||
|
("Asia/Magadan", "Asia/Magadan"),
|
||||||
|
("Asia/Makassar", "Asia/Makassar"),
|
||||||
|
("Asia/Manila", "Asia/Manila"),
|
||||||
|
("Asia/Muscat", "Asia/Muscat"),
|
||||||
|
("Asia/Nicosia", "Asia/Nicosia"),
|
||||||
|
("Asia/Novokuznetsk", "Asia/Novokuznetsk"),
|
||||||
|
("Asia/Novosibirsk", "Asia/Novosibirsk"),
|
||||||
|
("Asia/Omsk", "Asia/Omsk"),
|
||||||
|
("Asia/Oral", "Asia/Oral"),
|
||||||
|
("Asia/Phnom_Penh", "Asia/Phnom_Penh"),
|
||||||
|
("Asia/Pontianak", "Asia/Pontianak"),
|
||||||
|
("Asia/Pyongyang", "Asia/Pyongyang"),
|
||||||
|
("Asia/Qatar", "Asia/Qatar"),
|
||||||
|
("Asia/Qostanay", "Asia/Qostanay"),
|
||||||
|
("Asia/Qyzylorda", "Asia/Qyzylorda"),
|
||||||
|
("Asia/Rangoon", "Asia/Rangoon"),
|
||||||
|
("Asia/Riyadh", "Asia/Riyadh"),
|
||||||
|
("Asia/Saigon", "Asia/Saigon"),
|
||||||
|
("Asia/Sakhalin", "Asia/Sakhalin"),
|
||||||
|
("Asia/Samarkand", "Asia/Samarkand"),
|
||||||
|
("Asia/Seoul", "Asia/Seoul"),
|
||||||
|
("Asia/Shanghai", "Asia/Shanghai"),
|
||||||
|
("Asia/Singapore", "Asia/Singapore"),
|
||||||
|
("Asia/Srednekolymsk", "Asia/Srednekolymsk"),
|
||||||
|
("Asia/Taipei", "Asia/Taipei"),
|
||||||
|
("Asia/Tashkent", "Asia/Tashkent"),
|
||||||
|
("Asia/Tbilisi", "Asia/Tbilisi"),
|
||||||
|
("Asia/Tehran", "Asia/Tehran"),
|
||||||
|
("Asia/Tel_Aviv", "Asia/Tel_Aviv"),
|
||||||
|
("Asia/Thimbu", "Asia/Thimbu"),
|
||||||
|
("Asia/Thimphu", "Asia/Thimphu"),
|
||||||
|
("Asia/Tokyo", "Asia/Tokyo"),
|
||||||
|
("Asia/Tomsk", "Asia/Tomsk"),
|
||||||
|
("Asia/Ujung_Pandang", "Asia/Ujung_Pandang"),
|
||||||
|
("Asia/Ulaanbaatar", "Asia/Ulaanbaatar"),
|
||||||
|
("Asia/Ulan_Bator", "Asia/Ulan_Bator"),
|
||||||
|
("Asia/Urumqi", "Asia/Urumqi"),
|
||||||
|
("Asia/Ust-Nera", "Asia/Ust-Nera"),
|
||||||
|
("Asia/Vientiane", "Asia/Vientiane"),
|
||||||
|
("Asia/Vladivostok", "Asia/Vladivostok"),
|
||||||
|
("Asia/Yakutsk", "Asia/Yakutsk"),
|
||||||
|
("Asia/Yangon", "Asia/Yangon"),
|
||||||
|
("Asia/Yekaterinburg", "Asia/Yekaterinburg"),
|
||||||
|
("Asia/Yerevan", "Asia/Yerevan"),
|
||||||
|
("Atlantic/Azores", "Atlantic/Azores"),
|
||||||
|
("Atlantic/Bermuda", "Atlantic/Bermuda"),
|
||||||
|
("Atlantic/Canary", "Atlantic/Canary"),
|
||||||
|
("Atlantic/Cape_Verde", "Atlantic/Cape_Verde"),
|
||||||
|
("Atlantic/Faeroe", "Atlantic/Faeroe"),
|
||||||
|
("Atlantic/Faroe", "Atlantic/Faroe"),
|
||||||
|
("Atlantic/Jan_Mayen", "Atlantic/Jan_Mayen"),
|
||||||
|
("Atlantic/Madeira", "Atlantic/Madeira"),
|
||||||
|
("Atlantic/Reykjavik", "Atlantic/Reykjavik"),
|
||||||
|
("Atlantic/South_Georgia", "Atlantic/South_Georgia"),
|
||||||
|
("Atlantic/St_Helena", "Atlantic/St_Helena"),
|
||||||
|
("Atlantic/Stanley", "Atlantic/Stanley"),
|
||||||
|
("Australia/ACT", "Australia/ACT"),
|
||||||
|
("Australia/Adelaide", "Australia/Adelaide"),
|
||||||
|
("Australia/Brisbane", "Australia/Brisbane"),
|
||||||
|
("Australia/Broken_Hill", "Australia/Broken_Hill"),
|
||||||
|
("Australia/Canberra", "Australia/Canberra"),
|
||||||
|
("Australia/Currie", "Australia/Currie"),
|
||||||
|
("Australia/Darwin", "Australia/Darwin"),
|
||||||
|
("Australia/Eucla", "Australia/Eucla"),
|
||||||
|
("Australia/Hobart", "Australia/Hobart"),
|
||||||
|
("Australia/LHI", "Australia/LHI"),
|
||||||
|
("Australia/Lindeman", "Australia/Lindeman"),
|
||||||
|
("Australia/Lord_Howe", "Australia/Lord_Howe"),
|
||||||
|
("Australia/Melbourne", "Australia/Melbourne"),
|
||||||
|
("Australia/NSW", "Australia/NSW"),
|
||||||
|
("Australia/North", "Australia/North"),
|
||||||
|
("Australia/Perth", "Australia/Perth"),
|
||||||
|
("Australia/Queensland", "Australia/Queensland"),
|
||||||
|
("Australia/South", "Australia/South"),
|
||||||
|
("Australia/Sydney", "Australia/Sydney"),
|
||||||
|
("Australia/Tasmania", "Australia/Tasmania"),
|
||||||
|
("Australia/Victoria", "Australia/Victoria"),
|
||||||
|
("Australia/West", "Australia/West"),
|
||||||
|
("Australia/Yancowinna", "Australia/Yancowinna"),
|
||||||
|
("Brazil/Acre", "Brazil/Acre"),
|
||||||
|
("Brazil/DeNoronha", "Brazil/DeNoronha"),
|
||||||
|
("Brazil/East", "Brazil/East"),
|
||||||
|
("Brazil/West", "Brazil/West"),
|
||||||
|
("CET", "CET"),
|
||||||
|
("CST6CDT", "CST6CDT"),
|
||||||
|
("Canada/Atlantic", "Canada/Atlantic"),
|
||||||
|
("Canada/Central", "Canada/Central"),
|
||||||
|
("Canada/Eastern", "Canada/Eastern"),
|
||||||
|
("Canada/Mountain", "Canada/Mountain"),
|
||||||
|
("Canada/Newfoundland", "Canada/Newfoundland"),
|
||||||
|
("Canada/Pacific", "Canada/Pacific"),
|
||||||
|
("Canada/Saskatchewan", "Canada/Saskatchewan"),
|
||||||
|
("Canada/Yukon", "Canada/Yukon"),
|
||||||
|
("Chile/Continental", "Chile/Continental"),
|
||||||
|
("Chile/EasterIsland", "Chile/EasterIsland"),
|
||||||
|
("Cuba", "Cuba"),
|
||||||
|
("EET", "EET"),
|
||||||
|
("EST", "EST"),
|
||||||
|
("EST5EDT", "EST5EDT"),
|
||||||
|
("Egypt", "Egypt"),
|
||||||
|
("Eire", "Eire"),
|
||||||
|
("Etc/GMT", "Etc/GMT"),
|
||||||
|
("Etc/GMT+0", "Etc/GMT+0"),
|
||||||
|
("Etc/GMT+1", "Etc/GMT+1"),
|
||||||
|
("Etc/GMT+10", "Etc/GMT+10"),
|
||||||
|
("Etc/GMT+11", "Etc/GMT+11"),
|
||||||
|
("Etc/GMT+12", "Etc/GMT+12"),
|
||||||
|
("Etc/GMT+2", "Etc/GMT+2"),
|
||||||
|
("Etc/GMT+3", "Etc/GMT+3"),
|
||||||
|
("Etc/GMT+4", "Etc/GMT+4"),
|
||||||
|
("Etc/GMT+5", "Etc/GMT+5"),
|
||||||
|
("Etc/GMT+6", "Etc/GMT+6"),
|
||||||
|
("Etc/GMT+7", "Etc/GMT+7"),
|
||||||
|
("Etc/GMT+8", "Etc/GMT+8"),
|
||||||
|
("Etc/GMT+9", "Etc/GMT+9"),
|
||||||
|
("Etc/GMT-0", "Etc/GMT-0"),
|
||||||
|
("Etc/GMT-1", "Etc/GMT-1"),
|
||||||
|
("Etc/GMT-10", "Etc/GMT-10"),
|
||||||
|
("Etc/GMT-11", "Etc/GMT-11"),
|
||||||
|
("Etc/GMT-12", "Etc/GMT-12"),
|
||||||
|
("Etc/GMT-13", "Etc/GMT-13"),
|
||||||
|
("Etc/GMT-14", "Etc/GMT-14"),
|
||||||
|
("Etc/GMT-2", "Etc/GMT-2"),
|
||||||
|
("Etc/GMT-3", "Etc/GMT-3"),
|
||||||
|
("Etc/GMT-4", "Etc/GMT-4"),
|
||||||
|
("Etc/GMT-5", "Etc/GMT-5"),
|
||||||
|
("Etc/GMT-6", "Etc/GMT-6"),
|
||||||
|
("Etc/GMT-7", "Etc/GMT-7"),
|
||||||
|
("Etc/GMT-8", "Etc/GMT-8"),
|
||||||
|
("Etc/GMT-9", "Etc/GMT-9"),
|
||||||
|
("Etc/GMT0", "Etc/GMT0"),
|
||||||
|
("Etc/Greenwich", "Etc/Greenwich"),
|
||||||
|
("Etc/UCT", "Etc/UCT"),
|
||||||
|
("Etc/UTC", "Etc/UTC"),
|
||||||
|
("Etc/Universal", "Etc/Universal"),
|
||||||
|
("Etc/Zulu", "Etc/Zulu"),
|
||||||
|
("Europe/Amsterdam", "Europe/Amsterdam"),
|
||||||
|
("Europe/Andorra", "Europe/Andorra"),
|
||||||
|
("Europe/Astrakhan", "Europe/Astrakhan"),
|
||||||
|
("Europe/Athens", "Europe/Athens"),
|
||||||
|
("Europe/Belfast", "Europe/Belfast"),
|
||||||
|
("Europe/Belgrade", "Europe/Belgrade"),
|
||||||
|
("Europe/Berlin", "Europe/Berlin"),
|
||||||
|
("Europe/Bratislava", "Europe/Bratislava"),
|
||||||
|
("Europe/Brussels", "Europe/Brussels"),
|
||||||
|
("Europe/Bucharest", "Europe/Bucharest"),
|
||||||
|
("Europe/Budapest", "Europe/Budapest"),
|
||||||
|
("Europe/Busingen", "Europe/Busingen"),
|
||||||
|
("Europe/Chisinau", "Europe/Chisinau"),
|
||||||
|
("Europe/Copenhagen", "Europe/Copenhagen"),
|
||||||
|
("Europe/Dublin", "Europe/Dublin"),
|
||||||
|
("Europe/Gibraltar", "Europe/Gibraltar"),
|
||||||
|
("Europe/Guernsey", "Europe/Guernsey"),
|
||||||
|
("Europe/Helsinki", "Europe/Helsinki"),
|
||||||
|
("Europe/Isle_of_Man", "Europe/Isle_of_Man"),
|
||||||
|
("Europe/Istanbul", "Europe/Istanbul"),
|
||||||
|
("Europe/Jersey", "Europe/Jersey"),
|
||||||
|
("Europe/Kaliningrad", "Europe/Kaliningrad"),
|
||||||
|
("Europe/Kiev", "Europe/Kiev"),
|
||||||
|
("Europe/Kirov", "Europe/Kirov"),
|
||||||
|
("Europe/Kyiv", "Europe/Kyiv"),
|
||||||
|
("Europe/Lisbon", "Europe/Lisbon"),
|
||||||
|
("Europe/Ljubljana", "Europe/Ljubljana"),
|
||||||
|
("Europe/London", "Europe/London"),
|
||||||
|
("Europe/Luxembourg", "Europe/Luxembourg"),
|
||||||
|
("Europe/Madrid", "Europe/Madrid"),
|
||||||
|
("Europe/Malta", "Europe/Malta"),
|
||||||
|
("Europe/Mariehamn", "Europe/Mariehamn"),
|
||||||
|
("Europe/Minsk", "Europe/Minsk"),
|
||||||
|
("Europe/Monaco", "Europe/Monaco"),
|
||||||
|
("Europe/Moscow", "Europe/Moscow"),
|
||||||
|
("Europe/Nicosia", "Europe/Nicosia"),
|
||||||
|
("Europe/Oslo", "Europe/Oslo"),
|
||||||
|
("Europe/Paris", "Europe/Paris"),
|
||||||
|
("Europe/Podgorica", "Europe/Podgorica"),
|
||||||
|
("Europe/Prague", "Europe/Prague"),
|
||||||
|
("Europe/Riga", "Europe/Riga"),
|
||||||
|
("Europe/Rome", "Europe/Rome"),
|
||||||
|
("Europe/Samara", "Europe/Samara"),
|
||||||
|
("Europe/San_Marino", "Europe/San_Marino"),
|
||||||
|
("Europe/Sarajevo", "Europe/Sarajevo"),
|
||||||
|
("Europe/Saratov", "Europe/Saratov"),
|
||||||
|
("Europe/Simferopol", "Europe/Simferopol"),
|
||||||
|
("Europe/Skopje", "Europe/Skopje"),
|
||||||
|
("Europe/Sofia", "Europe/Sofia"),
|
||||||
|
("Europe/Stockholm", "Europe/Stockholm"),
|
||||||
|
("Europe/Tallinn", "Europe/Tallinn"),
|
||||||
|
("Europe/Tirane", "Europe/Tirane"),
|
||||||
|
("Europe/Tiraspol", "Europe/Tiraspol"),
|
||||||
|
("Europe/Ulyanovsk", "Europe/Ulyanovsk"),
|
||||||
|
("Europe/Uzhgorod", "Europe/Uzhgorod"),
|
||||||
|
("Europe/Vaduz", "Europe/Vaduz"),
|
||||||
|
("Europe/Vatican", "Europe/Vatican"),
|
||||||
|
("Europe/Vienna", "Europe/Vienna"),
|
||||||
|
("Europe/Vilnius", "Europe/Vilnius"),
|
||||||
|
("Europe/Volgograd", "Europe/Volgograd"),
|
||||||
|
("Europe/Warsaw", "Europe/Warsaw"),
|
||||||
|
("Europe/Zagreb", "Europe/Zagreb"),
|
||||||
|
("Europe/Zaporozhye", "Europe/Zaporozhye"),
|
||||||
|
("Europe/Zurich", "Europe/Zurich"),
|
||||||
|
("GB", "GB"),
|
||||||
|
("GB-Eire", "GB-Eire"),
|
||||||
|
("GMT", "GMT"),
|
||||||
|
("GMT+0", "GMT+0"),
|
||||||
|
("GMT-0", "GMT-0"),
|
||||||
|
("GMT0", "GMT0"),
|
||||||
|
("Greenwich", "Greenwich"),
|
||||||
|
("HST", "HST"),
|
||||||
|
("Hongkong", "Hongkong"),
|
||||||
|
("Iceland", "Iceland"),
|
||||||
|
("Indian/Antananarivo", "Indian/Antananarivo"),
|
||||||
|
("Indian/Chagos", "Indian/Chagos"),
|
||||||
|
("Indian/Christmas", "Indian/Christmas"),
|
||||||
|
("Indian/Cocos", "Indian/Cocos"),
|
||||||
|
("Indian/Comoro", "Indian/Comoro"),
|
||||||
|
("Indian/Kerguelen", "Indian/Kerguelen"),
|
||||||
|
("Indian/Mahe", "Indian/Mahe"),
|
||||||
|
("Indian/Maldives", "Indian/Maldives"),
|
||||||
|
("Indian/Mauritius", "Indian/Mauritius"),
|
||||||
|
("Indian/Mayotte", "Indian/Mayotte"),
|
||||||
|
("Indian/Reunion", "Indian/Reunion"),
|
||||||
|
("Iran", "Iran"),
|
||||||
|
("Israel", "Israel"),
|
||||||
|
("Jamaica", "Jamaica"),
|
||||||
|
("Japan", "Japan"),
|
||||||
|
("Kwajalein", "Kwajalein"),
|
||||||
|
("Libya", "Libya"),
|
||||||
|
("MET", "MET"),
|
||||||
|
("MST", "MST"),
|
||||||
|
("MST7MDT", "MST7MDT"),
|
||||||
|
("Mexico/BajaNorte", "Mexico/BajaNorte"),
|
||||||
|
("Mexico/BajaSur", "Mexico/BajaSur"),
|
||||||
|
("Mexico/General", "Mexico/General"),
|
||||||
|
("NZ", "NZ"),
|
||||||
|
("NZ-CHAT", "NZ-CHAT"),
|
||||||
|
("Navajo", "Navajo"),
|
||||||
|
("PRC", "PRC"),
|
||||||
|
("PST8PDT", "PST8PDT"),
|
||||||
|
("Pacific/Apia", "Pacific/Apia"),
|
||||||
|
("Pacific/Auckland", "Pacific/Auckland"),
|
||||||
|
("Pacific/Bougainville", "Pacific/Bougainville"),
|
||||||
|
("Pacific/Chatham", "Pacific/Chatham"),
|
||||||
|
("Pacific/Chuuk", "Pacific/Chuuk"),
|
||||||
|
("Pacific/Easter", "Pacific/Easter"),
|
||||||
|
("Pacific/Efate", "Pacific/Efate"),
|
||||||
|
("Pacific/Enderbury", "Pacific/Enderbury"),
|
||||||
|
("Pacific/Fakaofo", "Pacific/Fakaofo"),
|
||||||
|
("Pacific/Fiji", "Pacific/Fiji"),
|
||||||
|
("Pacific/Funafuti", "Pacific/Funafuti"),
|
||||||
|
("Pacific/Galapagos", "Pacific/Galapagos"),
|
||||||
|
("Pacific/Gambier", "Pacific/Gambier"),
|
||||||
|
("Pacific/Guadalcanal", "Pacific/Guadalcanal"),
|
||||||
|
("Pacific/Guam", "Pacific/Guam"),
|
||||||
|
("Pacific/Honolulu", "Pacific/Honolulu"),
|
||||||
|
("Pacific/Johnston", "Pacific/Johnston"),
|
||||||
|
("Pacific/Kanton", "Pacific/Kanton"),
|
||||||
|
("Pacific/Kiritimati", "Pacific/Kiritimati"),
|
||||||
|
("Pacific/Kosrae", "Pacific/Kosrae"),
|
||||||
|
("Pacific/Kwajalein", "Pacific/Kwajalein"),
|
||||||
|
("Pacific/Majuro", "Pacific/Majuro"),
|
||||||
|
("Pacific/Marquesas", "Pacific/Marquesas"),
|
||||||
|
("Pacific/Midway", "Pacific/Midway"),
|
||||||
|
("Pacific/Nauru", "Pacific/Nauru"),
|
||||||
|
("Pacific/Niue", "Pacific/Niue"),
|
||||||
|
("Pacific/Norfolk", "Pacific/Norfolk"),
|
||||||
|
("Pacific/Noumea", "Pacific/Noumea"),
|
||||||
|
("Pacific/Pago_Pago", "Pacific/Pago_Pago"),
|
||||||
|
("Pacific/Palau", "Pacific/Palau"),
|
||||||
|
("Pacific/Pitcairn", "Pacific/Pitcairn"),
|
||||||
|
("Pacific/Pohnpei", "Pacific/Pohnpei"),
|
||||||
|
("Pacific/Ponape", "Pacific/Ponape"),
|
||||||
|
("Pacific/Port_Moresby", "Pacific/Port_Moresby"),
|
||||||
|
("Pacific/Rarotonga", "Pacific/Rarotonga"),
|
||||||
|
("Pacific/Saipan", "Pacific/Saipan"),
|
||||||
|
("Pacific/Samoa", "Pacific/Samoa"),
|
||||||
|
("Pacific/Tahiti", "Pacific/Tahiti"),
|
||||||
|
("Pacific/Tarawa", "Pacific/Tarawa"),
|
||||||
|
("Pacific/Tongatapu", "Pacific/Tongatapu"),
|
||||||
|
("Pacific/Truk", "Pacific/Truk"),
|
||||||
|
("Pacific/Wake", "Pacific/Wake"),
|
||||||
|
("Pacific/Wallis", "Pacific/Wallis"),
|
||||||
|
("Pacific/Yap", "Pacific/Yap"),
|
||||||
|
("Poland", "Poland"),
|
||||||
|
("Portugal", "Portugal"),
|
||||||
|
("ROC", "ROC"),
|
||||||
|
("ROK", "ROK"),
|
||||||
|
("Singapore", "Singapore"),
|
||||||
|
("Turkey", "Turkey"),
|
||||||
|
("UCT", "UCT"),
|
||||||
|
("US/Alaska", "US/Alaska"),
|
||||||
|
("US/Aleutian", "US/Aleutian"),
|
||||||
|
("US/Arizona", "US/Arizona"),
|
||||||
|
("US/Central", "US/Central"),
|
||||||
|
("US/East-Indiana", "US/East-Indiana"),
|
||||||
|
("US/Eastern", "US/Eastern"),
|
||||||
|
("US/Hawaii", "US/Hawaii"),
|
||||||
|
("US/Indiana-Starke", "US/Indiana-Starke"),
|
||||||
|
("US/Michigan", "US/Michigan"),
|
||||||
|
("US/Mountain", "US/Mountain"),
|
||||||
|
("US/Pacific", "US/Pacific"),
|
||||||
|
("US/Samoa", "US/Samoa"),
|
||||||
|
("UTC", "UTC"),
|
||||||
|
("Universal", "Universal"),
|
||||||
|
("W-SU", "W-SU"),
|
||||||
|
("WET", "WET"),
|
||||||
|
("Zulu", "Zulu"),
|
||||||
|
],
|
||||||
|
default="UTC",
|
||||||
|
max_length=255,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
42
bookwyrm/migrations/0172_alter_user_preferred_language.py
Normal file
42
bookwyrm/migrations/0172_alter_user_preferred_language.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Generated by Django 3.2.16 on 2022-12-21 18:06
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0171_alter_user_preferred_timezone"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="user",
|
||||||
|
name="preferred_language",
|
||||||
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
choices=[
|
||||||
|
("en-us", "English"),
|
||||||
|
("ca-es", "Català (Catalan)"),
|
||||||
|
("de-de", "Deutsch (German)"),
|
||||||
|
("es-es", "Español (Spanish)"),
|
||||||
|
("eu-es", "Euskara (Basque)"),
|
||||||
|
("gl-es", "Galego (Galician)"),
|
||||||
|
("it-it", "Italiano (Italian)"),
|
||||||
|
("fi-fi", "Suomi (Finnish)"),
|
||||||
|
("fr-fr", "Français (French)"),
|
||||||
|
("lt-lt", "Lietuvių (Lithuanian)"),
|
||||||
|
("no-no", "Norsk (Norwegian)"),
|
||||||
|
("pl-pl", "Polski (Polish)"),
|
||||||
|
("pt-br", "Português do Brasil (Brazilian Portuguese)"),
|
||||||
|
("pt-pt", "Português Europeu (European Portuguese)"),
|
||||||
|
("ro-ro", "Română (Romanian)"),
|
||||||
|
("sv-se", "Svenska (Swedish)"),
|
||||||
|
("zh-hans", "简体中文 (Simplified Chinese)"),
|
||||||
|
("zh-hant", "繁體中文 (Traditional Chinese)"),
|
||||||
|
],
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,8 +1,6 @@
|
||||||
""" database schema for info about authors """
|
""" database schema for info about authors """
|
||||||
import re
|
import re
|
||||||
from django.contrib.postgres.indexes import GinIndex
|
from django.contrib.postgres.indexes import GinIndex
|
||||||
from django.core.cache import cache
|
|
||||||
from django.core.cache.utils import make_template_fragment_key
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
|
@ -37,16 +35,7 @@ class Author(BookDataModel):
|
||||||
bio = fields.HtmlField(null=True, blank=True)
|
bio = fields.HtmlField(null=True, blank=True)
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
"""clear related template caches"""
|
"""normalize isni format"""
|
||||||
# clear template caches
|
|
||||||
if self.id:
|
|
||||||
cache_keys = [
|
|
||||||
make_template_fragment_key("titleby", [book])
|
|
||||||
for book in self.book_set.values_list("id", flat=True)
|
|
||||||
]
|
|
||||||
cache.delete_many(cache_keys)
|
|
||||||
|
|
||||||
# normalize isni format
|
|
||||||
if self.isni:
|
if self.isni:
|
||||||
self.isni = re.sub(r"\s", "", self.isni)
|
self.isni = re.sub(r"\s", "", self.isni)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import re
|
||||||
from django.contrib.postgres.search import SearchVectorField
|
from django.contrib.postgres.search import SearchVectorField
|
||||||
from django.contrib.postgres.indexes import GinIndex
|
from django.contrib.postgres.indexes import GinIndex
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.cache.utils import make_template_fragment_key
|
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
@ -208,10 +207,6 @@ class Book(BookDataModel):
|
||||||
if not isinstance(self, Edition) and not isinstance(self, Work):
|
if not isinstance(self, Edition) and not isinstance(self, Work):
|
||||||
raise ValueError("Books should be added as Editions or Works")
|
raise ValueError("Books should be added as Editions or Works")
|
||||||
|
|
||||||
# clear template caches
|
|
||||||
cache_key = make_template_fragment_key("titleby", [self.id])
|
|
||||||
cache.delete(cache_key)
|
|
||||||
|
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
|
||||||
def get_remote_id(self):
|
def get_remote_id(self):
|
||||||
|
|
|
@ -19,7 +19,7 @@ from bookwyrm.models import (
|
||||||
Review,
|
Review,
|
||||||
ReviewRating,
|
ReviewRating,
|
||||||
)
|
)
|
||||||
from bookwyrm.tasks import app, LOW
|
from bookwyrm.tasks import app, LOW, IMPORTS
|
||||||
from .fields import PrivacyLevels
|
from .fields import PrivacyLevels
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,8 +74,7 @@ class ImportJob(models.Model):
|
||||||
task = start_import_task.delay(self.id)
|
task = start_import_task.delay(self.id)
|
||||||
self.task_id = task.id
|
self.task_id = task.id
|
||||||
|
|
||||||
self.status = "active"
|
self.save(update_fields=["task_id"])
|
||||||
self.save(update_fields=["status", "task_id"])
|
|
||||||
|
|
||||||
def complete_job(self):
|
def complete_job(self):
|
||||||
"""Report that the job has completed"""
|
"""Report that the job has completed"""
|
||||||
|
@ -328,10 +327,12 @@ class ImportItem(models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.task(queue=LOW)
|
@app.task(queue=IMPORTS)
|
||||||
def start_import_task(job_id):
|
def start_import_task(job_id):
|
||||||
"""trigger the child tasks for each row"""
|
"""trigger the child tasks for each row"""
|
||||||
job = ImportJob.objects.get(id=job_id)
|
job = ImportJob.objects.get(id=job_id)
|
||||||
|
job.status = "active"
|
||||||
|
job.save(update_fields=["status"])
|
||||||
# don't start the job if it was stopped from the UI
|
# don't start the job if it was stopped from the UI
|
||||||
if job.complete:
|
if job.complete:
|
||||||
return
|
return
|
||||||
|
@ -345,7 +346,7 @@ def start_import_task(job_id):
|
||||||
job.save()
|
job.save()
|
||||||
|
|
||||||
|
|
||||||
@app.task(queue=LOW)
|
@app.task(queue=IMPORTS)
|
||||||
def import_item_task(item_id):
|
def import_item_task(item_id):
|
||||||
"""resolve a row into a book"""
|
"""resolve a row into a book"""
|
||||||
item = ImportItem.objects.get(id=item_id)
|
item = ImportItem.objects.get(id=item_id)
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.db import models, transaction, IntegrityError
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
|
from bookwyrm.tasks import HIGH
|
||||||
from .activitypub_mixin import ActivitypubMixin, ActivityMixin
|
from .activitypub_mixin import ActivitypubMixin, ActivityMixin
|
||||||
from .activitypub_mixin import generate_activity
|
from .activitypub_mixin import generate_activity
|
||||||
from .base_model import BookWyrmModel
|
from .base_model import BookWyrmModel
|
||||||
|
@ -139,8 +140,9 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||||
)
|
)
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
# a local user is following a remote user
|
||||||
if broadcast and self.user_subject.local and not self.user_object.local:
|
if broadcast and self.user_subject.local and not self.user_object.local:
|
||||||
self.broadcast(self.to_activity(), self.user_subject)
|
self.broadcast(self.to_activity(), self.user_subject, queue=HIGH)
|
||||||
|
|
||||||
if self.user_object.local:
|
if self.user_object.local:
|
||||||
manually_approves = self.user_object.manually_approves_followers
|
manually_approves = self.user_object.manually_approves_followers
|
||||||
|
@ -157,13 +159,14 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||||
def accept(self, broadcast_only=False):
|
def accept(self, broadcast_only=False):
|
||||||
"""turn this request into the real deal"""
|
"""turn this request into the real deal"""
|
||||||
user = self.user_object
|
user = self.user_object
|
||||||
|
# broadcast when accepting a remote request
|
||||||
if not self.user_subject.local:
|
if not self.user_subject.local:
|
||||||
activity = activitypub.Accept(
|
activity = activitypub.Accept(
|
||||||
id=self.get_accept_reject_id(status="accepts"),
|
id=self.get_accept_reject_id(status="accepts"),
|
||||||
actor=self.user_object.remote_id,
|
actor=self.user_object.remote_id,
|
||||||
object=self.to_activity(),
|
object=self.to_activity(),
|
||||||
).serialize()
|
).serialize()
|
||||||
self.broadcast(activity, user)
|
self.broadcast(activity, user, queue=HIGH)
|
||||||
if broadcast_only:
|
if broadcast_only:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -180,7 +183,7 @@ class UserFollowRequest(ActivitypubMixin, UserRelationship):
|
||||||
actor=self.user_object.remote_id,
|
actor=self.user_object.remote_id,
|
||||||
object=self.to_activity(),
|
object=self.to_activity(),
|
||||||
).serialize()
|
).serialize()
|
||||||
self.broadcast(activity, self.user_object)
|
self.broadcast(activity, self.user_object, queue=HIGH)
|
||||||
|
|
||||||
self.delete()
|
self.delete()
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.utils import timezone
|
||||||
|
|
||||||
from bookwyrm import activitypub
|
from bookwyrm import activitypub
|
||||||
from bookwyrm.settings import DOMAIN
|
from bookwyrm.settings import DOMAIN
|
||||||
|
from bookwyrm.tasks import LOW
|
||||||
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
|
from .activitypub_mixin import CollectionItemMixin, OrderedCollectionMixin
|
||||||
from .base_model import BookWyrmModel
|
from .base_model import BookWyrmModel
|
||||||
from . import fields
|
from . import fields
|
||||||
|
@ -39,9 +40,9 @@ class Shelf(OrderedCollectionMixin, BookWyrmModel):
|
||||||
|
|
||||||
activity_serializer = activitypub.Shelf
|
activity_serializer = activitypub.Shelf
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, priority=LOW, **kwargs):
|
||||||
"""set the identifier"""
|
"""set the identifier"""
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, priority=priority, **kwargs)
|
||||||
if not self.identifier:
|
if not self.identifier:
|
||||||
self.identifier = self.get_identifier()
|
self.identifier = self.get_identifier()
|
||||||
super().save(*args, **kwargs, broadcast=False)
|
super().save(*args, **kwargs, broadcast=False)
|
||||||
|
@ -99,7 +100,7 @@ class ShelfBook(CollectionItemMixin, BookWyrmModel):
|
||||||
activity_serializer = activitypub.ShelfItem
|
activity_serializer = activitypub.ShelfItem
|
||||||
collection_field = "shelf"
|
collection_field = "shelf"
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, priority=LOW, **kwargs):
|
||||||
if not self.user:
|
if not self.user:
|
||||||
self.user = self.shelf.user
|
self.user = self.shelf.user
|
||||||
if self.id and self.user.local:
|
if self.id and self.user.local:
|
||||||
|
@ -110,7 +111,7 @@ class ShelfBook(CollectionItemMixin, BookWyrmModel):
|
||||||
for book in self.book.parent_work.editions.all()
|
for book in self.book.parent_work.editions.all()
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, priority=priority, **kwargs)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
if self.id and self.user.local:
|
if self.id and self.user.local:
|
||||||
|
|
|
@ -526,6 +526,11 @@ def preview_image(instance, *args, **kwargs):
|
||||||
"""create preview images when user is updated"""
|
"""create preview images when user is updated"""
|
||||||
if not ENABLE_PREVIEW_IMAGES:
|
if not ENABLE_PREVIEW_IMAGES:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# don't call the task for remote users
|
||||||
|
if not instance.local:
|
||||||
|
return
|
||||||
|
|
||||||
changed_fields = instance.field_tracker.changed()
|
changed_fields = instance.field_tracker.changed()
|
||||||
|
|
||||||
if len(changed_fields) > 0:
|
if len(changed_fields) > 0:
|
||||||
|
|
|
@ -71,20 +71,29 @@ def get_wrapped_text(text, font, content_width):
|
||||||
low = 0
|
low = 0
|
||||||
high = len(text)
|
high = len(text)
|
||||||
|
|
||||||
|
draw = ImageDraw.Draw(Image.new("RGB", (100, 100)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# ideal length is determined via binary search
|
# ideal length is determined via binary search
|
||||||
while low < high:
|
while low < high:
|
||||||
mid = math.floor(low + high)
|
mid = math.floor(low + high)
|
||||||
wrapped_text = textwrap.fill(text, width=mid)
|
wrapped_text = textwrap.fill(text, width=mid)
|
||||||
width = font.getsize_multiline(wrapped_text)[0]
|
|
||||||
|
left, top, right, bottom = draw.multiline_textbbox(
|
||||||
|
(0, 0), wrapped_text, font=font
|
||||||
|
)
|
||||||
|
width = right - left
|
||||||
|
height = bottom - top
|
||||||
|
|
||||||
if width < content_width:
|
if width < content_width:
|
||||||
low = mid
|
low = mid
|
||||||
else:
|
else:
|
||||||
high = mid - 1
|
high = mid - 1
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
wrapped_text = text
|
wrapped_text = text
|
||||||
|
height = 26
|
||||||
|
|
||||||
return wrapped_text
|
return wrapped_text, height
|
||||||
|
|
||||||
|
|
||||||
def generate_texts_layer(texts, content_width):
|
def generate_texts_layer(texts, content_width):
|
||||||
|
@ -100,47 +109,53 @@ def generate_texts_layer(texts, content_width):
|
||||||
text_y = 0
|
text_y = 0
|
||||||
|
|
||||||
if "text_zero" in texts and texts["text_zero"]:
|
if "text_zero" in texts and texts["text_zero"]:
|
||||||
# Text one (Book title)
|
# Text zero (Site preview domain name)
|
||||||
text_zero = get_wrapped_text(texts["text_zero"], font_text_zero, content_width)
|
text_zero, text_height = get_wrapped_text(
|
||||||
|
texts["text_zero"], font_text_zero, content_width
|
||||||
|
)
|
||||||
|
|
||||||
text_layer_draw.multiline_text(
|
text_layer_draw.multiline_text(
|
||||||
(0, text_y), text_zero, font=font_text_zero, fill=TEXT_COLOR
|
(0, text_y), text_zero, font=font_text_zero, fill=TEXT_COLOR
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
text_y = text_y + font_text_zero.getsize_multiline(text_zero)[1] + 16
|
text_y = text_y + text_height + 16
|
||||||
except (AttributeError, IndexError):
|
except (AttributeError, IndexError):
|
||||||
text_y = text_y + 26
|
text_y = text_y + 26
|
||||||
|
|
||||||
if "text_one" in texts and texts["text_one"]:
|
if "text_one" in texts and texts["text_one"]:
|
||||||
# Text one (Book title)
|
# Text one (Book/Site title, User display name)
|
||||||
text_one = get_wrapped_text(texts["text_one"], font_text_one, content_width)
|
text_one, text_height = get_wrapped_text(
|
||||||
|
texts["text_one"], font_text_one, content_width
|
||||||
|
)
|
||||||
|
|
||||||
text_layer_draw.multiline_text(
|
text_layer_draw.multiline_text(
|
||||||
(0, text_y), text_one, font=font_text_one, fill=TEXT_COLOR
|
(0, text_y), text_one, font=font_text_one, fill=TEXT_COLOR
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
text_y = text_y + font_text_one.getsize_multiline(text_one)[1] + 16
|
text_y = text_y + text_height + 16
|
||||||
except (AttributeError, IndexError):
|
except (AttributeError, IndexError):
|
||||||
text_y = text_y + 26
|
text_y = text_y + 26
|
||||||
|
|
||||||
if "text_two" in texts and texts["text_two"]:
|
if "text_two" in texts and texts["text_two"]:
|
||||||
# Text one (Book subtitle)
|
# Text two (Book subtitle)
|
||||||
text_two = get_wrapped_text(texts["text_two"], font_text_two, content_width)
|
text_two, text_height = get_wrapped_text(
|
||||||
|
texts["text_two"], font_text_two, content_width
|
||||||
|
)
|
||||||
|
|
||||||
text_layer_draw.multiline_text(
|
text_layer_draw.multiline_text(
|
||||||
(0, text_y), text_two, font=font_text_two, fill=TEXT_COLOR
|
(0, text_y), text_two, font=font_text_two, fill=TEXT_COLOR
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
text_y = text_y + font_text_one.getsize_multiline(text_two)[1] + 16
|
text_y = text_y + text_height + 16
|
||||||
except (AttributeError, IndexError):
|
except (AttributeError, IndexError):
|
||||||
text_y = text_y + 26
|
text_y = text_y + 26
|
||||||
|
|
||||||
if "text_three" in texts and texts["text_three"]:
|
if "text_three" in texts and texts["text_three"]:
|
||||||
# Text three (Book authors)
|
# Text three (Book authors, Site tagline, User address)
|
||||||
text_three = get_wrapped_text(
|
text_three, _ = get_wrapped_text(
|
||||||
texts["text_three"], font_text_three, content_width
|
texts["text_three"], font_text_three, content_width
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -172,7 +187,7 @@ def generate_instance_layer(content_width):
|
||||||
instance_text_x = 0
|
instance_text_x = 0
|
||||||
|
|
||||||
if logo_img:
|
if logo_img:
|
||||||
logo_img.thumbnail((50, 50), Image.ANTIALIAS)
|
logo_img.thumbnail((50, 50), Image.Resampling.LANCZOS)
|
||||||
|
|
||||||
instance_layer.paste(logo_img, (0, 0))
|
instance_layer.paste(logo_img, (0, 0))
|
||||||
|
|
||||||
|
@ -183,7 +198,7 @@ def generate_instance_layer(content_width):
|
||||||
(instance_text_x, 10), site.name, font=font_instance, fill=TEXT_COLOR
|
(instance_text_x, 10), site.name, font=font_instance, fill=TEXT_COLOR
|
||||||
)
|
)
|
||||||
|
|
||||||
line_width = 50 + 10 + font_instance.getsize(site.name)[0]
|
line_width = 50 + 10 + round(font_instance.getlength(site.name))
|
||||||
|
|
||||||
line_layer = Image.new(
|
line_layer = Image.new(
|
||||||
"RGBA", (line_width, 2), color=(*(ImageColor.getrgb(TEXT_COLOR)), 50)
|
"RGBA", (line_width, 2), color=(*(ImageColor.getrgb(TEXT_COLOR)), 50)
|
||||||
|
@ -253,10 +268,12 @@ def generate_default_inner_img():
|
||||||
default_cover_draw = ImageDraw.Draw(default_cover)
|
default_cover_draw = ImageDraw.Draw(default_cover)
|
||||||
|
|
||||||
text = "no image :("
|
text = "no image :("
|
||||||
text_dimensions = font_cover.getsize(text)
|
text_left, text_top, text_right, text_bottom = font_cover.getbbox(text)
|
||||||
|
text_width, text_height = text_right - text_left, text_bottom - text_top
|
||||||
|
|
||||||
text_coords = (
|
text_coords = (
|
||||||
math.floor((inner_img_width - text_dimensions[0]) / 2),
|
math.floor((inner_img_width - text_width) / 2),
|
||||||
math.floor((inner_img_height - text_dimensions[1]) / 2),
|
math.floor((inner_img_height - text_height) / 2),
|
||||||
)
|
)
|
||||||
default_cover_draw.text(text_coords, text, font=font_cover, fill="white")
|
default_cover_draw.text(text_coords, text, font=font_cover, fill="white")
|
||||||
|
|
||||||
|
@ -273,7 +290,9 @@ def generate_preview_image(
|
||||||
# Cover
|
# Cover
|
||||||
try:
|
try:
|
||||||
inner_img_layer = Image.open(picture)
|
inner_img_layer = Image.open(picture)
|
||||||
inner_img_layer.thumbnail((inner_img_width, inner_img_height), Image.ANTIALIAS)
|
inner_img_layer.thumbnail(
|
||||||
|
(inner_img_width, inner_img_height), Image.Resampling.LANCZOS
|
||||||
|
)
|
||||||
color_thief = ColorThief(picture)
|
color_thief = ColorThief(picture)
|
||||||
dominant_color = color_thief.get_color(quality=1)
|
dominant_color = color_thief.get_color(quality=1)
|
||||||
except: # pylint: disable=bare-except
|
except: # pylint: disable=bare-except
|
||||||
|
@ -453,12 +472,15 @@ def generate_edition_preview_image_task(book_id):
|
||||||
|
|
||||||
@app.task(queue=LOW)
|
@app.task(queue=LOW)
|
||||||
def generate_user_preview_image_task(user_id):
|
def generate_user_preview_image_task(user_id):
|
||||||
"""generate preview_image for a book"""
|
"""generate preview_image for a user"""
|
||||||
if not settings.ENABLE_PREVIEW_IMAGES:
|
if not settings.ENABLE_PREVIEW_IMAGES:
|
||||||
return
|
return
|
||||||
|
|
||||||
user = models.User.objects.get(id=user_id)
|
user = models.User.objects.get(id=user_id)
|
||||||
|
|
||||||
|
if not user.local:
|
||||||
|
return
|
||||||
|
|
||||||
texts = {
|
texts = {
|
||||||
"text_one": user.display_name,
|
"text_one": user.display_name,
|
||||||
"text_three": f"@{user.localname}@{settings.DOMAIN}",
|
"text_three": f"@{user.localname}@{settings.DOMAIN}",
|
||||||
|
@ -472,3 +494,25 @@ def generate_user_preview_image_task(user_id):
|
||||||
image = generate_preview_image(texts=texts, picture=avatar)
|
image = generate_preview_image(texts=texts, picture=avatar)
|
||||||
|
|
||||||
save_and_cleanup(image, instance=user)
|
save_and_cleanup(image, instance=user)
|
||||||
|
|
||||||
|
|
||||||
|
@app.task(queue=LOW)
|
||||||
|
def remove_user_preview_image_task(user_id):
|
||||||
|
"""remove preview_image for a user"""
|
||||||
|
if not settings.ENABLE_PREVIEW_IMAGES:
|
||||||
|
return
|
||||||
|
|
||||||
|
user = models.User.objects.get(id=user_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
file_name = user.preview_image.name
|
||||||
|
except ValueError:
|
||||||
|
file_name = None
|
||||||
|
|
||||||
|
# Delete image in model
|
||||||
|
user.preview_image.delete(save=False)
|
||||||
|
user.save(broadcast=False, update_fields=["preview_image"])
|
||||||
|
|
||||||
|
# Delete image file
|
||||||
|
if file_name and default_storage.exists(file_name):
|
||||||
|
default_storage.delete(file_name)
|
||||||
|
|
|
@ -193,7 +193,8 @@ STATICFILES_FINDERS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
SASS_PROCESSOR_INCLUDE_FILE_PATTERN = r"^.+\.[s]{0,1}(?:a|c)ss$"
|
SASS_PROCESSOR_INCLUDE_FILE_PATTERN = r"^.+\.[s]{0,1}(?:a|c)ss$"
|
||||||
SASS_PROCESSOR_ENABLED = True
|
# when debug is disabled, make sure to compile themes once with `./bw-dev compile_themes`
|
||||||
|
SASS_PROCESSOR_ENABLED = DEBUG
|
||||||
|
|
||||||
# minify css is production but not dev
|
# minify css is production but not dev
|
||||||
if not DEBUG:
|
if not DEBUG:
|
||||||
|
@ -287,6 +288,7 @@ LANGUAGES = [
|
||||||
("ca-es", _("Català (Catalan)")),
|
("ca-es", _("Català (Catalan)")),
|
||||||
("de-de", _("Deutsch (German)")),
|
("de-de", _("Deutsch (German)")),
|
||||||
("es-es", _("Español (Spanish)")),
|
("es-es", _("Español (Spanish)")),
|
||||||
|
("eu-es", _("Euskara (Basque)")),
|
||||||
("gl-es", _("Galego (Galician)")),
|
("gl-es", _("Galego (Galician)")),
|
||||||
("it-it", _("Italiano (Italian)")),
|
("it-it", _("Italiano (Italian)")),
|
||||||
("fi-fi", _("Suomi (Finnish)")),
|
("fi-fi", _("Suomi (Finnish)")),
|
||||||
|
|
|
@ -17,7 +17,7 @@ def create_key_pair():
|
||||||
random_generator = Random.new().read
|
random_generator = Random.new().read
|
||||||
key = RSA.generate(1024, random_generator)
|
key = RSA.generate(1024, random_generator)
|
||||||
private_key = key.export_key().decode("utf8")
|
private_key = key.export_key().decode("utf8")
|
||||||
public_key = key.publickey().export_key().decode("utf8")
|
public_key = key.public_key().export_key().decode("utf8")
|
||||||
|
|
||||||
return private_key, public_key
|
return private_key, public_key
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,53 @@
|
||||||
|
.summary-on-open {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.navbar-menu {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 1rem;
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navbar-dropdown {
|
||||||
|
&[open] {
|
||||||
|
.summary-on-open {
|
||||||
|
display: initial;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3rem;
|
||||||
|
z-index: 31;
|
||||||
|
background-color: $dropdown-content-background-color;
|
||||||
|
padding: 1rem 1.75rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
padding-top: 0;
|
||||||
|
top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-content {
|
||||||
|
padding-top: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-item {
|
||||||
|
// see ../components/_details.scss :: Navbar details
|
||||||
|
padding-right: 1.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,4 +46,16 @@
|
||||||
document
|
document
|
||||||
.querySelectorAll("[data-remove]")
|
.querySelectorAll("[data-remove]")
|
||||||
.forEach((node) => node.addEventListener("click", removeInput));
|
.forEach((node) => node.addEventListener("click", removeInput));
|
||||||
|
|
||||||
|
// Get the element, add a keypress listener...
|
||||||
|
document.getElementById("subjects").addEventListener("keypress", function (e) {
|
||||||
|
// e.target is the element where it listens!
|
||||||
|
// if e.target is input field within the "subjects" div, do stuff
|
||||||
|
if (e.target && e.target.nodeName == "INPUT") {
|
||||||
|
// Item found, prevent default
|
||||||
|
if (event.keyCode == 13) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -14,3 +14,5 @@ app = Celery(
|
||||||
LOW = "low_priority"
|
LOW = "low_priority"
|
||||||
MEDIUM = "medium_priority"
|
MEDIUM = "medium_priority"
|
||||||
HIGH = "high_priority"
|
HIGH = "high_priority"
|
||||||
|
# import items get their own queue because they're such a pain in the ass
|
||||||
|
IMPORTS = "imports"
|
||||||
|
|
|
@ -10,8 +10,9 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block about_content %}
|
{% block about_content %}
|
||||||
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
{# seven day cache #}
|
{# seven day cache #}
|
||||||
{% cache 604800 about_page_superlatives %}
|
{% cache 604800 about_page_superlatives LANGUAGE_CODE %}
|
||||||
|
|
||||||
{% get_book_superlatives as superlatives %}
|
{% get_book_superlatives as superlatives %}
|
||||||
<section class=" pb-4">
|
<section class=" pb-4">
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
{% include 'snippets/form_errors.html' with errors_list=form.languages.errors id="desc_languages" %}
|
{% include 'snippets/form_errors.html' with errors_list=form.languages.errors id="desc_languages" %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field" id="subjects">
|
||||||
<label class="label" for="id_add_subjects">
|
<label class="label" for="id_add_subjects">
|
||||||
{% trans "Subjects:" %}
|
{% trans "Subjects:" %}
|
||||||
</label>
|
</label>
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
{% with user_path=status.user.local_path username=status.user.display_name book_path=book.local_path book_title=book|book_title %}
|
{% with user_path=status.user.local_path username=status.user.display_name book_path=book.local_path book_title=book|book_title %}
|
||||||
|
|
||||||
{% if status.status_type == 'GeneratedNote' %}
|
{% if status.status_type == 'GeneratedNote' %}
|
||||||
{% if status.content == 'wants to read' %}
|
{% if status.content == 'wants to read' or status.content == '<p>wants to read</p>' %}
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
<a href="{{ user_path}}">{{ username }}</a> wants to read <a href="{{ book_path }}">{{ book_title }}</a>
|
<a href="{{ user_path}}">{{ username }}</a> wants to read <a href="{{ book_path }}">{{ book_title }}</a>
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if status.content == 'finished reading' %}
|
{% if finished reading or status.content == '<p>finished reading</p>' %}
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
<a href="{{ user_path}}">{{ username }}</a> finished reading <a href="{{ book_path }}">{{ book_title }}</a>
|
<a href="{{ user_path}}">{{ username }}</a> finished reading <a href="{{ book_path }}">{{ book_title }}</a>
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if status.content == 'started reading' %}
|
{% if started reading or status.content == '<p>started reading</p>' %}
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
<a href="{{ user_path}}">{{ username }}</a> started reading <a href="{{ book_path }}">{{ book_title }}</a>
|
<a href="{{ user_path}}">{{ username }}</a> started reading <a href="{{ book_path }}">{{ book_title }}</a>
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
|
@ -38,3 +38,4 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if not job.complete and show_progress %}
|
{% if job.status == "active" and show_progress %}
|
||||||
<div class="box is-processing">
|
<div class="box is-processing">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<span class="icon icon-spinner is-pulled-left" aria-hidden="true"></span>
|
<span class="icon icon-spinner is-pulled-left" aria-hidden="true"></span>
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% get_current_language as LANGUAGE_CODE %}
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
{% cache 60 * 60 LANGUAGE_CODE %}
|
{# 1 hour cache #}
|
||||||
|
{% cache 3600 landing LANGUAGE_CODE %}
|
||||||
{% get_landing_books as books %}
|
{% get_landing_books as books %}
|
||||||
<section class="tile is-ancestor">
|
<section class="tile is-ancestor">
|
||||||
<div class="tile is-vertical is-6">
|
<div class="tile is-vertical is-6">
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.edit_instance_settings %}
|
{% if perms.bookwyrm.edit_instance_settings %}
|
||||||
<h2 class="menu-label">{% trans "System" %}</h2>
|
<h2 class="menu-label">{% trans "System" %}</h2>
|
||||||
<ul class="menu-list">
|
<ul class="menu-list">
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
{% trans "Copy the theme file into the <code>bookwyrm/static/css/themes</code> directory on your server from the command line." %}
|
{% trans "Copy the theme file into the <code>bookwyrm/static/css/themes</code> directory on your server from the command line." %}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{% trans "Run <code>./bw-dev collectstatic</code>." %}
|
{% trans "Run <code>./bw-dev compile_themes</code> and <code>./bw-dev collectstatic</code>." %}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{% trans "Add the file name using the form below to make it available in the application interface." %}
|
{% trans "Add the file name using the form below to make it available in the application interface." %}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
|
|
||||||
{% get_current_language as LANGUAGE_CODE %}
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
{# 6 month cache #}
|
{# 10 second cache #}
|
||||||
{% cache 15552000 titleby LANGUAGE_CODE book.id %}
|
{% cache 10 titleby LANGUAGE_CODE book.id %}
|
||||||
|
|
||||||
{% if book.authors.exists %}
|
{% if book.authors.exists %}
|
||||||
{% blocktrans trimmed with path=book.local_path title=book|book_title %}
|
{% blocktrans trimmed with path=book.local_path title=book|book_title %}
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
<span class="ml-2">{{ request.user.display_name }}</span>
|
<span class="ml-2">{{ request.user.display_name }}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="icon icon-arrow-down is-hidden-mobile" aria-hidden="true"></span>
|
<span class="icon icon-arrow-down is-hidden-mobile" aria-hidden="true"></span>
|
||||||
|
<span class="summary-on-open">
|
||||||
|
<span class="icon icon-arrow-left is-small" aria-hidden="true"></span>
|
||||||
|
{% trans "Back" %}
|
||||||
|
</span>
|
||||||
</summary>
|
</summary>
|
||||||
|
|
||||||
<div class="dropdown-menu">
|
<div class="dropdown-menu">
|
||||||
|
|
|
@ -14,6 +14,7 @@ from bookwyrm.preview_images import (
|
||||||
generate_edition_preview_image_task,
|
generate_edition_preview_image_task,
|
||||||
generate_user_preview_image_task,
|
generate_user_preview_image_task,
|
||||||
generate_preview_image,
|
generate_preview_image,
|
||||||
|
remove_user_preview_image_task,
|
||||||
save_and_cleanup,
|
save_and_cleanup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,6 +47,37 @@ class PreviewImages(TestCase):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.remote_user = models.User.objects.create_user(
|
||||||
|
"rat",
|
||||||
|
"rat@rat.com",
|
||||||
|
"ratword",
|
||||||
|
local=False,
|
||||||
|
remote_id="https://example.com/users/rat",
|
||||||
|
inbox="https://example.com/users/rat/inbox",
|
||||||
|
outbox="https://example.com/users/rat/outbox",
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.remote_user_with_preview = models.User.objects.create_user(
|
||||||
|
"badger@your.domain.here",
|
||||||
|
"badger@badger.com",
|
||||||
|
"badgeword",
|
||||||
|
local=False,
|
||||||
|
remote_id="https://example.com/users/badger",
|
||||||
|
inbox="https://example.com/users/badger/inbox",
|
||||||
|
outbox="https://example.com/users/badger/outbox",
|
||||||
|
avatar=SimpleUploadedFile(
|
||||||
|
avatar_file,
|
||||||
|
open(avatar_file, "rb").read(),
|
||||||
|
content_type="image/jpeg",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
self.work = models.Work.objects.create(title="Test Work")
|
self.work = models.Work.objects.create(title="Test Work")
|
||||||
self.edition = models.Edition.objects.create(
|
self.edition = models.Edition.objects.create(
|
||||||
title="Example Edition",
|
title="Example Edition",
|
||||||
|
@ -122,6 +154,14 @@ class PreviewImages(TestCase):
|
||||||
self.local_user.preview_image.height, settings.PREVIEW_IMG_HEIGHT
|
self.local_user.preview_image.height, settings.PREVIEW_IMG_HEIGHT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_remote_user_preview(self, *args, **kwargs):
|
||||||
|
"""a remote user doesn’t get a user preview"""
|
||||||
|
generate_user_preview_image_task(self.remote_user.id)
|
||||||
|
|
||||||
|
self.remote_user.refresh_from_db()
|
||||||
|
|
||||||
|
self.assertFalse(self.remote_user.preview_image)
|
||||||
|
|
||||||
def test_generate_user_preview_images_task(self, *args, **kwargs):
|
def test_generate_user_preview_images_task(self, *args, **kwargs):
|
||||||
"""test task's external calls"""
|
"""test task's external calls"""
|
||||||
with patch("bookwyrm.preview_images.generate_preview_image") as generate_mock:
|
with patch("bookwyrm.preview_images.generate_preview_image") as generate_mock:
|
||||||
|
@ -129,3 +169,11 @@ class PreviewImages(TestCase):
|
||||||
args = generate_mock.call_args.kwargs
|
args = generate_mock.call_args.kwargs
|
||||||
self.assertEqual(args["texts"]["text_one"], "possum")
|
self.assertEqual(args["texts"]["text_one"], "possum")
|
||||||
self.assertEqual(args["texts"]["text_three"], f"@possum@{settings.DOMAIN}")
|
self.assertEqual(args["texts"]["text_three"], f"@possum@{settings.DOMAIN}")
|
||||||
|
|
||||||
|
def test_remove_user_preview_image_task(self, *args, **kwargs):
|
||||||
|
"""you can delete the preview image for a (remote) user"""
|
||||||
|
remove_user_preview_image_task(self.remote_user_with_preview.id)
|
||||||
|
|
||||||
|
self.remote_user_with_preview.refresh_from_db()
|
||||||
|
|
||||||
|
self.assertFalse(self.remote_user_with_preview.preview_image)
|
||||||
|
|
|
@ -63,7 +63,7 @@ class TransactionInboxCreate(TransactionTestCase):
|
||||||
|
|
||||||
with patch("bookwyrm.activitystreams.add_status_task.apply_async") as mock:
|
with patch("bookwyrm.activitystreams.add_status_task.apply_async") as mock:
|
||||||
views.inbox.activity_task(activity)
|
views.inbox.activity_task(activity)
|
||||||
self.assertEqual(mock.call_count, 2)
|
self.assertEqual(mock.call_count, 0)
|
||||||
|
|
||||||
|
|
||||||
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
||||||
|
|
12
bw-dev
12
bw-dev
|
@ -92,6 +92,7 @@ case "$CMD" in
|
||||||
migrate
|
migrate
|
||||||
migrate django_celery_beat
|
migrate django_celery_beat
|
||||||
initdb
|
initdb
|
||||||
|
runweb python manage.py compile_themes
|
||||||
runweb python manage.py collectstatic --no-input
|
runweb python manage.py collectstatic --no-input
|
||||||
admin_code
|
admin_code
|
||||||
;;
|
;;
|
||||||
|
@ -122,6 +123,9 @@ case "$CMD" in
|
||||||
prod_error
|
prod_error
|
||||||
runweb pytest -n 3 --cov-report term-missing "$@"
|
runweb pytest -n 3 --cov-report term-missing "$@"
|
||||||
;;
|
;;
|
||||||
|
compile_themes)
|
||||||
|
runweb python manage.py compile_themes
|
||||||
|
;;
|
||||||
collectstatic)
|
collectstatic)
|
||||||
runweb python manage.py collectstatic --no-input
|
runweb python manage.py collectstatic --no-input
|
||||||
;;
|
;;
|
||||||
|
@ -138,6 +142,7 @@ case "$CMD" in
|
||||||
git checkout l10n_main locale/ca_ES
|
git checkout l10n_main locale/ca_ES
|
||||||
git checkout l10n_main locale/de_DE
|
git checkout l10n_main locale/de_DE
|
||||||
git checkout l10n_main locale/es_ES
|
git checkout l10n_main locale/es_ES
|
||||||
|
git checkout l10n_main locale/eu_ES
|
||||||
git checkout l10n_main locale/fi_FI
|
git checkout l10n_main locale/fi_FI
|
||||||
git checkout l10n_main locale/fr_FR
|
git checkout l10n_main locale/fr_FR
|
||||||
git checkout l10n_main locale/gl_ES
|
git checkout l10n_main locale/gl_ES
|
||||||
|
@ -203,6 +208,7 @@ case "$CMD" in
|
||||||
docker-compose build
|
docker-compose build
|
||||||
# ./update.sh
|
# ./update.sh
|
||||||
runweb python manage.py migrate
|
runweb python manage.py migrate
|
||||||
|
runweb python manage.py compile_themes
|
||||||
runweb python manage.py collectstatic --no-input
|
runweb python manage.py collectstatic --no-input
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
docker-compose restart web
|
docker-compose restart web
|
||||||
|
@ -223,6 +229,9 @@ case "$CMD" in
|
||||||
generate_preview_images)
|
generate_preview_images)
|
||||||
runweb python manage.py generate_preview_images "$@"
|
runweb python manage.py generate_preview_images "$@"
|
||||||
;;
|
;;
|
||||||
|
remove_remote_user_preview_images)
|
||||||
|
runweb python manage.py remove_remote_user_preview_images
|
||||||
|
;;
|
||||||
copy_media_to_s3)
|
copy_media_to_s3)
|
||||||
awscommand "bookwyrm_media_volume:/images"\
|
awscommand "bookwyrm_media_volume:/images"\
|
||||||
"s3 cp /images s3://${AWS_STORAGE_BUCKET_NAME}/images\
|
"s3 cp /images s3://${AWS_STORAGE_BUCKET_NAME}/images\
|
||||||
|
@ -256,6 +265,7 @@ case "$CMD" in
|
||||||
migrate
|
migrate
|
||||||
migrate django_celery_beat
|
migrate django_celery_beat
|
||||||
initdb
|
initdb
|
||||||
|
runweb python manage.py compile_themes
|
||||||
runweb python manage.py collectstatic --no-input
|
runweb python manage.py collectstatic --no-input
|
||||||
admin_code
|
admin_code
|
||||||
;;
|
;;
|
||||||
|
@ -283,6 +293,7 @@ case "$CMD" in
|
||||||
echo " dbshell"
|
echo " dbshell"
|
||||||
echo " restart_celery"
|
echo " restart_celery"
|
||||||
echo " pytest [path]"
|
echo " pytest [path]"
|
||||||
|
echo " compile_themes"
|
||||||
echo " collectstatic"
|
echo " collectstatic"
|
||||||
echo " makemessages"
|
echo " makemessages"
|
||||||
echo " compilemessages [locale]"
|
echo " compilemessages [locale]"
|
||||||
|
@ -300,6 +311,7 @@ case "$CMD" in
|
||||||
echo " populate_suggestions"
|
echo " populate_suggestions"
|
||||||
echo " generate_thumbnails"
|
echo " generate_thumbnails"
|
||||||
echo " generate_preview_images [--all]"
|
echo " generate_preview_images [--all]"
|
||||||
|
echo " remove_remote_user_preview_images"
|
||||||
echo " copy_media_to_s3"
|
echo " copy_media_to_s3"
|
||||||
echo " sync_media_to_s3"
|
echo " sync_media_to_s3"
|
||||||
echo " set_cors_to_s3 [cors file]"
|
echo " set_cors_to_s3 [cors file]"
|
||||||
|
|
|
@ -14,6 +14,7 @@ dbshell \
|
||||||
restart_celery \
|
restart_celery \
|
||||||
pytest \
|
pytest \
|
||||||
pytest_coverage_report \
|
pytest_coverage_report \
|
||||||
|
compile_themes \
|
||||||
collectstatic \
|
collectstatic \
|
||||||
makemessages \
|
makemessages \
|
||||||
compilemessages \
|
compilemessages \
|
||||||
|
@ -31,6 +32,7 @@ populate_lists_streams \
|
||||||
populate_suggestions \
|
populate_suggestions \
|
||||||
generate_thumbnails \
|
generate_thumbnails \
|
||||||
generate_preview_images \
|
generate_preview_images \
|
||||||
|
remove_remote_user_preview_images \
|
||||||
copy_media_to_s3 \
|
copy_media_to_s3 \
|
||||||
set_cors_to_s3 \
|
set_cors_to_s3 \
|
||||||
setup \
|
setup \
|
||||||
|
@ -43,42 +45,44 @@ function __bw_complete -a cmds cmd desc
|
||||||
complete -f -c bw-dev -n "not __fish_seen_subcommand_from $cmds" -a $cmd -d $desc
|
complete -f -c bw-dev -n "not __fish_seen_subcommand_from $cmds" -a $cmd -d $desc
|
||||||
end
|
end
|
||||||
|
|
||||||
__bw_complete "$commands" "up" "bring one or all service(s) up"
|
__bw_complete "$commands" "up" "bring one or all service(s) up"
|
||||||
__bw_complete "$commands" "service_ports_web" "run command on the web container with its portsenabled and mapped"
|
__bw_complete "$commands" "service_ports_web" "run command on the web container with its portsenabled and mapped"
|
||||||
__bw_complete "$commands" "initdb" "initialize database"
|
__bw_complete "$commands" "initdb" "initialize database"
|
||||||
__bw_complete "$commands" "resetdb" "!! WARNING !! reset database"
|
__bw_complete "$commands" "resetdb" "!! WARNING !! reset database"
|
||||||
__bw_complete "$commands" "makemigrations" "create new migrations"
|
__bw_complete "$commands" "makemigrations" "create new migrations"
|
||||||
__bw_complete "$commands" "migrate" "perform all migrations"
|
__bw_complete "$commands" "migrate" "perform all migrations"
|
||||||
__bw_complete "$commands" "bash" "open up bash within the web container"
|
__bw_complete "$commands" "bash" "open up bash within the web container"
|
||||||
__bw_complete "$commands" "shell" "open the Python shell within the web container"
|
__bw_complete "$commands" "shell" "open the Python shell within the web container"
|
||||||
__bw_complete "$commands" "dbshell" "open the database shell within the web container"
|
__bw_complete "$commands" "dbshell" "open the database shell within the web container"
|
||||||
__bw_complete "$commands" "restart_celery" "restart the celery container"
|
__bw_complete "$commands" "restart_celery" "restart the celery container"
|
||||||
__bw_complete "$commands" "pytest" "run unit tests"
|
__bw_complete "$commands" "pytest" "run unit tests"
|
||||||
__bw_complete "$commands" "collectstatic" "copy changed static files into the installation"
|
__bw_complete "$commands" "compile_themes" "compile themes css files"
|
||||||
__bw_complete "$commands" "makemessages" "extract all localizable messages from the code"
|
__bw_complete "$commands" "collectstatic" "copy changed static files into the installation"
|
||||||
__bw_complete "$commands" "compilemessages" "compile .po localization files to .mo"
|
__bw_complete "$commands" "makemessages" "extract all localizable messages from the code"
|
||||||
__bw_complete "$commands" "update_locales" "run makemessages and compilemessages for the en_US and additional locales"
|
__bw_complete "$commands" "compilemessages" "compile .po localization files to .mo"
|
||||||
__bw_complete "$commands" "build" "build the containers"
|
__bw_complete "$commands" "update_locales" "run makemessages and compilemessages for the en_US and additional locales"
|
||||||
__bw_complete "$commands" "clean" "bring the cluster down and remove all containers"
|
__bw_complete "$commands" "build" "build the containers"
|
||||||
__bw_complete "$commands" "black" "run Python code formatting tool"
|
__bw_complete "$commands" "clean" "bring the cluster down and remove all containers"
|
||||||
__bw_complete "$commands" "prettier" "run JavaScript code formatting tool"
|
__bw_complete "$commands" "black" "run Python code formatting tool"
|
||||||
__bw_complete "$commands" "eslint" "run JavaScript linting tool"
|
__bw_complete "$commands" "prettier" "run JavaScript code formatting tool"
|
||||||
__bw_complete "$commands" "stylelint" "run SCSS linting tool"
|
__bw_complete "$commands" "eslint" "run JavaScript linting tool"
|
||||||
__bw_complete "$commands" "formatters" "run multiple formatter tools"
|
__bw_complete "$commands" "stylelint" "run SCSS linting tool"
|
||||||
__bw_complete "$commands" "populate_streams" "populate the main streams"
|
__bw_complete "$commands" "formatters" "run multiple formatter tools"
|
||||||
__bw_complete "$commands" "populate_lists_streams" "populate streams for book lists"
|
__bw_complete "$commands" "populate_streams" "populate the main streams"
|
||||||
__bw_complete "$commands" "populate_suggestions" "populate book suggestions"
|
__bw_complete "$commands" "populate_lists_streams" "populate streams for book lists"
|
||||||
__bw_complete "$commands" "generate_thumbnails" "generate book thumbnails"
|
__bw_complete "$commands" "populate_suggestions" "populate book suggestions"
|
||||||
__bw_complete "$commands" "generate_preview_images" "generate book preview images"
|
__bw_complete "$commands" "generate_thumbnails" "generate book thumbnails"
|
||||||
__bw_complete "$commands" "collectstatic_watch" "watch filesystem and copy changed static files"
|
__bw_complete "$commands" "generate_preview_images" "generate site/book/user preview images"
|
||||||
__bw_complete "$commands" "copy_media_to_s3" "run the `s3 cp` command to copy media to a bucket on S3"
|
__bw_complete "$commands" "remove_remote_user_preview_images" "remove preview images for remote users"
|
||||||
__bw_complete "$commands" "sync_media_to_s3" "run the `s3 sync` command to sync media with a bucket on S3"
|
__bw_complete "$commands" "collectstatic_watch" "watch filesystem and copy changed static files"
|
||||||
__bw_complete "$commands" "set_cors_to_s3" "push a CORS configuration defined in .json to s3"
|
__bw_complete "$commands" "copy_media_to_s3" "run the `s3 cp` command to copy media to a bucket on S3"
|
||||||
__bw_complete "$commands" "setup" "perform first-time setup"
|
__bw_complete "$commands" "sync_media_to_s3" "run the `s3 sync` command to sync media with a bucket on S3"
|
||||||
__bw_complete "$commands" "admin_code" "get the admin code"
|
__bw_complete "$commands" "set_cors_to_s3" "push a CORS configuration defined in .json to s3"
|
||||||
__bw_complete "$commands" "remove_2fa" "remove 2FA from user"
|
__bw_complete "$commands" "setup" "perform first-time setup"
|
||||||
__bw_complete "$commands" "confirm_email" "manually confirm email of user and set active"
|
__bw_complete "$commands" "admin_code" "get the admin code"
|
||||||
__bw_complete "$commands" "runweb" "run a command on the web container"
|
__bw_complete "$commands" "remove_2fa" "remove 2FA from user"
|
||||||
|
__bw_complete "$commands" "confirm_email" "manually confirm email of user and set active"
|
||||||
|
__bw_complete "$commands" "runweb" "run a command on the web container"
|
||||||
|
|
||||||
|
|
||||||
function __bw_complete_subcommand -a cmd
|
function __bw_complete_subcommand -a cmd
|
||||||
|
|
|
@ -11,6 +11,7 @@ dbshell
|
||||||
restart_celery
|
restart_celery
|
||||||
pytest
|
pytest
|
||||||
pytest_coverage_report
|
pytest_coverage_report
|
||||||
|
compile_themes
|
||||||
collectstatic
|
collectstatic
|
||||||
makemessages
|
makemessages
|
||||||
compilemessages
|
compilemessages
|
||||||
|
@ -28,6 +29,7 @@ populate_lists_streams
|
||||||
populate_suggestions
|
populate_suggestions
|
||||||
generate_thumbnails
|
generate_thumbnails
|
||||||
generate_preview_images
|
generate_preview_images
|
||||||
|
remove_remote_user_preview_images
|
||||||
copy_media_to_s3
|
copy_media_to_s3
|
||||||
set_cors_to_s3
|
set_cors_to_s3
|
||||||
setup
|
setup
|
||||||
|
|
|
@ -13,6 +13,7 @@ dbshell
|
||||||
restart_celery
|
restart_celery
|
||||||
pytest
|
pytest
|
||||||
pytest_coverage_report
|
pytest_coverage_report
|
||||||
|
compile_themes
|
||||||
collectstatic
|
collectstatic
|
||||||
makemessages
|
makemessages
|
||||||
compilemessages
|
compilemessages
|
||||||
|
@ -30,6 +31,7 @@ populate_lists_streams
|
||||||
populate_suggestions
|
populate_suggestions
|
||||||
generate_thumbnails
|
generate_thumbnails
|
||||||
generate_preview_images
|
generate_preview_images
|
||||||
|
remove_remote_user_preview_images
|
||||||
copy_media_to_s3
|
copy_media_to_s3
|
||||||
set_cors_to_s3
|
set_cors_to_s3
|
||||||
setup
|
setup
|
||||||
|
|
|
@ -62,7 +62,7 @@ services:
|
||||||
build: .
|
build: .
|
||||||
networks:
|
networks:
|
||||||
- main
|
- main
|
||||||
command: celery -A celerywyrm worker -l info -Q high_priority,medium_priority,low_priority
|
command: celery -A celerywyrm worker -l info -Q high_priority,medium_priority,low_priority,imports
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
- static_volume:/app/static
|
- static_volume:/app/static
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.0.1\n"
|
"Project-Id-Version: 0.0.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-12-11 21:08+0000\n"
|
"POT-Creation-Date: 2022-12-21 17:58+0000\n"
|
||||||
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
|
"PO-Revision-Date: 2021-02-28 17:19-0800\n"
|
||||||
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
"Last-Translator: Mouse Reeve <mousereeve@riseup.net>\n"
|
||||||
"Language-Team: English <LL@li.org>\n"
|
"Language-Team: English <LL@li.org>\n"
|
||||||
|
@ -206,26 +206,26 @@ msgstr ""
|
||||||
msgid "Blocked"
|
msgid "Blocked"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:27
|
#: bookwyrm/models/fields.py:28
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value)s is not a valid remote_id"
|
msgid "%(value)s is not a valid remote_id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:36 bookwyrm/models/fields.py:45
|
#: bookwyrm/models/fields.py:37 bookwyrm/models/fields.py:46
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value)s is not a valid username"
|
msgid "%(value)s is not a valid username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:181 bookwyrm/templates/layout.html:142
|
#: bookwyrm/models/fields.py:182 bookwyrm/templates/layout.html:142
|
||||||
#: bookwyrm/templates/ostatus/error.html:29
|
#: bookwyrm/templates/ostatus/error.html:29
|
||||||
msgid "username"
|
msgid "username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:186
|
#: bookwyrm/models/fields.py:187
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:205
|
#: bookwyrm/models/fields.py:206
|
||||||
#: bookwyrm/templates/snippets/privacy-icons.html:3
|
#: bookwyrm/templates/snippets/privacy-icons.html:3
|
||||||
#: bookwyrm/templates/snippets/privacy-icons.html:4
|
#: bookwyrm/templates/snippets/privacy-icons.html:4
|
||||||
#: bookwyrm/templates/snippets/privacy_select.html:11
|
#: bookwyrm/templates/snippets/privacy_select.html:11
|
||||||
|
@ -233,7 +233,7 @@ msgstr ""
|
||||||
msgid "Public"
|
msgid "Public"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:206
|
#: bookwyrm/models/fields.py:207
|
||||||
#: bookwyrm/templates/snippets/privacy-icons.html:7
|
#: bookwyrm/templates/snippets/privacy-icons.html:7
|
||||||
#: bookwyrm/templates/snippets/privacy-icons.html:8
|
#: bookwyrm/templates/snippets/privacy-icons.html:8
|
||||||
#: bookwyrm/templates/snippets/privacy_select.html:14
|
#: bookwyrm/templates/snippets/privacy_select.html:14
|
||||||
|
@ -241,14 +241,14 @@ msgstr ""
|
||||||
msgid "Unlisted"
|
msgid "Unlisted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:207
|
#: bookwyrm/models/fields.py:208
|
||||||
#: bookwyrm/templates/snippets/privacy_select.html:17
|
#: bookwyrm/templates/snippets/privacy_select.html:17
|
||||||
#: bookwyrm/templates/user/relationships/followers.html:6
|
#: bookwyrm/templates/user/relationships/followers.html:6
|
||||||
#: bookwyrm/templates/user/relationships/layout.html:11
|
#: bookwyrm/templates/user/relationships/layout.html:11
|
||||||
msgid "Followers"
|
msgid "Followers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/fields.py:208
|
#: bookwyrm/models/fields.py:209
|
||||||
#: bookwyrm/templates/snippets/create_status/post_options_block.html:6
|
#: bookwyrm/templates/snippets/create_status/post_options_block.html:6
|
||||||
#: bookwyrm/templates/snippets/privacy-icons.html:15
|
#: bookwyrm/templates/snippets/privacy-icons.html:15
|
||||||
#: bookwyrm/templates/snippets/privacy-icons.html:16
|
#: bookwyrm/templates/snippets/privacy-icons.html:16
|
||||||
|
@ -272,15 +272,15 @@ msgstr ""
|
||||||
msgid "Stopped"
|
msgid "Stopped"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/import_job.py:84 bookwyrm/models/import_job.py:92
|
#: bookwyrm/models/import_job.py:83 bookwyrm/models/import_job.py:91
|
||||||
msgid "Import stopped"
|
msgid "Import stopped"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/import_job.py:359 bookwyrm/models/import_job.py:384
|
#: bookwyrm/models/import_job.py:360 bookwyrm/models/import_job.py:385
|
||||||
msgid "Error loading book"
|
msgid "Error loading book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/models/import_job.py:368
|
#: bookwyrm/models/import_job.py:369
|
||||||
msgid "Could not find a match for book"
|
msgid "Could not find a match for book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -317,19 +317,19 @@ msgstr ""
|
||||||
msgid "Everything else"
|
msgid "Everything else"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:213
|
#: bookwyrm/settings.py:214
|
||||||
msgid "Home Timeline"
|
msgid "Home Timeline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:213
|
#: bookwyrm/settings.py:214
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:214
|
#: bookwyrm/settings.py:215
|
||||||
msgid "Books Timeline"
|
msgid "Books Timeline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:214
|
#: bookwyrm/settings.py:215
|
||||||
#: bookwyrm/templates/guided_tour/user_profile.html:101
|
#: bookwyrm/templates/guided_tour/user_profile.html:101
|
||||||
#: bookwyrm/templates/search/layout.html:22
|
#: bookwyrm/templates/search/layout.html:22
|
||||||
#: bookwyrm/templates/search/layout.html:43
|
#: bookwyrm/templates/search/layout.html:43
|
||||||
|
@ -337,71 +337,71 @@ msgstr ""
|
||||||
msgid "Books"
|
msgid "Books"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:286
|
#: bookwyrm/settings.py:287
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:287
|
#: bookwyrm/settings.py:288
|
||||||
msgid "Català (Catalan)"
|
msgid "Català (Catalan)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:288
|
#: bookwyrm/settings.py:289
|
||||||
msgid "Deutsch (German)"
|
msgid "Deutsch (German)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:289
|
#: bookwyrm/settings.py:290
|
||||||
msgid "Español (Spanish)"
|
msgid "Español (Spanish)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:290
|
#: bookwyrm/settings.py:291
|
||||||
msgid "Galego (Galician)"
|
msgid "Galego (Galician)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:291
|
#: bookwyrm/settings.py:292
|
||||||
msgid "Italiano (Italian)"
|
msgid "Italiano (Italian)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:292
|
#: bookwyrm/settings.py:293
|
||||||
msgid "Suomi (Finnish)"
|
msgid "Suomi (Finnish)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:293
|
#: bookwyrm/settings.py:294
|
||||||
msgid "Français (French)"
|
msgid "Français (French)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:294
|
#: bookwyrm/settings.py:295
|
||||||
msgid "Lietuvių (Lithuanian)"
|
msgid "Lietuvių (Lithuanian)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:295
|
#: bookwyrm/settings.py:296
|
||||||
msgid "Norsk (Norwegian)"
|
msgid "Norsk (Norwegian)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:296
|
#: bookwyrm/settings.py:297
|
||||||
msgid "Polski (Polish)"
|
msgid "Polski (Polish)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:297
|
#: bookwyrm/settings.py:298
|
||||||
msgid "Português do Brasil (Brazilian Portuguese)"
|
msgid "Português do Brasil (Brazilian Portuguese)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:298
|
#: bookwyrm/settings.py:299
|
||||||
msgid "Português Europeu (European Portuguese)"
|
msgid "Português Europeu (European Portuguese)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:299
|
#: bookwyrm/settings.py:300
|
||||||
msgid "Română (Romanian)"
|
msgid "Română (Romanian)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:300
|
#: bookwyrm/settings.py:301
|
||||||
msgid "Svenska (Swedish)"
|
msgid "Svenska (Swedish)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:301
|
#: bookwyrm/settings.py:302
|
||||||
msgid "简体中文 (Simplified Chinese)"
|
msgid "简体中文 (Simplified Chinese)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/settings.py:302
|
#: bookwyrm/settings.py:303
|
||||||
msgid "繁體中文 (Traditional Chinese)"
|
msgid "繁體中文 (Traditional Chinese)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -598,25 +598,25 @@ msgstr[1] ""
|
||||||
msgid "That’s great!"
|
msgid "That’s great!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:127
|
#: bookwyrm/templates/annual_summary/layout.html:128
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "That makes an average of %(pages)s pages per book."
|
msgid "That makes an average of %(pages)s pages per book."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:132
|
#: bookwyrm/templates/annual_summary/layout.html:134
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "(%(no_page_number)s book doesn’t have pages)"
|
msgid "(No page data was available for %(no_page_number)s book)"
|
||||||
msgid_plural "(%(no_page_number)s books don’t have pages)"
|
msgid_plural "(No page data was available for %(no_page_number)s books)"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:148
|
#: bookwyrm/templates/annual_summary/layout.html:150
|
||||||
msgid "Their shortest read this year…"
|
msgid "Their shortest read this year…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:155
|
#: bookwyrm/templates/annual_summary/layout.html:157
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:176
|
#: bookwyrm/templates/annual_summary/layout.html:178
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:245
|
#: bookwyrm/templates/annual_summary/layout.html:247
|
||||||
#: bookwyrm/templates/book/book.html:56
|
#: bookwyrm/templates/book/book.html:56
|
||||||
#: bookwyrm/templates/discover/large-book.html:22
|
#: bookwyrm/templates/discover/large-book.html:22
|
||||||
#: bookwyrm/templates/landing/large-book.html:26
|
#: bookwyrm/templates/landing/large-book.html:26
|
||||||
|
@ -624,44 +624,44 @@ msgstr ""
|
||||||
msgid "by"
|
msgid "by"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:161
|
#: bookwyrm/templates/annual_summary/layout.html:163
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:182
|
#: bookwyrm/templates/annual_summary/layout.html:184
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "<strong>%(pages)s</strong> pages"
|
msgid "<strong>%(pages)s</strong> pages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:169
|
#: bookwyrm/templates/annual_summary/layout.html:171
|
||||||
msgid "…and the longest"
|
msgid "…and the longest"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:200
|
#: bookwyrm/templates/annual_summary/layout.html:202
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(display_name)s set a goal of reading %(goal)s book in %(year)s,<br /> and achieved %(goal_percent)s%% of that goal"
|
msgid "%(display_name)s set a goal of reading %(goal)s book in %(year)s,<br /> and achieved %(goal_percent)s%% of that goal"
|
||||||
msgid_plural "%(display_name)s set a goal of reading %(goal)s books in %(year)s,<br /> and achieved %(goal_percent)s%% of that goal"
|
msgid_plural "%(display_name)s set a goal of reading %(goal)s books in %(year)s,<br /> and achieved %(goal_percent)s%% of that goal"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:209
|
#: bookwyrm/templates/annual_summary/layout.html:211
|
||||||
msgid "Way to go!"
|
msgid "Way to go!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:224
|
#: bookwyrm/templates/annual_summary/layout.html:226
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(display_name)s left %(ratings_total)s rating, <br />their average rating is %(rating_average)s"
|
msgid "%(display_name)s left %(ratings_total)s rating, <br />their average rating is %(rating_average)s"
|
||||||
msgid_plural "%(display_name)s left %(ratings_total)s ratings, <br />their average rating is %(rating_average)s"
|
msgid_plural "%(display_name)s left %(ratings_total)s ratings, <br />their average rating is %(rating_average)s"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:238
|
#: bookwyrm/templates/annual_summary/layout.html:240
|
||||||
msgid "Their best rated review"
|
msgid "Their best rated review"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:251
|
#: bookwyrm/templates/annual_summary/layout.html:253
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Their rating: <strong>%(rating)s</strong>"
|
msgid "Their rating: <strong>%(rating)s</strong>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/annual_summary/layout.html:268
|
#: bookwyrm/templates/annual_summary/layout.html:270
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "All the books %(display_name)s read in %(year)s"
|
msgid "All the books %(display_name)s read in %(year)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -5349,7 +5349,7 @@ msgid "Copy the theme file into the <code>bookwyrm/static/css/themes</code> dire
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/settings/themes.html:32
|
#: bookwyrm/templates/settings/themes.html:32
|
||||||
msgid "Run <code>./bw-dev collectstatic</code>."
|
msgid "Run <code>./bw-dev compile_themes</code> and <code>./bw-dev collectstatic</code>."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/settings/themes.html:35
|
#: bookwyrm/templates/settings/themes.html:35
|
||||||
|
@ -6049,7 +6049,7 @@ msgstr ""
|
||||||
msgid "Choose wisely! Your username cannot be changed."
|
msgid "Choose wisely! Your username cannot be changed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: bookwyrm/templates/snippets/register_form.html:64
|
#: bookwyrm/templates/snippets/register_form.html:66
|
||||||
msgid "Sign Up"
|
msgid "Sign Up"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
BIN
locale/eu_ES/LC_MESSAGES/django.mo
Normal file
BIN
locale/eu_ES/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
6454
locale/eu_ES/LC_MESSAGES/django.po
Normal file
6454
locale/eu_ES/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
136
nginx/production
136
nginx/production
|
@ -19,52 +19,96 @@ server {
|
||||||
# return 301 https://your-domain.com$request_uri;
|
# return 301 https://your-domain.com$request_uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# server {
|
server {
|
||||||
# listen [::]:443 ssl http2;
|
access_log /var/log/nginx/access.log cache_log;
|
||||||
# listen 443 ssl http2;
|
|
||||||
#
|
listen [::]:443 ssl http2;
|
||||||
# server_name your-domain.com;
|
listen 443 ssl http2;
|
||||||
#
|
|
||||||
# client_max_body_size 3M;
|
server_name your-domain.com;
|
||||||
#
|
|
||||||
# if ($host != "your-domain.com") {
|
client_max_body_size 3M;
|
||||||
# return 301 $scheme://your-domain.com$request_uri;
|
|
||||||
# }
|
if ($host != "your-domain.com") {
|
||||||
#
|
return 301 $scheme://your-domain.com$request_uri;
|
||||||
# # SSL code
|
}
|
||||||
# ssl_certificate /etc/nginx/ssl/live/your-domain.com/fullchain.pem;
|
|
||||||
# ssl_certificate_key /etc/nginx/ssl/live/your-domain.com/privkey.pem;
|
# SSL code
|
||||||
#
|
ssl_certificate /etc/nginx/ssl/live/your-domain.com/fullchain.pem;
|
||||||
# location ~ /.well-known/acme-challenge {
|
ssl_certificate_key /etc/nginx/ssl/live/your-domain.com/privkey.pem;
|
||||||
# allow all;
|
|
||||||
# root /var/www/certbot;
|
location ~ /.well-known/acme-challenge {
|
||||||
# }
|
allow all;
|
||||||
#
|
root /var/www/certbot;
|
||||||
# location ~ ^/(login[^-/]|password-reset|resend-link|2fa-check) {
|
}
|
||||||
# limit_req zone=loginlimit;
|
|
||||||
#
|
sendfile on;
|
||||||
# proxy_pass http://web;
|
tcp_nopush on;
|
||||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
tcp_nodelay on;
|
||||||
# proxy_set_header Host $host;
|
keepalive_timeout 65;
|
||||||
# proxy_redirect off;
|
types_hash_max_size 2048;
|
||||||
# }
|
#include /etc/nginx/mime.types;
|
||||||
#
|
#default_type application/octet-stream;
|
||||||
# location / {
|
|
||||||
# proxy_pass http://web;
|
gzip on;
|
||||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
gzip_disable "msie6";
|
||||||
# proxy_set_header Host $host;
|
|
||||||
# proxy_redirect off;
|
proxy_read_timeout 1800s;
|
||||||
# }
|
chunked_transfer_encoding on;
|
||||||
#
|
|
||||||
# location /images/ {
|
# store responses to anonymous users for up to 1 minute
|
||||||
# alias /app/images/;
|
proxy_cache bookwyrm_cache;
|
||||||
# }
|
proxy_cache_valid any 1m;
|
||||||
#
|
add_header X-Cache-Status $upstream_cache_status;
|
||||||
# location /static/ {
|
|
||||||
# alias /app/static/;
|
# ignore the set cookie header when deciding to
|
||||||
# }
|
# store a response in the cache
|
||||||
# }
|
proxy_ignore_headers Cache-Control Set-Cookie Expires;
|
||||||
|
|
||||||
|
# PUT requests always bypass the cache
|
||||||
|
# logged in sessions also do not populate the cache
|
||||||
|
# to avoid serving personal data to anonymous users
|
||||||
|
proxy_cache_methods GET HEAD;
|
||||||
|
proxy_no_cache $cookie_sessionid;
|
||||||
|
proxy_cache_bypass $cookie_sessionid;
|
||||||
|
|
||||||
|
# tell the web container the address of the outside client
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_redirect off;
|
||||||
|
|
||||||
|
location ~ ^/(login[^-/]|password-reset|resend-link|2fa-check) {
|
||||||
|
limit_req zone=loginlimit;
|
||||||
|
proxy_pass http://web;
|
||||||
|
}
|
||||||
|
|
||||||
|
# do not log periodic polling requests from logged in users
|
||||||
|
location /api/updates/ {
|
||||||
|
access_log off;
|
||||||
|
proxy_pass http://web;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://web;
|
||||||
|
}
|
||||||
|
|
||||||
|
# directly serve images and static files from the
|
||||||
|
# bookwyrm filesystem using sendfile.
|
||||||
|
# make the logs quieter by not reporting these requests
|
||||||
|
location ~ ^/(images|static)/ {
|
||||||
|
root /app;
|
||||||
|
try_files $uri =404;
|
||||||
|
add_header X-Cache-Status STATIC;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# monitor the celery queues with flower, no caching enabled
|
||||||
|
location /flower/ {
|
||||||
|
proxy_pass http://flower:8888;
|
||||||
|
proxy_cache_bypass 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Reverse-Proxy server
|
# Reverse-Proxy server
|
||||||
# server {
|
# server {
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
aiohttp==3.8.1
|
aiohttp==3.8.3
|
||||||
bleach==5.0.1
|
bleach==5.0.1
|
||||||
celery==5.2.2
|
celery==5.2.7
|
||||||
colorthief==0.2.1
|
colorthief==0.2.1
|
||||||
Django==3.2.16
|
Django==3.2.16
|
||||||
django-celery-beat==2.2.1
|
django-celery-beat==2.4.0
|
||||||
django-compressor==2.4.1
|
django-compressor==4.1
|
||||||
django-imagekit==4.1.0
|
django-imagekit==4.1.0
|
||||||
django-model-utils==4.0.0
|
django-model-utils==4.2.0
|
||||||
django-sass-processor==1.0.1
|
django-sass-processor==1.2.2
|
||||||
environs==9.3.4
|
environs==9.5.0
|
||||||
flower==1.2.0
|
flower==1.2.0
|
||||||
libsass==0.21.0
|
libsass==0.22.0
|
||||||
Markdown==3.3.3
|
Markdown==3.3.3
|
||||||
Pillow>=9.0.0
|
Pillow>=9.3.0
|
||||||
psycopg2==2.8.4
|
psycopg2==2.9.5
|
||||||
pycryptodome==3.9.4
|
pycryptodome==3.16.0
|
||||||
python-dateutil==2.8.1
|
python-dateutil==2.8.2
|
||||||
redis==3.4.1
|
redis==3.4.1
|
||||||
requests==2.22.0
|
requests==2.28.1
|
||||||
responses==0.10.14
|
responses==0.22.0
|
||||||
pytz>=2021.1
|
pytz>=2022.7
|
||||||
boto3==1.17.88
|
boto3==1.26.32
|
||||||
django-storages==1.11.1
|
django-storages==1.11.1
|
||||||
django-redis==5.2.0
|
django-redis==5.2.0
|
||||||
opentelemetry-api==1.11.1
|
opentelemetry-api==1.11.1
|
||||||
|
|
Loading…
Reference in a new issue