9 Commits

Author SHA1 Message Date
Eva
ae82ffe3d5 Merge 4dd445e0f0 into 376f687c38 2025-02-16 22:21:27 +13:00
376f687c38 chore: questionable is not a recognized rating 2025-02-11 21:50:27 +01:00
4fd848abf2 doc: use docker compose instead of docker-compose
The minimum version requirements are rough guesses, in practice any decently modern docker installation should work.
2025-02-11 21:25:10 +01:00
Eva
4dd445e0f0 client/posts: allow downloading swf file from right click menu 2024-03-21 23:49:17 +01:00
Eva
8f0981a3f3 client/posts: different approach for flash background
Something weird was happening during templating, it worked but would
surround the style attribute with %%%template1 and %%%template3
2024-03-21 23:49:17 +01:00
Eva
dd56a3b529 client/posts: warning on ruffle load failure and browsers without flash 2024-03-21 23:49:17 +01:00
Eva
9c70202322 client/posts: use flash thumbnail as a preroll 2024-03-21 23:49:17 +01:00
Eva
3079b86b80 client/posts: use ruffle polyfill for swf playback in modern browsers 2024-03-21 23:49:17 +01:00
Eva
b34d38bfac server/images: use ruffle exporter for swf thumbnails
Works with far more SWFs than ffmpeg. Using OpenGL backend.
2024-03-21 23:49:17 +01:00
9 changed files with 50 additions and 21 deletions

View File

@ -45,6 +45,8 @@
.post-content .post-content
margin: 0 margin: 0
background-size: cover
background-repeat: no-repeat
.after-mobile-controls .after-mobile-controls
width: 100% width: 100%

View File

@ -28,5 +28,6 @@
<div id='content-holder'></div> <div id='content-holder'></div>
<script type='text/javascript' src='js/vendor.min.js'></script> <script type='text/javascript' src='js/vendor.min.js'></script>
<script type='text/javascript' src='js/app.min.js'></script> <script type='text/javascript' src='js/app.min.js'></script>
<script type='text/javascript' src='https://unpkg.com/@ruffle-rs/ruffle' async></script>
</body> </body>
</html> </html>

View File

@ -1,4 +1,4 @@
<div class='post-content post-type-<%- ctx.post.type %>'> <div class='post-content post-type-<%- ctx.post.type %>' style='<%- ctx.post.type === 'flash' ? 'background-image: url('+ctx.post.thumbnailUrl+')' : '' %>'>
<% if (['image', 'animation'].includes(ctx.post.type)) { %> <% if (['image', 'animation'].includes(ctx.post.type)) { %>
<img class='resize-listener' alt='' src='<%- ctx.post.contentUrl %>'/> <img class='resize-listener' alt='' src='<%- ctx.post.contentUrl %>'/>
@ -6,8 +6,9 @@
<% } else if (ctx.post.type === 'flash') { %> <% } else if (ctx.post.type === 'flash') { %>
<object class='resize-listener' width='<%- ctx.post.canvasWidth %>' height='<%- ctx.post.canvasHeight %>' data='<%- ctx.post.contentUrl %>'> <object class='resize-listener' width='<%- ctx.post.canvasWidth %>' height='<%- ctx.post.canvasHeight %>' data='<%- ctx.post.contentUrl %>'>
<param name='wmode' value='opaque'/> <param name='wmode' value='transparent'/>
<param name='movie' value='<%- ctx.post.contentUrl %>'/> <param name='movie' value='<%- ctx.post.contentUrl %>'/>
<div class='messages'><div class='message-wrapper'><div class='message error'>Your browser does not support Flash.</div></div></div>
</object> </object>
<% } else if (ctx.post.type === 'video') { %> <% } else if (ctx.post.type === 'video') { %>

View File

@ -42,6 +42,17 @@ const pools = require("./pools.js");
const api = require("./api.js"); const api = require("./api.js");
const settings = require("./models/settings.js"); const settings = require("./models/settings.js");
const rgb2hex = (rgb) => `#${rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(n => parseInt(n, 10).toString(16).padStart(2, '0')).join('')}`
window.RufflePlayer = window.RufflePlayer || {};
window.RufflePlayer.config = {
"polyfills": true,
"autoplay": "off",
"warnOnUnsupportedContent": false,
"showSwfDownload": true,
"splashScreen": false,
};
Promise.resolve() Promise.resolve()
.then(() => api.fetchConfig()) .then(() => api.fetchConfig())
.then( .then(
@ -99,6 +110,8 @@ Promise.resolve()
if (settings.get().darkTheme) { if (settings.get().darkTheme) {
document.body.classList.add("darktheme"); document.body.classList.add("darktheme");
} }
window.RufflePlayer.config.autoplay = settings.get().autoplayVideos ? "auto" : "off"
}) })
.then(() => api.loginFromCookies()) .then(() => api.loginFromCookies())
.then( .then(

View File

@ -30,6 +30,7 @@ class SettingsView extends events.EventTarget {
_evtSubmit(e) { _evtSubmit(e) {
e.preventDefault(); e.preventDefault();
window.RufflePlayer.config.autoplay = this._find("autoplay-videos").checked ? "auto" : "off"
this.dispatchEvent( this.dispatchEvent(
new CustomEvent("submit", { new CustomEvent("submit", {
detail: { detail: {

View File

@ -789,7 +789,7 @@ data.
| `fav-time` | alias of `fav-date` | | `fav-time` | alias of `fav-date` |
| `feature-date` | featured at given date | | `feature-date` | featured at given date |
| `feature-time` | alias of `feature-time` | | `feature-time` | alias of `feature-time` |
| `safety` | having given safety. `<value>` can be either `safe`, `sketchy` (or `questionable`) or `unsafe`. | | `safety` | having given safety. `<value>` can be either `safe`, `sketchy` or `unsafe`. |
| `rating` | alias of `safety` | | `rating` | alias of `safety` |
**Sort style tokens** **Sort style tokens**

View File

@ -1,5 +1,5 @@
This assumes that you have Docker (version 17.05 or greater) This assumes that you have Docker (version 19.03 or greater)
and Docker Compose (version 1.6.0 or greater) already installed. and the Docker Compose CLI (version 1.27.0 or greater) already installed.
### Prepare things ### Prepare things
@ -38,7 +38,7 @@ and Docker Compose (version 1.6.0 or greater) already installed.
This pulls the latest containers from docker.io: This pulls the latest containers from docker.io:
```console ```console
user@host:szuru$ docker-compose pull user@host:szuru$ docker compose pull
``` ```
If you have modified the application's source and would like to manually If you have modified the application's source and would like to manually
@ -49,17 +49,17 @@ and Docker Compose (version 1.6.0 or greater) already installed.
For first run, it is recommended to start the database separately: For first run, it is recommended to start the database separately:
```console ```console
user@host:szuru$ docker-compose up -d sql user@host:szuru$ docker compose up -d sql
``` ```
To start all containers: To start all containers:
```console ```console
user@host:szuru$ docker-compose up -d user@host:szuru$ docker compose up -d
``` ```
To view/monitor the application logs: To view/monitor the application logs:
```console ```console
user@host:szuru$ docker-compose logs -f user@host:szuru$ docker compose logs -f
# (CTRL+C to exit) # (CTRL+C to exit)
``` ```
@ -84,13 +84,13 @@ and Docker Compose (version 1.6.0 or greater) already installed.
2. Build the containers: 2. Build the containers:
```console ```console
user@host:szuru$ docker-compose build user@host:szuru$ docker compose build
``` ```
That will attempt to build both containers, but you can specify `client` That will attempt to build both containers, but you can specify `client`
or `server` to make it build only one. or `server` to make it build only one.
If `docker-compose build` spits out: If `docker compose build` spits out:
``` ```
ERROR: Service 'server' failed to build: failed to parse platform : "" is an invalid component of "": platform specifier component must match "^[A-Za-z0-9_-]+$": invalid argument ERROR: Service 'server' failed to build: failed to parse platform : "" is an invalid component of "": platform specifier component must match "^[A-Za-z0-9_-]+$": invalid argument
@ -102,7 +102,7 @@ and Docker Compose (version 1.6.0 or greater) already installed.
user@host:szuru$ export DOCKER_BUILDKIT=1; export COMPOSE_DOCKER_CLI_BUILD=1 user@host:szuru$ export DOCKER_BUILDKIT=1; export COMPOSE_DOCKER_CLI_BUILD=1
``` ```
...and run `docker-compose build` again. ...and run `docker compose build` again.
*Note: If your changes are not taking effect in your builds, consider building *Note: If your changes are not taking effect in your builds, consider building
with `--no-cache`.* with `--no-cache`.*
@ -117,7 +117,7 @@ with `--no-cache`.*
run from docker: run from docker:
```console ```console
user@host:szuru$ docker-compose run server ./szuru-admin --help user@host:szuru$ docker compose run server ./szuru-admin --help
``` ```
will give you a breakdown on all available commands. will give you a breakdown on all available commands.

View File

@ -1,9 +1,7 @@
## Example Docker Compose configuration ## Example Docker Compose configuration
## ##
## Use this as a template to set up docker-compose, or as guide to set up other ## Use this as a template to set up docker compose, or as guide to set up other
## orchestration services ## orchestration services
version: '2'
services: services:
server: server:

View File

@ -28,6 +28,9 @@ class Image:
def __init__(self, content: bytes) -> None: def __init__(self, content: bytes) -> None:
self.content = content self.content = content
self._reload_info() self._reload_info()
if self.info["format"]["format_name"] == "swf":
self.content = self.swf_to_png()
self._reload_info()
@property @property
def width(self) -> int: def width(self) -> int:
@ -60,10 +63,7 @@ class Image:
"png", "png",
"-", "-",
] ]
if ( if "duration" in self.info["format"]:
"duration" in self.info["format"]
and self.info["format"]["format_name"] != "swf"
):
duration = float(self.info["format"]["duration"]) duration = float(self.info["format"]["duration"])
if duration > 3: if duration > 3:
cli = [ cli = [
@ -76,6 +76,19 @@ class Image:
self.content = content self.content = content
self._reload_info() self._reload_info()
def swf_to_png(self) -> bytes:
return self._execute(
[
"--silent",
"-g",
"gl",
"--",
"{path}",
"-",
],
program="exporter",
)
def to_png(self) -> bytes: def to_png(self) -> bytes:
return self._execute( return self._execute(
[ [
@ -315,7 +328,7 @@ class Image:
) )
assert "format" in self.info assert "format" in self.info
assert "streams" in self.info assert "streams" in self.info
if len(self.info["streams"]) < 1: if len(self.info["streams"]) < 1 and self.info["format"]["format_name"] != "swf":
logger.warning("The video contains no video streams.") logger.warning("The video contains no video streams.")
raise errors.ProcessingError( raise errors.ProcessingError(
"The video contains no video streams." "The video contains no video streams."