Compare commits

...

2018 commits
v0.4.3 ... main

Author SHA1 Message Date
Mouse Reeve 4e987a0e66
Merge pull request #3369 from bookwyrm-social/dependabot/pip/requests-2.32.0
Bump requests from 2.31.0 to 2.32.0
2024-05-21 14:47:34 -07:00
dependabot[bot] 332286cdff
---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 05:41:48 +00:00
Mouse Reeve c4b21ee258
Merge pull request #3114 from SMillerDev/feat/api/oauth
feat: add OAuth authentication
2024-04-24 15:45:54 -07:00
Mouse Reeve ad830dd885
Merge pull request #3350 from Minnozz/custom-port
Correctly handle serving BookWyrm on custom port
2024-04-24 15:27:01 -07:00
Mouse Reeve 366c647585
Merge pull request #3359 from bookwyrm-social/dependabot/pip/aiohttp-3.9.4
Bump aiohttp from 3.9.2 to 3.9.4
2024-04-24 15:13:30 -07:00
Bart Schuurmans 4f58b11330 Include the correct protocol and port in remote IDs 2024-04-24 15:35:19 +02:00
Bart Schuurmans 609bc15406 Support http:// protocol in BookWyrm connector 2024-04-24 15:30:47 +02:00
Bart Schuurmans c42db40a63 Construct absolute URLs with the correct protocol and port 2024-04-24 15:30:47 +02:00
Bart Schuurmans 3aefbb548e Allow serving BookWyrm on a non-standard port 2024-04-24 15:30:47 +02:00
Bart Schuurmans baea105c18 pytest.ini env values should be unquoted
Otherwise the quotes end up in the strings.
2024-04-24 15:30:47 +02:00
Bart Schuurmans c73d1fff6a Remove unnecessary exceptions from validate_url_domain 2024-04-24 15:30:47 +02:00
Bart Schuurmans 3d183a393f
Merge pull request #3360 from hughrun/move-fix
refactor Move for more redundancy
2024-04-24 15:30:19 +02:00
Bart Schuurmans f24fdf73b5 Update to match newer code style 2024-04-24 15:08:48 +02:00
Bart Schuurmans 839ab2fafd
Merge branch 'main' into move-fix 2024-04-24 14:56:32 +02:00
Bart Schuurmans 637f19b208
Merge pull request #3336 from Minnozz/s3-url-protocol
Support AWS_S3_URL_PROTOCOL
2024-04-24 14:53:55 +02:00
Bart Schuurmans 031223104f Clarify AWS_S3_URL_PROTOCOL in .env.example 2024-04-24 14:46:57 +02:00
Hugh Rundle 6684d60526
refactor Move for more redundancy
As outlined in #3354, a use `Move` fails if the user is moving from a BookWyrm server to another BookWrym server.
This is because:

1. the original code did not announce changes to alsoKnownAs;
2. the original code always checked the locally saved profile rather than refetching the remote data;

This commit fixes both these problems by forcing `MoveUser` to always perform a "refresh" of the local data from the remote, and by saving the user with broadcast=True when updating alsoKnownAs ids.
2024-04-22 13:35:08 +10:00
dependabot[bot] cca58023ed
Bump aiohttp from 3.9.2 to 3.9.4
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.9.2 to 3.9.4.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.2...v3.9.4)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-18 15:51:34 +00:00
Bart Schuurmans bf5c08dbf3 Add docker-compose.override.yml to .gitignore 2024-04-15 13:17:00 +02:00
Bart Schuurmans be872ed672 Support AWS_S3_URL_PROTOCOL
- Allow setting in .env
- Default to PROTOCOL (same as before)
- Propagate to django-storages so it generates the correct URLs in sass_src
2024-04-15 13:16:51 +02:00
Bart Schuurmans 70f803a1f6
Merge pull request #3353 from dato/fix_quotation_str_pagenum
Fix creation of quotations with no end position
2024-04-15 13:11:55 +02:00
Adeodato Simó 4304cd4a79
use re.escape 2024-04-13 21:26:41 -03:00
Adeodato Simó 8733369605
test_quotation_page_serialization: add test with no position 2024-04-13 21:26:41 -03:00
Adeodato Simó df78cc64a6
Quotation._format_position: do not treat page numbers as integers
Fixes: #3352
2024-04-13 21:26:41 -03:00
Adeodato Simó f844abcad9
test_quotation_page_serialization: use strings for page numbers
This follows from #3273, "Allow page numbers to be text, instead of
integers".
2024-04-13 21:26:39 -03:00
Bart Schuurmans 21a39f8170
Merge pull request #3228 from hughrun/user-export
Fix user exports to deal with s3 storage
2024-04-13 22:53:58 +02:00
Hugh Rundle c3c46144fe
add merge migration 2024-04-13 12:39:40 +10:00
Hugh Rundle d48d312c0a
Merge branch 'main' into user-export 2024-04-13 12:26:13 +10:00
Hugh Rundle 501fb45528
export avatars to own directory
Saving avatars to /images is problematic because it changes the original filepath from avatars/filename to images/avatars/filename.
In this PR prior to this commit, imports failed as they are looking for a file path beginning with "avatar"
2024-04-13 12:03:35 +10:00
Bart Schuurmans 7d581759da
Merge pull request #3342 from hbrunn/main-pilkit
[FIX] make sure to get Pillow>=10 compatible pilkit
2024-04-11 14:52:22 +02:00
Bart Schuurmans d5a536ae36 Change pilkit constraint to the version that does work 2024-04-11 14:45:13 +02:00
Bart Schuurmans 26f92db5d8 Merge branch 'main' into main-pilkit 2024-04-11 14:43:10 +02:00
Bart Schuurmans 5686c5ae5d
Merge pull request #3356 from Minnozz/quick-fix-frontend-ci
Install same version of eslint in CI as in dev-tools
2024-04-10 22:10:07 +02:00
Bart Schuurmans 9d9e64399c Install same version of eslint in CI as in dev-tools 2024-04-10 21:26:34 +02:00
Mouse Reeve b6aba44e42
Merge pull request #3355 from bookwyrm-social/merge-migration
Adds merge migration
2024-04-09 06:04:15 -05:00
Mouse Reeve 3ffbb242a4 Black 2024-04-09 05:59:01 -05:00
Mouse Reeve af0bd90c15 Adds merge migration 2024-04-09 05:57:27 -05:00
Mouse Reeve 73630331d1
Merge pull request #3299 from Minnozz/absorb
Track which Author/Work/Edition a duplicate has been merged into
2024-04-09 05:55:44 -05:00
Mouse Reeve ca6dbcb483
Merge pull request #3348 from Minnozz/more-indexes
Define more indexes for slow queries
2024-04-04 15:18:07 -07:00
Bart Schuurmans e1c54b2933 Remove optimizations with adverse effects
`if not audience` actually causes the entire query to be evaluated, before .values_list() is called.
2024-04-04 13:47:56 +02:00
Bart Schuurmans 439cb3ccaa Remove unnecessary conversions between list and set 2024-04-04 13:15:31 +02:00
Bart Schuurmans 321397a349 Specify which column DISTINCT should apply to 2024-04-03 21:28:22 +02:00
Bart Schuurmans 464a0298c6 Add index for finding active (and local) users 2024-04-03 21:27:52 +02:00
Bart Schuurmans 0501ce39cd Add index for looking up User by username 2024-04-03 21:15:24 +02:00
Bart Schuurmans 4d5a30d953 Add index for looking up KeyPair by remote id 2024-04-03 21:11:27 +02:00
Bart Schuurmans 5cfe7eca6f Add index for finding all statuses in a thread 2024-04-03 21:11:09 +02:00
Bart Schuurmans 5082806b82
Merge pull request #3338 from Minnozz/fix-nginx-location
Make nginx config safer
2024-04-03 19:22:16 +02:00
Mouse Reeve d1d91f0c2b
Merge pull request #3347 from bookwyrm-social/dependabot/pip/pillow-10.3.0
Bump pillow from 10.2.0 to 10.3.0
2024-04-03 10:01:59 -07:00
dependabot[bot] ea0ade955b
Bump pillow from 10.2.0 to 10.3.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.2.0 to 10.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.2.0...10.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-03 16:45:11 +00:00
Mouse Reeve f085d3d0fe
Merge pull request #3346 from Minnozz/status-remote-id-index
Add index on Status.remote_id
2024-04-02 13:02:35 -07:00
Bart Schuurmans 4bbdd0b2d0 Add index on Status.remote_id
This field is often used in WHERE-clauses in queries that are very slow on bookwyrm.social.
2024-04-02 21:54:30 +02:00
Sean Molenaar d5fb21f330
Merge branch 'main' into feat/api/oauth 2024-04-01 22:35:19 +02:00
Mouse Reeve f28800af7f
Merge pull request #3339 from Minnozz/fix-file-leaks
Fix resource leaks
2024-03-31 12:43:19 -07:00
Mouse Reeve cb3fd0cfc1
Merge branch 'main' into feat/api/oauth 2024-03-31 12:41:12 -07:00
Bart Schuurmans 72ed878eeb
Merge pull request #3343 from Minnozz/update-codeql
Update CodeQL workflows to v3
2024-03-30 22:01:49 +01:00
Bart Schuurmans f666951934 Update CodeQL workflows to v3
https://github.blog/changelog/2024-01-12-code-scanning-deprecation-of-codeql-action-v2/
2024-03-30 21:56:44 +01:00
Holger Brunn fcd0087589 [FIX] make sure to get Pillow>=10 compatible pilkit 2024-03-30 01:58:41 +01:00
Bart Schuurmans ffee29d8e2 Fix resource leaks
Rewrite places where files (or other resources) are opened but not closed to "with" blocks, which
automatically call close() at the end of the scope.

Also simplify some tests where images need to be saved to a model field: an opened file can be
passed directly to FileField.save().
2024-03-29 20:14:10 +01:00
Bart Schuurmans 75bc4f8cb0 Make nginx config safer
Instead of allowing all image files anywhere, and disallowing non-image file under /images/, only
allow image files under /images/ and don't match non-image files elsewhere. They get proxied to web
instead and result in a 404 there.

For example, the old config allowed /exports/foo.jpg to be served, while the new config does not.
2024-03-29 15:04:38 +01:00
Bart Schuurmans e7ae0fdf93
Merge pull request #3337 from prolibre/apport-perso
flower 2.0.1 fixes a few link bugs (particularly for favicon)
2024-03-29 14:45:59 +01:00
Bart Schuurmans 5d597f1ca9 Use new "with ()" style 2024-03-29 14:25:08 +01:00
Bart Schuurmans 0ac9d12d1c Merge branch 'main' into user-export 2024-03-29 14:23:10 +01:00
Bart Schuurmans e74de94640
Merge pull request #3334 from ccamara/patch-1
Remove twitter from README.md
2024-03-29 14:21:49 +01:00
Bart Schuurmans 1464d09a43
Merge pull request #3320 from dato/better-fmt-patch-calls
bulk-fmt: bracket-wrap calls to patch() for better readability
2024-03-29 14:19:16 +01:00
Anthony 2272e7a326 flower 2.0.1 fixes a few link bugs (particularly for favicon) 2024-03-29 12:07:52 +01:00
Bart Schuurmans 2bbe3d4c32 Test user export archive contents 2024-03-28 13:50:55 +01:00
Bart Schuurmans bb5d8152f1 Fix mypy error 2024-03-28 13:21:30 +01:00
Bart Schuurmans dabf7c6e10 User export testing fixes 2024-03-28 13:09:21 +01:00
Bart Schuurmans cdbc1d172c Fix double exports subdir in S3 user export 2024-03-27 23:28:24 +01:00
Adeodato Simó 3133a47b7c
Merge from main into 'better-fmt-patch-calls'
Conflicts:
	bookwyrm/tests/test_book_search.py
2024-03-27 17:13:08 -03:00
Bart Schuurmans c6ca547d58 Fix migration formatting 2024-03-27 20:41:59 +01:00
Bart Schuurmans 797d5cb508 Update BookwyrmExportJob tests 2024-03-27 20:39:57 +01:00
Adeodato Simó 699d637bae
Fix detection of unlisted posts (#3258)
Merged from dato/fix_unlisted_set_from_activity.
2024-03-27 16:29:09 -03:00
Bart Schuurmans 9afd0ebb54 Update migrations 2024-03-27 20:15:06 +01:00
Bart Schuurmans 9685ae5a0a Consolidate BookwyrmExportJob into two tasks
Creating the export JSON and export TAR are now the only two tasks.
2024-03-27 20:13:49 +01:00
Carlos Cámara 98600440d8
Remove twitter from README.md
The Twitter/X account doesn't seem to exist, so removing the badge
2024-03-26 17:14:09 +00:00
Bart Schuurmans ed2e9e5ea8 Merge migration 2024-03-26 13:41:39 +01:00
Bart Schuurmans ef57c0bc8b Check last user export too in post handler 2024-03-26 13:41:39 +01:00
Bart Schuurmans 145c67dd21 Merge BookwyrmExportJob export_data field back into one with dynamic storage backend 2024-03-26 13:41:39 +01:00
Bart Schuurmans 6a67943408
Merge branch 'main' into user-export 2024-03-26 13:15:40 +01:00
Mouse Reeve 9dfa218ba5
Merge pull request #3333 from bookwyrm-social/locales
Updates locales and version number
2024-03-25 16:36:51 -07:00
Mouse Reeve bf52eeaa9e Bump version to 0.7.3. 2024-03-25 16:15:02 -07:00
Mouse Reeve 011e4a27a6 Updates locales and adds missing trimmed on blocktrans 2024-03-25 16:13:00 -07:00
Mouse Reeve 7192449b21
Merge pull request #3325 from Minnozz/author-search-vector
Rework author search
2024-03-25 14:41:25 -07:00
Bart Schuurmans d9bf848cfa Fix pylint warnings 2024-03-25 18:25:43 +01:00
Bart Schuurmans bd95bcd50b Add test for special character in cover filename 2024-03-25 18:14:45 +01:00
Bart Schuurmans f721289b1d Simplify logic for rendering user exports 2024-03-25 18:14:45 +01:00
Bart Schuurmans a51402241b Refactor creation of user export archive 2024-03-25 18:14:45 +01:00
Bart Schuurmans e0decbfd1d Fix urlescaped relative path to cover image in export
Fixes #3292
2024-03-25 17:59:39 +01:00
Bart Schuurmans aee8dc16af Fix pylint warning 2024-03-24 13:27:01 +01:00
Bart Schuurmans 5bd66cb3f7 Only generate signed S3 link to user export when user clicks download 2024-03-24 13:08:33 +01:00
Bart Schuurmans ab7b0893e0 User exports: handle files that no longer exist on file storage 2024-03-24 12:47:26 +01:00
Bart Schuurmans 471233c1dc Use different export job fields for the different storage backends
This way, the database definition is not depdendent on the runtime configuration.
2024-03-24 12:46:42 +01:00
Bart Schuurmans 073f62d5bb Add exports_volume to docker-compose.yml
Exports should be written to a Docker volume instead of to the bind mount (= source directory). This
way they are shared between different containers even when they run on different machines.
2024-03-24 12:08:29 +01:00
Bart Schuurmans a770689245 Merge branch 'main' into user-export 2024-03-24 12:07:14 +01:00
Bart Schuurmans 69f464418d Remove problematic migration
This migration is dependent on the runtime configuration (.env); a structural fix will follow.
2024-03-24 12:06:44 +01:00
Bart Schuurmans f11c80162a
Merge pull request #3331 from Minnozz/revert-docker-mount-ro
Revert "docker-compose.yml: make all bind mounts read only"
2024-03-24 11:30:56 +01:00
Bart Schuurmans 7c2fa746ae Revert "docker-compose.yml: make all bind mounts read only"
This reverts commit 864304f128.
2024-03-24 11:23:23 +01:00
Hugh Rundle 03587dfdc7
migrations 2024-03-24 20:56:20 +11:00
Hugh Rundle dd27684d4b
set signed s3 url expiry with env value
Adds S3_SIGNED_URL_EXPIRY val to .env and settings (defaults to 15 mins)
Note that this is reset every time the user loads the exports page
and is independent of the _creation_ of export files.
2024-03-24 20:53:49 +11:00
Bart Schuurmans caebebeb37
Merge pull request #3261 from bSolt/book-series-3256
Add book series by title in feed posts
2024-03-23 20:01:03 +01:00
Bart Schuurmans 592914dc91 Render series number with comma and outside of link on book page 2024-03-23 19:51:20 +01:00
Bart Schuurmans 2915133223
Merge branch 'main' into book-series-3256 2024-03-23 19:37:07 +01:00
Bart Schuurmans 2d2ccd51df Factor out book series info into separate template 2024-03-23 19:35:24 +01:00
Bart Schuurmans 4a690e675a BookDataModel: add dry_run argument to merge_into 2024-03-23 19:28:57 +01:00
Bart Schuurmans fb82c7a579 Add test for merging authors 2024-03-23 19:28:57 +01:00
Bart Schuurmans 6f191acb27 BookDataModel: fix absorbing data from array and partial date fields 2024-03-23 19:28:57 +01:00
Bart Schuurmans 7fb079cb43 PartialDate: fix __eq__ method 2024-03-23 19:28:57 +01:00
Bart Schuurmans 7066e2815b BookDataModel.merge_into: return and log absorbed fields 2024-03-23 19:28:57 +01:00
Bart Schuurmans e04cd79ff8 Redirect to new URL when a merged object is requested 2024-03-23 19:28:57 +01:00
Bart Schuurmans 5e123972e8 BookDataModel: implement merge_into method 2024-03-23 19:28:57 +01:00
Bart Schuurmans b3753ab6da Add MergedBookDataModel 2024-03-23 19:28:57 +01:00
Bart Schuurmans b8995bd4b1 Add tests for author search 2024-03-23 19:26:51 +01:00
Bart Schuurmans 769d9726e5 Add book search test cases for author aliases 2024-03-23 19:26:51 +01:00
Bart Schuurmans 36222afa79 Switch author search from TrigramSimilarity to SearchQuery 2024-03-23 19:26:51 +01:00
Bart Schuurmans 0795b4d171 Include Author aliases in Book search vector 2024-03-23 19:26:51 +01:00
Bart Schuurmans 2de35f3fc7 Calculate Author search vector with name and aliases 2024-03-23 19:26:51 +01:00
Mouse Reeve bac52eef3e
Merge pull request #3275 from ccamara/wikidata
Add wikidata field for authors
2024-03-23 08:12:09 -07:00
Mouse Reeve 8bbac458a6
Merge pull request #3217 from dato/switch_edition_invalidate_active_shelves
Invalidate `active_shelf` when switching editions
2024-03-23 07:59:40 -07:00
Mouse Reeve 5b71e94888
Merge branch 'main' into user-export 2024-03-23 07:55:46 -07:00
Mouse Reeve a914a44fba
Removes unnecessary redeclaration of wikidata model field in Author 2024-03-23 07:54:54 -07:00
Mouse Reeve 8e088a6d53
Merge branch 'main' into switch_edition_invalidate_active_shelves 2024-03-23 07:53:24 -07:00
Mouse Reeve b508b4cd33
Merge pull request #3323 from Minnozz/docker-bind-ro
Docker: make bind mounts of source code read only
2024-03-23 07:51:00 -07:00
Mouse Reeve 886d6ec9f7
Merge branch 'main' into docker-bind-ro 2024-03-23 07:48:27 -07:00
Mouse Reeve 21f75da75e
Merge pull request #3328 from Minnozz/escape-query-in-link
Escape search query in generated URLs
2024-03-23 07:46:04 -07:00
Mouse Reeve 20db968315
Merge pull request #3322 from Minnozz/fix-font-download
Fix font download
2024-03-23 07:36:43 -07:00
Bart Schuurmans c3d25c59c5 Escape search query in generated URLs
Otherwise, a query containing '&' or other special characters results in a broken URL.
2024-03-21 16:48:34 +01:00
Bart Schuurmans 3cde6dbe5a
Merge pull request #3326 from Minnozz/black-required-version
black: specify major version 22 only
2024-03-21 16:30:56 +01:00
Bart Schuurmans 682bb3b62f dev-tools: relax black version constraint 2024-03-21 16:25:29 +01:00
Bart Schuurmans b5b9eddaf0 CI: relax black version constraints 2024-03-20 12:46:37 +01:00
Bart Schuurmans ab430e0208 requirements.txt: add black
This way, IDEs can be set up to use the black version from the environment instead of a globally
available/bundled black version.
2024-03-20 12:43:17 +01:00
Bart Schuurmans e13e4237f4 black: specify required-version
This ensures consistent formatting among different contributors / development setups.

https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#required-version
2024-03-20 12:26:21 +01:00
Bart Schuurmans 762786839c
Merge pull request #3134 from dato/trigger_migrations
Support trigger migrations
2024-03-20 12:11:34 +01:00
Bart Schuurmans 4ca52c0b38
Merge branch 'main' into trigger_migrations 2024-03-20 11:47:54 +01:00
Bart Schuurmans 6a87713f9f Recalculate all book search vectors after fixing the author trigger 2024-03-20 11:45:12 +01:00
Mouse Reeve d08147c6d9
Merge pull request #3244 from bookwyrm-social/dependabot/pip/pillow-10.2.0
Bump pillow from 10.0.1 to 10.2.0
2024-03-19 15:10:30 -07:00
Bart Schuurmans f423834bd0 Catch the correct exception type from Pillow 2024-03-19 12:42:52 +01:00
Mouse Reeve d304ceb437
Merge pull request #3324 from bookwyrm-social/dependabot/pip/django-3.2.25
Bump django from 3.2.24 to 3.2.25
2024-03-18 15:05:30 -07:00
dependabot[bot] 47afe34d97
Bump django from 3.2.24 to 3.2.25
Bumps [django](https://github.com/django/django) from 3.2.24 to 3.2.25.
- [Commits](https://github.com/django/django/compare/3.2.24...3.2.25)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 21:48:21 +00:00
Bart Schuurmans 4d23edddca Make sure /images/ and /static/ exist now that the bind mount is read only
Otherwise the static_volume and media_volume can't be mounted there.
2024-03-18 21:35:12 +01:00
Bart Schuurmans 68cb94daf2 docker-compose.yml: don't automatically start dev-tools by assigning profile 2024-03-18 21:34:51 +01:00
Bart Schuurmans 864304f128 docker-compose.yml: make all bind mounts read only
Except dev-tools, since it needs to be able to change the source.
2024-03-18 21:34:09 +01:00
Bart Schuurmans 7690247ab4 Font download: log the exact error 2024-03-18 20:34:47 +01:00
Bart Schuurmans 3367b20965 Font download: destination dir is allowed to exist
Without this argument, an existing directory (but not the file) causes an error.
2024-03-18 20:23:31 +01:00
Bart Schuurmans 748418590f docker-compose.yml: mount static_volume for flower
Because flower also uses BookwyrmConfig, it wants to download fonts, and will download them to an
incorrect location if the static_volume is not mounted.
2024-03-18 20:22:19 +01:00
Bart Schuurmans ccf2b16d73 requirements.txt: make typing-Pillow match Pillow 2024-03-18 19:52:40 +01:00
dependabot[bot] 3be227fc86 Bump pillow from 10.0.1 to 10.2.0
Bumps [pillow](https://github.com/python-pillow/Pillow) from 10.0.1 to 10.2.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/10.0.1...10.2.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 19:51:24 +01:00
Adeodato Simó a6dc5bd13f
Make get_file_size robust against typing errors 2024-03-18 15:03:07 -03:00
Adeodato Simó 518da3b9cf Merge from main into 'user-export'
Conflicts:
	bookwyrm/models/bookwyrm_export_job.py
	requirements.txt
2024-03-18 14:47:34 -03:00
Adeodato Simó 2cf7ed477d Consolidate test_posgres.py into test_book_search.py
These are tests I missed when first writing trigger tests in
test_book_search.py.
2024-03-17 22:38:44 -03:00
Adeodato Simó cceccd1ecf
Merge from main into 'trigger_migrations'
Conflicts:
	requirements.txt
2024-03-17 21:54:15 -03:00
Adeodato Simó beb49af514
Upgade django-pgtrigger to 4.11 2024-03-17 21:46:34 -03:00
Adeodato Simó 90bd893568 Fix remaining instances of bad-classmethod-argument 2024-03-17 21:28:55 -03:00
Adeodato Simó e2c9ea3cd2 Fix instances of bad-classmethod-argument in recently edited files 2024-03-17 21:28:55 -03:00
Adeodato Simó 4b9fe0af0c Remove nesting in several with..patch calls 2024-03-17 20:57:39 -03:00
Adeodato Simó 1b9e0546e6 Bracket-wrap calls to patch() for better readability 2024-03-17 20:34:12 -03:00
Bart Schuurmans 8cf52e0a77
Merge pull request #3318 from Minnozz/ci-annotations
CI: update pytest setup and show annotations on PRs
2024-03-17 11:24:01 +01:00
Bart Schuurmans 0282e20b89
Merge branch 'main' into book-series-3256 2024-03-16 11:23:40 +01:00
Bart Schuurmans 4e20e43037 CI: merge all Python actions into one file 2024-03-13 23:36:26 +01:00
Bart Schuurmans 383e6533e1 CI: use pytest-github-actions-annotate-failures 2024-03-13 23:35:05 +01:00
Bart Schuurmans 74fdd9a85a CI: simplify pytest setup 2024-03-13 23:35:05 +01:00
Bart Schuurmans 6af0a08838 CI: use actions/setup-python@v5 and cache pip 2024-03-13 23:35:03 +01:00
Bart Schuurmans 12b469a0d6 CI: use actions/checkout@v4 2024-03-13 23:33:40 +01:00
Mouse Reeve 288743b686
Merge pull request #3315 from Minnozz/fix-pytest-env
pytest.ini: define ALLOWED_HOSTS
2024-03-13 15:29:15 -07:00
Mouse Reeve a3465e6154
Merge pull request #3303 from MaggieFero/main
Upgrade Python Version and Several Other Packages for Security
2024-03-13 15:28:54 -07:00
Bart Schuurmans 3ba528ecdd pytest.ini: define ALLOWED_HOSTS
This fixes running `./bw-dev pytest` locally when having a different value defined for
`ALLOWED_HOSTS` in `.env`.
2024-03-11 20:12:46 +01:00
Adeodato Simó 304c47863b
FileLinkForm: fix duplicate check (#3311)
Merged from: Minnozz/filelink-duplicate-check.
2024-03-11 15:10:28 -03:00
Mouse Reeve b68a4cc392
Merge branch 'main' into filelink-duplicate-check 2024-03-09 07:37:26 -08:00
Mouse Reeve 6dfb5000cc
Merge pull request #3305 from dato/export_catch_missing_key_icon
json_export: also detect absent "icon" key
2024-03-09 07:37:14 -08:00
Bart Schuurmans 8d018b872f FileLinkForm: fix duplicate check 2024-03-09 15:49:42 +01:00
Adeodato Simó 9e7b040b73
Fix shelving date changing when changing editions (#3193)
Merged from  from jakejack13/switch-edition
Fixes: #3139.
2024-03-03 18:48:04 -03:00
Adeodato Simó 09c3d9c0dc
json_export: also detect absent "icon" key 2024-03-03 18:42:27 -03:00
Mouse Reeve dd9d68c97d
Merge pull request #3096 from bookwyrm-social/image-ap-serialization
Changes to how images are serialized
2024-03-02 18:58:08 -08:00
Margaret Fero d138395c75 Add linter exclusion for TBookWyrmModel 2024-03-02 17:43:49 -08:00
Margaret Fero 91fe4ad535 Fix spacing for linter 2024-03-02 17:31:16 -08:00
Margaret Fero 9fa09d5ebe Add extra space required by linter 2024-03-02 17:30:37 -08:00
Margaret Fero eadb0e640f Fix typo in operator 2024-03-02 17:29:42 -08:00
Margaret Fero be140d5e5a Pin setuptools at 65.5.1 2024-03-02 17:20:48 -08:00
Margaret Fero 22c4155c7c Upgrade pytest to 6.2.5 2024-03-02 16:09:34 -08:00
Margaret Fero 498dc35d99 Upgrade Pylint to 2.15.0 2024-03-02 16:09:06 -08:00
Margaret Fero 0f5a3e9163 Pin Tornado at 6.3.3 2024-03-02 16:08:41 -08:00
Margaret Fero da2636fa29 Add grpcio pin @ 1.57.0 2024-03-02 16:07:50 -08:00
Margaret Fero c1520da56d Upgrade flower to 2.0.0 2024-03-02 16:05:11 -08:00
Margaret Fero fee3fdd5a8 Upgrade django-compressor to 4.4 2024-03-02 16:04:37 -08:00
Margaret Fero c944824ac7 Upgrade django-celery-beat to 2.5.0 2024-03-02 16:04:06 -08:00
Margaret Fero 4312e9bba0 Upgrade Celery to 5.3.1 2024-03-02 16:03:19 -08:00
Margaret Fero 39da471f79 Disable Pylint Failure for imghdr deprecation for now 2024-03-02 15:59:17 -08:00
Margaret Fero 570017d3b0 Upgrade Python Version from 3.9 to 3.11 2024-03-02 15:57:06 -08:00
Margaret Fero 3652ac8100
Alphabetize requirements.txt
Alphabetize requirements.txt for developer convenience; this helps to find duplicates and unnecessarily-pinned subdependencies, as well as making the file easier to read and use.
2024-03-02 15:41:06 -08:00
Margaret Fero f8fd76cff0
Remove duplicate types-requests==2.31.0.2
The types-requests==2.31.0.2 dependency was double-listed right next to each other; this commit removes one.
2024-03-02 13:57:09 -08:00
Margaret Fero 206ed9f7fb
Merge pull request #2 from bookwyrm-social/main
No Actual Changes
2024-03-02 13:55:24 -08:00
Mouse Reeve 218171e9bc
Merge pull request #3300 from MaggieFero/MaggieFero-add-timeouts-to-requests.get
Add timeouts to requests.get
2024-03-01 22:49:44 -08:00
Margaret Fero 50b811d9aa
Typo fix
Add a comma
2024-03-01 20:11:14 -08:00
Margaret Fero 1ae9870862
Add timeout to base_activity.py
An instance of requests.get was missing a timeout; this commit adds a timeout of 15 as used in other places in this codebase which already have timeouts.
2024-03-01 20:02:40 -08:00
Margaret Fero db97d76a24
Add timeout to isbn.py
An instance of requests.get in isbn.py lacks a timeout, and this commit adds one with a default of 15 as used other places in the code, where requests.get does already have a timeout.
2024-03-01 19:58:11 -08:00
Mouse Reeve 354388cc8f
Merge pull request #3238 from hughrun/export-fixes
fix multiple issues from user exports config changes
2024-02-29 16:16:25 -08:00
Mouse Reeve 2c59908ddd
Merge branch 'main' into export-fixes 2024-02-29 16:10:20 -08:00
Mouse Reeve 6a70eadba8
Merge pull request #3284 from NetspherePub/072NginxSecurityFixed
Adds production.conf security configuration missing in version 0.7.2
2024-02-29 15:55:56 -08:00
Mouse Reeve ec52460f02
Merge pull request #3274 from Minnozz/author-search
Add search for author
2024-02-29 15:55:12 -08:00
Adeodato Simó 1fabe51261
Move ratings and reviews when switching editions (#3117)
Merged from mattlehrer/move-ratings-and-reviews-when-switching-editions.
Fixes: #2926.
2024-02-21 18:48:32 -03:00
Adeodato Simó e6b6bd648d
Merge branch 'main' into move-ratings-and-reviews-when-switching-editions 2024-02-21 18:42:18 -03:00
Mouse Reeve 9d7965780d
Merge pull request #3285 from polarbirke/fix-label-input-association-for-shelves-filter
Fix label and input association for shelves filter
2024-02-20 16:56:57 -08:00
Mouse Reeve 333fb03c2c
Merge pull request #3290 from bookwyrm-social/korean-locale
Korean locale
2024-02-20 16:56:26 -08:00
Mouse Reeve 8f537ef56a Adds missing migration for Korean locale 2024-02-20 16:45:16 -08:00
Mouse Reeve 6163e1a6be
Merge pull request #3283 from NetspherePub/ko_KR
Add Korean (ko-kr) to LANGUAGES and locale.
2024-02-20 16:44:31 -08:00
Ross Chapman dd1999eb8e
Adds view tests for shelf filters (#3162)
* Adds test file

* Adds success assertion

* Updates tests

* Updates shelf books creation

* Updates assertion to use isbn for Edition model

* Updates query

* trigger workflow test

* Updates validate_html

* Updates comment and test

* Fixes none test

* Adds management command to clear all deleted user data

* Adds success message

---------

Co-authored-by: Mouse Reeve <mousereeve@riseup.net>
Co-authored-by: Mouse Reeve <mouse.reeve@gmail.com>
2024-02-20 16:25:01 -08:00
Søren Birkemeyer 4c0d5ede86 Fix label and input association for shelves filter
This PR correctly associates label and text input of the shelves
filter via for- and id-attributes. With the association in place,
the aria-label can be removed (the label will be announced by
assistive software when the input is focused). This also fixes the
issue that the aria-label was not translated, whereas the label is.
2024-02-10 16:24:52 +00:00
FoW 1c587c5e53 Adds production.conf security configuration missing in version 0.7.2 2024-02-10 17:54:25 +09:00
FoW ddd13a3e2e Add Korean (ko-kr) to LANGUAGES and locale 2024-02-10 16:17:25 +09:00
Mouse Reeve 7469f1f4ca
Merge pull request #3281 from bookwyrm-social/dependabot/pip/django-3.2.24
Bump django from 3.2.23 to 3.2.24
2024-02-07 14:54:50 -08:00
dependabot[bot] 363cb79951
Bump django from 3.2.23 to 3.2.24
Bumps [django](https://github.com/django/django) from 3.2.23 to 3.2.24.
- [Commits](https://github.com/django/django/compare/3.2.23...3.2.24)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-07 22:50:00 +00:00
Hugh Rundle 46a158d701
Merge branch 'main' into export-fixes 2024-02-06 18:31:19 +11:00
Hugh Rundle 8773caa26b
Merge pull request #4 from dato/data_upload_max_size_mb
Support DATA_UPLOAD_MAX_MEMORY_MiB, only, in .env
2024-02-06 18:25:44 +11:00
Carlos Camara 89d8537e1b Add wikidata field to author's template 2024-02-05 22:08:34 +00:00
Carlos Cámara 71f527eb1b
Merge branch 'main' into wikidata 2024-02-04 20:34:51 +01:00
Adeodato Simó 4a9d69e169
Support DATA_UPLOAD_MAX_MEMORY_MiB, only, in .env
Since arithmetic is not allowed in .env files, a change in unit for
the variable seems most usable.
2024-02-04 15:34:04 -03:00
Mouse Reeve d97747078e
Merge pull request #3276 from bookwyrm-social/fixes-version-number
Fixes version number mistakenly reverted
2024-02-03 19:49:48 -08:00
Mouse Reeve db629255db Fixes version number mistakenly reverted 2024-02-03 18:27:59 -08:00
Carlos Cámara 6ac38564e2 Add wikidata field for authors 2024-02-03 22:55:33 +00:00
Bart Schuurmans 6c9ca0bf19 Add search for author 2024-02-03 21:55:46 +01:00
Mouse Reeve 6b1ffbc634
Merge pull request #3185 from bookwyrm-social/check-version-number
Check version number asynchronously
2024-02-03 08:25:52 -08:00
Mouse Reeve 748c934986 Merge migrations upon merge migrations 2024-02-03 08:20:12 -08:00
Mouse Reeve f7580c59a5 Merge branch 'main' into check-version-number 2024-02-03 08:19:46 -08:00
Mouse Reeve 4e2b8af147 Adds merge migration 2024-02-03 08:02:51 -08:00
Mouse Reeve 48f8ee57a6 Merge branch 'main' into check-version-number 2024-02-03 08:02:15 -08:00
Mouse Reeve faf45cf956
Merge pull request #3273 from bookwyrm-social/WesleyAC-freeform-page-number
Allow page numbers to be text, instead of integers
2024-02-03 08:00:34 -08:00
Mouse Reeve a1ac9494b2 Allow admins to un-schedule tasks 2024-02-03 08:00:07 -08:00
Mouse Reeve 6d5752fb4e Adds merge migration for page numbering fix 2024-02-03 07:40:23 -08:00
Mouse Reeve 37aa7ad2f6 Merge branch 'freeform-page-number' of github.com:WesleyAC/bookwyrm into WesleyAC-freeform-page-number 2024-02-03 07:38:02 -08:00
Mouse Reeve e0667c6a03
Merge pull request #3237 from Minnozz/status-title-description
Improve OpenGraph tags for status and book pages
2024-02-03 07:37:00 -08:00
Mouse Reeve 103da863c4
Merge pull request #3239 from Minnozz/user-agent
Replace python-requests with BookWyrm in user agent
2024-02-03 07:27:58 -08:00
Mouse Reeve fa66284000
Merge pull request #3253 from skobkin/patch-autocomplete-fictionbook-format
Adding FictionBook format ("FB2", "FB3") to autocomplete options in "get a copy" block.
2024-02-03 07:26:58 -08:00
Mouse Reeve 0f0420ce04
Merge pull request #3257 from dato/prefer_shared_inbox
Use shared inboxes for mentions too
2024-02-03 07:25:51 -08:00
Mouse Reeve 438d88d8d4
Merge pull request #3260 from bSolt/fix-widths-2023
Fix awkward layout for tablets on /confirm-email, /login, /invite, and /preferences/reactivate
2024-02-03 07:18:35 -08:00
Mouse Reeve 5f2f321ed5
Merge branch 'main' into export-fixes 2024-02-03 07:04:05 -08:00
Mouse Reeve 45cc3dc979
Merge pull request #3249 from dato/cookie_age_setting
Set SESSION_COOKIE_AGE from environment
2024-02-03 07:03:12 -08:00
Mouse Reeve 9c5f6c527b
Fixes translation tags 2024-02-03 06:51:23 -08:00
Mouse Reeve efa29b269c
Merge pull request #3269 from bookwyrm-social/dependabot/pip/aiohttp-3.9.2
Bump aiohttp from 3.9.0 to 3.9.2
2024-01-30 18:03:00 -08:00
Jacob Kerr 2ba7dff845 Fixed shelving date changing when changing editions 2024-01-30 16:53:59 -05:00
Hugh Rundle 21a8570035
Merge pull request #3207 from rsk2/issue-3187
Hide "year in the books" for newly registered users
2024-01-31 07:03:43 +11:00
Hugh Rundle ef6fd608fa
Merge branch 'main' into issue-3187 2024-01-30 18:47:07 +11:00
dependabot[bot] b05621005e
Bump aiohttp from 3.9.0 to 3.9.2
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.9.0 to 3.9.2.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.9.0...v3.9.2)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-30 00:10:13 +00:00
Hugh Rundle 3675a4cf3f
disable user exports if using azure 2024-01-29 14:28:30 +11:00
Hugh Rundle 5f7be848fc
subclass boto3 session instead of adding new env value
Thanks Dato!
2024-01-29 14:10:36 +11:00
Hugh Rundle f96ddaa3e1
Merge pull request #3 from dato/export_job_inject_aws_endpoint_setting
Subclass boto3.Session to use AWS_S3_ENDPOINT_URL
2024-01-29 13:49:45 +11:00
Hugh Rundle adff3c4251
allow user exports with s3
also undoes a line space change in settings.py to make the PR cleaner
2024-01-29 13:45:35 +11:00
Hugh Rundle 765fc1e43d
fix tests 2024-01-29 12:28:37 +11:00
Adeodato Simó c106b2a988
Subclass boto3.Session to use AWS_S3_ENDPOINT_URL
As of 0.1.13, the s3-tar library uses an environment variable
(`S3_ENDPOINT_URL`) to determine the AWS endpoint. See:
https://github.com/xtream1101/s3-tar/blob/0.1.13/s3_tar/utils.py#L25-L29.

To save BookWyrm admins from having to set it (e.g., through `.env`)
when they are already setting `AWS_S3_ENDPOINT_URL`, we create a Session
class that unconditionally uses that URL, and feed it to S3Tar.
2024-01-28 22:21:44 -03:00
Hugh Rundle 2c231acebe
linting and tests 2024-01-28 20:35:47 +11:00
Hugh Rundle a3e05254b5
fix avatar import path 2024-01-28 15:56:44 +11:00
Hugh Rundle 582e97e4a5
Merge branch 'image-serialize' into user-export
pulls Mouse's fix for imagefile serialization
2024-01-28 15:12:15 +11:00
Hugh Rundle 0d619f7eb4
Merge branch 'main' into user-export 2024-01-28 15:11:02 +11:00
Hugh Rundle 2bb9a85591
various fixes
- use signed url for s3 downloads
- re-arrange tar.gz file to match original
- delete all working files after tarring
- import from s3 export

TODO

- check local export and import
- fix error when avatar missing
- deal with multiple s3 storage options (e.g. Azure)
2024-01-28 15:07:55 +11:00
Braden Solt 6add81cf15 move outside of authors "if" 2024-01-27 11:02:42 -07:00
Braden Solt 629acbaa19 add series number on posts in the feed 2024-01-27 10:58:57 -07:00
Braden Solt 940274b1c2 classes that fix widths 2024-01-26 15:47:55 -07:00
Adeodato Simó accb3273f1
When determining privacy, check for unlisted early
If `followers_url` is found in `to`, the post may still be _unlisted_
if `"https://www.w3.org/ns/activitystreams#Public"` appears in `cc`.
Hence this should be checked earlier.
2024-01-26 06:45:54 -03:00
Adeodato Simó 8ac873419f
refactor: eagerly use a set in recipients, get_recipients 2024-01-26 06:29:59 -03:00
Adeodato Simó 31babdfa51
Always prefer shared inboxes when computing receipent lists
This avoids duplicate submissions to remote instances when mentioning
followers (i.e., `POST /user/foo/inbox` followed by `POST /inbox`, which
results in two separate `add_status` tasks, and might generate duplicates
in the target instance).
2024-01-26 06:18:02 -03:00
Adeodato Simó 80ad36e75b
Include SESSION_COOKIE_AGE in .env.example
Suggested-by: Alexey Skobkin <skobkin-ru@ya.ru>
2024-01-25 20:28:15 +01:00
Adeodato Simó 500e4eb4f5
Merge from main to avoid conflicts 2024-01-25 20:27:54 +01:00
Adeodato Simó 82f9aa9da4
Set SESSION_COOKIE_AGE from environment, default to one month
While we do wish for a longer maximum age (up to one year, see #3082),
we only want to do that after termination of active sessions is
implemented (see #2278).

In the meantime, by reading and setting the variable from settings,
we allow site admins to alter the default.
2024-01-25 20:27:24 +01:00
Alexey Skobkin 2d4b11aaee
Adding FictionBook format ("FB2", "FB3") to autocomplete options in "Get a copy" block. 2024-01-25 01:50:10 +03:00
Mouse Reeve 193aeff4d2
Merge pull request #3245 from WesleyAC/redis-aof-auto-compact
Add redis automatic rewrite configuration.
2024-01-24 08:26:45 -08:00
Rohan Sureshkumar c4596544a3 Issue-3187: fix failing tests 2024-01-24 19:18:46 +05:30
Wesley Aptekar-Cassels 30ba8d37dc Add redis automatic rewrite configuration.
This should hopefully prevent the AOF file from growing too large.
2024-01-23 18:19:31 -05:00
Bart Schuurmans eb6bea013f Fix pylint warning 2024-01-21 11:04:08 +01:00
Bart Schuurmans 646b27b7a7 OpenGraph: fall back on book cover when preview images are disabled 2024-01-20 17:34:52 +01:00
Bart Schuurmans ea9d3f8ba1 Use Status.page_image for OpenGraph tags 2024-01-20 17:34:52 +01:00
Bart Schuurmans 290ee997b3 Refactor OpenGraph tags logic 2024-01-20 17:34:52 +01:00
Bart Schuurmans ad56024ffe Add Status.page_image property 2024-01-20 17:34:52 +01:00
Bart Schuurmans f7b4d9ea50 Give individual status page a title and OpenGraph description 2024-01-20 17:34:52 +01:00
Bart Schuurmans 6cb3b97144 Replace python-requests with BookWyrm in user agent
Fixes #3108
2024-01-20 16:15:17 +01:00
Hugh Rundle a563275308
fix comment in env example 2024-01-20 13:27:30 +11:00
Hugh Rundle ddc35a7a52
fix multiple issues from user exports config changes
- improve nginx config
- fix DATA_UPLOAD_MAX_MEMORY_SIZE default not being an int
- translate fallback value in id_to_username template tag
- make location of setting to turn on user exports easier to locate for admins

fixes #3227
fixes #3231
fixes #3232
fixes #3236
2024-01-20 13:19:13 +11:00
Hugh Rundle 26c37de2d4
linting 2024-01-20 07:16:42 +11:00
Mouse Reeve fd0b1d90b0
Merge pull request #3229 from verymilan/nginx-ttf
nginx: fix missing ttf static files
2024-01-18 14:43:05 -08:00
Milan dd5c314bd5 nginx: also serve svg static files 2024-01-18 22:29:43 +01:00
Milan a59dcfc890 nginx: fix missing ttf static files 2024-01-18 17:03:02 +01:00
Rohan Sureshkumar 8e2649ba3b Issue-3187: change variable name and code formatting 2024-01-18 21:23:25 +05:30
Rohan d73141792d
Merge branch 'main' into issue-3187 2024-01-18 21:19:20 +05:30
Hugh Rundle 469172947b
cleanup and linting 2024-01-18 18:43:45 +11:00
Hugh Rundle 833f26fd0e
Merge branch 'main' into user-export 2024-01-18 18:24:56 +11:00
Mouse Reeve fb5fae4251
Merge pull request #3219 from bSolt/issue-3178
Fix awkward clipping on about page
2024-01-17 15:31:52 -08:00
Mouse Reeve c22f189c86
Merge pull request #3216 from dato/dev-tools_require_bookworm
Ensure dev-tools uses bookworm
2024-01-17 15:31:43 -08:00
Mouse Reeve 61a6ee29d8
Merge pull request #3224 from hughrun/move-fix
Pass correct user id in Move notification
2024-01-17 14:25:28 -08:00
Mouse Reeve a585321ef9
Merge pull request #3226 from hughrun/disable-exports
Disable user exports
2024-01-17 14:23:29 -08:00
Hugh Rundle 45d6f1f890
Merge pull request #3215 from ccamara/export_bookshelf
Export bookshelves and review date
2024-01-17 21:20:32 +11:00
Hugh Rundle b990d9ccd8
Pass correct user id in Move notification
We were passing the *requesting* user's moved_to value to the Move notification template, instead of the id of the user that they are being notified about.
Additionally, the id_to_username template tag had no fallback for if the user_id is None.

This resolves both problems and removes an unnecessary space in a template for when the logged in user made the move.

Fixes #3196
2024-01-17 21:06:04 +11:00
Hugh Rundle ea7f3c297e
allow js and css 2024-01-17 20:12:06 +11:00
Hugh Rundle d640e4ac96
disable user exports by default
- new setting to enable user exports defaults to False
- add setting to enable and disable user exports
- do not allow user exports when using s3 storage
- do not serve non-image files from /images/ (requires update to nginx settings)
- increase default file upload limit to 100MB to enable user exports to be imported (can be changed in .env)
2024-01-16 21:32:13 +11:00
Carlos Camara ddbda3ab9c Fix test_export 2024-01-16 08:12:59 +00:00
bSolt 76a3874662 add bulma classes to fix awkward spacing 2024-01-15 23:25:52 -07:00
Rohan 8144507893
Merge branch 'main' into issue-3187 2024-01-15 17:25:36 +05:30
Rohan Sureshkumar 70adf878e8 Merge branch 'issue-3187' of https://github.com/rsk2/bookwyrm into issue-3187 2024-01-15 17:23:17 +05:30
Rohan Sureshkumar 5ef104b802 Issue-3187: addressing review comments 2024-01-15 17:22:33 +05:30
Hugh Rundle d4d2734dab
ignore exports dir 2024-01-14 14:14:20 +11:00
Hugh Rundle 62cc6c298f
oops
- remove test export files
- check in emblackened files
2024-01-14 12:19:59 +11:00
Hugh Rundle cbd08127ef
initial work on fixing user exports with s3
- custom storages
- tar.gz within bucket using s3_tar
- slightly changes export directory structure
- major problems still outstanding re delivering s3 files to end users
2024-01-14 12:14:44 +11:00
Adeodato Simó eb13eb9882
Invalidate active_shelf when switching editions 2024-01-13 19:00:57 +01:00
Adeodato Simó 9a487b0442
Ensure dev-tools uses bookworm
In 1937177e1 ("dev-tools: use apt source for Node instead of setup script"),
I introduced the use of `Signed-By` with a public key block, which is only
supported in bookworm (bullseye only supports fingerprints, TTBOMK).

Python's Docker images already use bookworm by default, but we explicitly
require it now to avoid build errors if someone has a very old image laying
around (see, e.g., #3190).

(This can be dropped after Debian 13 ‘trixie’ is released.)
2024-01-13 17:55:21 +01:00
Carlos Camara 854eb36618 Export bookshelves and review date 2024-01-13 16:47:51 +00:00
Hugh Rundle b04ebe397b
Merge pull request #3189 from ccamara/2965_export_readthrough
Export ReadThrough in the csv export
2024-01-12 16:35:41 +11:00
Hugh Rundle 5d13bf8e49
Merge branch 'main' into 2965_export_readthrough 2024-01-12 16:12:01 +11:00
Rohan 6dc95a82d6
Merge branch 'bookwyrm-social:main' into issue-3187 2024-01-09 17:06:22 +05:30
Rohan Sureshkumar 1a682753c0 Issue-3187: changes 2024-01-09 15:31:05 +05:30
Mouse Reeve a4599d0374
Merge pull request #3205 from bookwyrm-social/revert-3079-deleted_user_follow_request
Revert "Don't show notification for user follow request if the user is inactive"
2024-01-08 10:28:27 -08:00
Mouse Reeve 83ff880603
Revert "Don't show notification for user follow request if the user is inactive" 2024-01-07 08:31:48 -08:00
Carlos Camara ce18d343e8 Fix pylint error and code format 2024-01-06 09:55:39 +01:00
Carlos Camara 93cab480d6 Code format 2024-01-06 09:50:14 +01:00
Mouse Reeve 1966f1d9a3
Merge pull request #3199 from bookwyrm-social/dependabot/pip/pycryptodome-3.19.1
Bump pycryptodome from 3.16.0 to 3.19.1
2024-01-05 16:54:55 -08:00
dependabot[bot] f267fc3235
Bump pycryptodome from 3.16.0 to 3.19.1
Bumps [pycryptodome](https://github.com/Legrandin/pycryptodome) from 3.16.0 to 3.19.1.
- [Release notes](https://github.com/Legrandin/pycryptodome/releases)
- [Changelog](https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst)
- [Commits](https://github.com/Legrandin/pycryptodome/compare/v3.16.0...v3.19.1)

---
updated-dependencies:
- dependency-name: pycryptodome
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-05 17:42:04 +00:00
Wesley Aptekar-Cassels 6cd2c91135 Allow page numbers to be text, instead of integers.
Fixes: #2640
2024-01-04 19:09:39 -05:00
Carlos Camara c2622a510c Change else statement to None vs "" 2024-01-04 11:40:40 +01:00
Carlos Camara ebcc81dd73 Revert changes to default book
These changes were introduced by mistake in my previous commit.
2024-01-04 11:33:26 +01:00
Carlos Camara 30c9ec9611 Prevent lint error
See @hughrun 's explanation https://github.com/bookwyrm-social/bookwyrm/pull/3189#issuecomment-1876145423
2024-01-04 11:28:17 +01:00
Carlos Camara 51cb70d344 Change readhtrough order 2024-01-04 11:27:17 +01:00
Carlos Camara 9acb5f66fe Convert DateTime to date 2024-01-04 11:26:44 +01:00
Carlos Camara ae5950f187 Add readthrough fields to text_export.py 2024-01-04 11:10:38 +01:00
Carlos Camara 766a2163dd Code formatting 2024-01-03 20:41:31 +01:00
Carlos Camara db8c686dd3 Include book Readtrhough in the csv export 2024-01-03 15:43:15 +01:00
Mouse Reeve 597378bb78
Merge pull request #3183 from bookwyrm-social/erase_user_command
Adds management command to clear all deleted user data
2024-01-02 20:13:03 -08:00
Mouse Reeve 9c3e6384f8
Merge pull request #3118 from rosschapman/let-a-user-search-within-their-books
Let a user search books within their shelves
2024-01-02 18:37:33 -08:00
Mouse Reeve 01db77a745 Adds success message 2024-01-02 18:29:55 -08:00
Mouse Reeve d287581620 Fixes html validation error 2024-01-02 13:31:18 -08:00
Mouse Reeve 193a1c7d54 updates wording and fixes get or create logic 2024-01-02 13:28:25 -08:00
Mouse Reeve 8be9e91d21 Re-use schedules rather than creating new ones 2024-01-02 13:18:26 -08:00
Mouse Reeve f36af42f41 Adds view to see scheduled tasks 2024-01-02 13:05:44 -08:00
Mouse Reeve 5509941aa4 Adds schedule-able task to check for version updates 2024-01-02 13:05:26 -08:00
Mouse Reeve d6f7f76c4d Removes outdated/unused version and updating code
I had the bright idea of creating this update script but it doesn't work
and hasn't been maintained, so it's just sitting there causing confusing
and requiring weird things to exist in other places.

Now, the unused `version` field can be removed and I can scrap the
management command for getting versions.
2024-01-02 11:37:01 -08:00
Mouse Reeve 381490e31d Adds management command to clear all deleted user data 2024-01-02 10:50:46 -08:00
Mouse Reeve addfee0607
Merge pull request #3182 from bookwyrm-social/broken-migration
Removes part of migration causing upgrade issues
2024-01-02 10:50:35 -08:00
Mouse Reeve 2a85378456 Removes part of migration causing upgrade issues 2024-01-02 09:57:41 -08:00
Mouse Reeve d9a640c809 Fixes version number 2024-01-02 08:36:42 -08:00
Mouse Reeve 0756c5ac5c
Merge pull request #3180 from bookwyrm-social/version-0-7-0
Version 0.7.0 miscellenea
2024-01-01 19:58:15 -08:00
Mouse Reeve 913a19c8f0 Formats migration file 2024-01-01 19:33:49 -08:00
Mouse Reeve e2249f2515 Updates locales 2024-01-01 19:30:03 -08:00
Mouse Reeve f72ada4780 Updates javascript cache buster just in case 2024-01-01 19:29:43 -08:00
Mouse Reeve 86d79f537a Adds merge migration 2024-01-01 19:29:24 -08:00
Mouse Reeve fb16806afe
Merge pull request #3177 from dato/naturalday_partial_fixes
Adjustments to naturalday_partial
2024-01-01 19:16:16 -08:00
Mouse Reeve ffeca9f908
Merge pull request #3150 from dato/get_representative_atomic
Make get_representative() atomic
2024-01-01 19:14:19 -08:00
Mouse Reeve 45d33c37ea
Merge pull request #3175 from dato/prefer_nodesource
dev-tools: ensure we install Node from upstream
2024-01-01 19:12:02 -08:00
Mouse Reeve ca79cb1ca7
Merge pull request #3054 from bookwyrm-social/user-migration
User migration via export file
2024-01-01 19:04:43 -08:00
Mouse Reeve 5647477ba7
Merge pull request #3154 from bookwyrm-social/ukrainian
Adds Ukranian locale and updates locales
2024-01-01 18:54:43 -08:00
Adeodato Simó 4711b3bc19
naturalday_partial: simplify/refactor 2024-01-01 18:36:31 +01:00
Adeodato Simó 0d908b594c
naturalday_partial: do not naturalize dates with missing parts 2024-01-01 18:36:31 +01:00
Adeodato Simó 0e3936cb61
naturalday_partial: do naturalize date and datetime objects 2024-01-01 18:36:30 +01:00
Dato Simó 09b2dea995 dev-tools: ensure we install Node from upstream
Fixes: #3173 ("`bw-dev build` fails")
2024-01-01 09:01:21 -03:00
Mouse Reeve 3754718916 Updates locales again 2023-12-30 15:54:06 -08:00
Mouse Reeve 9b3f4933ac Fixes language code for Ukrainian 2023-12-17 06:57:05 -08:00
Mouse Reeve 47cdc14bc0
Update bookwyrm/migrations/0189_alter_user_preferred_language.py
Co-authored-by: Demid <grrrr@protonmail.com>
2023-12-17 06:54:39 -08:00
Mouse Reeve 430e4eb90d
Update bookwyrm/settings.py
Co-authored-by: Demid <grrrr@protonmail.com>
2023-12-17 06:52:49 -08:00
Ross Chapman b728bb4323 Uses block trans 2023-12-16 12:05:35 -08:00
Ross Chapman a4172214d1 Updates size of filters panel label 2023-12-15 13:17:23 -08:00
Ross Chapman fb36958444 Removes unused variable 2023-12-14 13:47:51 -08:00
Ross Chapman 44d21d1ba4 Updates view logic 2023-12-14 13:04:45 -08:00
Ross Chapman bd3acdbf31 Puts string in template 2023-12-14 12:33:27 -08:00
Ross Chapman 4a4046a704 Shows message if empty and renames "search" to "filter" 2023-12-14 11:30:01 -08:00
Ross Chapman 7cca199a11 Merge branch 'main' into let-a-user-search-within-their-books 2023-12-14 10:25:05 -08:00
Hugh Rundle 1649457372
Merge pull request #3156 from hughrun/user-migration
fix upsert_statuses
2023-12-13 20:59:47 +11:00
Hugh Rundle 7fcadb1d4d
fix upsert_statuses
- remote_id is now updated on import of statuses
- statuses cannot be imported unless source has target listed in alsoKnownAs or movedTo
- add alert boxes to import and export screens advising of the above
- update tests accordingly
2023-12-13 20:55:38 +11:00
Mouse Reeve 5c0e159d43 Adds Ukranian locale and updates locales 2023-12-12 15:42:40 -08:00
Mouse Reeve 000e5e6145
Merge pull request #3152 from bookwyrm-social/fixes-typo-in-move-notice
Fixes incorrect translation and display of moved user page
2023-12-12 14:59:00 -08:00
Mouse Reeve 8bb5a664c5 Fixes incorrect translation and display of moved user page 2023-12-11 20:12:14 -08:00
Mouse Reeve e032e5491d
Merge pull request #3144 from villasv/patch-1
Update page formatter on ordered collection
2023-12-11 19:54:24 -08:00
Mouse Reeve 4bfa1ca5b8
Merge pull request #3124 from hughrun/softblock
Allow removing followers and fix follow rejections
2023-12-11 19:49:45 -08:00
Adeodato Simó 13374917f3
Make get_representative() atomic 2023-12-11 20:48:32 -03:00
Mouse Reeve 799f842115
Merge pull request #3146 from dato/setup_test_data
Faster tests with setUpTestData
2023-12-11 15:45:40 -08:00
Adeodato Simó aa67f598dd
Explicitly set doctype to html5 when invoking tidy_document()
Many tests break without this on newer versions of html-tidy.
2023-12-11 19:40:48 -03:00
Adeodato Simó 9d502f5ee2
Use setUpTestData() to speed up tests
Pylint's `bad-classmethod-argument` is disabled for each definition
to avoid rewriting the method bodies just to rename `self` → `cls`.
This can be done gradually, as the setUpTestData methods are modified
along the way.
2023-12-11 19:40:30 -03:00
Mouse Reeve 198c0037c6
Merge pull request #3121 from hughrun/413
Display custom page on 413 errors
2023-12-09 08:31:25 -08:00
Mouse Reeve e5d292919c
Merge pull request #3143 from dato/test_ordered_collection_use_bulk_create
Use bulk_create to test ordered collections
2023-12-09 08:30:23 -08:00
Mouse Reeve 029b438355 Clarify import/export of book vs user
I think this wording is a little clearer
2023-12-09 08:18:31 -08:00
Mouse Reeve dd72013225 Small fixes for notifications
Adds a link in the text of the notification, and fixes references to
notification type in the model
2023-12-09 08:09:22 -08:00
Sean Molenaar 5d09c54e57
Merge branch 'main' into feat/api/oauth 2023-12-07 15:38:19 +01:00
Ross Chapman aac8aa1adf Fixes formatting 2023-12-06 11:36:15 -08:00
Ross Chapman 0f6e567b21 Clean up 2023-12-05 19:49:38 -08:00
Ross Chapman c65e165aeb Hides filter if shelf empty 2023-12-05 19:37:29 -08:00
Ross Chapman 979162da10 Uses filters, fixes for any shelf 2023-12-05 19:33:59 -08:00
Ross Chapman b27ed847d5 Fixes result set passed to template 2023-12-05 16:36:58 -08:00
Ross Chapman d93da4e86d Checkpoint 2023-12-05 15:46:08 -08:00
Victor Villas 8fd05004ea
Update page formatter on ordered collection 2023-12-03 20:03:33 -08:00
Adeodato Simó 5384e4c470
Use bulk_create to test ordered collections 2023-11-30 15:58:48 -03:00
Sean Molenaar b7ba6f1a36
urls.py: fix style 2023-11-30 11:25:51 +01:00
Matt Lehrer 7f55495287 Merge branch 'move-ratings-and-reviews-when-switching-editions' of github.com:mattlehrer/bookwyrm into move-ratings-and-reviews-when-switching-editions 2023-11-30 11:15:33 +01:00
Matt Lehrer 31a78a5c9e linted 2023-11-30 11:13:11 +01:00
Mouse Reeve 193a36390b
Merge pull request #3083 from hughrun/file-resubmit
use bw-file-resubmit to retain images during validation checks
2023-11-29 15:36:33 -08:00
Mouse Reeve cf1afefc84
Merge pull request #3133 from dato/search_results_fix_work_order
Do not create a set for already-distinct query result
2023-11-29 15:27:57 -08:00
Mouse Reeve b8bf3d5bd9
Merge pull request #3138 from bookwyrm-social/dependabot/pip/aiohttp-3.9.0
Bump aiohttp from 3.8.6 to 3.9.0
2023-11-27 17:33:18 -08:00
dependabot[bot] 58f149d889
Bump aiohttp from 3.8.6 to 3.9.0
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.6 to 3.9.0.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.6...v3.9.0)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-28 01:02:35 +00:00
Ross Chapman 90cc28986e Merge branch 'main' into let-a-user-search-within-their-books 2023-11-27 11:40:57 -08:00
Adeodato Simó d6eb390cee
Add test that forces book_authors_search_vector_trigger to execute 2023-11-26 15:59:17 -03:00
Adeodato Simó b5805accac
Minor improvements to bookwyrm_book trigger code
- do not COALESCE columns that cannot be NULL
- do not bring bookwyrm_book to author names JOIN
- add comments documenting the four steps
2023-11-25 21:49:15 -03:00
Adeodato Simó bbfbd1e97a
Add tests for trigger code (i.e. how search_vector is computed) 2023-11-25 20:54:49 -03:00
Adeodato Simó 9bcb5b80ea
Further simplify bookwyrm_author trigger 2023-11-25 18:13:40 -03:00
Adeodato Simó 8df408e07e
Define search_vector_trigger via Book.Meta.triggers 2023-11-25 17:02:54 -03:00
Adeodato Simó bcb3a343d4
Fix JOIN in author_search_vector_trigger, add missing WHERE clause 2023-11-25 16:23:21 -03:00
Adeodato Simó 416a6caf2d
Define author_search_vector_trigger via Author.Meta.triggers
Previously, triggers lived only in a particular migration file. With
this change, code for the triggers resides in the model, and their
lifecycle is managed through normal Django migrations.
2023-11-25 16:17:51 -03:00
Adeodato Simó 44ef928c3c
Alter object row IDs to force test failure in original code 2023-11-25 16:11:01 -03:00
Adeodato Simó e4d688665c
Remove index for author.search_vector, which is never used 2023-11-24 22:43:12 -03:00
Adeodato Simó 0299f2e235
Add functional tests for search_vector triggers
As metadata changes, search continues to work.
2023-11-24 22:28:41 -03:00
Adeodato Simó c997d2d44a
Add test to assert distinct() clause
Also, tweak other `search_title_author()` tests to verify ordering by
edition rank.
2023-11-24 02:28:27 -03:00
Adeodato Simó e322d3cae1
Do not create a set for already-distinct query result 2023-11-23 23:01:56 -03:00
Hugh Rundle 48904fc60b
Merge pull request #3132 from hughrun/user-migration
notification type migration after merge
2023-11-24 06:51:51 +11:00
Hugh Rundle 99a9a64708
notification type migration after merge 2023-11-24 06:50:32 +11:00
Hugh Rundle 065e15e4db
Merge pull request #3131 from hughrun/user-migration
merge migrations and lint
2023-11-22 21:31:12 +11:00
Hugh Rundle 72c1c6ee3d
merge migrations and lint 2023-11-22 21:29:54 +11:00
Hugh Rundle 0276c15948
Merge branch 'main' into user-migration 2023-11-22 21:00:04 +11:00
Hugh Rundle c6dea2523c
Merge branch 'main' into softblock 2023-11-22 20:06:02 +11:00
Hugh Rundle 6ba7418121
improve tests and minor cleanup 2023-11-22 20:04:17 +11:00
Hugh Rundle 8ed4a997f8
add comment back to bookwyrm.js 2023-11-21 20:20:11 +11:00
Hugh Rundle 2c9ebba5d7
fix reject PR
- rationalise activitypub.Reject and fix model being undefined
- fix not being able to follow users from followers page: 'delete' option now in user_options dropdown
- revert bookwyrm.js
- fix delete_follow_request deleting instead of rejecting
- add user id to 'remove-follow' path
2023-11-21 20:13:56 +11:00
Mouse Reeve 7c2de92df3
Merge pull request #3128 from bookwyrm-social/test-themes
Give admins option to test if a theme loads correctly
2023-11-20 12:26:09 -08:00
Mouse Reeve b6325da9ab
Update bookwyrm/tests/views/admin/test_themes.py
Co-authored-by: Adeodato Simó <73768+dato@users.noreply.github.com>
2023-11-20 10:37:12 -08:00
Mouse Reeve 179dbd75aa Adds tests 2023-11-20 10:23:59 -08:00
Mouse Reeve b022b5a1b7
Merge pull request #3120 from hughrun/permission-required
403 handler
2023-11-20 10:06:24 -08:00
Mouse Reeve c2742b4d80 Updates migrations 2023-11-20 10:02:49 -08:00
Mouse Reeve cfe42305be Merge branch 'main' into test-themes 2023-11-20 10:02:23 -08:00
Mouse Reeve d828ba0bc6 Give admins option to test if a theme loads correctly
If a theme is uploaded incorrectly or has errors in it, users can still
select the theme but it will cause a 500 error on every page, making the
app unusable and also making it impossible for them to switch to a
functional theme.

A better fix would be to fail gracefully, but in lieu of that, this will
at least let admins confirm if a theme is broken safely.
2023-11-20 09:56:51 -08:00
Matt Lehrer 6933f70af3
Merge branch 'bookwyrm-social:main' into move-ratings-and-reviews-when-switching-editions 2023-11-20 09:31:45 +01:00
Mouse Reeve d94b27b723
Merge branch 'main' into user-migration 2023-11-19 19:18:22 -08:00
Mouse Reeve 3d9f339bd5
Merge pull request #3059 from dato/stable_dates_v2
Partial, stable dates with automatic precision field
2023-11-19 19:17:49 -08:00
Mouse Reeve 1d5cc83347
Merge branch 'main' into permission-required 2023-11-19 19:12:32 -08:00
Mouse Reeve d8018cb937
Merge pull request #3125 from hughrun/instance-actor
hide instance actor from users
2023-11-19 19:11:17 -08:00
Mouse Reeve 4da96d937e
Merge pull request #3126 from hughrun/savedlist-pagination
fix saved list pagination
2023-11-19 18:57:57 -08:00
Hugh Rundle 446854ccf0
fix saved list pagination
The SavedLists view was passing through an incorrect "path" value. Now it's not.
2023-11-20 12:45:39 +11:00
Hugh Rundle f011f2bce9
hide instance actor from users
The Instance Actor is required for signing http GET requests but is not a "user" and should not be otherwise interacted with.

- hides instance actor profile page, returning a 404
- excludes instance actor from search results and suggestions including in Getting Started
- replaces link to user profile in user admin page with a brief message box
- replaces panel in user admin page that allows for user to be suspended or removed with a message explaining why that is a very bad idea

fixes #3119
2023-11-20 12:17:52 +11:00
Adeodato Simó ff1f239a57
Use typing_extensions.Self instead of TypeVar 2023-11-19 15:10:14 -03:00
Adeodato Simó 6aaff28c13
Accept argument in naturalday_partial, downcast format if necessary 2023-11-19 15:10:14 -03:00
Adeodato Simó aaea1b1b9e
Add tests for naturalday_partial tag 2023-11-19 15:10:13 -03:00
Adeodato Simó 8dbfba17d6
Merge from 'main' into stable_dates 2023-11-19 15:09:52 -03:00
Hugh Rundle 2ba0e3d7ff
Allow removing followers and fix follow rejections
* adds the ability to remove a user from your followers list
* fixes verbs.Reject to process reject activities for previously accepted follows in both directions

fixes #2635
2023-11-19 20:03:48 +11:00
Hugh Rundle a7fcd898c2
middleware for displaying 413 page
When a RequestDataTooBig exception is thrown, users are largely in the dark about what happened and how it can be fixed.
This commit resolves this by inserting middleware to redirect the request to a custom 413 error page.

This exception is thrown when DATA_UPLOAD_MAX_MEMORY_SIZE is exceeded. The default value is 2.5MB.

Fixes #2340
Fixes #2633
2023-11-18 22:10:36 +11:00
Hugh Rundle 97757fa1ee
fix blocktrans 2023-11-18 15:58:01 +11:00
Hugh Rundle a56ba0ce1c
always return 403 to POST requests
- POST requests need to receive a 403 error code
- minor wording updates
2023-11-18 13:41:52 +11:00
Hugh Rundle 8ddafafa84
make naming consistent 2023-11-18 12:40:36 +11:00
Hugh Rundle d620bd7350
add handler for 403s
fixes #3104
2023-11-18 12:36:03 +11:00
Ross Chapman 68f54cf5a4 Initial commit to create PR 2023-11-16 17:20:23 -08:00
Matt Lehrer f4da9fbf34 remove unnecessary loop.
ReviewRatings are a subclass and are included in the models.Review block
2023-11-16 20:37:46 +01:00
Matt Lehrer bf81192d73
Merge branch 'main' into move-ratings-and-reviews-when-switching-editions 2023-11-16 10:49:05 +01:00
Sean Molenaar e144ce19fa
fix: add include import from django.urls 2023-11-16 10:48:06 +01:00
Matt Lehrer bd920a4630 move reviews to new edition 2023-11-16 10:38:45 +01:00
Matt Lehrer 7684101f15 move ratings to new edition 2023-11-16 10:38:41 +01:00
Mouse Reeve 06568aab88
Merge pull request #3105 from dato/notify_invitation_request
Create notifications for incoming invite requests
2023-11-15 17:27:34 -08:00
Mouse Reeve 5bf27d4fb2
Merge pull request #3115 from bookwyrm-social/dependabot/pip/aiohttp-3.8.6
Bump aiohttp from 3.8.5 to 3.8.6
2023-11-15 17:12:59 -08:00
Mouse Reeve 1a7a843dea Re-creates migrations and removes failing test
I think the test was failing because it was extremely brittle, not
because of anything wrong with the code itself.
2023-11-15 17:08:15 -08:00
Mouse Reeve 62f985edb8 Merge branch 'main' into user-migration 2023-11-15 16:46:18 -08:00
Hugh Rundle 54ec5e2ae0
Fix migrations properly (#3116)
* Revert "fix migrations and linting"
This reverts commit 53e410627f.
* really fix migrations
2023-11-15 19:54:16 +11:00
dependabot[bot] 63530294d4
Bump aiohttp from 3.8.5 to 3.8.6
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.5 to 3.8.6.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.5...v3.8.6)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-14 23:35:55 +00:00
Sean Molenaar da4214ad61 feat: add OAuth authentication
Issue GH-2292
2023-11-14 14:18:35 +01:00
Adeodato Simó 01d4381898
Create notifications for incoming invite requests
Closes: #2066
2023-11-14 07:09:04 -03:00
Mouse Reeve ab9cea1742
Merge pull request #3112 from dato/makemigrations_check
Check no missing migrations in django-tests workflow
2023-11-13 15:21:44 -08:00
Adeodato Simó b81170c149
Add missing migration from #3099 2023-11-13 19:56:00 -03:00
Adeodato Simó a884825b3c
Check no missing migrations in django-tests workflow 2023-11-13 19:56:00 -03:00
Hugh Rundle bbc78f03ae
fix DB migrations (#3111)
fix migrations and linting
2023-11-14 07:21:27 +11:00
Hugh Rundle d5762f1d52
Merge branch 'main' into user-migration 2023-11-13 21:17:07 +11:00
Hugh Rundle 891b72c79c
update user export file to use ActivityPub objects where possible. (#3109)
* add more context to user export page
* fix BookData fields wrong for files
* use to_activity and to_model where possible
* fixes for import and export
- use AP JSON where possible
- minor template wording updates
* import fixes and updates tests
* minor cleanup
* remove todo for mastodon
2023-11-13 21:14:03 +11:00
Mouse Reeve ddf94f8714
Merge pull request #3097 from Tak/fix-initdb
Fix `bw-dev initdb`
2023-11-12 09:37:42 -08:00
Mouse Reeve 43324cf43a
Merge pull request #3099 from dato/notification_type_top_level
Create NotificationType as class, not through API
2023-11-12 09:34:28 -08:00
Hugh Rundle 1bedcdaebd
Merge branch 'main' into file-resubmit 2023-11-11 13:14:52 +11:00
Hugh Rundle f3fc5f6179
add file_resubmit to DUMMY caches settings 2023-11-11 12:45:04 +11:00
Adeodato Simó 99a9dbe5f4
Create NotificationType as class, not through API
This way, we need not list every value again to create the enum.

N.B.: enum values are now accessed as `models.NotificationType.FOO`,
instead of `models.Notification.FOO`.
2023-11-09 22:43:36 -03:00
Adeodato Simó be9d92b1c2
Remove last references to "seal" in partial_date.py and migration 2023-11-09 14:00:45 -03:00
Adeodato Simó edfa6b18a1
Rename utils.sealed_date module (and tests) to utils.partial_date 2023-11-09 14:00:44 -03:00
Adeodato Simó fa80aa54a9
SealedDate renames, pt. 2
• SealedDate -> PartialDate
• MonthSeal  -> MonthParts
• YearSeal   -> YearParts
2023-11-09 14:00:44 -03:00
Adeodato Simó 0e4c5ed439
SealedDate renames, pt. 1
• SealedDateField      -> PartialDateModel
• SealedDateFormField  -> PartialDateFormField
• SealedDateDescriptor -> PartialDateDescriptor
2023-11-09 14:00:44 -03:00
Adeodato Simó c120fa8c87
Rename: templatetags/{sealed_dates => date_ext}.py 2023-11-09 14:00:44 -03:00
Adeodato Simó 2bb7652dfe
Update partial date migration to latest main 2023-11-09 14:00:22 -03:00
Adeodato Simó e928027e16
Merge from main for up-to-date migrations 2023-11-09 14:00:14 -03:00
Adeodato Simó dccac11527
PartialDateField: allow incoming dates without timezone 2023-11-09 13:04:09 -03:00
Levi Bard ebcacfc6c5 Fix bw-dev initdb 2023-11-09 12:57:45 +01:00
Mouse Reeve 44b14f4933 Fixes workflow errors 2023-11-08 16:00:10 -08:00
Mouse Reeve 774b1095a3
Merge pull request #3094 from hughrun/activitypub-files
fix missing types in `BookData` file fields
2023-11-08 15:27:40 -08:00
Mouse Reeve 0bb4b0d71d Changes to how images are serialized
I'm just going to see if any tests fail?
2023-11-08 15:24:47 -08:00
Hugh Rundle 2248206a66
fix missing types in BookData file fields
activitypub.BookData includes fields for 'files' and 'fileLinks'.
This is a problem because BookData is inherited by Book and Author, neither of which have 'files' as a field in the main model.
Additionally, Author doesn't have a value for 'file_links'.
When serializing to JSON, BookData therefore throws 'TypeError: Object of type _MISSING_TYPE is not JSON serializable'

This fixes the problem by removing links and moving fileLinks to activitypub.Book.
2023-11-08 18:30:49 +11:00
Hugh Rundle 0a5e1048ce
Add more info to user export page (#3093)
- match page title to menu
- change description on IMPORT page from 'readthroughs' to 'reading history'
- provide more information on export page about what is and is not included.
2023-11-07 12:09:06 +11:00
Mouse Reeve 9ddd631549
Merge pull request #3089 from bookwyrm-social/notification-and-download-links
UI changes for notification and download link in import/export flow
2023-11-06 16:31:09 -08:00
Mouse Reeve 1b958a9b31
Merge pull request #3091 from hughrun/notification-and-download-links
show filesize on user downloads page
2023-11-06 16:27:14 -08:00
Hugh Rundle 282f7dd8d6
show filesize on user downloads page
- add column to user download page to display filesize
- adds a filter to display file sizes
- don't download the user downloads page from notifications ;)
2023-11-07 11:04:11 +11:00
Mouse Reeve e152b625fa
Merge pull request #3090 from bookwyrm-social/user-migration-instructions
User migration instructions
2023-11-06 14:34:52 -08:00
Mouse Reeve ee88c3b914
Merge pull request #3081 from bookwyrm-social/handle-isbn-error
Fix error produced when an unexpected ISBN format is used
2023-11-06 11:06:46 -08:00
Mouse Reeve 8663e204c7
Merge pull request #3079 from bookwyrm-social/deleted_user_follow_request
Don't show notification for user follow request if the user is inactive
2023-11-06 11:05:50 -08:00
Mouse Reeve e7a1572450
Merge pull request #3086 from bookwyrm-social/user-deletion
Erase user data and statuses on account deletion
2023-11-06 09:49:06 -08:00
Mouse Reeve 3f038b4d67 Moves if to the right place 2023-11-06 09:42:58 -08:00
Mouse Reeve 06d822d9e0 Alternative format for user import guide 2023-11-06 09:35:04 -08:00
Mouse Reeve 85d1760b97 Changes recent exports table
I thought both dates seemed less necessary (happy to be told otherwise)
and the download link should be more explicit
2023-11-06 08:41:36 -08:00
Mouse Reeve 716e64de68 Changes notification links for user import/export
I found it unexpected that the export notification linked me directly to
the file, and wanted the import link to lead me to the import page
2023-11-06 08:27:30 -08:00
Hugh Rundle 15b7b7eaa7
Merge pull request #3088 from hughrun/user-migration
User migration fixes
2023-11-06 16:06:39 +11:00
Hugh Rundle d34b70cb7b
remove pointless viewer_aware 2023-11-06 16:01:34 +11:00
Mouse Reeve ee6e3ed7eb Adds a database field for is_deleted on user 2023-11-05 20:28:23 -08:00
Hugh Rundle 2d185dfb8a
remove unnecessary test data files 2023-11-06 14:51:52 +11:00
Mouse Reeve 27d99a0094 Removes failsafe that was overzealous 2023-11-05 19:47:32 -08:00
Hugh Rundle 93a32f4e15
update import/export user templates
- always explain what export file can be used for
- provide more information about overwrite vs upsert when importing
2023-11-06 14:40:19 +11:00
Hugh Rundle 8d3c2d9bd2
Merge pull request #3085 from bookwyrm-social/migration-explicit-imports
Uses explicit imports to avoid circular import in migrations code
2023-11-06 12:11:59 +11:00
Hugh Rundle 7a6b60772c
Merge pull request #3087 from hughrun/migration-explicit-imports
update references to bookwyrm models in export job
2023-11-06 12:10:47 +11:00
Hugh Rundle d2f06e804f
update references to bookwyrm models in export job 2023-11-06 12:07:40 +11:00
Hugh Rundle a93519ec3e
Merge pull request #3027 from dato/find_links_wrapped_punct
Fix parsing of punctuation in format_links()

fixes #2993  
fixes #3049
2023-11-06 09:42:57 +11:00
Hugh Rundle 1190ea7e69
Merge pull request #3078 from bookwyrm-social/tour-fixes
Update tour to reflect changes in #2201
2023-11-06 09:20:44 +11:00
Mouse Reeve c17a2ec55b Creates snippet for user tag in admin view
The existing display wasn't showing the correct colors and was repeating
code unnecessarily
2023-11-05 10:18:04 -08:00
Mouse Reeve d3668e413d Removes updates fields that was causing problems 2023-11-05 09:59:49 -08:00
Mouse Reeve f353b49d36 Another linting issues 2023-11-05 09:53:57 -08:00
Mouse Reeve 47953c84d7 Fixes linting errors
Apparently I didn't have a linter working!
2023-11-05 09:49:38 -08:00
Mouse Reeve 4de9907456 Adds migration tests 2023-11-05 09:26:49 -08:00
Mouse Reeve 61caeed5a3 Adds migration and more tests 2023-11-05 08:51:42 -08:00
Mouse Reeve 5e42afd85a Pass args and kwargs through status deletion 2023-11-05 08:10:03 -08:00
Mouse Reeve d0c652f0f5
Merge pull request #3084 from bookwyrm-social/find_existing_tests
Adds a couple more tests for find_existing
2023-11-05 08:06:15 -08:00
Mouse Reeve 93a7dd9cf3 Erase user data and statuses on account deletion 2023-11-05 08:00:29 -08:00
Mouse Reeve 9e9e9a9f85 Uses explicit imports to avoid circular import in migrations code 2023-11-05 07:04:05 -08:00
Mouse Reeve ff2bb513ed Adds migration for notification types 2023-11-05 06:56:10 -08:00
Mouse Reeve 89b87db1c8 Adds merge migration 2023-11-05 06:54:29 -08:00
Mouse Reeve 67822d3cb0
Merge branch 'main' into user-migration 2023-11-05 06:52:48 -08:00
Mouse Reeve 10e0f2224a Adds a couple more tests for find_existing 2023-11-05 06:44:39 -08:00
Mouse Reeve 7104e775d8 Updates working of header tour 2023-11-05 06:36:43 -08:00
Hugh Rundle d682e55812
swap out django-file-resubmit
- we decided to fork it, so this now uses the inaugural RC release of bw-file-resubmit (will need to be adjusted once we're confident it's ok to push a full release)
- I was accidentally using the wrong widget lol
2023-11-05 16:34:24 +11:00
Adeodato Simó afad39bf80
Use $ instead of \Z for end of string
They're identical here, since re.M is not used, and the better-known
should be used, for readability.
2023-11-03 19:38:24 -03:00
Adeodato Simó 954a02126e
format_links: parse punctuation inside brackets
Also, consolidate all punctuation tests into a single table-driven one.
2023-11-03 19:38:24 -03:00
Adeodato Simó 7d13cbb10b
Add failing tests for reported bugs in format_links() 2023-11-03 19:38:23 -03:00
Adeodato Simó 294788aa1a
format_links: refactor; support multiple punctuation 2023-11-03 19:38:23 -03:00
Mouse Reeve 116a838eef Fixes typo that confuses isbn 10 and 13 2023-11-02 19:37:58 -07:00
Mouse Reeve f839038c8f Add test for normalizing isbns in book model
Turns out this was actually working as expected
2023-11-02 19:12:46 -07:00
Mouse Reeve 285c513211 Adds test for invalid isbns and handle isbns with dashes 2023-11-02 19:03:15 -07:00
Mouse Reeve 95ba38524b
Merge pull request #3080 from bookwyrm-social/dependabot/pip/django-3.2.23
Bump django from 3.2.20 to 3.2.23
2023-11-02 18:48:30 -07:00
dependabot[bot] 68f1a69b6a
Bump django from 3.2.20 to 3.2.23
Bumps [django](https://github.com/django/django) from 3.2.20 to 3.2.23.
- [Commits](https://github.com/django/django/compare/3.2.20...3.2.23)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-02 22:13:52 +00:00
Mouse Reeve 8c950237a4
Merge pull request #3077 from bookwyrm-social/locales
Fixes plural string, "URL", and updates locales
2023-11-02 15:06:34 -07:00
Mouse Reeve e1217f2054 Don't show notification for user follow request if the user is inactive 2023-11-02 15:04:03 -07:00
Mouse Reeve ae51dcec63
Merge pull request #3039 from dato/ap_image_url
Fix creation of covers for ActivityPub imports
2023-11-02 14:44:44 -07:00
Mouse Reeve 22554f85ad Updates tour to reflect changes in #2201 2023-11-02 14:37:14 -07:00
Mouse Reeve c1a7e4d9eb
Merge pull request #2201 from bookwyrm-social/header-links
Adds "Your Books" to the header and removed "Feed"
2023-11-02 14:34:47 -07:00
Mouse Reeve 416bbd4d9e Fixes plural string, "URL", and updates locales 2023-11-02 14:33:38 -07:00
Mouse Reeve 45fc10e3bf
Merge pull request #3067 from hughrun/2989
add defaults of None to optional AWS values
2023-11-02 14:24:58 -07:00
Mouse Reeve 0502f6ba42
Merge pull request #3076 from bookwyrm-social/move
Add Move activity for user migration (with small change)
2023-11-01 18:19:56 -07:00
Mouse Reeve 86fd62a09e
Merge pull request #3075 from bookwyrm-social/small-migration-fix
Adds reverse migration for populate sort title
2023-11-01 18:19:34 -07:00
Mouse Reeve 2137737d9b Small changes to get blocktrans to work as expected in move code 2023-11-01 17:19:57 -07:00
Mouse Reeve 621cfa7ed2
Merge pull request #2970 from hughrun/move
Add `Move` activity for user migration
2023-11-01 17:14:34 -07:00
Mouse Reeve 6f9c7f39fb Adds reverse migration for populate sort title
This doesn't impact much, it just allows you to reverse the migration,
which you would probably (hopefully) only want ot do in development.
2023-11-01 16:24:47 -07:00
Hugh Rundle c486b9c37e
pylint fixes 2023-10-30 21:47:19 +11:00
Hugh Rundle df43a8e2c5
Use django-file-resubmit plugin
- save cover images to cache when checking author and work for existing records
- fixes #2760
2023-10-30 19:43:39 +11:00
Mouse Reeve 941efb3f72
Merge pull request #3068 from hughrun/3066
make options consistent in celery
2023-10-29 17:30:40 -07:00
Hugh Rundle d2b2cc0521
make options consistent in celery
- changes 'broadcasts' to 'broadcast' in Celery page in admin section
- re-orders celery queues on admin page to be in English alphabetical order (other than priority levels) - this makes them consistent with the Flower interface
- fixes #3066
2023-10-29 11:55:06 +11:00
Hugh Rundle 853b5f28a4
add defaults of None to optional AWS values
fixes #2989
2023-10-29 11:29:49 +11:00
Hugh Rundle 935779b5e3
Merge pull request #3064 from hughrun/user-migrate
stop pylint constantly whining in user-migration branch
2023-10-28 06:53:25 +11:00
Hugh Rundle 25a2615d5f
stop pylint constantly whining 2023-10-28 06:51:26 +11:00
Hugh Rundle 50ac691126
add alt tag 2023-10-28 06:28:43 +11:00
Hugh Rundle 4d35fd45df
template and migration fixes 2023-10-27 22:22:58 +11:00
Hugh Rundle 6f3b1b565f
fixes to move layout and notifs
- make Move notifications less complicated
- moved users cannot do anything other than unmove or log out
- refactor translations for moved users
2023-10-27 22:00:04 +11:00
Adeodato Simó 1952bb6ddc
fix mypy issues
The three "ignore" directives are:

  - avoid unreadable boilerplate from inherited `Field` methods; and:
  - https://github.com/typeddjango/django-stubs/issues/285#issuecomment-600029858
2023-10-24 18:14:05 -03:00
Adeodato Simó 170d1fe205
fix pylint issues (minus no-else-return) 2023-10-24 17:41:07 -03:00
Adeodato Simó 737ac8e908
Implement PartialDateField using SealedDate and a custom descriptor 2023-10-24 17:30:15 -03:00
Adeodato Simó 9752819bdb
Add support for parsing partial isoformats back 2023-10-24 17:30:13 -03:00
Adeodato Simó 4b47646e28
Fix typing hints in sealed_date module
In particular, SealedDate's class methods always return an instance
of the class they're invoked through (i.e., `SealedDate.from_date_parts`
intentionally never returns `MonthSeal` or `YearSeal`).

To propertly annotate this, a type variable is needed (or the much
simpler `Self` in Python 3.11).
2023-10-24 17:29:04 -03:00
Adeodato Simó 5f619d7a39
Implement SealedDateFormField to preserves partial dates
Note that Django forms _already_ have suppport for partial date data; we
just need to extend it when converting to Python (using SealedDate instead
of returning an error).
2023-10-24 17:29:00 -03:00
Adeodato Simó 777c8b4549
naturalday_partial filter for working with SealedDate 2023-10-24 04:32:27 -03:00
Adeodato Simó 46d80d56a5
Rename SealedDate.__str__ to partial_isoformat
Django uses `str(date)` for backends other than PostgreSQL, so do not
break "YYYY-MM-DD" formatting, just in case.
2023-10-24 04:32:27 -03:00
Adeodato Simó a9c605ea97
Add SealedDate class for globally-stable, maybe-incomplete dates 2023-10-24 04:32:27 -03:00
Adeodato Simó 52a979da2d
Add failing test case for "January 1st" offset bug 2023-10-24 04:32:27 -03:00
Hugh Rundle 5592a8e08b
Merge pull request #3061 from hughrun/user-migrate
minor pylint and mypy fixes
2023-10-23 21:32:36 +11:00
Hugh Rundle f30555be0f
minor pylint and mypy fixes 2023-10-23 21:30:17 +11:00
Hugh Rundle f662e4e049
Merge pull request #3060 from hughrun/user-migrate
Fix texts & linting plus minor bugfixes
2023-10-23 20:54:41 +11:00
Hugh Rundle e29c93a1e9
complete jobs more sensibly
- fix tuple in tar export I accidentally broke by following pylint blindly
- just use job.set_status to complete jobs since it does everything we need
- fix/avoid Celery "not JSON deserializable" error by not saving whole job including user value
2023-10-23 20:44:52 +11:00
Hugh Rundle ddec2dbaa9
fix tar types notification docstring 2023-10-23 20:43:49 +11:00
Hugh Rundle b8fc5c9b7a
fix tests 2023-10-23 20:42:56 +11:00
Hugh Rundle 8477d0b89d
Merge branch 'main' into user-migration 2023-10-22 18:47:41 +11:00
Hugh Rundle afb5c01947
Merge pull request #3058 from hughrun/user-migrate
oops import Any
2023-10-22 17:57:57 +11:00
Hugh Rundle 2b6852e7a0
oops import Any 2023-10-22 17:56:46 +11:00
Hugh Rundle d05cf8e59b
Merge pull request #3057 from hughrun/user-migrate
once more into the linting breach!
2023-10-22 17:50:58 +11:00
Hugh Rundle b6b55b2e65
once more into the linting breach! 2023-10-22 17:49:26 +11:00
Hugh Rundle c5e536aeaa
Merge pull request #3056 from hughrun/user-migrate
fix tests and linting
2023-10-22 17:27:57 +11:00
Hugh Rundle 07ef12ce8e
fix tests and linting 2023-10-22 17:26:27 +11:00
Hugh Rundle 0c846ca31f
Merge pull request #3055 from hughrun/user-migrate
formatting and linting fixes
2023-10-22 16:56:20 +11:00
Hugh Rundle 0a2efeb5aa
Merge branch 'user-migration' into user-migrate 2023-10-22 16:55:00 +11:00
Hugh Rundle 6222088f15
Merge branch 'user-migrate' of github.com:hughrun/bookwyrm into user-migrate 2023-10-22 16:53:32 +11:00
Hugh Rundle fd1ebf5f71
formatting and pylint fixes 2023-10-22 16:52:29 +11:00
Hugh Rundle 11a726b40b
Merge pull request #3037 from hughrun/user-migrate
complete most outstanding user migrate tasks
2023-10-22 15:40:22 +11:00
Hugh Rundle c0a5e55f7f
Merge branch 'user-migration' into user-migrate 2023-10-22 15:38:06 +11:00
Hugh Rundle b34a491172
run black 2023-10-22 15:34:25 +11:00
Hugh Rundle a27c652501
admin view for user imports
- makes user_import_time_limit a site setting rather than a value in settings.py (note this applies to exports as well as imports)
- admins can change user_import_time_limit from UI
- admins can cancel stuck user imports
- disabling new imports also disables user imports
2023-10-22 15:07:49 +11:00
Hugh Rundle 836127f369
cooldown period for user exports
add USER_EXPORT_COOLDOWN_HOURS setting for controlling user exports and imports
2023-10-22 10:49:13 +11:00
Hugh Rundle 20114b0059
add notifs and error handling for user export/import 2023-10-22 09:03:28 +11:00
Jascha Ezra Urbach c9e6dcc2d9
Merge pull request #3053 from bookwyrm-social/develop
Release 0.7.0
2023-10-21 18:30:45 +02:00
Jascha Ezra Urbach 00bf2903bc
Bumped version number to 0.7.0 (#3052) 2023-10-21 18:29:45 +02:00
Adeodato Simó 698e74a496
Minor vocabulary fixes and structured data improvements (#3036)
* Remove duplicate Review object under `rating` property

This was preventing validation, since `rating` is not a valid property
(`review` is, which is created from book.html already).

* Drop `bestRating` property in ratings, since it defaults to 5

See <https://schema.org/bestRating> ("If bestRating is omitted,
5 is assumed").

* Create Rating object (and its enclosing Review) in book/rating.html

* Use `position` property for Book objects in a series

`volumeNumber`, previously used, is only valid for objects of type
PublicationVolume (which series members are not).

* Give URL of book series when setting of `isPartOf`

* series.html: Add empty BookSeries object

---------

Co-authored-by: Adeodato Simó <dato@users.noreply.github.com>
2023-10-21 17:53:24 +02:00
Jascha Ezra Urbach 695c67a714
Merge pull request #3051 from bookwyrm-social/jaschaurbach-patch-1
Update bump-version.sh
2023-10-21 17:28:55 +02:00
Jascha Ezra Urbach abb6bcd199
Update bump-version.sh
just a little fix
2023-10-21 17:28:44 +02:00
Jascha Ezra Urbach 4e16800b52
Merge pull request #3050 from bookwyrm-social/bump-version-script
Create bump-version.sh
2023-10-21 17:18:31 +02:00
Jascha Urbach 4a9d80268a
Create bump-version.sh
This scripts reads VERSION (should be semantic version),  automatically
suggest a "minor" version update, and ask for input to use either suggestion, or a new value.

creates a pull request with updated VERSION and creates a tag for the new version.
2023-10-21 17:16:55 +02:00
Hugh Rundle 781b01a007
add error handling and status for user exports
* fix Safari not downloading with the correct filename
* add FAILED status
* don't provide download link for stopped jobs
2023-10-21 19:43:44 +11:00
Jascha Ezra Urbach 1685ac1953
Move version out of settings (#3045)
This removes the content of VERSION from settings.py and moves it into a seperate file which makes it easier to update versionnumbers via script in the future.
2023-10-19 11:29:59 +02:00
Mouse Reeve 2237a7eb9e
Merge pull request #3008 from dato/author_in_citation
Cite author in quotations and alt text
2023-10-18 17:31:55 -07:00
Mouse Reeve caa31de685
Merge pull request #3046 from dato/stylelint-fix
Remaining CSS lints and npm exec cleanup
2023-10-18 17:05:52 -07:00
Adeodato Simó f88a0f8229
Run stylelint to fix remaining issues
Including deletion of two duplicate stanzas introduced in 33c13608a8 ("Refixing
light and dark themes").
2023-10-18 20:39:12 -03:00
Adeodato Simó b78d51410b
bw-dev: drop use of npm exec by setting PATH in Docker image 2023-10-18 20:37:13 -03:00
Adeodato Simó 6392a8e01d
Merge pull request #2032 from viviicat/bw-dev-npm-fix
Conflicts:
	bw-dev
	dev-tools/Dockerfile
	bookwyrm/static/css/bookwyrm/_all.scss
	bookwyrm/static/css/themes/bookwyrm-dark.scss
	bookwyrm/static/css/themes/bookwyrm-light.scss
2023-10-18 18:54:53 -03:00
Jascha Ezra Urbach 912269303e
Merge pull request #2960 from hbrunn/main-systemd-sandboxing
Add sandboxing to systemd examples
2023-10-18 21:00:20 +02:00
Jascha Ezra Urbach abebf82042
Merge pull request #3029 from skmanohar/show-hide-password
Show/Hide password icon
2023-10-18 20:34:12 +02:00
Sidharth 25e8b259f7 Show/Hide password icon 2023-10-18 21:33:37 +05:30
Mouse Reeve 3624763073
Merge pull request #3043 from dato/prettier_rerun_final
Final prettier re-run
2023-10-17 14:28:48 -07:00
Adeodato Simó d55e0b6ba3
Final JS update to match 'es5' trailing comma style
This is  follow-up to cd247a668 ("Update .prettierrc").
2023-10-17 17:11:59 -03:00
Jascha Ezra Urbach 06923c64c1
Merge pull request #3003 from dato/book_info_first_pub_date
Fallback to showing first published date
2023-10-17 20:16:06 +02:00
Jascha Ezra Urbach 3ade72b90d
Merge pull request #3038 from dato/parsed_date_defaults
Stable defaults for incomplete parsed dates
2023-10-17 20:08:04 +02:00
Jascha Ezra Urbach 67f6c0a5a7
Merge pull request #3042 from bookwyrm-social/fix-prettierrc
Update .prettierrc
2023-10-17 19:52:10 +02:00
Jascha Urbach cd247a6689
Update .prettierrc
Forgot to change the file pre-merch
2023-10-17 19:49:32 +02:00
Jascha Ezra Urbach b97dafc303
Merge pull request #3034 from bookwyrm-social/prettier-trailing-comma
introduce .prettierrc
2023-10-17 19:32:04 +02:00
Jascha Ezra Urbach 4d352faae3
Merge branch 'main' into prettier-trailing-comma 2023-10-17 19:31:24 +02:00
Jascha Ezra Urbach f02faa1b74
Merge pull request #3040 from dato/update-node-installation
dev-tools: use apt source for Node instead of setup script
2023-10-17 19:13:41 +02:00
Adeodato Simó 1937177e1a
dev-tools: use apt source for Node instead of setup script
Extra bits:

  - use a single RUN instruction
  - silence upgrade notices from pip and npm
2023-10-17 02:26:22 -03:00
Adeodato Simó 3251ef0bf5
Fix creation of covers for ActivityPub imports
`cover` comes as a JSON dict, but the code was looking for URL as
an attribute.

(This commit leaves the attribute access in place, just in case
`cover` is updated to serialize as Document proper.)
2023-10-16 17:43:04 -03:00
Adeodato Simó 8afcb9b6d3
Fix tests warning: ImportJob.updated_date received a naive datetime 2023-10-15 22:03:45 -03:00
Adeodato Simó c02306a66b
Default to Jan 1st too on incomplete dates received from ActivityPub 2023-10-15 19:59:51 -03:00
Adeodato Simó c066d11eb1
Bugfix: default missing date components to 1, not today's
Fixes: #2660.
2023-10-15 19:49:00 -03:00
Adeodato Simó 8f0f3e6ace
ImportItem: preserve parsed timezones in date_started, date_read
This is a follow-up to b564e514f ("Handle parsed dates that already
have a timezone on import"), which was applied to `date_added` only.

(Appart from consistency, this will allow to apply future parsing fixes
more easily.)
2023-10-15 19:48:02 -03:00
Hugh Rundle f07d730e03
Merge pull request #2980 from CSDUMMI/upstream2
Complete Migrations of Bookwyrm Accounts across instances

Merging this into `user-migration` branch to enable final work on this within the main Bookwyrm repository. We will pull in the final PR from there into `main` when ready.

Thanks to @CSDUMMI and the crew for this huge job.
2023-10-15 15:19:01 +11:00
Hugh Rundle a4bfcb34d5
fix tests and clean up
* cleans up some test logging
* cleans up some commented-out code
* adds export_job model tests
* reconsiders some tests in export user view tests
2023-10-15 15:09:19 +11:00
Hugh Rundle 6667178703
Merge pull request #2981 from rg-wood/installable-pwa
Add: installable as PWA
Resolves #2558
2023-10-15 09:06:24 +11:00
Hugh Rundle c946e7dd82
Merge branch 'main' into installable-pwa 2023-10-15 08:42:17 +11:00
Jascha Urbach 0f79aea36f
introduce .prettierrc
With this pullrequest I introduce .prettierrc with one rule:
'trailingComma': 'none'
2023-10-14 17:52:58 +02:00
Jascha Ezra Urbach 66f62566d6
Merge pull request #3033 from bookwyrm-social/fix-eslint-warning
Fix eslint warning
2023-10-14 17:22:30 +02:00
Jascha Urbach 97adf2f7fd
I changed my own comments to get rid of this warning which I could have better written in the first place. 2023-10-14 17:21:15 +02:00
Jascha Ezra Urbach 0452e8698d
Merge branch 'main' into installable-pwa 2023-10-14 13:57:59 +02:00
Jascha Ezra Urbach 16b7db4639
Merge pull request #3022 from dato/drop_duplicate_isfdb_link
Drop duplicate author link to ISFDB
2023-10-14 13:57:08 +02:00
Jascha Ezra Urbach d7ba0e3a8a
Merge pull request #3023 from dato/series_name_urlencode
URL-encode book series name when linking to it
2023-10-14 13:56:38 +02:00
Adeodato Simó 17d741039c
Remove duplicate test
(Test case already part of test_format_links_simple_url.)
2023-10-09 21:37:39 -03:00
Adeodato Simó 0043329cc1
Simplify literals in _wrapped 2023-10-09 21:09:52 -03:00
Adeodato Simó c3c22022f6
Check for punctuation before checking for wrapping parenthesis
This allows to parse `(URL).` correctly, which was not detected
as URL before.
2023-10-09 21:09:51 -03:00
Adeodato Simó 1778c56be0
URL-encode book series name when linking to it
Closes: #3021.
2023-10-09 04:24:05 -03:00
Adeodato Simó 55eb81dbf9
Drop duplicate author link to ISFDB
Closes: #3018.
2023-10-09 01:16:32 -03:00
R.G. Wood a7e427efc2
Merge branch 'main' into installable-pwa 2023-10-07 13:34:35 +01:00
R.G. Wood 1798abfc3e
Display site name and description for PWA manifest 2023-10-07 13:32:49 +01:00
R.G. Wood 34d5c557d8
Fix syntax styling 2023-10-07 13:32:18 +01:00
Mouse Reeve 3d123bc2f2
Merge pull request #3017 from bookwyrm-social/dependabot/pip/pillow-10.0.1
Bump pillow from 9.4.0 to 10.0.1
2023-10-04 19:00:21 -07:00
dependabot[bot] 7cae5879c8
Bump pillow from 9.4.0 to 10.0.1
Bumps [pillow](https://github.com/python-pillow/Pillow) from 9.4.0 to 10.0.1.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](https://github.com/python-pillow/Pillow/compare/9.4.0...10.0.1)

---
updated-dependencies:
- dependency-name: pillow
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-04 01:09:41 +00:00
Mouse Reeve bcfd4d2efa
Merge pull request #3016 from bookwyrm-social/release-changes
Updates locales and version number for release
2023-10-02 10:22:05 -07:00
Mouse Reeve e4ba09178f
Merge pull request #2949 from bookwyrm-social/user-search
Allow searching for local users when logged out
2023-10-02 10:21:08 -07:00
Mouse Reeve 703a56940c
Merge pull request #2953 from phildini/add-spanish-articles
Add spanish articles
2023-10-02 10:20:51 -07:00
Mouse Reeve 3deddf6355
Merge pull request #2912 from categulario/fix-form-labels
fix ids of labels in invite request form in admin
2023-10-02 10:04:34 -07:00
Mouse Reeve b3bfcf8665 Updates test for new logic 2023-10-02 10:02:42 -07:00
Mouse Reeve 458b258ad5
Merge pull request #3007 from hughrun/signed-get
create instance user on instance creation
2023-10-02 09:52:59 -07:00
Mouse Reeve fcfe34f2f6 Updates locales and version number for release 2023-10-02 09:42:22 -07:00
Hugh Rundle e34fe9a059
Merge pull request #2917 from jderuiter/mypy-utils
Type annotations for utils
2023-10-01 10:29:52 +11:00
Joeri de Ruiter d4088ac854
Merge branch 'main' into mypy-utils 2023-09-28 09:43:40 +02:00
Mouse Reeve 33e179e44b
Merge pull request #3010 from bookwyrm-social/locales
Updates locales
2023-09-27 16:52:36 -07:00
Mouse Reeve 2a08170fb5 Updates locales 2023-09-26 18:14:24 -07:00
Hugh Rundle 088b9ab555
Merge branch 'main' into move 2023-09-26 08:10:18 +10:00
Hugh Rundle 3e38fecd55
id_to_username cleanup 2023-09-26 07:45:45 +10:00
Adeodato Simó 7cfdf235bc
Include author in cover image alt text 2023-09-25 16:03:16 -03:00
Adeodato Simó 80a1180090
Include author name when serializing Quotation 2023-09-25 16:03:16 -03:00
Hugh Rundle b05f2e99e8
undo moves
also cleans up some templates
2023-09-25 22:05:43 +10:00
Hugh Rundle 4fd5e2094a
hopefully fix template 2023-09-25 16:35:02 +10:00
Hugh Rundle 9547edf845
oops close div 2023-09-25 16:21:19 +10:00
Hugh Rundle d67903fd4b
fix tests and templates 2023-09-25 15:49:25 +10:00
Hugh Rundle 01a56540d0
cleanup 2023-09-25 15:29:01 +10:00
Hugh Rundle c95f160216
fix MoveUser errors and clean up
- minor template fixes
- notification logic fixes
- don't dedupe on moved_to or also_known_as
- add migration
2023-09-25 15:14:21 +10:00
Hugh Rundle fe4bc28f37
fix tests 2023-09-24 15:58:52 +10:00
Hugh Rundle b69031c01a
formatting 2023-09-24 12:31:01 +10:00
Mouse Reeve bab28a8fc9
Merge pull request #3000 from dato/position_serialization
Minor improvements to Quotation pure content
2023-09-23 17:47:27 -07:00
Adeodato Simó ec2c5cb546
Only use first publish date if publisher is unknown 2023-09-23 18:23:15 -03:00
Adeodato Simó 2c968e94cb
Fallback to first published date if published date not present 2023-09-23 18:22:02 -03:00
Adeodato Simó fadf30b942
Also use italics for book title in editions.html template 2023-09-23 17:49:38 -03:00
Adeodato Simó cc05cabcb5
Note content: use italics for book titles + em-dash for Quotation 2023-09-23 17:49:38 -03:00
Mouse Reeve ef582f1bc2
Merge pull request #2986 from NetspherePub/2985
Correct EPUB spelling
2023-09-22 17:04:18 -07:00
Mouse Reeve b75b5cb165
Merge pull request #2987 from JJimenez71/main
Pinned versions of docker containers
2023-09-22 17:03:39 -07:00
Mouse Reeve 0a029e6e01
Merge pull request #2992 from jderuiter/new-edition-issues
parent_work was not always included when needed
2023-09-22 17:00:40 -07:00
Mouse Reeve 85b647b7ab
Merge pull request #3002 from dato/django_serve_static_debug
Serve static files in debug mode
2023-09-22 16:17:58 -07:00
Adeodato Simó 1e495684af
Serve static files in debug mode 2023-09-18 19:01:22 -03:00
Hugh Rundle 5b051631ec
Move MVP
* update User model to allow for moved_to and also_known_as values
* allow users to add aliases (also_known_as) in UI
* allow users to move account to another one (moved_to)
* redirect webfinger to the new account after a move
* present notification to followers inviting to follow at new account

Note: unlike Mastodon we're not running any unfollow/autofollow action here: users can decide for themselves
This makes undoing moves easier.

TODO

There is still a bug with incoming Moves, at least from Mastodon.
This seems to be something to do with Update activities (rather than Move, strictly).
2023-09-18 21:21:04 +10:00
Adeodato Simó ce3885d4f6
Use endposition when serializing Quotation 2023-09-17 15:18:48 -03:00
Adeodato Simó 1322a0c693
Substitute “p.” for “page” in page progress serialization 2023-09-17 15:18:21 -03:00
Adeodato Simó 25fd7276ea
pure_content() refactor: shorter conditionals 2023-09-17 15:01:04 -03:00
Joeri de Ruiter af5f71f5ac Revert return type for get_or_set 2023-09-13 10:21:30 +02:00
Joeri de Ruiter 05f8bd0d3c parent_work was not always included in work when needed 2023-09-13 09:46:31 +02:00
Joeri de Ruiter a5cf912ae8 Fix some annotations 2023-09-13 09:22:53 +02:00
Joeri de Ruiter a5ede835b2 Dump dependencies related to typing 2023-09-13 09:09:43 +02:00
FoW d8ba1f4309 Correct EPUB spelling 2023-09-08 22:52:11 +09:00
Joeri de Ruiter 6e9f64262c
Merge branch 'main' into mypy-utils 2023-09-08 08:53:38 +02:00
JJimenez71 2260e14868 Pinned versions of docker containers 2023-09-07 19:30:29 -06:00
CSDUMMI 688978369f Implement self-contained archives to import and export entire users between instances (#38)
Co-authored-by: Daniel Burgess <developerdannymate@gmail.com>
Co-authored-by: Hugh Rundle <hugh@hughrundle.net>
Co-authored-by: dannymate <dannymate@noreply.codeberg.org>
Co-authored-by: hughrun <hughrun@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/GuildAlpha/bookwyrm/pulls/38
Co-authored-by: CSDUMMI <csdummi.misquality@simplelogin.co>
Co-committed-by: CSDUMMI <csdummi.misquality@simplelogin.co>
2023-09-07 22:37:28 +02:00
R.G. Wood b9851d665e
Add: installable as PWA 2023-09-07 13:41:31 +01:00
Mouse Reeve a09b2ab45c
Merge pull request #2964 from bookwyrm-social/delete-announcement-view
Makes the delete announcement view post-only
2023-09-05 16:43:31 -07:00
Mouse Reeve bc870a305f
Merge pull request #2962 from jderuiter/mypy-isbn
Type annotations and tests for isbn
2023-09-01 17:05:01 -07:00
Mouse Reeve c2196fb704
Merge pull request #2948 from bookwyrm-social/populate-sort-title
Pre-populate sort title in edit book form if not provided
2023-09-01 17:01:41 -07:00
Mouse Reeve 47e8f3c3e6
Merge pull request #2967 from 0x29a/version-bump
chore: bump version to match the latest tag
2023-09-01 17:01:04 -07:00
Mouse Reeve b0601a0958 Makes deleting announcements only work via POST 2023-09-01 16:59:56 -07:00
Mouse Reeve 4e999657cc
Merge pull request #2972 from hughrun/opensearch
fix opensearch template
2023-09-01 16:57:10 -07:00
Hugh Rundle d560a6baef
fix opensearch template
* "method" is not a valid attribute of the `Url` element
* "ShortName" cannot be empty - fixed site_name being used before it was assigned
2023-08-30 20:15:20 +10:00
Hugh Rundle e7ba6a3141
initial work to add 'Move' activity 2023-08-29 21:07:41 +10:00
Holger Brunn 0a9ef9e047 Add sandboxing to systemd examples 2023-08-28 07:29:42 +02:00
Abraham Toriz 4c526dfcaa
Don't rely on ids to target inputs from labels 2023-08-25 13:33:55 -06:00
Abraham Toriz dfa935bd72
fix pointed ids of labels in invite request form 2023-08-25 13:29:26 -06:00
0x29a 1c9da7b84b chore: bump version to match the latest tag 2023-08-25 14:11:29 +02:00
Joeri de Ruiter 5eae123668
Merge branch 'main' into mypy-isbn 2023-08-22 11:41:34 +02:00
Joeri de Ruiter 567c103e59
Merge branch 'main' into mypy-utils 2023-08-22 11:40:48 +02:00
Mouse Reeve e5f8e4babc
Merge pull request #2963 from jderuiter/mypy-importers
Type annotations for bookwyrm.importers
2023-08-21 20:39:32 -07:00
Joeri de Ruiter 0686926048 Type annotations for bookwyrm.importers 2023-08-21 16:58:16 +02:00
Joeri de Ruiter f6d8786179 Type annotations for bookwyrm.isbn 2023-08-21 15:46:50 +02:00
Joeri de Ruiter 3760e3b45c Tests for ISBN hyphenation 2023-08-21 15:46:24 +02:00
Joeri de Ruiter 2e88e73509 Remove returned None to make pylint happy 2023-08-21 14:00:09 +02:00
Joeri de Ruiter 0f2c0c034d Removed TODOs. When data is invalid return None. 2023-08-21 13:28:08 +02:00
Joeri de Ruiter 767cd14639 Stricter checks for bookwyrm.utils 2023-08-21 13:10:12 +02:00
Joeri de Ruiter 8f8587f79d Set **kwargs type to Any for ActivityObject.__init__ 2023-08-21 13:09:42 +02:00
Joeri de Ruiter ff8e4597e5 Type annotations for utils 2023-08-21 12:56:32 +02:00
Mouse Reeve 0f8da5b738
Merge pull request #2957 from hughrun/redisfix
fix illegal values in redis jobs
2023-08-19 16:41:50 -07:00
Mouse Reeve c6aaa80c62
Merge pull request #2947 from bookwyrm-social/small-ui-fixes
Small UI fixes
2023-08-19 15:09:12 -07:00
Mouse Reeve 1e0fe6d7c8 Remove duplicate if statement 2023-08-19 15:06:57 -07:00
Hugh Rundle 5ed1441ddb
fix illegal values in redis jobs
1. populate_streams_get_audience

This tries to set status_reply_parent_privacy as None if there is no status.reply_parent, but None is not a valid value for privacy.
This doesn't appear to be  breaking anything but does result in a lot of error messages in the logs.
I have set this to equal the original status.privacy - this won't realy have any effect since it only happens when there is no parent,
however we could set this to "direct" if we want to be highly cautious.

2. rerank_user_task

Again, this doesn't seem to caused major issues, but is throwing errors if the user in question no longer exists for some reason.
This commit checks whether 'user' exists before attempting to rerank.
2023-08-19 08:34:03 +10:00
Margaret Fero d7adada29c
Add Spanish Articles
Added articles for spanish language to list of articles in settings
2023-08-15 22:53:43 -07:00
Philip James 2826e184d2
Merge pull request #7 from bookwyrm-social/main
Update to main
2023-08-15 21:58:38 -07:00
Mouse Reeve 63b60ad62c Removes "all books" link from profile when there are none 2023-08-06 19:40:59 -07:00
Mouse Reeve 185486c6fc Uses {% empty %} instead of if statements 2023-08-06 19:35:50 -07:00
Mouse Reeve 53c8085207
Merge pull request #2946 from bookwyrm-social/followers-page-breadcrumbs
Adds breadcrumbs and better titles to followers/following pages
2023-08-06 19:13:35 -07:00
Mouse Reeve a05942fe15 Allow searching for local users when logged out 2023-08-06 18:23:57 -07:00
Mouse Reeve d9f6449767 Pre-populate sort title in edit book form if not provided
It's confusing to edit a book when this isn't set, so this provides the
best-guess version of the sort title if there isn't one provided, and
allows the user to change it as needed.
2023-08-06 17:57:57 -07:00
Mouse Reeve 15e82ece07
Merge pull request #2854 from bookwyrm-social/report-actions
Record report actions
2023-08-06 16:52:24 -07:00
Mouse Reeve 861d3b1500
Merge pull request #2935 from jderuiter/markdown-import
Convert description from Markdown when importing from Open Library
2023-08-06 16:14:25 -07:00
Mouse Reeve 518f87ef62 Adds merge migration 2023-08-06 16:02:28 -07:00
Mouse Reeve a166af9990
Merge branch 'main' into report-actions 2023-08-06 16:00:59 -07:00
Mouse Reeve e76b44fc8f
Merge pull request #2921 from axiomizer/isbn-hyphenation
Isbn hyphenation
2023-08-06 15:59:19 -07:00
Mouse Reeve b7e7867b9b
Merge pull request #2938 from jderuiter/redirect-referer
On readthrough, progressupdate or status delete return to previous page
2023-08-06 15:41:26 -07:00
Mouse Reeve e8949bbffd Make sure defaults are set on directory filters 2023-08-06 15:37:26 -07:00
Mouse Reeve 27c40ccf20 Uses comma formatting on user follower/following display values 2023-08-06 15:37:26 -07:00
Mouse Reeve 66250e0dd8 Consistent null states and page titles in user profile views 2023-08-06 15:36:56 -07:00
Mouse Reeve 0e43cc4274 Adds breadcrumbs and better titles to followers/following pages 2023-08-06 15:09:45 -07:00
Mouse Reeve 013c726869
Merge pull request #2918 from jderuiter/dutch
Include Dutch locale
2023-08-05 14:34:05 -07:00
axiomizer 83ad45644b Make hyphenated ISBN a property on the book model 2023-08-03 18:01:02 -04:00
Joeri de Ruiter 2dddb2e3da Revert change to redirect when deleting status 2023-08-03 13:18:35 +02:00
Joeri de Ruiter a901014e48 Change import of clean 2023-08-02 19:37:52 +02:00
Joeri de Ruiter ae5c27f3bb Sanitise description from Open Library 2023-08-02 19:30:40 +02:00
Joeri de Ruiter f4a4b59a14 Merge branch 'main' into markdown-import 2023-08-02 19:19:07 +02:00
Mouse Reeve 0be5cf31dc
Merge branch 'main' into isbn-hyphenation 2023-08-01 21:10:10 -07:00
Mouse Reeve 9d69f2fb3e
Merge pull request #2905 from bookwyrm-social/broken-editions
Adds management command to repair editions in bad state
2023-08-01 21:08:43 -07:00
Mouse Reeve 73f1484025
Merge pull request #2915 from axiomizer/main
Add copy button for ISBN
2023-08-01 20:55:12 -07:00
Mouse Reeve 455b0c82ea Fixes typo and outdated comment 2023-08-01 20:53:06 -07:00
Mouse Reeve acafa0b417
Merge pull request #2925 from jderuiter/mypy-connectors
Type annotations and related changes for connectors
2023-08-01 20:46:56 -07:00
axiomizer 3ca36fef4d Make copy button screen reader friendly
revert last commit because prettier was run with the wrong version
This reverts commit 5d3883c9a0.
2023-08-01 22:56:05 -04:00
Mouse Reeve 173d0b77ac
Merge pull request #2937 from jderuiter/create-book-fixes
Fixes for create-book
2023-08-01 19:02:33 -07:00
Mouse Reeve 211b60bba2
Merge pull request #2934 from bookwyrm-social/reduce-status-tasks
Only trigger add_status_task when status is first created
2023-08-01 08:30:43 -07:00
Joeri de Ruiter d1bad521e9 When deleting readthrough, progressupdate or status, return to referer instead of main page 2023-08-01 17:19:10 +02:00
axiomizer 8565367993 Fix pylint issues and failing unit tests 2023-08-01 09:45:13 -04:00
Joeri de Ruiter 220cad8661 Only show author confirmation if new authors are added, show suggestions for parent work and set it correctly. 2023-08-01 15:12:50 +02:00
axiomizer 5d3883c9a0 run prettier on bookwyrm.js 2023-08-01 08:09:10 -04:00
Joeri de Ruiter 1a733746f2 Only remove surrounding p tags if there are no other p tags 2023-08-01 12:17:57 +02:00
Joeri de Ruiter 1a215e9b9e Convert description from Markdown to HTML when importing from Open Library 2023-08-01 11:45:46 +02:00
Mouse Reeve 2f8cf941af
Merge pull request #2933 from joachimesque/remove-links-trailing-punctuation
Remove links trailing punctuation
2023-07-31 18:58:39 -07:00
Mouse Reeve 3336fd0f11 Updates test 2023-07-31 17:48:09 -07:00
Mouse Reeve f6fba19ac4 Only trigger add_status_task when status is first created
I think the reason I didn't do this initially was so that related users
and books, which are added necessarily after the model instance is
crated, will be part of the object when the task runs, but I have
investigated this and because of the transaction.atomic statement in the
to_model method in bookwyrm/activitypub/base_activity.py and in the
status view (added in this commit), this is not an issue.
2023-07-31 17:23:57 -07:00
Joachim 928d56b566 Fix function docstring 2023-07-31 22:15:09 +02:00
Joachim e37ed8ea5e Remove links trailing punctuation 2023-07-31 22:12:37 +02:00
Hugh Rundle c29ca5ad32
Merge pull request #2922 from tararoshan/wip-edit-post-and-save
fix button text when editing posts

Resolves #2642
2023-07-31 16:44:30 +10:00
Hugh Rundle 390f61ff3b
Merge branch 'main' into wip-edit-post-and-save 2023-07-31 16:25:04 +10:00
Hugh Rundle 61283b3d4f
Merge pull request #2929 from joachimesque/search-disable-spellcheck
Disable Spellcheck on header search inputs
2023-07-31 14:42:30 +10:00
Mouse Reeve 588ec80b4c
Merge pull request #2927 from bookwyrm-social/streams-queue
Reduce activity in streams queue from boost tasks
2023-07-30 18:37:49 -07:00
Joachim 6a81f91902 Disable Spellcheck on header search inputs 2023-07-30 22:33:08 +02:00
Mouse Reeve 71dc05f894 Reduce activity in streams queue from boost tasks 2023-07-30 13:07:12 -07:00
Mouse Reeve 30f025dbcd
Merge pull request #2923 from jderuiter/hashtag-naming
Remove '@' from the beginning of hashtag names in activity
2023-07-30 06:27:51 -07:00
Joeri de Ruiter 2920973961 Some small improvements to annotations 2023-07-28 20:54:03 +02:00
Joeri de Ruiter f07d7b02f1 Type annotations and related changes for bookwyrm.connectors 2023-07-28 17:43:32 +02:00
Joeri de Ruiter 8736f2c6ef Remove '@' from the beginning of hashtag names in activity 2023-07-28 11:20:08 +02:00
Tara Sophia Roshan c721e17aa0 Change wording from 'Save' to 'Update'
I think this wording is more clear.
2023-07-27 17:45:06 -05:00
Tara Sophia Roshan 9cd599dee3 Indicate edited post is saved
Should close #2642 and #2671. Gives a minimal solution to #2668.
2023-07-27 00:22:12 -05:00
axiomizer 2293c1c5a8 Revert part of "Hyphenate ISBN numbers and add copy button" related to copy button
This partially reverts commit d2c4785af1.
2023-07-25 08:54:49 -04:00
axiomizer bd26da351a Hyphenate ISBN numbers and add copy button 2023-07-25 08:54:49 -04:00
Joeri de Ruiter fec6f39e4e Migration to include Dutch in user.preferred_language 2023-07-23 21:34:28 +02:00
Joeri de Ruiter 308dfd1be0 Include Dutch locale 2023-07-23 21:27:42 +02:00
Joeri de Ruiter 0354e53eea Type annotations for utils 2023-07-23 20:50:44 +02:00
axiomizer 9a30a3656a satisfy js linter 2023-07-22 22:34:10 -04:00
Mouse Reeve 07aca2f62c
Merge pull request #2916 from jderuiter/mypy-integration
mypy integration
2023-07-22 18:14:10 -07:00
axiomizer 1bda8a5d9d Revert part of "Hyphenate ISBN numbers and add copy button" related to hyphenation
This partially reverts commit d2c4785af1.
2023-07-22 14:25:58 -04:00
Joeri de Ruiter 75f37d7361 Added mypy to scripts and workflow, and some first annotations for celerywyrm 2023-07-22 13:27:43 +02:00
axiomizer d2c4785af1 Hyphenate ISBN numbers and add copy button 2023-07-21 21:27:46 -04:00
Mouse Reeve eae06602a9 Fixes test data 2023-07-21 14:38:28 -07:00
Mouse Reeve 9c5b5d0ac1 Updates version 2023-07-20 19:08:47 -07:00
Mouse Reeve c4d72829e9
Merge pull request #2879 from bookwyrm-social/reactivation-bug
Don't allow invalid account reactivation
2023-07-20 19:07:18 -07:00
Mouse Reeve c947360da8
Merge pull request #2910 from WesleyAC/no-unauthed-remote-profile-view
Don't show remote profiles to unauthenticated users
2023-07-20 19:06:50 -07:00
Mouse Reeve 2f2dae074b
Merge pull request #2908 from WesleyAC/celery-functional-queues
Switch from priority queues to function-based queues
2023-07-20 19:05:55 -07:00
Mouse Reeve 9d531fcb62
Merge pull request #2909 from bookwyrm-social/dependabot/pip/aiohttp-3.8.5
build(deps): bump aiohttp from 3.8.3 to 3.8.5
2023-07-20 18:56:25 -07:00
Wesley Aptekar-Cassels aae1d10eea Don't show remote profiles to unauthenticated users 2023-07-20 20:29:08 -04:00
Wesley Aptekar-Cassels 3e78e398c0 Switch from priority queues to function-based queues
Fixes: #2907
2023-07-20 12:25:30 -04:00
dependabot[bot] 7d1f3deaca
build(deps): bump aiohttp from 3.8.3 to 3.8.5
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.3 to 3.8.5.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/v3.8.5/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.3...v3.8.5)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-20 15:55:55 +00:00
Mouse Reeve ccf3a4c5c1 Skip trying to match editions
It's rare that it will be useful, and it was a huge hassle.
2023-07-18 19:33:39 -07:00
Mouse Reeve 8b88de624d Adds test and fixes logic errors 2023-07-17 20:00:45 -07:00
Mouse Reeve eee4e30e25 Adds managment command to repair editions in bad state 2023-07-17 11:22:59 -07:00
Mouse Reeve fbb9d75cc8 Avoid server error when encountering broken edition
If an edition is missing its work, this change allows the page to still
load without a server error; this is important because otherwise the
book will break every page it appears on, including the feed page.
2023-07-17 07:07:01 -07:00
Mouse Reeve 107f5b38ca
Merge pull request #2904 from bookwyrm-social/updating-pluralization-error
Fixes plural display on import admin page
2023-07-17 06:40:15 -07:00
Mouse Reeve ac4276f212
Merge pull request #2834 from zachflanders/2678
Add support for title sort to ignore initial article
2023-07-17 06:04:25 -07:00
Mouse Reeve 6778046906 Formats large numbers 2023-07-17 05:53:23 -07:00
Mouse Reeve fbb6c41035 Joins entire sentence in import pluralization string 2023-07-17 05:49:40 -07:00
Mouse Reeve 815e788245
Merge pull request #2631 from rritik772/pluralization-error
fixed singularisation/pluralisation
2023-07-17 05:46:34 -07:00
Mouse Reeve 3bd20e3ff8
Set batch size to 1,000
Updated as per the comments on the PR so this is ready to merge
2023-07-17 05:42:17 -07:00
Mouse Reeve f39a1fd580
Merge pull request #2894 from bookwyrm-social/dependabot/pip/django-3.2.20
build(deps): bump django from 3.2.19 to 3.2.20
2023-07-16 07:15:39 -07:00
Mouse Reeve 0818d5aabb
Merge branch 'main' into report-actions 2023-07-16 07:13:42 -07:00
Mouse Reeve 0832a2fa8e
Merge branch 'main' into reactivation-bug 2023-07-16 07:13:34 -07:00
Mouse Reeve c2a7b9a77b
Merge pull request #2903 from bookwyrm-social/prettier-update
Fixes prettier JS complaints
2023-07-16 07:13:23 -07:00
Mouse Reeve 245ae35a81 Pin prettier version in github workflow 2023-07-16 06:57:31 -07:00
Mouse Reeve d56b9f14a2 Handles changing user perms from report 2023-07-16 06:36:32 -07:00
Mouse Reeve 040dca0c31 Places first item of report history at top 2023-07-16 06:11:26 -07:00
Mouse Reeve a7e6919b96 Fixes confirm email slow and adds test 2023-07-16 05:55:38 -07:00
Mouse Reeve 61037cf38a
Merge pull request #2883 from hughrun/modal-fix
Ensure report button triggers modal
2023-07-15 19:58:36 -07:00
dependabot[bot] 7f3a8f27ab
build(deps): bump django from 3.2.19 to 3.2.20
Bumps [django](https://github.com/django/django) from 3.2.19 to 3.2.20.
- [Commits](https://github.com/django/django/compare/3.2.19...3.2.20)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-05 23:27:36 +00:00
Hugh Rundle dd92c53410
Merge pull request #2887 from hughrun/federation
add `FEDERATION.md` so other app maintainers understand how BookWyrm behaves in the fediverse.
2023-07-03 09:21:40 +10:00
Hugh Rundle fad1eb8952
clean up and add stopped-reading shelf type 2023-07-03 08:38:53 +10:00
Hugh Rundle c875b18e34
complete FEDERATION.md initial file 2023-07-01 14:23:02 +10:00
Hugh Rundle 1841d196ff
Ensure report button triggers modal
Clicking on "report" in any context closed the dropdown menu and required a second click on the dropdown to trigger the modal.
With this change, the modal opens as expected.

Reverses part of #2322
2023-06-26 12:22:14 +10:00
Hugh Rundle e783c90693
add FEDERATION info 2023-06-26 08:27:14 +10:00
Mouse Reeve 6a949c24e2 Typo fix 2023-06-21 15:52:32 -07:00
Mouse Reeve 11f1a4662e Don't allow invalid account reactivation 2023-06-21 15:47:20 -07:00
Mouse Reeve 4f6a235d77 Reverses order of report action list 2023-06-21 15:05:02 -07:00
Jascha Ezra Urbach a601be4708
Merge branch 'main' into 2678 2023-06-01 16:53:28 +02:00
Mouse Reeve 65e3a31354
Merge pull request #2864 from bookwyrm-social/locales
Update locales
2023-05-30 11:37:01 -07:00
Mouse Reeve c6d23ba26a Record statuses deleted in reports 2023-05-30 11:35:47 -07:00
Mouse Reeve 0bb0537215 Updates version number 2023-05-30 11:00:12 -07:00
Mouse Reeve ca3054fdac
Merge pull request #2827 from hughrun/2571
Retain subjects and authors when new book form fails validation
2023-05-30 10:51:52 -07:00
Mouse Reeve 9056a5d9e7
Merge pull request #2842 from bookwyrm-social/set-remote-server
Set remote servers synchonously where possible
2023-05-30 10:51:39 -07:00
Mouse Reeve a1b3fc1a79 Update locales 2023-05-30 10:50:09 -07:00
Mouse Reeve d251f4201b
Merge pull request #2857 from bpeel/no-rating
Show “no rating” instead of blank stars if the review has no rating
2023-05-30 10:42:09 -07:00
Mouse Reeve aec99ba173
Merge pull request #2862 from kvibber/rssdate
Add dates to RSS feeds and sort by most recent first
2023-05-30 10:36:01 -07:00
Mouse Reeve bf0225fe93
Merge pull request #2858 from bookwyrm-social/dependabot/pip/requests-2.31.0
build(deps): bump requests from 2.28.2 to 2.31.0
2023-05-29 19:54:48 -07:00
Mouse Reeve a4ccd45537
Merge pull request #2812 from hughrun/gts
Fix federation with GoToSocial and inconsistent KeyId in headers
2023-05-29 19:54:00 -07:00
Kelson Vibber 70679856bd apply linter 2023-05-28 22:42:37 -07:00
Kelson Vibber c21d580fd8 sort feed by most recent 2023-05-28 22:38:53 -07:00
Kelson Vibber 98f5cd9393 apply linting 2023-05-28 22:25:01 -07:00
Kelson Vibber 637e0376d4 rss dates 2023-05-28 21:55:26 -07:00
Philip James 9ff28d97b1
Merge pull request #6 from bookwyrm-social/main
Update to upstream
2023-05-24 23:42:35 -07:00
dependabot[bot] 76fc0dfcc4
build(deps): bump requests from 2.28.2 to 2.31.0
Bumps [requests](https://github.com/psf/requests) from 2.28.2 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.2...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-23 05:59:52 +00:00
Neil Roberts 603b2d9502 Show “no rating” instead of stars if the review has no rating
The stars.html template now outputs a span containing “no rating” when
the stars represent a non-existent or zero rating. This text is already
translated because it was previously added as a invisible text only for
screen readers. The span is given a special CSS class so that it can be
styled as italic in the stylesheet.

There is now also an extra span in book.html to group the stars with the
“(2 reviews)” text. This is needed because the outer div is using a flex
layout and it eats the spacing between the two parts otherwise.

Fixes #2856
2023-05-22 15:40:18 +02:00
Mouse Reeve affaf3d0ba Fixes tests and incorrect class method reference 2023-05-22 06:39:23 -07:00
Mouse Reeve b3a519c082 Converts report "comments" into broader "actions" table
This table will now track all actions taken on a report, like resolving
it, re-opening it, suspending the reported user, et cetera, in addition
to comments. When there are multiple admins, this change will make it
easier to understand what actions have been taken by whom on a report.
2023-05-16 11:00:33 -07:00
Mouse Reeve ab146f652a Adds action types to report comments table 2023-05-16 09:02:43 -07:00
Mouse Reeve ee1dd612fb
Merge pull request #2853 from bookwyrm-social/locales
Updates locales
2023-05-15 13:46:18 -07:00
Mouse Reeve aae8b1ac14 Updates locales 2023-05-15 11:52:36 -07:00
Mouse Reeve 24d59315df
Merge pull request #2843 from bookwyrm-social/user-reports-link
Show all (not just open) reports when linked from user admin
2023-05-15 06:04:42 -07:00
Mouse Reeve d6a321dda9
Merge pull request #2839 from WesleyAC/optimize-get-audience-user-id-only
Optimize get_audience by only fetching IDs
2023-05-15 06:03:40 -07:00
Mouse Reeve 120a0f1882
Merge pull request #2852 from bpeel/remove-from-translate-shelf-name
Use the translated shelf name in the “remove from” shelf button
2023-05-15 05:43:13 -07:00
Mouse Reeve 3a5ddf33a9
Merge pull request #2850 from bpeel/other-edition-translate-shelf
Use the translated shelf name in the message for when another edition is shelved
2023-05-15 05:39:13 -07:00
Mouse Reeve 0e0d9d2d08 Updates ignore html error list 2023-05-15 05:31:07 -07:00
Neil Roberts 666f09c576 Use the translated shelf name in the “remove from” shelf button
The button to remove a book from a shelf when looking at the book’s page
wasn’t using the translated shelf name. It was also concatenating
strings instead of using a placeholder, which is difficult to translate
in some languages. This fixes it to use the translate_shelf_name
function and use the same placeholder string as in other places.
2023-05-15 11:26:12 +02:00
Neil Roberts a4ea4082e6 Use the translated shelf name in message when another edition is shelved
In the page for an edition, if the user has a different edition of the
same work on a shelf then a message is shown. Previously the name of the
status shelves wasn’t being translated.
2023-05-12 15:33:51 +02:00
Jascha Ezra Urbach 70a5153271
Merge pull request #2838 from bpeel/merge-works-command
Add a management command to merge works
2023-05-11 16:29:58 +02:00
Jascha Ezra Urbach 45127c9648
Merge pull request #2847 from bookwyrm-social/dependabot/pip/django-3.2.19
build(deps): bump django from 3.2.18 to 3.2.19
2023-05-11 16:27:19 +02:00
dependabot[bot] 1139d214a0
build(deps): bump django from 3.2.18 to 3.2.19
Bumps [django](https://github.com/django/django) from 3.2.18 to 3.2.19.
- [Commits](https://github.com/django/django/compare/3.2.18...3.2.19)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-09 22:15:37 +00:00
Mouse Reeve 379db26300 Fixes user model tests for new param 2023-05-07 10:01:33 -07:00
Mouse Reeve 912e92bacd Show all (not just open) reports when linked from user admin 2023-05-07 09:50:24 -07:00
Mouse Reeve bfb29c0d74 Set remote servers synchonously where possible 2023-05-07 09:24:45 -07:00
Zach Flanders ad1ddf2bff Fixing batch size 2023-04-29 09:48:01 -05:00
Zach Flanders 490064cdf8 updating sort title migration 2023-04-29 09:43:55 -05:00
Hugh Rundle 5c9b962639 retain additional authors on form failure when editing book 2023-04-29 09:42:57 +10:00
Wesley Aptekar-Cassels 097cd3ed72 Optimize get_audience by only fetching IDs
Looking at the tracing data from this function in prod, only ~500ms is
spent in the database. My best guess for the rest of the time is
transferring and creating the user objects, which we don't use, since we
simply need the ID.
2023-04-28 12:51:44 -04:00
Zach Flanders a1df116c58 Adding batch processing to the sort title migration 2023-04-27 15:30:52 -05:00
Zach Flanders a6e5939ad2 adding sort title to edit book form 2023-04-26 23:05:03 -05:00
Neil Roberts d80cefd416 Add a management command to merge works 2023-04-26 15:54:37 +02:00
Mouse Reeve 7211906697
Merge pull request #2837 from bookwyrm-social/revert-2798-celery-increase-ping-timeout
Revert "Increase Celery ping timeout for monitoring page"
2023-04-26 06:13:03 -07:00
Zach Flanders 3f205f1b10 Merge branch '2678' of https://github.com/zachflanders/bookwyrm into 2678 2023-04-25 21:06:13 -05:00
Zach Flanders 858a93e98a fixing migration 2023-04-25 21:05:11 -05:00
Zach Flanders f43d7f8c70 fixing test and other checks 2023-04-25 21:00:16 -05:00
Mouse Reeve 7bd9623b68
Revert "Increase Celery ping timeout for monitoring page" 2023-04-25 18:24:23 -07:00
Zach Flanders 1985c2d284
Merge branch 'main' into 2678 2023-04-25 19:47:07 -05:00
Zach Flanders 575e1bac4c responding to review comments 2023-04-25 19:46:38 -05:00
Mouse Reeve b77ae9e783 Ticks version number 2023-04-25 17:42:32 -07:00
Mouse Reeve b92836ee7b
Merge pull request #2836 from bookwyrm-social/locales
Updates locales
2023-04-25 17:41:51 -07:00
Mouse Reeve 4e025b5105 Updates locales 2023-04-25 17:21:54 -07:00
Mouse Reeve 8fa89f5ece
Merge pull request #2821 from bpeel/merge-commands
Add management commands to merge a pair of editions or authors
2023-04-25 16:27:12 -07:00
Mouse Reeve ac48457748
Merge pull request #2770 from bookwyrm-social/import-rating-parser
Catch value errors when parsing imported ratings
2023-04-25 16:21:25 -07:00
Mouse Reeve cbb027c56c
Merge pull request #2778 from ranok/upstream_pr
Move the search request logic into the AbstractConnector
2023-04-25 16:20:24 -07:00
Zach Flanders 6b39052fcc Adding test for sort_title population 2023-04-25 07:17:23 -05:00
Zach Flanders a3013c6224 updating list view 2023-04-25 00:20:54 -05:00
Zach Flanders 21d9cb5fe5 updating shelf view 2023-04-25 00:15:58 -05:00
Zach Flanders a94a4732ec add support for title sort to ignore initial article 2023-04-24 23:29:55 -05:00
Mouse Reeve 718939834a Fixes check on isbn list length in LT importer 2023-04-18 10:04:20 -07:00
Jacob Torrey 84834eb5d3 Run bw-dev black to fix formatting
Signed-off-by: Jacob Torrey <jacob@jacobtorrey.com>
2023-04-17 15:06:41 +00:00
Mouse Reeve ed5471c7ab
Merge pull request #2832 from bookwyrm-social/fix-api/instance
Fix language constant to show correct lang in API
2023-04-16 19:10:38 -07:00
Jascha Urbach 0cae89b2b6
Update wellknown.py
./bw-dev black
2023-04-16 17:30:27 +02:00
Jascha Urbach f3b1b1d8e4
Fix language constant to show correct lang in API
api/v1/instance had "en" hardcoded as language. This fix takes LANGUAGE_CODE from settings.py/.env and takes the first two letters as response.
2023-04-16 17:28:05 +02:00
Hugh Rundle 5f5886edea Actually fix ensure_transient_values_persist call
oops
2023-04-16 19:58:53 +10:00
Hugh Rundle 6f025af99f fix ensure_transient_values_persist call 2023-04-16 19:06:04 +10:00
Hugh Rundle 74f08323d1
Merge branch 'main' into 2571 2023-04-16 18:11:39 +10:00
Hugh Rundle fb3cb229e9 Fixes #2571
Persist book.subjects and add_author when form validation fails.

This does not resolve the problem of cover image uploads being dropped because this is a broader problem and is covered separately in #2760
(we should investigate the plugin ` django-file-resubmit`)
2023-04-16 17:58:03 +10:00
Mouse Reeve 290b740392
Merge pull request #2805 from WesleyAC/stop-ignoring-task-results
Stop ignoring task results
2023-04-15 09:03:43 -07:00
Jascha Ezra Urbach c918617a6a
Merge branch 'main' into import-rating-parser 2023-04-15 17:21:27 +02:00
Jascha Ezra Urbach fadbc76aaa
Merge pull request #2789 from bpeel/translatable-shelf-name
Fix two places where the reading status shelf name wasn’t translated
2023-04-15 16:59:59 +02:00
Jascha Ezra Urbach d788105eeb
Merge pull request #2814 from WesleyAC/bw-dev-pick-docker-compose-command
Choose installed docker compose command in bw-dev
2023-04-15 16:52:38 +02:00
Jascha Ezra Urbach dfcc61a3e1
Merge pull request #2816 from bpeel/missing-translatable-strings
Fix a few strings that weren’t marked as translatable
2023-04-15 16:51:51 +02:00
Jascha Urbach e28562949b
./bw.-dev black
get rid of the black error.
2023-04-15 16:31:15 +02:00
Neil Roberts bd893e29de Add management commands to merge editions and authors 2023-04-15 11:59:40 +02:00
Neil Roberts 71e2486d01 Move the merging code from deduplicate code to common module
That way it can be used in a new command to merge individual items.
2023-04-15 11:59:40 +02:00
Neil Roberts 2bbc9a16ad Fix deduplicating books that are on a shelf or in a list
Previously when the deduplicate_book_data script tried to merge an
edition that was on a shelf or in a list then it would fail because when
the canonical book was added to the shelf or the list then it wouldn’t
set the extra fields of the linking table for the “through” model of the
field. These would end up defaulting to NULL, but that is not valid for
some of the fields in ShelfItem and ListItem so postgres wouldn’t accept
it.

To fix that, this patch makes it skip updating fields that have a
non-autogenerated linking table. The linking table would appear as a
separate model anyway so the book will be moved via that instead.

Fixes: #2817
2023-04-15 11:59:12 +02:00
Neil Roberts 3619d8960b Mark two strings as translatable in the getting started questionnaire 2023-04-14 16:49:00 +02:00
Neil Roberts f520d1b7f8 Make the text on the search button translatable 2023-04-14 16:40:50 +02:00
Hugh Rundle a0b7112c9c
Merge branch 'main' into gts 2023-04-14 18:24:02 +10:00
Hugh Rundle 98726585f6 oops black 2023-04-14 18:20:06 +10:00
Hugh Rundle 8a8af4e909 fix tests and make pylint happier 2023-04-14 18:03:51 +10:00
Hugh Rundle 123628c66a fix tests and formatting 2023-04-13 22:33:54 +10:00
Hugh Rundle 56a062d01f pylint fixes 2023-04-13 20:21:35 +10:00
Hugh Rundle c7adb62831 make get_legacy_key more DRY 2023-04-13 19:48:20 +10:00
Hugh Rundle a6676718cb formatting 2023-04-13 13:27:51 +10:00
Hugh Rundle e3261c6b88 fix incoming GTS mentions and DMs
GoToSocial sends 'tag' values as a single object if there is only one
user mentioned, rather than an array with an object inside it.

This causes Bookwyrm to reject the tag since it comes through as a
dict rather than a list.

This commit fixes this at the point the incoming AP object is transformed
so that "mention" tags are turned into a mention_user.
2023-04-13 13:21:05 +10:00
Wesley Aptekar-Cassels 43b34610a6 Choose installed docker compose command in bw-dev
Docker is removing support for docker-compose, and it doesn't appear to
be possible to install it anymore. Instead, it has been replaced with
compose V2 which is a docker plugin called with 'docker compose' (no
hyphen). See https://docs.docker.com/compose/compose-v2/

Thanks to @Neriderc for noticing this in #2781.
2023-04-11 21:51:31 -04:00
Wesley Aptekar-Cassels 8e25ae34d6
Merge pull request #2782 from ranok/list_fix
Small quality of life improvements to list handling
2023-04-11 12:31:58 -04:00
Wesley Aptekar-Cassels 843147e16b
Merge pull request #2808 from bpeel/series-no-author
Don't show the series as a link if the book has no author
2023-04-11 12:25:52 -04:00
Hugh Rundle c450947eee update comment to identify bug 2023-04-11 18:57:55 +10:00
Hugh Rundle 279fa3851b add comment 2023-04-11 16:49:11 +10:00
Hugh Rundle 03f21b0f35 Use correct keyId with legacy fallback
Bookwyrm keyIds are at `userpath/#main-key`, however when signing AP objects we have claimed in the headers that the keyId is at `userpath#main-key`.
This is incorrect, and makes GoToSocial's strict checking break.
Simply updating the signatures to use the correct KeyId breaks legacy Bookwyrm's signature checks, becuase it assumes that the keyId path is the same as the user path plus a fragment.
This commit allows for either option, by sending the request a second time with the incorrect keyId if sending with the correct one causes an error.
2023-04-11 15:45:06 +10:00
Hugh Rundle c9dcd4f7ad Include initial '@' in mention tag name
GoToSocial expects the 'name' value of a mention tag to have an initial '@' symbol. Mastodon doesn't seem to mind either way.
2023-04-10 20:38:20 +10:00
Hugh Rundle ef85394a16 Allow for tag value to be object
Previously the 'tag' value in an activitypub object was assumed to be a List (array).
Some AP software sends 'tag' as a Dict (object) if there is only a single tag value.
It's somewhat debatable whether this is spec compliant but we should aim to be robust.
This commit puts an individual mention tag inside a list if necessary.
2023-04-10 20:35:13 +10:00
Hugh Rundle e112718d2d clean up troubleshooting comment 2023-04-10 20:34:45 +10:00
Hugh Rundle 49758f2383 formatting fixes 2023-04-10 17:50:25 +10:00
Hugh Rundle 632e3844b9 Don't assume user id is key id minus fragment
Fixes #2801
Related to #2794

It is legitimate to use any url for the user's key id. We have been assuming this id is the user id plus a fragment (#key-id) but this is not always the case, notably in the case of GoToSocial it is at /key-id. This commit instead checks the remote user's information to see if the key id listed matches the key id of the message allegedly received from them.

Whilst troubleshooting this it also became apparent that there is a mismatch between Bookwyrm users' keyId and the KeyId we claim to be using in signed requests (there is a forward slash missing). Since everything after the slash is a fragment, this usually slips through but we should be consistent so I updated that.
2023-04-10 17:32:49 +10:00
Neil Roberts 41633090ba Don't show the series as a link if the book has no author
The series link needs an author so if it doesn't have one, instead of
showing a server error let's just show the series details as plain text
without a link.

Fixes: #2797
2023-04-08 17:13:34 +02:00
Wesley Aptekar-Cassels e9f26b7d50
Merge pull request #2800 from WesleyAC/fix-activitypub-request-accept-header
Fix Accept header for requesting ActivityPub objects
2023-04-08 11:02:27 -04:00
Wesley Aptekar-Cassels 1048638e30 Stop ignoring task results
This is essentially a revert of 9cbff312a. The commit was at the advice
of the Celery docs for optimization, but I've since decided that the
downsides in terms of making things harder to debug (it makes Flower
nearly useless, for instance) are bigger than the upsides in performance
gain (which seem extremely small in practice, given how long our tasks
take, and the number of tasks we have).
2023-04-07 21:51:44 -04:00
Mouse Reeve 7272ca2564
Merge pull request #2785 from WesleyAC/optimize-get-audience
Optimize get_audience
2023-04-07 13:27:00 -07:00
Wesley Aptekar-Cassels 07b50a1453 Optimize get_audience
This avoids filtering for the user that made the post in the same query
as we use for other things, which should allow for better use of indices
in all cases. Previously, #2723 did some work on this that only worked
for some cases in HomeStream, but this code should work for all cases.

Related: #2720
2023-04-07 10:38:14 -04:00
Wesley Aptekar-Cassels 77264493eb Override get_audience instead of _get_audience in LocalStream
I suspect this will make some future work simpler.
2023-04-07 10:37:02 -04:00
Mouse Reeve 5272786fbb
Merge pull request #2779 from WesleyAC/get_audience_more_telemetry
Add more information to get_audience telemetry
2023-04-07 07:12:41 -07:00
Mouse Reeve 4e3513bd41
Merge pull request #2784 from WesleyAC/add-status-cache-get-audience
Only call get_audience once in add_status
2023-04-07 06:43:04 -07:00
Mouse Reeve 035ca6fec2
Merge pull request #2795 from WesleyAC/add-postgres-instrumentation
Add automatic instrumentation to Postgres queries
2023-04-07 06:39:47 -07:00
Mouse Reeve 10f53d9809
Merge branch 'main' into get_audience_more_telemetry 2023-04-07 06:30:59 -07:00
Mouse Reeve d033848d3f
Merge pull request #2780 from jsoref/spelling
Spelling
2023-04-07 06:30:16 -07:00
Mouse Reeve 22dc4cbcb8
Merge pull request #2791 from WesleyAC/add-rerank-users-telemetry
Add telemetry for SuggestedUsers rerank_user_task
2023-04-07 06:29:44 -07:00
Mouse Reeve 5bcd294f47
Merge pull request #2793 from WesleyAC/ignore-activity-allow-external-connections
Pass allow_external_connections through ignore_activity
2023-04-07 06:23:26 -07:00
Mouse Reeve 5895524a25
Merge pull request #2787 from WesleyAC/celery-clear-queues-form
Add form to remove tasks from Celery
2023-04-07 06:17:50 -07:00
Mouse Reeve d11bb17698
Merge pull request #2798 from WesleyAC/celery-increase-ping-timeout
Increase Celery ping timeout for monitoring page
2023-04-07 06:13:07 -07:00
Mouse Reeve 206698238d
Merge pull request #2799 from WesleyAC/suggested-users-check-is-active
Don't include deleted users in suggested users query
2023-04-07 06:12:38 -07:00
Mouse Reeve af3957d76b
Merge pull request #2786 from WesleyAC/celery-raise-network-timeout
Increase network timeout in Celery tasks
2023-04-07 06:09:16 -07:00
Mouse Reeve a8235fc3a2
Moves the stray "e" back to "mobile" 2023-04-07 06:04:47 -07:00
Wesley Aptekar-Cassels 912d0a0149 Fix Accept header for requesting ActivityPub objects
This is the header described in the ActivityPub spec, which should fix
some federation problems with GoToSocial and potentially other picky
services.

Related: #2794, superseriousbusiness/gotosocial#1676
2023-04-07 05:57:13 -04:00
Wesley Aptekar-Cassels c89da1bd66 Don't include deleted users in suggested users query
Related: #2727
2023-04-07 04:18:36 -04:00
Wesley Aptekar-Cassels 3709f5c7a9 Increase Celery ping timeout for monitoring page
This should prevent some transient alerts.
2023-04-07 03:18:43 -04:00
Wesley Aptekar-Cassels 6986fc9025 Add form to remove tasks from Celery 2023-04-07 03:16:14 -04:00
Wesley Aptekar-Cassels 61453d48e6 Add automatic instrumentation to Postgres queries
This enables automatic instrumentation of Postgres queries when
OpenTelemetry instrumentation is enabled, which will help with debugging
performance problems.
2023-04-07 01:58:49 -04:00
Wesley Aptekar-Cassels b574a12fff Pass allow_external_connections through ignore_activity
Previously, ignore_activity could unexpectedly make a outgoing HTTP
connection, leading to unwanted latency, particularly when called via
ActivityObject.to_model, which had the allow_external_connections
parameter already.

Related: #2717
2023-04-06 23:37:49 -04:00
Wesley Aptekar-Cassels 4e09391b2e Add telemetry for SuggestedUsers rerank_user_task
Related: #2727
2023-04-06 12:22:39 -04:00
Neil Roberts 9092c9c80c Add a translatable name for the "stopped-reading" status shelf 2023-04-06 16:03:35 +02:00
Neil Roberts b0f90d05f2 Move the shelf names to a dict instead of a chain of if statements
The main reason to do this is that if we try to add another name then
pylint will complain that there are too many return statements. It might
be slightly faster too.

If I understand correctly it doesn’t matter that the _ function is being
called at module load time because it is mapped to gettext_lazy so the
actual translation will be done when the string is used.
2023-04-06 16:02:24 +02:00
Neil Roberts 36c14655ec Use the translated shelf name in a book’s shelf list
Previously in the list of shelves on the page for a book it was always
using the English name of the shelf for the shelf of the reading status.
2023-04-06 15:58:20 +02:00
Mouse Reeve 4b1012b185
Merge pull request #2788 from WesleyAC/fix-bw-dev-down-help-text
Fix help text for `bw-dev down`
2023-04-06 06:09:23 -07:00
Wesley Aptekar-Cassels 29ac34cb92 Fix help text for bw-dev down 2023-04-06 05:57:21 -04:00
Wesley Aptekar-Cassels f91fcd518a Increase network timeout in Celery tasks
Since Celery tasks don't affect interactive latency, we should have a
more generous timeout. This also allows admins to set the timeout for
Celery and the web frontend separately, without breaking backwards
compatibility with the previous environment variable.
2023-04-06 01:21:27 -04:00
Wesley Aptekar-Cassels 776c5526c8 Remove ActivityStream.get_stores_for_object
I think this makes the code somewhat more understandable.
2023-04-05 23:20:47 -04:00
Wesley Aptekar-Cassels 7a93b5c315 Only call get_audience once in add_status
This is by far the most expensive part of this task, so this should
double the speed in the increment_unread case.

Related: #2720
2023-04-05 22:11:49 -04:00
Wesley Aptekar-Cassels 78607a0c3e Remove get_stores_for_object abstract method
The implementations still have and use this, we've just removed this
concept from the RedisStore abstraction, which simplifies things
somewhat.
2023-04-05 22:07:38 -04:00
Wesley Aptekar-Cassels 68c6a9e748 Rename remove_object_from_related_stores
This makes the stores argument required, making it simpler to change the
code.
2023-04-05 22:06:09 -04:00
Wesley Aptekar-Cassels 8053f49acc Always pass stores to remove_object_from_related_stores 2023-04-05 21:48:24 -04:00
Wesley Aptekar-Cassels 93bd66ad3e Refactor to delete add_object_to_related_stores
This is working towards some optimizations.
2023-04-05 21:48:22 -04:00
Wesley Aptekar-Cassels 9c54030b61 Add add_object_to_stores function
This should enable some useful refactoring to allow us to cache some
results of expensive queries better.
2023-04-05 21:44:59 -04:00
Jacob Torrey 011844b7ac Small quality of life improvements to list handling
Signed-off-by: Jacob Torrey <jacob@jacobtorrey.com>
2023-04-05 16:17:28 +00:00
Josh Soref 359228127d spelling: wyrm
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref ba7f0fce71 spelling: whenever
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 2a914f98b7 spelling: versions
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref dfae27ca32 spelling: updated
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 459b74294d spelling: uniqueness
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 7170e8972d spelling: uneventfully
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 42e78b14e9 spelling: translation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 2d4a42ceba spelling: suggestions
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 63dbb6a291 spelling: successfully
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref ffd035f25a spelling: stores
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 9dc3cdca5d spelling: statuses
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref e4677eb6fa spelling: someone
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 4607d30cad spelling: signatures
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 18fcea35da spelling: should
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 35f1d043f4 spelling: separate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 7a6e249614 spelling: sensitivity
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 02bf018271 spelling: search
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 2fb771f0de spelling: sanitize
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 4c9408d772 spelling: revoke
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref e5663f97c5 spelling: remove
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 182a722a55 spelling: recurring
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref e7d8692836 spelling: receiving
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 0b14d3fddf spelling: receive
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 55b6d63774 spelling: quotation
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 3526d9fd19 spelling: progress
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 764bc0c204 spelling: produce
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 27f025bc39 spelling: presence
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 1fdf5a7a39 spelling: physical
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 44b4b10eb8 spelling: password
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 9cddea11c7 spelling: paginate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 7b59f38cc8 spelling: owner
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref c009f6e4df spelling: overridden
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 56f38c178c spelling: ordered
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref d9a305a0f2 spelling: optimizequality
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref d640bc9b1c spelling: nonexistent
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 40632b2486 spelling: multiple
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 0b30373bd3 spelling: mention'd
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref c216937dc4 spelling: massively
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 1320108703 spelling: markdown
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref e8894b159f spelling: irrelevant
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 649c782782 spelling: inheritance
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref d2d087dcb7 spelling: identifiername
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 7ec56505ea spelling: having a
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref cee2de41ca spelling: handling
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 7f8279fe54 spelling: format
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 802a150c76 spelling: flex
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 9c5d588630 spelling: fields
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 050cd583df spelling: expiration
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 3b9828c0fc spelling: existing
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 445cb60f2c spelling: example
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref b949259c57 spelling: embedded
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 3850183e95 spelling: doesn't
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 8d4b69927b spelling: directly
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref f6a6cb281b spelling: different
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref c92cdec36e spelling: default
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 45a1457a4f spelling: deduplications
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 9cad11b2b3 spelling: deduplication
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref c2022acf67 spelling: deduplicate
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 9ea5a3b89c spelling: data
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref cfe388896b spelling: dashboard
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 6b0e51caf4 spelling: currently
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref be31a4b576 spelling: creating
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 72c292d2c3 spelling: breakpoints
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref fb74c1977e spelling: because
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 54285e4bcd spelling: auxiliary
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref b3edeca295 spelling: associated
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 319be60c80 spelling: assigning
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 06fa1adc27 spelling: arbitrary
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:54 -04:00
Josh Soref 94c573b469 spelling: appear
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 20:02:47 -04:00
Wesley Aptekar-Cassels 118b5bfda7 Add more information to get_audience telemetry
This will assist with debugging #2720, by letting us see which kinds of
requests take the longest.
2023-04-04 14:23:15 -04:00
Jacob Torrey f9c75a43ae Fixing pylint issues
Signed-off-by: Jacob Torrey <jacob@jacobtorrey.com>
2023-04-04 16:46:32 +00:00
Jascha Ezra Urbach e909cbfd4a
Merge pull request #2774 from fwalloe/fwalloe-patch-1 2023-04-04 18:38:56 +02:00
Jacob Torrey 797d339132 Move the search request logic into the AbstractConnector to allow for more flexibility
Signed-off-by: Jacob Torrey <jacob@jacobtorrey.com>
2023-04-04 16:03:37 +00:00
Josh Soref def58a3e18 spelling: activity
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2023-04-04 11:14:03 -04:00
Fredrik Walløe ac17876cb6
Merge branch 'main' into fwalloe-patch-1 2023-04-04 12:15:52 +02:00
Fredrik Walløe 0495da07a4
Update bw-dev
Added 'down' to list of of commands
2023-04-04 12:08:39 +02:00
Mouse Reeve 6e427cf372 Update version number 2023-04-03 21:31:41 -07:00
Fredrik Walløe b1962ef75d
Added command 'down', to bring down containers
Added the command 'down', which can be used to bring down the docker containers. Equivalent to running 'docker-compose down'
2023-04-01 11:23:27 +02:00
Jascha Ezra Urbach d35b1d91ba
Merge pull request #2766 from bookwyrm-social/redirect-in-admin
Uses referer redirect for some admin views
2023-04-01 11:06:42 +02:00
Hugh Rundle 499ff58a65
Merge pull request #2698 from rkmdCodes/main
Improving Feed link UI colours
2023-04-01 14:27:04 +11:00
Jascha Ezra Urbach a68f58e48c
Merge pull request #2773 from bookwyrm-social/dependabot/pip/redis-4.5.4
Bump redis from 4.5.3 to 4.5.4
2023-03-31 16:42:12 +02:00
dependabot[bot] 282f41bdb8
Bump redis from 4.5.3 to 4.5.4
Bumps [redis](https://github.com/redis/redis-py) from 4.5.3 to 4.5.4.
- [Release notes](https://github.com/redis/redis-py/releases)
- [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES)
- [Commits](https://github.com/redis/redis-py/compare/v4.5.3...v4.5.4)

---
updated-dependencies:
- dependency-name: redis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-31 14:28:59 +00:00
Mouse Reeve c77436fc12 Catch value errors when parsing imported ratings 2023-03-29 20:15:09 -07:00
Mouse Reeve 74df7511e7
Merge pull request #2768 from bookwyrm-social/grammar
Fixes effect/affect error
2023-03-29 18:46:14 -07:00
Mouse Reeve b5d6c94885
Merge pull request #2767 from bookwyrm-social/link-mention-clash
Clashes between links and mentions
2023-03-29 17:06:11 -07:00
Mouse Reeve b76da26c98 Fixes iteration over mentions dict 2023-03-29 10:13:44 -07:00
Mouse Reeve f1640399e3 Python formatting 2023-03-29 10:13:44 -07:00
Mouse Reeve f2ab8c2fe2 Fixes effect/affect error 2023-03-29 10:04:23 -07:00
Mouse Reeve 8cf7c5c392
Merge pull request #2750 from WesleyAC/get-audience-telemetry
Add more detailed telemetry for get_audience
2023-03-29 09:29:05 -07:00
Mouse Reeve 5ed46abcee
Merge branch 'main' into link-mention-clash 2023-03-29 09:25:34 -07:00
Mouse Reeve 935f8b0197
Merge pull request #2763 from bookwyrm-social/esperanto
Adds Esperanto locale
2023-03-29 09:24:32 -07:00
Mouse Reeve fe856bcf2c Updates regex on mentions and hashtags 2023-03-29 09:20:58 -07:00
Mouse Reeve 4fcb01805e Fixes test comparison string 2023-03-29 09:14:30 -07:00
Mouse Reeve 8a0e88db83 Adds test for links with # symbols 2023-03-29 08:39:41 -07:00
Mouse Reeve 42dd199084 Unit test that identifies clashes between links and mentions 2023-03-29 08:28:45 -07:00
Mouse Reeve 1d383cecff Compiles locales 2023-03-29 07:59:42 -07:00
Rajat Dwivedi 38e3f2e1b8
Merge branch 'main' into main 2023-03-29 16:37:57 +05:30
Rajat Dwivedi 33c13608a8 Refixing light and dark themes 2023-03-29 10:56:08 +00:00
Mouse Reeve 56cc0eb80f Adds Esperanto locale 2023-03-28 15:03:40 -07:00
Mouse Reeve ab1f08b39d
Merge pull request #2761 from bookwyrm-social/dependabot/pip/redis-4.5.3
Bump redis from 3.4.1 to 4.5.3
2023-03-27 18:58:40 -07:00
dependabot[bot] e9526ecaea
Bump redis from 3.4.1 to 4.5.3
Bumps [redis](https://github.com/redis/redis-py) from 3.4.1 to 4.5.3.
- [Release notes](https://github.com/redis/redis-py/releases)
- [Changelog](https://github.com/redis/redis-py/blob/master/CHANGES)
- [Commits](https://github.com/redis/redis-py/compare/3.4.1...v4.5.3)

---
updated-dependencies:
- dependency-name: redis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 21:57:11 +00:00
Mouse Reeve b2801d44a5
Merge pull request #2752 from lostfictions/patch-1
Add message about shelf privacy in user settings
2023-03-27 06:21:33 -07:00
Mouse Reeve 30a3096b25
Merge pull request #2749 from bookwyrm-social/redirects
Add helper to refer views back to http referers safely
2023-03-27 06:20:26 -07:00
Jascha Ezra Urbach bbed08e182
Merge branch 'main' into main 2023-03-21 05:49:52 +01:00
s a70417a07f
Add message about shelf privacy in user settings 2023-03-20 22:10:50 -04:00
Wesley Aptekar-Cassels 7efbdb1865 Add more detailed telemetry for get_audience
This is still slow in some cases, despite #2723, so this information
should give useful data about how it could be optimized more.

This also adds some abstraction around getting the tracer, just to
follow the advice in the OpenTelemetry documentation not to use __name__
directly to set the tracer name. The advice is ignored in most of their
examples, so it probably doesn't matter, but IDK, seems reasonable to
try to follow it.

Related: #2720
2023-03-20 20:51:20 -04:00
Wesley Aptekar-Cassels ef64fedbd9 Only enable OTLP exporter when configured
This wasn't a problem in the past, since we only enabled automatic
instrumentation when this was set up, but it does cause errors when
trying to add manual instrumentation.
2023-03-20 20:51:20 -04:00
Mouse Reeve e9d08e7424
Merge pull request #2744 from WesleyAC/opentelemetry-console-exporter
Add OpenTelemetry console exporter option
2023-03-20 14:26:24 -07:00
Mouse Reeve 89bb541bef
Merge pull request #2704 from tebriel/azure-support
Enable Azure BlobStorage as an alternative to AWS S3
2023-03-20 14:12:57 -07:00
Mouse Reeve 6f1e80be60
Merge pull request #2741 from WesleyAC/optimize-csv-export-query
Optimize CSV export query
2023-03-20 14:11:46 -07:00
Mouse Reeve 018cadf0cc
Merge pull request #2746 from WesleyAC/env-var-improvements
Env var improvements
2023-03-20 14:04:11 -07:00
Mouse Reeve 05e154f93e Uses referer redirect for some admin views 2023-03-20 13:58:20 -07:00
Mouse Reeve 0cebc4388c Adds unit tests for referer helper 2023-03-20 12:47:21 -07:00
Mouse Reeve 219f78755f Fixes args in list view redirect 2023-03-20 11:15:27 -07:00
Mouse Reeve 4e9fad2091 Updates views that currently use the validator to use the redirect
helper
2023-03-20 10:27:52 -07:00
Mouse Reeve 2de115fc1e Add helper to refer views back to http referers safely
In most cases, we want to return back to where we came from after
performing an action. It's not safe to return to an arbitrary referer,
so this streamlines using the util validator to verify the redirect and
fall back on regular redirect params if the referer is outside our
domain.
2023-03-20 10:25:38 -07:00
Rajat Dwivedi 349c61f698 Updated the _tabs.scss file 2023-03-20 04:11:44 +00:00
Wesley Aptekar-Cassels 63ab3abe67 Add setting for OpenTelemetry console exporter
This is primarily useful for debugging changes to the OpenTelemetry
setup.
2023-03-18 15:47:30 -04:00
Wesley Aptekar-Cassels fea3b67a55 Raise error if using default SECRET_KEY in production 2023-03-18 15:44:20 -04:00
Wesley Aptekar-Cassels 5bb5d120f0 Set default FLOWER_PORT 2023-03-18 15:35:41 -04:00
Wesley Aptekar-Cassels b3d3de5374 Use typecasting env functions
Many of these environment variables were probably not actually usable,
since they would be strings if set in the env file. Using the
typecasting functions fixes this, and generally shows the intention of
the code more clearly.
2023-03-18 15:35:08 -04:00
Philip James 6b6ed23e25
Merge pull request #5 from bookwyrm-social/main
Update from upstream
2023-03-16 17:18:01 -07:00
Wesley Aptekar-Cassels 7bb4e21a36 Bump opentelemetry versions
This isn't actually required for anything, just good practice to keep
things up to date.
2023-03-16 13:57:19 -04:00
Wesley Aptekar-Cassels 60fee54da9 Optimize CSV export query
Splitting this into five separate queries avoids the large join that
prevents us from using indexes, and requires materializing to disk.

Fixes: #2157 (hopefully)
2023-03-13 15:45:21 -04:00
Mouse Reeve ded3f469ef
Merge pull request #2738 from bookwyrm-social/update-version
Update version number and js cachebuster
2023-03-13 08:16:24 -07:00
Mouse Reeve 177131f53f
Merge pull request #2739 from bookwyrm-social/locales
Updates locales
2023-03-13 08:16:12 -07:00
Mouse Reeve ae164ee6e1 Updates locales 2023-03-13 07:56:25 -07:00
Mouse Reeve 9c1aaadab3 Update verison number and js cachebuster 2023-03-13 07:52:28 -07:00
Mouse Reeve a73a461867
Merge pull request #2737 from WesleyAC/fix-500-page-css
Use context processor for 500 page
2023-03-13 07:43:29 -07:00
Wesley Aptekar-Cassels 0b9e4d617e Use context processor for 500 page
By default, Django doesn't run any context processors for server errors,
to make the error path as simple as possible. However, this has the
downside that our template does not load correctly. To fix this, I added
a custom 500 error handler, which will run the context processor.

Fixes: #2736
2023-03-13 03:47:23 -04:00
Mouse Reeve cca20f4834
Merge pull request #2735 from bookwyrm-social/migration
Adds merge migration
2023-03-12 17:34:17 -07:00
Mouse Reeve 7ffe5b9440 Adds merge migration 2023-03-12 16:43:06 -07:00
Mouse Reeve 12af5992a3
Merge pull request #2524 from chdorner/feature/tag-support
Initial hashtag support
2023-03-12 16:37:39 -07:00
Mouse Reeve 48889ee6c4
Merge pull request #2695 from chdorner/book-edit-form-validation-notification
Show notification banner on top of form when book failed to update
2023-03-12 16:33:34 -07:00
Mouse Reeve 2e7eb0f3ce
Merge pull request #2702 from Ryuno-Ki/lazyload-images
Add attributes to images to hint async load
2023-03-12 16:31:27 -07:00
Mouse Reeve d253a61f02
Merge pull request #2708 from WesleyAC/portable-hashbangs
Use more portable hashbang for dev scripts.
2023-03-12 16:29:10 -07:00
Mouse Reeve 863ec1602a
Merge pull request #2710 from WesleyAC/celery-env-vars
Add env vars for celery concurrency and time limit
2023-03-12 16:27:02 -07:00
Mouse Reeve 6345beb90d
Merge pull request #2714 from WesleyAC/celery-ignore-results
Ignore Celery task results
2023-03-12 16:26:20 -07:00
Mouse Reeve 84b8a5c433
Merge pull request #2713 from WesleyAC/buffer-csv-export
Change CSV export to buffer instead of streaming
2023-03-12 16:17:53 -07:00
Mouse Reeve d17190fae3
Merge pull request #2718 from WesleyAC/broaden-dashboard-http-except
Broaden except section for HTTP request in dashboard
2023-03-12 16:10:01 -07:00
Mouse Reeve 600340771a
Merge pull request #2723 from WesleyAC/get-audience-perf
Improve `HomeStream.get_audience` performance
2023-03-12 16:08:54 -07:00
Mouse Reeve 352ba972c5
Merge pull request #2724 from WesleyAC/fix-bw-dev-dbshell
Fix dbshell command
2023-03-12 15:45:45 -07:00
Mouse Reeve c28d523e6f
Merge branch 'main' into get-audience-perf 2023-03-12 15:40:53 -07:00
Mouse Reeve efe3cb9461
Merge pull request #2726 from WesleyAC/optimize-add-remove-book-statuses-task
Optimize add/remove book statuses task queries
2023-03-12 15:36:27 -07:00
Wesley Aptekar-Cassels 2a5f722f6e Optimize add/remove book statuses task queries
The queries as they previously existed required joining together 12
different tables, which is extremely expensive. Splitting it into four
queries means that the individual queries can effectively use the
indexes we have, and should be very fast no matter how many statuses are
in the database.

Removing the .distinct() call is fine, since we're adding them to a set
in Redis anyways, which will take care of the duplicates.

It's a bit ugly that we now make four separate calls to Redis (this
might result in things being slightly slower in cases where there are an
extremely small number of statuses), but doing things differently would
result in significantly more surgery to the existing code, so I've opted
to avoid that for the moment.

Fixes: #2725
2023-03-09 15:26:03 -05:00
Wesley Aptekar-Cassels cc610372ca Fix dbshell command
dbshell needs to be run in a already-running container, thus exec rather
than run is the correct docker-compose command.
2023-03-09 02:02:56 -05:00
Wesley Aptekar-Cassels 56243f6529 Optimize HomeStream.get_audience
This splits HomeStream.get_audience into two separate database queries,
in order to more effectively take advantage of the indexes we have.
Combining the user ID query and the user following query means that
Postgres isn't able to use the index we have on the userfollows table.

The query planner claims that the userfollows query should be about 20
times faster than it was previously, and the id query should take a
negligible amount of time, since it's selecting a single item by primary
key.

We don't need to worry about duplicates, since there is a constraint
preventing a user from following themself.

Fixes: #2720
2023-03-09 00:50:24 -05:00
Wesley Aptekar-Cassels 23698dafe5 Change get_audience to return list of user IDs
This will make it simpler to implement various optimizations.
2023-03-09 00:50:24 -05:00
Wesley Aptekar-Cassels 41e14bdfaf Change unread_by_status_type_id to take user ID
Same reason as in prior commit.
2023-03-09 00:50:24 -05:00
Wesley Aptekar-Cassels 653e8ee81b Change unread_id to take user ID
Same reason as described in the prior commit.
2023-03-09 00:50:24 -05:00
Wesley Aptekar-Cassels 5446869c38 Change stream_id to take user ID
Anywhere we have a user object, we can easily get the user ID in the
caller, and this will allow us more flexibility in the future to
implement optimizations that involve knowing a user ID without querying
the database for the user object.
2023-03-09 00:50:16 -05:00
Mouse Reeve e4edef03c5
Merge pull request #2721 from verymilan/verymilan-patch-1
fix typo in systemd example
2023-03-08 18:39:05 -08:00
Wesley Aptekar-Cassels 50a81bdfdd Change CSV export to buffer instead of streaming
The idea behind a streaming CSV export was to reduce the amount of
memory used, by avoiding building the entire CSV file in memory before
sending it to the client. However, it didn't work out this way in
practice: the query objects that were created to represent each line
caused Postgres to generate a very large (~200MB on bookwyrm.social)
temp file, not to mention the memory being used by the Query object
likely being similar to, if not larger than that used by the finalized
CSV row.

While we should in the long term run our CSV exports as a Celery task,
this change should allow CSV exports to work on large servers without
causing disk-space problems.

Fixes: #2157
2023-03-08 21:37:56 -05:00
Mouse Reeve 5c109a2566
Merge branch 'main' into celery-env-vars 2023-03-08 18:37:03 -08:00
Mouse Reeve 2f737efeff
Merge pull request #2709 from WesleyAC/improve-polling-backoff
Improve polling algorithm
2023-03-08 18:36:19 -08:00
Wesley Aptekar-Cassels 4af4f30cde Broaden except section for HTTP request in dashboard
get_data can return exceptions other than ConnectorException, and when
it does, we want to simply not show the update section, rather than
crashing.

Related: #2717
2023-03-08 21:32:41 -05:00
Chris Moultrie 86675ee944
Example Settings and run black 2023-03-08 14:48:04 -05:00
Milan a6bc53a936
fix typo in systemd example
...which prevented imports from running
2023-03-08 19:58:58 +01:00
Wesley Aptekar-Cassels 9cbff312a5 Ignore Celery task results
Since we don't use the results of our Celery tasks (all of them return
None implicitly), it's prudent to set the ignore_result flag, for a
potential performance improvement. See the Celery docs for details [1].

We could do this with the global CELERY_IGNORE_RESULT setting, but it
offers more flexibility if we want to use task results in the future to
set it on a per-task basis.

[1]: https://docs.celeryq.dev/en/stable/userguide/tasks.html#ignore-results-you-don-t-want
2023-03-08 02:12:13 -05:00
Mouse Reeve c3109f1238
Merge branch 'main' into improve-polling-backoff 2023-03-07 13:57:00 -08:00
Mouse Reeve 3c57797852
Merge branch 'main' into portable-hashbangs 2023-03-07 13:56:44 -08:00
Mouse Reeve 1350e91971
Merge branch 'main' into book-edit-form-validation-notification 2023-03-07 13:56:23 -08:00
Mouse Reeve 00666c4f52
Merge pull request #2711 from bookwyrm-social/fix/reorder-head-migration
Reorder head migration
2023-03-07 13:56:04 -08:00
Christof Dorner ee0a89faf2 Reorder head migration 2023-03-07 22:31:58 +01:00
Christof Dorner bc0b291d36 Show notification banner on top of form when book failed to update 2023-03-07 21:58:12 +01:00
Wesley Aptekar-Cassels 26e34ddffa Add env vars for celery concurrency and time limit 2023-03-07 13:52:02 -05:00
Wesley Aptekar-Cassels abb5dc857e Use more portable shebang for dev scripts
/bin/bash, while common, is not part of the unix standard, and does not
exist on some operating systems (such as NixOS). /usr/bin/env, on the
other hand, is standardized, and thus should exist on all systems.
2023-03-07 13:39:18 -05:00
Wesley Aptekar-Cassels 43ad3d0c15 Improve polling algorithm
The existing polling code had a few problems:

* It started the timer for a new request when the first request was
  sent, rather than when a response was received.
* It increased the delay regardless of whether the response was a
  success or a failure.

This commit changes it to a more standard exponential backoff system,
where it starts with a 5 minute ± 30 second delay, and uses that same
delay until it hits an error, at which point the delay is increased by
10%. Once it receives a successful response again, the delay is reset to
the default.

I suspect this should be nicer on the server, since it avoids the
initial sending of many requests. After about half an hour of leaving
the page open, the request rate for this new code will be higher than
that of the old code, so it's possible that this may cause problems, but
I think that a five-minute request frequency should be pretty reasonable.
2023-03-07 13:15:52 -05:00
Mouse Reeve 05a303ea18
Merge pull request #2690 from bookwyrm-social/link-domain-notifications
Create notifications for link domains that need approval
2023-03-07 08:43:14 -08:00
Mouse Reeve 1612217eaa
Merge pull request #2696 from bookwyrm-social/chronological-pagination
Only use chronological pagination sometimes
2023-03-07 08:42:43 -08:00
Christof Dorner 9ca9883e0b Enable finding existing hashtags case-insensitive
We should store hashtags case-sensitive, but ensures that an existing
hashtag with different case are found and re-used. for example,
an existing #BookWyrm hashtag will be found and used even if the
status content is using #bookwyrm.
2023-03-07 13:16:45 +01:00
Christof Dorner f3334b1550 Render hashtag links with data-mention="hashtag" attribute 2023-03-07 13:16:45 +01:00
Christof Dorner 276b255f32 Post-process status.content field to change hashtag URLs
Since the status content already contains rendered HTML when we receive an
ActivityPub inbox message it contains links to the mentioned hashtags on the
originating instance.

To fix this on the receiving instance we need to post-process the status content
after successfully storing the status and its many-to-many fields (the one we're
is the `mention_hashtags`). Post-processing means that we run a regex against the
content to find the anchor tags linking to the originating hashtag and replace the
`href` attribute with the URL to the hashtag page on the receiving (local) instance.
2023-03-07 13:16:45 +01:00
Christof Dorner 0fd49d2aea Mark Hashtag.name field as deduplication field
This ensures that when an existing hashtag comes in through ActivityPub federation,
it correctly finds the local one, instead of creating duplicate hashtags.
2023-03-07 13:11:27 +01:00
Christof Dorner e8a306437f Reorder migrations to add hashtag one at the end 2023-03-07 13:11:27 +01:00
Christof Dorner 824d4207dc Try and fix a flaky test
Same case as with #2496, for some reason the URL to the cover just ends with `test.jpg`
2023-03-07 12:59:32 +01:00
Christof Dorner 499aace9fb Add basic view listing activities from a given hashtag 2023-03-07 12:59:32 +01:00
Christof Dorner 11640f986e Import hashtags from activitypub statuses 2023-03-07 12:59:31 +01:00
Christof Dorner ba0fcccfc5 Link hashtags in status content 2023-03-07 12:55:36 +01:00
Christof Dorner c68304a99b Parse hashtags and store them in CreateStatus view 2023-03-07 12:55:36 +01:00
Philip James c878e11913
Merge pull request #4 from bookwyrm-social/main
Merge Updates from Upstream
2023-03-06 20:39:50 -08:00
Mouse Reeve c402433587
Merge pull request #2683 from bookwyrm-social/resolve-local-tasks-synchronously
Attempt to complete inbox requests synchronously
2023-03-06 19:20:16 -08:00
Chris Moultrie f8e60f4a89
Enable Azure BlobStorage as an alternative to AWS S3
This adds a new storage backend for Azure BlobStorage, I'm running this patch in Azure Kubernetes
hosting all my assets in Azure BlobStorage and it's been stable enough I thought I should commit
this back upstream.
2023-03-05 12:08:16 -05:00
André Jaenisch 9c92ba1698
Add attributes to images to hint async load
This was suggested on Matrix a while ago but I only found the time now to move forward with it.

Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2023-03-01 14:14:42 +01:00
Rajat Dwivedi 7caa60dba5
Improving Feed link UI colours 2023-02-27 20:14:32 +05:30
Hugh Rundle 66ce298001
Merge pull request #2657 from chris-y/totp-window
Expand TOTP validity window

This changes the default window to allow 2 codes (60 seconds) on either side. Admins can change this by setting a different `TWO_FACTOR_LOGIN_VALIDITY_WINDOW` value in `.env`
2023-02-27 18:46:53 +11:00
Hugh Rundle bba0d09fa4
Merge branch 'main' into totp-window 2023-02-27 18:21:39 +11:00
Hugh Rundle 3a67727a9a
Merge pull request #2638 from Giebisch/page-range
Page Range
2023-02-27 17:39:42 +11:00
Christof Dorner d1110630db Use chronological pagination on user profile activity lists 2023-02-26 11:24:00 +01:00
Mouse Reeve 99fc2b7a36 Only use chronological pagination sometimes
The timeline uses chronological buttons, but other paginated pages do
not (by default). This also reversed the chronology.
2023-02-25 15:56:58 -08:00
Christof Dorner 233cf809dd
Merge pull request #2694 from kangangi/replace_next_previous
Replace Next and Previous with Older and Newer
2023-02-25 22:34:05 +01:00
wanjiku b4e388a975 Replace Next and Previous with Older and Newer 2023-02-24 11:11:55 +03:00
Giebisch 43fe433133 Quotation same start and endposition 2023-02-23 18:40:20 +01:00
Mouse Reeve 268946a77c Adds missing template and migration files 2023-02-22 10:46:01 -08:00
Mouse Reeve 2470a0fd1c Create notifications for link domains that need approval 2023-02-22 10:20:07 -08:00
Mouse Reeve e59b650ff9
Merge pull request #2689 from bookwyrm-social/discover-page-test
Improves discover page test so it catches errors
2023-02-22 09:39:15 -08:00
Mouse Reeve 46fe65c3bb
Merge branch 'main' into discover-page-test 2023-02-22 09:19:20 -08:00
Mouse Reeve fad8e8bdb8
Merge pull request #2687 from chdorner/configurable-csp
Add config variable for additional CSP hosts
2023-02-22 08:57:56 -08:00
Mouse Reeve d57ebe43af
Merge pull request #2688 from 0x29a/fix-discovery-page
fix: missing expand variable
2023-02-22 08:53:36 -08:00
Mouse Reeve 0a07607240 Improves discover page test so it catches errors
Without `select_subclasses` in the mock, it wasn't actually collecting
any statuses to display, so errors on that view weren't caught in this
test.
2023-02-22 08:43:13 -08:00
0x29a 9b94c1c288 fix: missing expand variable 2023-02-22 17:25:11 +01:00
Mouse Reeve d2e590a3c2
Merge pull request #2685 from bookwyrm-social/broadcast-queue
Use a separate queue for broadcasts
2023-02-22 08:20:33 -08:00
Christof Dorner 3814cb5b58 Add config variable for additional CSP hosts 2023-02-21 22:02:52 +01:00
Christof Dorner 5df0ead776
Merge pull request #1753 from nycterent/security/key-size
increasing rsa key size
2023-02-20 22:37:02 +01:00
Mouse Reeve b167364c5c Use a separate queue for broadcasts
I think this will go a long way to solve the federation delay problems
we're seeing on b.s. I'm not sure at what point adding more queues will
create more problems than it solves, but I do think in this case the
queues are out of balance and moving broadcasts (which are the most
common type of `medium_priority` task at the moment) to their own queue
will be an improvement.
2023-02-20 12:58:41 -08:00
Martynas Sklizmantas 2093c4760b increasing rsa key size 2023-02-20 21:51:50 +01:00
Mouse Reeve 216be2aeea Fixes pylint complaints
"fixes" as in silences, sorry
2023-02-20 12:24:53 -08:00
Mouse Reeve 12ed0f46f3 Fixes mocks for tests 2023-02-20 12:23:18 -08:00
Mouse Reeve 0211dee0ff Avoid unnecessary errors when a remote re-sends an Accept 2023-02-20 11:09:42 -08:00
Mouse Reeve 779d2b0694 Attempt to complete inbox requests synchronously
When an inbox activity comes in from another fediverse instance, the
behavior prior to this commit was always to immediately give a 200
response to the external server and then create a celery activity
(usually in the MEDIUM_PRIORITY queue) to complete it.

Instead, this would receive a request and try to complete it without
making any http requests (which would make the request take too long to
process). If an external request is required to complete the activity, a
task is created and added to the queue.

Ideally, this will cause some tasks to happen very promptly, and reduce
the load on celery, which would help queued tasks happen more quickly as
well.

One downside is that this will make completing http requests from
external servers slowing (since it's doing a bunch of thinking before
responding).
2023-02-20 11:05:18 -08:00
Mouse Reeve db207065ce Update version number 2023-02-20 09:15:38 -08:00
Christof Dorner 4b3849e4e0
Merge pull request #2681 from chdorner/fix/sitesettings-ondelete 2023-02-18 20:24:41 +01:00
Christof Dorner dc5b797796 Fix SiteSettings.default_user_auth_group FK on_delete value
The migration uses `RESTRICT` instead of `PROTECT`, which is both more
correct, but also those values need to be identical, otherwise Django
thinks that there's a migration missing and will refuse to apply any
new migrations.
2023-02-18 19:33:25 +01:00
Chris Young d123cc6b0c Add default values if not in .env 2023-02-17 11:36:21 +00:00
Chris Young 9460553086 Read TOTP variables from .env 2023-02-17 09:40:31 +00:00
Hugh Rundle 702c79496b
Merge pull request #2652 from chdorner/fix/status-get-no-trim
Always expand content status on single status view
2023-02-17 15:18:05 +11:00
Christof Dorner a5892fa531
Merge pull request #2667 from bookwyrm-social/dependabot/pip/django-3.2.18
chore(deps): bump django from 3.2.17 to 3.2.18
2023-02-16 10:25:58 +01:00
dependabot[bot] 173d7ba9bf
chore(deps): bump django from 3.2.17 to 3.2.18
Bumps [django](https://github.com/django/django) from 3.2.17 to 3.2.18.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.17...3.2.18)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-15 19:45:09 +00:00
Chris Young 867b2ff542 Specify TOTP validity window in settings.py 2023-02-13 15:17:54 +00:00
Mouse Reeve 2c2daf5fdf
Merge pull request #2644 from rrgeorge/rrgeorge/csp
Add Content-Security-Policy headers and secure cookies
2023-02-10 16:37:39 -08:00
Mouse Reeve cc9e94261c
Merge pull request #2637 from MeecoLabs/mobile/dropdown-larger-size
UI: larger dropdown size for mobile devices
2023-02-10 15:57:03 -08:00
Chris Young 5bae00b3fe Expand TOTP validity window 2023-02-09 12:49:05 +00:00
Hugh Rundle e88f1f0b8c
Merge pull request #2616 from MeecoLabs/book-series-v1
Book Series v1: a very simple version to link to book series by name\

Resolves #644
2023-02-08 21:14:51 +11:00
Dustin Steiner d1f85e4317 fix: books can have non-decimal series numbers 2023-02-07 12:05:20 +00:00
Dustin b20b52af7f
Merge branch 'main' into book-series-v1 2023-02-07 11:57:39 +00:00
Giebisch 21575fbf3f Unused variable fix 2023-02-06 14:09:53 +01:00
Giebisch 248eab22ed Merge branch 'main' into page-range 2023-02-06 14:02:05 +01:00
Giebisch f65e0b7632 Add Quotation endposition test 2023-02-06 14:00:04 +01:00
Christof Dorner 6af1be28f3 Always expand content status on single status view
On the feed view along with other statuses, the body will be trimmed,
but on the single view, there's no need to trim it. This preserves the
logic for spoiler alerts.
2023-02-04 12:52:09 +01:00
Mouse Reeve d94b9f9e30
Merge pull request #2648 from bookwyrm-social/dependabot/pip/django-3.2.17
Bump django from 3.2.16 to 3.2.17
2023-02-03 15:02:51 -08:00
dependabot[bot] b43f1eab38
Bump django from 3.2.16 to 3.2.17
Bumps [django](https://github.com/django/django) from 3.2.16 to 3.2.17.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.16...3.2.17)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-03 22:18:41 +00:00
Robert George b82231202c lint 2023-02-03 12:03:52 -08:00
Robert George 297738dbb1 Merge branch 'rrgeorge/csp' of github.com:rrgeorge/bookwyrm into rrgeorge/csp 2023-02-03 11:53:52 -08:00
Robert George afe651cd6d Added img-src * csp exception to search 2023-02-03 11:53:41 -08:00
Christof Dorner f9a916db09
Merge pull request #2639 from bookwyrm-social/celery-ping
Celery ping
2023-02-03 09:40:25 +01:00
Mouse Reeve fd59fea94e
Update bookwyrm/views/admin/celery_status.py
Co-authored-by: Christof Dorner <christof@chdorner.com>
2023-02-02 16:46:36 -08:00
Mouse Reeve 739c384715
Merge branch 'main' into rrgeorge/csp 2023-02-02 16:41:18 -08:00
Mouse Reeve 213984cd78
Merge pull request #2645 from chdorner/dev/black-versions
Pin black versions
2023-02-02 16:33:38 -08:00
Christof Dorner 5887a3e246
Merge pull request #2646 from 0x29a/improve-search
Improve search results
2023-02-02 22:11:12 +01:00
0x29a 22eeee7368 Urlencode search query 2023-02-02 21:02:57 +01:00
Christof Dorner 60a0075bf4 Pin Github Actions black to 22.12.0 2023-02-02 12:36:46 +01:00
Christof Dorner aecd4d2a4f Upgrade development black to 22.12.0 2023-02-02 12:36:34 +01:00
Robert George 6b97702cc4 Fix long line 2023-02-01 13:19:57 -08:00
Robert George 36605efd20 Added support for secure cookies and django-csp 2023-02-01 12:59:10 -08:00
Dustin Steiner 610a4e8a66
chore: run styling 2023-01-31 18:44:09 +00:00
Dustin Steiner 96097f3b58
chore: use bulma override for mobile dropdown instead of classes 2023-01-31 18:33:44 +00:00
Dustin Steiner 90f996ac90
chore: multi line comment for linter 2023-01-31 10:16:44 +00:00
Dustin Steiner c2a81d88bb
Merge branch 'main' into book-series-v1 2023-01-31 10:06:07 +00:00
Dustin Steiner d0ac65b931
chore: reset translation files 2023-01-31 10:05:03 +00:00
Dustin Steiner f30a0ae714
chore: more dropdown resizes 2023-01-31 08:12:57 +00:00
Dustin Steiner ed040cd3e4
Merge branch 'main' into mobile/dropdown-larger-size 2023-01-31 08:01:29 +00:00
Mouse Reeve 006ff697b9
Merge pull request #2636 from 0x29a/redundant-db-queries
Remove redundant DB queries
2023-01-30 09:03:18 -08:00
Mouse Reeve 686d5625ed
Merge pull request #2627 from MeecoLabs/admin-manually-activate-user
Button in admin view to manually activate pending user
2023-01-30 09:01:05 -08:00
Mouse Reeve 46607df7e5 Merge pull request #2628 from chdorner/fix/improve-federated-generatednotes-in-feed
Improve feed header for federated generated notes
2023-01-30 08:36:36 -08:00
Mouse Reeve 8f88b72620 Adds info about celery endpoint in admin view 2023-01-30 08:35:24 -08:00
Mouse Reeve c1090703e2 Adds a ping-able celery url
This will let admins set up a check to notify you if celery is not
running.
2023-01-30 08:27:40 -08:00
Giebisch f085315d70 Added Backend Part 2023-01-30 16:12:14 +01:00
Dustin Steiner e0505722e1
chore: formatting 2023-01-30 14:45:30 +00:00
Dustin Steiner f4cde843c0
chore: larger dropdown size for mobile devices 2023-01-30 14:40:33 +00:00
Dustin Steiner 59a8098517
chore: add translations 2023-01-30 08:26:59 +00:00
Dustin Steiner 1d0599d6d9
chore: make and compile messages 2023-01-30 08:23:06 +00:00
0x29a 5e87504b22 Remove duplicated editions request from book.html 2023-01-30 06:45:48 +01:00
0x29a f2d7efe2ba Remove duplicated readthrough request from comment.html 2023-01-30 06:45:48 +01:00
0x29a 6e1418c5d4 Remove duplicated mentions request from layout.html 2023-01-30 06:45:48 +01:00
0x29a 6ea2513790 Remove duplicated notifications request from layout.html 2023-01-30 06:45:48 +01:00
0x29a 3c52426a1c Optimize get_suggested_books 2023-01-30 06:45:44 +01:00
Dustin Steiner 0628ccad41
chore: sort editions with series number before edition rank 2023-01-29 11:43:56 +00:00
Dustin c0e541c7ed
Merge branch 'main' into admin-manually-activate-user 2023-01-29 11:21:31 +00:00
Dustin 23e04c2e62
Merge branch 'main' into book-series-v1 2023-01-29 09:36:52 +00:00
Dustin Steiner 4b64b70753
fix: sort series by float 2023-01-29 09:35:02 +00:00
Ritik Ranjan adcf9310a0 Fixed Syntax of pluralisation 2023-01-28 21:23:08 +05:30
Ritik Ranjan a12dc692ce Merge remote-tracking branch 'origin/main' into pluralization-error 2023-01-28 21:16:36 +05:30
Ritik Ranjan e5e9e807ca Splited stirng into two then fixed pluralization error. 2023-01-28 21:11:20 +05:30
Mouse Reeve d0a0851123
Merge pull request #2629 from 0x29a/performance-fixes
Minor performance improvements
2023-01-28 07:18:50 -08:00
Mouse Reeve e3ce12671a
Merge pull request #2630 from hughrun/shepherd
fix sass compound selector extensions
2023-01-28 07:18:34 -08:00
Dustin Steiner f2902e8de5
fix: sort series number as int 2023-01-28 08:38:57 +00:00
Dustin Steiner 952dd0dcdf
style: fix unused parameter linter error 2023-01-28 08:31:41 +00:00
Dustin Steiner 3fdbfe405b
fix: rename activate user form name 2023-01-28 08:31:16 +00:00
Ritik Ranjan fc599f8b9a fixed singularisation/pluralisation
edited two files
2023-01-28 12:10:06 +05:30
Hugh Rundle 2605b12ed0 fix sass compound selector extensions
Sass changed the way compound selectors can be extended, as outlined here:
https://sass-lang.com/documentation/breaking-changes/extend-compound

This commit aligns the styles in shepherd.scss to the nwe compound selector extension format.
2023-01-28 14:18:05 +11:00
0x29a cbd75dc766 Minor performance improvements 2023-01-27 20:24:53 +01:00
Christof Dorner 46bfc184f5 Improve feed header for federated generated notes
This works for wants/started/finished reading generated notes, but not yet for "set a goal".
2023-01-27 17:49:48 +01:00
Dustin Steiner 54aea0654a
style: run linter 2023-01-27 15:47:22 +00:00
Dustin Steiner 3d29524e29
chore: reverse support for localhost domain 2023-01-27 15:45:43 +00:00
Dustin Steiner 07f4300176
feat: button in admin view to manually activate pending user 2023-01-27 15:43:34 +00:00
Dustin Steiner 94c28810f1
Merge branch 'main' into book-series-v1 2023-01-26 20:18:18 +00:00
Mouse Reeve 48ac90a984
Merge pull request #2624 from bookwyrm-social/update_locales
Updates locales
2023-01-26 09:06:31 -08:00
Mouse Reeve a9142d9858 Updates locales 2023-01-26 08:55:52 -08:00
Dustin Steiner 264d32bf1b
Merge branch 'main' into book-series-v1 2023-01-26 16:43:53 +00:00
Mouse Reeve 90e3661636
Merge pull request #2623 from chdorner/fix/passwordless-redis
Fix passwordless redis connection string
2023-01-26 08:41:46 -08:00
Dustin Steiner ba2ff7e7a5
Merge branch 'main' into book-series-v1 2023-01-26 16:40:32 +00:00
Dustin Steiner 5cc158e3be
Merge branch 'main' into book-series-v1 2023-01-26 16:36:19 +00:00
Mouse Reeve d1d77ca9c3
Merge pull request #2622 from jaschaurbach/update-contrib
add "import" to celery worker
2023-01-26 08:33:42 -08:00
Christof Dorner afab255c85 Allow empty broker and activity redis password 2023-01-26 17:24:20 +01:00
Jascha Urbach c26387baea
add "import" to celery worker
import was missing in ExecStart for celery
2023-01-26 17:24:18 +01:00
Christof Dorner 80d3474cef Quote redis activity password
Same as the broker password in celerywyrm/settings.py
2023-01-26 17:23:55 +01:00
Mouse Reeve 62d1c54b31
Merge pull request #2613 from hughrun/authorized-fetch
Enable communication with "authorized_fetch" Mastodon servers
2023-01-26 08:21:34 -08:00
Mouse Reeve 2553a083f5
Merge pull request #2621 from bookwyrm-social/expose-import-queue
Show import queue in Celery admin
2023-01-26 08:18:42 -08:00
Mouse Reeve d12e755080
Merge pull request #2620 from jaschaurbach/update-requirements
Update requirements.txt
2023-01-26 08:13:50 -08:00
Mouse Reeve ef48149844 Show import queue in Celery admin 2023-01-26 07:52:37 -08:00
Jascha Urbach 7c75c246d2
Update requirements.txt
Important bugfixes and performance updates.

did not touch opentelemetry or the dev  dependencies.

No breaking changes.
2023-01-26 16:51:32 +01:00
Mouse Reeve 9c3c34834f Update version number 2023-01-26 07:39:25 -08:00
Mouse Reeve 9be2f00064
Update test_signing.py 2023-01-26 07:19:53 -08:00
Mouse Reeve e55e4429b1
Merge pull request #2604 from rrgeorge/redis-sockets
Add support to connecting to redis via unix socket
2023-01-26 06:39:15 -08:00
Mouse Reeve f4de00088f
Merge branch 'main' into authorized-fetch 2023-01-26 06:22:03 -08:00
Mouse Reeve 8a65296c29
Merge pull request #2618 from hughrun/tests
use mocks for isni API calls
2023-01-26 06:06:05 -08:00
Mouse Reeve 4b6678903f
Merge pull request #2617 from bookwyrm-social/follow-priority
Make follow activities a high priority
2023-01-26 06:03:57 -08:00
Dustin 1d909ee8e1
Merge branch 'main' into book-series-v1 2023-01-26 06:50:22 +00:00
Dustin Steiner eb4672ff18
style: format 2023-01-26 06:49:55 +00:00
Hugh Rundle 63dafd54d3 black
I can't even tell what it thinks it did, but Black likes to complain.
2023-01-26 17:24:51 +11:00
Hugh Rundle 821169251c add more verbose comment to settings.py 2023-01-26 17:19:44 +11:00
Hugh Rundle c86fdfbd40 black 2023-01-26 16:56:11 +11:00
Hugh Rundle 1fe6892d0a pylint 2023-01-26 16:54:14 +11:00
Hugh Rundle aa6eaccfbb use mocks for isni API calls
- fixes a couple of tests making author ISNI calls
- notes a future TODO to remove some possibly useless code
2023-01-26 16:22:50 +11:00
Mouse Reeve 9b8c6d54f7
Merge pull request #2554 from chdorner/feat/registration-default-user-auth-group
Allow to set default user auth group
2023-01-25 18:22:37 -08:00
Mouse Reeve 9fdcc7debd Fixes mocks in tests 2023-01-25 09:32:45 -08:00
Mouse Reeve b89cab1ee5 Fixes args passed to inbox activity task 2023-01-25 07:39:43 -08:00
Hugh Rundle 578de27515
Merge pull request #2610 from Giebisch/rss-feed
Add RSS feed for reviews, quotes, comments only
2023-01-25 20:04:34 +11:00
Mouse Reeve 858bf70d62 Make follow activities a high priority
This should go a long way towards fixing the problems with follows not
going through to remote servers. All it does is move relationship
related activities from the medium priority queue, which gets
backlogged easily, to the high priority queue, which is less backlogged.

The risk here is that the high priority queue could end up getting
backlogged, so this isn't the last word on fixing this, but I think the
volume of activities that this will add to it will be manageable.
2023-01-24 08:46:29 -08:00
Dustin aad934fa59
Merge branch 'main' into book-series-v1 2023-01-24 13:14:28 +00:00
Dustin Steiner cd13e6f523
style: run linter 2023-01-24 13:14:06 +00:00
Dustin Steiner 35d30a41f3
feat: first version of a book series list by author 2023-01-24 13:00:18 +00:00
Giebisch 3d99908d27 Fixed Object Selection for RSS Feeds 2023-01-23 15:17:20 +01:00
Hugh Rundle f0e1767bc9 black code 2023-01-22 16:10:30 +11:00
Hugh Rundle 803bba71a6 fix error handling
- when using raise_for_status we need to catch an HTTPError, not a ConnectionError
- simplify instance actor - use internal email address since it will never be used anyway, and make default username less likely to already be in use.
2023-01-22 15:59:19 +11:00
Christof Dorner c991733c8d Set default auth user group to editor on initdb 2023-01-21 17:04:32 +01:00
Christof Dorner 7ae983acdf Use default user auth group from site settings 2023-01-21 17:04:32 +01:00
Christof Dorner 2c680cb365 Add default user auth group to registration settings 2023-01-21 17:04:32 +01:00
Giebisch 88ddee74ae Sync main and fix user page 2023-01-21 00:22:00 +01:00
Giebisch 5d61003ce7 Merge branch 'main' into rss-feed 2023-01-20 23:29:33 +01:00
Giebisch 70f4d72322 Added Tests for several RSS Feeds 2023-01-20 23:28:50 +01:00
Hugh Rundle 317fa5cdfd black 2023-01-20 20:05:14 +11:00
Hugh Rundle e8452011f7 handle get_data exceptions better
Makes exception handling more precise, only raising status for 401s.

Also fixes a string pylint was complaining about.
2023-01-20 19:55:38 +11:00
Hugh Rundle f8c9df4aff pylint fixes 2023-01-20 18:20:18 +11:00
Hugh Rundle 4108238716 resolve SECURE_FETCH bugs
ERROR HANDLING FIXES

- use raise_for_status() to pass through response code
- handle exceptions where no response object is passed through

INSTANCE ACTOR

- models.User.objects.create_user function cannot take an ID
- allow instance admins to determine username and email for instance actor in settings.py
2023-01-20 16:32:17 +11:00
Hugh Rundle 0da5473b0c black formatting 2023-01-20 16:31:27 +11:00
Hugh Rundle 0c614e828f deal with missing digests in signatures
If no digest value is passed to make_signature and Exception was thrown.
Since digest is added to the signature headers if it is not None anyway, there is no need to assign the digest value before that check.
When signing a request _as the server_ for Mastodon's AUTHORIZED_FETCH there is no need to include a digest.
2023-01-20 08:24:46 +11:00
Mouse Reeve 6425e569c5
Merge pull request #2612 from bookwyrm-social/adds-merge-migration
Adds merge migration
2023-01-19 13:22:56 -08:00
Mouse Reeve 9ef5d53696 Python formatting 2023-01-19 13:06:58 -08:00
Hugh Rundle d97d6acfa4
Merge pull request #2599 from asmaloney/opengraph-book-and-list
Improve Open Graph data for books and add it for lists
2023-01-20 07:58:34 +11:00
Mouse Reeve a9f59ef8d5 Adds merge migration 2023-01-19 12:17:41 -08:00
Mouse Reeve 3e969bb349
Merge pull request #2606 from jaschaurbach/author_website
Add Website to author
2023-01-19 12:08:01 -08:00
Mouse Reeve 0594152f47
Merge pull request #2511 from Giebisch/import-limit
Added Import Limit
2023-01-19 11:16:58 -08:00
Hugh Rundle 9a0f8f9c2a fix test_get_representative_not_existing params 2023-01-19 16:40:13 +11:00
Mouse Reeve 2ceea24763
Merge pull request #2608 from kvibber/rss-autodiscover
Enable RSS autodiscovery on user profile
2023-01-18 19:51:15 -08:00
Kelson Vibber 919c9a7585 Add site name to RSS autodiscovery title 2023-01-18 18:27:51 -08:00
Andy Maloney 89c1edac36 Improve Open Graph data for books and add it for lists 2023-01-18 10:30:26 -05:00
Mouse Reeve 7f3551bab8
Merge pull request #2605 from rrgeorge/fix-barcode-scanner
Fix barcode scanner
2023-01-18 05:55:20 -08:00
Hugh Rundle d66e2fe861 merge in latest changes 2023-01-18 14:12:01 +11:00
Giebisch 18c786f63f Added RSS API 2023-01-17 21:59:05 +01:00
Giebisch bfc8856f66 Merge branch 'main' into rss-feed 2023-01-17 20:54:41 +01:00
Kelson Vibber fd7dcb320e fix mimetype on rss autodiscovery and add title 2023-01-16 22:30:15 -08:00
Kelson Vibber 78422ac35b Add RSS autodiscover support to user profile page 2023-01-16 21:46:50 -08:00
Mouse Reeve 1b17b94a28
Merge pull request #2607 from cthos/fix-email-user-settings-page
Email Config View Has a Typo
2023-01-16 19:34:07 -08:00
Giebisch 5faf7f5e87 Fixed Import limit for retries 2023-01-17 01:07:10 +01:00
Alexander Ward 1f50a2dbfc
Email Config Has a Typo
There's an errant capital "E" preventing the SMTP user from appearing on the settings page.
2023-01-16 15:47:24 -08:00
Giebisch d0adb370cd Merge branch 'main' into import-limit 2023-01-16 02:05:18 +01:00
Jascha Urbach 54e0fdd5ae
Here we go again! 2023-01-15 09:41:39 +01:00
Robert George 95b66480c9 lint fixes 2023-01-14 18:20:37 -08:00
Mouse Reeve 10322cdff3
Merge pull request #2572 from chdorner/fix/create-edit-book-cover-url
Ensure transient `cover_url` field value gets persisted across form renders
2023-01-14 18:08:22 -08:00
Robert George f362343dfa style fixes 2023-01-14 15:44:10 -08:00
Robert George 207abed654 Add support for specifying redis url to support unix sockets 2023-01-14 14:52:54 -08:00
Robert George 92341fb43a Add missing isbn span for barcode search 2023-01-14 14:38:16 -08:00
Mouse Reeve 788a33ee8a
Merge pull request #2600 from chdorner/fix/card-header
Fix generated note content checks in card header template
2023-01-12 15:41:52 -08:00
Christof Dorner 0291ffbcb1 Fix generated note content checks in card header template 2023-01-12 20:58:41 +01:00
Mouse Reeve 0f0da0bdbb
Merge pull request #2598 from bookwyrm-social/revert-2555-author_website
Revert "Add Website field to author"
2023-01-11 19:30:41 -08:00
Mouse Reeve dd2b166382
Revert "Add Website field to author" 2023-01-11 19:21:40 -08:00
Mouse Reeve 60f3f8fcc0
Merge pull request #2596 from bookwyrm-social/commented-nginx
Re-comment nginx config
2023-01-11 17:07:00 -08:00
Mouse Reeve 8fa8d433aa Re-comment nginx config
I thought this didn't need to be commented out but it does (if it isn't,
it tried to load the cert, which doesn't yet exist)
2023-01-11 16:56:31 -08:00
Mouse Reeve b89060d5fc
Merge pull request #2594 from bookwyrm-social/locales
Updates locales
2023-01-11 15:02:15 -08:00
Mouse Reeve 71f5e5a688 Updates locales 2023-01-11 14:47:42 -08:00
Mouse Reeve ba5d0f1b14
Merge pull request #2593 from asmaloney/opengraph
Move all opengraph (/twitter) metadata into one template
2023-01-11 14:44:15 -08:00
Andy Maloney b4aa39f0ed Move all opengraph (/twitter) metadata into one template
This makes it easier to modify & allows us to set title & description for specific types of pages.

Sets us up for #2575
2023-01-11 16:17:41 -05:00
Mouse Reeve 5c8145b79d
Merge pull request #2586 from asmaloney/fix-duplicate-suggestions
{list} Fix duplicate suggestions in Add Books section
2023-01-11 08:40:32 -08:00
Mouse Reeve bae3986a85
Merge pull request #2588 from asmaloney/spelling-author
Fix spelling in author form
2023-01-11 07:27:34 -08:00
Mouse Reeve c279477507
Merge pull request #2590 from asmaloney/spelling-blocktrans-arg
Fix spelling in blocktrans arg
2023-01-11 07:27:27 -08:00
Mouse Reeve 5ab67cac87
Merge pull request #2591 from asmaloney/spelling-various
Fix spelling in various comments
2023-01-11 07:27:18 -08:00
Giebisch b9576ccd31 Merge conflict fix 2023-01-11 16:26:36 +01:00
Giebisch b22d060d93 Merge branch 'main' into import-limit 2023-01-11 16:22:08 +01:00
Mouse Reeve bc276c4b3a
Merge pull request #2589 from asmaloney/spelling-aria
Fix two "aria-hidden" tags
2023-01-11 07:20:21 -08:00
Giebisch d35fec8217 Fixed trans 2023-01-11 15:18:50 +01:00
Giebisch 88e993d727 Frontend Mockup 2023-01-11 15:12:22 +01:00
Andy Maloney e5539a6faf Fix spelling in various comments 2023-01-10 17:24:02 -05:00
Andy Maloney c6d2edfe7a Fix spelling in blocktrans arg 2023-01-10 17:21:00 -05:00
Andy Maloney e1c90314ad Fix two "aria-hidden" tags 2023-01-10 17:17:03 -05:00
Andy Maloney a027204e5b Fix spelling in author form
"oepnlibrary" ➡️ "openlibrary"
2023-01-10 16:51:13 -05:00
Andy Maloney dd23bc4d0f {list} Fix duplicate suggestions in Add Books section
Fixes #2584

(Also fix a spelling mistake in a comment in book_search.py)
2023-01-10 11:08:11 -05:00
Mouse Reeve 917569ef0e
Merge pull request #2373 from codeurimpulsif/contrib-system
Add contrib directory with systemd service files for front, worker and scheduler
2023-01-09 20:26:02 -08:00
Mouse Reeve cdf51ccbc4
Merge pull request #2580 from Giebisch/fix-rating-half-stars
Fix Half Stars for Rating books
2023-01-09 20:24:50 -08:00
Mouse Reeve bdd32c5628
Merge pull request #2555 from jaschaurbach/author_website
Add Website field to author
2023-01-09 20:14:14 -08:00
Mouse Reeve c9fa90f83b
Merge pull request #2547 from avandeursen/docker-test-run
Ensure django tests pass in default Docker setting
2023-01-09 20:06:39 -08:00
Mouse Reeve 9480318c5d
Merge pull request #2544 from joachimesque/redirect-after-shelving-book
Redirect back to the original page after shelving book
2023-01-09 20:05:13 -08:00
Giebisch 892ba563a4 Fix Half Stars for Rating books 2023-01-07 20:59:32 +01:00
Joachim 336c92d96e
Merge branch 'main' into redirect-after-shelving-book 2023-01-06 15:13:57 +01:00
Giebisch 5200ea585a Import Limit Bugfix and lint 2023-01-05 23:37:43 +01:00
Christof Dorner 1c6548a0ad Ensure transient cover_url field value gets persisted across form renders
Given this field doesn't map to an `Edition` model field it lost its values when re-rendering the form.
It worked only when the form was valid and rendered as part of the confirmation screen, which is due to
the context data value being set in `add_authors` which was only getting called after the form validation.

I've opted to pull it out into a separate new function that gets called before form validation.
2023-01-04 18:02:04 +01:00
Giebisch 6d1de44c48 Sync with main and merge migrations 2023-01-02 17:38:43 +01:00
Mouse Reeve 2bd94b1332
Merge pull request #2563 from joachimesque/update-github-actions
Update github actions versions
2023-01-02 07:58:25 -07:00
Giebisch 7e7966987b Merge branch 'main' into import-limit 2023-01-02 15:42:50 +01:00
Joachim 4b55b4c026 Update black 2023-01-01 21:09:25 +01:00
Joachim 3f6cdff363 Update github actions versions 2023-01-01 21:06:35 +01:00
Joachim fa3edea87b Update validate.py 2023-01-01 20:51:23 +01:00
Joachim ac2ef667af Fix error when no referer 2023-01-01 19:57:10 +01:00
Joachim bc19d7c658 Black 2023-01-01 19:45:12 +01:00
Joachim f266c71da9 Replace hidden field with HTTP Referrer value 2023-01-01 19:42:03 +01:00
Arie van Deursen 2bf8cd88f1
Fix @pytest.mark.skipif formatting 2022-12-30 18:44:28 +01:00
Joachim 78c214a6d4 Add validation before using url 2022-12-30 17:56:25 +01:00
Joachim bfe04feca9 Add validation util + test 2022-12-30 17:55:47 +01:00
Doctor 45aa397863 Add redis.service in After for bookwyrm and bookwyrm-scheduler services 2022-12-30 17:36:16 +01:00
Codimp 358a0e60a9 Add systemd service files for bookwyrm front, worker and scheduler 2022-12-30 17:36:16 +01:00
Codimp 1e0cbe776c Add contrib directory with explanation 2022-12-30 17:36:16 +01:00
Mouse Reeve e026f4535a
Merge pull request #2550 from chdorner/fix/cache-languages
Fix fragment caches (language codes, cache keys, etc.)
2022-12-30 07:33:15 -08:00
Mouse Reeve ca89a6f098
Merge pull request #2543 from joachimesque/user-menu-mobile-align-right
User menu mobile align right
2022-12-30 07:20:23 -08:00
Jascha Urbach 2d76595af6
Add Website field to author
Authors have Websites. that might be interesting for BookWyrm users. Now there is a field specify the website of an author and it is shown tu users under the wikipedia link

Adds max char for ISFDB ID (6) and ISNI (19 - 16 plus three -)
2022-12-28 15:41:48 +01:00
Joachim 5c92774a7f Merge branch 'main' into redirect-after-shelving-book 2022-12-28 10:44:41 +01:00
Mouse Reeve cfbd0b97fc
Merge pull request #2552 from chdorner/fix/example-env-redis
Add REDIS_BROKER_HOST to example env
2022-12-27 06:40:14 -08:00
Christof Dorner 31028e9573 Add REDIS_BROKER_HOST to example env
This might avoid future confusion when somebody wants to run
this dockerless for example, given that in the settings module
this gets the default value of `redis_broker` when not set.
2022-12-27 11:29:09 +01:00
Christof Dorner 247d85305c Fix cache duration comment 2022-12-26 17:52:58 +01:00
Christof Dorner 9aad37acd5 Specificy fragment name in cache key for landing page 2022-12-26 17:52:03 +01:00
Christof Dorner 51c932802a Use language in cachey key for about_page_superlatives 2022-12-26 17:50:51 +01:00
Arie van Deursen 5d63b48328
Fix postgres to version 13 in Docker compose
Helps to make tests reproducible, and avoids accidentally
relying on postgres:11 in which some tests fail.
2022-12-26 14:27:46 +01:00
Arie van Deursen 1c0a3a7829
Only test thumbnails if they're enabled in the settings 2022-12-26 14:26:23 +01:00
Arie van Deursen 8441314e7c
Enable thumbnail generation in example environment
This makes the example environment more similar to the
setting in the django-tests.yml GitHub workflow.

It also ensures thumbnail generation is tested by default.
2022-12-26 14:23:19 +01:00
Joachim f5a79dfa82 Redirect to "next" value in view 2022-12-23 21:35:28 +01:00
Joachim 3f52d6ee33 Add hidden "next" input set to current path 2022-12-23 21:34:53 +01:00
Joachim 00d14cd37c Stylelint 2022-12-23 20:25:42 +01:00
Joachim 91d67b44fd Add back button to user submenu on mobile 2022-12-23 20:17:35 +01:00
Joachim 7f3b208927 Align user menu to the right on mobile 2022-12-23 20:17:12 +01:00
Mouse Reeve 6947e74f5d
Merge pull request #2525 from jaschaurbach/fix-form-submit
Update forms.js
2022-12-21 11:10:21 -08:00
Mouse Reeve d0f7cf56f6
Merge pull request #2529 from chdorner/fix/titleby-cache-clearing
Fix titleby cache fragment clearing
2022-12-21 11:06:13 -08:00
Mouse Reeve a4c3b79f41
Merge pull request #2532 from bookwyrm-social/generated-note-display
Display generated notes correctly depending on format
2022-12-21 11:05:48 -08:00
Mouse Reeve b2fd5c26b9
Merge pull request #2538 from bookwyrm-social/basque
Adds Basque language
2022-12-21 10:56:50 -08:00
Mouse Reeve 8f3d702652
Merge pull request #2537 from chdorner/fix/admin-system-nav-items
Fix permissions check for System admin navigation section
2022-12-21 10:37:23 -08:00
Mouse Reeve f2a52d4a18 Adds Basque language 2022-12-21 10:30:51 -08:00
Mouse Reeve 287cf75698
Merge pull request #2533 from bookwyrm-social/update_locals
Updates locales
2022-12-21 09:47:03 -08:00
Christof Dorner 4f6e4462dc Fix permissions check for System admin navigation section 2022-12-20 22:39:59 +01:00
Christof Dorner 3e25b04e4a Cache book_titleby only for 10 seconds
This should be enough caching when renderering pages like the feed, but
not so much that editing a book or author will not show the updated data.
At least without having to do some clever cache busting.
2022-12-20 21:48:16 +01:00
Giebisch 8f9ac82094 Handle unlimited Imports 2022-12-20 21:32:58 +01:00
Jascha Urbach 8a4d500489
Merge branch 'bookwyrm-social:main' into fix-form-submit 2022-12-20 21:21:05 +01:00
Jascha Urbach 105144a026
New approach: Event Delegation
This works as follows:

The div where the input fields for the subjects live got an id. The script now listens to all keypresses in this div, but only does something if it is within an INPUT field. If it is an INPUT field within this div, it looks for keyCode 13. If it is 13, preventDefault() is triggered.  Else nothing happens.
2022-12-20 11:36:14 +01:00
Mouse Reeve 9c03ba48fb Updates locales 2022-12-19 20:20:21 -08:00
Mouse Reeve d3c15efa0a Display generated notes correctly depending on format 2022-12-19 16:24:32 -08:00
Jascha Urbach 259ceeea21
./bw-dev prettier 2022-12-20 00:06:02 +01:00
Jascha Urbach e4892701d8
Update forms.js
Now it works in the correct fields.
2022-12-19 23:57:00 +01:00
Mouse Reeve 5ea922a551
Merge pull request #2528 from bookwyrm-social/broadcast-queues
Increase priority for follow activities and lower for shelve
2022-12-19 14:37:10 -08:00
Mouse Reeve fe29d30ab5
Merge pull request #2522 from joachimesque/disable-remote-users-preview-images
Disable remote users preview images generation
2022-12-19 14:36:52 -08:00
Giebisch 3295d419bf Add Test for Import Limit 2022-12-19 23:25:43 +01:00
Mouse Reeve 157c9c825b Increase priority for follow activities and lower for shelve 2022-12-19 14:07:44 -08:00
Joachim f0dc146005 Merge branch 'main' into disable-remote-users-preview-images 2022-12-19 22:32:30 +01:00
Joachim a44f427d84 Add remote user test before the task is called 2022-12-19 22:26:09 +01:00
Giebisch 32463c1157 Fix merge 2022-12-19 21:50:34 +01:00
Mouse Reeve c57d8d14b3
Merge pull request #2526 from jaschaurbach/bump_requirements
bump some versions in requirements
2022-12-19 12:46:03 -08:00
Mouse Reeve 7397a2dcb1
Merge branch 'main' into bump_requirements 2022-12-19 12:28:33 -08:00
Mouse Reeve 271337a7e5
Merge pull request #2523 from joachimesque/update-pillow-deprecated
Remove deprecation warnings from Pillow
2022-12-19 12:27:13 -08:00
Mouse Reeve 66dc070a26
Merge pull request #2527 from chdorner/fix/compile-scss
Disable sass processer when not in debug mode
2022-12-19 12:16:42 -08:00
Christof Dorner aefc02e3ee Disable sass processor when not in debug mode 2022-12-19 18:43:16 +01:00
Christof Dorner 744bd33d99 Add compile_themes command to themes admin page instructions 2022-12-19 18:43:16 +01:00
Christof Dorner 8bb5c867eb Add compile_themes to bw-dev 2022-12-19 18:43:16 +01:00
Christof Dorner f5ebdd4ba1 Add compile_themes management command 2022-12-19 18:43:16 +01:00
Jascha Urbach befcf4f3e9
bump some versions in requirements
Why update:

iohttp: supports now more of http standard.
celery: supports redis > = 4.0.2 (the docker image uses redis 7.0.6
django-celery-beat: better Django 3.2 support, bump celery to 5.2, downgrade of dependencies for better celery support
django-compressor: official Django 3.2 support, updates requirements
django-model-utils: official django 3.2 support.
django-sass-processor: remove deprecated default_app_config, support of ManifestStaticFilesStorage (which might be needed in the future)
environs: bugfixes
libsass: removes deprecated cli
Pillow: bug fixing
psycopg2: Bugfixing
pycryptodome: bugfixes
python-dateutil: updated tzdata
requests: better json Handling, bugfixing
responses: bugfixes and more
pytz: python3 code generation, All the corect timezone behaviour!
boto3: Updsate all the S3 Handling

signtures.py update because of breaking change in pycryptodome

migration because uf updated timezones

With updated celery I have less 501 errors on my instance. updated psycopg2 has better performance.

I have NOT chekced opentelemetry packages.

Upgrading redis package wold need a deeper inspection of the code as some functions are dropped in newer versions.
2022-12-19 16:37:41 +01:00
Jascha Urbach 7c88f7081c
Merge branch 'bookwyrm-social:main' into fix-form-submit 2022-12-18 22:53:36 +01:00
Jascha Urbach 64968c3081
Update forms.js
fixes #2519
2022-12-18 22:28:05 +01:00
Joachim c5eb27a7c5 Lint 2022-12-17 20:27:39 +01:00
Joachim 26f8710c6f Black 2022-12-17 19:52:58 +01:00
Joachim bf82b4cd35 Replace Font.getsize_multiline with Draw.multiline_textbbox 2022-12-17 19:52:52 +01:00
Joachim 003d1425f9 Fix comments 2022-12-17 19:32:10 +01:00
Joachim 684e84f5c3 Remove deprecated Font.getsize()
https://pillow.readthedocs.io/en/stable/deprecations.html#font-size-and-offset-methods
2022-12-17 19:24:07 +01:00
Joachim 86c810ee37 Change ANTIALIAS to Resampling.LANCZOS 2022-12-17 18:44:17 +01:00
Joachim 4549edb569 Bump Pillow minimum version 2022-12-17 18:43:48 +01:00
Joachim e9abae9b7d Add shell completion for remove_remote_user_preview_images command 2022-12-17 18:05:33 +01:00
Joachim 00c2930290 Black 2022-12-17 17:56:28 +01:00
Joachim cd940e2c40 Add tests for remove_user_preview_image_task 2022-12-17 17:49:39 +01:00
Joachim b570602a47 Update remove_remote_user_preview_images.py 2022-12-17 17:35:44 +01:00
Joachim 75ea2cdbb4 Fix generate_user_preview_image_task comment wording 2022-12-17 17:34:49 +01:00
Joachim 09c095cfec Add remove_remote_user_preview_images command 2022-12-17 17:34:27 +01:00
Joachim 8c34b23c35 Disable preview images generation for remote users 2022-12-17 11:39:10 +01:00
Mouse Reeve d86e6a6949
Merge pull request #2516 from bookwyrm-social/import-queue
Create a separate celery queue for imports
2022-12-16 14:58:35 -08:00
Mouse Reeve 37bd90e88b
Merge pull request #2515 from bookwyrm-social/import-statuses
Don't add imported reviews to timelines
2022-12-16 14:58:24 -08:00
Mouse Reeve e9ad1b4bf0
Merge pull request #2517 from bookwyrm-social/import-status
Don't mark imports as active until their job task runs
2022-12-16 14:50:23 -08:00
Mouse Reeve 7ff654720c updates tests 2022-12-16 14:45:32 -08:00
Mouse Reeve 3972d1cc7b Don't mark imports as active until their job task runs 2022-12-16 14:41:35 -08:00
Mouse Reeve 427d0c4fc8 Create a separate celery queue for imports 2022-12-16 14:20:50 -08:00
Mouse Reeve 0354eb9828 Don't add imported reviews to timelines
Generally they're so backdated that they don't add, and they put too
much load on the instance.
2022-12-16 14:11:15 -08:00
Mouse Reeve 44941ffc9c
Merge pull request #2514 from bookwyrm-social/update-locales
Updates locales
2022-12-16 13:10:14 -08:00
Mouse Reeve 01524110a7 Updates locales 2022-12-16 12:53:40 -08:00
Mouse Reeve 1a2a5b8bd2
Merge pull request #2499 from bookwyrm-social/nginx-prod
Updates nginx production config
2022-12-16 12:48:05 -08:00
Mouse Reeve d4351cfcb4
Merge branch 'main' into import-limit 2022-12-16 12:44:57 -08:00
Mouse Reeve bcec4f07c5
Merge pull request #2510 from jaschaurbach/main
delete avatar when user is deleted
2022-12-16 12:42:42 -08:00
Mouse Reeve 09e4735ad9
Merge pull request #2512 from hueyy/fix/year_of_reading_no_page_data
Fix year of reading: phrasing when there are books without page data
2022-12-16 12:24:14 -08:00
Huey b11a2dafc4
fix #2508 2022-12-16 10:38:08 +08:00
Giebisch df54df8309 Added Import Limit 2022-12-15 23:43:25 +01:00
Jascha Urbach 0744bd5385
delete avatar when user is deleted 2022-12-15 23:01:56 +01:00
Mouse Reeve 89478ac87e
Merge pull request #2491 from chdorner/register-tz-support
Detect preferred timezone via JavaScript on register
2022-12-11 14:49:29 -08:00
Christof Dorner 13b262bb7b Detect preferred timezone via JavaScript on register 2022-12-11 23:32:07 +01:00
Mouse Reeve c75bb1b4f8
Merge pull request #2504 from bookwyrm-social/version
Update version number and javascript cache buster
2022-12-11 13:57:23 -08:00
Mouse Reeve abf206a82b Update version number and javascript cache buster 2022-12-11 13:46:53 -08:00
Mouse Reeve bb5564461c
Merge pull request #2398 from bookwyrm-social/html-in-activitypub
Render markdown to html when using activitypub
2022-12-11 13:43:36 -08:00
Mouse Reeve 9ed2f7fc2b
Merge pull request #2502 from bookwyrm-social/locales
Updates locales
2022-12-11 13:43:18 -08:00
Mouse Reeve a6604c197d Updates tests 2022-12-11 13:19:26 -08:00
Mouse Reeve 6f8251a283 Updates locales 2022-12-11 13:10:48 -08:00
Mouse Reeve 3a9a344089
Merge pull request #2478 from bookwyrm-social/admin-roles
Adds "owner" role
2022-12-11 13:05:39 -08:00
Mouse Reeve 53ddaee3d9
Merge pull request #2501 from bookwyrm-social/book-keys-fix
Fixes new identifier fields in edit book form
2022-12-11 13:04:06 -08:00
Mouse Reeve 3e62cbe8b6 Fixes incorrect import from merge 2022-12-11 12:39:33 -08:00
Mouse Reeve b65a46582b Fixes new identifier fields in edit book form 2022-12-11 12:37:40 -08:00
Jascha Urbach ea316627be
Manual email confirm (#2492)
* manual approve email via bw-dev/manage.py

./bw-dev confirm_email USER
(venv) python manage.py confirm_email USER

* add "confirm_email" and "remove_2fa" to autocompletion

* OK, sometimes I feel fooled by this.

The lione was not LONG ENOUGH.

* Change deactivate reason to None

* Whyever this works now

Python in my system is a wondermachine.
2022-12-11 12:35:20 -08:00
Mouse Reeve 3a0533b7fc Updates nginx production config
This copies over the changes Trammell added to the development file. I
also realized that I think it's fine to only commend out the https
redirect, rather than commenting out the entire server block for
listening on port 443? If this works it makes the file a lot easier to
read.

Co-authored-by: Trammell Hudson <hudson@trmm.net>
2022-12-11 12:28:53 -08:00
Mouse Reeve a9846e7805
Merge pull request #2498 from bookwyrm-social/use-reactivate
Use user.reactivate when a user confirms their email address
2022-12-11 12:10:21 -08:00
Mouse Reeve 4f0e7b60d6 Adds merge migration 2022-12-11 12:03:22 -08:00
Mouse Reeve 58e8c0b5ec Merge branch 'main' into admin-roles 2022-12-11 11:58:54 -08:00
Mouse Reeve 734fb5ad34
Merge pull request #2489 from chdorner/user-reviews-comments-tab
Add new user tab listing only reviews and comments
2022-12-11 11:53:31 -08:00
Mouse Reeve d1774f0c99
Merge pull request #2497 from chdorner/add-bw-dev-eslint
Add eslint subcommand to bw-dev
2022-12-11 11:47:18 -08:00
Mouse Reeve 50a42dc0a2 Use user.reactivate when a user confirms their email address
This is cleaner and easier to maintain.
2022-12-11 11:44:04 -08:00
Mouse Reeve c314c9b5e3
Adds email config admin view (#2494)
This view lets you see your email configuration and send a test email.
2022-12-11 11:37:09 -08:00
Mouse Reeve a25a5b1032 Updates expected number of groups in tests 2022-12-11 11:35:48 -08:00
Christof Dorner 08d4b2e063 Add eslint subcommand to bw-dev 2022-12-11 20:33:38 +01:00
Jascha Urbach ac8b060d58
Isfdb ID for books and authors (#2482)
* New ID: Audible ASIN

Audible belongs to Amazon BUT they do not share the same IDs. The Audible ASIN of an audiobook is never the same as the Amazon ASIN.

Yeah, I know, Amazon is great. The fact that the ASIN is a good distinction for different works and editions bothers me more than I will ever be willing to admint.

* New ID "ISFDB"

Internet Speculative Ficiton Database ID for books and authors.
Links to the entry if set.

* Added aasin to test

Added aasin to test

* the answer expects more emptxy fields...
2022-12-11 11:33:33 -08:00
Mouse Reeve 0e2b88ad0c
Merge pull request #2495 from bookwyrm-social/edit-book-form
Uses a list of fields rather than exclusions for edit book form
2022-12-11 11:28:59 -08:00
Christof Dorner fbd8e22b97 Add new user tab listing only reviews and comments 2022-12-11 20:24:00 +01:00
Mouse Reeve 0452731d02
Merge pull request #2496 from bookwyrm-social/unit-test
Trying to fix an unreliable unit test regex
2022-12-11 11:22:56 -08:00
Mouse Reeve b4ddf281b5 Trying to fix an unreliable unit test regex 2022-12-11 11:13:16 -08:00
Mouse Reeve 3016f1416b
Merge pull request #2490 from chdorner/apple-touch-icon
Add apple-touch-icon to global layout
2022-12-11 11:10:21 -08:00
Mouse Reeve ca5676c287 Uses a list of fields rather than exclusions for edit book form 2022-12-11 10:58:19 -08:00
Mouse Reeve 3b56c85a87
Merge pull request #2488 from jaschaurbach/goodreads-visibility
goodreads_key for books editable
2022-12-11 10:51:29 -08:00
Mouse Reeve 91f8b0e15e
Merge pull request #2465 from osresearch/nginx-caching
Enable nginx caching and optimizations.
2022-12-11 10:40:38 -08:00
Christof Dorner 9ea7029c2f Add apple-touch-icon to global layout 2022-12-10 17:57:05 +01:00
Jascha Urbach 8325fbd772
goodreads_key for books editable
The field goodreads_key is now editable.
ID shows in ID section of book.
2022-12-10 10:50:25 +01:00
Mouse Reeve f779c57f33 Safely get or create permissions for tests/re-running 2022-12-06 14:25:50 -08:00
Mouse Reeve 309d5a535a
Merge pull request #2479 from bookwyrm-social/author-padding
Visually separate authors when creating book
2022-12-06 13:13:28 -08:00
Mouse Reeve a80e020344 Add direction to book page fields 2022-12-06 12:26:52 -08:00
Mouse Reeve 8d5192c816 Don't show HR under last author item in confirm view 2022-12-06 12:26:35 -08:00
Trammell Hudson 43b194d612 nginx: route /flower to the queue monitoring system.
This patch removes the exposed port for the flower
server and instead uses nginx to route urls /flower/*
to the queue monitoring system.
2022-12-06 13:01:40 +00:00
Trammell Hudson 5922e29369 Enable nginx caching and optimizations.
This patch enabled nginx caching of responses for non-logged in users
so that a boost by a popular mastodon user doesn't DDOS the bookwyrm site.
It also silences some of the nginx access logs so that static files are
not logged.
2022-12-06 13:01:40 +00:00
Mouse Reeve bffde6703c
Merge branch 'main' into html-in-activitypub 2022-12-05 17:46:31 -08:00
Mouse Reeve aecb2d38d6 Visually separate authors when creating book 2022-12-05 17:44:08 -08:00
Mouse Reeve fdaa24edfe Tweaks group query in migration for tests 2022-12-05 17:33:40 -08:00
Mouse Reeve 845bd2cc0d Only show themes to sys admin 2022-12-05 17:11:15 -08:00
Mouse Reeve a2874bf460 Updates forms 2022-12-05 17:09:10 -08:00
Mouse Reeve b8e403ce59 Fixes migration to give the correct perms 2022-12-05 17:04:58 -08:00
Mouse Reeve c7234bff64 Update admin role for new perms 2022-12-05 16:58:23 -08:00
Mouse Reeve 933cb6440f Creates admin views for owner and admin registration settings 2022-12-05 16:58:11 -08:00
Mouse Reeve dd9fbca7d7 Removes registration from site settings form 2022-12-05 16:19:15 -08:00
Mouse Reeve 9b087199ed Adds new role and permissions 2022-12-05 16:07:09 -08:00
Mouse Reeve 8951628e02 Don't try to markdownify a null field 2022-12-05 15:12:53 -08:00
Mouse Reeve 97358da503
Merge pull request #2452 from indutny/fix/gh-2451
Fix serialization of JSON-LD subarrays
2022-12-05 09:53:27 -08:00
Mouse Reeve d322da3faf
Merge pull request #2474 from bookwyrm-social/update-locales
Updates locales
2022-12-04 19:26:25 -08:00
Mouse Reeve 5a0985248d Updates locales 2022-12-04 18:26:40 -08:00
Mouse Reeve 18d1adf24a
Merge pull request #2473 from bookwyrm-social/imports-bug
Fixes bug that caused imports to be disabled unexpectedly
2022-12-04 18:16:40 -08:00
Fedor Indutny cdc833657f Fix serialization of JSON-LD subarrays
Properties like "tag" could be lists containing multiple subclasses of
ActivityObject. Make sure to serialize them recursively instead of
outputting them as they are, because otherwise we could get a bunch of
nulls in the resulting JSON and that wouldn't necessarily be a valid
JSON-LD object.

Fix: #2451
2022-12-04 18:12:39 -08:00
Mouse Reeve e7a0c3e421 Fixes bug that caused imports to be disabled unexpectedly 2022-12-04 18:07:17 -08:00
Mouse Reeve 117b86fdc0
Merge pull request #2471 from bookwyrm-social/impressum
Adds missing template
2022-12-04 13:24:07 -08:00
Mouse Reeve 26a05d2182 Adds tests for impressum page 2022-12-04 13:13:05 -08:00
Mouse Reeve 4a89a9ec88 Adds missing template 2022-12-04 13:05:03 -08:00
Mouse Reeve 5172f67c35
Merge pull request #2450 from bookwyrm-social/impressum
Adds database fields for legal page/impressum
2022-12-04 12:12:26 -08:00
Mouse Reeve b7b7b2680e Fixes unit test 2022-12-04 11:44:42 -08:00
Mouse Reeve c4d252754e
Merge pull request #2466 from rickosborne/storygraph-csv-isbn
StoryGraph import ISBN tweak
2022-12-04 11:31:12 -08:00
Mouse Reeve 300573e66e
Merge pull request #2457 from viviicat/use-html-templates
make use of templates instead of hidden divs which is more elegant
2022-12-04 11:24:04 -08:00
Mouse Reeve 5be7dad6f7
Merge pull request #2469 from bookwyrm-social/typo-fix
Typo fix
2022-12-04 11:16:57 -08:00
Mouse Reeve 712455368c Typo fix 2022-12-03 18:21:47 -08:00
Rick Osborne 862260294a
StoryGraph import ISBN tweak
Looks like SG updated their CSV headers just a little, so that the importer
hadn't been picking up the ISBN.
2022-12-02 19:16:22 -08:00
Mouse Reeve 61d8748d59
Merge pull request #2459 from viviicat/dark-theme-contrast
Dark theme contrast
2022-11-26 20:43:53 -08:00
Mouse Reeve 7eb267fbd1
Merge pull request #2460 from viviicat/visual-tweaks
Visual tweaks
2022-11-26 20:38:58 -08:00
Vivianne Langdon 56519d569d fix broken css 2022-11-26 15:29:08 -08:00
Vivianne Langdon 1fa7262b52 padding for edit shelf form 2022-11-26 15:29:08 -08:00
Vivianne Langdon 3728ee67d1 edit-list/save button spacing 2022-11-26 15:29:08 -08:00
Vivianne Langdon bfe2003e5c author book list read more spacing 2022-11-26 15:29:08 -08:00
Vivianne Langdon ab43134cc0 many minor visual tweaks to fix spacing and usability 2022-11-26 15:29:08 -08:00
Vivianne Langdon 9738c96175 fix css which caused weird spacing for desc. field 2022-11-26 15:29:08 -08:00
Vivianne Langdon 6cf028994e dark theme: increase background color darkness, fix shepherd color 2022-11-26 13:18:11 -08:00
Vivianne Langdon 86d1c8552e use transparent buttons for reply and more 2022-11-26 13:17:48 -08:00
Mouse Reeve d64dac6bbf
Merge pull request #2456 from viviicat/fix-invite-limit
registration answer not long enough client side, fixes #2377 for real
2022-11-26 13:06:51 -08:00
Mouse Reeve 3d35dc7c41
Merge pull request #2458 from viviicat/fix-fish-compilescss
Remove no-longer present `compilescss` from fish autocomplete config
2022-11-26 13:03:11 -08:00
Vivianne Langdon d9ecd35024 Remove no-longer present compilescss from fish autocomplete config 2022-11-26 12:36:52 -08:00
Vivianne Langdon c2b447cf49 lint 2022-11-26 12:19:37 -08:00
Vivianne Langdon c4398ff187 make use of templates instead of hidden divs which is more elegant 2022-11-26 12:14:48 -08:00
Vivianne Langdon e0896e3828 fix input type 2022-11-26 11:54:55 -08:00
Vivianne Langdon cac9dc2603 registration answer was not long enough client side, fixes #2377 for real 2022-11-26 11:33:16 -08:00
Mouse Reeve 8ec984c3ff Tick version number 2022-11-25 14:37:34 -08:00
Mouse Reeve df42712b8e
Merge pull request #2449 from bookwyrm-social/empty-csv
Don't start imports with empty CSVs
2022-11-25 12:31:13 -08:00
Mouse Reeve 8b068e94d5 Headers aren't one of the rows 2022-11-25 12:19:49 -08:00
Mouse Reeve 70d639440e Show impressum 2022-11-25 12:06:32 -08:00
Mouse Reeve 16f9232e1e Adds database fields for legal page/impressum 2022-11-25 11:02:42 -08:00
Mouse Reeve ccb60f45c3
Merge pull request #2447 from bookwyrm-social/fix-inventaire-import
Fixes error on importing from inventaire
2022-11-25 10:54:10 -08:00
Mouse Reeve 304757091e Fixes checking csv length to consider headers 2022-11-25 10:53:42 -08:00
Mouse Reeve 41d5102c72
Merge pull request #2448 from bookwyrm-social/search-review-counts
Show review counts in search results
2022-11-25 10:49:10 -08:00
Mouse Reeve 0a12be8279 Appease pylint 2022-11-25 10:41:04 -08:00
Mouse Reeve e94e72a594 Python formatting 2022-11-25 10:40:06 -08:00
Mouse Reeve 61d1e67349
Merge pull request #2418 from jaschaurbach/Fix-wrong-URL-behind-proxy
set HTTP_X_FORWARDED_PROTO in .env
2022-11-25 10:40:00 -08:00
Mouse Reeve d3cad15ee1
Merge pull request #2445 from bookwyrm-social/list-null-notification
Handles state in notifications where a list item was deleted
2022-11-25 10:39:02 -08:00
Mouse Reeve c3acbb9bd0
Merge pull request #2446 from bookwyrm-social/settings-federation-table
Make the federated servers table display correctly on mobile
2022-11-25 10:38:53 -08:00
Mouse Reeve 015af2c1e7 Don't start imports with empty csvs
Fixes #2353
2022-11-25 10:35:16 -08:00
Mouse Reeve becc90d485 Show review counts in search results
Fixes #2317
2022-11-25 10:06:51 -08:00
Mouse Reeve 44d308abad Fixes error on importing from inventaire 2022-11-25 09:35:26 -08:00
Mouse Reeve e72cb43bb2 Make the federated servers table display correctly on mobile 2022-11-25 09:09:57 -08:00
Mouse Reeve d8860f2a4d
Merge pull request #2443 from bookwyrm-social/edit-links
Fixes editing links
2022-11-25 08:56:19 -08:00
Mouse Reeve 748acc9a79
Merge pull request #2444 from bookwyrm-social/update-locales
Updates locales
2022-11-25 08:56:07 -08:00
Mouse Reeve 2d56ccfd50 Handles state in notifications where a list item was deleted 2022-11-25 08:55:33 -08:00
Mouse Reeve be33fe6040 Updates locales 2022-11-25 08:32:10 -08:00
Mouse Reeve 81ab08aaa3 Fixes editing links 2022-11-25 08:28:45 -08:00
Mouse Reeve 9dd0e22a47
Merge pull request #2426 from bookwyrm-social/password-reset-email
Don't use task for password reset emails
2022-11-23 22:10:47 -08:00
Mouse Reeve dd83e32f32 Fixes unit test 2022-11-23 22:00:34 -08:00
Mouse Reeve 2e882a447f
Merge pull request #2437 from cincodenada/fix/list-suggestions
Fix: Slice queryset in list suggestions before we resolve it
2022-11-23 21:47:05 -08:00
Mouse Reeve 4484d0baed
Merge pull request #2390 from jaschaurbach/fix-docker-compose
Quote ports in docker-compose
2022-11-23 17:44:43 -08:00
Joel Bradshaw 55bab0b70d Slice queryset before we resolve it
This was accidentally querying ALL books in the database to generate
suggestions if we didn't have enough, which broke some stuff
2022-11-23 19:26:09 +00:00
Mouse Reeve cc3cd5c98c Don't use task for password reset emails 2022-11-20 19:39:08 -08:00
Jascha Urbach 484484fd4b
Apologies for my lack of coding skills 2022-11-20 17:57:03 +01:00
Jascha Urbach 3c1b38ed2c
one should import what one declares...
... andn not what one thinks was declared^^
2022-11-20 17:47:26 +01:00
Jascha Urbach 31ea868ddc
Update to actual READ the file... 2022-11-19 20:40:36 +01:00
Mouse Reeve fdc53d6c60
Merge pull request #2394 from jaschaurbach/show-2fa-code
show otp_secret when setting up 2fa
2022-11-19 10:25:15 -08:00
Mouse Reeve 2adcbdea2f
Merge pull request #2419 from bookwyrm-social/robots
Expand robots.txt
2022-11-19 10:24:55 -08:00
Mouse Reeve 1e5a6ec744
Merge branch 'main' into show-2fa-code 2022-11-19 10:09:27 -08:00
Mouse Reeve 7d51a69c71 Expand robots.txt 2022-11-19 10:03:40 -08:00
Hugh Rundle 6baa58260a
2fa qrcode fixes (#2407)
* 2fa qrcode fixes

- add light background to qr code when using dark theme
- show OTP secret code under qr code for manual entry on apps if required

fixes #2386
fixes #2389

* fix code formatting

* revert changes re visible code

This conflicts with an existing PR.

* i code pretty
2022-11-19 09:51:18 -08:00
Mouse Reeve e11811d461
Fancier UI around OTP codes 2022-11-19 09:48:44 -08:00
Mouse Reeve bbd2dc75f8
Merge pull request #2414 from henryistaken/patch-1
Fix Quick Typo
2022-11-19 09:32:27 -08:00
Jascha Urbach 4e2324f06b
Add HTTP_X_FORWARDED_PROTO:false to Test
that it does not fail any more :)
2022-11-19 18:02:34 +01:00
Jascha Urbach 238a1b0e88
set HTTP_X_FORWARDED_PROTO in .env
This fixes #2397.

The description in .env is whith a warning and a link to the official documentation about what this setting is doing if set to true.
2022-11-19 17:54:44 +01:00
Henry c7ac936a9a
Fix Quick Typo 2022-11-18 23:24:18 -08:00
Mouse Reeve c5fb710f29 Fixes code of conduct link 2022-11-18 08:23:53 -08:00
Mouse Reeve 9aab14ee96
Merge pull request #2406 from bookwyrm-social/disable-imports
Allow admins to disable starting imports
2022-11-17 19:51:17 -08:00
Mouse Reeve 9c5fe7610b Fixes reference to site model 2022-11-17 15:41:30 -08:00
Mouse Reeve d36521c460
Merge pull request #2405 from bookwyrm-social/admins-list
Fixes collecting list of admins
2022-11-17 15:22:10 -08:00
Mouse Reeve 28567e2d8e Disable imports in the UI and view 2022-11-17 15:19:42 -08:00
Mouse Reeve 46b663b139 Rename new user to avoid duplication 2022-11-17 15:10:11 -08:00
Mouse Reeve bfca5706ea
Merge pull request #2404 from bookwyrm-social/embed-css
Uses correct css paths in embeds
2022-11-17 15:00:16 -08:00
Mouse Reeve 34f05c135b Adds unit tests for list of admins method 2022-11-17 14:59:46 -08:00
Mouse Reeve b1c6781036 Fixes collecting list of admins 2022-11-17 14:38:05 -08:00
Mouse Reeve 7c7c0e1a93 Admin UI to enable and disable importing 2022-11-17 14:23:39 -08:00
Mouse Reeve 2d3ec93086 Updates unit tests 2022-11-17 14:06:43 -08:00
Mouse Reeve 474da162ba Uses correct css paths in embeds 2022-11-17 13:34:54 -08:00
Mouse Reeve 7e10b0cd1f
Merge pull request #2400 from bookwyrm-social/local-rss
Only offer RSS feeds for local users
2022-11-17 12:53:19 -08:00
Mouse Reeve 4ce51be827
Merge pull request #2401 from bookwyrm-social/resolve-remote-errors
Change log level to info for connector exceptions
2022-11-17 12:49:32 -08:00
Mouse Reeve b37a4322de Change log level to info for connector exceptions
These errors in resolve_remote_id aren't really errors, they're
routine problems that we can expect from dealing with the outside world,
like a connection timeout, a server being down, a server being blocked,
et cetera. It's cluttering up the logs and causing unnecessary worry.
2022-11-17 12:35:19 -08:00
Mouse Reeve 77d96bf245 Only offer RSS feeds for local users 2022-11-17 12:03:59 -08:00
Mouse Reeve d40cc21460
Merge pull request #2399 from bookwyrm-social/cache-fix
Fixes user follow cache
2022-11-17 11:36:20 -08:00
Mouse Reeve 6dd671ae5a Fixes user follow cache 2022-11-17 11:23:48 -08:00
Mouse Reeve fe7163be33 Render markdown to html when using activitypub
This will produce better federated results outside of bookwyrm, and will
still display correctly within bookwyrm
2022-11-17 11:05:48 -08:00
Mouse Reeve 24f73f81f6 Update version number 2022-11-16 18:43:51 -08:00
Mouse Reeve 2dad14bdcf
Merge pull request #2395 from bookwyrm-social/settings-view-perms
Fixes permissions on settings invite request page
2022-11-16 18:33:20 -08:00
Mouse Reeve a546ab578b Fixes decorator on view method 2022-11-16 18:23:26 -08:00
Mouse Reeve fcdb7f106e Ticks version number 2022-11-16 18:19:23 -08:00
Mouse Reeve 5a7afe45a2 Fixes permissions on settings invite request page 2022-11-16 18:03:52 -08:00
Jascha Urbach 170aa7460a
Update 2fa.html
Or now, because obviously I can not write HTML^^
2022-11-16 20:35:28 +01:00
Jascha Urbach a98dbb97a5
fix error
fix my copy paste error -.-
2022-11-16 20:32:40 +01:00
Jascha Urbach c29256708a
show otp_secret when setting up 2fa
solves #2389
2022-11-16 20:30:06 +01:00
Mouse Reeve 39c5b0dc91
Merge pull request #2392 from jaschaurbach/Remove-dead-link-to-fediblock
Remove dead URL
2022-11-16 10:13:53 -08:00
Jascha Urbach be97fd2d39
Remove dead URL
https://fediblock.org delivers a 410 Gone as respone.
2022-11-16 18:24:19 +01:00
Mouse Reeve 55a603562c
Merge pull request #2387 from bookwyrm-social/admin-template
Adds unit test for failing view
2022-11-16 06:43:02 -08:00
Jascha Urbach cb187c880e
Quote ports in docker-compose
Per sepcification in compose-file v3 ports are in quotes.

https://docs.docker.com/compose/compose-file/compose-file-v3/
2022-11-16 12:38:49 +01:00
Mouse Reeve f95729a0c3 Adds unit test for failing view 2022-11-15 21:45:06 -08:00
Mouse Reeve 1a8580cdbc
Merge pull request #2385 from bookwyrm-social/search-improvements
Simplify title/author search logic
2022-11-15 20:21:45 -08:00
Mouse Reeve 47f1865c59 Remove trailing whitespace from queries 2022-11-15 20:09:00 -08:00
Mouse Reeve f0f65b8b73 Python formatting 2022-11-15 20:08:17 -08:00
Mouse Reeve fb60ffa512
Merge pull request #2384 from bookwyrm-social/search-improvements
Simplify identifier searches
2022-11-15 20:07:16 -08:00
Mouse Reeve 9185708224 Simplify how default edition is checked
This logic is still totally bonkers, but this change puts a hard limit
on how many iterations the loop can go through and makes the query that
selects which edition to display a little simpler.
2022-11-15 20:05:41 -08:00
Mouse Reeve eb61033626 Simplify identifier searches
This commit removes code that deduplicated search results for identifier
searches. If it was the case that multiple books have the same
identifier, in theory this would produce better search results, but in
practice this doesn't happen very much, is probably worth seeing when
it does, and worsens the performance of identifier search overall.
2022-11-15 19:42:40 -08:00
Mouse Reeve 807f8c02b2
Merge pull request #2382 from bookwyrm-social/invite-length
Longer invite answer field
2022-11-15 15:03:51 -08:00
Mouse Reeve c64914b41b
Merge pull request #2381 from jaschaurbach/deactivate-2fa-with-manage.py
Remove TFA from user
2022-11-15 15:03:16 -08:00
Mouse Reeve e47d84267f
Merge pull request #2376 from bookwyrm-social/env-defaults
Updates default state of .env file
2022-11-15 14:59:38 -08:00
Jascha Urbach 4c05e3b660
Merge branch 'main' into deactivate-2fa-with-manage.py 2022-11-15 23:52:52 +01:00
Mouse Reeve c47a425cbe Longer invite answer field
It was an oversight that it was only set to 50 characters I expect!
2022-11-15 14:52:07 -08:00
Mouse Reeve ec4d9f6b63
Merge pull request #2380 from bookwyrm-social/status-activity-tasks
Generate fewer add_status_tasks
2022-11-15 14:41:10 -08:00
Jascha Urbach 8a99482a2f
correct linter errors
./bw-dev black

reformatted bookwyrm/management/commands/remove_2fa.py

All done!  🍰 
1 file reformatted, 544 files left unchanged.
2022-11-15 23:32:24 +01:00
Jascha Urbach cd57537854
Remove TFA from user
added bookwyrm/management/remove_2fa.py

changed bw-dev
2022-11-15 23:20:21 +01:00
Mouse Reeve 317cf5fcf5 Generate fewer add_status_tasks
Previously, every time a status was saved, a task would start to add it
to people's timelines. This meant there were a ton of duplicate tasks
that were potentially heavy to run. Now, the Status model has a "ready"
field which indicates that it's worth updating the timelines. It
defaults to True, which prevents statuses from accidentally not being
added due to ready state.

The ready state is explicitly set to false in the view, which is the
source of most of the noise for that task.
2022-11-15 14:14:32 -08:00
Mouse Reeve 413bd33894 Updates default state of .env file 2022-11-15 12:31:47 -08:00
Mouse Reeve f0b73c18c1
Merge pull request #2367 from bookwyrm-social/footer-links
Include privacy policy and code of conduct in footer
2022-11-14 18:58:50 -08:00
Mouse Reeve bf3043f91f Fixes column widths 2022-11-14 18:48:30 -08:00
Mouse Reeve 85337c73e5
Merge branch 'main' into footer-links 2022-11-14 18:46:42 -08:00
Mouse Reeve 4178eb81e4
Merge pull request #2366 from bookwyrm-social/footer-snippet
Uses the same snippet for the footer across different templates
2022-11-14 18:46:15 -08:00
Mouse Reeve fe82599de9 Include privacy policy and code of conduct in footer 2022-11-14 18:37:27 -08:00
Mouse Reeve dbe74f6388 Uses the same snippet for the footer across different templates 2022-11-14 18:18:27 -08:00
Mouse Reeve 914479f1c9
Merge pull request #2365 from bookwyrm-social/url-typo
Small fixes - typo in a url and emails about reports
2022-11-14 18:13:09 -08:00
Mouse Reeve 5b358094ab Fixes report emails always claiming to be about links 2022-11-14 18:03:36 -08:00
Mouse Reeve e655f5c2f3 Fixes typo in url regex 2022-11-14 16:06:40 -08:00
Mouse Reeve 36f511ebb7
Merge pull request #2140 from cincodenada/ignore-does-not-exist
Ignore VariableDoesNotExist errors in debug logging
2022-11-14 12:26:06 -08:00
Mouse Reeve a91d9f67be
Merge pull request #2362 from bookwyrm-social/revoke-image-tasks
Adds management command to revoke preview image tasks
2022-11-14 12:20:05 -08:00
Mouse Reeve b812a5c73e Adds management command to revoke preview image tasks 2022-11-14 12:09:16 -08:00
Mouse Reeve e1f6110dc8
Merge branch 'main' into bw-dev-npm-fix 2022-11-14 09:11:16 -08:00
Ell Bradshaw c9adb7ff12 Linting fixes 2022-11-14 01:04:20 -08:00
Ell Bradshaw b3603bc3f5 Merge branch 'main' into ignore-does-not-exist 2022-11-14 00:31:34 -08:00
Mouse Reeve c29ce65c27
Merge pull request #2355 from Ryuno-Ki/task-queues
Use variable instead of string
2022-11-13 12:51:07 -08:00
André Jaenisch 530d7de309
Use variable instead of string
Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>
2022-11-13 16:59:05 +01:00
Mouse Reeve dc14670a2c
Merge pull request #2346 from bookwyrm-social/async-broadcast
Use aiohttp for broadcasting
2022-11-10 17:33:10 -08:00
Mouse Reeve ddcaf8e3b8 Use asyncio for broadcasting 2022-11-10 15:41:56 -08:00
Mouse Reeve cbd14a69ea
Merge pull request #2345 from bookwyrm-social/import-time-tweak
Another tweak to how import wait times are calculated
2022-11-10 14:20:21 -08:00
Mouse Reeve 49d0590599 Another tweak to how import wait times are calculated 2022-11-10 13:59:27 -08:00
Mouse Reeve 26e185718f
Merge pull request #2344 from bookwyrm-social/locales
Updates locales
2022-11-10 13:55:00 -08:00
Mouse Reeve a670b45a4b Updates locales 2022-11-10 13:43:40 -08:00
Mouse Reeve eae1866992
Allow users to temporarily deactivate their accounts (#2324) 2022-11-10 13:40:54 -08:00
Mouse Reeve 3ebd957d3d
Merge pull request #2341 from bookwyrm-social/import-time-estimate
Import time estimate fixes
2022-11-10 13:22:23 -08:00
Mouse Reeve bbdba9e793 Python formatting 2022-11-10 13:13:53 -08:00
Mouse Reeve 8f2de48b0a Comments out unrelated test block 2022-11-10 13:05:42 -08:00
Mouse Reeve 48d4149151 Fixes null state 2022-11-10 12:39:07 -08:00
Mouse Reeve f80e2465ed Adds tests for recent import average time 2022-11-10 12:29:36 -08:00
Mouse Reeve f0d3ceefa0 Cache import time
Also uses a type hint
2022-11-10 12:27:38 -08:00
Mouse Reeve 784dab3d41 Fixes to how import times are estimated
The wrong attr was being used to grab the number of seconds, and imports
that were stopped were being counted
2022-11-10 11:42:38 -08:00
Mouse Reeve 89a2109731
Merge pull request #2339 from bookwyrm-social/locales
Updates locales
2022-11-07 11:50:42 -08:00
Mouse Reeve cc95c4d7b5
Merge pull request #2338 from bookwyrm-social/sort-admin-imports
Make the import admin table sortable
2022-11-07 11:41:58 -08:00
Mouse Reeve 9e0867af91 Make the import admin table sortable 2022-11-07 11:32:45 -08:00
Mouse Reeve ab0655a997 Updates locales 2022-11-07 11:22:13 -08:00
Mouse Reeve 16c92a62c4
Merge pull request #2337 from bookwyrm-social/invite-table-scroll
Makes the invite request table side scroll for mobile
2022-11-07 10:55:39 -08:00
Mouse Reeve eb7777c0a1
Merge pull request #2336 from bookwyrm-social/cancel-imports
Fixes duplicate notification on import
2022-11-07 10:47:38 -08:00
Mouse Reeve 4b01103f84 Makes the invite request table side scroll for mobile
Fixes #2335
2022-11-07 10:44:49 -08:00
Mouse Reeve 1f022496dd Fixes duplicate notification on import 2022-11-07 10:36:31 -08:00
Mouse Reeve 4e1da6a759
Merge pull request #2333 from bookwyrm-social/cancel-imports
Let users and admins cancel imports
2022-11-07 10:35:37 -08:00
Mouse Reeve b64f0511a5 Another mock 2022-11-07 10:07:37 -08:00
Mouse Reeve 141d3aa813 Updates mocks in tests 2022-11-07 09:50:05 -08:00
Mouse Reeve 493fd68af4 Merge branch 'main' into cancel-imports 2022-11-07 09:06:13 -08:00
Mouse Reeve 6e748c5476 Typo fix 2022-11-05 18:16:59 -07:00
Mouse Reeve 817047bdeb Use stop functionality in import admin view 2022-11-05 15:44:00 -07:00
Mouse Reeve 76fb4c9280 Revoke tasks 2022-11-05 15:41:06 -07:00
Mouse Reeve 6792b3d7b8 adds button to stop job 2022-11-05 14:44:09 -07:00
Mouse Reeve 7a36de5ebe Start and stop jobs from the model 2022-11-05 14:35:27 -07:00
Mouse Reeve 0399f9eb01
Merge pull request #2332 from bookwyrm-social/import-time-estimate
Show average run times for imports
2022-11-05 13:48:07 -07:00
Mouse Reeve 97513a43d6 Set import job status when job starts and finishes 2022-11-05 13:47:06 -07:00
Mouse Reeve 59fe9e4d3b Show import status in table 2022-11-05 13:44:07 -07:00
Mouse Reeve 9cfcad20e0 Avoid divide by zero error 2022-11-05 13:33:57 -07:00
Mouse Reeve 24e5ea3295 Check if import is stopped and create import status field 2022-11-05 13:32:23 -07:00
Mouse Reeve 3c2f2c10bf Show recent imports in a table 2022-11-05 13:12:23 -07:00
Mouse Reeve 4806a6273e Show average run times for imports
This should give users a sense of when to start wondering if their
import isn't running after all.
2022-11-05 12:50:51 -07:00
Mouse Reeve 01d5274ebb
Merge pull request #2331 from bookwyrm-social/locales
Updates locales
2022-11-03 15:20:00 -07:00
Mouse Reeve b439114932 Updates locales 2022-11-03 11:50:12 -07:00
Mouse Reeve ccf091e42d
Merge pull request #2330 from bookwyrm-social/import-admin-table
Adds more fields to import admin table and ticks version
2022-11-03 11:49:57 -07:00
Mouse Reeve 40e9428b49 Adds more fields to import admin table and ticks version 2022-11-03 11:30:43 -07:00
Mouse Reeve 3f2f718878
Merge pull request #2329 from bookwyrm-social/import-admin-fixes
Import admin fixes
2022-11-03 11:06:29 -07:00
Mouse Reeve 14e61fa32d Adds extremely basic tests file 2022-11-03 10:55:21 -07:00
Mouse Reeve 0ba4dbbc6f Fixes pagination and user links on import admin 2022-11-03 10:54:59 -07:00
Mouse Reeve 91b935bc0a
Merge pull request #2327 from bookwyrm-social/imports-admin
Imports admin
2022-11-01 20:53:58 -07:00
Mouse Reeve 5af195de58 Python formatting 2022-11-01 20:43:27 -07:00
Mouse Reeve a8424f61f2 Mark imports as complete
This will let the user debug the import, and should only be used when
the import is in a bad state (marked as incomplete but with no pending
tasks)
2022-11-01 19:26:23 -07:00
Mouse Reeve 6eab1fdd6d Adds import admin view 2022-11-01 19:05:51 -07:00
Mouse Reeve 61c2d2a36a Use elided page range on user admin view 2022-11-01 18:45:21 -07:00
Mouse Reeve 641fc325b4
Merge pull request #2326 from bookwyrm-social/synchronous-confirmation-emails
Send confirmation emails directly, rather than with celery
2022-11-01 18:43:53 -07:00
Mouse Reeve 881d5682e3 Updates test mock 2022-11-01 18:20:56 -07:00
Mouse Reeve c16155aa41
Merge pull request #2325 from bookwyrm-social/author-page-editions
Only show editions with the author on the author page
2022-11-01 18:18:58 -07:00
Mouse Reeve 40ead41176 Fixes rate limiter 2022-11-01 18:17:37 -07:00
Mouse Reeve 1c949a5d71 Send confirmation emails directly, rather than with celery
Whenver bookwyrm has an influx of new users, celery gets delayed and
the emails don't get sent out promptly, which causes people to first
resend the email multiple times, and then to email me, both of which
just create more work and confusion for everyone involved.
2022-11-01 18:08:45 -07:00
Mouse Reeve 553f170f89 Only show editions with the author on the author page 2022-11-01 18:04:27 -07:00
Mouse Reeve 43202f5bb7
Merge pull request #2322 from obrenckle/menus_overlap
Close dropdown menu when opening one of its modal
2022-11-01 17:15:00 -07:00
Olivier Brencklé cfaec434c0 🚸 Close dropdown when opening modal item 2022-10-28 13:15:53 +02:00
Olivier Brencklé 474b78dad2 💄 Set dropdown menu below modals on mobile 2022-10-24 19:34:25 +02:00
Mouse Reeve 54a056f582
Merge pull request #2321 from bookwyrm-social/dependabot/pip/django-3.2.16
Bump django from 3.2.15 to 3.2.16
2022-10-21 14:14:21 -07:00
Mouse Reeve 2a0a67de5f Adds 2fa locales 2022-10-21 14:13:14 -07:00
Mouse Reeve 62a34c42a3
Merge branch 'main' into dependabot/pip/django-3.2.16 2022-10-20 20:57:05 -07:00
Mouse Reeve eb07deadf2
Merge pull request #2320 from bookwyrm-social/announcement-size
Remove extra whitespace in announcements
2022-10-20 20:56:52 -07:00
Mouse Reeve 6fb21b9e4b Disable wayward stylelint error 2022-10-20 20:44:27 -07:00
dependabot[bot] 09446def54
Bump django from 3.2.15 to 3.2.16
Bumps [django](https://github.com/django/django) from 3.2.15 to 3.2.16.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.15...3.2.16)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-21 03:40:27 +00:00
Mouse Reeve c375e842ad
Merge pull request #2294 from hughrun/otp
Enable optional 2FA
2022-10-20 20:40:00 -07:00
Mouse Reeve b81a5faff7 Remove extra whitespace in announcements 2022-10-20 07:45:53 -07:00
Hugh Rundle 3d95916b55 handle 2fa user exception properly 2022-10-15 07:47:20 +11:00
Hugh Rundle 32e4f7718e pylint is being pedantic 2022-10-15 07:47:20 +11:00
Hugh Rundle cf1fae6af8 return Bad Request if 2fa user does not exist 2022-10-15 07:47:20 +11:00
Hugh Rundle 905aa66f38 add test_post_login_with_2fa 2022-10-15 07:47:20 +11:00
Hugh Rundle a1c3f15d80 remove unused import 2022-10-15 07:47:20 +11:00
Hugh Rundle f55adbadf4 fix 2fa tests 2022-10-15 07:47:20 +11:00
Hugh Rundle cffbf82ddb DRY footer for 2FA pages 2022-10-15 07:47:20 +11:00
Hugh Rundle f3768c3d92 code formatting fix 2022-10-15 07:47:20 +11:00
Hugh Rundle 79b04c2240 various 2fa improvements
- cleaner code
- use TWO_FACTOR_LOGIN_MAX_SECONDS instead of hardcoded number
- render qrcode properly
- use nginx to rate limit login attempts
- do not throw error if session user is undefined
2022-10-15 07:47:20 +11:00
Hugh Rundle aefc7a23bc fix 2fa templates
- translate all strings
- do not embed svg element inside svg element
- fix sizing of input for confirming 2fa setup
2022-10-15 07:47:20 +11:00
Hugh Rundle e1513bf98d amend nginx rate limiting urls 2022-10-15 07:47:20 +11:00
Hugh Rundle da613c9b26 ugh forgot to run black 2022-10-15 07:47:20 +11:00
Hugh Rundle fda150fa0d resolve migration conflict 2022-10-15 07:47:20 +11:00
Hugh Rundle 119b4bf2ff clean up tests
- remove unnecessary crap
- add missing tests
2022-10-15 07:47:20 +11:00
Hugh Rundle 9d36722783 code formatting 2022-10-15 07:47:20 +11:00
Hugh Rundle b63d4bec60 add tests for 2fa 2022-10-15 07:47:20 +11:00
Hugh Rundle 28329c1781 use string for datetime in session
It seemed to work when testing manually, but both pytest and the django documentation indicate that you can't pass datetimes around as session values.
2022-10-15 07:47:20 +11:00
Hugh Rundle e1b1bb20dc make password field less goofy in 2fa screen 2022-10-15 07:47:20 +11:00
Hugh Rundle 9b74c26742 backup codes
- add hotp_secret to user model
- view to create backup codes in user prefs
- check backup code if otp doesn't work
- increment hotp count if used
- show correct errors if code wrong
2022-10-15 07:47:20 +11:00
Hugh Rundle 9616abb6bd clean up 2fa prompt page 2022-10-15 07:47:20 +11:00
Hugh Rundle 5b244f06d6 fix error messages when setting up 2FA 2022-10-15 07:47:20 +11:00
Hugh Rundle 6db4fb39ed improve security and fix error msg
- Instead of passing the user as a hidden form element, we use a session variable.
- Introduces a 60 second limit on completing the login, and an exponentially increasing delay to attempt to login with 2FA if the code is entered incorrectly.
- use proper Django form error when incorrect otp value entered
2022-10-15 07:47:20 +11:00
Hugh Rundle 9d12b7caff make pylint stop grumbling 2022-10-15 07:47:20 +11:00
Hugh Rundle 1d13f0ab4f lint 2022-10-15 07:47:20 +11:00
Hugh Rundle 8837495ffd redirect login to 2fa check if active 2022-10-15 07:47:20 +11:00
Hugh Rundle 2ec343c5db new views for capturing user for 2fa check 2022-10-15 07:47:20 +11:00
Hugh Rundle f26ac1ccde 2fa page templates 2022-10-15 07:47:20 +11:00
Hugh Rundle 0e1751eb57 prep for 2fa login check
- new 2fa checker page to be inserted between initial login and completion of login
- new views and forms for above
2022-10-15 07:47:20 +11:00
Hugh Rundle 514762c233 fix typo in new user fields
oopsie
2022-10-15 07:47:20 +11:00
Hugh Rundle aca5c19f70 2fa templates
- new page templates for 2FA
- add 2FA to menu in user preferences
2022-10-15 07:47:20 +11:00
Hugh Rundle 54daade9f9 prepare for 2FA
- add and migrate User fields for 2FA
- add views for 2FA
- add new forms for 2FA
- update package list in requirements.txt
- add URLs for 2FA views
2022-10-15 07:47:20 +11:00
Mouse Reeve fed6bcd375
Merge pull request #2314 from chambersh1129/2194-normalize-stored-ISNI
Closes #2194 Normalize stored ISNI
2022-10-14 12:20:07 -07:00
Mouse Reeve b02ad2ec68
Merge pull request #2316 from redshiftss/bugfix/reading-status-future
Make it so that finishing a book cannot happen in the future
2022-10-14 12:17:42 -07:00
Mouse Reeve b06c35b7dd
Update forms.py 2022-10-14 12:06:54 -07:00
Laura Pircalaboiu f97b6f3da2 fix pylint complaint 2022-10-12 11:25:03 +02:00
x3005504 4423827c27 Merge branch 'bugfix/reading-status-future' of github.com:redshiftss/bookwyrm into bugfix/reading-status-future 2022-10-11 14:42:09 +02:00
Laura Pircalaboiu 4ab5e4b5d9 re-format code 2022-10-11 14:40:52 +02:00
Laura Pircalaboiu b895fbd8f2 fix bug, can no longer finish a book in the future 2022-10-11 14:40:45 +02:00
Laura Pircalaboiu aeeb2c3442 WIP: fix reading status ending in the future 2022-10-11 14:40:32 +02:00
x3005504 ec25ffe6ba re-format code 2022-10-11 14:07:17 +02:00
x3005504 9a9a7821b7 fix bug, can no longer finish a book in the future 2022-10-11 14:05:20 +02:00
x3005504 68b9791d8c WIP: fix reading status ending in the future 2022-10-11 13:41:07 +02:00
Hunter Chambers 32f68c3f62 remove trailing whitespace causing pylint/black errors 2022-10-10 14:13:57 -04:00
Hunter Chambers 02c7397eaf Closes #2194 Normalize stored ISNI 2022-10-09 19:36:24 -04:00
Mouse Reeve 003c5c9c82
Merge pull request #2311 from bookwyrm-social/small-tests
Just adds a couple tests
2022-10-04 12:18:10 -07:00
Mouse Reeve 74b89b2d4a That test didn't work 2022-10-04 12:09:05 -07:00
Mouse Reeve 5b5e15d48b Just adds a couple tests 2022-10-04 11:40:01 -07:00
Mouse Reeve f32eaad8ef
Merge pull request #2310 from bookwyrm-social/typo-fix
Typo fix
2022-10-04 11:22:35 -07:00
Mouse Reeve 520b1d2207 Updates locales 2022-10-04 11:04:36 -07:00
Mouse Reeve 78d36ebc39 Fixes typo in tour 2022-09-24 19:41:37 -07:00
Mouse Reeve 44ce12405b
Merge pull request #2301 from bookwyrm-social/annual-review-tests
Adds a couple tests to annual review views
2022-09-19 20:33:37 -07:00
Mouse Reeve 3a73ced5fa Adds a couple tests to annual review views
Also I tweaked the save functions so they don't broadcast
2022-09-19 14:38:30 -07:00
Mouse Reeve fdc477afdf
Merge pull request #2258 from bookwyrm-social/form-perms
Check permissions automatically on form save
2022-09-19 13:32:41 -07:00
Mouse Reeve 7d61cb55bc Ignore pylint complaints about argument counts to form saves 2022-09-19 13:23:18 -07:00
Mouse Reeve 35aebacf70 Fixes theme form and adds view tests 2022-09-19 13:13:21 -07:00
Mouse Reeve bf092ec44e Small fixes 2022-09-19 12:10:27 -07:00
Mouse Reeve d023f71058
Merge pull request #2300 from bookwyrm-social/notification
Fixes creating notifications for automod reports
2022-09-19 12:00:02 -07:00
Mouse Reeve 4c099afc63 Python formatting 2022-09-19 11:23:40 -07:00
Mouse Reeve 37dacaff6f Fixes creating notifications for auto-moderation reports 2022-09-19 11:11:08 -07:00
Mouse Reeve 6947f3b787 Uses class method to get list of instance admins
Re-writing this query over and over is a bad approach
2022-09-19 10:43:52 -07:00
Mouse Reeve 9d8d85ebc1 Invite perms checks 2022-09-19 10:26:40 -07:00
Mouse Reeve 1e988cae6c More edit book lines 2022-09-19 10:26:29 -07:00
Mouse Reeve be480e40f0 Updates links form saves 2022-09-19 10:18:30 -07:00
Mouse Reeve 3fd573c0da Check perms on site model form 2022-09-19 10:16:38 -07:00
Mouse Reeve b0d8697006 Adds missing save in edit book view 2022-09-19 10:16:29 -07:00
Mouse Reeve 330be16516 Adds permissions checking for admin models 2022-09-19 10:12:47 -07:00
Mouse Reeve e51980bc12 Use BookWyrmModel as parent for admin models
This will make them more internally consistent and give them built-in
permissions checking
2022-09-19 09:35:38 -07:00
Mouse Reeve b0236b95bd Merge branch 'main' into form-perms 2022-09-19 09:32:48 -07:00
Mouse Reeve 3f5eb6c682 Adds raise_not_editable to User model
This model doens't inherit from BookwyrmModel for various reasons, but
it still needs to editability check.
2022-09-19 09:26:01 -07:00
Mouse Reeve aa67f23b03 Override raise_not_editable for report model
This model uses "reporter" as the field that represents the onwer of the
object, and "user" and the subject. In retrospect, maybe not the ideal
way to do it.
2022-09-19 09:20:44 -07:00
Mouse Reeve ac7be43e82
Merge pull request #2299 from bookwyrm-social/locales
Adds new admin view to locales
2022-09-19 08:27:12 -07:00
Mouse Reeve 44f27ec132 Adds new admin view to locales 2022-09-19 08:05:11 -07:00
Mouse Reeve d5c095ce6e
Merge pull request #2298 from bookwyrm-social/import-review-null-state
Adds celery status view
2022-09-15 11:20:16 -07:00
Mouse Reeve 81d5195d20 Adds test 2022-09-15 11:12:05 -07:00
Mouse Reeve fcd96c332d Null state 2022-09-15 11:09:07 -07:00
Mouse Reeve d76eae358f Show queues and runtime instead of start time 2022-09-15 10:53:08 -07:00
Mouse Reeve 3739bdbf81 Better comments 2022-09-15 09:49:58 -07:00
Mouse Reeve 0f55b76a93 Adds celery status view 2022-09-14 18:58:51 -07:00
Mouse Reeve b62c78aa3f
Merge pull request #2297 from bookwyrm-social/import-review-null-state
Null state for review view during imports
2022-09-14 18:20:05 -07:00
Mouse Reeve fcf796abe1 Null state for review view during imports
Without this, it will show an empty progress bar and no info about why
the table is empty.
2022-09-14 18:08:16 -07:00
Mouse Reeve c6f4098334
Merge pull request #2295 from bookwyrm-social/dependabot/pip/flower-1.2.0
Bump flower from 1.0.0 to 1.2.0
2022-09-13 18:10:07 -07:00
dependabot[bot] f9c608e728
Bump flower from 1.0.0 to 1.2.0
Bumps [flower](https://github.com/mher/flower) from 1.0.0 to 1.2.0.
- [Release notes](https://github.com/mher/flower/releases)
- [Commits](https://github.com/mher/flower/compare/v1.0.0...v1.2.0)

---
updated-dependencies:
- dependency-name: flower
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-13 23:03:54 +00:00
Mouse Reeve 6e00d49f78
Merge pull request #2293 from hughrun/starfix
Fix star rating default and minimum
2022-09-09 17:51:26 -07:00
Hugh Rundle aa18179dbc add migration 2022-09-10 10:27:17 +10:00
Hugh Rundle 0ad3dc6245 allow 0.5 star ratings 2022-09-10 07:24:11 +10:00
Hugh Rundle 230d30abb8 sidebar review stars should default to zero
PR #2283 surfaced an existing formerly-hidden issue with star rating defaults in the sidebar of book pages.
This commit ensures the default rating is zero, not half a star.

Fixes #2291
2022-09-10 07:03:12 +10:00
Mouse Reeve 543d13af6e Removes explicit calls to raise_not_editable from views
These raises are handled implicitly in the form, so they don't have to
be called outright.
2022-09-08 11:03:06 -07:00
Mouse Reeve 351292fcda Catches places where form.save() needs the request
Thank you, tests.
2022-09-08 11:02:17 -07:00
Mouse Reeve c71d133d2c
Merge pull request #2288 from mooseyboots/del-notifs-button
conditional display of notifs button
2022-09-08 10:16:07 -07:00
Mouse Reeve 834c7e9cd5
Merge pull request #2282 from hughrun/normalise-isbn
Normalise ISBNs for searching
2022-09-08 10:14:30 -07:00
marty hiatt b4cc9f5753 conditional display of notifs button 2022-09-01 11:54:49 +02:00
Hugh Rundle 1ee2ff4811 normalise isbn on local book search
- uppercase ISBN before checking it's a number to account for trailing 'x'
- check maybe_isbn for search_identifiers search. Without this we are only searching external connectors, not locally!
2022-08-30 20:00:09 +10:00
Hugh Rundle 68d91086ed add wonky ISBN test 2022-08-30 19:57:25 +10:00
Mouse Reeve 7ff8d85696
Merge pull request #2286 from bookwyrm-social/locales
Updates locales
2022-08-29 15:19:26 -07:00
Mouse Reeve 1f93dc9c62
Merge pull request #2260 from bookwyrm-social/mentions
Refactors how mentions are collected
2022-08-29 15:17:40 -07:00
Mouse Reeve d2941d4396
Merge pull request #2287 from bookwyrm-social/search-remote
Fixes logic that displays search remote or manually add link
2022-08-29 14:53:48 -07:00
Mouse Reeve e782b3f360 Fixes logic that displays search remote or manually add link 2022-08-29 14:03:47 -07:00
Mouse Reeve 35cf907f8b
Merge pull request #2285 from bookwyrm-social/isbn-url
Allow x in isbn path
2022-08-29 13:54:36 -07:00
Mouse Reeve 49c5feee99 Updates locales 2022-08-29 13:45:48 -07:00
Mouse Reeve 98562dc92f Allow x in isbn path 2022-08-29 13:41:49 -07:00
Mouse Reeve 775ee6f590
Merge pull request #2283 from hughrun/halfstars
fix visibility of stars when editing a review
2022-08-29 13:39:47 -07:00
Mouse Reeve e1ab81b86b
Merge pull request #2284 from bookwyrm-social/remote-follow-css
Uses theme in remote follow template
2022-08-29 09:38:39 -07:00
Mouse Reeve f0effb9d3e Uses theme in remote follow template 2022-08-29 07:10:36 -07:00
Hugh Rundle 252fe7fd6a fix visibility of stars when editing a review
Previously the star rating appeared to be five stars when editing a review, regardless of what value was actually stored.
Now it will show the actual rating, including half stars.

Fixes #2213
2022-08-29 14:02:04 +10:00
Hugh Rundle 18d3d2f85d linting 2022-08-28 17:30:46 +10:00
Hugh Rundle f219851f3a strip leading and following spaces from ISBN 2022-08-28 17:28:00 +10:00
Hugh Rundle da5fd32196 normalise isbn searching
ISBNs are always numeric except for when the check digit in ISBN-10s is a ten, indicated with a capital X.
These changes ensure that ISBNs are always upper-case so that a lower-case 'x' is not used when searching.

Additionally some ancient ISBNs have been printed without a leading zero (i.e. they only have 9 characters on the physical book). This change prepends a zero if something looks like an ISBN but only has 9 chars.
2022-08-28 11:05:40 +10:00
Mouse Reeve c902301d82
Merge pull request #2281 from hughrun/resetdb
fix resetdb
2022-08-27 09:14:21 -07:00
Hugh Rundle bc297d663d fix resetdb
Instead of just whining I thought maybe I should fix the problem.

This replaces a manual reset of the database with deletion of the bookwyrm volumes using docker.

fixes #2276
2022-08-27 19:53:57 +10:00
Mouse Reeve 58c3a4c2bc
Merge pull request #2277 from hughrun/permissions
hide replies to posts user cannot see
2022-08-23 19:48:36 -07:00
Hugh Rundle cc97c52d12 make get_audience logic clearer
Retains 'direct' messages at the top of the logic tree to make it easier to understand.
In practice because direct messages are excluded from feeds anyway, this doesn't seem to make much difference, but it's easier to read.
2022-08-21 09:33:43 +10:00
Hugh Rundle 8d593e4498 hide replies to posts user cannot see
This is in response to #1870

Users should not see links to posts they are not allowed to see, in their feed. The main question is how to stop that happening.
This commit hides all replies to posts if the original post was "followers only" and the user is not a follower of the original poster. The privacy of the reply is not considered relevant (except "direct").

I believe this is the cleanest way to deal with the problem, as it avoids orphaned replies and confusing 404s, and a reply without access to the context of the original post is not particularly useful to anyone. This also feels like it respects the wishes of the original poster more accurately, as it does not draw attention from non-followers to the original followers-only post.

A less draconian approach might be to remove the link to the original status in the feed interface, however that simply leads to confusion of another kind since it will make the interface inconsistent.

This commit does not change any ActivityPub behaviour - it only affects the Bookwyrm user feeds. This means orphaned posts may be sent to external apps like Mastodon.
2022-08-14 14:17:10 +10:00
Mouse Reeve be1141dddc
Merge pull request #2275 from hughrun/spaceless
strip spaces from user search
2022-08-13 21:15:30 -07:00
Mouse Reeve 987dbe15b3
Merge pull request #2271 from bookwyrm-social/dependabot/pip/django-3.2.15
Bump django from 3.2.14 to 3.2.15
2022-08-13 07:26:44 -07:00
Hugh Rundle 22495e40bd strip spaces from user search
Strips leading and trailing spaces from user search to prevent errors when doing webfinger lookup.
Prior to this, webfinger user queries included everything after the second '@' as part of the hostname. This resulted in failed webfinger requests when there was one or more trailing spaces.
Fixes #2205
2022-08-13 15:40:53 +10:00
dependabot[bot] c591371b4e
Bump django from 3.2.14 to 3.2.15
Bumps [django](https://github.com/django/django) from 3.2.14 to 3.2.15.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.14...3.2.15)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-11 16:08:55 +00:00
Mouse Reeve d58282bc37
Merge pull request #2263 from bookwyrm-social/safer-book-description
Safer display of book descriptions
2022-08-09 10:21:11 -07:00
Mouse Reeve 0cf9e1033b Safer display of book descriptions 2022-08-07 13:26:05 -07:00
Mouse Reeve cbc23dba3b
Merge pull request #2262 from bookwyrm-social/compilescss-command
Removes compilescss command
2022-08-07 11:41:57 -07:00
Mouse Reeve a5c7ca1cfd Removes compilescss command
This does not work and doesn't reflect how the stylesheets are compiled
any longer.
2022-08-07 11:27:52 -07:00
Mouse Reeve f566b43e5f
Merge pull request #2261 from bookwyrm-social/duplicate-version-warning
Removes duplicate version warning
2022-08-05 19:13:19 -07:00
Mouse Reeve 1581491471 Removes duplicate version warning 2022-08-05 17:03:56 -07:00
Mouse Reeve c8fc907705 Update version 2022-08-05 16:54:55 -07:00
Mouse Reeve 5c3bb2da13 Refactors how mentions are collected
This should be quicker, because it queries the users in one go instead
of jumping straight to iterating over them, and it checks if a user
blocks the poster before allowing them to be tagged.
2022-08-05 14:06:39 -07:00
Mouse Reeve 9d7ece47ef
Merge pull request #2254 from bookwyrm-social/fixes-search-pagination
Fixes search pagination
2022-08-05 12:32:47 -07:00
Mouse Reeve 9fad5b5623 Fixes isbn view 2022-08-05 11:44:10 -07:00
Mouse Reeve bdf563748c
Merge pull request #2255 from joachimesque/front/mobile-header
Add notifications count on mobile header
2022-08-05 11:28:42 -07:00
Mouse Reeve 1518dbba86
Merge pull request #2259 from bookwyrm-social/links
Improves rel attrs on links that open on new tabs
2022-08-05 11:28:04 -07:00
Mouse Reeve 7c7df99cef Fixes template syntax error 2022-08-05 11:14:14 -07:00
Mouse Reeve 20572688ba Removes test exception 2022-08-05 11:04:32 -07:00
Mouse Reeve 1ba69acc49 Adds unit tests that checks if rel field is set on links 2022-08-05 11:01:02 -07:00
Mouse Reeve 4dd7f88e0a Updates all links that open in new tabs 2022-08-05 10:20:43 -07:00
Mouse Reeve 9407695328 Updates footer links
Adds a missing rel="nofollow noopener noreferrer" attribute for the
Patreon link, and makes the github link open in a new tab (and updates
the url, which was out of date)
2022-08-05 10:06:12 -07:00
Mouse Reeve 8f79b362f8 Check permissions automatically on form save 2022-08-05 09:56:32 -07:00
Mouse Reeve e5611c7c03
Merge pull request #2257 from bookwyrm-social/group-perms
Fixes perms checks for groups
2022-08-05 09:24:22 -07:00
Mouse Reeve 9f22aeacea
Merge pull request #2256 from bookwyrm-social/locales
Locales update
2022-08-05 09:24:08 -07:00
Mouse Reeve 2894aa37a2 Fixes perms checks for groups 2022-08-05 09:12:48 -07:00
Mouse Reeve 44848c6621 Locales update 2022-08-05 09:04:26 -07:00
Mouse Reeve b4cfda0587 Updates tests 2022-08-05 08:56:24 -07:00
Joachim 610d8fdf5b Add notifications count on mobile header 2022-08-05 11:15:11 +02:00
Mouse Reeve ed71b791c9 Python formatting 2022-08-04 12:19:26 -07:00
Mouse Reeve 77d1d70207 Much shorter search timeout 2022-08-04 12:16:12 -07:00
Mouse Reeve 48df5076e7 Use elided page range and paginate user and list results 2022-08-04 12:11:39 -07:00
Mouse Reeve 06d1936ac9 Fixes pagination of local search results 2022-08-04 12:04:13 -07:00
Mouse Reeve 0ee7054640
Merge pull request #2253 from bookwyrm-social/otel-fix
Updates and fixes opentelemetry install
2022-08-04 11:25:39 -07:00
Mouse Reeve 073d8b1d67 Updates and fixes opentelemetry install 2022-08-04 11:05:18 -07:00
Mouse Reeve 3270d0a7d4
Merge pull request #2247 from bookwyrm-social/followers-following-views
Merges follower/following views
2022-08-02 11:59:06 -07:00
Mouse Reeve 72281bc459
Merge pull request #2251 from bookwyrm-social/polish-locale
Adds Polish locale
2022-08-02 11:58:42 -07:00
Mouse Reeve 0bc3c3b5f6 Adds locale migration 2022-08-02 11:09:58 -07:00
Mouse Reeve f9b772e234 Adds polish locale 2022-08-02 10:59:40 -07:00
Mouse Reeve 6d258d5445 Fixes test mocks 2022-07-30 10:07:13 -07:00
Mouse Reeve d7bf348c77
Merge pull request #2249 from bookwyrm-social/crsf-exempt
Removes improperly placed csrf_exempt decorator
2022-07-29 13:49:29 -07:00
Mouse Reeve 8e2a8ec6e0 Removes improperly places csrf_exempt decorator 2022-07-29 13:40:40 -07:00
Mouse Reeve 96f1521239
Merge pull request #2248 from bookwyrm-social/list-suggestions
Move list suggestions into helper function
2022-07-29 13:27:04 -07:00
Mouse Reeve 844023f104
Merge pull request #2246 from bookwyrm-social/goal-model
Moves annual goal to its own file
2022-07-29 13:22:12 -07:00
Mouse Reeve d301cecc9f Move list suggestions into helper function
The view was complicated, this makes it a little easier to read and
test.
2022-07-29 13:15:24 -07:00
Mouse Reeve 23188dfc5f
Merge branch 'main' into followers-following-views 2022-07-29 13:09:30 -07:00
Mouse Reeve d458001491 Merges follower/following views
They were almost identical!
2022-07-29 13:07:15 -07:00
Mouse Reeve 2298a478cf Moves annual goal to its own file
The user model file is just,, very long
2022-07-29 13:00:59 -07:00
Mouse Reeve 3c9c23803e
Merge pull request #2245 from bookwyrm-social/tour-strings
Fixes how guided tour strings are localized
2022-07-29 12:56:58 -07:00
Mouse Reeve f52965b8f4 Fixes a couple typos 2022-07-29 12:08:36 -07:00
Mouse Reeve 29db9c68a1 Fixes typo and spacing 2022-07-29 11:31:35 -07:00
Mouse Reeve 5a7ce7a58c Updates locales 2022-07-29 11:24:47 -07:00
Mouse Reeve 868ab62863 Fixes template string quote escapes
It seems totally reasonable that using an escape slash would make
apostrophes in words work, but the translation system works in
mysterious ways that do not include supporting that. I've used backticks
as a third quote type to escape everything in a way that both
javascript and gettext understand.

While I was there I split up some strings that have more complicated
html in them, since that can be fragile when passed through translation,
and confusing for translators.
2022-07-29 11:22:31 -07:00
Mouse Reeve 03a77c93ac
Merge pull request #2244 from bookwyrm-social/node-version
Updates node to version 18
2022-07-28 12:24:38 -07:00
Mouse Reeve 41b20c4dd5
Merge pull request #2243 from bookwyrm-social/list-crate-perms
Fixes list creation perms
2022-07-28 11:54:28 -07:00
Mouse Reeve 336c62bfc2
Merge branch 'main' into header-links 2022-07-28 11:45:59 -07:00
Mouse Reeve 2837d0148f Checks permissions when saving a list 2022-07-28 11:44:04 -07:00
Mouse Reeve 85dce81b6a Adds unit test or list create perms 2022-07-28 11:42:27 -07:00
Mouse Reeve cb4945c384
Merge pull request #2242 from bookwyrm-social/locales
Locales updates
2022-07-28 11:26:48 -07:00
Mouse Reeve 7bbe42fb30
Merge pull request #2230 from bookwyrm-social/nginx-rate-limit
Adds rate limiting to some views in nginx
2022-07-28 11:26:19 -07:00
Mouse Reeve 4013e1782e Locales updates
Grabs translations and adds guided tour strings
2022-07-28 11:13:14 -07:00
Mouse Reeve ed20587695
Merge pull request #2168 from hughrun/tour
Add guided tour / walkthrough
2022-07-28 11:08:49 -07:00
Hugh Rundle 2455aadbfd add scrollTo where needed
A couple of tour steps could benefit from a scrollTo for users on smallers screens.
2022-07-27 15:53:54 +10:00
Hugh Rundle a4714f097f fix anchors not working on homepage tour
Fixes bug on larger screens.

We need to use a function to set the anchor for tour steps when using menus and other elements that become visible or hidden responsively. Because the element is still in the DOM, we can't just rely on it disappearing completely, we have to assign a different (visible) element otherwise the step will simply disappear and the user cannot continue the tour. Previously this used a simple selector which didn't work due to the above.
2022-07-27 15:14:28 +10:00
Mouse Reeve 7eb2a82e5f
Merge branch 'main' into misc/add_signatures_to_requests_for_masto_compat 2022-07-26 15:46:18 -07:00
Mouse Reeve 5faaa6b750
Merge pull request #2196 from bookwyrm-social/bw-dev-alerts
Block some bw-dev commands from being run in prod
2022-07-26 15:34:40 -07:00
Mouse Reeve bdd75c434b Updates node to version 18 2022-07-26 15:07:40 -07:00
Mouse Reeve 6fc44cff8b
Merge pull request #2241 from bookwyrm-social/nonviable-follow-requests
Only show pending follow requests from active users
2022-07-24 12:38:55 -07:00
Mouse Reeve f3bc7d759f Only show pending follow requests from active users 2022-07-24 12:26:58 -07:00
Mouse Reeve 056f9c45a4
Merge pull request #2239 from bookwyrm-social/unauth-lists
Show lists to logged out viewers
2022-07-23 21:02:03 -07:00
Mouse Reeve 0217d36f7b Show lists to logged out viewers
The activitystreams for lists require a logged in user, so this just
uses a simple database query of all public lists when there is no logged
in user.
2022-07-23 20:42:40 -07:00
Mouse Reeve 5e887085b5
Merge pull request #2237 from bookwyrm-social/locales
Updates locales
2022-07-19 12:15:37 -07:00
Mouse Reeve 25557593f9 Updates locales 2022-07-19 12:03:49 -07:00
Mouse Reeve c2fb076add
Merge pull request #2235 from bookwyrm-social/fix-rating
Fix ratings
2022-07-17 20:08:10 -07:00
Mouse Reeve 639b727c92 Fixes perms check for ratings 2022-07-17 16:21:43 -07:00
Mouse Reeve 3f5bb41380 Unit test for creating rating status 2022-07-17 16:18:59 -07:00
Hugh Rundle 356c1c0b62 fix migration dependency order
Show_guided_tour needs to come after alter_user_preferred_language due to conficts. I think.
2022-07-17 16:34:42 +10:00
Hugh Rundle 17dc5e7eb1 Merge branch 'main' into tour
- we need to do this because of conflicting migrations
2022-07-17 16:30:45 +10:00
Hugh Rundle c48ddf419d cleanup 2022-07-17 16:19:55 +10:00
Hugh Rundle bec2943aad remove console logs 2022-07-17 16:17:08 +10:00
Hugh Rundle 387f2a70c9 update tour text
- new classname for posting guide
- various improvements to wording
- use function to find responsive menu elements
- add scrollTo transitions where needed
2022-07-17 16:13:12 +10:00
Hugh Rundle 43c598d92c remove DMs from guided tour 2022-07-17 11:11:34 +10:00
Mouse Reeve e1e6a2d380 Adds block to prod config 2022-07-15 13:19:42 -07:00
Mouse Reeve 143eaf362d Adds rate limiting to some views in nginx 2022-07-15 13:14:31 -07:00
Mouse Reeve 569e5400fe Updates locales 2022-07-15 12:29:31 -07:00
Mouse Reeve d3f35fb691 Adds Catalan 2022-07-15 12:28:31 -07:00
Mouse Reeve 41818717fb Updates locales 2022-07-15 12:21:34 -07:00
Mouse Reeve 4a82bef9a6 Ticks version number 2022-07-15 12:21:25 -07:00
Mouse Reeve 086ec10849
Merge pull request #2229 from bookwyrm-social/password-validation
Password validation
2022-07-15 11:53:27 -07:00
Mouse Reeve 65117fe3c6 Use manual password field to customize id 2022-07-15 11:41:39 -07:00
Mouse Reeve b1f5171502 Updates reset password tests 2022-07-15 11:39:29 -07:00
Mouse Reeve 3846b201bd Updates reset password flow to use validators 2022-07-15 11:39:18 -07:00
Mouse Reeve 1bb0a9d998 Updates tests 2022-07-15 11:18:47 -07:00
Mouse Reeve b62f8eff42 Updates method decorators 2022-07-15 10:59:35 -07:00
Mouse Reeve 659ee96002 Use password validation in change password flow
This also moves the form validation into a form instead of doing it in
the view.
2022-07-15 10:51:58 -07:00
Mouse Reeve 4a65ee326a Use password validation in register view 2022-07-15 09:59:57 -07:00
Mouse Reeve b66ce2e6a5
Merge pull request #2228 from bookwyrm-social/status-perms
Check permissions when creating a status
2022-07-15 09:56:01 -07:00
Mouse Reeve d74d59a57b Disable pylint complaint 2022-07-15 09:33:13 -07:00
Mouse Reeve 55b5393488
Merge pull request #2226 from bookwyrm-social/locales
Locale updates
2022-07-15 09:30:58 -07:00
Mouse Reeve 7fdfd0c9c7 Check permissions when creating a status 2022-07-15 09:26:52 -07:00
Mouse Reeve 753b988d1d Locale updates 2022-07-15 07:42:49 -07:00
Mouse Reeve a2540e8361
Merge pull request #2225 from bookwyrm-social/login-redirect
Remove redirecting to "next"
2022-07-14 13:06:17 -07:00
Mouse Reeve 5ecd75ee24 Remove redirecting to "next"
This wasn't even particularly working
2022-07-14 12:54:02 -07:00
Mouse Reeve aa579605e0
Merge pull request #2224 from bookwyrm-social/email-not-found-text
Remove error reporting on resend to invalid email address
2022-07-14 12:34:14 -07:00
Mouse Reeve 69728439c8 Remove error reporting on resend to invalid email address 2022-07-14 12:23:43 -07:00
Mouse Reeve 44b86baa5b
Merge pull request #2223 from bookwyrm-social/shelf-edit-perms
Shelf edit perms
2022-07-14 12:22:33 -07:00
Mouse Reeve 317a239d40 Update shelf test now that it has multiple users 2022-07-14 12:10:29 -07:00
Mouse Reeve 3f47cca5e6 Python formatting 2022-07-14 11:56:18 -07:00
Mouse Reeve c21864a1ac Merge branch 'main' into shelf-edit-perms 2022-07-14 11:50:27 -07:00
Mouse Reeve 95a72ae902
Merge pull request #2222 from bookwyrm-social/redirects
Removes insecure redirects
2022-07-14 11:46:47 -07:00
Mouse Reeve 73c4a01a6e Test for PermissionDenied error, not isNone 2022-07-14 11:45:59 -07:00
Mouse Reeve 4f1283ff52 Check editability before creating shelf 2022-07-14 11:42:59 -07:00
Mouse Reeve 05716c3578 Adds unit test for creating shelves for another user 2022-07-14 11:38:53 -07:00
Mouse Reeve 661865de87 Remmoves insecure redirects
This should really fundamentally work differently, but this is a quick
for for now to avoid an insecure redirect. There will be a negative
impact on user experience from this, and a followup change should look
into these views and improve their flow.
2022-07-14 11:22:17 -07:00
Mouse Reeve 2def5ff2bc
Merge pull request #2221 from bookwyrm-social/notification_order
Notification order
2022-07-14 11:21:49 -07:00
Mouse Reeve 235e877b3d Reverse order of notification users lists
Should show newest first
2022-07-14 11:00:05 -07:00
Mouse Reeve 3670ae46ec Reverse order of notification related users 2022-07-12 10:32:56 -07:00
Mouse Reeve e3dbe5a142
Update README.md 2022-07-11 15:55:17 -07:00
Mouse Reeve 4929dd3b26
Merge pull request #2219 from bookwyrm-social/readme-update
Update README.md
2022-07-11 14:58:08 -07:00
Mouse Reeve e895451a21
Update README.md 2022-07-11 14:47:56 -07:00
Mouse Reeve 222d0c6d4e
Merge pull request #2218 from bookwyrm-social/locales
Updates locales
2022-07-11 09:15:54 -07:00
Mouse Reeve 798476d670 Updates locales 2022-07-11 09:05:26 -07:00
Mouse Reeve 77bff3b263
Merge pull request #2217 from bookwyrm-social/connector-exceptions
Log failing to connect as info instead of exception
2022-07-11 09:04:01 -07:00
Mouse Reeve 5706028656 Log failing to connect as info instead of exception
These are normal, expected errors, and while we should probably
re-evaluate the connectors in some way, pending that, there's no need to
log these as unepected errors, which causes confusion and clutters my
error logging.
2022-07-11 08:47:18 -07:00
Mouse Reeve f1ae64543f
Merge pull request #2216 from bookwyrm-social/export-post
Use HTTP post for CSV export
2022-07-11 08:14:47 -07:00
Mouse Reeve 9104d1f8db Fixes reference to renamed view 2022-07-11 08:05:32 -07:00
Mouse Reeve 42e29e40b3 Use HTTP post for csv export
Also fixes a missing translation string
2022-07-11 07:51:51 -07:00
Mouse Reeve 137311e006
Merge pull request #2215 from bookwyrm-social/change-password
Improves change password flow
2022-07-10 20:34:24 -07:00
Mouse Reeve a0e01af2ca Updates tests 2022-07-10 20:22:54 -07:00
Mouse Reeve f44b3cc4b2 Improves change password flow
There are two changes: one is to require the current password to change
your password (which is a security improvement), and the other is error
reporting when you either get your current password wrong or your new
password doesn't match it's second entry.
2022-07-10 20:05:54 -07:00
Hugh Rundle 6b1fcc3cbb use class instead of id for spoilers tour 2022-07-10 13:16:28 +10:00
Hugh Rundle 126fd4e634 various wording updates to guided tour 2022-07-10 11:27:01 +10:00
Hugh Rundle a84deff119 add scrollTo for link step on home tour 2022-07-10 11:26:14 +10:00
Hugh Rundle 142c0e1a59 fix template error in search tour 2022-07-10 10:58:48 +10:00
Hugh Rundle 37c2ad11b6 fix border radius on shepherd messages
remove bottom border radius from message text and top border radius from message footer on guided tour popovers.
2022-07-10 09:54:19 +10:00
Hugh Rundle e1acdd0062 fix migrations
There was a conflict due to the order of migrations. Hopefully this commit fixes it!
2022-07-10 09:53:43 +10:00
Hugh Rundle ab5e4128e6 Merge branch 'main' into tour
Also fixes conflict
2022-07-09 20:54:48 +10:00
Hugh Rundle 8fbd634ee8 add id to dm box 2022-07-09 20:52:03 +10:00
Hugh Rundle 48bcb85e24 resolve conflict 2022-07-09 20:12:46 +10:00
Hugh Rundle 02c6932409 lint migration file 2022-07-09 20:10:28 +10:00
Hugh Rundle 245120e7ca resolve git conflict with main branch 2022-07-09 20:08:23 +10:00
Hugh Rundle baad1314d8 default existing users to no tour 2022-07-09 19:51:05 +10:00
Hugh Rundle 495bac2b50 transfer tour from group to DM 2022-07-09 19:38:44 +10:00
Hugh Rundle 2f2ab5c24a add DM tour
- rearrange script includes on feed pages
- add DM tour to close
2022-07-09 19:27:42 +10:00
Hugh Rundle 791847d75e add timeline info to home tour 2022-07-09 19:27:12 +10:00
Hugh Rundle c68c7216f3 minor wording updates for tour 2022-07-09 17:49:56 +10:00
Hugh Rundle 6df09eb5d7 update user groups tour
- use strong instead of code
- clean up templates
- use notification styling for actions
- update wording
2022-07-09 17:39:22 +10:00
Hugh Rundle 07a882692c update lists tour
- cleaner templates
- send user directly to their Groups page at end of section
2022-07-09 17:31:04 +10:00
Hugh Rundle d67c6dc92b user books tour update
- add element highlights
- fix template text
- replace code with strong
2022-07-09 16:56:07 +10:00
Hugh Rundle e85e4a5467 update book page tour
- styling for next action
- replace code with strong
- clean up wording
- make translation templates cleaner
2022-07-09 15:30:45 +10:00
Hugh Rundle bb85d3cdb2 update search tour
- action styling
- code to strong
2022-07-09 15:16:27 +10:00
Hugh Rundle bb4b1a14fd update user profile tour styles 2022-07-09 15:10:52 +10:00
Hugh Rundle 5472cdcad7 update homepage tour
- add highlights to some elements
- consolidate message text for easier translation
- emphasise action with notification style
2022-07-09 15:00:30 +10:00
Hugh Rundle b36968166e fix import message
import files don't import shelves, only books.
2022-07-09 14:47:31 +10:00
Hugh Rundle 3c317d509d fix sass styles import bug
Using @import caused styles to double up on elements, in some cases preventing the correct override behaviour.
Usint @use instead fixes this, and is recommended by Sass for exactly this reason.
2022-07-09 14:42:42 +10:00
Hugh Rundle b41c826a0d custom style for highlighting tour anchorpoints 2022-07-09 14:29:04 +10:00
Hugh Rundle 68308aaa79 update tour colour scheme
- use info instead of default
- increase box shadow
- arrows at top should match header colour
2022-07-09 12:35:06 +10:00
Hugh Rundle 56b91f4c6d fix incorrect tour step header 2022-07-09 10:37:08 +10:00
Hugh Rundle 4d843b583d move shelve button tour id to prevent duplicates 2022-07-09 10:32:04 +10:00
Hugh Rundle 389da79af4 fix missing hyphen 2022-07-09 10:31:40 +10:00
Hugh Rundle 53a89f69e7 guided tour only for request.user 2022-07-09 10:23:09 +10:00
Hugh Rundle 3365bb6d35 show_guided_tour is not added to AP serialisation 2022-07-09 10:17:10 +10:00
Mouse Reeve 583d5b3bdb Remove redundant "Your Books" link from menu 2022-07-08 10:57:53 -07:00
Mouse Reeve 891a5d4dd8 Adds "Your Books" to the header and removed "Feed"
The instance icon is already a link to the feed, and I think it's weird
not to have a quick link to your books, since books are important.
2022-07-08 10:51:22 -07:00
Mouse Reeve 19e0db566c Block some bw-dev commands from being run in prod
Right now, commands that should not be run in production are removed
from the bw-dev file in the `production` branch. Since eventually I'd
like to get rid of that branch, this change would use the `DEBUG`
environment variable to determine if a command should be disabled,
rather than depending on the file available in the branch.
2022-07-07 12:51:09 -07:00
Hugh Rundle d1180d4216 linting fix for linting fix 2022-07-03 17:24:33 +10:00
Hugh Rundle b82cf887e2 linting fixes 2022-07-03 17:14:13 +10:00
Hugh Rundle f8e51b5826 format guided tour js with prettier 2022-07-03 16:24:34 +10:00
Hugh Rundle 0e9dc66ffa Merge branch 'main' into tour
Merging in latest changes from main, since I got covid and missed a few weeks.
2022-07-03 16:18:50 +10:00
Hugh Rundle 04324c00b4 back button on all tour modals 2022-07-03 16:12:17 +10:00
Hugh Rundle 39efb90870 add noscript message for guided tour 2022-07-03 16:10:32 +10:00
Hugh Rundle 3f67bc3b61 standardise ids for tour anchors
To make it harder to accidentally mess up the tour when making changes to pages, this commit adds ids with 'tour' prefixes to (nearly) all elements used by the guided tour as anchor points. The exception is where an element already had an id that is being used by something else in Bookwyrm.

Some minor changes also made to clean up the wording of the tour.
2022-07-03 15:57:10 +10:00
Hugh Rundle a8940b8e12 Fix order of tour
The tour now shows users how to add a book first, then bookshelves, lists, and finally groups.
2022-07-03 14:48:23 +10:00
Hugh Rundle 06b4a55979 add lists to guided tour
Takes user through the main /list page, as well as the options for creating a list.
2022-07-03 09:10:43 +10:00
Hugh Rundle 827a63b4eb add shelves to guided tour 2022-07-02 18:46:16 +10:00
Hugh Rundle d1079a1f7d remove console log from guided_tour.js 2022-07-02 18:44:18 +10:00
Hugh Rundle bc4a1c6c41 Guided tour of book page
This is intended to be one of the earlier pages in the tour. It should show users the concept of reading status, editions, and other useful points.
2022-06-19 14:06:36 +10:00
Hugh Rundle ff37b77be9 clean up search guided tour code 2022-06-19 11:13:04 +10:00
Hugh Rundle fef66a7cfe guided tour for book search
Adds a guided tour for book search page including logic for differing messages depending on what results are visible.
2022-06-19 11:08:01 +10:00
Hugh Rundle 0e06143c31 add guided tour to user shelves 2022-06-18 17:17:22 +10:00
Hugh Rundle 044a173095 remove CSRF from tour scripts 2022-06-18 17:16:43 +10:00
Hugh Rundle 57965973dc make guided tour cancel button DRY
Move cancel button function into a separate JS file.
The selector JS for this function cannot be within bookwyrm.js because the guided tour elements load after bookwyrm.js.
2022-06-18 13:27:00 +10:00
Hugh Rundle 5bf835b965 fix typos 2022-06-18 10:49:42 +10:00
Hugh Rundle d36dd9ce96 guided tour for user groups
Includes adding creating a new group.
2022-06-18 10:48:14 +10:00
Hugh Rundle 00df3c94df add guided tour for user groups page
- add ID for add group button
- add tour steps for user groups page
- trigger tour steps if guided tour is turned on
2022-06-13 20:27:36 +10:00
Hugh Rundle 7fbc9914de change cancel buttons for guided tour
The first pop up in the guided tour on each page should provide a button to switch off the guided tour altogether, not simply cancel the current iteration.
If we don't do this, then the only way to turn off the guided tour is to go right to the end, which could be really irritating, especially for people who star the tour and then start exploring on their own.
2022-06-13 20:25:42 +10:00
Hugh Rundle fbf7f37664 user profile tour only on activity tab 2022-06-13 19:36:14 +10:00
Hugh Rundle aebeac9112 add guided tour to user profile
- adds ids to relevant elements to enable tour
- adds guided tour using Shepherd
2022-06-13 17:26:53 +10:00
Hugh Rundle 83e7302bc1 update home feed guided tour 2022-06-13 16:56:07 +10:00
Hugh Rundle 2030dc834f clean up tour files 2022-06-13 16:48:49 +10:00
Hugh Rundle 5f0e14934f add guided tour to main feed page
This uses an embedded script tag so that we can use django templates for logic - most importantly, we need to be able to use translations within the tour text.
2022-06-13 15:29:20 +10:00
Hugh Rundle 6ffb0863d1 update tour link in main template 2022-06-13 15:27:05 +10:00
Hugh Rundle 8cadb3dc3b fix guided tour url
Use a url fragment (<tour>) instead of a classic url param (/?tour=True)
2022-06-13 15:22:23 +10:00
Hugh Rundle 07225c6ddc add guided tour link 2022-06-13 13:14:31 +10:00
Hugh Rundle 6b7caa9c71 url for setting show_guided_tour
Uses a URL param to indicate whether the value should be set to True or False.
Redirects to home page.
2022-06-13 13:10:31 +10:00
Hugh Rundle 80c71928c3 add show_guided_tour value to User
This boolean value indicates whether the user wishes to be show the guided tour.
It defaults to True but will be able to be easily set to False.
2022-06-13 13:07:48 +10:00
Hugh Rundle 2b431986d6 help tour button styling updates 2022-06-12 20:39:37 +10:00
Hugh Rundle e768cf49a3 add barcode reader to home feed tour 2022-06-12 20:11:21 +10:00
Hugh Rundle c614aeb28e add shepherd tours
This file creates and triggers tours using shepherd.

Initially this is a tour on the home feed page, triggered by clicking on the help button in the top nav.
2022-06-12 19:43:21 +10:00
Hugh Rundle 806e2778df add help button if page has tour
- include logic in main layout to add button if there is a page tour available
- add button for main user feed page
2022-06-12 19:41:50 +10:00
Hugh Rundle f81095cb64 give suggested books block an id 2022-06-12 19:40:36 +10:00
Hugh Rundle cfa659748c add shepherd styles for guided tour
Adds a sass file based on the v10.0.0 Shepherd CSS. Original Shepherd styles are kept where appropriate, otherwise this is intended to inherit whatever styles are being used through the Bulma and Bookwyrm SASS, so that it uses appropriate colours in both light and dark modes.
2022-06-12 13:42:06 +10:00
Mouse Reeve 51f445bc72
Merge branch 'main' into bw-dev-npm-fix 2022-06-11 20:39:18 -07:00
Hugh Rundle b6cd64f82a add Shepherd version 10.0.0 2022-06-11 14:19:03 +10:00
Mouse Reeve 7320375f0c
Merge branch 'main' into ignore-does-not-exist 2022-06-05 15:41:39 -07:00
Joel Bradshaw 7014786fe0 Run formatters 2022-06-05 13:41:00 -07:00
Joel Bradshaw 7ae0db7f4a Ignore VariableDoesNotExist errors in debug logging
They're so noisy as to make debug logging useless otherwise
2022-05-30 12:15:50 -07:00
Vivianne Langdon 51bb4c6f5d make bw-dev consistent 2022-03-17 00:50:04 -07:00
Vivianne Langdon 225957ba8a remove non-css extensions 2022-03-17 00:50:04 -07:00
Vivianne Langdon 54b8d2c3f3 add import rule override for styles 2022-03-17 00:50:04 -07:00
Vivianne Langdon 6f27b5fd2e auto-fixes from running this 2022-03-17 00:50:04 -07:00
Vivianne Langdon dbd5a02617 specify npm prefix and stylelint configs and adjust ignores 2022-03-17 00:50:04 -07:00
Mouse Reeve d2dab0f2db
Merge branch 'main' into misc/add_signatures_to_requests_for_masto_compat 2022-03-01 10:20:39 -08:00
Mouse Reeve 8cc4427e60
Merge branch 'main' into misc/add_signatures_to_requests_for_masto_compat 2022-01-13 11:37:54 -08:00
Renato "Lond" Cerqueira e2ee3d27a7 WIP 2022-01-05 15:47:05 +01:00
Renato "Lond" Cerqueira 097d86454a Add signatures to requests to mastodon to support authorized fetch mode
When mastodon is in authorized fetch mode any request has to be signed
or it fails with 401. This adds the needed signature to the requests
made to discover the actor when receiving something from mastodon (such
as a follow request)
2022-01-05 15:46:42 +01:00
722 changed files with 125383 additions and 17361 deletions

View file

@ -5,3 +5,4 @@ __pycache__
.git
.github
.pytest*
.env

View file

@ -8,7 +8,7 @@ USE_HTTPS=true
DOMAIN=your.domain.here
EMAIL=your@email.here
# Instance defualt language (see options at bookwyrm/settings.py "LANGUAGES"
# Instance default language (see options at bookwyrm/settings.py "LANGUAGES"
LANGUAGE_CODE="en-us"
# Used for deciding which editions to prefer
DEFAULT_LANGUAGE="English"
@ -16,13 +16,18 @@ DEFAULT_LANGUAGE="English"
## Leave unset to allow all hosts
# ALLOWED_HOSTS="localhost,127.0.0.1,[::1]"
# Specify when the site is served from a port that is not the default
# for the protocol (80 for HTTP or 443 for HTTPS).
# Probably only necessary in development.
# PORT=1333
MEDIA_ROOT=images/
# Database configuration
PGPORT=5432
POSTGRES_PASSWORD=securedbypassword123
POSTGRES_USER=fedireads
POSTGRES_DB=fedireads
POSTGRES_USER=bookwyrm
POSTGRES_DB=bookwyrm
POSTGRES_HOST=db
# Redis activity stream manager
@ -32,12 +37,17 @@ REDIS_ACTIVITY_PORT=6379
REDIS_ACTIVITY_PASSWORD=redispassword345
# Optional, use a different redis database (defaults to 0)
# REDIS_ACTIVITY_DB_INDEX=0
# Alternatively specify the full redis url, i.e. if you need to use a unix:// socket
# REDIS_ACTIVITY_URL=
# Redis as celery broker
REDIS_BROKER_HOST=redis_broker
REDIS_BROKER_PORT=6379
REDIS_BROKER_PASSWORD=redispassword123
# Optional, use a different redis database (defaults to 0)
# REDIS_BROKER_DB_INDEX=0
# Alternatively specify the full redis url, i.e. if you need to use a unix:// socket
# REDIS_BROKER_URL=
# Monitoring for celery
FLOWER_PORT=8888
@ -56,30 +66,42 @@ EMAIL_SENDER_NAME=admin
EMAIL_SENDER_DOMAIN=
# Query timeouts
SEARCH_TIMEOUT=15
SEARCH_TIMEOUT=5
QUERY_TIMEOUT=5
# Thumbnails Generation
ENABLE_THUMBNAIL_GENERATION=false
ENABLE_THUMBNAIL_GENERATION=true
# S3 configuration
USE_S3=false
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
# seconds for signed S3 urls to expire
# this is currently only used for user export files
S3_SIGNED_URL_EXPIRY=900
# Commented are example values if you use a non-AWS, S3-compatible service
# AWS S3 should work with only AWS_STORAGE_BUCKET_NAME and AWS_S3_REGION_NAME
# non-AWS S3-compatible services will need AWS_STORAGE_BUCKET_NAME,
# along with both AWS_S3_CUSTOM_DOMAIN and AWS_S3_ENDPOINT_URL
# along with both AWS_S3_CUSTOM_DOMAIN and AWS_S3_ENDPOINT_URL.
# AWS_S3_URL_PROTOCOL must end in ":" and defaults to the same protocol as
# the BookWyrm instance ("http:" or "https:", based on USE_SSL).
# AWS_STORAGE_BUCKET_NAME= # "example-bucket-name"
# AWS_S3_CUSTOM_DOMAIN=None # "example-bucket-name.s3.fr-par.scw.cloud"
# AWS_S3_URL_PROTOCOL=None # "http:"
# AWS_S3_REGION_NAME=None # "fr-par"
# AWS_S3_ENDPOINT_URL=None # "https://s3.fr-par.scw.cloud"
# Commented are example values if you use Azure Blob Storage
# USE_AZURE=true
# AZURE_ACCOUNT_NAME= # "example-account-name"
# AZURE_ACCOUNT_KEY= # "base64-encoded-access-key"
# AZURE_CONTAINER= # "example-blob-container-name"
# AZURE_CUSTOM_DOMAIN= # "example-account-name.blob.core.windows.net"
# Preview image generation can be computing and storage intensive
# ENABLE_PREVIEW_IMAGES=True
ENABLE_PREVIEW_IMAGES=False
# Specify RGB tuple or RGB hex strings,
# or use_dominant_color_light / use_dominant_color_dark
@ -108,3 +130,28 @@ OTEL_EXPORTER_OTLP_ENDPOINT=
OTEL_EXPORTER_OTLP_HEADERS=
# Service name to identify your app
OTEL_SERVICE_NAME=
# Set HTTP_X_FORWARDED_PROTO ONLY to true if you know what you are doing.
# Only use it if your proxy is "swallowing" if the original request was made
# via https. Please refer to the Django-Documentation and assess the risks
# for your instance:
# https://docs.djangoproject.com/en/3.2/ref/settings/#secure-proxy-ssl-header
HTTP_X_FORWARDED_PROTO=false
# TOTP settings
# TWO_FACTOR_LOGIN_VALIDITY_WINDOW sets the number of codes either side
# which will be accepted.
TWO_FACTOR_LOGIN_VALIDITY_WINDOW=2
TWO_FACTOR_LOGIN_MAX_SECONDS=60
# Additional hosts to allow in the Content-Security-Policy, "self" (should be
# DOMAIN with optionally ":" + PORT) and AWS_S3_CUSTOM_DOMAIN (if used) are
# added by default. Value should be a comma-separated list of host names.
CSP_ADDITIONAL_HOSTS=
# Time before being logged out (in seconds)
# SESSION_COOKIE_AGE=2592000 # current default: 30 days
# Maximum allowed memory for file uploads (increase if users are having trouble
# uploading BookWyrm export files).
# DATA_UPLOAD_MAX_MEMORY_MiB=100

View file

@ -1,15 +0,0 @@
name: Python Formatting (run ./bw-dev black to fix)
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: psf/black@21.4b2

View file

@ -36,11 +36,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -51,7 +51,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -65,4 +65,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3

View file

@ -10,7 +10,7 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install curlylint
run: pip install curlylint

View file

@ -1,60 +0,0 @@
name: Run Python Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-20.04
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: hunter2
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run Tests
env:
SECRET_KEY: beepbeep
DEBUG: false
USE_HTTPS: true
DOMAIN: your.domain.here
BOOKWYRM_DATABASE_BACKEND: postgres
MEDIA_ROOT: images/
POSTGRES_PASSWORD: hunter2
POSTGRES_USER: postgres
POSTGRES_DB: github_actions
POSTGRES_HOST: 127.0.0.1
CELERY_BROKER: ""
REDIS_BROKER_PORT: 6379
REDIS_BROKER_PASSWORD: beep
USE_DUMMY_CACHE: true
FLOWER_PORT: 8888
EMAIL_HOST: "smtp.mailgun.org"
EMAIL_PORT: 587
EMAIL_HOST_USER: ""
EMAIL_HOST_PASSWORD: ""
EMAIL_USE_TLS: true
ENABLE_PREVIEW_IMAGES: false
ENABLE_THUMBNAIL_GENERATION: true
run: |
pytest -n 3

View file

@ -19,16 +19,17 @@ jobs:
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it.
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install modules
run: npm install stylelint stylelint-config-recommended stylelint-config-standard stylelint-order eslint
# run: npm install stylelint stylelint-config-recommended stylelint-config-standard stylelint-order eslint
run: npm install eslint@^8.9.0
# See .stylelintignore for files that are not linted.
- name: Run stylelint
run: >
npx stylelint bookwyrm/static/css/*.scss bookwyrm/static/css/bookwyrm/**/*.scss \
--config dev-tools/.stylelintrc.js
# - name: Run stylelint
# run: >
# npx stylelint bookwyrm/static/css/*.scss bookwyrm/static/css/bookwyrm/**/*.scss \
# --config dev-tools/.stylelintrc.js
# See .eslintignore for files that are not linted.
- name: Run ESLint

View file

@ -14,10 +14,10 @@ jobs:
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it.
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install modules
run: npm install prettier
run: npm install prettier@2.5.1
- name: Run Prettier
run: npx prettier --check bookwyrm/static/js/*.js

View file

@ -1,27 +0,0 @@
name: Pylint
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Analysing the code with pylint
run: |
pylint bookwyrm/

99
.github/workflows/python.yml vendored Normal file
View file

@ -0,0 +1,99 @@
name: Python
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# overrides for .env.example
env:
POSTGRES_HOST: 127.0.0.1
PGPORT: 5432
POSTGRES_USER: postgres
POSTGRES_PASSWORD: hunter2
POSTGRES_DB: github_actions
SECRET_KEY: beepbeep
EMAIL_HOST_USER: ""
EMAIL_HOST_PASSWORD: ""
jobs:
pytest:
name: Tests (pytest)
runs-on: ubuntu-latest
services:
postgres:
image: postgres:13
env: # does not inherit from jobs.build.env
POSTGRES_USER: postgres
POSTGRES_PASSWORD: hunter2
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: pip
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest-github-actions-annotate-failures
- name: Set up .env
run: cp .env.example .env
- name: Check migrations up-to-date
run: python ./manage.py makemigrations --check
- name: Run Tests
run: pytest -n 3
pylint:
name: Linting (pylint)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: pip
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Analyse code with pylint
run: pylint bookwyrm/
mypy:
name: Typing (mypy)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: 3.11
cache: pip
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Set up .env
run: cp .env.example .env
- name: Analyse code with mypy
run: mypy bookwyrm celerywyrm
black:
name: Formatting (black; run ./bw-dev black to fix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: psf/black@stable
with:
version: "22.*"

5
.gitignore vendored
View file

@ -16,6 +16,8 @@
# BookWyrm
.env
/images/
/exports/
/static/
bookwyrm/static/css/bookwyrm.css
bookwyrm/static/css/themes/
!bookwyrm/static/css/themes/bookwyrm-*.scss
@ -36,3 +38,6 @@ nginx/default.conf
#macOS
**/.DS_Store
# Docker
docker-compose.override.yml

1
.prettierrc Normal file
View file

@ -0,0 +1 @@
'trailingComma': 'es5'

View file

@ -1,4 +1,4 @@
FROM python:3.9
FROM python:3.11
ENV PYTHONUNBUFFERED 1

334
FEDERATION.md Normal file
View file

@ -0,0 +1,334 @@
# Federation
BookWyrm uses the [ActivityPub](http://activitypub.rocks/) protocol to send and receive user activity between other BookWyrm instances and other services that implement ActivityPub. To handle book data, BookWyrm has a handful of extended Activity types which are not part of the standard, but are legible to other BookWyrm instances.
## Activities and Objects
### Users and relationships
User relationship interactions follow the standard ActivityPub spec.
- `Follow`: request to receive statuses from a user, and view their statuses that have followers-only privacy
- `Accept`: approves a `Follow` and finalizes the relationship
- `Reject`: denies a `Follow`
- `Block`: prevent users from seeing one another's statuses, and prevents the blocked user from viewing the actor's profile
- `Update`: updates a user's profile and settings
- `Delete`: deactivates a user
- `Undo`: reverses a `Block` or `Follow`
### Activities
- `Create/Status`: saves a new status in the database.
- `Delete/Status`: Removes a status
- `Like/Status`: Creates a favorite on the status
- `Announce/Status`: Boosts the status into the actor's timeline
- `Undo/*`,: Reverses an `Announce`, `Like`, or `Move`
- `Move/User`: Moves a user from one ActivityPub id to another.
### Collections
User's books and lists are represented by [`OrderedCollection`](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection)
### Statuses
BookWyrm is focused on book reading activities - it is not a general-purpose messaging application. For this reason, BookWyrm only accepts status `Create` activities if they are:
- Direct messages (i.e., `Note`s with the privacy level `direct`, which mention a local user),
- Related to a book (of a custom status type that includes the field `inReplyToBook`),
- Replies to existing statuses saved in the database
All other statuses will be received by the instance inbox, but by design **will not be delivered to user inboxes or displayed to users**.
### Custom Object types
With the exception of `Note`, the following object types are used in Bookwyrm but are not currently provided with a custom JSON-LD `@context` extension IRI. This is likely to change in future to make them true deserialisable JSON-LD objects.
##### Note
Within BookWyrm a `Note` is constructed according to [the ActivityStreams vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note), however `Note`s can only be created as direct messages or as replies to other statuses. As mentioned above, this also applies to incoming `Note`s.
##### Review
A `Review` is a status in response to a book (indicated by the `inReplyToBook` field), which has a title, body, and numerical rating between 0 (not rated) and 5.
Example:
```json
{
"id": "https://example.net/user/library_lurker/review/2",
"type": "Review",
"published": "2023-06-30T21:43:46.013132+00:00",
"attributedTo": "https://example.net/user/library_lurker",
"content": "<p>This is an enjoyable book with great characters.</p>",
"to": ["https://example.net/user/library_lurker/followers"],
"cc": [],
"replies": {
"id": "https://example.net/user/library_lurker/review/2/replies",
"type": "OrderedCollection",
"totalItems": 0,
"first": "https://example.net/user/library_lurker/review/2/replies?page=1",
"last": "https://example.net/user/library_lurker/review/2/replies?page=1",
"@context": "https://www.w3.org/ns/activitystreams"
},
"summary": "Spoilers ahead!",
"tag": [],
"attachment": [],
"sensitive": true,
"inReplyToBook": "https://example.net/book/1",
"name": "What a cracking read",
"rating": 4.5,
"@context": "https://www.w3.org/ns/activitystreams"
}
```
##### Comment
A `Comment` on a book mentions a book and has a message body, reading status, and progress indicator.
Example:
```json
{
"id": "https://example.net/user/library_lurker/comment/9",
"type": "Comment",
"published": "2023-06-30T21:43:46.013132+00:00",
"attributedTo": "https://example.net/user/library_lurker",
"content": "<p>This is a very enjoyable book so far.</p>",
"to": ["https://example.net/user/library_lurker/followers"],
"cc": [],
"replies": {
"id": "https://example.net/user/library_lurker/comment/9/replies",
"type": "OrderedCollection",
"totalItems": 0,
"first": "https://example.net/user/library_lurker/comment/9/replies?page=1",
"last": "https://example.net/user/library_lurker/comment/9/replies?page=1",
"@context": "https://www.w3.org/ns/activitystreams"
},
"summary": "Spoilers ahead!",
"tag": [],
"attachment": [],
"sensitive": true,
"inReplyToBook": "https://example.net/book/1",
"readingStatus": "reading",
"progress": 25,
"progressMode": "PG",
"@context": "https://www.w3.org/ns/activitystreams"
}
```
##### Quotation
A quotation (aka "quote") has a message body, an excerpt from a book including position as a page number or percentage indicator, and mentions a book.
Example:
```json
{
"id": "https://example.net/user/mouse/quotation/13",
"url": "https://example.net/user/mouse/quotation/13",
"inReplyTo": null,
"published": "2020-05-10T02:38:31.150343+00:00",
"attributedTo": "https://example.net/user/mouse",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://example.net/user/mouse/followers"
],
"sensitive": false,
"content": "I really like this quote",
"type": "Quotation",
"replies": {
"id": "https://example.net/user/mouse/quotation/13/replies",
"type": "Collection",
"first": {
"type": "CollectionPage",
"next": "https://example.net/user/mouse/quotation/13/replies?only_other_accounts=true&page=true",
"partOf": "https://example.net/user/mouse/quotation/13/replies",
"items": []
}
},
"inReplyToBook": "https://example.net/book/1",
"quote": "To be or not to be, that is the question.",
"position": 50,
"positionMode": "PCT",
"@context": "https://www.w3.org/ns/activitystreams"
}
```
### Custom Objects
##### Work
A particular book, a "work" in the [FRBR](https://en.wikipedia.org/wiki/Functional_Requirements_for_Bibliographic_Records) sense.
Example:
```json
{
"id": "https://bookwyrm.social/book/5988",
"type": "Work",
"authors": [
"https://bookwyrm.social/author/417"
],
"first_published_date": null,
"published_date": null,
"title": "Piranesi",
"sort_title": null,
"subtitle": null,
"description": "**From the *New York Times* bestselling author of *Jonathan Strange & Mr. Norrell*, an intoxicating, hypnotic new novel set in a dreamlike alternative reality.",
"languages": [],
"series": null,
"series_number": null,
"subjects": [
"English literature"
],
"subject_places": [],
"openlibrary_key": "OL20893680W",
"librarything_key": null,
"goodreads_key": null,
"attachment": [
{
"url": "https://bookwyrm.social/images/covers/10226290-M.jpg",
"type": "Image"
}
],
"lccn": null,
"editions": [
"https://bookwyrm.social/book/5989"
],
"@context": "https://www.w3.org/ns/activitystreams"
}
```
##### Edition
A particular _manifestation_ of a Work, in the [FRBR](https://en.wikipedia.org/wiki/Functional_Requirements_for_Bibliographic_Records) sense.
Example:
```json
{
"id": "https://bookwyrm.social/book/5989",
"lastEditedBy": "https://example.net/users/rat",
"type": "Edition",
"authors": [
"https://bookwyrm.social/author/417"
],
"first_published_date": null,
"published_date": "2020-09-15T00:00:00+00:00",
"title": "Piranesi",
"sort_title": null,
"subtitle": null,
"description": "Piranesi's house is no ordinary building; its rooms are infinite, its corridors endless, its walls are lined with thousands upon thousands of statues, each one different from all the others.",
"languages": [
"English"
],
"series": null,
"series_number": null,
"subjects": [],
"subject_places": [],
"openlibrary_key": "OL29486417M",
"librarything_key": null,
"goodreads_key": null,
"isfdb": null,
"attachment": [
{
"url": "https://bookwyrm.social/images/covers/50202953._SX318_.jpg",
"type": "Image"
}
],
"isbn_10": "1526622424",
"isbn_13": "9781526622426",
"oclc_number": null,
"asin": null,
"pages": 272,
"physical_format": null,
"publishers": [
"Bloomsbury Publishing Plc"
],
"work": "https://bookwyrm.social/book/5988",
"@context": "https://www.w3.org/ns/activitystreams"
}
```
#### Shelf
A user's book collection. By default, every user has a `to-read`, `reading`, `read`, and `stopped-reading` shelf which are used to track reading progress. Users may create an unlimited number of additional shelves with their own ids.
Example
```json
{
"id": "https://example.net/user/avid_reader/books/extraspecialbooks-5",
"type": "Shelf",
"totalItems": 0,
"first": "https://example.net/user/avid_reader/books/extraspecialbooks-5?page=1",
"last": "https://example.net/user/avid_reader/books/extraspecialbooks-5?page=1",
"name": "Extra special books",
"owner": "https://example.net/user/avid_reader",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://example.net/user/avid_reader/followers"
],
"@context": "https://www.w3.org/ns/activitystreams"
}
```
#### List
A collection of books that may have items contributed by users other than the one who created the list.
Example:
```json
{
"id": "https://example.net/list/1",
"type": "BookList",
"totalItems": 0,
"first": "https://example.net/list/1?page=1",
"last": "https://example.net/list/1?page=1",
"name": "My cool list",
"owner": "https://example.net/user/avid_reader",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://example.net/user/avid_reader/followers"
],
"summary": "A list of books I like.",
"curation": "curated",
"@context": "https://www.w3.org/ns/activitystreams"
}
```
#### Activities
- `Create`: Adds a shelf or list to the database.
- `Delete`: Removes a shelf or list.
- `Add`: Adds a book to a shelf or list.
- `Remove`: Removes a book from a shelf or list.
## Alternative Serialization
Because BookWyrm uses custom object types that aren't listed in [the standard ActivityStreams Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary), some statuses are transformed into standard types when sent to or viewed by non-BookWyrm services. `Review`s are converted into `Article`s, and `Comment`s and `Quotation`s are converted into `Note`s, with a link to the book and the cover image attached.
In future this may be done with [JSON-LD type arrays](https://www.w3.org/TR/json-ld/#specifying-the-type) instead.
## Other extensions
### Webfinger
Bookwyrm uses the [Webfinger](https://datatracker.ietf.org/doc/html/rfc7033) standard to identify and disambiguate fediverse actors. The [Webfinger documentation on the Mastodon project](https://docs.joinmastodon.org/spec/webfinger/) provides a good overview of how Webfinger is used.
### HTTP Signatures
Bookwyrm uses and requires HTTP signatures for all `POST` requests. `GET` requests are not signed by default, but if Bookwyrm receives a `403` response to a `GET` it will re-send the request, signed by the default server user. This usually will have a user id of `https://example.net/user/bookwyrm.instance.actor`
#### publicKey id
In older versions of Bookwyrm the `publicKey.id` was incorrectly listed in request headers as `https://example.net/user/username#main-key`. As of v0.6.3 the id is now listed correctly, as `https://example.net/user/username/#main-key`. In most ActivityPub implementations this will make no difference as the URL will usually resolve to the same place.
### NodeInfo
Bookwyrm uses the [NodeInfo](http://nodeinfo.diaspora.software/) standard to provide statistics and version information for each instance.
## Further Documentation
See [docs.joinbookwyrm.com/](https://docs.joinbookwyrm.com/) for more documentation.

View file

@ -1,60 +1,44 @@
# BookWyrm
Social reading and reviewing, decentralized with ActivityPub
[![](https://img.shields.io/github/release/bookwyrm-social/bookwyrm.svg?colorB=58839b)](https://github.com/bookwyrm-social/bookwyrm/releases)
[![Run Python Tests](https://github.com/bookwyrm-social/bookwyrm/actions/workflows/django-tests.yml/badge.svg)](https://github.com/bookwyrm-social/bookwyrm/actions/workflows/django-tests.yml)
[![Pylint](https://github.com/bookwyrm-social/bookwyrm/actions/workflows/pylint.yml/badge.svg)](https://github.com/bookwyrm-social/bookwyrm/actions/workflows/pylint.yml)
## Contents
- [Joining BookWyrm](#joining-bookwyrm)
- [Contributing](#contributing)
- [About BookWyrm](#about-bookwyrm)
- [What it is and isn't](#what-it-is-and-isnt)
- [The role of federation](#the-role-of-federation)
- [Features](#features)
- [Set up BookWyrm](#set-up-bookwyrm)
## Joining BookWyrm
If you'd like to join an instance, you can check out the [instances](https://joinbookwyrm.com/instances/) list.
BookWyrm is a social network for tracking your reading, talking about books, writing reviews, and discovering what to read next. Federation allows BookWyrm users to join small, trusted communities that can connect with one another, and with other ActivityPub services like [Mastodon](https://joinmastodon.org/) and [Pleroma](http://pleroma.social/).
## Contributing
See [contributing](https://docs.joinbookwyrm.com/contributing.html) for code, translation or monetary contributions.
## Links
[![Mastodon Follow](https://img.shields.io/mastodon/follow/000146121?domain=https%3A%2F%2Ftech.lgbt&style=social)](https://tech.lgbt/@bookwyrm)
- [Project homepage](https://joinbookwyrm.com/)
- [Support](https://patreon.com/bookwyrm)
- [Documentation](https://docs.joinbookwyrm.com/)
## About BookWyrm
### What it is and isn't
BookWyrm is a platform for social reading. You can use it to track what you're reading, review books, and follow your friends. It isn't primarily meant for cataloguing or as a data-source for books, but it does do both of those things to some degree.
### The role of federation
## Federation
BookWyrm is built on [ActivityPub](http://activitypub.rocks/). With ActivityPub, it inter-operates with different instances of BookWyrm, and other ActivityPub compliant services, like Mastodon. This means you can run an instance for your book club, and still follow your friend who posts on a server devoted to 20th century Russian speculative fiction. It also means that your friend on mastodon can read and comment on a book review that you post on your BookWyrm instance.
Federation makes it possible to have small, self-determining communities, in contrast to the monolithic service you find on GoodReads or Twitter. An instance can be focused on a particular interest, be just for a group of friends, or anything else that brings people together. Each community can choose which other instances they want to federate with, and moderate and run their community autonomously. Check out https://runyourown.social/ to get a sense of the philosophy and logistics behind small, high-trust social networks.
### Features
Since the project is still in its early stages, the features are growing every day, and there is plenty of room for suggestions and ideas. Open an [issue](https://github.com/bookwyrm-social/bookwyrm/issues) to get the conversation going!
- Posting about books
- Compose reviews, with or without ratings, which are aggregated in the book page
- Compose other kinds of statuses about books, such as:
- Comments on a book
- Quotes or excerpts
- Reply to statuses
- View aggregate reviews of a book across connected BookWyrm instances
- Differentiate local and federated reviews and rating in your activity feed
- Track reading activity
- Shelve books on default "to-read," "currently reading," and "read" shelves
- Create custom shelves
- Store started reading/finished reading dates, as well as progress updates along the way
- Update followers about reading activity (optionally, and with granular privacy controls)
- Create lists of books which can be open to submissions from anyone, curated, or only edited by the creator
- Federation with ActivityPub
- Broadcast and receive user statuses and activity
- Share book data between instances to create a networked database of metadata
- Identify shared books across instances and aggregate related content
- Follow and interact with users across BookWyrm instances
- Inter-operate with non-BookWyrm ActivityPub services (currently, Mastodon is supported)
- Granular privacy controls
- Private, followers-only, and public privacy levels for posting, shelves, and lists
- Option for users to manually approve followers
- Allow blocking and flagging for moderation
## Features
### The Tech Stack
### Post about books
Compose reviews, comment on what you're reading, and post quotes from books. You can converse with other BookWyrm users across the network about what they're reading.
### Track reading activity
Keep track of what books you've read, and what books you'd like to read in the future.
### Federation with ActivityPub
Federation allows you to interact with users on other instances and services, and also shares metadata about books and authors, which collaboratively builds a decentralized database of books.
### Privacy and moderation
Users and administrators can control who can see their posts and what other instances to federate with.
## Tech Stack
Web backend
- [Django](https://www.djangoproject.com/) web server
- [PostgreSQL](https://www.postgresql.org/) database

1
VERSION Normal file
View file

@ -0,0 +1 @@
0.7.3

View file

@ -3,8 +3,12 @@ import inspect
import sys
from .base_activity import ActivityEncoder, Signature, naive_parse
from .base_activity import Link, Mention
from .base_activity import ActivitySerializerError, resolve_remote_id
from .base_activity import Link, Mention, Hashtag
from .base_activity import (
ActivitySerializerError,
resolve_remote_id,
get_representative,
)
from .image import Document, Image
from .note import Note, GeneratedNote, Article, Comment, Quotation
from .note import Review, Rating
@ -19,6 +23,7 @@ from .verbs import Create, Delete, Undo, Update
from .verbs import Follow, Accept, Reject, Block
from .verbs import Add, Remove
from .verbs import Announce, Like
from .verbs import Move
# this creates a list of all the Activity types that we can serialize,
# so when an Activity comes in from outside, we can check if it's known

View file

@ -1,16 +1,28 @@
""" basics for an activitypub serializer """
from __future__ import annotations
from dataclasses import dataclass, fields, MISSING
from json import JSONEncoder
import logging
from typing import Optional, Union, TypeVar, overload, Any
import requests
from django.apps import apps
from django.db import IntegrityError, transaction
from django.utils.http import http_date
from bookwyrm import models
from bookwyrm.connectors import ConnectorException, get_data
from bookwyrm.tasks import app
from bookwyrm.models import base_model
from bookwyrm.signatures import make_signature
from bookwyrm.settings import DOMAIN, INSTANCE_ACTOR_USERNAME
from bookwyrm.tasks import app, MISC
logger = logging.getLogger(__name__)
# pylint: disable=invalid-name
TBookWyrmModel = TypeVar("TBookWyrmModel", bound=base_model.BookWyrmModel)
class ActivitySerializerError(ValueError):
"""routine problems serializing activitypub json"""
@ -60,7 +72,13 @@ class ActivityObject:
id: str
type: str
def __init__(self, activity_objects=None, **kwargs):
def __init__(
self,
activity_objects: Optional[
dict[str, Union[str, list[str], ActivityObject, base_model.BookWyrmModel]]
] = None,
**kwargs: Any,
):
"""this lets you pass in an object with fields that aren't in the
dataclass, which it ignores. Any field in the dataclass is required or
has a default value"""
@ -95,16 +113,34 @@ class ActivityObject:
# pylint: disable=too-many-locals,too-many-branches,too-many-arguments
def to_model(
self, model=None, instance=None, allow_create=True, save=True, overwrite=True
):
"""convert from an activity to a model instance"""
self,
model: Optional[type[TBookWyrmModel]] = None,
instance: Optional[TBookWyrmModel] = None,
allow_create: bool = True,
save: bool = True,
overwrite: bool = True,
allow_external_connections: bool = True,
) -> Optional[TBookWyrmModel]:
"""convert from an activity to a model instance. Args:
model: the django model that this object is being converted to
(will guess if not known)
instance: an existing database entry that is going to be updated by
this activity
allow_create: whether a new object should be created if there is no
existing object is provided or found matching the remote_id
save: store in the database if true, return an unsaved model obj if false
overwrite: replace fields in the database with this activity if true,
only update blank fields if false
allow_external_connections: look up missing data if true,
throw an exception if false and an external connection is needed
"""
model = model or get_model_from_type(self.type)
# only reject statuses if we're potentially creating them
if (
allow_create
and hasattr(model, "ignore_activity")
and model.ignore_activity(self)
and model.ignore_activity(self, allow_external_connections)
):
return None
@ -122,7 +158,10 @@ class ActivityObject:
for field in instance.simple_fields:
try:
changed = field.set_field_from_activity(
instance, self, overwrite=overwrite
instance,
self,
overwrite=overwrite,
allow_external_connections=allow_external_connections,
)
if changed:
update_fields.append(field.name)
@ -133,7 +172,11 @@ class ActivityObject:
# too early and jank up users
for field in instance.image_fields:
changed = field.set_field_from_activity(
instance, self, save=save, overwrite=overwrite
instance,
self,
save=save,
overwrite=overwrite,
allow_external_connections=allow_external_connections,
)
if changed:
update_fields.append(field.name)
@ -156,8 +199,12 @@ class ActivityObject:
# add many to many fields, which have to be set post-save
for field in instance.many_to_many_fields:
# mention books/users, for example
field.set_field_from_activity(instance, self)
# mention books/users/hashtags, for example
field.set_field_from_activity(
instance,
self,
allow_external_connections=allow_external_connections,
)
# reversed relationships in the models
for (
@ -190,10 +237,15 @@ class ActivityObject:
omit = kwargs.get("omit", ())
data = self.__dict__.copy()
# recursively serialize
for (k, v) in data.items():
for k, v in data.items():
try:
if issubclass(type(v), ActivityObject):
data[k] = v.serialize()
elif isinstance(v, list):
data[k] = [
e.serialize() if issubclass(type(e), ActivityObject) else e
for e in v
]
except TypeError:
pass
data = {k: v for (k, v) in data.items() if v is not None and k not in omit}
@ -202,7 +254,7 @@ class ActivityObject:
return data
@app.task(queue="medium_priority")
@app.task(queue=MISC)
@transaction.atomic
def set_related_field(
model_name, origin_model_name, related_field_name, related_remote_id, data
@ -241,10 +293,10 @@ def set_related_field(
def get_model_from_type(activity_type):
"""given the activity, what type of model"""
models = apps.get_models()
activity_models = apps.get_models()
model = [
m
for m in models
for m in activity_models
if hasattr(m, "activity_serializer")
and hasattr(m.activity_serializer, "type")
and m.activity_serializer.type == activity_type
@ -256,10 +308,48 @@ def get_model_from_type(activity_type):
return model[0]
# pylint: disable=too-many-arguments
@overload
def resolve_remote_id(
remote_id, model=None, refresh=False, save=True, get_activity=False
):
"""take a remote_id and return an instance, creating if necessary"""
remote_id: str,
model: type[TBookWyrmModel],
refresh: bool = False,
save: bool = True,
get_activity: bool = False,
allow_external_connections: bool = True,
) -> TBookWyrmModel:
...
# pylint: disable=too-many-arguments
@overload
def resolve_remote_id(
remote_id: str,
model: Optional[str] = None,
refresh: bool = False,
save: bool = True,
get_activity: bool = False,
allow_external_connections: bool = True,
) -> base_model.BookWyrmModel:
...
# pylint: disable=too-many-arguments
def resolve_remote_id(
remote_id: str,
model: Optional[Union[str, type[base_model.BookWyrmModel]]] = None,
refresh: bool = False,
save: bool = True,
get_activity: bool = False,
allow_external_connections: bool = True,
) -> base_model.BookWyrmModel:
"""take a remote_id and return an instance, creating if necessary. Args:
remote_id: the unique url for looking up the object in the db or by http
model: a string or object representing the model that corresponds to the object
save: whether to return an unsaved database entry or a saved one
get_activity: whether to return the activitypub object or the model object
allow_external_connections: whether to make http connections
"""
if model: # a bonus check we can do if we already know the model
if isinstance(model, str):
model = apps.get_model(f"bookwyrm.{model}", require_ready=True)
@ -267,13 +357,26 @@ def resolve_remote_id(
if result and not refresh:
return result if not get_activity else result.to_activity_dataclass()
# The above block will return the object if it already exists in the database.
# If it doesn't, an external connection would be needed, so check if that's cool
if not allow_external_connections:
raise ActivitySerializerError(
"Unable to serialize object without making external HTTP requests"
)
# load the data and create the object
try:
data = get_data(remote_id)
except ConnectorException:
logger.exception("Could not connect to host for remote_id: %s", remote_id)
except ConnectionError:
logger.info("Could not connect to host for remote_id: %s", remote_id)
return None
except requests.HTTPError as e:
if (e.response is not None) and e.response.status_code == 401:
# This most likely means it's a mastodon with secure fetch enabled.
data = get_activitypub_data(remote_id)
else:
logger.info("Could not connect to host for remote_id: %s", remote_id)
return None
# determine the model implicitly, if not provided
# or if it's a model with subclasses like Status, check again
if not model or hasattr(model.objects, "select_subclasses"):
@ -292,6 +395,49 @@ def resolve_remote_id(
return item.to_model(model=model, instance=result, save=save)
def get_representative():
"""Get or create an actor representing the instance
to sign outgoing HTTP GET requests"""
return models.User.objects.get_or_create(
username=f"{INSTANCE_ACTOR_USERNAME}@{DOMAIN}",
defaults=dict(
email="bookwyrm@localhost",
local=True,
localname=INSTANCE_ACTOR_USERNAME,
),
)[0]
def get_activitypub_data(url):
"""wrapper for request.get"""
now = http_date()
sender = get_representative()
if not sender.key_pair.private_key:
# this shouldn't happen. it would be bad if it happened.
raise ValueError("No private key found for sender")
try:
resp = requests.get(
url,
headers={
# pylint: disable=line-too-long
"Accept": 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
"Date": now,
"Signature": make_signature("get", sender, url, now),
},
timeout=15,
)
except requests.RequestException:
raise ConnectorException()
if not resp.ok:
resp.raise_for_status()
try:
data = resp.json()
except ValueError:
raise ConnectorException()
return data
@dataclass(init=False)
class Link(ActivityObject):
"""for tagging a book in a status"""
@ -306,7 +452,9 @@ class Link(ActivityObject):
def serialize(self, **kwargs):
"""remove fields"""
omit = ("id", "type", "@context")
omit = ("id", "@context")
if self.type == "Link":
omit += ("type",)
return super().serialize(omit=omit)
@ -315,3 +463,10 @@ class Mention(Link):
"""a subtype of Link for mentioning an actor"""
type: str = "Mention"
@dataclass(init=False)
class Hashtag(Link):
"""a subtype of Link for mentioning a hashtag"""
type: str = "Hashtag"

View file

@ -1,6 +1,6 @@
""" book and author data """
from dataclasses import dataclass, field
from typing import List
from typing import Optional
from .base_activity import ActivityObject
from .image import Document
@ -11,17 +11,17 @@ from .image import Document
class BookData(ActivityObject):
"""shared fields for all book data and authors"""
openlibraryKey: str = None
inventaireId: str = None
librarythingKey: str = None
goodreadsKey: str = None
bnfId: str = None
viaf: str = None
wikidata: str = None
asin: str = None
lastEditedBy: str = None
links: List[str] = field(default_factory=lambda: [])
fileLinks: List[str] = field(default_factory=lambda: [])
openlibraryKey: Optional[str] = None
inventaireId: Optional[str] = None
librarythingKey: Optional[str] = None
goodreadsKey: Optional[str] = None
bnfId: Optional[str] = None
viaf: Optional[str] = None
wikidata: Optional[str] = None
asin: Optional[str] = None
aasin: Optional[str] = None
isfdb: Optional[str] = None
lastEditedBy: Optional[str] = None
# pylint: disable=invalid-name
@ -33,17 +33,19 @@ class Book(BookData):
sortTitle: str = None
subtitle: str = None
description: str = ""
languages: List[str] = field(default_factory=lambda: [])
languages: list[str] = field(default_factory=list)
series: str = ""
seriesNumber: str = ""
subjects: List[str] = field(default_factory=lambda: [])
subjectPlaces: List[str] = field(default_factory=lambda: [])
subjects: list[str] = field(default_factory=list)
subjectPlaces: list[str] = field(default_factory=list)
authors: List[str] = field(default_factory=lambda: [])
authors: list[str] = field(default_factory=list)
firstPublishedDate: str = ""
publishedDate: str = ""
cover: Document = None
fileLinks: list[str] = field(default_factory=list)
cover: Optional[Document] = None
type: str = "Book"
@ -56,10 +58,10 @@ class Edition(Book):
isbn10: str = ""
isbn13: str = ""
oclcNumber: str = ""
pages: int = None
pages: Optional[int] = None
physicalFormat: str = ""
physicalFormatDetail: str = ""
publishers: List[str] = field(default_factory=lambda: [])
publishers: list[str] = field(default_factory=list)
editionRank: int = 0
type: str = "Edition"
@ -71,7 +73,7 @@ class Work(Book):
"""work instance of a book object"""
lccn: str = ""
editions: List[str] = field(default_factory=lambda: [])
editions: list[str] = field(default_factory=list)
type: str = "Work"
@ -81,12 +83,13 @@ class Author(BookData):
"""author of a book"""
name: str
isni: str = None
viafId: str = None
gutenbergId: str = None
born: str = None
died: str = None
aliases: List[str] = field(default_factory=lambda: [])
isni: Optional[str] = None
viafId: Optional[str] = None
gutenbergId: Optional[str] = None
born: Optional[str] = None
died: Optional[str] = None
aliases: list[str] = field(default_factory=list)
bio: str = ""
wikipediaLink: str = ""
type: str = "Author"
website: str = ""

View file

@ -1,9 +1,12 @@
""" note serializer and children thereof """
from dataclasses import dataclass, field
from typing import Dict, List
from django.apps import apps
import re
from .base_activity import ActivityObject, Link
from django.apps import apps
from django.db import IntegrityError, transaction
from .base_activity import ActivityObject, ActivitySerializerError, Link
from .image import Document
@ -38,6 +41,47 @@ class Note(ActivityObject):
updated: str = None
type: str = "Note"
# pylint: disable=too-many-arguments
def to_model(
self,
model=None,
instance=None,
allow_create=True,
save=True,
overwrite=True,
allow_external_connections=True,
):
instance = super().to_model(
model, instance, allow_create, save, overwrite, allow_external_connections
)
if instance is None:
return instance
# Replace links to hashtags in content with local URLs
changed_content = False
for hashtag in instance.mention_hashtags.all():
updated_content = re.sub(
rf'(<a href=")[^"]*(" data-mention="hashtag">{hashtag.name}</a>)',
rf"\1{hashtag.remote_id}\2",
instance.content,
flags=re.IGNORECASE,
)
if instance.content != updated_content:
instance.content = updated_content
changed_content = True
if not save or not changed_content:
return instance
with transaction.atomic():
try:
instance.save(broadcast=False, update_fields=["content"])
except IntegrityError as e:
raise ActivitySerializerError(e)
return instance
@dataclass(init=False)
class Article(Note):

View file

@ -1,5 +1,5 @@
""" actor serializer """
from dataclasses import dataclass, field
from dataclasses import dataclass
from typing import Dict
from .base_activity import ActivityObject
@ -35,9 +35,11 @@ class Person(ActivityObject):
endpoints: Dict = None
name: str = None
summary: str = None
icon: Image = field(default_factory=lambda: {})
icon: Image = None
bookwyrmUser: bool = False
manuallyApprovesFollowers: str = False
discoverable: str = False
hideFollows: str = False
movedTo: str = None
alsoKnownAs: dict[str] = None
type: str = "Person"

View file

@ -14,12 +14,12 @@ class Verb(ActivityObject):
actor: str
object: ActivityObject
def action(self):
def action(self, allow_external_connections=True):
"""usually we just want to update and save"""
# self.object may return None if the object is invalid in an expected way
# ie, Question type
if self.object:
self.object.to_model()
self.object.to_model(allow_external_connections=allow_external_connections)
# pylint: disable=invalid-name
@ -42,7 +42,7 @@ class Delete(Verb):
cc: List[str] = field(default_factory=lambda: [])
type: str = "Delete"
def action(self):
def action(self, allow_external_connections=True):
"""find and delete the activity object"""
if not self.object:
return
@ -52,7 +52,11 @@ class Delete(Verb):
model = apps.get_model("bookwyrm.User")
obj = model.find_existing_by_remote_id(self.object)
else:
obj = self.object.to_model(save=False, allow_create=False)
obj = self.object.to_model(
save=False,
allow_create=False,
allow_external_connections=allow_external_connections,
)
if obj:
obj.delete()
@ -67,11 +71,13 @@ class Update(Verb):
to: List[str]
type: str = "Update"
def action(self):
def action(self, allow_external_connections=True):
"""update a model instance from the dataclass"""
if not self.object:
return
self.object.to_model(allow_create=False)
self.object.to_model(
allow_create=False, allow_external_connections=allow_external_connections
)
@dataclass(init=False)
@ -80,10 +86,10 @@ class Undo(Verb):
type: str = "Undo"
def action(self):
def action(self, allow_external_connections=True):
"""find and remove the activity object"""
if isinstance(self.object, str):
# it may be that sometihng should be done with these, but idk what
# it may be that something should be done with these, but idk what
# this seems just to be coming from pleroma
return
@ -92,13 +98,28 @@ class Undo(Verb):
model = None
if self.object.type == "Follow":
model = apps.get_model("bookwyrm.UserFollows")
obj = self.object.to_model(model=model, save=False, allow_create=False)
obj = self.object.to_model(
model=model,
save=False,
allow_create=False,
allow_external_connections=allow_external_connections,
)
if not obj:
# this could be a folloq request not a follow proper
# this could be a follow request not a follow proper
model = apps.get_model("bookwyrm.UserFollowRequest")
obj = self.object.to_model(model=model, save=False, allow_create=False)
obj = self.object.to_model(
model=model,
save=False,
allow_create=False,
allow_external_connections=allow_external_connections,
)
else:
obj = self.object.to_model(model=model, save=False, allow_create=False)
obj = self.object.to_model(
model=model,
save=False,
allow_create=False,
allow_external_connections=allow_external_connections,
)
if not obj:
# if we don't have the object, we can't undo it. happens a lot with boosts
return
@ -112,9 +133,9 @@ class Follow(Verb):
object: str
type: str = "Follow"
def action(self):
def action(self, allow_external_connections=True):
"""relationship save"""
self.to_model()
self.to_model(allow_external_connections=allow_external_connections)
@dataclass(init=False)
@ -124,9 +145,9 @@ class Block(Verb):
object: str
type: str = "Block"
def action(self):
def action(self, allow_external_connections=True):
"""relationship save"""
self.to_model()
self.to_model(allow_external_connections=allow_external_connections)
@dataclass(init=False)
@ -136,7 +157,7 @@ class Accept(Verb):
object: Follow
type: str = "Accept"
def action(self):
def action(self, allow_external_connections=True):
"""accept a request"""
obj = self.object.to_model(save=False, allow_create=True)
obj.accept()
@ -149,10 +170,20 @@ class Reject(Verb):
object: Follow
type: str = "Reject"
def action(self):
"""reject a follow request"""
obj = self.object.to_model(save=False, allow_create=False)
obj.reject()
def action(self, allow_external_connections=True):
"""reject a follow or follow request"""
for model_name in ["UserFollowRequest", "UserFollows", None]:
model = apps.get_model(f"bookwyrm.{model_name}") if model_name else None
if obj := self.object.to_model(
model=model,
save=False,
allow_create=False,
allow_external_connections=allow_external_connections,
):
# Reject the first model that can be built.
obj.reject()
break
@dataclass(init=False)
@ -163,7 +194,7 @@ class Add(Verb):
object: CollectionItem
type: str = "Add"
def action(self):
def action(self, allow_external_connections=True):
"""figure out the target to assign the item to a collection"""
target = resolve_remote_id(self.target)
item = self.object.to_model(save=False)
@ -177,7 +208,7 @@ class Remove(Add):
type: str = "Remove"
def action(self):
def action(self, allow_external_connections=True):
"""find and remove the activity object"""
obj = self.object.to_model(save=False, allow_create=False)
if obj:
@ -191,9 +222,9 @@ class Like(Verb):
object: str
type: str = "Like"
def action(self):
def action(self, allow_external_connections=True):
"""like"""
self.to_model()
self.to_model(allow_external_connections=allow_external_connections)
# pylint: disable=invalid-name
@ -207,6 +238,33 @@ class Announce(Verb):
object: str
type: str = "Announce"
def action(self):
def action(self, allow_external_connections=True):
"""boost"""
self.to_model()
self.to_model(allow_external_connections=allow_external_connections)
@dataclass(init=False)
class Move(Verb):
"""a user moving an object"""
object: str
type: str = "Move"
origin: str = None
target: str = None
def action(self, allow_external_connections=True):
"""move"""
object_is_user = resolve_remote_id(remote_id=self.object, model="User")
if object_is_user:
model = apps.get_model("bookwyrm.MoveUser")
self.to_model(
model=model,
save=True,
allow_external_connections=allow_external_connections,
)
else:
# we might do something with this to move other objects at some point
pass

View file

@ -4,27 +4,32 @@ from django.dispatch import receiver
from django.db import transaction
from django.db.models import signals, Q
from django.utils import timezone
from opentelemetry import trace
from bookwyrm import models
from bookwyrm.redis_store import RedisStore, r
from bookwyrm.tasks import app, LOW, MEDIUM, HIGH
from bookwyrm.tasks import app, STREAMS, IMPORT_TRIGGERED
from bookwyrm.telemetry import open_telemetry
tracer = open_telemetry.tracer()
class ActivityStream(RedisStore):
"""a category of activity stream (like home, local, books)"""
def stream_id(self, user):
def stream_id(self, user_id):
"""the redis key for this user's instance of this stream"""
return f"{user.id}-{self.key}"
return f"{user_id}-{self.key}"
def unread_id(self, user):
def unread_id(self, user_id):
"""the redis key for this user's unread count for this stream"""
stream_id = self.stream_id(user)
stream_id = self.stream_id(user_id)
return f"{stream_id}-unread"
def unread_by_status_type_id(self, user):
def unread_by_status_type_id(self, user_id):
"""the redis key for this user's unread count for this stream"""
stream_id = self.stream_id(user)
stream_id = self.stream_id(user_id)
return f"{stream_id}-unread-by-type"
def get_rank(self, obj): # pylint: disable=no-self-use
@ -33,16 +38,19 @@ class ActivityStream(RedisStore):
def add_status(self, status, increment_unread=False):
"""add a status to users' feeds"""
audience = self.get_audience(status)
# the pipeline contains all the add-to-stream activities
pipeline = self.add_object_to_related_stores(status, execute=False)
pipeline = self.add_object_to_stores(
status, self.get_stores_for_users(audience), execute=False
)
if increment_unread:
for user in self.get_audience(status):
for user_id in audience:
# add to the unread status count
pipeline.incr(self.unread_id(user))
pipeline.incr(self.unread_id(user_id))
# add to the unread status count for status type
pipeline.hincrby(
self.unread_by_status_type_id(user), get_status_type(status), 1
self.unread_by_status_type_id(user_id), get_status_type(status), 1
)
# and go!
@ -52,21 +60,21 @@ class ActivityStream(RedisStore):
"""add a user's statuses to another user's feed"""
# only add the statuses that the viewer should be able to see (ie, not dms)
statuses = models.Status.privacy_filter(viewer).filter(user=user)
self.bulk_add_objects_to_store(statuses, self.stream_id(viewer))
self.bulk_add_objects_to_store(statuses, self.stream_id(viewer.id))
def remove_user_statuses(self, viewer, user):
"""remove a user's status from another user's feed"""
# remove all so that followers only statuses are removed
statuses = user.status_set.all()
self.bulk_remove_objects_from_store(statuses, self.stream_id(viewer))
self.bulk_remove_objects_from_store(statuses, self.stream_id(viewer.id))
def get_activity_stream(self, user):
"""load the statuses to be displayed"""
# clear unreads for this feed
r.set(self.unread_id(user), 0)
r.delete(self.unread_by_status_type_id(user))
r.set(self.unread_id(user.id), 0)
r.delete(self.unread_by_status_type_id(user.id))
statuses = self.get_store(self.stream_id(user))
statuses = self.get_store(self.stream_id(user.id))
return (
models.Status.objects.select_subclasses()
.filter(id__in=statuses)
@ -83,11 +91,11 @@ class ActivityStream(RedisStore):
def get_unread_count(self, user):
"""get the unread status count for this user's feed"""
return int(r.get(self.unread_id(user)) or 0)
return int(r.get(self.unread_id(user.id)) or 0)
def get_unread_count_by_status_type(self, user):
"""get the unread status count for this user's feed's status types"""
status_types = r.hgetall(self.unread_by_status_type_id(user))
status_types = r.hgetall(self.unread_by_status_type_id(user.id))
return {
str(key.decode("utf-8")): int(value) or 0
for key, value in status_types.items()
@ -95,13 +103,20 @@ class ActivityStream(RedisStore):
def populate_streams(self, user):
"""go from zero to a timeline"""
self.populate_store(self.stream_id(user))
self.populate_store(self.stream_id(user.id))
def get_audience(self, status): # pylint: disable=no-self-use
"""given a status, what users should see it"""
# direct messages don't appeard in feeds, direct comments/reviews/etc do
@tracer.start_as_current_span("ActivityStream._get_audience")
def _get_audience(self, status): # pylint: disable=no-self-use
"""given a status, what users should see it, excluding the author"""
trace.get_current_span().set_attribute("status_type", status.status_type)
trace.get_current_span().set_attribute("status_privacy", status.privacy)
trace.get_current_span().set_attribute(
"status_reply_parent_privacy",
status.reply_parent.privacy if status.reply_parent else status.privacy,
)
# direct messages don't appear in feeds, direct comments/reviews/etc do
if status.privacy == "direct" and status.status_type == "Note":
return []
return models.User.objects.none()
# everybody who could plausibly see this status
audience = models.User.objects.filter(
@ -114,19 +129,38 @@ class ActivityStream(RedisStore):
# only visible to the poster and mentioned users
if status.privacy == "direct":
audience = audience.filter(
Q(id=status.user.id) # if the user is the post's author
| Q(id__in=status.mention_users.all()) # if the user is mentioned
Q(id__in=status.mention_users.all()) # if the user is mentioned
)
# don't show replies to statuses the user can't see
elif status.reply_parent and status.reply_parent.privacy == "followers":
audience = audience.filter(
Q(id=status.reply_parent.user.id) # if the user is the OG author
| (
Q(following=status.user) & Q(following=status.reply_parent.user)
) # if the user is following both authors
)
# only visible to the poster's followers and tagged users
elif status.privacy == "followers":
audience = audience.filter(
Q(id=status.user.id) # if the user is the post's author
| Q(following=status.user) # if the user is following the author
Q(following=status.user) # if the user is following the author
)
return audience.distinct()
return audience.distinct("id")
def get_stores_for_object(self, obj):
return [self.stream_id(u) for u in self.get_audience(obj)]
@tracer.start_as_current_span("ActivityStream.get_audience")
def get_audience(self, status):
"""given a status, what users should see it"""
trace.get_current_span().set_attribute("stream_id", self.key)
audience = self._get_audience(status).values_list("id", flat=True)
status_author = models.User.objects.filter(
is_active=True, local=True, id=status.user.id
).values_list("id", flat=True)
return list(set(audience) | set(status_author))
def get_stores_for_users(self, user_ids):
"""convert a list of user ids into redis store ids"""
return [self.stream_id(user_id) for user_id in user_ids]
def get_statuses_for_user(self, user): # pylint: disable=no-self-use
"""given a user, what statuses should they see on this stream"""
@ -145,14 +179,17 @@ class HomeStream(ActivityStream):
key = "home"
@tracer.start_as_current_span("HomeStream.get_audience")
def get_audience(self, status):
audience = super().get_audience(status)
if not audience:
return []
return audience.filter(
Q(id=status.user.id) # if the user is the post's author
| Q(following=status.user) # if the user is following the author
).distinct()
trace.get_current_span().set_attribute("stream_id", self.key)
audience = super()._get_audience(status)
# if the user is following the author
audience = audience.filter(following=status.user).values_list("id", flat=True)
# if the user is the post's author
status_author = models.User.objects.filter(
is_active=True, local=True, id=status.user.id
).values_list("id", flat=True)
return list(set(audience) | set(status_author))
def get_statuses_for_user(self, user):
return models.Status.privacy_filter(
@ -191,8 +228,18 @@ class BooksStream(ActivityStream):
key = "books"
def get_audience(self, status):
def _get_audience(self, status):
"""anyone with the mentioned book on their shelves"""
work = (
status.book.parent_work
if hasattr(status, "book")
else status.mention_books.first().parent_work
)
audience = super()._get_audience(status)
return audience.filter(shelfbook__book__parent_work=work)
def get_audience(self, status):
# only show public statuses on the books feed,
# and only statuses that mention books
if status.privacy != "public" or not (
@ -200,16 +247,7 @@ class BooksStream(ActivityStream):
):
return []
work = (
status.book.parent_work
if hasattr(status, "book")
else status.mention_books.first().parent_work
)
audience = super().get_audience(status)
if not audience:
return []
return audience.filter(shelfbook__book__parent_work=work).distinct()
return super().get_audience(status)
def get_statuses_for_user(self, user):
"""any public status that mentions the user's books"""
@ -233,38 +271,38 @@ class BooksStream(ActivityStream):
def add_book_statuses(self, user, book):
"""add statuses about a book to a user's feed"""
work = book.parent_work
statuses = (
models.Status.privacy_filter(
user,
privacy_levels=["public"],
)
.filter(
Q(comment__book__parent_work=work)
| Q(quotation__book__parent_work=work)
| Q(review__book__parent_work=work)
| Q(mention_books__parent_work=work)
)
.distinct()
statuses = models.Status.privacy_filter(
user,
privacy_levels=["public"],
)
self.bulk_add_objects_to_store(statuses, self.stream_id(user))
book_comments = statuses.filter(Q(comment__book__parent_work=work))
book_quotations = statuses.filter(Q(quotation__book__parent_work=work))
book_reviews = statuses.filter(Q(review__book__parent_work=work))
book_mentions = statuses.filter(Q(mention_books__parent_work=work))
self.bulk_add_objects_to_store(book_comments, self.stream_id(user.id))
self.bulk_add_objects_to_store(book_quotations, self.stream_id(user.id))
self.bulk_add_objects_to_store(book_reviews, self.stream_id(user.id))
self.bulk_add_objects_to_store(book_mentions, self.stream_id(user.id))
def remove_book_statuses(self, user, book):
"""add statuses about a book to a user's feed"""
work = book.parent_work
statuses = (
models.Status.privacy_filter(
user,
privacy_levels=["public"],
)
.filter(
Q(comment__book__parent_work=work)
| Q(quotation__book__parent_work=work)
| Q(review__book__parent_work=work)
| Q(mention_books__parent_work=work)
)
.distinct()
statuses = models.Status.privacy_filter(
user,
privacy_levels=["public"],
)
self.bulk_remove_objects_from_store(statuses, self.stream_id(user))
book_comments = statuses.filter(Q(comment__book__parent_work=work))
book_quotations = statuses.filter(Q(quotation__book__parent_work=work))
book_reviews = statuses.filter(Q(review__book__parent_work=work))
book_mentions = statuses.filter(Q(mention_books__parent_work=work))
self.bulk_remove_objects_from_store(book_comments, self.stream_id(user.id))
self.bulk_remove_objects_from_store(book_quotations, self.stream_id(user.id))
self.bulk_remove_objects_from_store(book_reviews, self.stream_id(user.id))
self.bulk_remove_objects_from_store(book_mentions, self.stream_id(user.id))
# determine which streams are enabled in settings.py
@ -287,6 +325,11 @@ def add_status_on_create(sender, instance, created, *args, **kwargs):
remove_status_task.delay(instance.id)
return
# We don't want to create multiple add_status_tasks for each status, and because
# the transactions are atomic, on_commit won't run until the status is ready to add.
if not created:
return
# when creating new things, gotta wait on the transaction
transaction.on_commit(
lambda: add_status_on_create_command(sender, instance, created)
@ -295,13 +338,21 @@ def add_status_on_create(sender, instance, created, *args, **kwargs):
def add_status_on_create_command(sender, instance, created):
"""runs this code only after the database commit completes"""
priority = HIGH
# boosts trigger 'saves" twice, so don't bother duplicating the task
if sender == models.Boost and not created:
return
priority = STREAMS
# check if this is an old status, de-prioritize if so
# (this will happen if federation is very slow, or, more expectedly, on csv import)
if instance.published_date < timezone.now() - timedelta(
days=1
) or instance.created_date < instance.published_date - timedelta(days=1):
priority = LOW
# 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 = IMPORT_TRIGGERED
add_status_task.apply_async(
args=(instance.id,),
@ -445,7 +496,7 @@ def remove_statuses_on_unshelve(sender, instance, *args, **kwargs):
# ---- TASKS
@app.task(queue=LOW)
@app.task(queue=STREAMS)
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)
@ -453,7 +504,7 @@ def add_book_statuses_task(user_id, book_id):
BooksStream().add_book_statuses(user, book)
@app.task(queue=LOW)
@app.task(queue=STREAMS)
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)
@ -461,7 +512,7 @@ def remove_book_statuses_task(user_id, book_id):
BooksStream().remove_book_statuses(user, book)
@app.task(queue=MEDIUM)
@app.task(queue=STREAMS)
def populate_stream_task(stream, user_id):
"""background task for populating an empty activitystream"""
user = models.User.objects.get(id=user_id)
@ -469,7 +520,7 @@ def populate_stream_task(stream, user_id):
stream.populate_streams(user)
@app.task(queue=MEDIUM)
@app.task(queue=STREAMS)
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
@ -479,10 +530,12 @@ def remove_status_task(status_ids):
for stream in streams.values():
for status in statuses:
stream.remove_object_from_related_stores(status)
stream.remove_object_from_stores(
status, stream.get_stores_for_users(stream.get_audience(status))
)
@app.task(queue=HIGH)
@app.task(queue=STREAMS)
def add_status_task(status_id, increment_unread=False):
"""add a status to any stream it should be in"""
status = models.Status.objects.select_subclasses().get(id=status_id)
@ -494,7 +547,7 @@ def add_status_task(status_id, increment_unread=False):
stream.add_status(status, increment_unread=increment_unread)
@app.task(queue=MEDIUM)
@app.task(queue=STREAMS)
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()
@ -504,7 +557,7 @@ def remove_user_statuses_task(viewer_id, user_id, stream_list=None):
stream.remove_user_statuses(viewer, user)
@app.task(queue=MEDIUM)
@app.task(queue=STREAMS)
def add_user_statuses_task(viewer_id, user_id, stream_list=None):
"""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()
@ -514,7 +567,7 @@ def add_user_statuses_task(viewer_id, user_id, stream_list=None):
stream.add_user_statuses(viewer, user)
@app.task(queue=MEDIUM)
@app.task(queue=STREAMS)
def handle_boost_task(boost_id):
"""remove the original post and other, earlier boosts"""
instance = models.Status.objects.get(id=boost_id)
@ -528,10 +581,10 @@ def handle_boost_task(boost_id):
for stream in streams.values():
# people who should see the boost (not people who see the original status)
audience = stream.get_stores_for_object(instance)
stream.remove_object_from_related_stores(boosted, stores=audience)
audience = stream.get_stores_for_users(stream.get_audience(instance))
stream.remove_object_from_stores(boosted, audience)
for status in old_versions:
stream.remove_object_from_related_stores(status, stores=audience)
stream.remove_object_from_stores(status, audience)
def get_status_type(status):

View file

@ -1,4 +1,5 @@
"""Do further startup configuration and initialization"""
import os
import urllib
import logging
@ -14,16 +15,16 @@ def download_file(url, destination):
"""Downloads a file to the given path"""
try:
# Ensure our destination directory exists
os.makedirs(os.path.dirname(destination))
os.makedirs(os.path.dirname(destination), exist_ok=True)
with urllib.request.urlopen(url) as stream:
with open(destination, "b+w") as outfile:
outfile.write(stream.read())
except (urllib.error.HTTPError, urllib.error.URLError):
logger.info("Failed to download file %s", url)
except OSError:
logger.info("Couldn't open font file %s for writing", destination)
except: # pylint: disable=bare-except
logger.info("Unknown error in file download")
except (urllib.error.HTTPError, urllib.error.URLError) as err:
logger.error("Failed to download file %s: %s", url, err)
except OSError as err:
logger.error("Couldn't open font file %s for writing: %s", destination, err)
except Exception as err: # pylint:disable=broad-except
logger.error("Unknown error in file download: %s", err)
class BookwyrmConfig(AppConfig):
@ -35,11 +36,12 @@ class BookwyrmConfig(AppConfig):
# pylint: disable=no-self-use
def ready(self):
"""set up OTLP and preview image files, if desired"""
if settings.OTEL_EXPORTER_OTLP_ENDPOINT:
if settings.OTEL_EXPORTER_OTLP_ENDPOINT or settings.OTEL_EXPORTER_CONSOLE:
# pylint: disable=import-outside-toplevel
from bookwyrm.telemetry import open_telemetry
open_telemetry.instrumentDjango()
open_telemetry.instrumentPostgres()
if settings.ENABLE_PREVIEW_IMAGES and settings.FONTS:
# Download any fonts that we don't have yet

View file

@ -1,27 +1,69 @@
""" using a bookwyrm instance as a source of book data """
from __future__ import annotations
from dataclasses import asdict, dataclass
from functools import reduce
import operator
from typing import Optional, Union, Any, Literal, overload
from django.contrib.postgres.search import SearchRank, SearchQuery
from django.db.models import OuterRef, Subquery, F, Q
from django.db.models import F, Q
from django.db.models.query import QuerySet
from bookwyrm import models
from bookwyrm import connectors
from bookwyrm.settings import MEDIA_FULL_URL
@overload
def search(
query: str,
*,
min_confidence: float = 0,
filters: Optional[list[Any]] = None,
return_first: Literal[False],
) -> QuerySet[models.Edition]:
...
@overload
def search(
query: str,
*,
min_confidence: float = 0,
filters: Optional[list[Any]] = None,
return_first: Literal[True],
) -> Optional[models.Edition]:
...
# pylint: disable=arguments-differ
def search(query, min_confidence=0, filters=None, return_first=False):
def search(
query: str,
*,
min_confidence: float = 0,
filters: Optional[list[Any]] = None,
return_first: bool = False,
books: Optional[QuerySet[models.Edition]] = None,
) -> Union[Optional[models.Edition], QuerySet[models.Edition]]:
"""search your local database"""
filters = filters or []
if not query:
return []
# first, try searching unqiue identifiers
results = search_identifiers(query, *filters, return_first=return_first)
return None if return_first else []
query = query.strip()
results = None
# first, try searching unique identifiers
# unique identifiers never have spaces, title/author usually do
if not " " in query:
results = search_identifiers(
query, *filters, return_first=return_first, books=books
)
# if there were no identifier results...
if not results:
# then try searching title/author
results = search_title_author(
query, min_confidence, *filters, return_first=return_first
query, min_confidence, *filters, return_first=return_first, books=books
)
return results
@ -30,26 +72,14 @@ def isbn_search(query):
"""search your local database"""
if not query:
return []
# Up-case the ISBN string to ensure any 'X' check-digit is correct
# If the ISBN has only 9 characters, prepend missing zero
query = query.strip().upper().rjust(10, "0")
filters = [{f: query} for f in ["isbn_10", "isbn_13"]]
results = models.Edition.objects.filter(
return models.Edition.objects.filter(
reduce(operator.or_, (Q(**f) for f in filters))
).distinct()
# when there are multiple editions of the same work, pick the default.
# it would be odd for this to happen.
default_editions = models.Edition.objects.filter(
parent_work=OuterRef("parent_work")
).order_by("-edition_rank")
results = (
results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter(
default_id=F("id")
)
or results
)
return results
def format_search_result(search_result):
"""convert a book object into a search result object"""
@ -70,62 +100,65 @@ def format_search_result(search_result):
).json()
def search_identifiers(query, *filters, return_first=False):
"""tries remote_id, isbn; defined as dedupe fields on the model"""
def search_identifiers(
query,
*filters,
return_first=False,
books=None,
) -> Union[Optional[models.Edition], QuerySet[models.Edition]]:
"""search Editions by deduplication fields
Best for cases when we can assume someone is searching for an exact match on
commonly unique data identifiers like isbn or specific library ids.
"""
books = books or models.Edition.objects
if connectors.maybe_isbn(query):
# Oh did you think the 'S' in ISBN stood for 'standard'?
normalized_isbn = query.strip().upper().rjust(10, "0")
query = normalized_isbn
# pylint: disable=W0212
or_filters = [
{f.name: query}
for f in models.Edition._meta.get_fields()
if hasattr(f, "deduplication_field") and f.deduplication_field
]
results = models.Edition.objects.filter(
results = books.filter(
*filters, reduce(operator.or_, (Q(**f) for f in or_filters))
).distinct()
if results.count() <= 1:
if return_first:
return results.first()
return results
# when there are multiple editions of the same work, pick the default.
# it would be odd for this to happen.
default_editions = models.Edition.objects.filter(
parent_work=OuterRef("parent_work")
).order_by("-edition_rank")
results = (
results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter(
default_id=F("id")
)
or results
)
if return_first:
return results.first()
return results
def search_title_author(query, min_confidence, *filters, return_first=False):
def search_title_author(
query,
min_confidence,
*filters,
return_first=False,
books=None,
) -> QuerySet[models.Edition]:
"""searches for title and author"""
books = books or models.Edition.objects
query = SearchQuery(query, config="simple") | SearchQuery(query, config="english")
results = (
models.Edition.objects.filter(*filters, search_vector=query)
books.filter(*filters, search_vector=query)
.annotate(rank=SearchRank(F("search_vector"), query))
.filter(rank__gt=min_confidence)
.order_by("-rank")
)
# when there are multiple editions of the same work, pick the closest
editions_of_work = results.values("parent_work__id").values_list("parent_work__id")
editions_of_work = results.values_list("parent_work__id", flat=True).distinct()
# filter out multiple editions of the same work
list_results = []
for work_id in set(editions_of_work):
editions = results.filter(parent_work=work_id)
default = editions.order_by("-edition_rank").first()
default_rank = default.rank if default else 0
# if mutliple books have the top rank, pick the default edition
if default_rank == editions.first().rank:
result = default
else:
result = editions.first()
for work_id in editions_of_work[:30]:
result = (
results.filter(parent_work=work_id)
.order_by("-rank", "-edition_rank")
.first()
)
if return_first:
return result
@ -140,11 +173,11 @@ class SearchResult:
title: str
key: str
connector: object
view_link: str = None
author: str = None
year: str = None
cover: str = None
confidence: int = 1
view_link: Optional[str] = None
author: Optional[str] = None
year: Optional[str] = None
cover: Optional[str] = None
confidence: float = 1.0
def __repr__(self):
# pylint: disable=consider-using-f-string

View file

@ -1,6 +1,6 @@
""" bring connectors into the namespace """
from .settings import CONNECTORS
from .abstract_connector import ConnectorException
from .abstract_connector import get_data, get_image
from .abstract_connector import get_data, get_image, maybe_isbn
from .connector_manager import search, first_search_result

View file

@ -1,89 +1,153 @@
""" functionality outline for a book data connector """
from __future__ import annotations
from abc import ABC, abstractmethod
import imghdr
from typing import Optional, TypedDict, Any, Callable, Union, Iterator
from urllib.parse import quote_plus
# pylint: disable-next=deprecated-module
import imghdr # Deprecated in 3.11 for removal in 3.13; no good alternative yet
import logging
import re
import asyncio
import requests
from requests.exceptions import RequestException
import aiohttp
from django.core.files.base import ContentFile
from django.db import transaction
import requests
from requests.exceptions import RequestException
from bookwyrm import activitypub, models, settings
from bookwyrm.settings import USER_AGENT
from .connector_manager import load_more_data, ConnectorException, raise_not_valid_url
from .format_mappings import format_mappings
from ..book_search import SearchResult
logger = logging.getLogger(__name__)
JsonDict = dict[str, Any]
class ConnectorResults(TypedDict):
"""TypedDict for results returned by connector"""
connector: AbstractMinimalConnector
results: list[SearchResult]
class AbstractMinimalConnector(ABC):
"""just the bare bones, for other bookwyrm instances"""
def __init__(self, identifier):
def __init__(self, identifier: str):
# load connector settings
info = models.Connector.objects.get(identifier=identifier)
self.connector = info
# the things in the connector model to copy over
self_fields = [
"base_url",
"books_url",
"covers_url",
"search_url",
"isbn_search_url",
"name",
"identifier",
]
for field in self_fields:
setattr(self, field, getattr(info, field))
self.base_url = info.base_url
self.books_url = info.books_url
self.covers_url = info.covers_url
self.search_url = info.search_url
self.isbn_search_url = info.isbn_search_url
self.name = info.name
self.identifier = info.identifier
def get_search_url(self, query):
def get_search_url(self, query: str) -> str:
"""format the query url"""
# Check if the query resembles an ISBN
if maybe_isbn(query) and self.isbn_search_url and self.isbn_search_url != "":
return f"{self.isbn_search_url}{query}"
# Up-case the ISBN string to ensure any 'X' check-digit is correct
# If the ISBN has only 9 characters, prepend missing zero
normalized_query = query.strip().upper().rjust(10, "0")
return f"{self.isbn_search_url}{normalized_query}"
# NOTE: previously, we tried searching isbn and if that produces no results,
# searched as free text. This, instead, only searches isbn if it's isbn-y
return f"{self.search_url}{query}"
return f"{self.search_url}{quote_plus(query)}"
def process_search_response(self, query, data, min_confidence):
"""Format the search results based on the formt of the query"""
def process_search_response(
self, query: str, data: Any, min_confidence: float
) -> list[SearchResult]:
"""Format the search results based on the format of the query"""
if maybe_isbn(query):
return list(self.parse_isbn_search_data(data))[:10]
return list(self.parse_search_data(data, min_confidence))[:10]
async def get_results(
self,
session: aiohttp.ClientSession,
url: str,
min_confidence: float,
query: str,
) -> Optional[ConnectorResults]:
"""try this specific connector"""
# pylint: disable=line-too-long
headers = {
"Accept": (
'application/json, application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8'
),
"User-Agent": USER_AGENT,
}
params = {"min_confidence": min_confidence}
try:
async with session.get(url, headers=headers, params=params) as response:
if not response.ok:
logger.info("Unable to connect to %s: %s", url, response.reason)
return None
try:
raw_data = await response.json()
except aiohttp.client_exceptions.ContentTypeError as err:
logger.exception(err)
return None
return ConnectorResults(
connector=self,
results=self.process_search_response(
query, raw_data, min_confidence
),
)
except asyncio.TimeoutError:
logger.info("Connection timed out for url: %s", url)
except aiohttp.ClientError as err:
logger.info(err)
return None
@abstractmethod
def get_or_create_book(self, remote_id):
def get_or_create_book(self, remote_id: str) -> Optional[models.Book]:
"""pull up a book record by whatever means possible"""
@abstractmethod
def parse_search_data(self, data, min_confidence):
def parse_search_data(
self, data: Any, min_confidence: float
) -> Iterator[SearchResult]:
"""turn the result json from a search into a list"""
@abstractmethod
def parse_isbn_search_data(self, data):
def parse_isbn_search_data(self, data: Any) -> Iterator[SearchResult]:
"""turn the result json from a search into a list"""
class AbstractConnector(AbstractMinimalConnector):
"""generic book data connector"""
def __init__(self, identifier):
generated_remote_link_field = ""
def __init__(self, identifier: str):
super().__init__(identifier)
# fields we want to look for in book data to copy over
# title we handle separately.
self.book_mappings = []
self.book_mappings: list[Mapping] = []
self.author_mappings: list[Mapping] = []
def get_or_create_book(self, remote_id):
def get_or_create_book(self, remote_id: str) -> Optional[models.Book]:
"""translate arbitrary json into an Activitypub dataclass"""
# first, check if we have the origin_id saved
existing = models.Edition.find_existing_by_remote_id(
remote_id
) or models.Work.find_existing_by_remote_id(remote_id)
if existing:
if hasattr(existing, "default_edition"):
if hasattr(existing, "default_edition") and isinstance(
existing.default_edition, models.Edition
):
return existing.default_edition
return existing
@ -115,6 +179,9 @@ class AbstractConnector(AbstractMinimalConnector):
)
# this will dedupe automatically
work = work_activity.to_model(model=models.Work, overwrite=False)
if not work:
return None
for author in self.get_authors_from_data(work_data):
work.authors.add(author)
@ -122,12 +189,21 @@ class AbstractConnector(AbstractMinimalConnector):
load_more_data.delay(self.connector.id, work.id)
return edition
def get_book_data(self, remote_id): # pylint: disable=no-self-use
def get_book_data(self, remote_id: str) -> JsonDict: # pylint: disable=no-self-use
"""this allows connectors to override the default behavior"""
return get_data(remote_id)
def create_edition_from_data(self, work, edition_data, instance=None):
def create_edition_from_data(
self,
work: models.Work,
edition_data: Union[str, JsonDict],
instance: Optional[models.Edition] = None,
) -> Optional[models.Edition]:
"""if we already have the work, we're ready"""
if isinstance(edition_data, str):
# We don't expect a string here
return None
mapped_data = dict_from_mappings(edition_data, self.book_mappings)
mapped_data["work"] = work.remote_id
edition_activity = activitypub.Edition(**mapped_data)
@ -135,6 +211,9 @@ class AbstractConnector(AbstractMinimalConnector):
model=models.Edition, overwrite=False, instance=instance
)
if not edition:
return None
# if we're updating an existing instance, we don't need to load authors
if instance:
return edition
@ -151,7 +230,9 @@ class AbstractConnector(AbstractMinimalConnector):
return edition
def get_or_create_author(self, remote_id, instance=None):
def get_or_create_author(
self, remote_id: str, instance: Optional[models.Author] = None
) -> Optional[models.Author]:
"""load that author"""
if not instance:
existing = models.Author.find_existing_by_remote_id(remote_id)
@ -171,46 +252,51 @@ class AbstractConnector(AbstractMinimalConnector):
model=models.Author, overwrite=False, instance=instance
)
def get_remote_id_from_model(self, obj):
def get_remote_id_from_model(self, obj: models.BookDataModel) -> Optional[str]:
"""given the data stored, how can we look this up"""
return getattr(obj, getattr(self, "generated_remote_link_field"))
remote_id: Optional[str] = getattr(obj, self.generated_remote_link_field)
return remote_id
def update_author_from_remote(self, obj):
def update_author_from_remote(self, obj: models.Author) -> Optional[models.Author]:
"""load the remote data from this connector and add it to an existing author"""
remote_id = self.get_remote_id_from_model(obj)
if not remote_id:
return None
return self.get_or_create_author(remote_id, instance=obj)
def update_book_from_remote(self, obj):
def update_book_from_remote(self, obj: models.Edition) -> Optional[models.Edition]:
"""load the remote data from this connector and add it to an existing book"""
remote_id = self.get_remote_id_from_model(obj)
if not remote_id:
return None
data = self.get_book_data(remote_id)
return self.create_edition_from_data(obj.parent_work, data, instance=obj)
@abstractmethod
def is_work_data(self, data):
def is_work_data(self, data: JsonDict) -> bool:
"""differentiate works and editions"""
@abstractmethod
def get_edition_from_work_data(self, data):
def get_edition_from_work_data(self, data: JsonDict) -> JsonDict:
"""every work needs at least one edition"""
@abstractmethod
def get_work_from_edition_data(self, data):
def get_work_from_edition_data(self, data: JsonDict) -> JsonDict:
"""every edition needs a work"""
@abstractmethod
def get_authors_from_data(self, data):
def get_authors_from_data(self, data: JsonDict) -> Iterator[models.Author]:
"""load author data"""
@abstractmethod
def expand_book_data(self, book):
def expand_book_data(self, book: models.Book) -> None:
"""get more info on a book"""
def dict_from_mappings(data, mappings):
def dict_from_mappings(data: JsonDict, mappings: list[Mapping]) -> JsonDict:
"""create a dict in Activitypub format, using mappings supplies by
the subclass"""
result = {}
result: JsonDict = {}
for mapping in mappings:
# sometimes there are multiple mappings for one field, don't
# overwrite earlier writes in that case
@ -220,7 +306,11 @@ def dict_from_mappings(data, mappings):
return result
def get_data(url, params=None, timeout=10):
def get_data(
url: str,
params: Optional[dict[str, str]] = None,
timeout: int = settings.QUERY_TIMEOUT,
) -> JsonDict:
"""wrapper for request.get"""
# check if the url is blocked
raise_not_valid_url(url)
@ -242,17 +332,26 @@ def get_data(url, params=None, timeout=10):
raise ConnectorException(err)
if not resp.ok:
raise ConnectorException()
if resp.status_code == 401:
# this is probably an AUTHORIZED_FETCH issue
resp.raise_for_status()
else:
raise ConnectorException()
try:
data = resp.json()
except ValueError as err:
logger.info(err)
raise ConnectorException(err)
if not isinstance(data, dict):
raise ConnectorException("Unexpected data format")
return data
def get_image(url, timeout=10):
def get_image(
url: str, timeout: int = 10
) -> Union[tuple[ContentFile[bytes], str], tuple[None, None]]:
"""wrapper for requesting an image"""
raise_not_valid_url(url)
try:
@ -282,14 +381,19 @@ def get_image(url, timeout=10):
class Mapping:
"""associate a local database field with a field in an external dataset"""
def __init__(self, local_field, remote_field=None, formatter=None):
def __init__(
self,
local_field: str,
remote_field: Optional[str] = None,
formatter: Optional[Callable[[Any], Any]] = None,
):
noop = lambda x: x
self.local_field = local_field
self.remote_field = remote_field or local_field
self.formatter = formatter or noop
def get_value(self, data):
def get_value(self, data: JsonDict) -> Optional[Any]:
"""pull a field from incoming json and return the formatted version"""
value = data.get(self.remote_field)
if not value:
@ -300,7 +404,7 @@ class Mapping:
return None
def infer_physical_format(format_text):
def infer_physical_format(format_text: str) -> Optional[str]:
"""try to figure out what the standardized format is from the free value"""
format_text = format_text.lower()
if format_text in format_mappings:
@ -313,8 +417,8 @@ def infer_physical_format(format_text):
return matches[0]
def unique_physical_format(format_text):
"""only store the format if it isn't diretly in the format mappings"""
def unique_physical_format(format_text: str) -> Optional[str]:
"""only store the format if it isn't directly in the format mappings"""
format_text = format_text.lower()
if format_text in format_mappings:
# try a direct match, so saving this would be redundant
@ -322,7 +426,14 @@ def unique_physical_format(format_text):
return format_text
def maybe_isbn(query):
def maybe_isbn(query: str) -> bool:
"""check if a query looks like an isbn"""
isbn = re.sub(r"[\W_]", "", query) # removes filler characters
return len(isbn) in [10, 13] # ISBN10 or ISBN13
# ISBNs must be numeric except an ISBN10 checkdigit can be 'X'
if not isbn.upper().rstrip("X").isnumeric():
return False
return len(isbn) in [
9,
10,
13,
] # ISBN10 or ISBN13, or maybe ISBN10 missing a leading zero

View file

@ -1,4 +1,7 @@
""" using another bookwyrm instance as a source of book data """
from __future__ import annotations
from typing import Any, Iterator
from bookwyrm import activitypub, models
from bookwyrm.book_search import SearchResult
from .abstract_connector import AbstractMinimalConnector
@ -7,15 +10,19 @@ from .abstract_connector import AbstractMinimalConnector
class Connector(AbstractMinimalConnector):
"""this is basically just for search"""
def get_or_create_book(self, remote_id):
def get_or_create_book(self, remote_id: str) -> models.Edition:
return activitypub.resolve_remote_id(remote_id, model=models.Edition)
def parse_search_data(self, data, min_confidence):
def parse_search_data(
self, data: list[dict[str, Any]], min_confidence: float
) -> Iterator[SearchResult]:
for search_result in data:
search_result["connector"] = self
yield SearchResult(**search_result)
def parse_isbn_search_data(self, data):
def parse_isbn_search_data(
self, data: list[dict[str, Any]]
) -> Iterator[SearchResult]:
for search_result in data:
search_result["connector"] = self
yield SearchResult(**search_result)

View file

@ -1,8 +1,11 @@
""" interface with whatever connectors the app has """
from __future__ import annotations
import asyncio
import importlib
import ipaddress
import logging
from asyncio import Future
from typing import Iterator, Any, Optional, Union, overload, Literal
from urllib.parse import urlparse
import aiohttp
@ -12,8 +15,10 @@ from django.db.models import signals
from requests import HTTPError
from bookwyrm import book_search, models
from bookwyrm.settings import SEARCH_TIMEOUT, USER_AGENT
from bookwyrm.tasks import app
from bookwyrm.book_search import SearchResult
from bookwyrm.connectors import abstract_connector
from bookwyrm.settings import SEARCH_TIMEOUT
from bookwyrm.tasks import app, CONNECTORS
logger = logging.getLogger(__name__)
@ -22,61 +27,46 @@ class ConnectorException(HTTPError):
"""when the connector can't do what was asked"""
async def get_results(session, url, min_confidence, query, connector):
"""try this specific connector"""
# pylint: disable=line-too-long
headers = {
"Accept": (
'application/json, application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"; charset=utf-8'
),
"User-Agent": USER_AGENT,
}
params = {"min_confidence": min_confidence}
try:
async with session.get(url, headers=headers, params=params) as response:
if not response.ok:
logger.info("Unable to connect to %s: %s", url, response.reason)
return
try:
raw_data = await response.json()
except aiohttp.client_exceptions.ContentTypeError as err:
logger.exception(err)
return
return {
"connector": connector,
"results": connector.process_search_response(
query, raw_data, min_confidence
),
}
except asyncio.TimeoutError:
logger.info("Connection timed out for url: %s", url)
except aiohttp.ClientError as err:
logger.exception(err)
async def async_connector_search(query, items, min_confidence):
async def async_connector_search(
query: str,
items: list[tuple[str, abstract_connector.AbstractConnector]],
min_confidence: float,
) -> list[Optional[abstract_connector.ConnectorResults]]:
"""Try a number of requests simultaneously"""
timeout = aiohttp.ClientTimeout(total=SEARCH_TIMEOUT)
async with aiohttp.ClientSession(timeout=timeout) as session:
tasks = []
tasks: list[Future[Optional[abstract_connector.ConnectorResults]]] = []
for url, connector in items:
tasks.append(
asyncio.ensure_future(
get_results(session, url, min_confidence, query, connector)
connector.get_results(session, url, min_confidence, query)
)
)
results = await asyncio.gather(*tasks)
return results
return list(results)
def search(query, min_confidence=0.1, return_first=False):
"""find books based on arbitary keywords"""
@overload
def search(
query: str, *, min_confidence: float = 0.1, return_first: Literal[False]
) -> list[abstract_connector.ConnectorResults]:
...
@overload
def search(
query: str, *, min_confidence: float = 0.1, return_first: Literal[True]
) -> Optional[SearchResult]:
...
def search(
query: str, *, min_confidence: float = 0.1, return_first: bool = False
) -> Union[list[abstract_connector.ConnectorResults], Optional[SearchResult]]:
"""find books based on arbitrary keywords"""
if not query:
return []
results = []
return None if return_first else []
items = []
for connector in get_connectors():
@ -91,8 +81,12 @@ def search(query, min_confidence=0.1, return_first=False):
items.append((url, connector))
# load as many results as we can
results = asyncio.run(async_connector_search(query, items, min_confidence))
results = [r for r in results if r]
# failed requests will return None, so filter those out
results = [
r
for r in asyncio.run(async_connector_search(query, items, min_confidence))
if r
]
if return_first:
# find the best result from all the responses and return that
@ -100,11 +94,12 @@ def search(query, min_confidence=0.1, return_first=False):
all_results = sorted(all_results, key=lambda r: r.confidence, reverse=True)
return all_results[0] if all_results else None
# failed requests will return None, so filter those out
return results
def first_search_result(query, min_confidence=0.1):
def first_search_result(
query: str, min_confidence: float = 0.1
) -> Union[models.Edition, SearchResult, None]:
"""search until you find a result that fits"""
# try local search first
result = book_search.search(query, min_confidence=min_confidence, return_first=True)
@ -114,18 +109,20 @@ def first_search_result(query, min_confidence=0.1):
return search(query, min_confidence=min_confidence, return_first=True) or None
def get_connectors():
def get_connectors() -> Iterator[abstract_connector.AbstractConnector]:
"""load all connectors"""
for info in models.Connector.objects.filter(active=True).order_by("priority").all():
yield load_connector(info)
def get_or_create_connector(remote_id):
def get_or_create_connector(remote_id: str) -> abstract_connector.AbstractConnector:
"""get the connector related to the object's server"""
url = urlparse(remote_id)
identifier = url.netloc
identifier = url.hostname
if not identifier:
raise ValueError("Invalid remote id")
raise ValueError(f"Invalid remote id: {remote_id}")
base_url = f"{url.scheme}://{url.netloc}"
try:
connector_info = models.Connector.objects.get(identifier=identifier)
@ -133,18 +130,18 @@ def get_or_create_connector(remote_id):
connector_info = models.Connector.objects.create(
identifier=identifier,
connector_file="bookwyrm_connector",
base_url=f"https://{identifier}",
books_url=f"https://{identifier}/book",
covers_url=f"https://{identifier}/images/covers",
search_url=f"https://{identifier}/search?q=",
base_url=base_url,
books_url=f"{base_url}/book",
covers_url=f"{base_url}/images/covers",
search_url=f"{base_url}/search?q=",
priority=2,
)
return load_connector(connector_info)
@app.task(queue="low_priority")
def load_more_data(connector_id, book_id):
@app.task(queue=CONNECTORS)
def load_more_data(connector_id: str, book_id: str) -> None:
"""background the work of getting all 10,000 editions of LoTR"""
connector_info = models.Connector.objects.get(id=connector_id)
connector = load_connector(connector_info)
@ -152,8 +149,10 @@ def load_more_data(connector_id, book_id):
connector.expand_book_data(book)
@app.task(queue="low_priority")
def create_edition_task(connector_id, work_id, data):
@app.task(queue=CONNECTORS)
def create_edition_task(
connector_id: int, work_id: int, data: Union[str, abstract_connector.JsonDict]
) -> None:
"""separate task for each of the 10,000 editions of LoTR"""
connector_info = models.Connector.objects.get(id=connector_id)
connector = load_connector(connector_info)
@ -161,30 +160,41 @@ def create_edition_task(connector_id, work_id, data):
connector.create_edition_from_data(work, data)
def load_connector(connector_info):
def load_connector(
connector_info: models.Connector,
) -> abstract_connector.AbstractConnector:
"""instantiate the connector class"""
connector = importlib.import_module(
f"bookwyrm.connectors.{connector_info.connector_file}"
)
return connector.Connector(connector_info.identifier)
return connector.Connector(connector_info.identifier) # type: ignore[no-any-return]
@receiver(signals.post_save, sender="bookwyrm.FederatedServer")
# pylint: disable=unused-argument
def create_connector(sender, instance, created, *args, **kwargs):
def create_connector(
sender: Any,
instance: models.FederatedServer,
created: Any,
*args: Any,
**kwargs: Any,
) -> None:
"""create a connector to an external bookwyrm server"""
if instance.application_type == "bookwyrm":
get_or_create_connector(f"https://{instance.server_name}")
def raise_not_valid_url(url):
def raise_not_valid_url(url: str) -> None:
"""do some basic reality checks on the url"""
parsed = urlparse(url)
if not parsed.scheme in ["http", "https"]:
raise ConnectorException("Invalid scheme: ", url)
if not parsed.hostname:
raise ConnectorException("Hostname missing: ", url)
try:
ipaddress.ip_address(parsed.netloc)
ipaddress.ip_address(parsed.hostname)
raise ConnectorException("Provided url is an IP address: ", url)
except ValueError:
# it's not an IP address, which is good

View file

@ -1,9 +1,10 @@
""" inventaire data connector """
import re
from typing import Any, Union, Optional, Iterator, Iterable
from bookwyrm import models
from bookwyrm.book_search import SearchResult
from .abstract_connector import AbstractConnector, Mapping
from .abstract_connector import AbstractConnector, Mapping, JsonDict
from .abstract_connector import get_data
from .connector_manager import ConnectorException, create_edition_task
@ -13,7 +14,7 @@ class Connector(AbstractConnector):
generated_remote_link_field = "inventaire_id"
def __init__(self, identifier):
def __init__(self, identifier: str):
super().__init__(identifier)
get_first = lambda a: a[0]
@ -60,13 +61,13 @@ class Connector(AbstractConnector):
Mapping("died", remote_field="wdt:P570", formatter=get_first),
] + shared_mappings
def get_remote_id(self, value):
def get_remote_id(self, value: str) -> str:
"""convert an id/uri into a url"""
return f"{self.books_url}?action=by-uris&uris={value}"
def get_book_data(self, remote_id):
def get_book_data(self, remote_id: str) -> JsonDict:
data = get_data(remote_id)
extracted = list(data.get("entities").values())
extracted = list(data.get("entities", {}).values())
try:
data = extracted[0]
except (KeyError, IndexError):
@ -74,10 +75,16 @@ class Connector(AbstractConnector):
# flatten the data so that images, uri, and claims are on the same level
return {
**data.get("claims", {}),
**{k: data.get(k) for k in ["uri", "image", "labels", "sitelinks", "type"]},
**{
k: data.get(k)
for k in ["uri", "image", "labels", "sitelinks", "type"]
if k in data
},
}
def parse_search_data(self, data, min_confidence):
def parse_search_data(
self, data: JsonDict, min_confidence: float
) -> Iterator[SearchResult]:
for search_result in data.get("results", []):
images = search_result.get("image")
cover = f"{self.covers_url}/img/entities/{images[0]}" if images else None
@ -96,8 +103,8 @@ class Connector(AbstractConnector):
connector=self,
)
def parse_isbn_search_data(self, data):
"""got some daaaata"""
def parse_isbn_search_data(self, data: JsonDict) -> Iterator[SearchResult]:
"""got some data"""
results = data.get("entities")
if not results:
return
@ -114,35 +121,44 @@ class Connector(AbstractConnector):
connector=self,
)
def is_work_data(self, data):
def is_work_data(self, data: JsonDict) -> bool:
return data.get("type") == "work"
def load_edition_data(self, work_uri):
def load_edition_data(self, work_uri: str) -> JsonDict:
"""get a list of editions for a work"""
# pylint: disable=line-too-long
url = f"{self.books_url}?action=reverse-claims&property=wdt:P629&value={work_uri}&sort=true"
return get_data(url)
def get_edition_from_work_data(self, data):
data = self.load_edition_data(data.get("uri"))
def get_edition_from_work_data(self, data: JsonDict) -> JsonDict:
work_uri = data.get("uri")
if not work_uri:
raise ConnectorException("Invalid URI")
data = self.load_edition_data(work_uri)
try:
uri = data.get("uris", [])[0]
except IndexError:
raise ConnectorException("Invalid book data")
return self.get_book_data(self.get_remote_id(uri))
def get_work_from_edition_data(self, data):
uri = data.get("wdt:P629", [None])[0]
def get_work_from_edition_data(self, data: JsonDict) -> JsonDict:
try:
uri = data.get("wdt:P629", [])[0]
except IndexError:
raise ConnectorException("Invalid book data")
if not uri:
raise ConnectorException("Invalid book data")
return self.get_book_data(self.get_remote_id(uri))
def get_authors_from_data(self, data):
def get_authors_from_data(self, data: JsonDict) -> Iterator[models.Author]:
authors = data.get("wdt:P50", [])
for author in authors:
yield self.get_or_create_author(self.get_remote_id(author))
model = self.get_or_create_author(self.get_remote_id(author))
if model:
yield model
def expand_book_data(self, book):
def expand_book_data(self, book: models.Book) -> None:
work = book
# go from the edition to the work, if necessary
if isinstance(book, models.Edition):
@ -154,36 +170,45 @@ class Connector(AbstractConnector):
# who knows, man
return
for edition_uri in edition_options.get("uris"):
for edition_uri in edition_options.get("uris", []):
remote_id = self.get_remote_id(edition_uri)
create_edition_task.delay(self.connector.id, work.id, remote_id)
def create_edition_from_data(self, work, edition_data, instance=None):
def create_edition_from_data(
self,
work: models.Work,
edition_data: Union[str, JsonDict],
instance: Optional[models.Edition] = None,
) -> Optional[models.Edition]:
"""pass in the url as data and then call the version in abstract connector"""
if isinstance(edition_data, str):
try:
edition_data = self.get_book_data(edition_data)
except ConnectorException:
# who, indeed, knows
return
super().create_edition_from_data(work, edition_data, instance=instance)
return None
return super().create_edition_from_data(work, edition_data, instance=instance)
def get_cover_url(self, cover_blob, *_):
def get_cover_url(
self, cover_blob: Union[list[JsonDict], JsonDict], *_: Any
) -> Optional[str]:
"""format the relative cover url into an absolute one:
{"url": "/img/entities/e794783f01b9d4f897a1ea9820b96e00d346994f"}
"""
# covers may or may not be a list
if isinstance(cover_blob, list) and len(cover_blob) > 0:
if isinstance(cover_blob, list):
if len(cover_blob) == 0:
return None
cover_blob = cover_blob[0]
cover_id = cover_blob.get("url")
if not cover_id:
if not isinstance(cover_id, str):
return None
# cover may or may not be an absolute url already
if re.match(r"^http", cover_id):
return cover_id
return f"{self.covers_url}{cover_id}"
def resolve_keys(self, keys):
def resolve_keys(self, keys: Iterable[str]) -> list[str]:
"""cool, it's "wd:Q3156592" now what the heck does that mean"""
results = []
for uri in keys:
@ -191,10 +216,10 @@ class Connector(AbstractConnector):
data = self.get_book_data(self.get_remote_id(uri))
except ConnectorException:
continue
results.append(get_language_code(data.get("labels")))
results.append(get_language_code(data.get("labels", {})))
return results
def get_description(self, links):
def get_description(self, links: JsonDict) -> str:
"""grab an extracted excerpt from wikipedia"""
link = links.get("enwiki")
if not link:
@ -204,15 +229,15 @@ class Connector(AbstractConnector):
data = get_data(url)
except ConnectorException:
return ""
return data.get("extract")
return data.get("extract", "")
def get_remote_id_from_model(self, obj):
def get_remote_id_from_model(self, obj: models.BookDataModel) -> str:
"""use get_remote_id to figure out the link from a model obj"""
remote_id_value = obj.inventaire_id
return self.get_remote_id(remote_id_value)
def get_language_code(options, code="en"):
def get_language_code(options: JsonDict, code: str = "en") -> Any:
"""when there are a bunch of translation but we need a single field"""
result = options.get(code)
if result:

View file

@ -1,9 +1,13 @@
""" openlibrary data connector """
import re
from typing import Any, Optional, Union, Iterator, Iterable
from markdown import markdown
from bookwyrm import models
from bookwyrm.book_search import SearchResult
from .abstract_connector import AbstractConnector, Mapping
from bookwyrm.utils.sanitizer import clean
from .abstract_connector import AbstractConnector, Mapping, JsonDict
from .abstract_connector import get_data, infer_physical_format, unique_physical_format
from .connector_manager import ConnectorException, create_edition_task
from .openlibrary_languages import languages
@ -14,7 +18,7 @@ class Connector(AbstractConnector):
generated_remote_link_field = "openlibrary_link"
def __init__(self, identifier):
def __init__(self, identifier: str):
super().__init__(identifier)
get_first = lambda a, *args: a[0]
@ -94,14 +98,14 @@ class Connector(AbstractConnector):
Mapping("inventaire_id", remote_field="links", formatter=get_inventaire_id),
]
def get_book_data(self, remote_id):
def get_book_data(self, remote_id: str) -> JsonDict:
data = get_data(remote_id)
if data.get("type", {}).get("key") == "/type/redirect":
remote_id = self.base_url + data.get("location")
remote_id = self.base_url + data.get("location", "")
return get_data(remote_id)
return data
def get_remote_id_from_data(self, data):
def get_remote_id_from_data(self, data: JsonDict) -> str:
"""format a url from an openlibrary id field"""
try:
key = data["key"]
@ -109,10 +113,10 @@ class Connector(AbstractConnector):
raise ConnectorException("Invalid book data")
return f"{self.books_url}{key}"
def is_work_data(self, data):
def is_work_data(self, data: JsonDict) -> bool:
return bool(re.match(r"^[\/\w]+OL\d+W$", data["key"]))
def get_edition_from_work_data(self, data):
def get_edition_from_work_data(self, data: JsonDict) -> JsonDict:
try:
key = data["key"]
except KeyError:
@ -124,7 +128,7 @@ class Connector(AbstractConnector):
raise ConnectorException("No editions for work")
return edition
def get_work_from_edition_data(self, data):
def get_work_from_edition_data(self, data: JsonDict) -> JsonDict:
try:
key = data["works"][0]["key"]
except (IndexError, KeyError):
@ -132,7 +136,7 @@ class Connector(AbstractConnector):
url = f"{self.books_url}{key}"
return self.get_book_data(url)
def get_authors_from_data(self, data):
def get_authors_from_data(self, data: JsonDict) -> Iterator[models.Author]:
"""parse author json and load or create authors"""
for author_blob in data.get("authors", []):
author_blob = author_blob.get("author", author_blob)
@ -144,7 +148,7 @@ class Connector(AbstractConnector):
continue
yield author
def get_cover_url(self, cover_blob, size="L"):
def get_cover_url(self, cover_blob: list[str], size: str = "L") -> Optional[str]:
"""ask openlibrary for the cover"""
if not cover_blob:
return None
@ -152,8 +156,10 @@ class Connector(AbstractConnector):
image_name = f"{cover_id}-{size}.jpg"
return f"{self.covers_url}/b/id/{image_name}"
def parse_search_data(self, data, min_confidence):
for idx, search_result in enumerate(data.get("docs")):
def parse_search_data(
self, data: JsonDict, min_confidence: float
) -> Iterator[SearchResult]:
for idx, search_result in enumerate(data.get("docs", [])):
# build the remote id from the openlibrary key
key = self.books_url + search_result["key"]
author = search_result.get("author_name") or ["Unknown"]
@ -174,7 +180,7 @@ class Connector(AbstractConnector):
confidence=confidence,
)
def parse_isbn_search_data(self, data):
def parse_isbn_search_data(self, data: JsonDict) -> Iterator[SearchResult]:
for search_result in list(data.values()):
# build the remote id from the openlibrary key
key = self.books_url + search_result["key"]
@ -188,12 +194,12 @@ class Connector(AbstractConnector):
year=search_result.get("publish_date"),
)
def load_edition_data(self, olkey):
def load_edition_data(self, olkey: str) -> JsonDict:
"""query openlibrary for editions of a work"""
url = f"{self.books_url}/works/{olkey}/editions"
return self.get_book_data(url)
def expand_book_data(self, book):
def expand_book_data(self, book: models.Book) -> None:
work = book
# go from the edition to the work, if necessary
if isinstance(book, models.Edition):
@ -206,14 +212,14 @@ class Connector(AbstractConnector):
# who knows, man
return
for edition_data in edition_options.get("entries"):
for edition_data in edition_options.get("entries", []):
# does this edition have ANY interesting data?
if ignore_edition(edition_data):
continue
create_edition_task.delay(self.connector.id, work.id, edition_data)
def ignore_edition(edition_data):
def ignore_edition(edition_data: JsonDict) -> bool:
"""don't load a million editions that have no metadata"""
# an isbn, we love to see it
if edition_data.get("isbn_13") or edition_data.get("isbn_10"):
@ -232,19 +238,30 @@ def ignore_edition(edition_data):
return True
def get_description(description_blob):
def get_description(description_blob: Union[JsonDict, str]) -> str:
"""descriptions can be a string or a dict"""
if isinstance(description_blob, dict):
return description_blob.get("value")
return description_blob
description = markdown(description_blob.get("value", ""))
else:
description = markdown(description_blob)
if (
description.startswith("<p>")
and description.endswith("</p>")
and description.count("<p>") == 1
):
# If there is just one <p> tag and it is around the text remove it
return description[len("<p>") : -len("</p>")].strip()
return clean(description)
def get_openlibrary_key(key):
def get_openlibrary_key(key: str) -> str:
"""convert /books/OL27320736M into OL27320736M"""
return key.split("/")[-1]
def get_languages(language_blob):
def get_languages(language_blob: Iterable[JsonDict]) -> list[Optional[str]]:
"""/language/eng -> English"""
langs = []
for lang in language_blob:
@ -252,14 +269,14 @@ def get_languages(language_blob):
return langs
def get_dict_field(blob, field_name):
def get_dict_field(blob: Optional[JsonDict], field_name: str) -> Optional[Any]:
"""extract the isni from the remote id data for the author"""
if not blob or not isinstance(blob, dict):
return None
return blob.get(field_name)
def get_wikipedia_link(links):
def get_wikipedia_link(links: list[Any]) -> Optional[str]:
"""extract wikipedia links"""
if not isinstance(links, list):
return None
@ -272,7 +289,7 @@ def get_wikipedia_link(links):
return None
def get_inventaire_id(links):
def get_inventaire_id(links: list[Any]) -> Optional[str]:
"""extract and format inventaire ids"""
if not isinstance(links, list):
return None
@ -282,11 +299,13 @@ def get_inventaire_id(links):
continue
if link.get("title") == "inventaire.io":
iv_link = link.get("url")
if not isinstance(iv_link, str):
return None
return iv_link.split("/")[-1]
return None
def pick_default_edition(options):
def pick_default_edition(options: list[JsonDict]) -> Optional[JsonDict]:
"""favor physical copies with covers in english"""
if not options:
return None

View file

@ -3,8 +3,8 @@ from django.core.mail import EmailMultiAlternatives
from django.template.loader import get_template
from bookwyrm import models, settings
from bookwyrm.tasks import app
from bookwyrm.settings import DOMAIN
from bookwyrm.tasks import app, EMAIL
from bookwyrm.settings import DOMAIN, BASE_URL
def email_data():
@ -14,16 +14,23 @@ def email_data():
"site_name": site.name,
"logo": site.logo_small_url,
"domain": DOMAIN,
"base_url": BASE_URL,
"user": None,
}
def test_email(user):
"""Just an admin checking if emails are sending"""
data = email_data()
send_email(user.email, *format_email("test", data))
def email_confirmation_email(user):
"""newly registered users confirm email address"""
data = email_data()
data["confirmation_code"] = user.confirmation_code
data["confirmation_link"] = user.confirmation_link
send_email.delay(user.email, *format_email("confirm", data))
send_email(user.email, *format_email("confirm", data))
def invite_email(invite_request):
@ -38,7 +45,7 @@ def password_reset_email(reset_code):
data = email_data()
data["reset_link"] = reset_code.link
data["user"] = reset_code.user.display_name
send_email.delay(reset_code.user.email, *format_email("password_reset", data))
send_email(reset_code.user.email, *format_email("password_reset", data))
def moderation_report_email(report):
@ -48,6 +55,7 @@ def moderation_report_email(report):
if report.user:
data["reportee"] = report.user.localname or report.user.username
data["report_link"] = report.remote_id
data["link_domain"] = report.links.exists()
for admin in models.User.objects.filter(
groups__name__in=["admin", "moderator"]
@ -68,7 +76,7 @@ def format_email(email_name, data):
return (subject, html_content, text_content)
@app.task(queue="high_priority")
@app.task(queue=EMAIL)
def send_email(recipient, subject, html_content, text_content):
"""use a task to send the email"""
email = EmailMultiAlternatives(

View file

@ -2,19 +2,20 @@
import datetime
from django import forms
from django.core.exceptions import PermissionDenied
from django.forms import widgets
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django_celery_beat.models import IntervalSchedule
from bookwyrm import models
from .custom_form import CustomForm
from .custom_form import CustomForm, StyledForm
# pylint: disable=missing-class-docstring
class ExpiryWidget(widgets.Select):
def value_from_datadict(self, data, files, name):
"""human-readable exiration time buckets"""
"""human-readable expiration time buckets"""
selected_string = super().value_from_datadict(data, files, name)
if selected_string == "day":
@ -54,11 +55,46 @@ class CreateInviteForm(CustomForm):
class SiteForm(CustomForm):
class Meta:
model = models.SiteSettings
exclude = ["admin_code", "install_mode"]
fields = [
"name",
"instance_tagline",
"instance_description",
"instance_short_description",
"default_theme",
"code_of_conduct",
"privacy_policy",
"impressum",
"show_impressum",
"logo",
"logo_small",
"favicon",
"support_link",
"support_title",
"admin_email",
"footer_item",
]
widgets = {
"instance_short_description": forms.TextInput(
attrs={"aria-describedby": "desc_instance_short_description"}
),
}
class RegistrationForm(CustomForm):
class Meta:
model = models.SiteSettings
fields = [
"allow_registration",
"allow_invite_requests",
"registration_closed_text",
"invite_request_text",
"invite_request_question",
"invite_question_text",
"require_confirm_email",
"default_user_auth_group",
]
widgets = {
"require_confirm_email": forms.CheckboxInput(
attrs={"aria-describedby": "desc_require_confirm_email"}
),
@ -68,6 +104,23 @@ class SiteForm(CustomForm):
}
class RegistrationLimitedForm(CustomForm):
class Meta:
model = models.SiteSettings
fields = [
"registration_closed_text",
"invite_request_text",
"invite_request_question",
"invite_question_text",
]
widgets = {
"invite_request_text": forms.Textarea(
attrs={"aria-describedby": "desc_invite_request_text"}
),
}
class ThemeForm(CustomForm):
class Meta:
model = models.Theme
@ -130,7 +183,7 @@ class AutoModRuleForm(CustomForm):
fields = ["string_match", "flag_users", "flag_statuses", "created_by"]
class IntervalScheduleForm(CustomForm):
class IntervalScheduleForm(StyledForm):
class Meta:
model = IntervalSchedule
fields = ["every", "period"]
@ -139,3 +192,10 @@ class IntervalScheduleForm(CustomForm):
"every": forms.NumberInput(attrs={"aria-describedby": "desc_every"}),
"period": forms.Select(attrs={"aria-describedby": "desc_period"}),
}
# pylint: disable=arguments-differ
def save(self, request, *args, **kwargs):
"""This is an outside model so the perms check works differently"""
if not request.user.has_perm("bookwyrm.moderate_user"):
raise PermissionDenied()
return super().save(*args, **kwargs)

View file

@ -15,12 +15,15 @@ class AuthorForm(CustomForm):
"aliases",
"bio",
"wikipedia_link",
"wikidata",
"website",
"born",
"died",
"openlibrary_key",
"inventaire_id",
"librarything_key",
"goodreads_key",
"isfdb",
"isni",
]
widgets = {
@ -30,10 +33,12 @@ class AuthorForm(CustomForm):
"wikipedia_link": forms.TextInput(
attrs={"aria-describedby": "desc_wikipedia_link"}
),
"wikidata": forms.TextInput(attrs={"aria-describedby": "desc_wikidata"}),
"website": forms.TextInput(attrs={"aria-describedby": "desc_website"}),
"born": forms.SelectDateWidget(attrs={"aria-describedby": "desc_born"}),
"died": forms.SelectDateWidget(attrs={"aria-describedby": "desc_died"}),
"oepnlibrary_key": forms.TextInput(
attrs={"aria-describedby": "desc_oepnlibrary_key"}
"openlibrary_key": forms.TextInput(
attrs={"aria-describedby": "desc_openlibrary_key"}
),
"inventaire_id": forms.TextInput(
attrs={"aria-describedby": "desc_inventaire_id"}

View file

@ -1,8 +1,9 @@
""" using django model forms """
from django import forms
from file_resubmit.widgets import ResubmitImageWidget
from bookwyrm import models
from bookwyrm.models.fields import ClearableFileInputWithWarning
from .custom_form import CustomForm
from .widgets import ArrayWidget, SelectDateWidget, Select
@ -18,22 +19,37 @@ class CoverForm(CustomForm):
class EditionForm(CustomForm):
class Meta:
model = models.Edition
exclude = [
"remote_id",
"origin_id",
"created_date",
"updated_date",
"edition_rank",
"authors",
"parent_work",
"shelves",
"connector",
"search_vector",
"links",
"file_links",
fields = [
"title",
"sort_title",
"subtitle",
"description",
"series",
"series_number",
"languages",
"subjects",
"publishers",
"first_published_date",
"published_date",
"cover",
"physical_format",
"physical_format_detail",
"pages",
"isbn_13",
"isbn_10",
"openlibrary_key",
"inventaire_id",
"goodreads_key",
"oclc_number",
"asin",
"aasin",
"isfdb",
]
widgets = {
"title": forms.TextInput(attrs={"aria-describedby": "desc_title"}),
"sort_title": forms.TextInput(
attrs={"aria-describedby": "desc_sort_title"}
),
"subtitle": forms.TextInput(attrs={"aria-describedby": "desc_subtitle"}),
"description": forms.Textarea(
attrs={"aria-describedby": "desc_description"}
@ -55,9 +71,7 @@ class EditionForm(CustomForm):
"published_date": SelectDateWidget(
attrs={"aria-describedby": "desc_published_date"}
),
"cover": ClearableFileInputWithWarning(
attrs={"aria-describedby": "desc_cover"}
),
"cover": ResubmitImageWidget(attrs={"aria-describedby": "desc_cover"}),
"physical_format": Select(
attrs={"aria-describedby": "desc_physical_format"}
),
@ -73,10 +87,15 @@ class EditionForm(CustomForm):
"inventaire_id": forms.TextInput(
attrs={"aria-describedby": "desc_inventaire_id"}
),
"goodreads_key": forms.TextInput(
attrs={"aria-describedby": "desc_goodreads_key"}
),
"oclc_number": forms.TextInput(
attrs={"aria-describedby": "desc_oclc_number"}
),
"ASIN": forms.TextInput(attrs={"aria-describedby": "desc_ASIN"}),
"AASIN": forms.TextInput(attrs={"aria-describedby": "desc_AASIN"}),
"isfdb": forms.TextInput(attrs={"aria-describedby": "desc_isfdb"}),
}
@ -91,6 +110,7 @@ class EditionFromWorkForm(CustomForm):
model = models.Work
fields = [
"title",
"sort_title",
"subtitle",
"authors",
"description",

View file

@ -4,7 +4,7 @@ from django.forms import ModelForm
from django.forms.widgets import Textarea
class CustomForm(ModelForm):
class StyledForm(ModelForm):
"""add css classes to the forms"""
def __init__(self, *args, **kwargs):
@ -16,7 +16,7 @@ class CustomForm(ModelForm):
css_classes["checkbox"] = "checkbox"
css_classes["textarea"] = "textarea"
# pylint: disable=super-with-arguments
super(CustomForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
for visible in self.visible_fields():
if hasattr(visible.field.widget, "input_type"):
input_type = visible.field.widget.input_type
@ -24,3 +24,13 @@ class CustomForm(ModelForm):
input_type = "textarea"
visible.field.widget.attrs["rows"] = 5
visible.field.widget.attrs["class"] = css_classes[input_type]
class CustomForm(StyledForm):
"""Check permissions on save"""
# pylint: disable=arguments-differ
def save(self, request, *args, **kwargs):
"""Save and check perms"""
self.instance.raise_not_editable(request.user)
return super().save(*args, **kwargs)

View file

@ -1,11 +1,13 @@
""" using django model forms """
from django import forms
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from bookwyrm.models.fields import ClearableFileInputWithWarning
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class EditUserForm(CustomForm):
class Meta:
@ -66,3 +68,67 @@ class DeleteUserForm(CustomForm):
class Meta:
model = models.User
fields = ["password"]
class MoveUserForm(CustomForm):
target = forms.CharField(widget=forms.TextInput)
class Meta:
model = models.User
fields = ["password"]
class AliasUserForm(CustomForm):
username = forms.CharField(widget=forms.TextInput)
class Meta:
model = models.User
fields = ["password"]
class ChangePasswordForm(CustomForm):
current_password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = models.User
fields = ["password"]
widgets = {
"password": forms.PasswordInput(),
}
def clean(self):
"""Make sure passwords match and are valid"""
current_password = self.data.get("current_password")
if not self.instance.check_password(current_password):
self.add_error("current_password", _("Incorrect password"))
cleaned_data = super().clean()
new_password = cleaned_data.get("password")
confirm_password = self.data.get("confirm_password")
if new_password != confirm_password:
self.add_error("confirm_password", _("Password does not match"))
try:
validate_password(new_password)
except ValidationError as err:
self.add_error("password", err)
class ConfirmPasswordForm(CustomForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = models.User
fields = ["password"]
widgets = {
"password": forms.PasswordInput(),
}
def clean(self):
"""Make sure password is correct"""
password = self.data.get("password")
if not self.instance.check_password(password):
self.add_error("password", _("Incorrect Password"))

View file

@ -1,4 +1,5 @@
""" using django model forms """
import datetime
from django import forms
from django.forms import widgets
from django.utils.translation import gettext_lazy as _
@ -7,7 +8,6 @@ from bookwyrm import models
from bookwyrm.models.user import FeedFilterChoices
from .custom_form import CustomForm
# pylint: disable=missing-class-docstring
class FeedStatusTypesForm(CustomForm):
class Meta:
@ -25,6 +25,10 @@ class ImportForm(forms.Form):
csv_file = forms.FileField()
class ImportUserForm(forms.Form):
archive_file = forms.FileField()
class ShelfForm(CustomForm):
class Meta:
model = models.Shelf
@ -58,6 +62,21 @@ class ReadThroughForm(CustomForm):
self.add_error(
"stopped_date", _("Reading stopped date cannot be before start date.")
)
current_time = datetime.datetime.now()
if (
stopped_date is not None
and current_time.timestamp() < stopped_date.timestamp()
):
self.add_error(
"stopped_date", _("Reading stopped date cannot be in the future.")
)
if (
finish_date is not None
and current_time.timestamp() < finish_date.timestamp()
):
self.add_error(
"finish_date", _("Reading finished date cannot be in the future.")
)
class Meta:
model = models.ReadThrough

View file

@ -1,8 +1,14 @@
""" Forms for the landing pages """
from django.forms import PasswordInput
from django import forms
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
import pyotp
from bookwyrm import models
from bookwyrm.settings import DOMAIN
from bookwyrm.settings import TWO_FACTOR_LOGIN_VALIDITY_WINDOW
from .custom_form import CustomForm
@ -13,21 +19,40 @@ class LoginForm(CustomForm):
fields = ["localname", "password"]
help_texts = {f: None for f in fields}
widgets = {
"password": PasswordInput(),
"password": forms.PasswordInput(),
}
def infer_username(self):
"""Users may enter their localname, username, or email"""
localname = self.data.get("localname")
if "@" in localname: # looks like an email address to me
try:
return models.User.objects.get(email=localname).username
except models.User.DoesNotExist: # maybe it's a full username?
return localname
return f"{localname}@{DOMAIN}"
def add_invalid_password_error(self):
"""We don't want to be too specific about this"""
# pylint: disable=attribute-defined-outside-init
self.non_field_errors = _("Username or password are incorrect")
class RegisterForm(CustomForm):
class Meta:
model = models.User
fields = ["localname", "email", "password"]
help_texts = {f: None for f in fields}
widgets = {"password": PasswordInput()}
widgets = {"password": forms.PasswordInput()}
def clean(self):
"""Check if the username is taken"""
cleaned_data = super().clean()
localname = cleaned_data.get("localname").strip()
try:
validate_password(cleaned_data.get("password"))
except ValidationError as err:
self.add_error("password", err)
if models.User.objects.filter(localname=localname).first():
self.add_error("localname", _("User with this username already exists"))
@ -43,3 +68,65 @@ class InviteRequestForm(CustomForm):
class Meta:
model = models.InviteRequest
fields = ["email", "answer"]
class PasswordResetForm(CustomForm):
confirm_password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = models.User
fields = ["password"]
widgets = {
"password": forms.PasswordInput(),
}
def clean(self):
"""Make sure the passwords match and are valid"""
cleaned_data = super().clean()
new_password = cleaned_data.get("password")
confirm_password = self.data.get("confirm_password")
if new_password != confirm_password:
self.add_error("confirm_password", _("Password does not match"))
try:
validate_password(new_password)
except ValidationError as err:
self.add_error("password", err)
class Confirm2FAForm(CustomForm):
otp = forms.CharField(
max_length=6, min_length=6, widget=forms.TextInput(attrs={"autofocus": True})
)
class Meta:
model = models.User
fields = ["otp_secret", "hotp_count"]
def clean_otp(self):
"""Check otp matches"""
otp = self.data.get("otp")
totp = pyotp.TOTP(self.instance.otp_secret)
if not totp.verify(otp, valid_window=TWO_FACTOR_LOGIN_VALIDITY_WINDOW):
if self.instance.hotp_secret:
# maybe it's a backup code?
hotp = pyotp.HOTP(self.instance.hotp_secret)
hotp_count = (
self.instance.hotp_count
if self.instance.hotp_count is not None
else 0
)
if not hotp.verify(otp, hotp_count):
self.add_error("otp", _("Incorrect code"))
# increment the user hotp_count
else:
self.instance.hotp_count = hotp_count + 1
self.instance.save(broadcast=False, update_fields=["hotp_count"])
else:
self.add_error("otp", _("Incorrect code"))

View file

@ -1,4 +1,5 @@
""" using django model forms """
from urllib.parse import urlparse
from django.utils.translation import gettext_lazy as _
@ -25,7 +26,7 @@ class FileLinkForm(CustomForm):
url = cleaned_data.get("url")
filetype = cleaned_data.get("filetype")
book = cleaned_data.get("book")
domain = urlparse(url).netloc
domain = urlparse(url).hostname
if models.LinkDomain.objects.filter(domain=domain).exists():
status = models.LinkDomain.objects.get(domain=domain).status
if status == "blocked":
@ -36,13 +37,15 @@ class FileLinkForm(CustomForm):
"This domain is blocked. Please contact your administrator if you think this is an error."
),
)
elif models.FileLink.objects.filter(
url=url, book=book, filetype=filetype
).exists():
# pylint: disable=line-too-long
self.add_error(
"url",
_(
"This link with file type has already been added for this book. If it is not visible, the domain is still pending."
),
)
if (
models.FileLink.objects.filter(url=url, book=book, filetype=filetype)
.exclude(pk=self.instance)
.exists()
):
# pylint: disable=line-too-long
self.add_error(
"url",
_(
"This link with file type has already been added for this book. If it is not visible, the domain is still pending."
),
)

View file

@ -24,7 +24,7 @@ class SortListForm(forms.Form):
sort_by = ChoiceField(
choices=(
("order", _("List Order")),
("title", _("Book Title")),
("sort_title", _("Book Title")),
("rating", _("Rating")),
),
label=_("Sort By"),

View file

@ -53,6 +53,7 @@ class QuotationForm(CustomForm):
"sensitive",
"privacy",
"position",
"endposition",
"position_mode",
]

View file

@ -1,6 +1,7 @@
""" import classes """
from .importer import Importer
from .bookwyrm_import import BookwyrmImporter
from .calibre_import import CalibreImporter
from .goodreads_import import GoodreadsImporter
from .librarything_import import LibrarythingImporter

View file

@ -0,0 +1,24 @@
"""Import data from Bookwyrm export files"""
from django.http import QueryDict
from bookwyrm.models import User
from bookwyrm.models.bookwyrm_import_job import BookwyrmImportJob
class BookwyrmImporter:
"""Import a Bookwyrm User export file.
This is kind of a combination of an importer and a connector.
"""
# pylint: disable=no-self-use
def process_import(
self, user: User, archive_file: bytes, settings: QueryDict
) -> BookwyrmImportJob:
"""import user data from a Bookwyrm export file"""
required = [k for k in settings if settings.get(k) == "on"]
job = BookwyrmImportJob.objects.create(
user=user, archive_file=archive_file, required=required
)
return job

View file

@ -1,4 +1,6 @@
""" handle reading a csv from calibre """
from typing import Any, Optional
from bookwyrm.models import Shelf
from . import Importer
@ -9,7 +11,7 @@ class CalibreImporter(Importer):
service = "Calibre"
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any):
# Add timestamp to row_mappings_guesses for date_added to avoid
# integrity error
row_mappings_guesses = []
@ -23,6 +25,6 @@ class CalibreImporter(Importer):
self.row_mappings_guesses = row_mappings_guesses
super().__init__(*args, **kwargs)
def get_shelf(self, normalized_row):
def get_shelf(self, normalized_row: dict[str, Optional[str]]) -> Optional[str]:
# Calibre export does not indicate which shelf to use. Use a default one for now
return Shelf.TO_READ

View file

@ -1,15 +1,10 @@
""" handle reading a csv from an external service, defaults are from Goodreads """
import csv
import logging
from datetime import timedelta
from typing import Iterable, Optional
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from bookwyrm import models
from bookwyrm.models import ImportJob, ImportItem
from bookwyrm.tasks import app, LOW
logger = logging.getLogger(__name__)
from bookwyrm.models import ImportJob, ImportItem, SiteSettings, User
class Importer:
@ -24,8 +19,8 @@ class Importer:
("id", ["id", "book id"]),
("title", ["title"]),
("authors", ["author", "authors", "primary author"]),
("isbn_10", ["isbn10", "isbn"]),
("isbn_13", ["isbn13", "isbn", "isbns"]),
("isbn_10", ["isbn10", "isbn", "isbn/uid"]),
("isbn_13", ["isbn13", "isbn", "isbns", "isbn/uid"]),
("shelf", ["shelf", "exclusive shelf", "read status", "bookshelf"]),
("review_name", ["review name"]),
("review_body", ["my review", "review"]),
@ -41,26 +36,48 @@ class Importer:
"reading": ["currently-reading", "reading", "currently reading"],
}
def create_job(self, user, csv_file, include_reviews, privacy):
# pylint: disable=too-many-locals
def create_job(
self, user: User, csv_file: Iterable[str], include_reviews: bool, privacy: str
) -> ImportJob:
"""check over a csv and creates a database entry for the job"""
csv_reader = csv.DictReader(csv_file, delimiter=self.delimiter)
rows = enumerate(list(csv_reader))
rows = list(csv_reader)
if len(rows) < 1:
raise ValueError("CSV file is empty")
mappings = (
self.create_row_mappings(list(fieldnames))
if (fieldnames := csv_reader.fieldnames)
else {}
)
job = ImportJob.objects.create(
user=user,
include_reviews=include_reviews,
privacy=privacy,
mappings=self.create_row_mappings(csv_reader.fieldnames),
mappings=mappings,
source=self.service,
)
for index, entry in rows:
enforce_limit, allowed_imports = self.get_import_limit(user)
if enforce_limit and allowed_imports <= 0:
job.complete_job()
return job
for index, entry in enumerate(rows):
if enforce_limit and index >= allowed_imports:
break
self.create_item(job, index, entry)
return job
def update_legacy_job(self, job):
def update_legacy_job(self, job: ImportJob) -> None:
"""patch up a job that was in the old format"""
items = job.items
headers = list(items.first().data.keys())
first_item = items.first()
if first_item is None:
return
headers = list(first_item.data.keys())
job.mappings = self.create_row_mappings(headers)
job.updated_date = timezone.now()
job.save()
@ -71,24 +88,24 @@ class Importer:
item.normalized_data = normalized
item.save()
def create_row_mappings(self, headers):
def create_row_mappings(self, headers: list[str]) -> dict[str, Optional[str]]:
"""guess what the headers mean"""
mappings = {}
for (key, guesses) in self.row_mappings_guesses:
value = [h for h in headers if h.lower() in guesses]
value = value[0] if len(value) else None
values = [h for h in headers if h.lower() in guesses]
value = values[0] if len(values) else None
if value:
headers.remove(value)
mappings[key] = value
return mappings
def create_item(self, job, index, data):
def create_item(self, job: ImportJob, index: int, data: dict[str, str]) -> None:
"""creates and saves an import item"""
normalized = self.normalize_row(data, job.mappings)
normalized["shelf"] = self.get_shelf(normalized)
ImportItem(job=job, index=index, data=data, normalized_data=normalized).save()
def get_shelf(self, normalized_row):
def get_shelf(self, normalized_row: dict[str, Optional[str]]) -> Optional[str]:
"""determine which shelf to use"""
shelf_name = normalized_row.get("shelf")
if not shelf_name:
@ -99,11 +116,35 @@ class Importer:
]
return shelf[0] if shelf else None
def normalize_row(self, entry, mappings): # pylint: disable=no-self-use
# pylint: disable=no-self-use
def normalize_row(
self, entry: dict[str, str], mappings: dict[str, Optional[str]]
) -> dict[str, Optional[str]]:
"""use the dataclass to create the formatted row of data"""
return {k: entry.get(v) for k, v in mappings.items()}
return {k: entry.get(v) if v else None for k, v in mappings.items()}
def create_retry_job(self, user, original_job, items):
# pylint: disable=no-self-use
def get_import_limit(self, user: User) -> tuple[int, int]:
"""check if import limit is set and return how many imports are left"""
site_settings = SiteSettings.objects.get()
import_size_limit = site_settings.import_size_limit
import_limit_reset = site_settings.import_limit_reset
enforce_limit = import_size_limit and import_limit_reset
allowed_imports = 0
if enforce_limit:
time_range = timezone.now() - timedelta(days=import_limit_reset)
import_jobs = ImportJob.objects.filter(
user=user, created_date__gte=time_range
)
# pylint: disable=consider-using-generator
imported_books = sum([job.successful_item_count for job in import_jobs])
allowed_imports = import_size_limit - imported_books
return enforce_limit, allowed_imports
def create_retry_job(
self, user: User, original_job: ImportJob, items: list[ImportItem]
) -> ImportJob:
"""retry items that didn't import"""
job = ImportJob.objects.create(
user=user,
@ -114,131 +155,13 @@ class Importer:
mappings=original_job.mappings,
retry=True,
)
for item in items:
enforce_limit, allowed_imports = self.get_import_limit(user)
if enforce_limit and allowed_imports <= 0:
job.complete_job()
return job
for index, item in enumerate(items):
if enforce_limit and index >= allowed_imports:
break
# this will re-normalize the raw data
self.create_item(job, item.index, item.data)
return job
def start_import(self, job): # pylint: disable=no-self-use
"""initalizes a csv import job"""
result = start_import_task.delay(job.id)
job.task_id = result.id
job.save()
@app.task(queue="low_priority")
def start_import_task(job_id):
"""trigger the child tasks for each row"""
job = ImportJob.objects.get(id=job_id)
# these are sub-tasks so that one big task doesn't use up all the memory in celery
for item in job.items.values_list("id", flat=True).all():
import_item_task.delay(item)
@app.task(queue="low_priority")
def import_item_task(item_id):
"""resolve a row into a book"""
item = models.ImportItem.objects.get(id=item_id)
try:
item.resolve()
except Exception as err: # pylint: disable=broad-except
item.fail_reason = _("Error loading book")
item.save()
item.update_job()
raise err
if item.book:
# shelves book and handles reviews
handle_imported_book(item)
else:
item.fail_reason = _("Could not find a match for book")
item.save()
item.update_job()
def handle_imported_book(item):
"""process a csv and then post about it"""
job = item.job
user = job.user
if isinstance(item.book, models.Work):
item.book = item.book.default_edition
if not item.book:
item.fail_reason = _("Error loading book")
item.save()
return
if not isinstance(item.book, models.Edition):
item.book = item.book.edition
existing_shelf = models.ShelfBook.objects.filter(book=item.book, user=user).exists()
# shelve the book if it hasn't been shelved already
if item.shelf and not existing_shelf:
desired_shelf = models.Shelf.objects.get(identifier=item.shelf, user=user)
shelved_date = item.date_added or timezone.now()
models.ShelfBook(
book=item.book, shelf=desired_shelf, user=user, shelved_date=shelved_date
).save(priority=LOW)
for read in item.reads:
# check for an existing readthrough with the same dates
if models.ReadThrough.objects.filter(
user=user,
book=item.book,
start_date=read.start_date,
finish_date=read.finish_date,
).exists():
continue
read.book = item.book
read.user = user
read.save()
if job.include_reviews and (item.rating or item.review) and not item.linked_review:
# we don't know the publication date of the review,
# but "now" is a bad guess
published_date_guess = item.date_read or item.date_added
if item.review:
# pylint: disable=consider-using-f-string
review_title = "Review of {!r} on {!r}".format(
item.book.title,
job.source,
)
review = models.Review.objects.filter(
user=user,
book=item.book,
name=review_title,
rating=item.rating,
published_date=published_date_guess,
).first()
if not review:
review = models.Review(
user=user,
book=item.book,
name=review_title,
content=item.review,
rating=item.rating,
published_date=published_date_guess,
privacy=job.privacy,
)
review.save(software="bookwyrm", priority=LOW)
else:
# just a rating
review = models.ReviewRating.objects.filter(
user=user,
book=item.book,
published_date=published_date_guess,
rating=item.rating,
).first()
if not review:
review = models.ReviewRating(
user=user,
book=item.book,
rating=item.rating,
published_date=published_date_guess,
privacy=job.privacy,
)
review.save(software="bookwyrm", priority=LOW)
# only broadcast this review to other bookwyrm instances
item.linked_review = review
item.save()

View file

@ -1,11 +1,16 @@
""" handle reading a tsv from librarything """
import re
from typing import Optional
from bookwyrm.models import Shelf
from . import Importer
def _remove_brackets(value: Optional[str]) -> Optional[str]:
return re.sub(r"\[|\]", "", value) if value else None
class LibrarythingImporter(Importer):
"""csv downloads from librarything"""
@ -13,16 +18,19 @@ class LibrarythingImporter(Importer):
delimiter = "\t"
encoding = "ISO-8859-1"
def normalize_row(self, entry, mappings): # pylint: disable=no-self-use
def normalize_row(
self, entry: dict[str, str], mappings: dict[str, Optional[str]]
) -> dict[str, Optional[str]]: # pylint: disable=no-self-use
"""use the dataclass to create the formatted row of data"""
remove_brackets = lambda v: re.sub(r"\[|\]", "", v) if v else None
normalized = {k: remove_brackets(entry.get(v)) for k, v in mappings.items()}
isbn_13 = normalized.get("isbn_13")
isbn_13 = isbn_13.split(", ") if isbn_13 else []
normalized["isbn_13"] = isbn_13[1] if len(isbn_13) > 0 else None
normalized = {
k: _remove_brackets(entry.get(v) if v else None)
for k, v in mappings.items()
}
isbn_13 = value.split(", ") if (value := normalized.get("isbn_13")) else []
normalized["isbn_13"] = isbn_13[1] if len(isbn_13) > 1 else None
return normalized
def get_shelf(self, normalized_row):
def get_shelf(self, normalized_row: dict[str, Optional[str]]) -> Optional[str]:
if normalized_row["date_finished"]:
return Shelf.READ_FINISHED
if normalized_row["date_started"]:

View file

@ -1,4 +1,6 @@
""" handle reading a csv from openlibrary"""
from typing import Any
from . import Importer
@ -7,7 +9,7 @@ class OpenLibraryImporter(Importer):
service = "OpenLibrary"
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any):
self.row_mappings_guesses.append(("openlibrary_key", ["edition id"]))
self.row_mappings_guesses.append(("openlibrary_work_key", ["work id"]))
super().__init__(*args, **kwargs)

File diff suppressed because it is too large Load diff

View file

128
bookwyrm/isbn/isbn.py Normal file
View file

@ -0,0 +1,128 @@
""" Use the range message from isbn-international to hyphenate ISBNs """
import os
from typing import Optional
from xml.etree import ElementTree
from xml.etree.ElementTree import Element
import requests
from bookwyrm import settings
def _get_rules(element: Element) -> list[Element]:
if (rules_el := element.find("Rules")) is not None:
return rules_el.findall("Rule")
return []
class IsbnHyphenator:
"""Class to manage the range message xml file and use it to hyphenate ISBNs"""
__range_message_url = "https://www.isbn-international.org/export_rangemessage.xml"
__range_file_path = os.path.join(
settings.BASE_DIR, "bookwyrm", "isbn", "RangeMessage.xml"
)
__element_tree = None
def update_range_message(self) -> None:
"""Download the range message xml file and save it locally"""
response = requests.get(self.__range_message_url, timeout=15)
with open(self.__range_file_path, "w", encoding="utf-8") as file:
file.write(response.text)
self.__element_tree = None
def hyphenate(self, isbn_13: Optional[str]) -> Optional[str]:
"""hyphenate the given ISBN-13 number using the range message"""
if isbn_13 is None:
return None
if self.__element_tree is None:
self.__element_tree = ElementTree.parse(self.__range_file_path)
gs1_prefix = isbn_13[:3]
try:
reg_group = self.__find_reg_group(isbn_13, gs1_prefix)
except ValueError:
# if the reg groups are invalid, just return the original isbn
return isbn_13
if reg_group is None:
return isbn_13 # failed to hyphenate
registrant = self.__find_registrant(isbn_13, gs1_prefix, reg_group)
if registrant is None:
return isbn_13 # failed to hyphenate
publication = isbn_13[len(gs1_prefix) + len(reg_group) + len(registrant) : -1]
check_digit = isbn_13[-1:]
return "-".join((gs1_prefix, reg_group, registrant, publication, check_digit))
def __find_reg_group(self, isbn_13: str, gs1_prefix: str) -> Optional[str]:
if self.__element_tree is None:
self.__element_tree = ElementTree.parse(self.__range_file_path)
ucc_prefixes_el = self.__element_tree.find("EAN.UCCPrefixes")
if ucc_prefixes_el is None:
return None
for ean_ucc_el in ucc_prefixes_el.findall("EAN.UCC"):
if (
prefix_el := ean_ucc_el.find("Prefix")
) is not None and prefix_el.text == gs1_prefix:
for rule_el in _get_rules(ean_ucc_el):
length_el = rule_el.find("Length")
if length_el is None:
continue
length = int(text) if (text := length_el.text) else 0
if length == 0:
continue
range_el = rule_el.find("Range")
if range_el is None or range_el.text is None:
continue
reg_grp_range = [int(x[:length]) for x in range_el.text.split("-")]
reg_group = isbn_13[len(gs1_prefix) : len(gs1_prefix) + length]
if reg_grp_range[0] <= int(reg_group) <= reg_grp_range[1]:
return reg_group
return None
return None
def __find_registrant(
self, isbn_13: str, gs1_prefix: str, reg_group: str
) -> Optional[str]:
from_ind = len(gs1_prefix) + len(reg_group)
if self.__element_tree is None:
self.__element_tree = ElementTree.parse(self.__range_file_path)
reg_groups_el = self.__element_tree.find("RegistrationGroups")
if reg_groups_el is None:
return None
for group_el in reg_groups_el.findall("Group"):
if (
prefix_el := group_el.find("Prefix")
) is not None and prefix_el.text == "-".join((gs1_prefix, reg_group)):
for rule_el in _get_rules(group_el):
length_el = rule_el.find("Length")
if length_el is None:
continue
length = int(text) if (text := length_el.text) else 0
if length == 0:
continue
range_el = rule_el.find("Range")
if range_el is None or range_el.text is None:
continue
registrant_range = [
int(x[:length]) for x in range_el.text.split("-")
]
registrant = isbn_13[from_ind : from_ind + length]
if registrant_range[0] <= int(registrant) <= registrant_range[1]:
return registrant
return None
return None
hyphenator_singleton = IsbnHyphenator()

View file

@ -5,7 +5,7 @@ from django.db.models import signals, Count, Q
from bookwyrm import models
from bookwyrm.redis_store import RedisStore
from bookwyrm.tasks import app, MEDIUM, HIGH
from bookwyrm.tasks import app, LISTS
class ListsStream(RedisStore):
@ -24,8 +24,7 @@ class ListsStream(RedisStore):
def add_list(self, book_list):
"""add a list to users' feeds"""
# the pipeline contains all the add-to-stream activities
self.add_object_to_related_stores(book_list)
self.add_object_to_stores(book_list, self.get_stores_for_object(book_list))
def add_user_lists(self, viewer, user):
"""add a user's lists to another user's feed"""
@ -86,18 +85,19 @@ class ListsStream(RedisStore):
if group:
audience = audience.filter(
Q(id=book_list.user.id) # if the user is the list's owner
| Q(following=book_list.user) # if the user is following the pwmer
| Q(following=book_list.user) # if the user is following the owner
# if a user is in the group
| Q(memberships__group__id=book_list.group.id)
)
else:
audience = audience.filter(
Q(id=book_list.user.id) # if the user is the list's owner
| Q(following=book_list.user) # if the user is following the pwmer
| Q(following=book_list.user) # if the user is following the owner
)
return audience.distinct()
def get_stores_for_object(self, obj):
"""the stores that an object belongs in"""
return [self.stream_id(u) for u in self.get_audience(obj)]
def get_lists_for_user(self, user): # pylint: disable=no-self-use
@ -217,14 +217,14 @@ def add_list_on_account_create_command(user_id):
# ---- TASKS
@app.task(queue=MEDIUM)
@app.task(queue=LISTS)
def populate_lists_task(user_id):
"""background task for populating an empty list stream"""
user = models.User.objects.get(id=user_id)
ListsStream().populate_lists(user)
@app.task(queue=MEDIUM)
@app.task(queue=LISTS)
def remove_list_task(list_id, re_add=False):
"""remove a list from any stream it might be in"""
stores = models.User.objects.filter(local=True, is_active=True).values_list(
@ -233,20 +233,20 @@ def remove_list_task(list_id, re_add=False):
# delete for every store
stores = [ListsStream().stream_id(idx) for idx in stores]
ListsStream().remove_object_from_related_stores(list_id, stores=stores)
ListsStream().remove_object_from_stores(list_id, stores)
if re_add:
add_list_task.delay(list_id)
@app.task(queue=HIGH)
@app.task(queue=LISTS)
def add_list_task(list_id):
"""add a list to any stream it should be in"""
book_list = models.List.objects.get(id=list_id)
ListsStream().add_list(book_list)
@app.task(queue=MEDIUM)
@app.task(queue=LISTS)
def remove_user_lists_task(viewer_id, user_id, exclude_privacy=None):
"""remove all lists by a user from a viewer's stream"""
viewer = models.User.objects.get(id=viewer_id)
@ -254,7 +254,7 @@ def remove_user_lists_task(viewer_id, user_id, exclude_privacy=None):
ListsStream().remove_user_lists(viewer, user, exclude_privacy=exclude_privacy)
@app.task(queue=MEDIUM)
@app.task(queue=LISTS)
def add_user_lists_task(viewer_id, user_id):
"""add all lists by a user to a viewer's stream"""
viewer = models.User.objects.get(id=viewer_id)

View 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))

View file

@ -0,0 +1,19 @@
""" manually confirm e-mail of user """
from django.core.management.base import BaseCommand
from bookwyrm import models
class Command(BaseCommand):
"""command-line options"""
help = "Manually confirm email for user"
def add_arguments(self, parser):
parser.add_argument("username")
def handle(self, *args, **options):
name = options["username"]
user = models.User.objects.get(localname=name)
user.reactivate()
self.stdout.write(self.style.SUCCESS("User's email is now confirmed."))

View file

@ -1,44 +1,14 @@
""" PROCEED WITH CAUTION: uses deduplication fields to permanently
merge book data objects """
from django.core.management.base import BaseCommand
from django.db.models import Count
from bookwyrm import models
def update_related(canonical, obj):
"""update all the models with fk to the object being removed"""
# move related models to canonical
related_models = [
(r.remote_field.name, r.related_model) for r in canonical._meta.related_objects
]
for (related_field, related_model) in related_models:
related_objs = related_model.objects.filter(**{related_field: obj})
for related_obj in related_objs:
print("replacing in", related_model.__name__, related_field, related_obj.id)
try:
setattr(related_obj, related_field, canonical)
related_obj.save()
except TypeError:
getattr(related_obj, related_field).add(canonical)
getattr(related_obj, related_field).remove(obj)
def copy_data(canonical, obj):
"""try to get the most data possible"""
for data_field in obj._meta.get_fields():
if not hasattr(data_field, "activitypub_field"):
continue
data_value = getattr(obj, data_field.name)
if not data_value:
continue
if not getattr(canonical, data_field.name):
print("setting data field", data_field.name, data_value)
setattr(canonical, data_field.name, data_value)
canonical.save()
def dedupe_model(model):
def dedupe_model(model, dry_run=False):
"""combine duplicate editions and update related models"""
print(f"deduplicating {model.__name__}:")
fields = model._meta.get_fields()
dedupe_fields = [
f for f in fields if hasattr(f, "deduplication_field") and f.deduplication_field
@ -47,33 +17,42 @@ def dedupe_model(model):
dupes = (
model.objects.values(field.name)
.annotate(Count(field.name))
.filter(**{"%s__count__gt" % field.name: 1})
.filter(**{f"{field.name}__count__gt": 1})
.exclude(**{field.name: ""})
.exclude(**{f"{field.name}__isnull": True})
)
for dupe in dupes:
value = dupe[field.name]
if not value or value == "":
continue
print("----------")
print(dupe)
objs = model.objects.filter(**{field.name: value}).order_by("id")
canonical = objs.first()
print("keeping", canonical.remote_id)
action = "would merge" if dry_run else "merging"
print(
f"{action} into {model.__name__} {canonical.remote_id} based on {field.name} {value}:"
)
for obj in objs[1:]:
print(obj.remote_id)
copy_data(canonical, obj)
update_related(canonical, obj)
# remove the outdated entry
obj.delete()
print(f"- {obj.remote_id}")
absorbed_fields = obj.merge_into(canonical, dry_run=dry_run)
print(f" absorbed fields: {absorbed_fields}")
class Command(BaseCommand):
"""dedplucate allllll the book data models"""
"""deduplicate allllll the book data models"""
help = "merges duplicate book data"
def add_arguments(self, parser):
"""add the arguments for this command"""
parser.add_argument(
"--dry_run",
action="store_true",
help="don't actually merge, only print what would happen",
)
# pylint: disable=no-self-use,unused-argument
def handle(self, *args, **options):
"""run deudplications"""
dedupe_model(models.Edition)
dedupe_model(models.Work)
dedupe_model(models.Author)
"""run deduplications"""
dedupe_model(models.Edition, dry_run=options["dry_run"])
dedupe_model(models.Work, dry_run=options["dry_run"])
dedupe_model(models.Author, dry_run=options["dry_run"])

View file

@ -0,0 +1,43 @@
""" Erase any data stored about deleted users """
import sys
from django.core.management.base import BaseCommand, CommandError
from bookwyrm import models
from bookwyrm.models.user import erase_user_data
# pylint: disable=missing-function-docstring
class Command(BaseCommand):
"""command-line options"""
help = "Remove Two Factor Authorisation from user"
def add_arguments(self, parser): # pylint: disable=no-self-use
parser.add_argument(
"--dryrun",
action="store_true",
help="Preview users to be cleared without altering the database",
)
def handle(self, *args, **options): # pylint: disable=unused-argument
# Check for anything fishy
bad_state = models.User.objects.filter(is_deleted=True, is_active=True)
if bad_state.exists():
raise CommandError(
f"{bad_state.count()} user(s) marked as both active and deleted"
)
deleted_users = models.User.objects.filter(is_deleted=True)
self.stdout.write(f"Found {deleted_users.count()} deleted users")
if options["dryrun"]:
self.stdout.write("\n".join(u.username for u in deleted_users[:5]))
if deleted_users.count() > 5:
self.stdout.write("... and more")
sys.exit()
self.stdout.write("Erasing user data:")
for user_id in deleted_users.values_list("id", flat=True):
erase_user_data.delay(user_id)
self.stdout.write(".", ending="")
self.stdout.write("")
self.stdout.write("Tasks created successfully")

View file

@ -4,12 +4,7 @@ import redis
from bookwyrm import settings
r = redis.Redis(
host=settings.REDIS_ACTIVITY_HOST,
port=settings.REDIS_ACTIVITY_PORT,
password=settings.REDIS_ACTIVITY_PASSWORD,
db=settings.REDIS_ACTIVITY_DB_INDEX,
)
r = redis.from_url(settings.REDIS_ACTIVITY_URL)
def erase_streams():

View file

@ -8,54 +8,64 @@ from bookwyrm import models
def init_groups():
"""permission levels"""
groups = ["admin", "moderator", "editor"]
groups = ["admin", "owner", "moderator", "editor"]
for group in groups:
Group.objects.create(name=group)
Group.objects.get_or_create(name=group)
def init_permissions():
"""permission types"""
permissions = [
{
"codename": "manage_registration",
"name": "allow or prevent user registration",
"groups": ["admin"],
},
{
"codename": "system_administration",
"name": "technical controls",
"groups": ["admin"],
},
{
"codename": "edit_instance_settings",
"name": "change the instance info",
"groups": ["admin"],
"groups": ["admin", "owner"],
},
{
"codename": "set_user_group",
"name": "change what group a user is in",
"groups": ["admin", "moderator"],
"groups": ["admin", "owner", "moderator"],
},
{
"codename": "control_federation",
"name": "control who to federate with",
"groups": ["admin", "moderator"],
"groups": ["admin", "owner", "moderator"],
},
{
"codename": "create_invites",
"name": "issue invitations to join",
"groups": ["admin", "moderator"],
"groups": ["admin", "owner", "moderator"],
},
{
"codename": "moderate_user",
"name": "deactivate or silence a user",
"groups": ["admin", "moderator"],
"groups": ["admin", "owner", "moderator"],
},
{
"codename": "moderate_post",
"name": "delete other users' posts",
"groups": ["admin", "moderator"],
"groups": ["admin", "owner", "moderator"],
},
{
"codename": "edit_book",
"name": "edit book info",
"groups": ["admin", "moderator", "editor"],
"groups": ["admin", "owner", "moderator", "editor"],
},
]
content_type = ContentType.objects.get_for_model(models.User)
for permission in permissions:
permission_obj = Permission.objects.create(
permission_obj, _ = Permission.objects.get_or_create(
codename=permission["codename"],
name=permission["name"],
content_type=content_type,
@ -107,10 +117,12 @@ def init_connectors():
def init_settings():
"""info about the instance"""
group_editor = Group.objects.filter(name="editor").first()
models.SiteSettings.objects.create(
support_link="https://www.patreon.com/bookwyrm",
support_title="Patreon",
install_mode=True,
default_user_auth_group=group_editor,
)

View file

@ -1,54 +0,0 @@
""" Get your admin code to allow install """
from django.core.management.base import BaseCommand
from bookwyrm import models
from bookwyrm.settings import VERSION
# pylint: disable=no-self-use
class Command(BaseCommand):
"""command-line options"""
help = "What version is this?"
def add_arguments(self, parser):
"""specify which function to run"""
parser.add_argument(
"--current",
action="store_true",
help="Version stored in database",
)
parser.add_argument(
"--target",
action="store_true",
help="Version stored in settings",
)
parser.add_argument(
"--update",
action="store_true",
help="Update database version",
)
# pylint: disable=unused-argument
def handle(self, *args, **options):
"""execute init"""
site = models.SiteSettings.objects.get()
current = site.version or "0.0.1"
target = VERSION
if options.get("current"):
print(current)
return
if options.get("target"):
print(target)
return
if options.get("update"):
site.version = target
site.save()
return
if current != target:
print(f"{current}/{target}")
else:
print(current)

View file

@ -0,0 +1,12 @@
""" PROCEED WITH CAUTION: uses deduplication fields to permanently
merge author data objects """
from bookwyrm import models
from bookwyrm.management.merge_command import MergeCommand
class Command(MergeCommand):
"""merges two authors by ID"""
help = "merges specified authors into one"
MODEL = models.Author

View file

@ -0,0 +1,12 @@
""" PROCEED WITH CAUTION: uses deduplication fields to permanently
merge edition data objects """
from bookwyrm import models
from bookwyrm.management.merge_command import MergeCommand
class Command(MergeCommand):
"""merges two editions by ID"""
help = "merges specified editions into one"
MODEL = models.Edition

View file

@ -0,0 +1,12 @@
""" PROCEED WITH CAUTION: uses deduplication fields to permanently
merge work data objects """
from bookwyrm import models
from bookwyrm.management.merge_command import MergeCommand
class Command(MergeCommand):
"""merges two works by ID"""
help = "merges specified works into one"
MODEL = models.Work

View file

@ -0,0 +1,22 @@
"""deactivate two factor auth"""
from django.core.management.base import BaseCommand, CommandError
from bookwyrm import models
class Command(BaseCommand):
"""command-line options"""
help = "Remove Two Factor Authorisation from user"
def add_arguments(self, parser):
parser.add_argument("username")
def handle(self, *args, **options):
name = options["username"]
user = models.User.objects.get(localname=name)
user.two_factor_auth = False
user.save(broadcast=False, update_fields=["two_factor_auth"])
self.stdout.write(
self.style.SUCCESS("Two Factor Authorisation was removed from user")
)

View file

@ -33,10 +33,10 @@ def remove_editions():
class Command(BaseCommand):
"""dedplucate allllll the book data models"""
"""deduplicate allllll the book data models"""
help = "merges duplicate book data"
# pylint: disable=no-self-use,unused-argument
def handle(self, *args, **options):
"""run deudplications"""
"""run deduplications"""
remove_editions()

View file

@ -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("🧑‍🚒 ⎨ Im all done! ✧ Enjoy ✧")

View file

@ -0,0 +1,21 @@
""" Repair editions with missing works """
from django.core.management.base import BaseCommand
from bookwyrm import models
class Command(BaseCommand):
"""command-line options"""
help = "Repairs an edition that is in a broken state"
# pylint: disable=unused-argument
def handle(self, *args, **options):
"""Find and repair broken editions"""
# Find broken editions
editions = models.Edition.objects.filter(parent_work__isnull=True)
self.stdout.write(f"Repairing {editions.count()} edition(s):")
# Do repair
for edition in editions:
edition.repair()
self.stdout.write(".", ending="")

View file

@ -0,0 +1,31 @@
""" Actually let's not generate those preview images """
import json
from django.core.management.base import BaseCommand
from bookwyrm.tasks import app
class Command(BaseCommand):
"""Find and revoke image tasks"""
# pylint: disable=unused-argument
def handle(self, *args, **options):
"""revoke nonessential low priority tasks"""
types = [
"bookwyrm.preview_images.generate_edition_preview_image_task",
"bookwyrm.preview_images.generate_user_preview_image_task",
]
self.stdout.write(" | Finding tasks of types:")
self.stdout.write("\n".join(types))
with app.pool.acquire(block=True) as conn:
tasks = conn.default_channel.client.lrange("low_priority", 0, -1)
self.stdout.write(f" | Found {len(tasks)} task(s) in low priority queue")
revoke_ids = []
for task in tasks:
task_json = json.loads(task)
task_type = task_json.get("headers", {}).get("task")
if task_type in types:
revoke_ids.append(task_json.get("headers", {}).get("id"))
self.stdout.write(".", ending="")
self.stdout.write(f"\n | Revoking {len(revoke_ids)} task(s)")
app.control.revoke(revoke_ids)

View file

@ -0,0 +1,37 @@
from django.core.management.base import BaseCommand
class MergeCommand(BaseCommand):
"""base class for merge commands"""
def add_arguments(self, parser):
"""add the arguments for this command"""
parser.add_argument("--canonical", type=int, required=True)
parser.add_argument("--other", type=int, required=True)
parser.add_argument(
"--dry_run",
action="store_true",
help="don't actually merge, only print what would happen",
)
# pylint: disable=no-self-use,unused-argument
def handle(self, *args, **options):
"""merge the two objects"""
model = self.MODEL
try:
canonical = model.objects.get(id=options["canonical"])
except model.DoesNotExist:
print("canonical book doesnt exist!")
return
try:
other = model.objects.get(id=options["other"])
except model.DoesNotExist:
print("other book doesnt exist!")
return
absorbed_fields = other.merge_into(canonical, dry_run=options["dry_run"])
action = "would be" if options["dry_run"] else "has been"
print(f"{other.remote_id} {action} merged into {canonical.remote_id}")
print(f"absorbed fields: {absorbed_fields}")

View file

@ -1,3 +1,4 @@
""" look at all this nice middleware! """
from .timezone_middleware import TimezoneMiddleware
from .ip_middleware import IPBlocklistMiddleware
from .file_too_big import FileTooBig

View file

@ -0,0 +1,30 @@
"""Middleware to display a custom 413 error page"""
from django.http import HttpResponse
from django.shortcuts import render
from django.core.exceptions import RequestDataTooBig
class FileTooBig:
"""Middleware to display a custom page when a
RequestDataTooBig exception is thrown"""
def __init__(self, get_response):
"""boilerplate __init__ from Django docs"""
self.get_response = get_response
def __call__(self, request):
"""If RequestDataTooBig is thrown, render the 413 error page"""
try:
body = request.body # pylint: disable=unused-variable
except RequestDataTooBig:
rendered = render(request, "413.html")
response = HttpResponse(rendered)
return response
response = self.get_response(request)
return response

View file

@ -1467,7 +1467,7 @@ class Migration(migrations.Migration):
(
"expiry",
models.DateTimeField(
default=bookwyrm.models.site.get_passowrd_reset_expiry
default=bookwyrm.models.site.get_password_reset_expiry
),
),
(

View file

@ -6,7 +6,7 @@ from bookwyrm.connectors.abstract_connector import infer_physical_format
def infer_format(app_registry, schema_editor):
"""set the new phsyical format field based on existing format data"""
"""set the new physical format field based on existing format data"""
db_alias = schema_editor.connection.alias
editions = (

View file

@ -5,7 +5,7 @@ from bookwyrm.settings import DOMAIN
def remove_self_connector(app_registry, schema_editor):
"""set the new phsyical format field based on existing format data"""
"""set the new physical format field based on existing format data"""
db_alias = schema_editor.connection.alias
app_registry.get_model("bookwyrm", "Connector").objects.using(db_alias).filter(
connector_file="self_connector"

View file

@ -14,6 +14,8 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="annualgoal",
name="year",
field=models.IntegerField(default=bookwyrm.models.user.get_current_year),
field=models.IntegerField(
default=bookwyrm.models.annual_goal.get_current_year
),
),
]

View file

@ -0,0 +1,40 @@
# Generated by Django 3.2.14 on 2022-07-15 19:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0153_merge_20220706_2141"),
]
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)"),
("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)"),
("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,
),
),
]

View file

@ -0,0 +1,25 @@
# Generated by Django 3.2.14 on 2022-07-09 23:33
from django.db import migrations, models
def existing_users_default(apps, schema_editor):
db_alias = schema_editor.connection.alias
user_model = apps.get_model("bookwyrm", "User")
user_model.objects.using(db_alias).filter(local=True).update(show_guided_tour=False)
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0154_alter_user_preferred_language"),
]
operations = [
migrations.AddField(
model_name="user",
name="show_guided_tour",
field=models.BooleanField(default=True),
),
migrations.RunPython(existing_users_default, migrations.RunPython.noop),
]

View file

@ -0,0 +1,41 @@
# Generated by Django 3.2.14 on 2022-08-02 18:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0155_user_show_guided_tour"),
]
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)"),
("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,
),
),
]

View file

@ -0,0 +1,647 @@
# Generated by Django 3.2.15 on 2022-09-09 23:38
import bookwyrm.models.fields
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0156_alter_user_preferred_language"),
]
operations = [
migrations.AlterField(
model_name="review",
name="rating",
field=bookwyrm.models.fields.DecimalField(
blank=True,
decimal_places=2,
default=None,
max_digits=3,
null=True,
validators=[
django.core.validators.MinValueValidator(0.5),
django.core.validators.MaxValueValidator(5),
],
),
),
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/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,
),
),
]

View file

@ -0,0 +1,65 @@
# Generated by Django 3.2.15 on 2022-09-19 16:34
import bookwyrm.models.fields
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0157_auto_20220909_2338"),
]
operations = [
migrations.AddField(
model_name="automod",
name="created_date",
field=models.DateTimeField(
auto_now_add=True, default=django.utils.timezone.now
),
preserve_default=False,
),
migrations.AddField(
model_name="automod",
name="remote_id",
field=bookwyrm.models.fields.RemoteIdField(
max_length=255,
null=True,
validators=[bookwyrm.models.fields.validate_remote_id],
),
),
migrations.AddField(
model_name="automod",
name="updated_date",
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name="emailblocklist",
name="remote_id",
field=bookwyrm.models.fields.RemoteIdField(
max_length=255,
null=True,
validators=[bookwyrm.models.fields.validate_remote_id],
),
),
migrations.AddField(
model_name="emailblocklist",
name="updated_date",
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name="ipblocklist",
name="remote_id",
field=bookwyrm.models.fields.RemoteIdField(
max_length=255,
null=True,
validators=[bookwyrm.models.fields.validate_remote_id],
),
),
migrations.AddField(
model_name="ipblocklist",
name="updated_date",
field=models.DateTimeField(auto_now=True),
),
]

View file

@ -0,0 +1,33 @@
# Generated by Django 3.2.15 on 2022-09-24 06:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0158_auto_20220919_1634"),
]
operations = [
migrations.AddField(
model_name="user",
name="hotp_count",
field=models.IntegerField(blank=True, default=0, null=True),
),
migrations.AddField(
model_name="user",
name="hotp_secret",
field=models.CharField(blank=True, default=None, max_length=32, null=True),
),
migrations.AddField(
model_name="user",
name="otp_secret",
field=models.CharField(blank=True, default=None, max_length=32, null=True),
),
migrations.AddField(
model_name="user",
name="two_factor_auth",
field=models.BooleanField(blank=True, default=None, null=True),
),
]

View file

@ -0,0 +1,52 @@
# Generated by Django 3.2.15 on 2022-11-01 22:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0159_auto_20220924_0634"),
]
operations = [
migrations.AddField(
model_name="user",
name="allow_reactivation",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="connector",
name="deactivation_reason",
field=models.CharField(
blank=True,
choices=[
("pending", "Pending"),
("self_deletion", "Self deletion"),
("self_deactivation", "Self deactivation"),
("moderator_suspension", "Moderator suspension"),
("moderator_deletion", "Moderator deletion"),
("domain_block", "Domain block"),
],
max_length=255,
null=True,
),
),
migrations.AlterField(
model_name="user",
name="deactivation_reason",
field=models.CharField(
blank=True,
choices=[
("pending", "Pending"),
("self_deletion", "Self deletion"),
("self_deactivation", "Self deactivation"),
("moderator_suspension", "Moderator suspension"),
("moderator_deletion", "Moderator deletion"),
("domain_block", "Domain block"),
],
max_length=255,
null=True,
),
),
]

View file

@ -0,0 +1,32 @@
# Generated by Django 3.2.15 on 2022-11-05 20:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0159_auto_20220924_0634"),
]
operations = [
migrations.AddField(
model_name="importitem",
name="task_id",
field=models.CharField(blank=True, max_length=200, null=True),
),
migrations.AddField(
model_name="importjob",
name="status",
field=models.CharField(
choices=[
("pending", "Pending"),
("active", "Active"),
("complete", "Complete"),
("stopped", "Stopped"),
],
max_length=50,
null=True,
),
),
]

View file

@ -0,0 +1,28 @@
# Generated by Django 3.2.15 on 2022-11-05 20:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0160_auto_20221105_2030"),
]
operations = [
migrations.AlterField(
model_name="importjob",
name="status",
field=models.CharField(
choices=[
("pending", "Pending"),
("active", "Active"),
("complete", "Complete"),
("stopped", "Stopped"),
],
default="pending",
max_length=50,
null=True,
),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.2.15 on 2022-11-05 22:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0161_alter_importjob_status"),
]
operations = [
migrations.AddField(
model_name="importjob",
name="task_id",
field=models.CharField(blank=True, max_length=200, null=True),
),
]

View file

@ -0,0 +1,13 @@
# Generated by Django 3.2.15 on 2022-11-10 20:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0160_auto_20221101_2251"),
("bookwyrm", "0162_importjob_task_id"),
]
operations = []

View file

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2022-11-15 21:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0163_merge_0160_auto_20221101_2251_0162_importjob_task_id"),
]
operations = [
migrations.AddField(
model_name="status",
name="ready",
field=models.BooleanField(default=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2022-11-15 22:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0164_status_ready"),
]
operations = [
migrations.AlterField(
model_name="inviterequest",
name="answer",
field=models.TextField(blank=True, max_length=255, null=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2022-11-17 21:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0165_alter_inviterequest_answer"),
]
operations = [
migrations.AddField(
model_name="sitesettings",
name="imports_enabled",
field=models.BooleanField(default=True),
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 3.2.16 on 2022-11-25 19:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0166_sitesettings_imports_enabled"),
]
operations = [
migrations.AddField(
model_name="sitesettings",
name="impressum",
field=models.TextField(default="Add a impressum here."),
),
migrations.AddField(
model_name="sitesettings",
name="show_impressum",
field=models.BooleanField(default=False),
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 3.2.16 on 2022-12-05 13:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0166_sitesettings_imports_enabled"),
]
operations = [
migrations.AddField(
model_name="sitesettings",
name="import_size_limit",
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name="sitesettings",
name="import_limit_reset",
field=models.IntegerField(default=0),
),
]

View file

@ -0,0 +1,28 @@
# Generated by Django 3.2.16 on 2022-12-05 17:01
import bookwyrm.models.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0167_auto_20221125_1900"),
]
operations = [
migrations.AddField(
model_name="author",
name="aasin",
field=bookwyrm.models.fields.CharField(
blank=True, max_length=255, null=True
),
),
migrations.AddField(
model_name="book",
name="aasin",
field=bookwyrm.models.fields.CharField(
blank=True, max_length=255, null=True
),
),
]

View file

@ -0,0 +1,63 @@
""" I added two new permission types and a new group to the management command that
creates the database on install, this creates them for existing instances """
# Generated by Django 3.2.16 on 2022-12-05 23:31
from django.db import migrations
def create_groups_and_perms(apps, schema_editor):
"""create the new "owner" group and "system admin" permission"""
db_alias = schema_editor.connection.alias
group_model = apps.get_model("auth", "Group")
# Add the "owner" group, if needed
owner_group, group_created = group_model.objects.using(db_alias).get_or_create(
name="owner"
)
# Create perms, if needed
user_model = apps.get_model("bookwyrm", "User")
content_type_model = apps.get_model("contenttypes", "ContentType")
content_type = content_type_model.objects.get_for_model(user_model)
perms_model = apps.get_model("auth", "Permission")
reg_perm, perm_created = perms_model.objects.using(db_alias).get_or_create(
codename="manage_registration",
name="allow or prevent user registration",
content_type=content_type,
)
admin_perm, admin_perm_created = perms_model.objects.using(db_alias).get_or_create(
codename="system_administration",
name="technical controls",
content_type=content_type,
)
# Add perms to the group if anything was created
if group_created or perm_created or admin_perm_created:
perms = [
"edit_instance_settings",
"set_user_group",
"control_federation",
"create_invites",
"moderate_user",
"moderate_post",
"edit_book",
]
owner_group.permissions.set(
perms_model.objects.using(db_alias).filter(codename__in=perms).all()
)
# also extend these perms to admins
# This is get or create so the tests don't fail -- it should already exist
admin_group, _ = group_model.objects.using(db_alias).get_or_create(name="admin")
admin_group.permissions.add(reg_perm)
admin_group.permissions.add(admin_perm)
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0167_auto_20221125_1900"),
]
operations = [
migrations.RunPython(create_groups_and_perms, migrations.RunPython.noop)
]

View file

@ -0,0 +1,28 @@
# Generated by Django 3.2.16 on 2022-12-06 09:02
import bookwyrm.models.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0168_auto_20221205_1701"),
]
operations = [
migrations.AddField(
model_name="author",
name="isfdb",
field=bookwyrm.models.fields.CharField(
blank=True, max_length=255, null=True
),
),
migrations.AddField(
model_name="book",
name="isfdb",
field=bookwyrm.models.fields.CharField(
blank=True, max_length=255, null=True
),
),
]

View file

@ -0,0 +1,13 @@
# Generated by Django 3.2.16 on 2022-12-11 20:00
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0168_auto_20221205_2331"),
("bookwyrm", "0169_auto_20221206_0902"),
]
operations = []

View 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,
),
),
]

View file

@ -0,0 +1,13 @@
# Generated by Django 3.2.16 on 2022-12-19 20:20
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0167_sitesettings_import_size_limit"),
("bookwyrm", "0170_merge_0168_auto_20221205_2331_0169_auto_20221206_0902"),
]
operations = []

View 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,
),
),
]

View file

@ -0,0 +1,21 @@
# Generated by Django 3.2.16 on 2023-01-15 08:38
import bookwyrm.models.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0172_alter_user_preferred_language"),
]
operations = [
migrations.AddField(
model_name="author",
name="website",
field=bookwyrm.models.fields.CharField(
blank=True, max_length=255, null=True
),
),
]

View file

@ -0,0 +1,34 @@
# Generated by Django 3.2.16 on 2022-12-27 21:34
from django.db import migrations, models
import django.db.models.deletion
def backfill_sitesettings(apps, schema_editor):
db_alias = schema_editor.connection.alias
group_model = apps.get_model("auth", "Group")
editor_group = group_model.objects.using(db_alias).filter(name="editor").first()
sitesettings_model = apps.get_model("bookwyrm", "SiteSettings")
sitesettings_model.objects.update(default_user_auth_group=editor_group)
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0175_merge_0173_author_website_0174_merge_20230111_1523"),
]
operations = [
migrations.AddField(
model_name="sitesettings",
name="default_user_auth_group",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.RESTRICT,
to="auth.group",
),
),
migrations.RunPython(backfill_sitesettings, migrations.RunPython.noop),
]

View file

@ -0,0 +1,13 @@
# Generated by Django 3.2.16 on 2023-01-02 14:44
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0171_merge_20221219_2020"),
("bookwyrm", "0172_alter_user_preferred_language"),
]
operations = []

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