Merge branch 'master' into better-links
This commit is contained in:
commit
4f9d46e1c2
10 changed files with 105 additions and 18 deletions
|
@ -8,7 +8,7 @@ scrubbing](https://sjp.pwn.pl/sjp/;2527372). It is pronounced as *shoorubooru*.
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Post content: images (JPG, PNG, GIF, animated GIF), videos (MP4, WEBM), Flash animations
|
- Post content: images (JPG, PNG, GIF, animated GIF), videos (MP4, WEBM), Flash animations
|
||||||
- Ability to retrieve web video content using [youtube-dl](https://github.com/ytdl-org/youtube-dl)
|
- Ability to retrieve web video content using [yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
||||||
- Post comments
|
- Post comments
|
||||||
- Post notes / annotations, including arbitrary polygons
|
- Post notes / annotations, including arbitrary polygons
|
||||||
- Rich JSON REST API ([see documentation](doc/API.md))
|
- Rich JSON REST API ([see documentation](doc/API.md))
|
||||||
|
|
|
@ -127,6 +127,10 @@ $comment-border-color = #DDD
|
||||||
color: mix($main-color, $inactive-link-color-darktheme)
|
color: mix($main-color, $inactive-link-color-darktheme)
|
||||||
|
|
||||||
.comment-content
|
.comment-content
|
||||||
|
p
|
||||||
|
word-wrap: normal
|
||||||
|
word-break: break-all
|
||||||
|
|
||||||
ul, ol
|
ul, ol
|
||||||
list-style-position: inside
|
list-style-position: inside
|
||||||
margin: 1em 0
|
margin: 1em 0
|
||||||
|
|
|
@ -300,10 +300,10 @@ a .access-key
|
||||||
background-size: 20px 20px
|
background-size: 20px 20px
|
||||||
img
|
img
|
||||||
opacity: 0
|
opacity: 0
|
||||||
width: inherit
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
video
|
video
|
||||||
width: inherit
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
|
|
||||||
.flexbox-dummy
|
.flexbox-dummy
|
||||||
|
|
|
@ -43,6 +43,8 @@ class PoolListController {
|
||||||
this._headerView.addEventListener(
|
this._headerView.addEventListener(
|
||||||
"submit",
|
"submit",
|
||||||
(e) => this._evtSubmit(e),
|
(e) => this._evtSubmit(e),
|
||||||
|
);
|
||||||
|
this._headerView.addEventListener(
|
||||||
"navigate",
|
"navigate",
|
||||||
(e) => this._evtNavigate(e)
|
(e) => this._evtNavigate(e)
|
||||||
);
|
);
|
||||||
|
|
14
doc/API.md
14
doc/API.md
|
@ -54,7 +54,7 @@
|
||||||
- [Deleting pool category](#deleting-pool-category)
|
- [Deleting pool category](#deleting-pool-category)
|
||||||
- [Setting default pool category](#setting-default-pool-category)
|
- [Setting default pool category](#setting-default-pool-category)
|
||||||
- Pools
|
- Pools
|
||||||
- [Listing pools](#listing-pool)
|
- [Listing pools](#listing-pools)
|
||||||
- [Creating pool](#creating-pool)
|
- [Creating pool](#creating-pool)
|
||||||
- [Updating pool](#updating-pool)
|
- [Updating pool](#updating-pool)
|
||||||
- [Getting pool](#getting-pool)
|
- [Getting pool](#getting-pool)
|
||||||
|
@ -165,9 +165,9 @@ way. The files, however, should be passed as regular fields appended with a
|
||||||
accepts a file named `content`, the client should pass
|
accepts a file named `content`, the client should pass
|
||||||
`{"contentUrl":"http://example.com/file.jpg"}` as a part of the JSON message
|
`{"contentUrl":"http://example.com/file.jpg"}` as a part of the JSON message
|
||||||
body. When creating or updating post content using this method, the server can
|
body. When creating or updating post content using this method, the server can
|
||||||
also be configured to employ [youtube-dl](https://github.com/ytdl-org/youtube-dl)
|
also be configured to employ [yt-dlp](https://github.com/yt-dlp/yt-dlp) to
|
||||||
to download content from popular sites such as youtube, gfycat, etc. Access to
|
download content from popular sites such as youtube, gfycat, etc. Access to
|
||||||
youtube-dl can be configured with the `'uploads:use_downloader'` permission
|
yt-dlp can be configured with the `'uploads:use_downloader'` permission
|
||||||
|
|
||||||
Finally, in some cases the user might want to reuse one file between the
|
Finally, in some cases the user might want to reuse one file between the
|
||||||
requests to save the bandwidth (for example, reverse search + consecutive
|
requests to save the bandwidth (for example, reverse search + consecutive
|
||||||
|
@ -323,7 +323,7 @@ data.
|
||||||
{
|
{
|
||||||
"name": <name>,
|
"name": <name>,
|
||||||
"color": <color>,
|
"color": <color>,
|
||||||
"order": <order> // optional
|
"order": <order>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1389,7 +1389,7 @@ data.
|
||||||
## Creating pool
|
## Creating pool
|
||||||
- **Request**
|
- **Request**
|
||||||
|
|
||||||
`POST /pools/create`
|
`POST /pool`
|
||||||
|
|
||||||
- **Input**
|
- **Input**
|
||||||
|
|
||||||
|
@ -2491,7 +2491,7 @@ One file together with its metadata posted to the site.
|
||||||
## Micro post
|
## Micro post
|
||||||
**Description**
|
**Description**
|
||||||
|
|
||||||
A [post resource](#post) stripped down to `name` and `thumbnailUrl` fields.
|
A [post resource](#post) stripped down to `id` and `thumbnailUrl` fields.
|
||||||
|
|
||||||
## Note
|
## Note
|
||||||
**Description**
|
**Description**
|
||||||
|
|
|
@ -23,15 +23,15 @@ RUN apk --no-cache add \
|
||||||
py3-pillow \
|
py3-pillow \
|
||||||
py3-pynacl \
|
py3-pynacl \
|
||||||
py3-tz \
|
py3-tz \
|
||||||
py3-pyrfc3339 \
|
py3-pyrfc3339
|
||||||
&& pip3 install --no-cache-dir --disable-pip-version-check \
|
RUN pip3 install --no-cache-dir --disable-pip-version-check \
|
||||||
"alembic>=0.8.5" \
|
"alembic>=0.8.5" \
|
||||||
"coloredlogs==5.0" \
|
"coloredlogs==5.0" \
|
||||||
"pyheif==0.6.1" \
|
"pyheif==0.6.1" \
|
||||||
"heif-image-plugin>=0.3.2" \
|
"heif-image-plugin>=0.3.2" \
|
||||||
youtube_dl \
|
yt-dlp \
|
||||||
"pillow-avif-plugin>=1.1.0" \
|
"pillow-avif-plugin~=1.1.0"
|
||||||
&& apk --no-cache del py3-pip
|
RUN apk --no-cache del py3-pip
|
||||||
|
|
||||||
COPY ./ /opt/app/
|
COPY ./ /opt/app/
|
||||||
RUN rm -rf /opt/app/szurubooru/tests
|
RUN rm -rf /opt/app/szurubooru/tests
|
||||||
|
|
|
@ -3,7 +3,7 @@ certifi>=2017.11.5
|
||||||
coloredlogs==5.0
|
coloredlogs==5.0
|
||||||
heif-image-plugin==0.3.2
|
heif-image-plugin==0.3.2
|
||||||
numpy>=1.8.2
|
numpy>=1.8.2
|
||||||
pillow-avif-plugin>=1.1.0
|
pillow-avif-plugin~=1.1.0
|
||||||
pillow>=4.3.0
|
pillow>=4.3.0
|
||||||
psycopg2-binary>=2.6.1
|
psycopg2-binary>=2.6.1
|
||||||
pyheif==0.6.1
|
pyheif==0.6.1
|
||||||
|
@ -12,4 +12,4 @@ pyRFC3339>=1.0
|
||||||
pytz>=2018.3
|
pytz>=2018.3
|
||||||
pyyaml>=3.11
|
pyyaml>=3.11
|
||||||
SQLAlchemy>=1.0.12, <1.4
|
SQLAlchemy>=1.0.12, <1.4
|
||||||
youtube_dl
|
yt-dlp
|
||||||
|
|
|
@ -64,7 +64,7 @@ def download(url: str, use_video_downloader: bool = False) -> bytes:
|
||||||
|
|
||||||
|
|
||||||
def _get_youtube_dl_content_url(url: str) -> str:
|
def _get_youtube_dl_content_url(url: str) -> str:
|
||||||
cmd = ["youtube-dl", "--format", "best", "--no-playlist"]
|
cmd = ["yt-dlp", "--format", "best", "--no-playlist"]
|
||||||
if config.config["user_agent"]:
|
if config.config["user_agent"]:
|
||||||
cmd.extend(["--user-agent", config.config["user_agent"]])
|
cmd.extend(["--user-agent", config.config["user_agent"]])
|
||||||
cmd.extend(["--get-url", url])
|
cmd.extend(["--get-url", url])
|
||||||
|
|
|
@ -122,6 +122,34 @@ def _pool_filter(
|
||||||
)(query, criterion, negated)
|
)(query, criterion, negated)
|
||||||
|
|
||||||
|
|
||||||
|
def _category_filter(
|
||||||
|
query: SaQuery, criterion: Optional[criteria.BaseCriterion], negated: bool
|
||||||
|
) -> SaQuery:
|
||||||
|
assert criterion
|
||||||
|
|
||||||
|
# Step 1. find the id for the category
|
||||||
|
q1 = db.session.query(model.TagCategory.tag_category_id).filter(
|
||||||
|
model.TagCategory.name == criterion.value
|
||||||
|
)
|
||||||
|
|
||||||
|
# Step 2. find the tags with that category
|
||||||
|
q2 = db.session.query(model.Tag.tag_id).filter(
|
||||||
|
model.Tag.category_id.in_(q1)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Step 3. find all posts that have at least one of those tags
|
||||||
|
q3 = db.session.query(model.PostTag.post_id).filter(
|
||||||
|
model.PostTag.tag_id.in_(q2)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Step 4. profit
|
||||||
|
expr = model.Post.post_id.in_(q3)
|
||||||
|
if negated:
|
||||||
|
expr = ~expr
|
||||||
|
|
||||||
|
return query.filter(expr)
|
||||||
|
|
||||||
|
|
||||||
class PostSearchConfig(BaseSearchConfig):
|
class PostSearchConfig(BaseSearchConfig):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.user = None # type: Optional[model.User]
|
self.user = None # type: Optional[model.User]
|
||||||
|
@ -349,6 +377,7 @@ class PostSearchConfig(BaseSearchConfig):
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(["pool"], _pool_filter),
|
(["pool"], _pool_filter),
|
||||||
|
(["category"], _category_filter),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -863,3 +863,55 @@ def test_tumbleweed(
|
||||||
db.session.flush()
|
db.session.flush()
|
||||||
verify_unpaged("special:tumbleweed", [4])
|
verify_unpaged("special:tumbleweed", [4])
|
||||||
verify_unpaged("-special:tumbleweed", [1, 2, 3])
|
verify_unpaged("-special:tumbleweed", [1, 2, 3])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"input,expected_post_ids",
|
||||||
|
[
|
||||||
|
("category:cat1", [1, 2, 3]),
|
||||||
|
("category:cat2", [3, 4]),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_search_by_tag_category(
|
||||||
|
verify_unpaged,
|
||||||
|
post_factory,
|
||||||
|
tag_factory,
|
||||||
|
tag_category_factory,
|
||||||
|
input,
|
||||||
|
expected_post_ids,
|
||||||
|
):
|
||||||
|
cat1 = tag_category_factory(name="cat1")
|
||||||
|
cat2 = tag_category_factory(name="cat2")
|
||||||
|
tag1 = tag_factory(names=["t1"], category=cat1)
|
||||||
|
tag2 = tag_factory(names=["t2"], category=cat1)
|
||||||
|
tag3 = tag_factory(names=["t3"], category=cat2)
|
||||||
|
|
||||||
|
post1 = post_factory(id=1)
|
||||||
|
post1.tags.append(tag1)
|
||||||
|
|
||||||
|
post2 = post_factory(id=2)
|
||||||
|
post2.tags.append(tag2)
|
||||||
|
|
||||||
|
post3 = post_factory(id=3)
|
||||||
|
post3.tags.append(tag1)
|
||||||
|
post3.tags.append(tag3)
|
||||||
|
|
||||||
|
post4 = post_factory(id=4)
|
||||||
|
post4.tags.append(tag3)
|
||||||
|
|
||||||
|
post5 = post_factory(id=5)
|
||||||
|
|
||||||
|
db.session.add_all(
|
||||||
|
[
|
||||||
|
tag1,
|
||||||
|
tag2,
|
||||||
|
tag3,
|
||||||
|
post1,
|
||||||
|
post2,
|
||||||
|
post3,
|
||||||
|
post4,
|
||||||
|
post5,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
db.session.flush()
|
||||||
|
verify_unpaged(input, expected_post_ids)
|
||||||
|
|
Loading…
Reference in a new issue