diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py
index 52b1b1f27..4f7b55d50 100644
--- a/bookwyrm/activitypub/base_activity.py
+++ b/bookwyrm/activitypub/base_activity.py
@@ -213,7 +213,7 @@ class ActivityObject:
return data
-@app.task
+@app.task(queue="medium_priority")
@transaction.atomic
def set_related_field(
model_name, origin_model_name, related_field_name, related_remote_id, data
diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py
index f59eaf2e6..c32dfa35d 100644
--- a/bookwyrm/activitystreams.py
+++ b/bookwyrm/activitystreams.py
@@ -395,7 +395,7 @@ def remove_statuses_on_unshelve(sender, instance, *args, **kwargs):
# ---- TASKS
-@app.task
+@app.task(queue="low_priority")
def add_book_statuses_task(user_id, book_id):
"""add statuses related to a book on shelve"""
user = models.User.objects.get(id=user_id)
@@ -403,7 +403,7 @@ def add_book_statuses_task(user_id, book_id):
BooksStream().add_book_statuses(user, book)
-@app.task
+@app.task(queue="low_priority")
def remove_book_statuses_task(user_id, book_id):
"""remove statuses about a book from a user's books feed"""
user = models.User.objects.get(id=user_id)
@@ -411,7 +411,7 @@ def remove_book_statuses_task(user_id, book_id):
BooksStream().remove_book_statuses(user, book)
-@app.task
+@app.task(queue="medium_priority")
def populate_stream_task(stream, user_id):
"""background task for populating an empty activitystream"""
user = models.User.objects.get(id=user_id)
@@ -419,7 +419,7 @@ def populate_stream_task(stream, user_id):
stream.populate_streams(user)
-@app.task
+@app.task(queue="medium_priority")
def remove_status_task(status_ids):
"""remove a status from any stream it might be in"""
# this can take an id or a list of ids
@@ -432,7 +432,7 @@ def remove_status_task(status_ids):
stream.remove_object_from_related_stores(status)
-@app.task
+@app.task(queue="medium_priority")
def add_status_task(status_id, increment_unread=False):
"""remove a status from any stream it might be in"""
status = models.Status.objects.get(id=status_id)
@@ -440,7 +440,7 @@ def add_status_task(status_id, increment_unread=False):
stream.add_status(status, increment_unread=increment_unread)
-@app.task
+@app.task(queue="medium_priority")
def remove_user_statuses_task(viewer_id, user_id, stream_list=None):
"""remove all statuses by a user from a viewer's stream"""
stream_list = [streams[s] for s in stream_list] if stream_list else streams.values()
@@ -450,9 +450,9 @@ def remove_user_statuses_task(viewer_id, user_id, stream_list=None):
stream.remove_user_statuses(viewer, user)
-@app.task
+@app.task(queue="medium_priority")
def add_user_statuses_task(viewer_id, user_id, stream_list=None):
- """remove all statuses by a user from a viewer's stream"""
+ """add all statuses by a user to a viewer's stream"""
stream_list = [streams[s] for s in stream_list] if stream_list else streams.values()
viewer = models.User.objects.get(id=viewer_id)
user = models.User.objects.get(id=user_id)
@@ -460,7 +460,7 @@ def add_user_statuses_task(viewer_id, user_id, stream_list=None):
stream.add_user_statuses(viewer, user)
-@app.task
+@app.task(queue="medium_priority")
def handle_boost_task(boost_id):
"""remove the original post and other, earlier boosts"""
instance = models.Status.objects.get(id=boost_id)
diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py
index 1a615c9b2..1d9588d6b 100644
--- a/bookwyrm/connectors/connector_manager.py
+++ b/bookwyrm/connectors/connector_manager.py
@@ -119,7 +119,7 @@ def get_or_create_connector(remote_id):
return load_connector(connector_info)
-@app.task
+@app.task(queue="low_priority")
def load_more_data(connector_id, book_id):
"""background the work of getting all 10,000 editions of LoTR"""
connector_info = models.Connector.objects.get(id=connector_id)
diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py
index fff3985ef..4f43c69e6 100644
--- a/bookwyrm/emailing.py
+++ b/bookwyrm/emailing.py
@@ -64,7 +64,7 @@ def format_email(email_name, data):
return (subject, html_content, text_content)
-@app.task
+@app.task(queue="high_priority")
def send_email(recipient, subject, html_content, text_content):
"""use a task to send the email"""
email = EmailMultiAlternatives(
diff --git a/bookwyrm/importers/importer.py b/bookwyrm/importers/importer.py
index d5f1449ca..0968cdd79 100644
--- a/bookwyrm/importers/importer.py
+++ b/bookwyrm/importers/importer.py
@@ -61,7 +61,7 @@ class Importer:
job.save()
-@app.task
+@app.task(queue="low_priority")
def import_data(source, job_id):
"""does the actual lookup work in a celery task"""
job = ImportJob.objects.get(id=job_id)
diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py
index f287b752f..ed51158bc 100644
--- a/bookwyrm/models/activitypub_mixin.py
+++ b/bookwyrm/models/activitypub_mixin.py
@@ -502,7 +502,7 @@ def unfurl_related_field(related_field, sort_field=None):
return related_field.remote_id
-@app.task
+@app.task(queue="medium_priority")
def broadcast_task(sender_id, activity, recipients):
"""the celery task for broadcast"""
user_model = apps.get_model("bookwyrm.User", require_ready=True)
diff --git a/bookwyrm/models/import_job.py b/bookwyrm/models/import_job.py
index 05aada161..69d5f5da7 100644
--- a/bookwyrm/models/import_job.py
+++ b/bookwyrm/models/import_job.py
@@ -174,6 +174,7 @@ class ImportItem(models.Model):
if start_date and start_date is not None and not self.date_read:
return [ReadThrough(start_date=start_date)]
if self.date_read:
+ start_date = start_date if start_date < self.date_read else None
return [
ReadThrough(
start_date=start_date,
diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py
index 0745dffa2..4b03f6656 100644
--- a/bookwyrm/models/user.py
+++ b/bookwyrm/models/user.py
@@ -274,30 +274,46 @@ class User(OrderedCollectionPageMixin, AbstractUser):
transaction.on_commit(lambda: set_remote_server.delay(self.id))
return
- # populate fields for local users
- link = site_link()
- self.remote_id = f"{link}/user/{self.localname}"
- self.followers_url = f"{self.remote_id}/followers"
- self.inbox = f"{self.remote_id}/inbox"
- self.shared_inbox = f"{link}/inbox"
- self.outbox = f"{self.remote_id}/outbox"
+ with transaction.atomic():
+ # populate fields for local users
+ link = site_link()
+ self.remote_id = f"{link}/user/{self.localname}"
+ self.followers_url = f"{self.remote_id}/followers"
+ self.inbox = f"{self.remote_id}/inbox"
+ self.shared_inbox = f"{link}/inbox"
+ self.outbox = f"{self.remote_id}/outbox"
- # an id needs to be set before we can proceed with related models
+ # an id needs to be set before we can proceed with related models
+ super().save(*args, **kwargs)
+
+ # make users editors by default
+ try:
+ self.groups.add(Group.objects.get(name="editor"))
+ except Group.DoesNotExist:
+ # this should only happen in tests
+ pass
+
+ # create keys and shelves for new local users
+ self.key_pair = KeyPair.objects.create(
+ remote_id=f"{self.remote_id}/#main-key"
+ )
+ self.save(broadcast=False, update_fields=["key_pair"])
+
+ self.create_shelves()
+
+ def delete(self, *args, **kwargs):
+ """deactivate rather than delete a user"""
+ self.is_active = False
+ # skip the logic in this class's save()
super().save(*args, **kwargs)
- # make users editors by default
- try:
- self.groups.add(Group.objects.get(name="editor"))
- except Group.DoesNotExist:
- # this should only happen in tests
- pass
-
- # create keys and shelves for new local users
- self.key_pair = KeyPair.objects.create(
- remote_id="%s/#main-key" % self.remote_id
- )
- self.save(broadcast=False, update_fields=["key_pair"])
+ @property
+ def local_path(self):
+ """this model doesn't inherit bookwyrm model, so here we are"""
+ return "/user/%s" % (self.localname or self.username)
+ def create_shelves(self):
+ """default shelves for a new user"""
shelves = [
{
"name": "To Read",
@@ -321,17 +337,6 @@ class User(OrderedCollectionPageMixin, AbstractUser):
editable=False,
).save(broadcast=False)
- def delete(self, *args, **kwargs):
- """deactivate rather than delete a user"""
- self.is_active = False
- # skip the logic in this class's save()
- super().save(*args, **kwargs)
-
- @property
- def local_path(self):
- """this model doesn't inherit bookwyrm model, so here we are"""
- return "/user/%s" % (self.localname or self.username)
-
class KeyPair(ActivitypubMixin, BookWyrmModel):
"""public and private keys for a user"""
@@ -420,7 +425,7 @@ class AnnualGoal(BookWyrmModel):
}
-@app.task
+@app.task(queue="low_priority")
def set_remote_server(user_id):
"""figure out the user's remote server in the background"""
user = User.objects.get(id=user_id)
@@ -459,7 +464,7 @@ def get_or_create_remote_server(domain):
return server
-@app.task
+@app.task(queue="low_priority")
def get_remote_reviews(outbox):
"""ingest reviews by a new remote bookwyrm user"""
outbox_page = outbox + "?page=true&type=Review"
diff --git a/bookwyrm/preview_images.py b/bookwyrm/preview_images.py
index 4f85bb56e..900a3e123 100644
--- a/bookwyrm/preview_images.py
+++ b/bookwyrm/preview_images.py
@@ -352,7 +352,7 @@ def save_and_cleanup(image, instance=None):
# pylint: disable=invalid-name
-@app.task
+@app.task(queue="low_priority")
def generate_site_preview_image_task():
"""generate preview_image for the website"""
if not settings.ENABLE_PREVIEW_IMAGES:
@@ -377,7 +377,7 @@ def generate_site_preview_image_task():
# pylint: disable=invalid-name
-@app.task
+@app.task(queue="low_priority")
def generate_edition_preview_image_task(book_id):
"""generate preview_image for a book"""
if not settings.ENABLE_PREVIEW_IMAGES:
@@ -402,7 +402,7 @@ def generate_edition_preview_image_task(book_id):
save_and_cleanup(image, instance=book)
-@app.task
+@app.task(queue="low_priority")
def generate_user_preview_image_task(user_id):
"""generate preview_image for a book"""
if not settings.ENABLE_PREVIEW_IMAGES:
diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py
index c1f900794..9450ba81f 100644
--- a/bookwyrm/settings.py
+++ b/bookwyrm/settings.py
@@ -13,17 +13,6 @@ VERSION = "0.0.1"
PAGE_LENGTH = env("PAGE_LENGTH", 15)
DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English")
-# celery
-CELERY_BROKER = "redis://:{}@redis_broker:{}/0".format(
- requests.utils.quote(env("REDIS_BROKER_PASSWORD", "")), env("REDIS_BROKER_PORT")
-)
-CELERY_RESULT_BACKEND = "redis://:{}@redis_broker:{}/0".format(
- requests.utils.quote(env("REDIS_BROKER_PASSWORD", "")), env("REDIS_BROKER_PORT")
-)
-CELERY_ACCEPT_CONTENT = ["application/json"]
-CELERY_TASK_SERIALIZER = "json"
-CELERY_RESULT_SERIALIZER = "json"
-
# email
EMAIL_BACKEND = env("EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend")
EMAIL_HOST = env("EMAIL_HOST")
diff --git a/bookwyrm/static/css/bookwyrm.css b/bookwyrm/static/css/bookwyrm.css
index 0724c7f14..3529afc2b 100644
--- a/bookwyrm/static/css/bookwyrm.css
+++ b/bookwyrm/static/css/bookwyrm.css
@@ -96,7 +96,7 @@ body {
@see https://www.youtube.com/watch?v=9xXBYcWgCHA */
.shelf-option:disabled > *::after {
font-family: "icomoon"; /* stylelint-disable font-family-no-missing-generic-family-keyword */
- content: "\e918";
+ content: "\e919"; /* icon-check */
margin-left: 0.5em;
}
@@ -167,21 +167,21 @@ body {
/* All stars are visually filled by default. */
.form-rate-stars .icon::before {
- content: '\e9d9';
+ content: '\e9d9'; /* icon-star-full */
}
/* Icons directly following inputs that follow the checked input are emptied. */
.form-rate-stars input:checked ~ input + .icon::before {
- content: '\e9d7';
+ content: '\e9d7'; /* icon-star-empty */
}
/* When a label is hovered, repeat the fill-all-then-empty-following pattern. */
.form-rate-stars:hover .icon.icon::before {
- content: '\e9d9';
+ content: '\e9d9'; /* icon-star-full */
}
.form-rate-stars .icon:hover ~ .icon::before {
- content: '\e9d7';
+ content: '\e9d7'; /* icon-star-empty */
}
/** Book covers
@@ -292,13 +292,13 @@ body {
}
.quote > blockquote::before {
- content: "\e906";
+ content: "\e907"; /* icon-quote-open */
top: 0;
left: 0;
}
.quote > blockquote::after {
- content: "\e905";
+ content: "\e906"; /* icon-quote-close */
right: 0;
}
diff --git a/bookwyrm/static/css/fonts/icomoon.eot b/bookwyrm/static/css/fonts/icomoon.eot
index 2c801b2b6..12526617a 100644
Binary files a/bookwyrm/static/css/fonts/icomoon.eot and b/bookwyrm/static/css/fonts/icomoon.eot differ
diff --git a/bookwyrm/static/css/fonts/icomoon.svg b/bookwyrm/static/css/fonts/icomoon.svg
index 6327b19e6..765815843 100644
--- a/bookwyrm/static/css/fonts/icomoon.svg
+++ b/bookwyrm/static/css/fonts/icomoon.svg
@@ -7,34 +7,34 @@