Commit Graph

689 Commits

Author SHA1 Message Date
kermieisinthehouse 21a86bb452
Fix build for renamed armv6 (#2278) 2022-02-03 11:59:00 +11:00
kermieisinthehouse 10bb9a6abc
Delete funscripts while deleting scene (#2265)
* Delete funscripts while deleting scene
* Indicate that funscripts will be deleted

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2022-02-03 11:58:48 +11:00
kermieisinthehouse 0e514183a7
Desktop integration (#2073)
* Open stash in system tray on Windows/MacOS
* Add desktop notifications
* MacOS Bundling
* Add binary icon

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2022-02-03 11:20:34 +11:00
kermieisinthehouse def9ad88b0
Remove trusted proxies (#2229) 2022-02-03 10:16:22 +11:00
InfiniteTF a3c20ce8da
Add support for submitting performer/scene drafts to stash-box (#2234)
* Add support for submitting performer/scene drafts to stash-box

Co-authored-by: Kermie <kermie@isinthe.house>
2022-02-01 15:06:51 +11:00
Viacheslav Poturaev d9fb51f2f9
Reuse static server for multiple requests (#2258) 2022-01-28 15:20:05 +11:00
kermieisinthehouse e1cf695b65
Deprecate forwarded port (#2228) 2022-01-11 10:09:14 +11:00
kermieisinthehouse 28c72d3ee3
Allow stash to be iframed (#2217) 2022-01-11 10:05:12 +11:00
kermieisinthehouse 13b60e7218
Add preview languages (#2194)
* Add preview languages
* Turkish is completed
* Update README.md
2022-01-05 14:21:15 +11:00
bnkai be5dc7e545
Resolve hostname for chromium RDP requests (#2174) 2022-01-04 15:47:39 +11:00
InfiniteTF 34aea876e8
Add stash-box credentials validation (#2173) 2022-01-04 14:20:31 +11:00
bnkai 849c590b2a
Fix scrubber sprite creation for short video files (#2167)
* Fix scrubber sprite creation for small files
* accept only valid ffprobe nbReadFrames
2022-01-04 13:46:53 +11:00
InfiniteTF bd784cdf96
Fix conversion of multi word stash-box enums (#2191) 2022-01-04 12:55:45 +11:00
InfiniteTF a2bfa9ee79
Fix stash-box batch performer birthdate update (#2189) 2022-01-04 12:15:38 +11:00
bnkai 0c0bdd4e21
Fix oshash calculation for symlinks (#2198) 2022-01-04 11:30:42 +11:00
WithoutPants bdfb8ad567
Support setting scrapers path in UI (#2124)
* Support setting scrapers path in UI
* Refresh scrapers when scrapers path changes
2021-12-20 12:00:26 +11:00
WithoutPants b0cf04865a
Add force transcode option (#2126) 2021-12-20 11:45:36 +11:00
bnkai f830d9cf13
Fix UseFileMetadata when scanning (#2138) 2021-12-19 14:03:46 +11:00
kermieisinthehouse 65b8a3fe96
Whitelist CDN used by playground (#2139) 2021-12-18 11:09:39 +11:00
kermieisinthehouse bf1b835d6d
Fix ffmpeg downloader on windows (#2133) 2021-12-16 13:29:42 +11:00
WithoutPants d25510fdd7
Selective clean (#2125)
* Add backend support for selective clean
* Add selective clean button and dialog
2021-12-16 13:28:44 +11:00
kermieisinthehouse d94e4f9a5b
Add short sprite error logging (#2129) 2021-12-16 11:35:22 +11:00
bnkai 66dd239732
Skip cleaning for search by name scrape queries (#2059)
* Skip pp for search by name queries
* upgrade htmlquery
2021-12-16 11:18:39 +11:00
WithoutPants 439c338049
Add media-src to content-security-policy (#2132) 2021-12-16 09:18:23 +11:00
kermieisinthehouse bbe99a0dd8
Fix Safari websockets requests (#2128) 2021-12-15 21:07:12 +11:00
InfiniteTF b58883c074
Fix image querying (#2119)
* Fix image querying
* Add unit tests

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-12-15 13:56:03 +11:00
WithoutPants d176e9f192
Settings UI refactor (#2086)
* Full width settings page
* Group settings
* Make config fields optional
* auto save on change
* Add settings context
* Refactor stash library section
* Restructure settings
* Refactor tasks page
* Add collapse buttons for setting groups
* Add collapse buttons in library
* Add loading indicator
* Simplify task options. Add details to manual
* Add manual links to tasks page
* Add help tooltips
* Refactor about page
* Refactor log page
* Refactor tools panel
* Refactor plugin page
* Refactor task queue
* Improve disabled styling
2021-12-14 15:06:05 +11:00
kermieisinthehouse b4b955efc8
Fix images loading from stashdb (#2115)
* Allow images from any source

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-12-14 10:13:23 +11:00
kermieisinthehouse 98e836fdb3
Fix auth in CSP (#2112) 2021-12-13 15:45:02 +11:00
kermieisinthehouse b86c9fa8fe
Security Hardening: Content Security Policy + more (#2108)
* Add CSP, varied security headers
2021-12-13 14:54:19 +11:00
WithoutPants 79e01589ca
Include path and hashes in destroy hook input (#2102) 2021-12-13 14:38:00 +11:00
kermieisinthehouse 9a8f05d826
Marker previews should respect preview audio setting (#2101) 2021-12-13 14:09:00 +11:00
agentfisk e8447c520a
Heatmap and speed sorting/filtering for interactive scenes [rewrite] (#2096)
* add InteractiveSpeed to scene model
* add InteractiveHeatmapSpeedGenerator
* add GenerateInteractiveHeatmapSpeedTask
* add InteractiveHeatmapSpeedTask to GenerateJob
* add InteractiveHeatmap on sceneRoutes
* delete heatmap when scene is destroyed
* render interactive heatmap in GridCard
* render InteractiveSpeed on SceneCard
* render InteractiveSpeed in SceneFileInfoPanel
* InteractiveSpeed filters
2021-12-13 13:41:07 +11:00
InfiniteTF f3ab6578d9
Add performer aliases to stash-box tagging/scraping (#2091)
* Add performer aliases to stash-box tagging/scraping
2021-12-08 09:36:06 +11:00
Esteban Sanchez 70d9a05580
Use inner join when getting images in a gallery (#2083)
* Added joinType to join struct
* Added addInnerJoin function to perform INNER JOIN type of joins
* Added innerJoin function to perform INNER JOIN type of joins
* Use inner joins when querying images in a gallery
* Renamed addJoin to addLeftJoin
2021-12-06 12:30:40 +11:00
SmallCoccinelle cf4ab843f6
Fix setting images (#2068)
When postprocessing, pass the images by reference rather than value,
so we get the Image fields populated correctly in the output.
2021-11-29 14:54:01 +11:00
kermieisinthehouse 7953fa356f
Add Finnish Locale (#2075)
* Add Finnish Locale
* Update readme
2021-11-29 14:43:18 +11:00
WithoutPants 9ebf8331ac
Refactor file deletion (#1954)
* Add file deleter
* Change scene delete code
* Add image/gallery delete code
* Don't remove stash library paths
* Fail silently if file does not exist
2021-11-29 14:08:32 +11:00
Releck 59883df115
Fix identify ScrapedScene conversion (#2071) 2021-11-29 13:42:23 +11:00
SmallCoccinelle 09c4c4173d
Support a minModTime input on metadata scans. (#1951)
* Support a maxAge input on metadata scans.

Extend the GraphQL world with a Duration scalar. It is parsed as a
typical Go duration, i.e., "4h" is 4 hours. Alternatively, one can
pass an integer which is interpreted as seconds.

Extend Mutation.metadataScan(input: $input) to support a new optional
value, maxAge. If set, the scanner will exit early if the file it
is looking at has an mtime older than the cutOff point generated by

now() - maxAge

This speeds up scanning in the case where the user knows how old the
changes on disk are, by exiting the scan early if that is the case.

* Change maxAge into minModTime

Introduce a `Timestamp` scalar, so we have a scalar we control. Let
it accept three formats:

* RFC3339Nano
* @UNIX where UNIX is a unix-timestamp: seconds after 01-01-1970
* '<4h': a timestamp relative to the current server time

This scalar parses to a time.Time.

Use MinModTime in the scanner to filter out a large number of scan
analyzes by exiting the scan operation early.

* Heed the linter, perform errcheck

* Rename test vars for consistency.

* Code review: move minModTime into queuefiles

* Remove the ability to input Unix timestamps

Test failures on the CI-system explains why this is undesirable. It is
not clear what timezone one is operating in when entering a unix
timestamp. We could go with UTC, but it is so much easier to require an
RFC3339 timestamp, which avoids this problem entirely.

* Move the minModTime field into filters

Create a new filter input object for metadata scans, and push the
minModTime field in there. If we come up with new filters, they can
be added to that input object rather than cluttering the main input
object.

* Use utils.ParseDateStringAsTime

Replace time.Parse with utils.ParseDateStringAsTime

While here, add some more test cases for that parser.
2021-11-26 11:48:31 +11:00
SmallCoccinelle 4089fcf1e2
Scraper refactor middle (#2043)
* Push scrapeByURL into scrapers

Replace ScrapePerfomerByURL, ScrapeMovie..., ... with ScrapeByURL in
the scraperActionImpl interface. This allows us to delete a lot of
repeated code in the scrapers and replace the central part with a
switch on the scraper type.

* Fold name scraping into one call

Follow up on scraper refactoring. Name scrapers use the same code path.
This allows us to restructure some code and kill some functions, adding
variance to the name scraping code. It allows us to remove some code
repetition as well.

* Do not export loop refs.

* Simplify fragment scraping

Generalize fragment scrapers into ScrapeByFragment. This simplifies
fragment code flows into a simpler pathing which should be easier
to handle in the future.

* Eliminate more context.TODO()

In a number of cases, we have a context now. Use the context rather than
TODO() for those cases in order to make those operations cancellable.

* Pass the context for the stashbox scraper

This removes all context.TODO() in the path of the stashbox scraper,
and replaces it with the context that's present on each of the paths.

* Pass the context into subscrapers

Mostly a mechanical update, where we pass in the context for
subscraping. This removes the final context.TODO() in the scraper
code.

* Warn on unknown fields from scripts

A common mistake for new script writers are that they return fields
not known to stash. For instance the name "description" is used rather
than "details".

Decode disallowing unknown fields. If this fails, use a tee-reader to
fall back to the old behavior, but print a warning for the user in this
case. Thus, we retain the old behavior, but print warnings for scripts
which fails the more strict unknown-fields detection.

* Nil-check before running the postprocessing chain

Fixes panics when scraping returns nil values.

* Lift nil-ness in post-postprocessing

If the struct we are trying to post-process is nil, we shouldn't
enter the postprocessing flow at all. Pass the struct as a value
rather than a pointer, eliminating nil-checks as we go. Use the
top-level postProcess call to make the nil-check and then abort there
if the object we are looking at is nil.

* Allow conversion routines to handle values

If we have a non-pointer type in the interface, we should also convert
those into ScrapedContent. Otherwise we get errors on deprecated
functions.
2021-11-26 11:20:06 +11:00
WithoutPants 19e69f5310
Prefer studio name later in filename (#2057) 2021-11-26 08:29:25 +11:00
WithoutPants ff32f22c1a
Tasks page refactor (#1949)
* Add scan dialog
* Add Auto Tag dialog
* Refactor and combine Generate dialog
* Add clean dialog
* Support scan task default setting
* Support saving auto tag defaults
* Support for generate defaults
2021-11-24 09:09:47 +11:00
WithoutPants c98ad7a62c
Validate SQLiteDate (#2052)
* Reject invalid SQLiteDate strings
* Add unit tests
* Handle null values
2021-11-23 08:18:43 +11:00
WithoutPants f2903d4dcf
Fix setting autostart options (#2050) 2021-11-22 16:19:59 +11:00
WithoutPants 2277d0a919
Add search string parsing (#1982)
* Add search string parsing
* Add manual page
2021-11-22 14:59:22 +11:00
kermieisinthehouse 27c0fc8a18
Varied macOS fixes (#2044)
* Fix selects, fix ffprobe download, fix baseurl in dev server
2021-11-22 12:44:24 +11:00
kermieisinthehouse 74fcaa9a3f
Reenable gzipping, pull in statigz fix, fix proxy prefix (#2039)
Co-authored-by: peolic <66393006+peolic@users.noreply.github.com>
2021-11-19 13:30:21 +11:00
SmallCoccinelle 92a5d96d3b
Add a TagMergePost post-hook (#2010)
* Add a TagMergePost post-hook

Introduce a post-hook for merging tags, call it in the merge path, as
the last thing we do before returning.
2021-11-19 11:12:34 +11:00
SmallCoccinelle c1f89611e2
Refactor scraper top half (#1893)
* Simplify scraper listing

Introduce an enum, scraper.Kind, which explains what we are looking
for. Make it possible to match this from a scraper struct.

Use the enum to rewrite all the listing code to use the same code path.

* Use a map, nitpick ScrapePerformerList

Let the cache store a map from ID of a scraper to the scraper. This
improves lookups when there are many scrapers, making it practically
O(1) rather than O(n). If many scrapers are stored, this is faster.

Since range expressions work unchanged, we don't have to change much,
and things will still work.

make Kind a Stringer

Rename ScraperPerformerList -> ScraperPerformerQuery since that name
is used in the other scrapers, and we value consistency.

Tune ScraperPerformerQuery:

* Return static errors
* Use the new functionality

* When loading scrapers, do so directly

Rather than first walking the directory structure to obtain file paths,
fold the load directly in the the filepath walk. This makes the code
for more direct.

* Use static ErrNotFound

If a scraper isn't found, return one static error. This paves the way
for eventually doing our own error-presenter in gqlgen.

* Store the cache in the Resolver state

Putting the scraperCache directly in the resolver avoids the need to
call manager.GetInstance() all over the place to get access to the
scraper cache. The cache is stored by pointer, so it should be safe,
since the cache will just update its internal state rather than being
overwritten.

We can now utilize the resolver state to grab the cache where needed.

While here, pass context.Context from the resolver down into a function,
which removes a context.TODO()

* Introduce ScrapedContent

Create a union in the GraphQL schema for all scraped content. This
simplifies the internal implementation because we get variance on
the output content type.

Introduce a new type ScrapedContentType which signifies the scraped
content you want as a caller.

Use these to generalize the List interface and the URL scraping
interface.

* Simplify the scraper API

Introduce a new interface for scraping. This interface is then
used in the upper half of the scraper code, to make the code use one
code flow rather than multiple code flows. Variance is currently at
the old scraper structure.

Add extending interfaces for the different ways of invoking scrapes.
Use interface conversions to convert a scraper from the cache to a
scraper supporting the extra methods.

The return path returns models.ScrapedContent.

Write a general postProcess function in the scraper, handling all
ScrapedContent via type switching. This consolidates all postprocessing
code flows.

Introduce marhsallers in the resolver code for converting ScrapedContent
into the underlying concrete types. Use this to plug the existing
fields in the Query resolver, so everything still works.

* ScrapedContent: add more marshalling functions

Handle all marshalling of ScrapedContent through marhsalling functions.
Removes some hand-rolled early variants of it, and replaces it with
a canonical code flow.

* Support loadByName via scraper_s

In order to temporarily plug a hole in the current implementation, we
use the older implementation as a hook to get the newer implementation
to run.

Later on, this can serve as a guide for how to implement the lower level
bits inside the scrapers themselves. For now, it just enables support.

* Plug the remaining scraper functions for now

Since we would like to have a scraper which works in between refactors,
plug the lower level parts of the scraper for now. It avoids us having
to tackle this part just yet.

* Move postprocessing to its own file

There's enough postprocessing to clutter the main scrapers.go file.

Move all of this into a new file, postprocessing to make the API
simpler. It now lives in scrapers.go.

* Scraper: Invoke API consistency

scraper.Cache.ScrapeByName -> ScrapeName

* Fix scraping scenes by URL

Simple typo. While here, also make a single marshaller nil-aware.

* Introduce scraper groups, consolidate loadByURL

Rename `scraper_s` into `group`. A group is a group of scrapers with
the same identity. This corresponds to a single YAML file for a scraper
configuration. It defines a group which supports different types of
scraping contexts.

Move config into the group, and lift txnManager and globalConfig to
the group.

Because we now return models.ScrapedContent we can use interfaces to
get variance from the different underlying scrapers. Use a type
switch for the URL matcher candidates. And then again for the scrapers.

This consolidates all URL scraping paths into one.

While here, remove the urlMatcher interface which isn't needed. Also
clean up the remaining interfaces for url scraping and delete code
which has no purpose anymore.

* Consolidate fragment scraping in one code path

While here, abide the linters checks.

* Refactor loadByFragment

Give it the same treatment as loadByURL:

Step 1: find a scraperActionImpl which works for the data.
Step 2: use that to scrape

Most of this is simple analysis on the data at hand. It can be pushed
down further in a later commit, but for now we leave it here.

* Remove configScraper, autotag is a scraper

Remove the remains of the configScraper struct. It now lives on in the
group struct. Kill the remaining interfaces from the old implementation
while here.

Remove group.specification since it can now be handled by a simple
func call to spec().

Work through the autotag scraper. It now implements the scraper
interface, so it can be used as a scraper. This also simplifies the
autotag scraper quite a bit since it doens't have to implement a number
of unsupported func calls.

* Simplify the fragment scraper flow

* Pass the context

Eliminate a round of context.TODO() in the scraper code by passing
the calling context down into the subsystem. This will gracefully
allow for termination of remote calls if the client goes away for some
reason in GraphQL requests.

* Improve listScrapers in the schema

Support lists of types we accept.

* Be graceful on nil values in conversion

Supporting nil-values make the API more robust in the
case of partial results in a multi-scrape situation.

* Improve listScrapers: output at-most-once

Use the ID of a scraper to reduce the output set. If a scraper has
been included, don't include it again.

* Consolidate all API level errors into resolver.go
* Reorder files and functions:

scrapers.go -> cache.go:
    It almost contains nothing but the cache code.
    Move errors into scraper.go from here because
    It is a better place to have them living right now
group.go:
    All of the group structure. This can now go from
    scraper.go, making it more lean. Move group create
    from config_scraper to here.
config.go:
    Move the `(c config) spec()` call to here.
config_scraper.go:
    Empty file by now

* Name-update the scraper interfaces

Use 'via' rather than 'loadBy'.

The scrape happens via a given scrape method, so I think this is a nice
name for it.

* Rename scrapers for consistency.

While here, improve the error formatting, so different errors come
back differently.

* Nuke the freeones field from the GraphQL schema

* Fix autotag interfacing, refactor

The autotag scraper uses a pointer receiver, but the rest of the code
we use for scraping doesn't expect a pointer-receiver. Hence, to fix
the autotag scraper, we change it to be a value receiver, like the
rest of the code.

Fix: viaScene, and viaGallery.

While here, remove a couple of pointer-receiver methods which can be
trivially rewritten into plain functions.

* Protect against pointer interfaces

The underlying code can be a bit inconsistent in what it returns.
Introduce pointer-types in the postprocessing layer and handle them
accordingly for now. Once a better understanding of the lower levels
are understood, we can lift this.

* Move ErrConversion into the models package.

The conversion error pertains to the logic of converting models.
Because of this, it should move there, so it is centralized.

* Be consistent in scraper resolver error handling

If we have a static error

    Err = errors.New(..)

Then use it wrapped at the start:

    fmt.Errorf("%w: ...context...", Err)

This reads better.

While here, avoid using the underlying Atoi errors: they are verbose,
and like 99% of the time, the user know what is wrong from the input
string, so just give that back.

Also, remove the scraper id from the error contexts: it is implicit,
and the error wouldn't change if we used a different scraper, which
the error message would imply.

* Mark the list*Scrapers() API as deprecated

The same functionality is now present in listScrapers.

* Improve error formatting

Think about how each error is going to be used and tweak them to be
nicer.

* Return a sorted list of scrapers

This helps testing, it's closer to what we had, caches like stable data,
and it is easier for humans. It also makes the output stable, because
map iteration is randomized.

* Fix listScrapers calls to return in ID-order

Since we need the ordering to be by ID in all situations, it is easier
to just generalize the cache listScrapers call to support multiple
scraper types.

This avoids a de-dupe map up the chain, since every scraper is only
considered once. Sorting now happens in the cache listScrapers call.

Use this generalized function in all resolvers, which are now simple
passthroughs.

* Remove UpdateConfig from the scraper cache.

This isn't needed, so get rid of it.

* Pull a context into identify

Scraping scenes in the identify tasks now use a context from up the
call chain.

* Do not store the scraper cache in the resolver.

Scraper caches are updated through
manager.singleton•RefreshScraperCache, so we can't keep a pointer to
it in the resolver. Instead, solve this by adding a fetcher method to
the resolver type. This keeps it local to the resolver, while handling
the problem of updating caches in the configuration.
2021-11-19 10:55:34 +11:00
kermieisinthehouse 8d94392cfb
Fix Vite issues (#2038)
* Fix environment vars in Vite
* Add types, remove process.env override
* Temporarily Remove Statigz / gzip
* Update ui/v2.5/src/core/createClient.ts

Co-authored-by: peolic <66393006+peolic@users.noreply.github.com>

* Update ui/v2.5/src/serviceWorker.ts

Co-authored-by: peolic <66393006+peolic@users.noreply.github.com>

* Ignore case rules in types
* Add windows js workaround

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-11-18 19:38:19 +11:00
kermieisinthehouse a4e52d3130
Vite-based frontend builds (#1900)
* Remove image conversion, add gzip
* Add MacOS Environment options
2021-11-18 12:32:04 +11:00
peolic 955083882e
Only add image files to `imageBox` files slice (#2017)
* Only add image files to `imageBox` files slice
* Update Changelog
2021-11-17 11:58:49 +11:00
7dJx1qP aa50dbf5e2
add missing trace loglevel (#2007) 2021-11-15 12:26:49 +11:00
InfiniteTF c571687c99
Resolve performer/studio stashIDs for scraped scenes (#2006)
* Resolve performer/studio stashIDs for scraped scenes
* Check endpoint when matching stashids
2021-11-15 07:51:52 +11:00
InfiniteTF 2a5afecc77
Fix invalid baseurl if host header already contains port (#2005) 2021-11-15 07:50:42 +11:00
peolic 0d76fede84
Fix config path regression (#1996) 2021-11-13 08:05:05 +11:00
kermieisinthehouse 2c7e0f0571
Apply python path resolution to plugins (#1990)
* Symlink python3 to python
* Apply path resolution to plugins
2021-11-12 09:21:52 +11:00
kermieisinthehouse a7ed0a7004
Bump viper version, fix nobrowser (#1991) 2021-11-12 09:21:04 +11:00
InfiniteTF 808202ba8a
Fix performer tagger field updating (#1977)
* Fix performer tagger field updating
2021-11-11 11:34:46 +11:00
Releck d316aeca16
Fix identify defaults not returning by using main viper instance (#1979) 2021-11-10 09:32:47 +11:00
Frix-416 ffc8043273
French translation (fr-FR) (#1967) 2021-11-08 11:41:05 +11:00
WithoutPants 49b2860909
Improve flag and environment config overrides (#1898)
* Separate overrides from config
* Don't allow changing overridden value
* Write default host and port to config file
* Use existing library value. Hide generated if set
2021-11-08 10:14:11 +11:00
WithoutPants 3aa5f657bc
Add display autoplay and playlist continue options (#1921)
* Add display autoplay and playlist continue options
* Include continue parameter in scene links
2021-11-07 09:55:51 +11:00
gitgiggety 25274e2596
Support Is (not) null for all multi criterions (#1785)
* Support Is (not) null for all multi criterions

Add support for the Is null and Is not null modifiers for all cases of
the MultiCriterionInput and HierarchicalMultiCriterionInput. This
partially overlaps the "X Count" filter which sometimes is available
(because it would be the same as "X Count equals 0" and "X Count greater
than 0") but this also enables it for other criterions like the "Parent
Studio" filter for studios or just the "Studios" filter for scenes /
images / galleries, the "Movies" filter for scenes etc.

* Don't crash UI on bad saved filter
* Add missing code for tag parent/child

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-11-07 09:34:33 +11:00
7dJx1qP e961ba4459
Fix tag hierarchy validation (#1926)
* update tag hierarchy validation
* refactor MergeHierarchy
* update tag hierarchy error message
* rename tag hierarchy function
* add tag path to error message
* Rename EnsureHierarchy to ValidateHierarchy

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-11-07 09:33:46 +11:00
WithoutPants 5bb5f6f2ce
Move scene post update hook to outside Identify transaction (#1953)
* Move update post hook call outside transaction
* Make Scene Movies resolver use read transaction
2021-11-06 09:58:52 +11:00
WithoutPants 602183cca9
File size scanning fixes (#1944) 2021-11-04 10:50:03 +11:00
kermieisinthehouse 9134490be2
Add linux ffmpeg urls (#1943) 2021-11-04 08:22:25 +11:00
SmallCoccinelle 5f26719d2d
Suppress a benign warning (#1932) 2021-11-01 11:16:23 +11:00
7dJx1qP c6a326ca64
Add stash_ids to performer, scene, studio import/export (#1916)
* add stash_ids to performer, scene, studio import/export
2021-10-29 11:12:39 +11:00
kermieisinthehouse 87036a07bc
Start browser on server start (#1832)
* Start browser on server start
* Add config option for opening browser
2021-10-29 10:19:23 +11:00
7dJx1qP 96fce90cc3
Add delete file and generated files by default config options (#1852)
* add delete file and generated files by default config options
* add alert message with files to be deleted

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-10-28 16:45:44 +11:00
WithoutPants 0f64954e5b
Identify task (#1839)
* Add identify task
* Change type naming
* Debounce folder select text input
* Add generic slice comparison function
2021-10-28 14:25:17 +11:00
kermieisinthehouse 5de06d4b62
Convert filesize to float64 for arm32 (#1895)
* Convert filesize to float64 for arm32
2021-10-27 11:55:11 +11:00
WithoutPants 595e8efb73
Fix race condition in generate task (#1888) 2021-10-26 08:41:40 +11:00
kermieisinthehouse 1e5889ba17
Spanish translation (#1886)
* Spanish translation
2021-10-25 13:07:16 +11:00
kermieisinthehouse 4dd56c3d82
Show duration and filesize in results (#1776)
* Add new query interface
* Refactor query builder
* Change Query interface
* Return duration and filesize in scene query
* Adjust UI for scene metadata
* Introduce new image query interface
* Change image Query interface
* Add megapixels and size to image query
* Update image UI

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-10-25 11:40:13 +11:00
kermieisinthehouse cb52eb798d
Italian Translation (it-IT) (#1875)
* Italian translation metadata
* Add json file from BViking
2021-10-25 10:41:29 +11:00
SmallCoccinelle 401fc290ef
Handle request cancellation more gracefully (#1877)
The version checking code performs its own error management and will
not pass errors to the caller. Hence, it needs to be aware of the types
of errors which can be returned.

In particular, the context.Canceled error will be returned if the
context is aborted through cancelation. This happens when the request
is terminated by tapping CTRL-C or if the browser request is terminated
while we are sitting waiting for the GH API.
2021-10-25 10:09:20 +11:00
WithoutPants d292ed0b34
Fix deleting folder-based gallery file deleting (#1872)
* Fix deleting gallery image files
* Clarify delete file documentation
2021-10-25 09:29:03 +11:00
WithoutPants 0ab8d32687
Refactor generate task (#1871)
* Refactor generate task
2021-10-23 10:48:42 +11:00
kermieisinthehouse f80a5e3222
Docker+Build optimizations (#1833)
* Docker CI builds: half the size, less than half the build time
* Add an "Official Build" Designator
* Fix .git constantly invalidating build cache, use distro ffmpeg
* Fix official build detection, add some compiler image docs

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-10-22 13:14:08 +11:00
InfiniteTF 15acf91b90
Add PHash distance matching to stash-box integration (#1858)
* Add PHash distance matching to stash-box integration
2021-10-20 17:22:25 +11:00
WithoutPants 976038424b
Fix parsing ipv6 address with scope id (#1841)
* Fix parsing ipv6 address with scope id

Also allows connections from link local unicast address

* Add unit tests
2021-10-20 16:52:15 +11:00
SmallCoccinelle 8b7720e3bf
Enable the appendAssign lint check (#1865)
* Make copies of buffers

Avoid reusing one of the incoming arrays as a append extension, and
make a copy of the data. It's cleaner in the long run and possibly
easier for the GC to maintain.

* Avoid appendAssign problems in tag code

Reuse the existing slice when appending.

* Fix appendAssign in encoder_scene_preview_chunk

Appending and creating a new slice is somewhat unintuitive since the
underlying slice might be extended to satisfy the new capacity. This
sometimes leads to faulty logic.

Rewrite the code so it reuses `args` for all appending, and builds one
array clearly in the code. It follows the general style of the function
where `args` is being built in small incremental batches and avoids
the introduction of new names.

* Enable the appendAssign check

This makes us pass all gocritic warnings.

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-10-20 16:34:19 +11:00
SmallCoccinelle e513b6ffa5
Cache and reuse the scraper HTTP client (#1855)
* Add Cookies directly to the request

Rather than maintaining a cookie jar on a one-shot HTTP client, maintain
the jar ourselves: make a new jar, then use it to select the right
cookies.

The cookies are set on the request rather than on the client. This will
retain the current behavior as we are always throwing the client away
after each use.

This patch enables the lifting of the http client as well over time.

* Introduce a cached scraper HTTP client

The scraper cache is augmented with an *http.Client. These are safe for
concurrent use, so the pointer can safely be passed around. Push this
into scraper configurations where applicable, next to the txnManagers.

When we issue a loadUrl request, do so on the cached *http.Client,
which will reuse existing idle connections in the client if any are
present.

* Set MaxIdleConnsPerHost. Closes #1850

We allow for up to 8 idle connections to a single host. This should
make concurrent operation toward the same host reuse connections, even
for sizeable concurrency.

The number isn't bumped excessively high. We should probably limit
concurrency toward a single site anyway, since we'll be able to overrun
a site with queries quite easily if we have many concurrent goroutines
issuing requests at the same time.

* Reinstate driverOptions / useCDP check

Use DeMorgan's laws to invert the logic and exit early. Fixes tests
breaking.

* Documentation fixup.

* Use the scraper http.Client when fetching images

Fold image fetchers onto the cached scraper http.Client as well. This
makes the scraper have a single http.Client cache for all its
operations.

Thread the client upwards to the relevant attachment points: either the
cache, or a stash_box instance, which is extended to include a pointer
to the client.

Style roughly follows that of txnManagers.

* Use the same http Client as the GraphQL client use

Rather than using http.DefaultClient, use the same client as the
GraphQL client use in the stash_box subsystem. This localizes the
client used in the subsystem into the constructing New.. call.

* Hoist HTTP client construction

Create a function for initializaing the HTTP Client we use. While here
hoist magic numbers into constants. Introduce a proper static redirect
error and use it in the client code as well.

* Reinstate printCookies

This is a debugging function, and it might still come in handy in the
future at some point.

* Nitpick comment.

* Minor tidy

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-10-20 16:12:24 +11:00
SmallCoccinelle 214a15bc40
Fixups + enable the commentFormatting linter (#1866)
* Add a space after // comments

For consistency, the commentFormatting lint checker suggests a space
after each // comment block. This commit handles all the spots in
the code where that is needed.

* Rewrite documentation on functions

Use the Go idiom of commenting:

* First sentence declares the purpose.
* First word is the name being declared

The reason this style is preferred is such that grep is able to find
names the user might be interested in. Consider e.g.,

    go doc -all pkg/ffmpeg | grep -i transcode

in which case a match will tell you the name of the function you are
interested in.

* Remove old code comment-blocks

There are some commented out old code blocks in the code base. These are
either 3 years old, or 2 years old. By now, I don't think their use is
going to come back any time soon, and Git will track old pieces of
deleted code anyway.

Opt for deletion.

* Reorder imports

Split stdlib imports from non-stdlib imports in files we are touching.

* Use a range over an iteration variable

Probably more go-idiomatic, and the code needed comment-fixing anyway.

* Use time.After rather than rolling our own

The idiom here is common enough that the stdlib contains a function for
it. Use the stdlib function over our own variant.

* Enable the commentFormatting linter
2021-10-20 16:10:46 +11:00
SmallCoccinelle e14bb8432c
Enable gocritic (#1848)
* Don't capitalize local variables

ValidCodecs -> validCodecs

* Capitalize deprecation markers

A deprecated marker should be capitalized.

* Use re.MustCompile for static regexes

If the regex fails to compile, it's a programmer error, and should be
treated as such. The regex is entirely static.

* Simplify else-if constructions

Rewrite

   else { if cond {}}

to

   else if cond {}

* Use a switch statement to analyze formats

Break an if-else chain. While here, simplify code flow.

Also introduce a proper static error for unsupported image formats,
paving the way for being able to check against the error.

* Rewrite ifElse chains into switch statements

The "Effective Go" https://golang.org/doc/effective_go#switch document
mentions it is more idiomatic to write if-else chains as switches when
it is possible.

Find all the plain rewrite occurrences in the code base and rewrite.
In some cases, the if-else chains are replaced by a switch scrutinizer.
That is, the code sequence

  if x == 1 {
      ..
  } else if x == 2 {
      ..
  } else if x == 3 {
      ...
  }

can be rewritten into

  switch x {
  case 1:
    ..
  case 2:
    ..
  case 3:
    ..
  }

which is clearer for the compiler: it can decide if the switch is
better served by a jump-table then a branch-chain.

* Rewrite switches, introduce static errors

Introduce two new static errors:

* `ErrNotImplmented`
* `ErrNotSupported`

And use these rather than forming new generative errors whenever the
code is called. Code can now test on the errors (since they are static
and the pointers to them wont change).

Also rewrite ifElse chains into switches in this part of the code base.

* Introduce a StashBoxError in configuration

Since all stashbox errors are the same, treat them as such in the code
base. While here, rewrite an ifElse chain.

In the future, it might be beneifical to refactor configuration errors
into one error which can handle missing fields, which context the error
occurs in and so on. But for now, try to get an overview of the error
categories by hoisting them into static errors.

* Get rid of an else-block in transaction handling

If we succesfully `recover()`, we then always `panic()`. This means the
rest of the code is not reachable, so we can avoid having an else-block
here.

It also solves an ifElse-chain style check in the code base.

* Use strings.ReplaceAll

Rewrite

    strings.Replace(s, o, n, -1)

into

    strings.ReplaceAll(s, o, n)

To make it consistent and clear that we are doing an all-replace in the
string rather than replacing parts of it. It's more of a nitpick since
there are no implementation differences: the stdlib implementation is
just to supply -1.

* Rewrite via gocritic's assignOp

Statements of the form

    x = x + e

is rewritten into

    x += e

where applicable.

* Formatting

* Review comments handled

Stash-box is a proper noun.

Rewrite a switch into an if-chain which returns on the first error
encountered.

* Use context.TODO() over context.Background()

Patch in the same vein as everything else: use the TODO() marker so we
can search for it later and link it into the context tree/tentacle once
it reaches down to this level in the code base.

* Tell the linter to ignore a section in manager_tasks.go

The section is less readable, so mark it with a nolint for now. Because
the rewrite enables a ifElseChain, also mark that as nolint for now.

* Use strings.ReplaceAll over strings.Replace

* Apply an ifElse rewrite

else { if .. { .. } } rewrite into else if { .. }

* Use switch-statements over ifElseChains

Rewrite chains of if-else into switch statements. Where applicable,
add an early nil-guard to simplify case analysis. Also, in
ScanTask's Start(..), invert the logic to outdent the whole block, and
help the reader: if it's not a scene, the function flow is now far more
local to the top of the function, and it's clear that the rest of the
function has to do with scene management.

* Enable gocritic on the code base.

Disable appendAssign for now since we aren't passing that check yet.

* Document the nolint additions

* Document StashBoxBatchPerformerTagInput
2021-10-18 14:12:40 +11:00
kermieisinthehouse 5ec70ac3e0
Fix List filter styles, fix freeones spam (#1853)
* Fix List filter styles, fix freeones spam
2021-10-15 14:02:49 +11:00
WithoutPants 39fdde273d
Scan refactor (#1816)
* Add file scanner
* Scan scene changes
* Split scan files
* Generalise scan
* Refactor ffprobe
* Refactor ffmpeg encoder
* Move scene scan code to scene package
* Move matchExtension to utils
* Refactor gallery scanning
* Refactor image scanning
* Prevent race conditions on identical hashes
* Refactor image thumbnail generation
* Perform count concurrently
* Allow progress increment before total set
* Make progress updates more frequent
2021-10-15 10:39:48 +11:00
WithoutPants 3d5ee16e90
Fix colours on console when logging to file (#1846)
* Fix colours on console when logging to file
2021-10-15 10:38:32 +11:00
SmallCoccinelle 655d3ae969
Toward better context handling (#1835)
* Use the request context

The code uses context.Background() in a flow where there is a
http.Request. Use the requests context instead.

* Use a true context in the plugin example

Let AddTag/RemoveTag take a context and use that context throughout
the example.

* Avoid the use of context.Background

Prefer context.TODO over context.Background deep in the call chain.

This marks the site as something which we need to context-handle
later, and also makes it clear to the reader that the context is
sort-of temporary in the code base.

While here, be consistent in handling the `act` variable in each
branch of the if .. { .. } .. check.

* Prefer context.TODO over context.Background

For the different scraping operations here, there is a context
higher up the call chain, which we ought to use. Mark the call-sites
as TODO for now, so we can come back later on a sweep of which parts
can be context-lifted.

* Thread context upwards

Initialization requires context for transactions. Thread the context
upward the call chain.

At the intialization call, add a context.TODO since we can't break this
yet. The singleton assumption prevents us from pulling it up into main for
now.

* make tasks context-aware

Change the task interface to understand contexts.

Pass the context down in some of the branches where it is needed.

* Make QueryStashBoxScene context-aware

This call naturally sits inside the request-context. Use it.

* Introduce a context in the JS plugin code

This allows us to use a context for HTTP calls inside the system.

Mark the context with a TODO at top level for now.

* Nitpick error formatting

Use %v rather than %s for error interfaces.
Do not begin an error strong with a capital letter.

* Avoid the use of http.Get in FFMPEG download chain

Since http.Get has no context, it isn't possible to break out or have
policy induced. The call will block until the GET completes. Rewrite
to use a http Request and provide a context.

Thread the context through the call chain for now. provide
context.TODO() at the top level of the initialization chain.

* Make getRemoteCDPWSAddress aware of contexts

Eliminate a call to http.Get and replace it with a context-aware
variant.

Push the context upwards in the call chain, but plug it before the
scraper interface so we don't have to rewrite said interface yet.

Plugged with context.TODO()

* Scraper: make the getImage function context-aware

Use a context, and pass it upwards. Plug it with context.TODO()
up the chain before the rewrite gets too much out of hand for now.

Minor tweaks along the way, remove a call to context.Background()
deep in the call chain.

* Make NOTIFY request context-aware

The call sits inside a Request-handler. So it's natural to use the
requests context as the context for the outgoing HTTP request.

* Use a context in the url scraper code

We are sitting in code which has a context, so utilize it for the
request as well.

* Use a context when checking versions

When we check the version of stash on Github, use a context. Thread
the context up to the initialization routine of the HTTP/GraphQL
server and plug it with a context.TODO() for now.

This paves the way for providing a context to the HTTP server code in a
future patch.

* Make utils func ReadImage context-aware

In almost all of the cases, there is a context in the call chain which
is a natural use. This is true for all the GraphQL mutations.

The exception is in task_stash_box_tag, so plug that task with
context.TODO() for now.

* Make stash-box get context-aware

Thread a context through the call chain until we hit the Client API.
Plug it with context.TODO() there for now.

* Enable the noctx linter

The code is now free of any uncontexted HTTP request. This means we
pass the noctx linter, and we can enable it in the code base.
2021-10-14 15:32:41 +11:00
SmallCoccinelle 41a1fb8aec
Add collation to directory listings (#1823)
* Add collation to directory listings. Closes #1806

Introduce a new `locale` arg to the `Query.directory` field. Set "en"
as the default for the field for backward compatibility. Use the given
locale, sending it through a language matcher, and use `x/text` as the
collation engine for the matched language.

Augment the file `ListDirs` call to optionally take a Collator. If the
Collator is given, sort file listings according to the collators rules.

While here, document the GraphQL schema a bit more.

Add matchers by looking at the current front-end locales, and make sure
each of these occur in the matcher list.

* Language matcher touchups

* Avoid having `en-US` twice.
* Introduce `en-AU`.

* Pass IgnoreCase and Numeric collation

Allow the collator to be configured with options. Pass the options
IgnoreCase and Numeric to the collator.
2021-10-14 15:16:45 +11:00
SmallCoccinelle c6f6205e4f
Errorlint sweep + minor linter tweaks (#1796)
* Replace error assertions with Go 1.13 style

Use `errors.As(..)` over type assertions. This enables better use of
wrapped errors in the future, and lets us pass some errorlint checks
in the process.

The rewrite is entirely mechanical, and uses a standard idiom for
doing so.

* Use Go 1.13's errors.Is(..)

Rather than directly checking for error equality, use errors.Is(..).

This protects against error wrapping issues in the future.

Even though something like sql.ErrNoRows doesn't need the wrapping, do
so anyway, for the sake of consistency throughout the code base.

The change almost lets us pass the `errorlint` Go checker except for
a missing case in `js.go` which is to be handled separately; it isn't
mechanical, like these changes are.

* Remove goconst

goconst isn't a useful linter in many cases, because it's false positive
rate is high. It's 100% for the current code base.

* Avoid direct comparison of errors in recover()

Assert that we are catching an error from recover(). If we are,
check that the error caught matches errStop.

* Enable the "errorlint" checker

Configure the checker to avoid checking for errorf wraps. These are
often false positives since the suggestion is to blanket wrap errors
with %w, and that exposes the underlying API which you might not want
to do.

The other warnings are good however, and with the current patch stack,
the code base passes all these checks as well.

* Configure rowserrcheck

The project uses sqlx. Configure rowserrcheck to include said package.

* Mechanically rewrite a large set of errors

Mechanically search for errors that look like

    fmt.Errorf("...%s", err.Error())

and rewrite those into

    fmt.Errorf("...%v", err)

The `fmt` package is error-aware and knows how to call err.Error()
itself.

The rationale is that this is more idiomatic Go; it paves the
way for using error wrapping later with %w in some sites.

This patch only addresses the entirely mechanical rewriting caught by
a project-side search/replace. There are more individual sites not
addressed by this patch.
2021-10-12 14:03:08 +11:00
SmallCoccinelle 38384f2c60
Improve oshash code (#1829)
Reduce allocations. Don't create intermediary arrays which we then
consume right after. Manually fuse the arrays and decode straight into
the sum instead.

Furthermore, don't invoke a Reader, but carve out the locations via a
loop, directly.

These two changes taken together speeds up oshash computations by a
factor of 10 according to the benchmark tests. The main reason for
this change is a much lowered memory allocation rate which in turn
improves GC pressure.

While here, add a benchmark for oshash computations and use it for
testing the performance.
2021-10-12 11:59:51 +11:00
WithoutPants e9d48683f8
Autotag scraper (#1817)
* Refactor scraper structures
* Move matching code into new package
* Add autotag scraper
* Always check first letter of auto-tag names
* Account for nulls

Co-authored-by: Kermie <kermie@isinthe.house>
2021-10-11 23:06:06 +11:00
WithoutPants b5381ff071
Add option to disable create from dropdown (#1814)
* Convert config hooks to common context
* Add option to disable creating from dropdown
2021-10-11 17:45:58 +11:00
WithoutPants 46ae4581b8
Refactor clean task (#1805)
* Refactor clean task
* Use path sorting for scenes and galleries
* Add changelog
2021-10-11 16:45:24 +11:00
kermieisinthehouse c31c7c3c99
Fix exclude filter query performance (#1815)
* Fix query performance
* Reorder changelog changes by size to prepare for release
2021-10-10 19:02:26 +11:00