Compare commits

...

702 Commits

Author SHA1 Message Date
Tweeticoats
a73c99a61d Update docker file to add mechanicalsoup python library (#1688)
Add a new python library mechanicalsoup to the docker container.
There is a pending pull request in the Community scrapers for the Ifeelmyself that uses this library so it might be worth including it in the container.
This should add ~100k to the size of the container.
2021-08-31 20:14:39 +10:00
WithoutPants
709d7ce1cc Load TLS config files from config path before stash home (#1678)
* Load tls files from config or home directory
* Update README
* Require both ssl files if either present
2021-08-31 19:37:45 +10:00
gitgiggety
1774a3600c Fix Performers Is Missing: stash ID filter (#1681)
* Fix Performers Is Missing: stash ID filter.

Fixes #1679
2021-08-30 11:46:41 +10:00
FleetingOrchard
50cb6a9c79 Add duration statistics to stats page (#1626) 2021-08-26 13:37:08 +10:00
UnluckyChemical765
45a9aabdaf Add script offset / delay to Handy support. (#1573)
* Add script offset / delay to Handy support.

Further work on  #1376.

Offsets are added to the current video position, so a positive value leads to earlier motion.  (The most common setting.)

This is needed because most script times have a consistent delay when compared to the video. (Delay from the API calls to the server should be handled by the server offset calculation.)

* Rename scriptOffset to funscriptOffset
* Correct localisation keys

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-08-26 11:50:02 +10:00
gitgiggety
50217f6318 Rebuild image edit using formik (#1669)
* Rebuild image edit using formik
* Prompt on page leave when changes are not saved
* Only enables save when changes are made
* Wrap in <Form onSubmit> (not sure if this does anything)
2021-08-26 11:24:49 +10:00
gitgiggety
2e83405841 Add "toolbar" buttons for some list actions (#1673)
* Support adding buttons to list "toolbar"
* Show add and remove images to gallery in toolbar
* Show button to play selected scenes to list toolbar
2021-08-26 10:46:07 +10:00
gitgiggety
e98302fcd0 Add image and gallery count to tag listing (#1672) 2021-08-26 10:18:13 +10:00
gitgiggety
3f888a0335 Fix error when creating scene queue of single item (#1674)
* Fix error when creating scene queue of single item
2021-08-26 10:03:56 +10:00
gitgiggety
4c144db510 Performers listing improvements (#1671)
* Add sorting on image and gallery count to performers
* Make performer table headers translatable
* Add image and gallery count to performers table
* Make sure list table container fits the table

Make the table container minimally as wide as the table. This fixes the
table "overflowing" to the left and right and the left not being
accessible.

* Remove unnecessary truncation in tables

IMO there is no need to truncate the title in the scenes table and the
name in the performers table. This because both tables also contain an
image which means that multiple lines should be possible without really
extending the height of the row. Furthermore both tables contain other
values which might be way longer and also aren't wrapped (like tags and
performers for scenes, and aliases for performers).
2021-08-26 09:41:18 +10:00
Still Hsu
177339c14e Update zh-tw strings & fix various hard strings (#1666)
* Update unlocalized strings & fix various hard strings
* Fix incorrect placement of ignore_organized in en-US
* Add missing strings
* Fix hard string in PerformerList
2021-08-26 08:51:54 +10:00
EnameEtavir
cb6dab3c5f Fix: config race conditions with RWMutex (#1645)
* Fix: config race conditions with RWMutex

Added RWMutex to config.Instance which read or write locks
all instances where viper is used.

Refactored checksum manager to only use config and not
viper directly anymore.

All stash viper operations are now "behind" the config.Instance
and thus mutex "protected".
2021-08-24 15:18:30 +10:00
gitgiggety
da8803925c Add date, duration and rating to Movie sorting (#1663)
* Add date, duration and rating to Movie sorting

Fixes: #1637
2021-08-24 15:04:17 +10:00
gitgiggety
28b092885c Add option to filename parser to skip organized scenes (#1665)
Fixes #1219
2021-08-24 12:14:37 +10:00
gitgiggety
392fa3535c Rebuild gallery edit using formik (#1654)
* Rebuild gallery edit using formik

* Prompt on page leave when changes are not saved
* Fixes missing required validation
* Only enables save when changes are made
* Wrap in <Form onSubmit> (not sure if this does anything)
2021-08-24 12:01:05 +10:00
peolic
ac72d4db2b Fix scene bitrate unit (#1650) 2021-08-24 11:33:46 +10:00
InfiniteTF
0d4ab7f6f3 Fix studio editing (#1668) 2021-08-24 11:23:25 +10:00
kermieisinthehouse
7b3b2ae9ba Order sceneDuplicateChecker results by size (#1639) 2021-08-18 13:11:57 +10:00
EnameEtavir
9803684535 UI: Add checkbox to scenes List view (#1642) 2021-08-18 12:56:52 +10:00
WithoutPants
680af72dcf Custom page size and saved zoom level (#1636)
* Allow custom page sizes
* Save zoom level in filters
2021-08-18 12:14:56 +10:00
gitgiggety
fc6cafa15f Fix hierarchical criteria performance issue (#1643)
* Fix hierarchical criteria performance issue

Don't apply recursive clause to hierarchical criteria when the depth is
set to 0 (i.e.: no recursion is needed).

This undoes the current performance penalty on for example the studios
page. This as reported in #1519, using a database of 4M images, 30K
scenes and 500 studios. Without this fix loading the studios overview,
with the default of 40 items per page, takes 6 to 7 seconds. With this
fix it only takes 0,07 seconds reverting the performance back to the
pre-hierarchical filtering performance (tested against 508f7b84 which
was the last commit before #1397 was merged).
2021-08-17 13:43:22 +10:00
WithoutPants
0fc5a06332 Add scene queue keyboard shortcuts (#1635) 2021-08-16 14:14:39 +10:00
WithoutPants
b6d15cc077 Make performer scrape button a dropdown (#1634) 2021-08-16 10:16:05 +10:00
gitgiggety
7cb3d05535 Add (not) between modifiers for number criterion (#1559)
* Add (not) between modifiers for number criterion
* Extract list filters into dedicated components

Extract the filters from the AddFiltersDialog into custom components.
This allows for further refactorring where components will be bound to
criterions.

* Add placeholders to number and duration criterions
* Add backwards compatibility for saved filters

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-08-12 10:24:16 +10:00
WithoutPants
c29d8b547d Overwrite phash during generate if flag set (#1633) 2021-08-11 16:08:10 +10:00
WithoutPants
59c6fe046d Fix scrape dialog not showing when scraping url (#1632) 2021-08-11 15:54:29 +10:00
gitgiggety
d4d45d5a06 Rebuild Studio page by splitting view and edit (#1629)
* Rebuild Studio page by splitting view and edit
* Fix parent studio id, open studio link in same tab

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-08-11 14:44:18 +10:00
Still Hsu
53489106a6 Update zh-tw localization (#1631)
* Fill missing zh-tw fields
* Replace "Merge" verb hard string with i18n impl
2021-08-11 10:26:30 +10:00
kermieisinthehouse
c5e1a3ed72 Fix dropdown menus z-index issue (#1628) 2021-08-11 10:13:17 +10:00
gitgiggety
915533b8c5 Create default config directory during setup (#1623)
* Create default config directory during setup

Instead of creating the config directory during startup, create it
during setup when needed.

Fixes #1616
2021-08-10 14:58:14 +10:00
gitgiggety
59c7dd622b Fix links and styling of File Info tabs (#1622)
* Refactor HTML of movie and performer details panels

Refactor HTML of the movie and performer details panels so that the
items are contained in a single list (`<dl/>`). This allows using a grid
layout which means that the styling is easier to get right for multiple
form factors, fixing issues where "values" would overlap the "labels"
(for instance on my phone performers "Measurements" almost overlaps the
actual value, while there is a lot of space for the value itself).

This refactor also allows reusing the `TextField` and `URLField`
components as they don't have any styling related classes anymore (i.e.:
the `col-` classes are gone). Which means they can be used in more dense
places, like the SceneFileInfoPanel, as well. As the width of the label
/ value doesn't rely on the viewport size anymore (as happened due to
the `col-xl` usage, but for example the scene sidebar being small, and
16% being to small).

* Rebuild SceneFileInfoPanel

Completely rebuild the SceneFileInfoPanel to make use of the `TextField`
and `URLField` components. Using these components means that the URLs
automatically get `target="_blank" rel="noopener noreferrer"`.
Furhermore this should also improve the styling a bit, as described in
the previous commit.

* Rebuild ImageFileInfoPanel

Completely rebuild the ImageFileInfoPanel to make use of `TextField` and
`URLField` components. Furthermore it should resolve some small styling
issues.

* Rebuild GalleryFileInfoPanel

Rebuild the GalleryFileInfoPanel to make use of `TextField` and
`URLField` components. Using these components means that for example the
URLs automatically get `target="blank" rel="noopener noreferrer"`.

Also adds the url property as 1. at the moment it is nowhere accessible,
and 2. scenes also has it in this panel.

* Truncate links on the file info tabs at latest opportunity

On the File Info tabs links always have the link destination as text for
the link as well. But these texts can be long and without whitespace.
This means that the default applied `word-wrap: break-word` doesn't
really work as URLs (and paths) don't contain spaces that ofter. So
apply `word-break: break-all` instead so that the text will be as long
as possible and just cut off in the middle, instead of only at
whitespace. This thus means that the fully available width will be used
to display the URL.
2021-08-10 14:39:09 +10:00
fnoopv
d31b6841d0 Add Chinese Simplified Translation (#1620) 2021-08-10 14:15:56 +10:00
gitgiggety
dfd55346b2 Scrape tag exclusions (#1617)
* Add config option for scraper tag exclusion patterns

Add a config option for exclusing tags / tag patterns from the scraper
results.

* Handle tag exclusion patterns during scraping
2021-08-10 14:07:01 +10:00
capnrowdy
404eaa32d2 Changes to Default Performer Images (for Accessibility) (#1489)
* Changes to support custom URL paths
* Refactor image resolver code
* Initialise box files at startup
* Update packr

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-08-10 13:51:31 +10:00
WithoutPants
3e78d642a2 Remove unnecessary fields from StudioData (#1618) 2021-08-06 11:41:51 +10:00
gitgiggety
9d641c64e3 Actually implement TagFilter.marker_count (#1603)
* Actually implement TagFilter.marker_count

The marker_count filter/criterion as defined in TagFilterType isn't
actually implemented. This adds an implementation for it.

Do note this implementation _might_ have performance issues because of
using OR (in the join). Another implentation would be to remove both
joins and use:
```SQL
COUNT(
    SELECT id FROM scene_markers WHERE primary_tag_id = tags.id
  UNION
    SELECT scene_marker_id FROM scene_markers_tags WHERE tag_id = tags.id
)
```
Note this doesn't require a DISTINCT as UNION already removes any
duplicate records.

* Restore marker count filter and sorting

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-08-04 13:39:24 +10:00
gitgiggety
ac41416cd7 Restructure scraping settings (#1548)
* Change scrapers overview into collapsible per type
* Move scraping configuration to (renamed) scrapers tab

Rename the Scrapers tab to Scraping and move the scraping configuration
to this tab.
2021-08-04 12:32:58 +10:00
bnkai
518be8ee70 Upgrade gjson module (#1610) 2021-08-04 09:52:16 +10:00
WithoutPants
eaa23240f7 Tagger UI improvements (#1605)
* Choose fields to tag
* Use check-circle for success icon
* Maintain fingerprint results
* Show scene details
* Maintain whitespace in TruncatedText
* Use undefine for img when not setting
2021-08-04 09:44:51 +10:00
WithoutPants
f52bfae8ac Set stash id during performer scrape (#1608) 2021-08-04 09:33:21 +10:00
WithoutPants
7287ad3a05 Remove stripes and add background colour to default performer images (#1609) 2021-08-04 09:01:34 +10:00
WithoutPants
8a7577c9bf Fix inf values causing marshal error (#1607) 2021-08-03 14:29:57 +10:00
WithoutPants
c7d2ddc5db Fix unsetting performer gender (#1606)
* Fix unset performer gender
* Fix button group appearing over select menu
2021-08-03 13:13:48 +10:00
Felipe Fernandes Leandro
8f3036b351 Portuguese translation (#1587)
Co-authored-by: kermieisinthehouse <kermie@isinthe.house>
2021-08-03 10:58:46 +10:00
Jekora
ede8cca631 [Feature] Better resolution search (#1568)
* Fix width in database test setup
* Added more filters on resolution field
* added test to verify resolution range is defined for every resolution
* Refactor UI code

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-08-02 13:22:39 +10:00
WithoutPants
723446842f Split up Tagger component (#1534) 2021-08-02 10:32:23 +10:00
Phasetime
4bdd759dae German Translation (#1578)
* initial translation pass
* New line at EOF
2021-07-17 19:00:47 +10:00
gitgiggety
a13f43c13b Always wrap filter conditions in parentheses (#1577)
* Always wrap filter conditions in parentheses

Fixes #1571
2021-07-14 18:29:59 +10:00
thatbrick
1b20fd1ad6 Fix Incorrect loading of images on iOS devices (#1562)
* Removing the height parameter seems to resolve the issue without noticeable differences in functionality
2021-07-13 10:29:47 +10:00
gitgiggety
aecab2d131 Tag stable versions with the version number on Docker (#1550)
Fixes #1546
2021-07-13 09:59:09 +10:00
gitgiggety
9591faf3d4 Mobile fixes (#1539)
* Make new tag, gallery and studio pages mobile friendly
* Enable new button on mobile
* Update movies edit HTML to be more in line with scene

Update the code of the MovieEditPanel to be more in sync with the
SceneEditPanel. Changes made are:
 * Use FormUtil.renderLabel instead of manually building
 * Always apply xs=9 breakpoint

This fixes some layout issues on mobile while still looking the same on
tablet and desktop resolution.

* Enable delete button for tags, studios and movies on mobile
* Add changelog

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-07-12 20:56:38 +10:00
WithoutPants
7b85df868d Merge pull request #1558 from stashapp/master
Merge master to develop for version tag
2021-07-06 17:35:40 +10:00
WithoutPants
0c417ad439 Merge pull request #1544 from stashapp/develop
Merge develop to master for 0.8
2021-07-02 09:34:37 +10:00
InfiniteTF
73f99f019c Show unknown duration when tagging files without a duration (#1535) 2021-06-28 10:37:58 +10:00
bnkai
4c05535a13 Fix potential race condintion in CDP (#1536) 2021-06-28 10:36:51 +10:00
WithoutPants
4c838daa12 Add sprite to SceneData fragment (#1533)
* Add sprite to SceneData fragment

Necessary so that TypePolicies object is populated correctly.
2021-06-26 14:25:01 +10:00
WithoutPants
fd3c9153d5 Fix message id issue (#1530) 2021-06-24 10:50:51 +10:00
WithoutPants
0589df51cd Fix query text field bug (#1528) 2021-06-24 09:00:14 +10:00
WithoutPants
4e08e37d74 Clear scene tagger results on new search (#1526)
* Clear search results when searching in tagger
* Fix oshash messageID
2021-06-23 13:00:58 +10:00
WithoutPants
4e26633abb UI fixes (#1525)
* Fix scene page styling
* Hide plugins with no tasks on task page
* Update query on URL change
2021-06-23 11:57:03 +10:00
WithoutPants
debf21e6b2 Saved filter bugs (#1524)
* Don't use default filter in VIEW persist state
* Reshuffle randomly sorted saved filters
2021-06-23 11:01:23 +10:00
WithoutPants
2fdf672015 Fix scene galleries panel (#1523) 2021-06-23 10:43:54 +10:00
WithoutPants
4165e7779f Add various filter criteria (#1505)
* Add various filter criteria
* Add tag name criterion
2021-06-23 09:10:20 +10:00
WithoutPants
5ecea3f69f Test database generator (#1513) 2021-06-23 08:29:10 +10:00
peolic
be2fe1de26 Update chromedp to fix console errors (#1521) 2021-06-23 08:05:58 +10:00
WithoutPants
ae3400a9b1 DLNA refactor and support browse folder objects (#1517) 2021-06-22 18:56:16 +10:00
WithoutPants
5fdfbaa7f1 Query bug fixes (#1510)
* Fix joins being dropped
* Fix missing scene stash_id criterion
* Refactor criterion handlers
* Add tag alias filter
* Remove handleCriterionFunc
2021-06-21 15:48:28 +10:00
WithoutPants
df6e06aaf6 Allow navigation by clicking lightbox image (#1516) 2021-06-21 14:55:31 +10:00
InfiniteTF
3d1b949f4c Add button to scene page to open scene in external player (#679)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-06-21 14:52:21 +10:00
WithoutPants
8e636545f7 Include server host in plugin input (#1514) 2021-06-21 14:38:44 +10:00
gitgiggety
d7439b4832 Optimize studio filter on performers (#1515) 2021-06-21 14:17:43 +10:00
peolic
86bd993b60 fix scrape dialog title (#1511) 2021-06-17 17:57:19 +10:00
WithoutPants
dc7584d77e Saved filters (#1474)
* Refactor list filter
* Filter/criterion refactor
* Rename option value to type
* Remove None from options
* Add saved filter button
* Integrate default filters
2021-06-16 14:53:32 +10:00
WithoutPants
4fe4da6c01 Merge tags functionality (#1481)
* Add API to merge tags

Add new API endpoint, `tagsMerge(source, destination)` to merge multiple
tags into a single one. The "sources" must be provided as a list of ids
and the destination as a single id. All usages of the source tags
(scenes, markers (primary and additional), images, galleries and
performers) will be updated to the destination tag, all aliases of the
source tags will be updated to the destination, and the name of the
source will be added as alias to the destination as well.

* Add merge tag UI
* Add unit tests
* Update test mocks
* Update internationalisation
* Add changelog entry

Co-authored-by: gitgiggety <gitgiggety@outlook.com>
2021-06-16 14:33:54 +10:00
WithoutPants
45f4a5ba81 Various UI fixes (#1502)
* Set/unset existing ids when moving to/from set
* Refactor rating banner
* Fix overlapping in multi set
* Prevent UI crash on bad hierarchical input value
2021-06-16 12:17:54 +10:00
bnkai
b55715775d Fix concurrency issue in audio preview option (#1500) 2021-06-15 17:12:39 +10:00
Still Hsu
3ae187e6f0 Incorporate i18n into UI elements (#1471)
* Update zh-tw string table (till 975343d2)
* Prepare localization table
* Implement i18n for Performers & Tags
* Add "add" action strings
* Use Lodash merge for deep merging language JSONs

The original implementation does not properly merge language files, causing unexpected localization string fallback behavior.

* Localize pagination strings
* Use Field name value as null id fallback

...otherwise FormattedMessage is gonna throw when the ID is null

* Use localized "Path" string for all instances
* Localize the "Interface" tab under settings
* Localize scene & performer cards
* Rename locale folder for better compatibility with i18n-ally
* Localize majority of the categories and features
2021-06-14 15:48:59 +10:00
WithoutPants
46bbede9a0 Plugin hooks (#1452)
* Refactor session and plugin code
* Add context to job tasks
* Show hooks in plugins page
* Refactor session management
2021-06-11 17:24:58 +10:00
WithoutPants
dde361f9f3 Handle case sensitive file moves (#1427) 2021-06-11 15:25:09 +10:00
bnkai
f1786ad871 Make audio stream optional for preview generation (#1454) 2021-06-11 15:01:32 +10:00
WithoutPants
f843359ba3 Handle auto-tagging where filename has no whitespace in name (#1488) 2021-06-08 10:47:22 +10:00
WithoutPants
099b4ecc56 Fix marker display mode (#1487) 2021-06-07 15:09:06 +10:00
WithoutPants
3e80dffe34 Fix setting scene gallery (#1484) 2021-06-06 15:33:06 +10:00
WithoutPants
c53799c25b Fix Performer Studio filtering (#1483)
* Fix performer studio filtering

* Fix studio filter hook
2021-06-06 15:05:05 +10:00
WithoutPants
732cc57149 Fix card click selection (#1476)
* Make other cards use generic card
2021-06-04 12:11:17 +10:00
WithoutPants
2469012008 Fix empty sort by causing UI crash (#1480) 2021-06-04 09:49:10 +10:00
bnkai
ad0a9d0707 Fix movies sorting, scene studio editing (#1478)
* Fix movies:sort_by->scenes_count, scene:edit->remove studio
2021-06-04 09:21:17 +10:00
Still Hsu
2ce4d9f0d8 Fix exception when scene preview is unavailable (#1477) 2021-06-03 21:05:43 +10:00
gitgiggety
7164bb28ac Filter studio hierarchy (#1397)
* Add basic support for hierarchical filters

Add a new `hierarchicalMultiCriterionHandlerBuilder` filter type which
can / will be used for filtering hierarchical things like the
parent/child relation of the studios.
On the frontend side a new IHierarchicalLabeledIdCriterion criterion
type has been added to accompany this new filter type.

* Refactor movieQueryBuilder to use filterBuilder

Refactor the movieQueryBuilder to use the filterBuilder just as scene,
image and gallery as well.

* Support specifying depth for studios filter

Add an optional depth field to the studios filter for scenes, images,
galleries and movies. When specified that number of included
(grant)children are shown as well. In other words: this adds support for
showing scenes set to child studios when searching on the parent studio.

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-06-03 20:52:19 +10:00
WithoutPants
508f7b84f2 Fix plugin cache initialisation (#1475) 2021-06-03 11:00:17 +10:00
InfiniteTF
c98cc73f33 Fix scene editing of scenes with stash_ids (#1467) 2021-06-03 10:48:58 +10:00
WithoutPants
1bb5de12e3 Use formik for scene edit (#1429)
* Use formik for scene edit panel
* Fix unsetting rating
* Disable save if not dirty
* Movie image fixes
2021-06-02 08:33:38 +10:00
WithoutPants
975343d2e9 Make multiset mode buttons more obvious (#1435) 2021-06-01 08:55:15 +10:00
peolic
eec071f248 Small UI filter fixes (#1456)
* Fix interactive filter name/value
* place `none` filter criterion first and disable it
* display current criterion when editing filter
2021-06-01 08:16:16 +10:00
EnameEtavir
b5a26cec8b Deprecation Fix: Updated gqlgen server handler initialization (#1415)
Only changed to the new initialization API.
To minimize risk of possible regressions, I tried to make as little changes as possible.

Resolves #1135
2021-05-31 13:58:32 +10:00
WithoutPants
3e81d45ae9 UI filter refactor (#1406)
* Refactor Criterion
* Separate filter options from filter
* Rename utils to factory
* Sort sort by options by alphabetical
* Refactor criterion options
* Simplify list filter options
* Refactor i8n
* Simplify ILabeledIdCriterion
2021-05-31 13:46:21 +10:00
bnkai
c5fed1bbdc Fix sort by movies_scene_number (#1448) 2021-05-28 09:01:03 +10:00
peolic
47ecb9f9b1 Fix scraped tag creation (#1436) 2021-05-28 09:00:13 +10:00
WithoutPants
c70faa2a53 Tag aliases (#1412)
* Add Tag Update/UpdateFull
* Tag alias implementation
* Refactor tag page
* Add aliases in UI
* Include tag aliases in q filter
* Include aliases in tag select
* Add aliases to auto-tagger
* Use aliases in scraper
* Add tag aliases for filename parser
2021-05-26 14:36:05 +10:00
WithoutPants
9b57fbbf50 Embedded javascript plugins (#1393) 2021-05-26 14:17:53 +10:00
peolic
cc5ec650ae Fix scraper date parser failing when parsing time (#1431)
* Don't mutate the original scraped date

`time.Parse` is case-sensitive for some values, `AM/pm` in particular
2021-05-26 07:29:51 +10:00
EnameEtavir
d6ada23616 Fix: unhandled errors (#1419)
As these errors where not explicitly ignored with _, I made changes to make sure they bubble up.
2021-05-25 18:40:51 +10:00
WithoutPants
65baf46c40 Revert scrubber debounce (#1428) 2021-05-25 14:57:02 +10:00
stashist
872e0b531c utils: oshash: add tests (#1285)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-05-25 11:32:59 +10:00
stashist
fc9d70f702 utils: vtt: test + rewrite (#1284)
* utils: vtt: add tests

In lieu of documentation.

* utils: vtt: rewrite for correctness and simplicity

Now handles fractional seconds and negative values correctly.
2021-05-25 11:25:26 +10:00
peolic
3d93f7f0fe Fix invalid scene queue generated link (#1425)
* Escape quotes in criterion label

JSON encoding and slicing off the encompassing JSON-string quotes seems like a safer option

* Wrap criterion parse in try/catch

to prevent the page from crashing
2021-05-25 11:18:09 +10:00
EnameEtavir
5c4351f338 Cleanup fixes (#1422)
* cleanup: remove dead code

removing some code that does nothing

* cleanup: fixing usage of deprecated gqlgen/graphql api in api/changeset_translator

* cleanup: changing to recommended comparison methods

Changing byte and case-insensitive string comparison to the recommended methods.

* cleanup: making staticcheck happy
2021-05-25 11:03:09 +10:00
peolic
d326d4380f Add CreatedAt & UpdatedAt to all object resolvers (#1421)
* add `CreatedAt` & `UpdatedAt` to all objects
* add `FileModTime` to supported objects
* Use `GQL.SlimTagDataFragment` over `GQL.Tag`
2021-05-25 10:56:34 +10:00
Tweeticoats
3981a781b9 This adds extra libraries required by scrapers: requests-toolbelt lxml cloudscraper (#1381)
This installs pip in the prep environment, uses this to install cloudscraper then copies this to the final application container.
2021-05-25 10:48:06 +10:00
peolic
4bad988373 Remove performer "is missing scenes" filter (#1414) 2021-05-25 10:45:26 +10:00
EnameEtavir
fad558a618 Fix: login form label references (#1416)
Fixes the login form label references for Username and Password by adding
the missing id attributes to each of the input fields respectively
to which the labels where referring to.
2021-05-25 08:26:21 +10:00
EnameEtavir
dc453c193d Fix: file close even if file was not opened (#1417)
Fixed a bug where in many implementations of load-file functions the file-close was still
executed even if the file-open resulted in an error.
2021-05-25 07:52:55 +10:00
peolic
0472cd9996 Fix performer filters and sort keys (#1413)
* Fix "performer is missing image" filter
* Fix `scene_count` sort
* Add unit tests

Co-authored-by: bnkai <48220860+bnkai@users.noreply.github.com>
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-05-24 17:45:51 +10:00
EnameEtavir
c08e0c0f60 add REACT_APP_PLATFORM_PORT for development (#1411)
* add REACT_APP_PLATFORM_PORT for development

Add development REACT_APP_PLATFORM_PORT env variable
to createClient.getPlatformURL so that you can more easily
run more stash platform services at once during development.

If non is given, it falls back to standard port "9999".
2021-05-24 15:44:40 +10:00
WithoutPants
0e01374537 Job queueing (#1379) 2021-05-24 14:24:18 +10:00
EnameEtavir
9aa2dfd96c fix typos in performer models repo interface (#1410)
tag methods used sceneID argument name instead of performerID
2021-05-24 14:07:08 +10:00
UnluckyChemical765
547f6d79ad Add Handy / Funscript support (#1377)
* Add funscript route to scenes

Adds a /scene/:id/funscript route which serves a funscript file, if present.

Current convention is that these are files stored with the same path, but with the extension ".funscript".

* Look for funscript during scan

This is stored in the Scene record and used to drive UI changes for funscript support.

Currently, that's limited to a funscript link in the Scene's file info.

* Add filtering and sorting for interactive
* Add Handy connection key to interface config
* Add Handy client and placeholder component.

Uses defucilis/thehandy, but not thehandy-react as I had difficulty integrating the context with the existing components.

Instead, the expensive calculation for the server time offset is put in localStorage for reuse.

A debounce was added when scrubbing the video, as otherwise it spammed the Handy API with updates to the current offset.
2021-05-24 13:34:28 +10:00
WithoutPants
33999d3e93 Studio Performers page (#1405)
* Refactor performer filter
* Add performer studio criterion
* Add Studio Performers page
2021-05-22 17:07:03 +10:00
gitgiggety
586d146fdb Apply all post processors to performer (#1387)
* Apply all post processors to performer

Scraping a performer by fragment doesn't correctly work with tags.
When tags are returned to the scraper then all are recognized as new.
This is due to the post process method not being applied while it should
be, as is done when scraping a performer by URL.
2021-05-21 12:32:28 +10:00
bnkai
ab24d0f625 Add subtractDays pp action to scraper (#1399) 2021-05-21 12:20:12 +10:00
WithoutPants
76019af3e5 DLNA (#1364) 2021-05-20 16:58:43 +10:00
WithoutPants
0f579076b6 Clamp page to max pages (#1403) 2021-05-20 07:28:42 +10:00
Still Hsu
81058a7807 i18n: Add zh-TW localization strings (#1375) 2021-05-18 13:24:40 +10:00
WithoutPants
22a2fc3177 Make ffmpeg download location more portable (#1384)
* Download ffmpeg to config path
* Add setup message for ffmpeg download
* Handle missing ffmpeg in tasks
2021-05-18 09:14:25 +10:00
WithoutPants
3df7ee06eb Shortcut scan walk for excluded folders (#1382)
* Shortcut scan walk for excluded folders
* Add note to manual
* Add changelog entry
2021-05-17 15:46:00 +10:00
bnkai
aba2514534 fix DirExists (#1388) 2021-05-17 15:05:29 +10:00
InfiniteTF
ce20df343a Add option to remove studio stash ids (#1378)
* Add option to remove studio stash ids
* Add v0.8 changelog
2021-05-17 14:58:25 +10:00
WithoutPants
9d138278c2 Github build action refinement and caching (#1295)
* Run in same container
* Add cross compile targets to makefile
* Use make targets and existing container
* Cache UI build
* Update cross-compile script
2021-05-16 19:19:56 +10:00
WithoutPants
16fe21138f CPU profiling (#1371)
* Add cpuprofile flag
* Add notes to readme
2021-05-16 17:21:11 +10:00
bnkai
bc9aa02835 Discard null values from scraper results (#1374) 2021-05-16 16:40:54 +10:00
WithoutPants
c73025c86d Merge pull request #1391 from stashapp/master
Merge back to develop for tag
2021-05-15 16:58:29 +10:00
WithoutPants
3acb21d4e1 Merge pull request #1390 from stashapp/develop
Merge to master for 0.7
2021-05-15 16:17:08 +10:00
WithoutPants
e0623eb302 Fix initial setup issue issues (#1380)
* Refactor initial setup behaviour
* Adjust wizard
2021-05-13 22:15:21 +10:00
InfiniteTF
5a37e6cf52 Add search modal for stash-box performer scraper (#1373)
* Cache tagger fingerprint lookups between renders
* Show search modal for stash-box performer scraper
2021-05-10 09:33:08 +10:00
WithoutPants
3f97b3a1cb Remove unnecessary graphql fields (#1370)
* Remove unnecessary graphql fields
* Optimise joined queries
* Tag resolver query optimisation
2021-05-09 19:25:57 +10:00
InfiniteTF
81cf3d3337 Fix sorting of tagger fingerprint matches (#1369) 2021-05-07 13:00:29 +10:00
WithoutPants
bdac352250 Update demo video link 2021-05-05 14:14:39 +10:00
InfiniteTF
31981d4116 Add in-memory screenshot generation for sprites and phash (#1316) 2021-05-05 13:22:05 +10:00
WithoutPants
08c294414d Fix initial plugins/scrapers paths when initialising in home directory (#1358)
* Only set default values once config file present
* Fix configLocation presentation when using home
2021-05-04 07:42:33 +10:00
bnkai
2ab42e9cd3 Populate image/gallery title during scan (#1359) 2021-05-03 14:21:51 +10:00
InfiniteTF
896c3874af Stash-Box Performer Tagger (#1277)
* Add bulk stash-box performer task
* Add stash-box performer scraper to scrape with menu
2021-05-03 14:21:20 +10:00
WithoutPants
a3609079bb Autotag support for images and galleries (#1345)
* Add compound queries for images and galleries
* Implement image and gallery auto tagging
2021-05-03 13:09:46 +10:00
Jeremy Meyers
2c52fd711b Several syntactical and content changes (#1347) 2021-05-03 12:49:15 +10:00
WithoutPants
d7a04ced00 Revert always show preview videos on small devices (#1340) 2021-05-03 08:23:19 +10:00
WithoutPants
3f0c965400 Fix development releases 2021-05-01 11:19:21 +10:00
InfiniteTF
4a04dfe4a2 Fix scene tagger bugs (#1357) 2021-04-30 14:55:18 +10:00
bnkai
597576f5e6 Get distinct values from scraper (#1338)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-04-29 11:38:55 +10:00
julien0221
502d99de1b Added new filters (date and title) to galleries (#1344)
* Added new filters (date and title) to galleries
* Added image_count on filter for galleries
2021-04-29 11:31:51 +10:00
julien0221
4d13e8d7f7 Fixed rating filter on studios (#1342) 2021-04-29 11:20:59 +10:00
WithoutPants
210feb4034 Apply scene queuing for all scene listviews (#1332)
* Apply queue population for all scene list views
* Add missing localisation strings
2021-04-28 09:27:47 +10:00
WithoutPants
fe0c5615a6 Memo-ise list hook functions (#1329) 2021-04-28 09:12:35 +10:00
julien0221
70b66d91a0 Added rating to performers and studios (#1308) 2021-04-26 13:48:32 +10:00
stg-annon
eefc628cf0 update docs to match current functionality (#1339)
was wondering why `per_page:0` was not working it seems to have been updated to `per_page:-1` to return all results
2021-04-26 13:37:31 +10:00
bnkai
aedadc3857 Add lbToKg pp action to the scraper (#1337) 2021-04-26 13:31:25 +10:00
WithoutPants
2eb2d865dc Auto tag rewrite (#1324) 2021-04-26 12:51:31 +10:00
julien0221
f66010a367 Fixed 0 for weight when a new performer is created and fixed the search is null (#1336) 2021-04-26 12:13:50 +10:00
bnkai
7836a37d6e Fix various generate issues (#1322)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-04-22 13:51:51 +10:00
WithoutPants
bf3f658091 Movie scene sort (#1325)
* Add movie_scene_number sort order
* Sort movie scenes by scene number by default
2021-04-22 12:22:51 +10:00
peolic
1767390e0d Overwrite new performer image after clearing current image (#1321) 2021-04-21 14:19:40 +10:00
Jeremy Meyers
79a180ba73 Fix README formatting (#1328) 2021-04-21 10:33:33 +10:00
WithoutPants
8705f78591 Duplicate checker UI improvements (#1309)
* Add tools settings page
* Add tools and move dupe checker
* Make negative number get all
* Show missing phashes
* Add multi-edit button
* Show scene details
2021-04-20 18:58:28 +10:00
WithoutPants
39512e1452 Separate UI (#1299)
* Add custom_ui_location to serve UI from filesystem
2021-04-20 17:12:40 +10:00
peolic
9200f167bf Add studio *_count filters and sort options (#1307) 2021-04-20 16:48:36 +10:00
peolic
1759a99f65 Fix creating performer from gallery scrape dialog (#1320) 2021-04-18 13:22:02 +02:00
InfiniteTF
cd0a9a1d62 Fix performer scraping (#1314) 2021-04-17 08:52:18 +10:00
InfiniteTF
e3fa8f7b24 Fix fingerprint search when scene only has phash match (#1312) 2021-04-16 19:15:47 +02:00
bnkai
a5e9e7abce Update README with currently used ffmpeg URLs (#1304) 2021-04-16 16:20:20 +10:00
julien0221
d673c4ce03 added details, deathdate, hair color, weight to performers and added details to studios (#1274)
* added details to performers and studios
* added deathdate, hair_color and weight to performers
* Simplify performer/studio create mutations
* Add changelog and recategorised

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-04-16 16:06:35 +10:00
bnkai
cd6b6b74eb Add http headers support to scraper (#1273) 2021-04-16 15:42:56 +10:00
WithoutPants
0b40017b09 Sort performers in popover and card views (#1294) 2021-04-15 11:33:20 +10:00
InfiniteTF
e59018acfb Skip validation of existing paths when adding new paths (#1301) 2021-04-15 11:01:31 +10:00
WithoutPants
ea54a67798 Add scene/image/gallery popover count buttons for performer/studio/tag cards (#1293)
* Add counts to graphql schema
* Add count resolvers and query refactor
* Add count popover buttons
2021-04-15 10:46:31 +10:00
InfiniteTF
e6aaa196f3 Load settings panels on demand (#1302) 2021-04-15 10:01:44 +10:00
stashist
34f114faff Simplify GH build pipeline. (#1268)
The toolchain is already bundled in the stashapp/compiler image.
Rather than introducing a second one via GH actions standardize on that
one instead.

Also
* Clear up what "Cross Compile" actually does
* Still pull stashapp/compiler separately for easier debugability.
2021-04-13 16:11:19 +10:00
Elad Lachmi
f443223d16 [Feature] Added slideshow to gallery in wall display mode (#1224) 2021-04-13 14:59:37 +10:00
julien0221
6a4421f8e1 Whitespace is not trimmed from the end of query strings (#1263)
* fixed whitespace not trimmed query string
* fixed whitespace trimming on backend
* added query trim tests and fixed double space
2021-04-13 10:32:52 +10:00
WithoutPants
f5dc654f6b Support streaming via API key (#1279)
* Support api key via url query parameter
* Add api key to stream URL
2021-04-12 11:05:49 +10:00
WithoutPants
f6ffda7504 Setup and migration UI refactor (#1190)
* Make config instance-based
* Remove config dependency in paths
* Refactor config init
* Allow startup without database
* Get system status at UI initialise
* Add setup wizard
* Cache and Metadata optional. Database mandatory
* Handle metadata not set during full import/export
* Add links
* Remove config check middleware
* Stash not mandatory
* Panic on missing mandatory config fields
* Redirect setup to main page if setup not required
* Add migration UI
* Remove unused stuff
* Move UI initialisation into App
* Don't create metadata paths on RefreshConfig
* Add folder selector for generated in setup
* Env variable to set and create config file.
Make docker images use a fixed config file.
* Set config file during setup
2021-04-12 09:31:33 +10:00
InfiniteTF
c38660d209 Add phash generation and dupe checking (#1158) 2021-04-12 09:04:40 +10:00
WithoutPants
a2582047ca Join count filter criteria (#1254)
Co-authored-by: mrbrdo <mrbrdo@gmail.com>
Co-authored-by: peolic <66393006+peolic@users.noreply.github.com>
2021-04-09 18:46:00 +10:00
peolic
6a0c73b3a1 Remove external resource from Login page (#1275) 2021-04-09 16:42:52 +10:00
julien0221
d042ec42ee Added Auto scroll user back to the top when page navigation is clicked (#1270) 2021-04-09 15:27:48 +10:00
julien0221
25311247ed added an url filter option in scenes (#1266)
* added an url filter option in scenes
* added url filter on gallery, movies, performers and studios
* Add empty string filter to stringCriterionHandler
* Add unit tests

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-04-09 15:05:11 +10:00
peolic
60af076fff Fix "Clear Image" button (#1249)
* Fix "Clear Image" button (Performer Edit)
* Fix "Clear Image" button (New Performer)
* Fix "Clear Image" button (Edit Studio)
* Fix "Clear Image" button (Edit Tag)
2021-04-09 14:41:28 +10:00
stashist
4462b3cc8e Handle /healthz for liveness checks. (#1264) 2021-04-09 10:06:02 +10:00
bnkai
2edcdeaeb9 Support today, yesterday when using parseDate in scrapers (#1261) 2021-04-07 09:09:04 +10:00
peolic
d8ba4a08c0 Update various GQL image fields' comments (#1271) 2021-04-07 08:58:41 +10:00
julien0221
72b027a887 Added random for studios, movies and tags (#1250) 2021-04-07 08:32:20 +10:00
peolic
7671465334 Fix performer age timezone issues (#1251)
* Parse date string manually
2021-04-02 10:09:10 +11:00
bnkai
2c1300cae0 Upgrade x/image (#1248) 2021-04-01 16:43:42 +11:00
peolic
35718ce59a Disable sounds on scene/marker wall previews by default (#1247) 2021-04-01 16:10:56 +11:00
WithoutPants
1412b554a0 Api key (#1241) 2021-03-31 16:08:52 +11:00
UncleRoger33
2c2e56d33a Add format to performer field placeholder (#1232)
* Update README.md

Extra letter "p" in the title removed and "(FAQ)" suffix added.

Co-authored-by: peolic <66393006+peolic@users.noreply.github.com>
2021-03-31 15:55:15 +11:00
WithoutPants
ccb96c3795 Movie UI refresh (#1227)
* Improve movie UI
* Return nil when no back image set
2021-03-31 14:54:58 +11:00
WithoutPants
d5e9030768 Scene queuing (#1214)
* Add missing localisation strings
* Ignore container error in scene streams
* Implement missing FindScenes by ID
2021-03-31 14:36:11 +11:00
peolic
496900df42 Fix inaccurate age calculation (#1237) 2021-03-30 14:25:56 +11:00
peolic
7acae34ed4 Fix performer search columns (#1236)
* Fix performer search columns
* Update changelog
* Move changelog to new version

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-03-30 14:04:57 +11:00
WithoutPants
d30a68567e Update libraries and regenerate yarn.lock (#1231)
* Update and regenerate yarn.lock
* Remove eslint check for react function order
2021-03-30 12:33:57 +11:00
WithoutPants
8a3d2e8e06 Merge pull request #1240 from stashapp/master
Merge master back to develop for tag
2021-03-29 14:15:24 +11:00
WithoutPants
cad96b7872 Update build.yml 2021-03-29 12:59:03 +11:00
WithoutPants
de538be79c Merge pull request #1239 from stashapp/develop
Merge to master for 0.6
2021-03-29 12:05:59 +11:00
bnkai
4299f113e0 Fix Freeones search (#1230) 2021-03-25 10:01:56 +11:00
WithoutPants
b39fe3ed2b Correct tag link for gallery and images tags (#1221) 2021-03-24 11:03:52 +11:00
bnkai
68d4a4fe42 Add User Agent to image download reqs (#1222) 2021-03-24 08:12:11 +11:00
WithoutPants
73a8bad1bc Add missing tag writer for performer importer (#1213) 2021-03-18 21:45:31 +11:00
WithoutPants
960f843259 Fix filter building with sub-filters (#1212)
* Fix bracketing on sub-filters
* Add vscode to gitignore
2021-03-18 21:45:18 +11:00
WithoutPants
d93011a828 Add write mutex and max connection lifetime (#1211) 2021-03-18 21:45:01 +11:00
bnkai
215737d6c5 Add configFilePath and scrapersPath to configuration query (#1205) 2021-03-18 11:07:56 +11:00
InfiniteTF
6369a500b3 Update go-sqlite3 to 1.14.6 (#1209) 2021-03-17 11:17:27 +11:00
InfiniteTF
58243cded0 Remove slim graphql endpoints (#1207) 2021-03-17 11:17:01 +11:00
WithoutPants
7e6127975d Handle NULL in regex criteria (#1208) 2021-03-16 11:13:14 +11:00
WithoutPants
f7cd9cb00d Performer edit UI further updates (#1206)
* Make performer edit single column
* Make aliases textarea
* Add textareas to performer scrape dialog
2021-03-16 11:10:49 +11:00
InfiniteTF
ecac7a8013 Add timestamp suffix to all image urls (#1200) 2021-03-13 11:49:20 +11:00
InfiniteTF
a619b9dd48 Improve performer scrape search modal (#1198) 2021-03-13 11:48:04 +11:00
WithoutPants
b63e8ef929 Add Galleries tab to Tag details page (#1195) 2021-03-12 08:27:59 +11:00
WithoutPants
23d85655a8 Refactor tag query (#1194) 2021-03-11 22:17:37 +11:00
Jeremy Meyers
53cb9a1b7b Documentation Updates to README.md (#1179) 2021-03-11 15:56:22 +11:00
WithoutPants
a3a531d122 Fix IsPathInDir (#1192) 2021-03-11 13:37:13 +11:00
WithoutPants
55aee21cff Upload Image from url (#1193) 2021-03-11 12:56:34 +11:00
WithoutPants
b3966b3c76 Remove streaming resolutions over max configured (#1187) 2021-03-11 12:51:42 +11:00
SpedNSFW
b647a75151 Toggle visibility of unmatched scenes in Tagger (#1176) 2021-03-10 14:26:48 +11:00
gitgiggety
baeeb2d649 Hide create option when searching in filters (#1169)
Hide the "Create '<term>'" option when using filters. This as it doesn't make sense to create a new performer/tag/studio in the context of searching for one. As obviously there won't be any results after searching as it has just been created and not assigned to anything yet.
2021-03-10 14:08:45 +11:00
gitgiggety
f794c6ae45 Add scrape gallery from fragment to UI (#1166) 2021-03-10 13:47:22 +11:00
WithoutPants
a0676d5c30 Performer tags (#1132)
* Add scraping support for performer tags
* Add performer count to tag cards
* Refactor sqlite test setup
* Add performer tag filtering in gallery and image
* Add bulk update performer
* Add Performers tab to tag page
* Add count filters and sort bys for tags
* Move scene count to icon in performer card #1148
2021-03-10 12:25:51 +11:00
InfiniteTF
698e21a04f Fix scene form layout bugs (#1177) 2021-03-07 09:19:30 +11:00
WithoutPants
9d1b716f48 Performer UI improvements (#1168)
* Refactor performer edit page with Formik
* Upgrade react-scripts
* Make eslint errors warnings in dev environment
* Refactor performer details
* Prompt if leaving dirty performer edit page
2021-03-05 15:46:20 +11:00
InfiniteTF
c2c06d8f8d Fix tagger parsing bugs (#1172) 2021-03-05 15:03:08 +11:00
WithoutPants
e5c5cde974 Detect cover images in subdirectories (#1144) 2021-03-04 10:52:45 +11:00
WithoutPants
16da483674 Change gallery icon to images (#1167) 2021-03-04 08:27:42 +11:00
SpedNSFW
bde5d07afb Find correct python executable (#1156)
* find correct python executable
For script scrapers using python, both python and python3 are valid depending on the OS and running environment. To save users from having any issues, this change will find the correct executable for them.

Co-authored-by: bnkai <bnkai@users.noreply.github.com>
2021-03-03 08:01:01 +11:00
WithoutPants
1850a2b533 Add sqlite filter builder. Add AND, OR, NOT filters to scene filter (#1115)
* Add resolution enum extension
* Add filter builder
* Use filterBuilder for scene query
* Optimise joins
* Add binary operators to scene query
* Use Query for auto-tag
2021-03-02 11:27:36 +11:00
bnkai
117e6326db Expose url for URLReplace in JSON scrapeByURL and scrapeByFragment (#1150)
* Expose url for URLReplace in JSON scrapeByURL and scrapeByFragment
* Apply queryURLReplace to xpath scrapers

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2021-03-02 09:19:56 +11:00
bnkai
fe990e00c1 Check if gallery is already associated during scanning (#1154) 2021-03-01 16:37:55 +11:00
gitgiggety
4825de7d35 Fix SQL error in 8K resolution filter (#1159) 2021-03-01 16:06:57 +11:00
WithoutPants
7cfff46d02 Gallery filter fix (#1147)
* Fix gallery performer and tags filters
* Add unit tests
2021-03-01 13:30:40 +11:00
bnkai
44ea777019 Add check version support for armv7, arm64 (#1142) 2021-03-01 12:37:46 +11:00
bnkai
711496e9f4 Add full timestamp for console/file logging (#1130) 2021-03-01 12:28:09 +11:00
InfiniteTF
01da28010d Gallery view persistence (#1105)
* Persist gallery image view separately from primary image view
2021-03-01 12:10:05 +11:00
InfiniteTF
7e0db2aad4 Change NULL filters to filter empty strings as well (#1137) 2021-03-01 11:48:25 +11:00
bnkai
144cd6e4f2 Skip insecure certificates check when scraping (#1120)
* Ignore insecure certificates when scraping
* add ScraperCertCheck to scraper config options
2021-03-01 11:47:39 +11:00
WithoutPants
a9ac176e91 Mobile UI improvements (#1104)
* Use dropdown for o-counter instead of hover
* Always show previews on non-hoverable device
* Add IntersectionObserver polyfill
* Prevent video previews playing fullscreen
2021-02-26 16:13:34 +11:00
WithoutPants
af6b21a428 Update latest_develop tag 2021-02-24 14:36:39 +11:00
WithoutPants
8ec25ef161 Add commitish for dev release 2021-02-24 13:48:56 +11:00
WithoutPants
777956f0ab GitHub actions (#1146) 2021-02-24 11:26:48 +11:00
SpedNSFW
acbdee76de Random strings for cookie values (#1122) 2021-02-23 13:40:43 +11:00
InfiniteTF
14230d7b52 Enable keepalive for websocket connection (#1134) 2021-02-23 13:03:02 +11:00
WithoutPants
f7a8899d90 Add rescan option to overflow dropdown (#1119)
* Make scan options optional
* Add scene rescan
* Add image rescan
* Add gallery rescan
* Add changelog
2021-02-23 12:56:01 +11:00
WithoutPants
7fbb92d071 Merge master back to develop for tag 2021-02-23 10:46:28 +11:00
WithoutPants
2ec595dedf Merge to master for 0.5 2021-02-22 18:04:33 +11:00
WithoutPants
f9b2a4be5e Update changelog 2021-02-22 16:00:53 +11:00
WithoutPants
ac117c2934 Fix performer input values being lost when failing to create (#1133)
* Fix lost performer input values
* Fix unsetting image studio
2021-02-19 20:09:59 +11:00
InfiniteTF
dd03c63da2 Add country synonyms for Iran and Moldova (#1121) 2021-02-19 14:27:21 +11:00
Tweeticoats
3f9b395b89 build arm and x86_64 docker containers (#1097) 2021-02-19 10:38:13 +11:00
InfiniteTF
deebeab9e8 Fix performer details gender (#1124) 2021-02-14 11:18:26 +01:00
InfiniteTF
647ae2d7f9 Fix cover image in scene edit tab (#1123) 2021-02-13 19:03:29 +01:00
InfiniteTF
758eccc659 Fix scene edit state resetting when scene is updated (#1112)
* Fix organized click resetting scene form state
* Fix state resetting for images/galleries
* Fix favoriting a performer resetting edit state
2021-02-11 14:33:16 +11:00
WithoutPants
bbc34bd1bf Exclude media in generated directory (#1118) 2021-02-11 11:06:04 +11:00
WithoutPants
7609969491 Add donate button to navbar (#1117) 2021-02-11 09:12:35 +11:00
InfiniteTF
8d8a8530e8 Migrate generated files when a scene is rescanned (#1106) 2021-02-10 10:50:34 +11:00
bnkai
bcbbd1474c fix check version (#1103) 2021-02-09 21:00:27 +11:00
bnkai
984a0c9247 Tweak scraper script error printing (#1107) 2021-02-09 19:07:53 +11:00
SpedNSFW
714ae541d4 fix json unmarshal error return (#1109) 2021-02-09 19:04:42 +11:00
JoeSmithStarkers
9da11603c2 Add selective cross compile (#921) 2021-02-04 09:41:43 +11:00
bnkai
918b739b6c Add checksums for releases (#1093) 2021-02-04 09:41:05 +11:00
InfiniteTF
25b600f768 Fix tagger performance issue and date parsing (#1096) 2021-02-04 08:22:52 +11:00
WithoutPants
0dd2e269ee Don't delete downloads directory at startup if generated not set (#1098)
* Don't empty directories if generated not set
* Rename downloads to download_stage
2021-02-02 20:32:37 +11:00
WithoutPants
6d48cd1c97 Minor UI tweaks (#1099)
* Show one decimal point for sizes GB and over
* Don't open 0.4 version section by default
2021-02-02 20:25:36 +11:00
WithoutPants
4e9ebe055b Fix scene filename parser Q filter value (#1100) 2021-02-02 20:25:08 +11:00
WithoutPants
e4d91a0226 String regex filter criteria and selective autotag (#1082)
* Add regex string filter criterion
* Use query interface for auto tagging
* Use Query interface for filename parser
* Remove query regex interfaces
* Add selective auto tag
* Use page size 0 as no limit
2021-02-02 07:57:56 +11:00
InfiniteTF
4fd022a93b Decouple galleries from scenes (#1057) 2021-02-02 07:56:54 +11:00
Belley
86bfb64a0d Fix freeones scraper (#1091) 2021-02-01 08:15:50 +11:00
InfiniteTF
6114caa938 Fix import file copying (#1085) 2021-02-01 08:15:10 +11:00
InfiniteTF
23d2668b38 Update javascript polyfills (#1083) 2021-01-30 09:16:28 +11:00
InfiniteTF
89fcd6d775 Make file upload limits configurable (#1079) 2021-01-29 20:27:02 +11:00
bnkai
df8675c2e7 Add Dry Run option to clean task (#1081) 2021-01-29 15:03:34 +11:00
InfiniteTF
203fc3e4b2 Force reload of custom css if it's updated (#1073) 2021-01-29 15:00:47 +11:00
InfiniteTF
0d7663c13d Fix performer scrape select, and studio/gallery select glitching (#1080) 2021-01-28 21:00:58 +01:00
InfiniteTF
d1274d559d Update javascript libraries (#1075) 2021-01-27 11:25:29 +11:00
bnkai
088f32a116 * fix database reset (#1076) 2021-01-26 10:37:42 +11:00
WithoutPants
3b41894dbd Add backup database functionality (#1069) 2021-01-21 22:02:09 +11:00
WithoutPants
093b997eb1 Login to docker before building image (#1067) 2021-01-19 11:11:10 +11:00
WithoutPants
1e04deb3d4 Data layer restructuring (#997)
* Move query builders to sqlite package
* Add transaction system
* Wrap model resolvers in transaction
* Add error return value for StringSliceToIntSlice
* Update/refactor mutation resolvers
* Convert query builders
* Remove unused join types
* Add stash id unit tests
* Use WAL journal mode
2021-01-18 12:23:20 +11:00
InfiniteTF
7bae990c67 Fix interface state storage (#1064) 2021-01-15 15:15:59 +11:00
bnkai
defb23aaa2 Fix vtt sprite generation ( issue #1033 ) (#1035) 2021-01-14 12:53:42 +11:00
InfiniteTF
aad4ddc46d Add batch delete for performers/tags/studios/movies (#1053)
* Add batch delete for performers/tags/studios/movies
* Fix ListFilter styling bug
2021-01-13 11:57:53 +11:00
InfiniteTF
8a3d940aa7 Prevent studio from being selected as its own parent (#1051) 2021-01-12 17:11:01 +11:00
InfiniteTF
3d83fa449d Fix z-index of performer scrape selector and correct no options message (#1050) 2021-01-12 15:05:01 +11:00
InfiniteTF
0a123548a0 Cache fixes (#1048)
* Bust cache for studio/tag image updates
* Reset cache when a scan/clean has been run
2021-01-12 15:03:50 +11:00
SpedNSFW
03a9d65cfe extend resolutions (#1036)
* extend resolutions
 - Simplifies logic
 - Adds more options including 540p, 1440p, and resolutions common to VR such as 1920p
 - Supports vertical/portrait videos and images
* implement new resolution filters
2021-01-07 16:10:59 +11:00
bnkai
1882b44951 Strip file extension from scene title when scanning (#1022) 2021-01-07 11:38:30 +11:00
dependabot[bot]
4fc0d47087 Bump axios from 0.21.0 to 0.21.1 in /ui/v2.5 (#1045)
Bumps [axios](https://github.com/axios/axios) from 0.21.0 to 0.21.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v0.21.1/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.21.0...v0.21.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-01-06 13:18:44 +11:00
InfiniteTF
6b1d229a6d Equalise card styles for movies/galleries/images (#1015) 2021-01-05 13:12:16 +11:00
Jeremy Meyers
d84d48bc29 Update AutoTagging.md (#1037) 2021-01-04 09:02:10 +11:00
InfiniteTF
d50238cf41 Various bugfixes for scene tagger (#1014)
* Tagger fixes
* Validate stash-box endpoint pattern
2020-12-28 13:28:29 +11:00
InfiniteTF
5c10712aab Fix performer page lightbox (#1020) 2020-12-24 11:10:09 +01:00
InfiniteTF
232a69c518 Add gallery wall view, and new lightbox (#1008) 2020-12-24 11:17:15 +11:00
WithoutPants
c8bcaaf27d Fix scene file name parser update (#998)
* Fix conversion of input maps
* Only set changed scene values in parser update
2020-12-24 09:03:23 +11:00
InfiniteTF
e84c92355e Fix integer overflow for scene size on 32bit systems (#994)
* Fix integer overflow for scene size on 32bit systems
* Cast to double in sqlite to prevent potential overflow
* Add migration to reset scene sizes and scan logic to repopulate if empty
2020-12-22 10:29:53 +11:00
bnkai
e883e5fe27 Add Mouse Click support for the CDP scraper (#827) 2020-12-22 09:42:31 +11:00
InfiniteTF
dd2086a912 Fix galleryCreate mutation (#1004) 2020-12-20 12:35:41 +01:00
WithoutPants
aadbcaeec2 Organised flag (#988)
* Add organized boolean to scene model (#729)
* Add organized button to scene page
* Add flag to galleries and images
* Import/export changes
* Make organized flag not null
* Ignore organized scenes for autotag

Co-authored-by: com1234 <com1234@notarealemail.com>
2020-12-18 08:06:49 +11:00
InfiniteTF
99bd7bc750 Fix broken isMissing filters (#1000) 2020-12-17 20:27:44 +01:00
InfiniteTF
f264baa330 Add includes/excludes modifiers to path filter (#996) 2020-12-17 14:00:07 +11:00
WithoutPants
931d3a0974 Fix login redirect to remember current page (#989) 2020-12-13 14:00:01 +11:00
InfiniteTF
4a08bd351a Fix scene gallery selection (#990) 2020-12-11 11:15:32 +11:00
aGlkZGVu
fad64ba126 Implement user customizable menu items (#974) 2020-12-09 11:59:09 +11:00
bnkai
938559ca11 Fix studio logo getting nulled when editing a studio (#986) 2020-12-07 08:08:49 +11:00
WithoutPants
86747acc78 Use changesets correctly when updating objects (#976) 2020-12-04 12:42:56 +11:00
WithoutPants
6eea33aec9 Fix manual tables (#978) 2020-12-02 08:26:49 +11:00
SpedNSFW
c45780dc59 Add missing gallery components (#969)
* add gallery scrapers to settings page
* add galleries to performers page
* add galleries to studios page
2020-12-01 19:38:53 +11:00
bnkai
a96ab9ce6f Add support for setting cookies in the scraper (#934) 2020-12-01 16:34:09 +11:00
bnkai
aecbd236bc Tune image referrer path (#968) 2020-11-30 10:50:43 +11:00
InfiniteTF
a7d333786f Fix studio parent getting wiped in edit mode (#973) 2020-11-30 10:50:04 +11:00
InfiniteTF
a45c1111be Add TruncatedText component (#932) 2020-11-27 13:01:37 +11:00
WithoutPants
54c9f167ba Show studio as text in scene cards where studio image isn't set (#965) 2020-11-27 08:01:56 +11:00
WithoutPants
1d910419d1 Replace natural_sort with third party call (#964) 2020-11-27 08:01:36 +11:00
peolic
89277f1e25 Fix oversized movie images on scrape dialog (#961) 2020-11-26 10:33:41 +11:00
InfiniteTF
7d37e3e564 Add type policies for entity fetch queries (#958) 2020-11-26 09:50:36 +11:00
JoeSmithStarkers
df37ddcc2c Added natural sort for scene and image titles (#943)
* Added natural sort for scene and images
* Use natural sort for movie names

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-11-25 20:09:07 +11:00
InfiniteTF
794ea00d37 Upgrade create-react-app and assorted libraries (#914)
* Update create-react-app, react, typescript and eslint versions
* Various library updates
2020-11-25 13:20:48 +11:00
JoeSmithStarkers
e3eb550a7d Parallel scanning/generation, and combined scanning/preview/sprite (#820)
* Implement parallel scanning and generation, and combined scanning/preview/sprite generation.
* Added UI component for preview/sprite generation during scan, and configurable number of parallel tasks.
* Add v050 changelog entry
2020-11-25 12:45:10 +11:00
WithoutPants
502e9297ad Merge pull request #960 from stashapp/master
Merge master to develop for tag
2020-11-24 22:24:49 +11:00
WithoutPants
56b47ff9be Merge pull request #959 from stashapp/develop 2020-11-24 09:50:55 +11:00
JoeSmithStarkers
f0ec37c343 Added screenshots/previews to tagger list (#939)
* Added screenshots/previews to tagger list
* Move errors and stashids to subcontent container, and tweak layout
* Fix search-result margin
Co-authored-by: Infinite <infinitekittens@protonmail.com>
2020-11-24 08:02:31 +11:00
WithoutPants
93068e1ded Merge pull request #955 from stashapp/develop
0.4 release
2020-11-23 09:40:54 +11:00
WithoutPants
abf0281903 Merge branch 'master' into develop 2020-11-23 08:36:07 +11:00
WithoutPants
bbf7dbe98f Changelog for 0.4 release (#951)
* 0.4 changelog
* Updated galleries manual page
2020-11-23 08:19:54 +11:00
InfiniteTF
21806decca Expand tagger manual entry and add link to tagger interface (#947) 2020-11-20 12:07:36 +11:00
bnkai
e62e74bff4 Use symwalk for scrapers (#938) 2020-11-16 09:21:26 +11:00
WithoutPants
0a098b1d63 Selective scan (#940) 2020-11-16 09:20:04 +11:00
InfiniteTF
ba8b3b29a4 Update findGalleries to only fetch imageCount instead of all images (#941) 2020-11-15 14:40:47 +11:00
WithoutPants
c74f145224 Only set stash from env if not set (#937) 2020-11-12 10:05:09 +11:00
WithoutPants
beb84b8e94 Fix image memory issue (#935)
* Return slim images from mutations
* Fix potential memory leaks
2020-11-10 20:19:13 +11:00
peolic
ceb888958e Update scraping docs (#929)
* update editorconfig to ignore trailing whitespaces in markdown
* fix incorrect code example
* add missing genders
* add gallery to scraping docs
* reorder Scraping.md
2020-11-10 13:03:44 +11:00
InfiniteTF
6bb24d1744 Prevent movie link from being wiped when tagging scene (#933) 2020-11-09 12:29:13 +11:00
WithoutPants
8097cd39d2 Lightbox keybinds (#928)
* Add mousetrap-pause
* Disable keybinds while lightbox open
2020-11-08 11:22:38 +11:00
Belley
94392c7c4d Fixing image for Freeones Scrapers (#930) 2020-11-07 09:36:26 +11:00
bnkai
ccc2df7315 Abort PR upload if no server is available (#922)
* gracefully abort PR upload
* timeout if api doesn't respond in 15secs
2020-11-06 13:15:50 +11:00
InfiniteTF
8a04e5df62 Prevent studio parent id and scene rating from being unset when tagged (#927) 2020-11-06 13:14:17 +11:00
WithoutPants
5f482b7b8a Handle zip file modification (#877)
* Rescan zip if updating mod time
* Use inequality for mod time comparison
* Add sort by file_mod_time (fixes #469)
2020-11-05 10:26:51 +11:00
InfiniteTF
9ec762ae9a Fix outstanding tagger issues (#912)
* Fix potential image errors
* Fix issue preventing favoriting of tagged performers
* Add error handling in case of network issues
* Show individual search errors
* Unset scene results if query fails
* Don't abort scene submission if scene id isn't found
2020-11-05 08:28:58 +11:00
WithoutPants
66c7af62f6 Add gallery file info (#919) 2020-11-05 08:18:57 +11:00
bnkai
cc81d0b3ee Migrate PR build storage from transfer.sh to Gofile.io (#916) 2020-11-03 11:54:59 +11:00
WithoutPants
cbfd9e82b7 Fix image clean (#913)
* Use correct regex when cleaning images
* Clarify video exclusion pattern heading
2020-11-03 09:34:53 +11:00
WithoutPants
bae82513eb Add equals/not equals string criteria (#917)
* Fix encoding of string criteria
* Add equals and includes (and not) string criteria
2020-11-03 09:26:07 +11:00
WithoutPants
8e75a8fff5 Add selection and export for all list pages (#873)
* Include studios in movie export
* Generalise cards
* Add selection and export for movies
* Refactor gallery card
* Refactor export dialogs
* Add performer selection and export
* Add selection and export for studios
* Add selection and export of tags
* Include movie scenes and gallery images
2020-10-31 09:41:12 +11:00
WithoutPants
07212dbea9 Fix image thumbnail display (#907) 2020-10-30 09:52:53 +11:00
WithoutPants
90c5a9dd4a Add page sizes up to 1000 (#904) 2020-10-29 09:27:56 +11:00
WithoutPants
01227ceb85 Fix recursive loop (#905) 2020-10-27 12:53:34 +11:00
WithoutPants
c75b5c204d Don't set default studio image (#887) 2020-10-27 09:35:50 +11:00
SpedNSFW
cfbffb3b96 Add basic i18n implementation (#879)
To be used as a reference point for any future i18n additions for either new languages or more translatable content.
2020-10-27 09:35:25 +11:00
JoeSmithStarkers
47468fe122 Cache generated regex for each path (#891) 2020-10-26 15:57:58 +11:00
dullcibus
b3906f4b97 Add languages to code blocks for syntax highlight (#896)
Added languages to code blocks to get colored syntax highlighting for easier reading.
2020-10-26 15:12:42 +11:00
InfiniteTF
77da544e98 Wire up Tagger set tags checkbox (#889) 2020-10-24 19:19:45 +11:00
InfiniteTF
3346f8dcca Stash-box tagger integration (#454) 2020-10-24 14:31:39 +11:00
WithoutPants
70f73ecf4a Update freeones scraper (#881) 2020-10-24 13:12:21 +11:00
JoeSmithStarkers
2987b7f3d2 Video filters and transforms (#826) 2020-10-22 15:45:05 +11:00
JoeSmithStarkers
71c814c116 Added streaming quality options (#790) 2020-10-22 15:02:27 +11:00
InfiniteTF
a31c8ccd33 Fix new performer scraping (#880) 2020-10-22 12:30:22 +11:00
WithoutPants
109e55a25a Query url parameters (#878) 2020-10-22 11:56:04 +11:00
WithoutPants
228a5c5537 Use temp redirects for setup (#875) 2020-10-22 08:17:15 +11:00
com1234475
3832c8505a Make performer name mandatory in graphQL (#273) (#841) 2020-10-21 11:27:16 +11:00
SpedNSFW
147d0067f5 Add gallery scraping (#862) 2020-10-21 09:24:32 +11:00
WithoutPants
872bb70f6e Fix scan issue when encountering invalid symlinks (#871)
* Implement fixed symwalk algorithm
* Remove dependency
2020-10-20 17:00:23 +11:00
WithoutPants
8eda72ad89 Image improvements (#847)
* Fix image performer filtering
* Add performer images tab
* Add studio images tab
* Rename interface
* Add tag images tab
* Add path filtering for images
* Show image stats on stats page
* Fix incorrect scan counts after timeout
* Add gallery filters
* Relax scene gallery selector
2020-10-20 10:11:15 +11:00
InfiniteTF
80199f79f3 Persist gallery list state (#864) 2020-10-19 08:21:38 +11:00
InfiniteTF
cf003a55bf Fix loading issue in galleries and redirect on gallery creation (#857)
* Fix loading issue in galleries and redirect on gallery creation
* Add error messages when image/galleries aren't found
* Clean up gallery/image/performer/scene view states
* Simplify error messages
2020-10-17 09:57:02 +11:00
InfiniteTF
bbc6c43201 Add shim for String.prototype.replaceAll (#858) 2020-10-17 09:46:24 +11:00
InfiniteTF
d9270dd7c3 Treat empty string columns as missing (#852) 2020-10-16 11:14:48 +11:00
InfiniteTF
528b32d1b7 Sort images in galleries by path (#855) 2020-10-16 10:56:24 +11:00
InfiniteTF
73eb5c7a1f Add image-count sorting, and image deletion on gallery deletion (#853) 2020-10-16 10:35:50 +11:00
WithoutPants
d0f1ad3c24 Show static image if wall video missing (#849) 2020-10-15 10:53:00 +11:00
InfiniteTF
482f8cbd92 Fix clean and scan bugs (#846) 2020-10-14 10:51:36 +11:00
WithoutPants
12cba97192 Add scraper list page (#833) 2020-10-13 15:19:54 +11:00
WithoutPants
aca2c7c5f4 Images section (#813)
* Add new configuration options
* Refactor scan/clean
* Schema changes
* Add details to galleries
* Remove redundant code
* Refine thumbnail generation
* Gallery overhaul
* Don't allow modifying zip gallery images
* Show gallery card overlays
* Hide zoom slider when not in grid mode
2020-10-13 10:12:46 +11:00
InfiniteTF
df3252e24f Fix folder selector link color (#842) 2020-10-12 08:26:20 +11:00
WithoutPants
4f9af6ba27 Example python plugin (#825)
* Add example python plugin
* Fix log incorrectly detecting as progress level
2020-10-12 08:20:20 +11:00
WithoutPants
ade109d9e4 Path filter for scenes and galleries (#834) 2020-10-12 08:19:51 +11:00
WithoutPants
08276ac616 Add collapse button to scene page (#838) 2020-10-11 18:35:34 +11:00
WithoutPants
98dda782aa Prevent invalid date tag in video file from aborting scan (#836)
* Give more context when ffprobe fails
* Suppress JSONTime unmarshal error
* Tidy scan logging
2020-10-11 12:02:41 +11:00
InfiniteTF
ca14859339 Fix filter layout on devices (#840) 2020-10-11 12:02:01 +11:00
WithoutPants
d55177c170 Parent studio link in studio page (#835) 2020-10-10 10:29:31 +11:00
WithoutPants
c3a7d30a33 Convert scraped movie create data (#832) 2020-10-09 11:43:54 +11:00
bnkai
94dc74f4a8 Fix ffmpeg/ffprobe downloads (#824) 2020-10-03 17:28:02 +10:00
JoeSmithStarkers
30e88b96ee Added ffmpeg/ffprobe permission correction code for linux/osx (#814) 2020-10-03 16:59:23 +10:00
WithoutPants
8866670e53 Add partial import functionality (#812) 2020-09-20 18:36:02 +10:00
WithoutPants
7a45943e8e Stash box client interface (#751)
* Add gql client generation files
* Update dependencies
* Add stash-box client generation to the makefile
* Move scraped scene object matchers to models
* Add stash-box to scrape with dropdown
* Add scrape scene from fingerprint in UI
2020-09-17 19:57:18 +10:00
WithoutPants
b0b5621337 Add 0.4.0 changelog, convert to md (#803)
* Turn page into shared component
* Add v0.4.0 changelog markdown page
* Rename version files
* Markdown conversion
2020-09-16 09:54:24 +10:00
WithoutPants
03d4826c85 Selective export (#770) 2020-09-15 17:28:53 +10:00
InfiniteTF
03f5e1a442 Config for stash-box instances (#748) 2020-09-14 17:13:35 +10:00
bnkai
b527a8d137 Update makefile for static build (#808) 2020-09-14 11:12:36 +10:00
caustico
5df1e0025f Add filter on Movie section "Is Missing is scenes" (#800) 2020-09-14 10:35:54 +10:00
caustico
933d6d0bd5 Add gallery icon in "scene card" and "scene list table" (#799) 2020-09-12 19:11:43 +10:00
caustico
981b2622a5 Add filter country when click the performer flag (#795) 2020-09-12 17:55:02 +10:00
InfiniteTF
b541322d0a Hotfix for theme preview bug (#804) 2020-09-12 17:53:37 +10:00
InfiniteTF
7f907fdf41 Fix date timezone bug (#807) 2020-09-12 17:52:48 +10:00
InfiniteTF
147f50de6b Update gallery view layout and switch libraries (#793)
* Update gallery view layout and switch libraries
* Tweak gallery grid layout
2020-09-11 18:18:31 +10:00
InfiniteTF
5cd7dcaeb2 Library updates (#792)
* Upgrade Typescript to 4.0
* Update i18n-iso-countries to 6.0
* Update react-intl to 5.8.0
* Update jimp to 0.16.1
* Update apollo and graphql libraries
* Update various libraries and fix linting/type errors
* Refactor cache invalidation
* Codegen refetch queries
2020-09-11 13:01:00 +10:00
InfiniteTF
5ba11e0e93 Persist studio/gallery/marker list filters (#802) 2020-09-11 11:08:59 +10:00
InfiniteTF
9095ba21dc Scene card preview refactor (#787)
* Refactor scene card preview
* Add delay to video preview
2020-09-11 10:52:36 +10:00
WithoutPants
629126df98 Update to golang 1.13 (#754)
* Update to use golang 1.13
* Update node and ubuntu versions
* Update compiler version
2020-09-11 10:43:41 +10:00
WithoutPants
19d1d30946 Change cross compiler to fixed version (#794)
* Change cross compiler to fixed version
* Update compiler version in travis
2020-09-10 16:22:20 +10:00
InfiniteTF
19dfa571da Fix erroneous pending thumbnail on wall items (#784) 2020-09-09 08:37:19 +10:00
WithoutPants
a26151c9a3 Merge master back to develop for tagging 2020-09-03 10:07:15 +10:00
WithoutPants
fb5867ba59 Fix travis script error 2020-09-02 13:23:17 +10:00
WithoutPants
2638a9d5e1 Merge pull request #782 from stashapp/develop
Version 0.3 release
2020-09-02 12:21:05 +10:00
InfiniteTF
5d9cc09fca Allow updating tag name capitalization (#781) 2020-09-02 10:30:37 +10:00
WithoutPants
16ea6abf91 Fix age filtering regression (#778)
* Show filter control in loading/error
* Add performer age unit tests
* Fix addWhere regression
2020-08-31 18:17:17 +10:00
bnkai
b437425a41 Add cbz to supported extensions as gallery (#774) 2020-08-31 14:21:49 +10:00
WithoutPants
c1d22f60a9 Add skip cleanup to docker releases 2020-08-31 13:35:05 +10:00
WithoutPants
1258a5e3f4 Remove echo statements 2020-08-31 13:13:10 +10:00
WithoutPants
0345bc9ef7 Make travis build and push docker images (#772) 2020-08-31 12:04:05 +10:00
InfiniteTF
cb753f28f6 Fix scene markers (#769) 2020-08-30 14:51:40 +10:00
WithoutPants
ae24fc2d3c Fix prod dockerfile to not pick up arm builds 2020-08-30 14:50:36 +10:00
WithoutPants
ba442e8d90 Fix develop dockerfile to not pick up arm binaries 2020-08-30 14:42:46 +10:00
InfiniteTF
fe6afca3c2 Fix scene-card jumping (#764) 2020-08-28 16:37:12 +10:00
InfiniteTF
fef16d7e09 Fix various console errors and graphql loading issues (#760)
* Refactor listhook to resolve loading issues
* Fix graphql loading race conditions
* Various console spam
* Fix scene card overlay hierarchy
* Fix modal and manual borders
2020-08-28 16:33:19 +10:00
WithoutPants
9a84726128 Fix xpath comment element parsing (#759) 2020-08-23 17:39:15 +10:00
peolic
165a0d4398 MovieScrapeDialog tweaks (#753)
* MovieScrapeDialog: use TextArea for Synopsis
* MovieScrapeDialog: add Date placeholder
2020-08-23 13:14:16 +10:00
InfiniteTF
ffa1fbda7f Fix infinite load issue (#756)
* Remove subcomponents to resolve infinite load issue
2020-08-23 12:54:52 +10:00
WithoutPants
1fd3fcc6a8 Show and allow creation of unknown performers/tags/studios/movies from scraper dialog (#741)
* Fix toast container z-index
* Make scrape operations network only
* Add CollapseButton component
2020-08-22 18:12:39 +10:00
WithoutPants
2cdec6bde1 Update changelog for #745 2020-08-21 17:58:20 +10:00
JoeSmithStarkers
85aa1d8790 Replace os.Rename with util.SafeMove to allow cross device moving to not fail. (#745)
Fixed annoyingly noisy transcoding progress log messages.
Fixed minor minor issue with directories than are named "blah.mp4" being detected as files to be scanned.
2020-08-21 17:57:07 +10:00
WithoutPants
6a3588e4e0 Fix compiler version in cross-compile.sh 2020-08-20 11:47:27 +10:00
WithoutPants
f7a45f9d10 Cross compile for armv7/armv8, raise raspi variant to armv6 (only) (#737)
* Add arm cross compile changes from #602
* Bump pi arm version
* Prevent caching of yarn key
* Add dockerignore for build dockerfile
2020-08-20 09:27:54 +10:00
InfiniteTF
ecf745162f Upgrade doublestar to v2.0.1 (#742) 2020-08-17 12:06:40 +10:00
JoeSmithStarkers
ecc42e4e24 Preview generation fallback (#725)
* Added preview generation fallback feature.
When a preview generation fails (often for wmv/avi files), the new code tries with less stricted (no xerror) and more time consuming options (slow+fast seek).
Fix a minor issue when stash downloads ffmpeg/ffprobe, but doesn't re-detect their paths.
2020-08-17 09:21:58 +10:00
WithoutPants
44c32a91d3 UI improvements (#726)
* Use rating stars in movie
* Make multiset button more obvious
* Hide select all/none buttons where not selectable
* Make add the default multi-set mode
2020-08-14 09:41:01 +10:00
WithoutPants
a39666467e Fix import performers/movies/studios with no image (#732) 2020-08-14 09:40:25 +10:00
woodgen
e3ea3ea85e scraper/mapped: Add feetToCm post process. (#711)
This patch adds a feetToCm post process that converts imperial feet and
inches to centimeters.
2020-08-12 11:17:43 +10:00
WithoutPants
551c13bbc8 Update changelog 2020-08-12 09:21:39 +10:00
WithoutPants
e16118f551 Clear image (#722)
* Allow clearing of tag images
* Allow clearing of studio images
* Allow clearing of performer images
* Allow clearing of movie images
* Add filtering for missing images
2020-08-12 09:19:27 +10:00
WithoutPants
c0afd31b1c Make scene movie number freely editable (#721) 2020-08-12 08:45:48 +10:00
peolic
39bc8b7351 update scraping docs (#720) 2020-08-11 08:44:57 +10:00
woodgen
4045ddf3e9 Implement scraping movies by URL (#709)
* api/urlbuilders/movie: Auto format.

* graphql+pkg+ui: Implement scraping movies by URL.

This patch implements the missing required boilerplate for scraping
movies by URL, using performers and scenes as a reference.

Although this patch contains a big chunck of ground work for enabling
scraping movies by fragment, the feature would require additional
changes to be completely implemented and was not tested.

* graphql+pkg+ui: Scrape movie studio.

Extends and corrects the movie model for the ability to store and
dereference studio IDs with received studio string from the scraper.
This was done with Scenes as a reference. For simplicity the duplication
of having `ScrapedMovieStudio` and `ScrapedSceneStudio` was kept, which
should probably be refactored to be the same type in the model in the
future.

* ui/movies: Add movie scrape dialog.

Adds possibility to update existing movie entries with the URL scraper.

For this the MovieScrapeDialog.tsx was implemented with Performers and
Scenes as a reference. In addition DurationUtils needs to be called one
time for converting seconds from the model to the string that is
displayed in the component. This seemed the least intrusive to me as it
kept a ScrapeResult<string> type compatible with ScrapedInputGroupRow.
2020-08-10 15:34:15 +10:00
WithoutPants
7158e83b75 Add JSON scrape support (#717)
* Add support for scene fragment scrape in xpath
2020-08-10 14:21:50 +10:00
WithoutPants
470a2b5833 Fix sprite vtt panic (#718) 2020-08-10 09:20:04 +10:00
WithoutPants
711fadcffd Don't play after failover (#716) 2020-08-10 09:19:37 +10:00
WithoutPants
634b892df1 Fix typo 2020-08-09 13:48:47 +10:00
WithoutPants
0ffefa6e16 Add plugin tasks (#651) 2020-08-08 12:05:35 +10:00
WithoutPants
0874852fa8 Improve oshash collision detection and logging (#713)
* Log colliding file when setting hash
* Check for existing using both hashes
2020-08-08 11:22:25 +10:00
WithoutPants
5992ff8706 Add oshash support (#667) 2020-08-06 11:21:14 +10:00
friendlycrab
f59ad0ca2b Allow adding performer & studio from scenes page (#663)
* Allow adding performer & studio from scenes page

Adds "create" options for performer and studio select in SceneEditPanel.
Adds new FilterSelectComponent to reduce duplicate logic in selects.

Make invalidateQueries case insensitive so we can pass upper-case query
names that also work with refetchQueries
2020-08-05 15:38:11 +10:00
WithoutPants
f5c3cafa63 Fix markers not autoplaying (#698)
* Fix marker seeking
* Autostart when loading from marker
2020-08-05 09:48:23 +10:00
WithoutPants
b166abfa7b Fix scraping error (#704) 2020-08-04 20:43:56 +10:00
bnkai
4373f9bf01 Add cdp support for xpath scrapers (#625)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-08-04 10:42:40 +10:00
Nic Patterson
1b4a9eed36 add non-binary option for gender (#695) 2020-08-01 16:26:00 +10:00
WithoutPants
b465c36fc7 Fix tag delete (#690)
* Fix tag list delete button not working
* Fix tags not refreshed when created/deleted
2020-07-29 11:51:20 +10:00
WithoutPants
278be33618 Fix marker seeking (#689) 2020-07-29 11:50:58 +10:00
WithoutPants
c327a98ecb Fix missing video player poster (#686) 2020-07-24 10:45:48 +10:00
InfiniteTF
116f61b6bf Fix potential sprite generation segfault (#685) 2020-07-24 09:20:34 +10:00
WithoutPants
a2341f0819 Allow customisation of preview generation (#673)
* Add generate-specific options
* Include no-cache in preview response
2020-07-23 12:51:35 +10:00
WithoutPants
37be146a9d Transcode stream refactor (#609)
* Remove forceMkv and forceHEVC
* Add HLS support and refactor
* Add new streaming endpoints
2020-07-23 11:56:08 +10:00
InfiniteTF
274d84ce93 Fix performer card name truncation (#682) 2020-07-22 11:21:14 +10:00
WithoutPants
2b9215702e Refactor xpath scraper code. Add fixed and map (#616)
* Refactor xpath scraper code
* Make post-process a list
* Add map post-process action
* Add fixed xpath values
* Refactor scrapers into cache
* Refactor into mapped config
* Trim test html
2020-07-21 14:06:25 +10:00
InfiniteTF
f4ae9b09a6 Fix FormattedDate timezone bug (#681) 2020-07-21 13:04:56 +10:00
WithoutPants
c1be600b01 Don't show dialog when setting front movie image (#678) 2020-07-21 08:30:26 +10:00
WithoutPants
c104c6d075 Generate content for specific scenes (#672)
* Add UI dialog for scene(s)
* Move preview preset to config
2020-07-19 11:59:18 +10:00
WithoutPants
8e4945325d Fix badly sized performer container (#670) 2020-07-19 11:10:52 +10:00
WithoutPants
8076405965 Support random performer sort (#666) 2020-07-14 08:51:39 +10:00
bnkai
ec2bcc7a74 Scan for files with ALLCAPS extensions (#650) 2020-07-11 17:22:36 +10:00
bnkai
56210cf456 Use referer on xpath getImage, apply printHTML to subscraper also (#661) 2020-07-10 08:42:06 +10:00
WithoutPants
e9141b5dfc Fix tag query performance problems (#657)
* Fix sql tracing
* Disable query by marker count
* Disable unit test
2020-07-09 08:42:07 +10:00
WithoutPants
f5784246ce Add website link to readme 2020-07-08 13:05:55 +10:00
WithoutPants
244ae54f3f Add grid view, image to tag (#641)
* Add grid view for tags
* Add tag page
* Import/export tags
* Add tag name uniqueness checks
* Fix styling on missing marker previews
* Add trace loglevel
* Add SQL trace
* Add filter options for tags
* Add tag sort by options
* Add tag page keyboard shortcuts
2020-07-07 10:35:43 +10:00
WithoutPants
54430dbc11 Fix travis not validating UI (#653)
* Fix travis not validating UI
* Fix lint errors
2020-07-06 08:58:35 +10:00
WithoutPants
f1c544affb Scrape dialog (#644)
* Fix performer page button spacing
* Improve scene URL scrape button styling
2020-07-02 10:10:29 +10:00
WithoutPants
bfeb7d1824 Add keyboard shortcuts (#637)
* Add documentation
* Fix manual styling
* Add dialog for setting Movie images
* Mention manual in README
2020-07-02 08:45:14 +10:00
WithoutPants
3157d748bc Scene selection improvements (#642)
* Select subsequent scenes on card click
2020-07-01 11:50:43 +10:00
WithoutPants
d516947af2 Strip debug symbols from release builds (#636)
* Add release target that strips debug symbols
* Make cross compile use make
2020-06-29 14:44:21 +10:00
WithoutPants
56b9c081ec [RFC] Fix query toolbar, performer/studio/movie page styling improvements (#632)
* Fix query toolbar
* Fix performer page styling
* Improve studio page styling
* Improve movie page styling
2020-06-26 07:49:00 +10:00
WithoutPants
883a0e785a Fix UI not showing version (#631) 2020-06-24 15:46:37 +10:00
WithoutPants
455e16ece9 Support deleting multiple scenes (#630)
* Improve layout and add buttons
* Move functionality into ListFilter
* Make modal style dark
* Convert scene options into edit scenes dialog
* Add delete scenes dialog
* Clear selected ids on delete
* Refetch after update/delete
* Use DeleteScenesDialog in Scene page
* Show scene check boxes in small screens
* Change default multi-set mode to set
2020-06-23 10:40:11 +10:00
WithoutPants
83f8bc0832 In-app help manual (#628) 2020-06-23 10:15:02 +10:00
WithoutPants
534d47500b Integrate build version in UI (#629) 2020-06-23 09:51:57 +10:00
WithoutPants
aa57b75243 Add changelog entry for #618 2020-06-23 09:21:18 +10:00
WithoutPants
7a74658a73 Move image blobs into separate tables (#618)
* Scene cover fallback to database
* Fix panic if studio not found
* Fix movie studio not being imported/exported
2020-06-23 09:19:19 +10:00
bnkai
f8048dc27c Increase xpath redirects, use cookies (#624) 2020-06-22 12:18:02 +10:00
WithoutPants
77a5b1d814 Add custom served folders (#620) 2020-06-21 22:25:13 +10:00
WithoutPants
d3ababf0a1 Gallery list improvement (#622)
* Add grid view to galleries
* Show scene in gallery card
* Add is missing scene gallery filter
* Don't store galleries with no images
2020-06-21 21:43:57 +10:00
WithoutPants
e50f1d01be Fix scene delete (#621) 2020-06-19 23:09:47 +10:00
WithoutPants
f60ce01fec Render pagination at top as well (#614) 2020-06-18 11:10:00 +10:00
bnkai
9d0522f62d Add "split" xpath in post-processing , newlines in replace support (#579) 2020-06-18 10:47:10 +10:00
WithoutPants
3fbb4cdc32 [RFC] Revamp scene page (#562)
* Don't show scrubber on small height device
* Move operations into ellipsis menu
* Hide scrubber in mobile devices
* Add delete scene to operations drop down
* Remove redundant panels
* Fix video height on smaller devices
* Adjust player aspect ratio for portrait videos
2020-06-18 10:26:05 +10:00
WithoutPants
1ca5f357e9 Remove v2 UI (#613) 2020-06-17 11:02:47 +10:00
bnkai
a7ac02fb50 freeones fixes (#615) 2020-06-17 11:02:06 +10:00
bnkai
f40e234748 Apply xpath parseDate after subScraper (#606) 2020-06-15 21:38:59 +10:00
WithoutPants
96e6e16507 Parent studios (#595)
* Refactor getMultiCriterionClause
Co-authored-by: Anon247 <61889302+Anon247@users.noreply.github.com>
2020-06-15 21:34:39 +10:00
WithoutPants
a77fea5724 Rating stars (#567)
* Add ratings stars control. Add to scene details
* Replace rating with stars on edit panel
* Add changelog entry
2020-06-12 09:11:39 +10:00
WithoutPants
d8ce137086 Reload scrapers button (#592)
* Add reload scraper option to performer details
* Add scraper reload to scene edit page
* Show scene scraper menu when no queryable scrapers
* Add 0.3 changelog
2020-06-10 13:43:17 +10:00
WithoutPants
32011aa86f Merge master to develop for 0.2.1 2020-06-10 11:51:31 +10:00
WithoutPants
9f335b8ea2 Add 0.2.1 changelog (#607) 2020-06-10 10:53:49 +10:00
WithoutPants
d168df1ad6 Fix max loop duration not working (#604) 2020-06-10 10:15:02 +10:00
peolic
ef8cba804f Fix sanitizeURL (#599) 2020-06-10 10:13:57 +10:00
WithoutPants
bd5ee9ba6b Merge pull request #597 from stashapp/develop
Merge 0.2 to master
2020-06-06 14:59:07 +10:00
WithoutPants
caef648659 Update changelog for 0.2 release (#582) 2020-06-06 14:38:19 +10:00
bnkai
f255104951 Upgrade bmatcuk/doublestar to 1.3.1 (#586) 2020-06-03 11:46:12 +10:00
InfiniteTF
dcf7233e38 Add polyfill for number unit formatting (#589) 2020-06-02 10:19:27 +10:00
bnkai
b89956de25 freeones scraper fixes/tweaking (#584) 2020-06-02 09:45:37 +10:00
InfiniteTF
d1e6858c11 Remove German language option (#590) 2020-06-02 09:37:13 +10:00
bnkai
dc5efb9e31 Unit testing for performers,studios,movies FindByName/s (#581) 2020-05-27 10:48:45 +10:00
WithoutPants
1110e9c311 Fix date rendering for missing date values (#580)
* Fix date rendering when missing date value
* Move scene studio overlay within scene card
2020-05-27 09:34:46 +10:00
InfiniteTF
4ec6d62e01 Selectable wall preview type (#510)
* Add optional image preview generation
* Add setting for video preview encoding preset
2020-05-27 09:33:49 +10:00
InfiniteTF
197918d13c Localize dates and numbers (#574) 2020-05-25 15:49:13 +10:00
bnkai
ccd75731b7 Change scrape matching (studio, movies, tag, performers) to case insensitive (#556)
* Change scrape matching (studio, movies, tag, performers) to case insensitive
* * fix collate order
* * make filename parser findbyname calls case insensitive
* * add unit testing for Tags GetFindbyName/s
2020-05-24 16:19:22 +10:00
InfiniteTF
32fce9ac6f Speed up tag count queries (#570)
* Speed up tag count queries
* Add test for marker CountByTagID

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-05-24 16:18:02 +10:00
WithoutPants
95a6d3ea2f Fix sceneTags filter selection (#564) 2020-05-20 22:47:16 +10:00
WithoutPants
1a31ca3e33 Set performers/tags/studios in parser (#563) 2020-05-20 22:47:01 +10:00
InfiniteTF
5c68c70216 Encode pasted images to jpegs (#560) 2020-05-20 22:46:38 +10:00
WithoutPants
ec420df871 Add debug logging for xpath scraping (#555)
* Add debug logging for xpath scraping
* Add logging for processing scene members
2020-05-20 22:46:00 +10:00
WithoutPants
ad374dc7f5 Include stash version in bug report template 2020-05-20 14:41:02 +10:00
WithoutPants
05488d59c3 Find scrapers in subdirectories (#554) 2020-05-19 08:44:33 +10:00
InfiniteTF
5450fe8e9a Changelog (#531) 2020-05-19 08:37:56 +10:00
bnkai
0fc57ce1e0 Fix xpath comments text (#550) 2020-05-18 12:26:20 +10:00
WithoutPants
46746e6848 Fix redirect loops in login, migrate and setup pages (#549)
* Fix redirect loop when setup and migrate required
* Fix redirect loop between setup and login
2020-05-18 08:55:01 +10:00
WithoutPants
215c4e3bde Change builtin freeones scraper to community yml (#542) 2020-05-15 20:10:20 +10:00
WithoutPants
50530ae85d Fix setting release notes for development build 2020-05-15 16:52:03 +10:00
WithoutPants
7fd9428cbb Fix stash directory with spaces (#541) 2020-05-15 09:12:17 +10:00
WithoutPants
93d6cc43c5 Add details to is missing filter (#533) 2020-05-15 09:11:28 +10:00
bnkai
d74a303c00 Fix 0 undefined library size on empty db (#535) 2020-05-14 10:44:13 +10:00
WithoutPants
fde02425ab Make auto tagger matching more flexible (#534) 2020-05-13 17:32:39 +10:00
WithoutPants
41c6d9e681 Revert preview generation change 2020-05-13 17:23:23 +10:00
bnkai
4829b4b214 Fix edge case preview generation, tweak preview generation preset (#528) 2020-05-11 17:24:52 +10:00
bnkai
bd45daacf3 Add a cache for gallery thumbnails (#496) 2020-05-11 17:20:08 +10:00
InfiniteTF
8ba76783b0 Query optimizations (#478)
* Remove slow and largely pointless groupbys
* Change scene.query to use querybuilder
2020-05-11 15:19:11 +10:00
InfiniteTF
328db57d6c Overhaul look and feel of folder select (#527) 2020-05-09 13:08:00 +10:00
InfiniteTF
e9c68897d7 Add is-missing tags filter (#526) 2020-05-09 12:21:08 +10:00
InfiniteTF
0d9dcdd1e9 Add title to flags, and alias for Slovakia (#519) 2020-05-09 10:38:11 +10:00
InfiniteTF
df2d2c2d09 Upgrade javascript libraries (#516)
* Bump react-bootstrap
* Bump library versions and clean up hooks
* Bump intl libraries
* Fix image pasting
2020-05-08 12:06:07 +10:00
WithoutPants
99f88b8d73 Querybuilder integration tests (#513)
* Vet fixes
* Change low resolution to < 480
2020-05-04 17:02:49 +10:00
bnkai
0b50e83dbf freeones scraper tweaks (#509) 2020-05-04 14:11:49 +10:00
InfiniteTF
a4edd21072 Add flags for performer countries (#508) 2020-05-03 18:15:24 +10:00
InfiniteTF
2c85aeedf4 Set movies studioId on create mutation (#511) 2020-05-03 08:54:02 +10:00
bnkai
0e01177440 Merge pull request #515 from stashapp/revert-514-travis_body
Revert "travis fix"
2020-05-03 00:23:04 +03:00
bnkai
db716d2e17 Revert "travis fix" 2020-05-03 00:22:11 +03:00
bnkai
5370870598 Merge pull request #514 from bnkai/travis_body
Travis release date fix
2020-05-03 00:03:00 +03:00
bnkai
461127c8c4 travis fix 2020-05-02 23:28:35 +03:00
WithoutPants
2166caf322 Update xpath dependency (#507) 2020-04-30 08:32:33 +10:00
WithoutPants
3d22d5a742 Refactor build (#493)
* Add lint/format checks to build
* Make travis get full repo to get tags
* Run packr2 once in cross-compile
* Fix quotes in package.json
* Fix linting issues
* Formatting
* Fix vet issue
* Fix go lint issues
* Show start of each platform compilation
* Add validate target
* Set gitattributes for go fmt and mod vendor
* Fix tag name
* Add fmt-ui target
2020-04-29 12:13:08 +10:00
InfiniteTF
a0306bfbd2 Remove hotkeys and fix tag selection (#505)
* Remove broken scene player hotkeys
* Disable closing tag select menu after a select
2020-04-29 09:55:34 +10:00
bnkai
52a1059380 Make image extension check in zip files case insensitive (#501) 2020-04-29 09:24:01 +10:00
FleetingOrchard
1513617f95 Add index/total count to end of pagination buttons (#490) 2020-04-29 08:28:57 +10:00
bnkai
f933a28e5a Fix yarn extract error due to "library size" (#494) 2020-04-26 16:49:55 +10:00
WithoutPants
309f7047b0 Add parser support for 3-letter month (#500) 2020-04-26 16:29:53 +10:00
bnkai
5e84c0922d Add random male performer image (#491)
* Add random male performer image during performer creation if gender is male
2020-04-25 09:54:42 +10:00
WithoutPants
5923917e6c Clean missing galleries (#489)
* Clean missing galleries
* Refactor matchFile
2020-04-25 09:32:55 +10:00
FleetingOrchard
8a4d853a5d Add "reshuffle button" when sortby is random (#497) 2020-04-24 14:30:41 +10:00
bnkai
29336d1ee0 Move image with cover.jpg in name to first place in Galleries (#477) 2020-04-24 12:53:18 +10:00
bnkai
9b1518beae Export performance optimization (#475)
* recreate metadata path if needed, before exporting data
2020-04-24 12:52:21 +10:00
WithoutPants
ba09bfa64a Include scene o-counter in import/export (#488)
* Include o-counter in import/export
* Fix scene card o-counter display
2020-04-23 09:14:58 +10:00
WithoutPants
eee7adfb85 Add Studio to movie and fix movie schema (#458)
* Add movie migration
* Update server and UI code for type changes
* Add studio to movies
* Movie blobs to end
* Document movie duration
* Add filtering on movie studio
2020-04-22 11:22:14 +10:00
InfiniteTF
f21e04dcbc Fix navbar height (#481) 2020-04-21 09:30:15 +10:00
WithoutPants
7e747fd8a9 Restore movie/studio data on edit cancel (#476) 2020-04-20 12:46:55 +10:00
WithoutPants
359e80f364 Don't error in IsStreamable resolver (#482) 2020-04-20 12:42:56 +10:00
InfiniteTF
2a3c9742cc Add slim endpoints for entities to speed up filters (#460)
* Move performers image column to end of table
* Remove redundant index
2020-04-19 12:03:51 +10:00
f1delio
7ef0000744 Update README.md (#474)
Added Customization section with links toward Custom CSS snippets, CSS Tweaks, and Plex Theme.
2020-04-18 09:47:40 +10:00
bnkai
e2f66a3492 Fix editing movie name (#470) 2020-04-15 08:36:16 +10:00
InfiniteTF
7cd682e59c Fix log population (#459) 2020-04-13 11:49:23 +10:00
InfiniteTF
a5a264dcc2 Fix tag creation (#461) 2020-04-13 11:45:45 +10:00
bnkai
424e62a226 Fix studio edit name (#465) 2020-04-13 11:42:02 +10:00
WithoutPants
849a5261a3 Include gender in performer scraper results (#448)
* Fix scraper gender
* Set scraped gender in the UI
* Match gender on enum or case insensitive string
2020-04-11 13:26:53 +10:00
WithoutPants
6764c1f545 Performer and Movie UI fixes and improvements (#447)
* Improve gender display
* Sanitise performer URLs
* Refactor editable text into separate module
* Make movie duration DurationInput
* Fix clearing sometimes not firing onChange
* Set movie duration as string
* Fix TextUtil.fileSize
* Improve scene URL
2020-04-11 13:23:31 +10:00
WithoutPants
aef31c8b50 Don't redirect login to migrate page (#453) 2020-04-10 08:41:09 +10:00
WithoutPants
2ab45848a5 Prefer modified performer image over scraped one (#449) 2020-04-10 08:40:45 +10:00
WithoutPants
91d842ed47 Delete marker preview on marker change or delete (#446) 2020-04-10 08:39:41 +10:00
bnkai
d5617307f1 Add detection of container/video_codec/audio_codec compatibility for live file streaming or transcoding (#384)
* add forceMKV, forceHEVC config options
* drop audio stream instead of trying to transcode for ffmpeg unsupported/unknown audio codecs
2020-04-10 08:38:34 +10:00
Anon247
dc37a3045b Added various missing filters to performer page (#438) 2020-04-08 14:21:05 +10:00
WithoutPants
15e7756d33 Replace basic auth with cookie authentication (#440)
* Add logout functionality and button
* Make session age configurable
2020-04-08 12:51:12 +10:00
WithoutPants
b3e8d1e8dd Add scene rating to scene filename parser (#432)
* Fix scene parser display issues in 2.5
* Dropdown menu presentation improvements
* Fix refresh on parser apply
* Ignore line endings on scss files
2020-04-05 07:59:57 +10:00
bnkai
18dc5e85fa Don't run travis for the latest_develop tag (#439) 2020-04-04 09:27:49 +11:00
bnkai
8a6fff61ae Enable sorting for galleries (#437) 2020-04-03 14:40:37 +11:00
bnkai
e58c311ddd Add library size to main stats page (#427) 2020-04-03 13:44:17 +11:00
InfiniteTF
66cb7f4928 Update prettier to v2.0.1 and enable for SCSS (#420) 2020-04-03 10:29:33 +11:00
Anon247
ad7bfb8dbf Fix to filter on movies from performer filter to movie filter (#435) 2020-04-03 10:28:15 +11:00
InfiniteTF
0f622c84f4 Add SVG studio image support, and studio image caching (#418)
* Support SVGs for studio images and add ETAGs
* Add SVG to studio image input
* Update content sniffing
2020-04-03 09:11:48 +11:00
InfiniteTF
aee9df966b Cut over to v2.5 UI (#433)
* Cut over to v2.5 UI
* Use node 12 in travis
* Remove unnecessary `nvm use`
* Update docker file
2020-04-03 08:46:23 +11:00
ueaslsef
10b6d4b579 [Feature] Add image count to gallery list (#429)
* Add imagecount to gallery list
* Port to 2.5
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-04-02 08:27:33 +11:00
WithoutPants
82201e23e0 Make ethnicity freetext and fix freeones ethnicity panic (#431)
* Make ethnicity free text

* Fix panic in freeones scraper for other ethnicity
2020-04-02 08:25:39 +11:00
Anon247
0bbb2bd1d0 Fix to allow scene to be removed when attached to a movie (#421) 2020-04-01 12:07:43 +11:00
InfiniteTF
2a8e5d5b9b UI fixes (#419) 2020-04-01 11:08:01 +11:00
dependabot[bot]
777cd96759 Bump acorn from 5.7.3 to 5.7.4 in /ui/v2 (#399)
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-04-01 09:57:38 +11:00
hiddenpants255
494b794228 Add gender support for performer (#371)
Co-authored-by: HiddenPants255 <>
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-04-01 09:36:38 +11:00
WithoutPants
d886012d74 Add modes for performer/tag for bulk scene editing (#412) 2020-03-23 08:16:11 +11:00
bnkai
acb7260824 Backup database if a migration is needed (#415)
* Confirm before migrating database

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-03-23 08:07:15 +11:00
WithoutPants
abf2b49803 Configurable scraper user agent string (#409)
* Add debug scrape option.

Co-authored-by: HiddenPants255 <>
2020-03-21 08:55:15 +11:00
WithoutPants
ff495361d9 Port Movies UI to v2.5 (#397)
* Ignore generated-graphql.tsx in 2.5
* Make movie name mandatory
* Port #395 fix to v2.5
* Differentiate front/back image browse buttons
* Move URL, Synopsis to separate rows
* Fix unknown query params crashing UI
2020-03-21 08:21:49 +11:00
WithoutPants
5aa6dec8dc Fix random sort not changing seed (#411) 2020-03-21 08:07:46 +11:00
bnkai
9dacad70a1 Autoassociate galleries to scenes when scanning (#405) 2020-03-19 12:36:00 +11:00
WithoutPants
1a6374fae9 Fix error when viewing scenes related to objects with illegal characters in name (#395)
* Fix gitattributes for v2.5
2020-03-14 08:06:55 +11:00
WithoutPants
6f5f3112e1 Fix marker time setting in v2.5 UI (#396) 2020-03-13 19:58:13 +11:00
WithoutPants
3de6955a9e Generate cover image (#376)
* Make mutating metadata ops mutation
* Implement scene generate screenshot
* Remove fetch policy on metadata mutations
* Port UI changes to v2.5
* Set generated image in database
2020-03-12 08:34:04 +11:00
WithoutPants
34d829338d Add image scraping support (#370)
* Add sub-scraper functionality
* Add scraping of performer image
* Add scene cover image scraping
* Port UI changes to v2.5
* Fix v2.5 dialog suggest color
* Don't convert eol of UI to support pretty
2020-03-11 11:41:55 +11:00
caustico
5fb8bbf768 Movies Section (#338)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-03-10 14:28:15 +11:00
InfiniteTF
b3fab3cfef Make mobile menu behavior more consistent, and stats styles responsive (#391) 2020-03-08 12:55:42 +11:00
WithoutPants
cb594f0e43 Fix various issues with v2.5 UI (#390)
* Fix navbar collapse breakpoint
* Fix list filter colors and height
* Make styling similar to v2
* Fix scene card zoom and orientation
* Keep p tag even without details
* Fix custom css
* Default settings tab to tasks
* Fix flickering progress bar. Fix percentage.
* Fix unsetting studio
* Fix scene gallery select
* Don't hide edit on small devices
* Fix log dropdown style
* Use monospace for custom css input
2020-03-06 20:02:02 +11:00
WithoutPants
088ddc9df4 Add new v2.5 UI (#357) 2020-03-05 10:15:02 +11:00
Infinite
c875515730 Fix localForage infinite loop, set base font-size to 14px, and tweak
styles
2020-03-04 09:21:30 +01:00
InfiniteTF
c8a56aea40 Update browser cache when images are updated (#389) 2020-03-03 10:33:41 +11:00
InfiniteTF
41f7a46ac1 Fix performer height filter error (#388)
* Fix performer height filter error
* Make all performer columns qualified

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-03-03 10:30:29 +11:00
InfiniteTF
80a8d2de97 Use parameter binding for all queries (#387) 2020-03-03 09:18:14 +11:00
Infinite
2fac50ba3e Formatting and list hook fix 2020-03-01 21:30:40 +01:00
Infinite
85936edb9c Fix list filter default values and error state 2020-03-01 21:04:38 +01:00
Infinite
429df84479 Update stats page #366 2020-03-01 21:04:38 +01:00
Infinite
93c7ad7559 Make performer image position top #358 2020-03-01 21:04:38 +01:00
Infinite
5b6a3a7732 Fix scene edit page for smaller screens 2020-03-01 21:04:38 +01:00
Infinite
dba4b350a0 Fix scene list view 2020-03-01 21:04:38 +01:00
Infinite
ac4f4972b6 Correct scene card truncation 2020-03-01 21:04:38 +01:00
Infinite
8672c4437e Navbar key 2020-03-01 21:04:38 +01:00
Infinite
6d71663f99 Fix whitespace 2020-03-01 21:04:37 +01:00
Infinite
195158db8b Fix performer scrape menu layout 2020-03-01 21:04:37 +01:00
Infinite
857b2cc78d Lint + prettier 2020-03-01 21:04:37 +01:00
Infinite
960d5c7000 Switch to hamburger menu for phones 2020-03-01 21:04:37 +01:00
Infinite
49354d571b Small fixes 2020-03-01 21:04:37 +01:00
Infinite
6f07380628 Fix list hook state 2020-03-01 21:04:37 +01:00
Infinite
151d69632e Refactor list hook filter storag 2020-03-01 21:04:37 +01:00
Infinite
6df25a2c5e Fix toast styles 2020-03-01 21:04:37 +01:00
Infinite
750759e4bf Prettier 2020-03-01 21:04:37 +01:00
Infinite
8fe6eb0d77 Update jwplayer 2020-03-01 21:04:37 +01:00
Infinite
cdadb66d85 Remove or exempt all uses of 'any
* Refactored LocalForage
* Refactored SceneFilenameParser
2020-03-01 21:04:37 +01:00
Infinite
a60c89ceb1 Fix localForage initialization when stored config is undefined 2020-03-01 21:04:37 +01:00
Infinite
a43cae43c0 Prettier 2020-03-01 21:04:37 +01:00
Infinite
a7df23c54d Fix 2020-03-01 21:04:37 +01:00
Infinite
3a0420b79e Change i18n to just use single language setting 2020-03-01 21:04:37 +01:00
Infinite
e6d9d385a7 Add O-counter (#334) 2020-03-01 21:04:37 +01:00
Infinite
f23247d9c8 Delete swp 2020-03-01 21:04:37 +01:00
Infinite
a5036ebe5f Prevent flashing when filter is updated 2020-03-01 21:04:37 +01:00
Infinite
4e5c65f90d Maintain filter parameters in session (#326) 2020-03-01 21:04:37 +01:00
Infinite
690596aa34 Refactor list filter query functionality 2020-03-01 21:04:37 +01:00
Infinite
0fdde7726b i18n 2020-03-01 21:04:37 +01:00
Infinite
fb5a49e58c Add Xpath post processing and performer name query (#333) 2020-03-01 21:04:36 +01:00
Infinite
3bbcc65521 Accept random seed from UI for random sorting (#328) 2020-03-01 21:04:36 +01:00
Infinite
79f69b4d61 Allow path separator in scene filename parser pattern (#327) 2020-03-01 21:04:36 +01:00
Infinite
c33639d824 Rename component folders, and prune styles 2020-03-01 21:04:36 +01:00
Infinite
fd560c2147 Switch back to CRA 2020-03-01 21:04:36 +01:00
Infinite
49a6076500 Style changes 2020-03-01 21:04:36 +01:00
Infinite
4a32f90382 Styles 2020-03-01 21:04:36 +01:00
Infinite
c1ce6d539d Prettier 2020-03-01 21:04:35 +01:00
Infinite
3f9f32c356 Responsive styles for portrait orientation phones 2020-03-01 21:04:35 +01:00
Infinite
1ccf8d1586 Changes 2020-03-01 21:04:35 +01:00
Infinite
247ad0a470 Style fixes 2020-03-01 21:04:35 +01:00
Infinite
ac3d03715f Styling 2020-03-01 21:04:35 +01:00
Infinite
3fa3f61d93 Styling 2020-03-01 21:04:35 +01:00
Infinite
c2544fee98 Prettier 2020-03-01 21:04:35 +01:00
Infinite
e1a1914d16 Fixes 2020-03-01 21:04:35 +01:00
Infinite
d1ffc0be0a Optimization 2020-03-01 21:04:35 +01:00
Infinite
1928f09dcf Eject create-react-app 2020-03-01 21:04:35 +01:00
Infinite
95bedc77fe Styling 2020-03-01 21:04:34 +01:00
Infinite
71251ee6a8 Add useful links to about page (#322) 2020-03-01 21:04:34 +01:00
Infinite
498491e82d Fix react warnings (#317) 2020-03-01 21:04:34 +01:00
Infinite
71dd939806 Add scene duration filter (#313) 2020-03-01 21:04:34 +01:00
Infinite
dda36f6b09 Add check version functionality (#296) 2020-03-01 21:04:34 +01:00
Infinite
63cc97d199 Add scenes tab to performer page (#280) 2020-03-01 21:04:33 +01:00
Infinite
dcfd445040 Library updates 2020-03-01 21:04:33 +01:00
Infinite
111d5dd7c5 Fixes 2020-03-01 21:04:33 +01:00
Infinite
244c8ff234 Prettier 2020-03-01 21:04:32 +01:00
Infinite
9827647122 Linting update 2020-03-01 21:04:32 +01:00
Infinite
c83e0898f9 Linting config 2020-03-01 21:04:32 +01:00
Infinite
c31205c47f Linting 2020-03-01 21:04:31 +01:00
Infinite
0cb61d14be Remove final react-router props 2020-03-01 21:04:31 +01:00
Infinite
0e717d6aae Fixes 2020-03-01 21:04:31 +01:00
Infinite
129dcecdef Blueprint removed 2020-03-01 21:04:31 +01:00
Infinite
e18e67b512 Toast 2020-03-01 21:04:31 +01:00
Infinite
cb1fa323e4 Changes 2020-03-01 21:04:30 +01:00
Infinite
f50cb45ca5 Changes 2020-03-01 21:04:30 +01:00
Infinite
4d44deff64 WIP 2020-03-01 21:04:30 +01:00
Infinite
716c33fc8e Use parameter binding for all queries 2020-02-29 16:18:59 +01:00
WithoutPants
97ab40595e Merge master back to develop 2020-02-25 12:43:42 +11:00
bnkai
6578cfb843 Fix version check for v0.1.0+ (#382)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2020-02-25 11:59:08 +11:00
WithoutPants
acc8a126d0 Fix travis tagged build (#379)
* Fix tagged master build on travis
* Remove branches section
2020-02-24 17:05:08 +11:00
WithoutPants
71ca30e8f4 Merge pull request #378 from stashapp/develop
Merge develop to master for 0.1 release
2020-02-24 15:52:45 +11:00
WithoutPants
691a8c23c0 Dockerfiles for production, develop and build (#364)
* Separate develop and production dockerfiles
* Add build docker file
* Fix curl http2 framing error
* updated MAINTAINER
* Add README for build dockerfile
* Remove stash user from docker files

Co-authored-by: Leopere <1068374+Leopere@users.noreply.github.com>
2020-02-24 11:40:56 +11:00
WithoutPants
8d57629af3 Fix scene selection not working (#373) 2020-02-19 07:56:46 +11:00
WithoutPants
bf49a23df8 Fix panic when version check times out (#374) 2020-02-19 07:56:24 +11:00
twotobinary
776727140f fix(middleware): set baseURL to external host if provided (#369) 2020-02-17 14:01:02 +11:00
WithoutPants
df3d3d24f5 Update stats page (#366)
* Remove notes. Make stats like old version
* Make font size responsive
2020-02-14 08:15:05 +11:00
Leopere
aa8bfaf407 [Feature] Adding Feature.md/BugFix.md Pull Request Template. (#343)
* Adding Feature.md Pull Request Template.

* Create BugFix.md Pull Request Tempalte

* Create CONTRIBUTING.md

* Disabled Librepay since we've decided properly on OpenCollective
2020-02-12 21:07:51 -05:00
bnkai
df890dca79 Fix database locked on image cover too big bug (#359) (#360) 2020-02-13 11:57:17 +11:00
WithoutPants
ae5aa6a6ec Change performer position to top (#358) 2020-02-11 08:29:06 +11:00
WithoutPants
c99ba68181 Fix URL update not reflected in list hook (#350)
* Fix URL update not reflected in list hook

* Maintain query prefs on tag click
2020-02-08 14:54:41 +11:00
WithoutPants
1d9913d268 Revert "Make performer image contain (#355)"
This reverts commit 40de2caa95.
2020-02-08 14:46:37 +11:00
WithoutPants
40de2caa95 Make performer image contain (#355) 2020-02-07 21:42:22 -05:00
WithoutPants
254d6978d0 Fix branch condition in travis 2020-02-07 06:57:44 +11:00
WithoutPants
3c1eeb3d47 Prepare for 0.1.0 release (#345)
* Tag develop builds as latest. Version in makefile
* Rename latest to latest_develop
* Update GetLatestVersion
* Separate master and develop releases
* Add release date back into development version
* Remove unused code
* Two minute limit per file to upload to transfer.sh
2020-02-07 06:39:08 +11:00
WithoutPants
f87117b0d6 Add O-counter (#334)
* Add backend support for o-counter

* Add o-counter buttons everywhere

* Put o-counter button right-aligned on tabs

* Add o-counter filter
2020-02-02 19:17:28 -05:00
ThUnD3r|Gr33n
066295f0c9 Fix to avoid creating generated folder inside data folder. (#335)
* Fix to avoid creating generated folder inside data folder. 

This Fix is to avoid that ```generated``` folder will be created inside the movie /video files forder which leads to see the generated clips of the movies in SCENES.

* Update docker-compose.yml

Added generated volume , removed transcoded as it wasn't needed.
All volumes remain with relative paths as suggested.

Co-authored-by: bnkai <48220860+bnkai@users.noreply.github.com>
2020-02-01 14:55:22 -05:00
WithoutPants
077b257316 Fix paging not working (#340)
* Don't set total count while loading

* Don't render pagination while loading
2020-02-01 05:20:13 -05:00
InfiniteTF
cd9c6e998e Add cache headers to static files and etags to performer images (#337) 2020-01-31 17:20:14 -05:00
InfiniteTF
6a6e8d8875 Change thumbnail default size and resize algorithm (#336)
* Change thumbnail resize algorithm and add size parameter

* Height -> Width

* Change default size from 100px to 200px

* Height -> width
2020-01-31 17:19:15 -05:00
WithoutPants
03c07a429d Add Xpath post processing and performer name query (#333)
* Extend xpath configuration. Support concatenation

* Add parseDate parsing option

* Add regex replacements

* Add xpath query performer by name

* Fix loading spinner on scrape performer

* Change ReplaceAll to Replace
2020-01-31 17:17:40 -05:00
WithoutPants
2632f9e971 Maintain filter parameters in session (#326)
* Maintain query parameters in local forage

* Keep items per page

* Refactor

* Fix warnings

* Add back required go module

* Fix loading spinner on sub-component listhook

* Add queries to localforage if not present
2020-01-31 17:16:04 -05:00
WithoutPants
78eb527ec4 Scraper fixes (#332)
* Fix panic on invalid xpath

* Add missing attrs to scraped performer fragment
2020-01-24 22:36:24 -05:00
WithoutPants
2dc1b42a0a Use --frozen-lockfile in travis calls to yarn install (#329)
* Add --freeze-lock to travis

* Update README
2020-01-24 22:35:55 -05:00
WithoutPants
3d3f8877de Accept random seed from UI for random sorting (#328) 2020-01-24 22:35:21 -05:00
WithoutPants
c83eb098bc Allow path separator in scene filename parser pattern (#327)
* Allow path in filename parser

* Fix helper text re escaping {} characters
2020-01-24 22:34:01 -05:00
bnkai
5a5f42f061 Refresh yarn.lock (#319)
* Refresh yarn.lock

* * recreate yarn.lock
2020-01-22 16:23:09 -05:00
bnkai
fed7311d9c Add timeout to neededGenerate function (#324)
* Add timeout to neededGenerate function

* * verbose and cosmetic fixes
2020-01-21 22:54:38 -05:00
Leopere
d2e67fdb31 Add LICENSE until we get all signers on the switch (#297)
* Add LICENSE until we get all signers on the switch

For now, all subsequent commits should be against the appropriate license.
2020-01-20 22:18:12 -05:00
bnkai
80027b91c0 Add useful links to about page (#322)
* Add useful links to about page

* * open about link urls in new tab/window
2020-01-20 22:11:18 -05:00
WithoutPants
66b4f6db4f Fix react warnings (#317)
* Remove unused imports

* Fix === warnings

* Remove unnecessary escape character

* Add alt text for images

* Add missing alt text

* Remove unused variable

* Change scrubber buttons from anchors

* Change folder select anchor to button

* Replace anchors with buttons

* Add missing useEffect dependencies

* Refactor filter debounce

* Throw error object

* Update dependencies

* Fix === warning
2020-01-16 13:36:38 -05:00
WithoutPants
cf96cae4c8 Add scene duration filter (#313)
* Add scene duration filter
2020-01-13 11:43:14 -05:00
WithoutPants
600862c0bb Autotag no longer overwrites studio (#312) 2020-01-09 13:40:23 -05:00
bnkai
87f0b667b5 Add check version functionality (#296)
* Add check version functionality
 * add backend support
 * add ui support
 * minor fixes
 * cosmetic fixes
 * workaround query refetch not working after network error
 * revert changes to Makefile after testing is complete
 * switch to Releases Github API endpoint, add latest Release URL to UI
 * latest version is only shown in UI when version is available and data is ready
 * resolve conflict , squash rebase
2020-01-07 17:21:23 -05:00
3119 changed files with 600827 additions and 209064 deletions

63
.dockerignore Normal file
View File

@@ -0,0 +1,63 @@
####
# Go
####
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Packr2 artifacts
**/*-packr.go
# GraphQL generated output
pkg/models/generated_*.go
ui/v2.5/src/core/generated-*.tsx
# packr generated files
*-packr.go
####
# Jetbrains
####
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
####
# Random
####
ui/v2.5/node_modules
ui/v2.5/build
*.db
stash
dist
docker

6
.gitattributes vendored
View File

@@ -1,2 +1,6 @@
go.mod text eol=lf
go.sum text eol=lf
go.sum text eol=lf
*.go text eol=lf
vendor/** -text
ui/v2.5/**/*.ts* text eol=lf
ui/v2.5/**/*.scss text eol=lf

2
.github/FUNDING.yml vendored
View File

@@ -6,7 +6,7 @@ open_collective: stashapp
# ko_fi: # Replace with a single Ko-fi username
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: StashApp
# liberapay: StashApp
# issuehunt: # Replace with a single IssueHunt username
# otechie: # Replace with a single Otechie username
# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -23,6 +23,8 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem please ensure that your screenshots are SFW or at least appropriately censored.
**Stash Version: (from Settings -> About):**
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]

18
.github/PULL_REQUEST_TEMPLATE/BugFix.md vendored Normal file
View File

@@ -0,0 +1,18 @@
---
name: Bug Fix
about: Add a bug fix this project!
title: "[Bug Fix] Short Form Title (50 chars or less.)"
labels: bug
assignees: 'WithoutPants, bnkai, Leopere'
---
<!-- Please make sure to read https://github.com/stashapp/stash/docs/CONTRIBUTING.md and check that you understand and have followed it as best as possible -->
<!-- Explain what your bugfix seeks to remedy in a short paragraph. -->
# Scope
<!-- Declare any issues by typing `fixes #1` or `closes #1` for example so that the automation can kick in when this is merged -->
## Closes/Fixes Issues
<!-- What have you tested specifically and what possible impacts/areas there are that may need retesting by others. -->
## Other testing QA Notes

View File

@@ -0,0 +1,17 @@
---
name: Feature Addition
about: Add a feature to this project!
title: "[Feature] Short Form Title (50 chars or less.)"
labels: enhancement
assignees: 'WithoutPants, bnkai, Leopere'
---
<!-- Please make sure to read https://github.com/stashapp/stash/docs/CONTRIBUTING.md and check that you understand and have followed it as best as possible
Explain what your feature does in a short paragraph. -->
# Scope
<!-- Declare any issues by typing `fixes #1` or `closes #1` for example so that the automation can kick in when this is merged -->
## Closes/Fixes Issues
<!-- What have you tested specifically and what possible impacts/areas there are that may need retesting by others. -->
## Other testing QA Notes

185
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,185 @@
name: Build
on:
push:
branches: [ develop, master ]
pull_request:
branches: [ develop ]
release:
types: [ published ]
env:
COMPILER_IMAGE: stashapp/compiler:4
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Checkout
run: git fetch --prune --unshallow --tags
- name: Pull compiler image
run: docker pull $COMPILER_IMAGE
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-node_modules
with:
path: ui/v2.5/node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('ui/v2.5/yarn.lock') }}
- name: Cache UI build
uses: actions/cache@v2
id: cache-ui
env:
cache-name: cache-ui
with:
path: ui/v2.5/build
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('ui/v2.5/yarn.lock', 'ui/v2.5/public/**', 'ui/v2.5/src/**', 'graphql/**/*.graphql') }}
- name: Cache go build
uses: actions/cache@v2
env:
cache-name: cache-go-cache
with:
path: .go-cache
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/go.sum') }}
- name: Start build container
run: |
mkdir -p .go-cache
docker run -d --name build --mount type=bind,source="$(pwd)",target=/stash,consistency=delegated --mount type=bind,source="$(pwd)/.go-cache",target=/root/.cache/go-build,consistency=delegated -w /stash $COMPILER_IMAGE tail -f /dev/null
- name: Pre-install
run: docker exec -t build /bin/bash -c "make pre-ui"
- name: Generate
run: docker exec -t build /bin/bash -c "make generate"
- name: Validate UI
# skip UI validation for pull requests if UI is unchanged
if: ${{ github.event_name != 'pull_request' || steps.cache-ui.outputs.cache-hit != 'true' }}
run: docker exec -t build /bin/bash -c "make ui-validate"
# TODO: Replace with `make validate` once `revive` is bundled in COMPILER_IMAGE
- name: Validate
run: docker exec -t build /bin/bash -c "make fmt-check vet it"
- name: Build UI
# skip UI build for pull requests if UI is unchanged (UI was cached)
# this means that the build version/time may be incorrect if the UI is
# not changed in a pull request
if: ${{ github.event_name != 'pull_request' || steps.cache-ui.outputs.cache-hit != 'true' }}
run: docker exec -t build /bin/bash -c "make ui-only"
- name: Compile for all supported platforms
run: |
docker exec -t build /bin/bash -c "make packr"
docker exec -t build /bin/bash -c "make cross-compile-windows"
docker exec -t build /bin/bash -c "make cross-compile-osx"
docker exec -t build /bin/bash -c "make cross-compile-linux"
docker exec -t build /bin/bash -c "make cross-compile-linux-arm64v8"
docker exec -t build /bin/bash -c "make cross-compile-linux-arm32v7"
docker exec -t build /bin/bash -c "make cross-compile-pi"
- name: Cleanup build container
run: docker rm -f -v build
- name: Generate checksums
run: |
git describe --tags --exclude latest_develop | tee CHECKSUMS_SHA1
sha1sum dist/stash-* | sed 's/dist\///g' | tee -a CHECKSUMS_SHA1
echo "STASH_VERSION=$(git describe --tags --exclude latest_develop)" >> $GITHUB_ENV
echo "RELEASE_DATE=$(date +'%Y-%m-%d %H:%M:%S %Z')" >> $GITHUB_ENV
- name: Upload Windows binary
# only upload binaries for pull requests
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
uses: actions/upload-artifact@v2
with:
name: stash-win.exe
path: dist/stash-win.exe
- name: Upload OSX binary
# only upload binaries for pull requests
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
uses: actions/upload-artifact@v2
with:
name: stash-osx
path: dist/stash-osx
- name: Upload Linux binary
# only upload binaries for pull requests
if: ${{ github.event_name == 'pull_request' && github.base_ref != 'refs/heads/develop' && github.base_ref != 'refs/heads/master'}}
uses: actions/upload-artifact@v2
with:
name: stash-linux
path: dist/stash-linux
- name: Update latest_develop tag
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
run : git tag -f latest_develop; git push -f --tags
- name: Development Release
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
uses: marvinpinto/action-automatic-releases@v1.1.2
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: true
automatic_release_tag: latest_develop
title: "${{ env.STASH_VERSION }}: Latest development build"
files: |
dist/stash-osx
dist/stash-win.exe
dist/stash-linux
dist/stash-linux-arm64v8
dist/stash-linux-arm32v7
dist/stash-pi
CHECKSUMS_SHA1
- name: Master release
if: ${{ github.event_name == 'release' && github.ref != 'refs/tags/latest_develop' }}
uses: meeDamian/github-release@2.0
with:
token: "${{ secrets.GITHUB_TOKEN }}"
allow_override: true
files: |
dist/stash-osx
dist/stash-win.exe
dist/stash-linux
dist/stash-linux-arm64v8
dist/stash-linux-arm32v7
dist/stash-pi
CHECKSUMS_SHA1
gzip: false
- name: Development Docker
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
env:
DOCKER_CLI_EXPERIMENTAL: enabled
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64
docker info
docker buildx create --name builder --use
docker buildx inspect --bootstrap
docker buildx ls
bash ./docker/ci/x86_64/docker_push.sh development
- name: Release Docker
if: ${{ github.event_name == 'release' && github.ref != 'refs/tags/latest_develop' }}
env:
DOCKER_CLI_EXPERIMENTAL: enabled
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64
docker info
docker buildx create --name builder --use
docker buildx inspect --bootstrap
docker buildx ls
bash ./docker/ci/x86_64/docker_push.sh latest "${{ github.event.release.tag_name }}"

7
.gitignore vendored
View File

@@ -20,7 +20,7 @@
# GraphQL generated output
pkg/models/generated_*.go
ui/v2/src/core/generated-*.tsx
ui/v2.5/src/core/generated-*.tsx
# packr generated files
*-packr.go
@@ -35,6 +35,7 @@ ui/v2/src/core/generated-*.tsx
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
.vscode
# Generated files
.idea/**/contentModel.xml
@@ -48,6 +49,9 @@ ui/v2/src/core/generated-*.tsx
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Goland Junk
pkg/pkg
####
# Random
####
@@ -58,3 +62,4 @@ node_modules
stash
dist
.DS_Store

13
.gqlgenc.yml Normal file
View File

@@ -0,0 +1,13 @@
model:
filename: ./pkg/scraper/stashbox/graphql/generated_models.go
client:
filename: ./pkg/scraper/stashbox/graphql/generated_client.go
models:
Date:
model: github.com/99designs/gqlgen/graphql.String
endpoint:
# This points to stashdb.org currently, but can be directed at any stash-box
# instance. It is used for generation only.
url: https://stashdb.org/graphql
query:
- "./graphql/stash-box/*.graphql"

7
.idea/go.iml generated
View File

@@ -4,11 +4,10 @@
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/certs" />
<excludeFolder url="file://$MODULE_DIR$/dist" />
<excludeFolder url="file://$MODULE_DIR$/ui/v1/dist" />
<excludeFolder url="file://$MODULE_DIR$/ui/v2/build" />
<excludeFolder url="file://$MODULE_DIR$/ui/v2/node_modules" />
<excludeFolder url="file://$MODULE_DIR$/ui/v2.5/build" />
<excludeFolder url="file://$MODULE_DIR$/ui/v2.5/node_modules" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
</module>

View File

@@ -1,50 +0,0 @@
dist: xenial
language: go
go:
- 1.11.x
services:
- docker
env:
global:
- GO111MODULE=on
before_install:
- echo -e "machine github.com\n login $CI_USER_TOKEN" > ~/.netrc
- travis_retry yarn --cwd ui/v2 install
- make generate
- CI=false yarn --cwd ui/v2 build # TODO: Fix warnings
#- go get -v github.com/mgechev/revive
script:
#- make lint
#- make vet
- make it
after_success:
- if [ "$TRAVIS_BRANCH" = "develop" ]; then export TAG_SUFFIX="_dev"; elif [ "$TRAVIS_BRANCH" != "master" ]; then export TAG_SUFFIX="_$TRAVIS_BRANCH"; fi
- export STASH_VERSION="v0.0.0-alpha${TAG_SUFFIX}"
- docker pull stashapp/compiler:develop
- sh ./scripts/cross-compile.sh ${STASH_VERSION}
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then sh ./scripts/upload-pull-request.sh; fi'
before_deploy:
- if [ "$TRAVIS_BRANCH" = "develop" ]; then export TAG_SUFFIX="_dev"; fi
- git tag -f ${STASH_VERSION}
- git push -f --tags
- export RELEASE_DATE=$(date +'%Y-%m-%d %H:%M:%S %Z')
deploy:
provider: releases
api_key:
secure: tGJ2q62CfPdayid2qEtW2aGRhMgCl3lBXYYQqp3eH0vFgIIf6cs7IDX7YC/x3XKMEQ/iMLZmtCXZvSTqNrD6Sk7MSnt30GIs+4uxIZDnnd8mV5X3K4n4gjD+NAORc4DrQBvUGrYMKJsR5gtkH0nu6diWb1o1If7OiJEuCPRhrmQYcza7NUdABnA9Z2wn2RNUV9Ga33WUCqLMEU5GtNBlfQPiP/khCQrqn/ocR6wUjYut3J6YagzqH4wsfJi3glHyWtowcNIw1LZi5zFxHD/bRBT4Tln7yypkjWNq9eQILA6i6kRUGf7ggyTx26/k8n4tnu+QD0vVh4EcjlThpU/LGyUXzKrrxjRwaDZnM0oYxg5AfHcBuAiAdo0eWnV3lEWRfTJMIVb9MPf4qDmzR4RREfB5OXOxwq3ODeCcJE8sTIMD/wBPZrlqS/QrRpND2gn2X4snkVukN9t9F4CMTFMtVSzFV7TDJW5E5Lq6VEExulteQhs6kcK9NRPNAaLgRQAw7X9kVWfDtiGUP+fE2i8F9Bo8bm7sOT5O5VPMPykx3EgeNg1IqIgMTCsMlhMJT4xBJoQUgmd2wWyf3Ryw+P+sFgdb5Sd7+lFgJBjMUUoOxMxAOiEgdFvCXcr+/Udyz2RdtetU1/6VzXzLPcKOw0wubZeBkISqu7o9gpfdMP9Eq00=
file:
- dist/stash-osx
- dist/stash-win.exe
- dist/stash-linux
- dist/stash-pi
skip_cleanup: true
overwrite: true
body: ${RELEASE_DATE}
on:
repo: stashapp/stash
all_branches: true
condition: $TRAVIS_BRANCH =~ ^(master|develop)$
branches:
only:
- master
- develop

118
.travis.yml.disabled Normal file
View File

@@ -0,0 +1,118 @@
if: tag != latest_develop # dont build for the latest_develop tagged version
dist: xenial
git:
depth: false
language: go
go:
- 1.13.x
services:
- docker
env:
global:
- GO111MODULE=on
before_install:
- set -e
# Configure environment so changes are picked up when the Docker daemon is restarted after upgrading
- echo '{"experimental":true}' | sudo tee /etc/docker/daemon.json
- export DOCKER_CLI_EXPERIMENTAL=enabled
# Upgrade to Docker CE 19.03 for BuildKit support
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- sudo apt-get update
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
# install binfmt docker container, this container uses qemu to run arm programs transparently allowng docker to build arm 6,7,8 containers.
- docker run --rm --privileged docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64
# Show info to simplify debugging and create a builder that can build the platforms we need
- docker info
- docker buildx create --name builder --use
- docker buildx inspect --bootstrap
- docker buildx ls
install:
- echo -e "machine github.com\n login $CI_USER_TOKEN" > ~/.netrc
- nvm install 12
- travis_retry make pre-ui
- make generate
- CI=false make ui-validate ui-only
#- go get -v github.com/mgechev/revive
script:
# left lint off to avoid getting extra dependency
#- make lint
- make fmt-check vet it
after_success:
- docker pull stashapp/compiler:4
- sh ./scripts/cross-compile.sh
- git describe --tags --exclude latest_develop | tee CHECKSUMS_SHA1
- sha1sum dist/stash-* | sed 's/dist\///g' | tee -a CHECKSUMS_SHA1
- 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then sh ./scripts/upload-pull-request.sh; fi'
before_deploy:
# push the latest tag when on the develop branch
- if [ "$TRAVIS_BRANCH" = "develop" ]; then git tag -f latest_develop; git push -f --tags; fi
- export RELEASE_DATE=$(date +'%Y-%m-%d %H:%M:%S %Z')
- export STASH_VERSION=$(git describe --tags --exclude latest_develop)
# set TRAVIS_TAG explcitly to the version so that it doesn't pick up latest_develop
- if [ "$TRAVIS_BRANCH" = "master" ]; then export TRAVIS_TAG=${STASH_VERSION}; fi
deploy:
# latest develop release
- provider: releases
# use the v2 release provider for proper release note setting
edge: true
api_key:
secure: tGJ2q62CfPdayid2qEtW2aGRhMgCl3lBXYYQqp3eH0vFgIIf6cs7IDX7YC/x3XKMEQ/iMLZmtCXZvSTqNrD6Sk7MSnt30GIs+4uxIZDnnd8mV5X3K4n4gjD+NAORc4DrQBvUGrYMKJsR5gtkH0nu6diWb1o1If7OiJEuCPRhrmQYcza7NUdABnA9Z2wn2RNUV9Ga33WUCqLMEU5GtNBlfQPiP/khCQrqn/ocR6wUjYut3J6YagzqH4wsfJi3glHyWtowcNIw1LZi5zFxHD/bRBT4Tln7yypkjWNq9eQILA6i6kRUGf7ggyTx26/k8n4tnu+QD0vVh4EcjlThpU/LGyUXzKrrxjRwaDZnM0oYxg5AfHcBuAiAdo0eWnV3lEWRfTJMIVb9MPf4qDmzR4RREfB5OXOxwq3ODeCcJE8sTIMD/wBPZrlqS/QrRpND2gn2X4snkVukN9t9F4CMTFMtVSzFV7TDJW5E5Lq6VEExulteQhs6kcK9NRPNAaLgRQAw7X9kVWfDtiGUP+fE2i8F9Bo8bm7sOT5O5VPMPykx3EgeNg1IqIgMTCsMlhMJT4xBJoQUgmd2wWyf3Ryw+P+sFgdb5Sd7+lFgJBjMUUoOxMxAOiEgdFvCXcr+/Udyz2RdtetU1/6VzXzLPcKOw0wubZeBkISqu7o9gpfdMP9Eq00=
file:
- dist/stash-osx
- dist/stash-win.exe
- dist/stash-linux
- dist/stash-linux-arm64v8
- dist/stash-linux-arm32v7
- dist/stash-pi
- CHECKSUMS_SHA1
skip_cleanup: true
overwrite: true
name: "${STASH_VERSION}: Latest development build"
release_notes: "**${RELEASE_DATE}**\n This is always the latest committed version on the develop branch. Use as your own risk!"
prerelease: true
on:
repo: stashapp/stash
branch: develop
# docker image build for develop release
- provider: script
skip_cleanup: true
script: bash ./docker/ci/x86_64/docker_push.sh development
on:
repo: stashapp/stash
branch: develop
# official master release - only build when tagged
- provider: releases
api_key:
secure: tGJ2q62CfPdayid2qEtW2aGRhMgCl3lBXYYQqp3eH0vFgIIf6cs7IDX7YC/x3XKMEQ/iMLZmtCXZvSTqNrD6Sk7MSnt30GIs+4uxIZDnnd8mV5X3K4n4gjD+NAORc4DrQBvUGrYMKJsR5gtkH0nu6diWb1o1If7OiJEuCPRhrmQYcza7NUdABnA9Z2wn2RNUV9Ga33WUCqLMEU5GtNBlfQPiP/khCQrqn/ocR6wUjYut3J6YagzqH4wsfJi3glHyWtowcNIw1LZi5zFxHD/bRBT4Tln7yypkjWNq9eQILA6i6kRUGf7ggyTx26/k8n4tnu+QD0vVh4EcjlThpU/LGyUXzKrrxjRwaDZnM0oYxg5AfHcBuAiAdo0eWnV3lEWRfTJMIVb9MPf4qDmzR4RREfB5OXOxwq3ODeCcJE8sTIMD/wBPZrlqS/QrRpND2gn2X4snkVukN9t9F4CMTFMtVSzFV7TDJW5E5Lq6VEExulteQhs6kcK9NRPNAaLgRQAw7X9kVWfDtiGUP+fE2i8F9Bo8bm7sOT5O5VPMPykx3EgeNg1IqIgMTCsMlhMJT4xBJoQUgmd2wWyf3Ryw+P+sFgdb5Sd7+lFgJBjMUUoOxMxAOiEgdFvCXcr+/Udyz2RdtetU1/6VzXzLPcKOw0wubZeBkISqu7o9gpfdMP9Eq00=
file:
- dist/stash-osx
- dist/stash-win.exe
- dist/stash-linux
- dist/stash-linux-arm64v8
- dist/stash-linux-arm32v7
- dist/stash-pi
- CHECKSUMS_SHA1
# make the release a draft so the maintainers can confirm before releasing
draft: true
skip_cleanup: true
overwrite: true
# don't write the body. To be done manually for now. In future we might
# want to generate the changelog or get it from a file
name: ${STASH_VERSION}
on:
repo: stashapp/stash
tags: true
# make sure we don't release using the latest_develop tag
condition: $TRAVIS_TAG != latest_develop
# docker image build for master release
- provider: script
skip_cleanup: true
script: bash ./docker/ci/x86_64/docker_push.sh latest
on:
repo: stashapp/stash
tags: true
# make sure we don't release using the latest_develop tag
condition: $TRAVIS_TAG != latest_develop

674
LICENSE
View File

@@ -1,21 +1,661 @@
MIT License
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (c) 2019 StashApp
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Preamble
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

160
Makefile
View File

@@ -1,14 +1,101 @@
ifeq ($(OS),Windows_NT)
SEPARATOR := &&
SET := set
IS_WIN =
ifeq (${SHELL}, sh.exe)
IS_WIN = true
endif
ifeq (${SHELL}, cmd)
IS_WIN = true
endif
release: generate ui build
ifdef IS_WIN
SEPARATOR := &&
SET := set
else
SEPARATOR := ;
SET := export
endif
build:
$(eval DATE := $(shell go run scripts/getDate.go))
# set LDFLAGS environment variable to any extra ldflags required
# set OUTPUT to generate a specific binary name
LDFLAGS := $(LDFLAGS)
ifdef OUTPUT
OUTPUT := -o $(OUTPUT)
endif
export CGO_ENABLED = 1
export GO111MODULE = on
.PHONY: release pre-build install clean
release: generate ui build-release
pre-build:
ifndef BUILD_DATE
$(eval BUILD_DATE := $(shell go run -mod=vendor scripts/getDate.go))
endif
ifndef GITHASH
$(eval GITHASH := $(shell git rev-parse --short HEAD))
$(SET) CGO_ENABLED=1 $(SEPARATOR) go build -mod=vendor -v -ldflags "-X 'github.com/stashapp/stash/pkg/api.buildstamp=$(DATE)' -X 'github.com/stashapp/stash/pkg/api.githash=$(GITHASH)'"
endif
ifndef STASH_VERSION
$(eval STASH_VERSION := $(shell git describe --tags --exclude latest_develop))
endif
build: pre-build
$(eval LDFLAGS := $(LDFLAGS) -X 'github.com/stashapp/stash/pkg/api.version=$(STASH_VERSION)' -X 'github.com/stashapp/stash/pkg/api.buildstamp=$(BUILD_DATE)' -X 'github.com/stashapp/stash/pkg/api.githash=$(GITHASH)')
go build $(OUTPUT) -mod=vendor -v -tags "sqlite_omit_load_extension osusergo netgo" -ldflags "$(LDFLAGS) $(EXTRA_LDFLAGS)"
# strips debug symbols from the release build
# consider -trimpath in go build if we move to go 1.13+
build-release: EXTRA_LDFLAGS := -s -w
build-release: build
build-release-static: EXTRA_LDFLAGS := -extldflags=-static -s -w
build-release-static: build
# cross-compile- targets should be run within the compiler docker container
cross-compile-windows: export GOOS := windows
cross-compile-windows: export GOARCH := amd64
cross-compile-windows: export CC := x86_64-w64-mingw32-gcc
cross-compile-windows: export CXX := x86_64-w64-mingw32-g++
cross-compile-windows: OUTPUT := -o dist/stash-win.exe
cross-compile-windows: build-release-static
cross-compile-osx: export GOOS := darwin
cross-compile-osx: export GOARCH := amd64
cross-compile-osx: export CC := o64-clang
cross-compile-osx: export CXX := o64-clang++
cross-compile-osx: OUTPUT := -o dist/stash-osx
# can't use static build for OSX
cross-compile-osx: build-release
cross-compile-linux: export GOOS := linux
cross-compile-linux: export GOARCH := amd64
cross-compile-linux: OUTPUT := -o dist/stash-linux
cross-compile-linux: build-release-static
cross-compile-linux-arm64v8: export GOOS := linux
cross-compile-linux-arm64v8: export GOARCH := arm64
cross-compile-linux-arm64v8: export CC := aarch64-linux-gnu-gcc
cross-compile-linux-arm64v8: OUTPUT := -o dist/stash-linux-arm64v8
cross-compile-linux-arm64v8: build-release-static
cross-compile-linux-arm32v7: export GOOS := linux
cross-compile-linux-arm32v7: export GOARCH := arm
cross-compile-linux-arm32v7: export GOARM := 7
cross-compile-linux-arm32v7: export CC := arm-linux-gnueabihf-gcc
cross-compile-linux-arm32v7: OUTPUT := -o dist/stash-linux-arm32v7
cross-compile-linux-arm32v7: build-release-static
cross-compile-pi: export GOOS := linux
cross-compile-pi: export GOARCH := arm
cross-compile-pi: export GOARM := 6
cross-compile-pi: export CC := arm-linux-gnueabi-gcc
cross-compile-pi: OUTPUT := -o dist/stash-pi
cross-compile-pi: build-release-static
cross-compile-all: cross-compile-windows cross-compile-osx cross-compile-linux cross-compile-linux-arm64v8 cross-compile-linux-arm32v7 cross-compile-pi
install:
packr2 install
@@ -20,13 +107,23 @@ clean:
.PHONY: generate
generate:
go generate -mod=vendor
cd ui/v2 && yarn run gqlgen
cd ui/v2.5 && yarn run gqlgen
# Regenerates stash-box client files
.PHONY: generate-stash-box-client
generate-stash-box-client:
go run -mod=vendor github.com/Yamashou/gqlgenc
# Runs gofmt -w on the project's source code, modifying any files that do not match its style.
.PHONY: fmt
fmt:
go fmt ./...
# Ensures that changed files have had gofmt run on them
.PHONY: fmt-check
fmt-check:
sh ./scripts/check-gofmt.sh
# Runs go vet on the project's source code.
.PHONY: vet
vet:
@@ -46,7 +143,50 @@ test:
it:
go test -mod=vendor -tags=integration ./...
# generates test mocks
.PHONY: generate-test-mocks
generate-test-mocks:
go run -mod=vendor github.com/vektra/mockery/v2 --dir ./pkg/models --name '.*ReaderWriter' --outpkg mocks --output ./pkg/models/mocks
# installs UI dependencies. Run when first cloning repository, or if UI
# dependencies have changed
.PHONY: pre-ui
pre-ui:
cd ui/v2.5 && yarn install --frozen-lockfile
.PHONY: ui-only
ui-only: pre-build
$(SET) REACT_APP_DATE="$(BUILD_DATE)" $(SEPARATOR) \
$(SET) REACT_APP_GITHASH=$(GITHASH) $(SEPARATOR) \
$(SET) REACT_APP_STASH_VERSION=$(STASH_VERSION) $(SEPARATOR) \
cd ui/v2.5 && yarn build
.PHONY: ui
ui:
cd ui/v2 && yarn build
ui: ui-only
packr2
.PHONY: ui-start
ui-start: pre-build
$(SET) REACT_APP_DATE="$(BUILD_DATE)" $(SEPARATOR) \
$(SET) REACT_APP_GITHASH=$(GITHASH) $(SEPARATOR) \
$(SET) REACT_APP_STASH_VERSION=$(STASH_VERSION) $(SEPARATOR) \
cd ui/v2.5 && yarn start
.PHONY: fmt-ui
fmt-ui:
cd ui/v2.5 && yarn format
# runs tests and checks on the UI and builds it
.PHONY: ui-validate
ui-validate:
cd ui/v2.5 && yarn run validate
# just repacks the packr files - use when updating migrations and packed files without
# rebuilding the UI
.PHONY: packr
packr:
packr2
# runs all of the tests and checks required for a PR to be accepted
.PHONY: validate
validate: ui-validate fmt-check vet lint it

View File

@@ -4,72 +4,99 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/stashapp/stash)](https://goreportcard.com/report/github.com/stashapp/stash)
[![Discord](https://img.shields.io/discord/559159668438728723.svg?logo=discord)](https://discord.gg/2TsNFKt)
**Stash is a Go app which organizes and serves your porn.**
https://stashapp.cc
See a demo [here](https://vimeo.com/275537038) (password is stashapp).
**Stash is a locally hosted web-based app written in Go which organizes and serves your porn.**
# Docker install
* It can gather information about videos in your collection from the internet, and is extensible through the use of community-built plugins for a large number of content producers.
* It supports a wide variety of both video and image formats.
* You can tag videos and find them later.
* It provides statistics about performers, tags, studios and other things.
You can [watch a SFW demo video](https://vimeo.com/545323354) to see it in action.
For further information you can [read the in-app manual](ui/v2.5/src/docs/en).
# Installing stash
## via Docker
Follow [this README.md in the docker directory.](docker/production/README.md)
# Bare-metal Install
## Pre-Compiled Binaries
Stash supports macOS, Windows, and Linux. Download the [latest release here](https://github.com/stashapp/stash/releases).
The Stash server runs on macOS, Windows, and Linux. Download the [latest release here](https://github.com/stashapp/stash/releases).
Run the executable (double click the exe on windows or run `./stash-osx` / `./stash-linux` from the terminal on macOS / Linux) and navigate to either https://localhost:9999 or http://localhost:9998 to get started.
Run the executable (double click the exe on windows or run `./stash-osx` / `./stash-linux` from the terminal on macOS / Linux) and navigate to either https://localhost:9999 or http://localhost:9999 to get started.
*Note for Windows users:* Running the app might present a security prompt since the binary isn't signed yet. Just click more info and then the "run anyway" button.
*Note for Windows users:* Running the app might present a security prompt since the binary isn't yet signed. Bypass this by clicking "more info" and then the "run anyway" button.
#### FFMPEG
If stash is unable to find or download FFMPEG then download it yourself from the link for your platform:
* [macOS](https://ffmpeg.zeranoe.com/builds/macos64/static/ffmpeg-4.0-macos64-static.zip)
* [Windows](https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.0-win64-static.zip)
* [Linux](https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz)
* [macOS ffmpeg](https://evermeet.cx/ffmpeg/ffmpeg-4.3.1.zip), [macOS ffprobe](https://evermeet.cx/ffmpeg/ffprobe-4.3.1.zip)
* [Windows](https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip)
* [Linux](https://www.johnvansickle.com/ffmpeg/)
The `ffmpeg(.exe)` and `ffprobe(.exe)` files should be placed in `~/.stash` on macOS / Linux or `C:\Users\YourUsername\.stash` on Windows.
# Usage
## Quickstart Guide
1) Download and install Stash and its dependencies
2) Run Stash. It will prompt you for some configuration options and a directory to index (you can also do this step afterward)
3) After configuration, launch your web browser and navigate to the URL shown within the Stash app.
**Note that Stash does not currently retrieve and organize information about your entire library automatically.** You will need to help it along through the use of [scrapers](blob/develop/ui/v2.5/src/docs/en/Scraping.md). The Stash community has developed scrapers for many popular data sources which can be downloaded and installed from [this repository](https://github.com/stashapp/CommunityScrapers).
The simplest way to tag a large number of files is by using the [Tagger](https://github.com/stashapp/stash/blob/develop/ui/v2.5/src/docs/en/Tagger.md) which uses filename keywords to help identify the file and pull in scene and performer information from our stash-box database. Note that this data source is not comprehensive and you may need to use the scrapers to identify some of your media.
## CLI
Stash provides some command line options. See what is currently available by running `stash --help`.
Stash runs as a command-line app and local web server. There are some command-line options available, which you can see by running `stash --help`.
For example, to run stash locally on port 80 run it like this (OSX / Linux) `stash --host 127.0.0.1 --port 80`
## SSL (HTTPS)
Stash supports HTTPS with some additional work. First you must generate a SSL certificate and key combo. Here is an example using openssl:
Stash can run over HTTPS with some additional work. First you must generate a SSL certificate and key combo. Here is an example using openssl:
`openssl req -x509 -newkey rsa:4096 -sha256 -days 7300 -nodes -keyout stash.key -out stash.crt -extensions san -config <(echo "[req]"; echo distinguished_name=req; echo "[san]"; echo subjectAltName=DNS:stash.server,IP:127.0.0.1) -subj /CN=stash.server`
This command would need customizing for your environment. [This link](https://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl) might be useful.
Once you have a certificate and key file name them `stash.crt` and `stash.key` and place them in the `~/.stash` directory. Stash detects these and starts up using HTTPS rather than HTTP.
Once you have a certificate and key file name them `stash.crt` and `stash.key` and place them in the same directory as the `config.yml` file, or the `~/.stash` directory. Stash detects these and starts up using HTTPS rather than HTTP.
# FAQ
# Customization
> I'm unable to run the app on OSX or Linux
## Themes and CSS Customization
There is a [directory of community-created themes](https://github.com/stashapp/stash/wiki/Themes) on our Wiki, along with instructions on how to install them.
Try running `chmod u+x stash-osx` or `chmod u+x stash-linux` to make the file executable.
You can also make Stash interface fit your desired style with [Custom CSS snippets](https://github.com/stashapp/stash/wiki/Custom-CSS-snippets) and [CSS Tweaks](https://github.com/stashapp/stash/wiki/CSS-Tweaks).
> I have a question not answered here.
# Support (FAQ)
Join the [Discord server](https://discord.gg/2TsNFKt).
Answers to other Frequently Asked Questions can be found [on our Wiki](https://github.com/stashapp/stash/wiki/FAQ)
# Development
For issues not addressed there, there are a few options.
## Install
* Read the [Wiki](https://github.com/stashapp/stash/wiki)
* Check the in-app documentation (also available [here](https://github.com/stashapp/stash/tree/develop/ui/v2.5/src/docs/en)
* Join the [Discord server](https://discord.gg/2TsNFKt), where the community can offer support.
# Compiling From Source Code
## Pre-requisites
* [Go](https://golang.org/dl/)
* [Revive](https://github.com/mgechev/revive) - Configurable linter
* Go Install: `go get github.com/mgechev/revive`
* [Packr2](https://github.com/gobuffalo/packr/tree/v2.0.2/v2) - Static asset bundler
* Go Install: `go get github.com/gobuffalo/packr/v2/packr2@v2.0.2`
* [Packr2](https://github.com/gobuffalo/packr/) - Static asset bundler
* Go Install: `go get github.com/gobuffalo/packr/v2/packr2`
* [Binary Download](https://github.com/gobuffalo/packr/releases)
* [Yarn](https://yarnpkg.com/en/docs/install) - Yarn package manager
* Run `yarn install` in the `stash/ui/v2` folder (before running make generate for first time).
* Run `yarn install --frozen-lockfile` in the `stash/ui/v2.5` folder (before running make generate for first time).
NOTE: You may need to run the `go get` commands outside the project directory to avoid modifying the projects module file.
@@ -92,11 +119,19 @@ NOTE: The `make` command in Windows will be `mingw32-make` with MingW.
## Commands
* `make generate` - Generate Go GraphQL and packr2 files
* `make generate` - Generate Go and UI GraphQL files
* `make build` - Builds the binary (make sure to build the UI as well... see below)
* `make ui` - Builds the frontend
* `make pre-ui` - Installs the UI dependencies. Only needs to be run once before building the UI for the first time, or if the dependencies are updated
* `make fmt-ui` - Formats the UI source code.
* `make ui` - Builds the frontend and the packr2 files
* `make packr` - Generate packr2 files (sub-target of `ui`. Use to regenerate packr2 files without rebuilding UI)
* `make vet` - Run `go vet`
* `make lint` - Run the linter
* `make fmt` - Run `go fmt`
* `make fmt-check` - Ensure changed files are formatted correctly
* `make it` - Run the unit and integration tests
* `make validate` - Run all of the tests and checks required to submit a PR
* `make ui-start` - Runs the UI in development mode. Requires a running stash server to connect to. Stash port can be changed from the default of `9999` with environment variable `REACT_APP_PLATFORM_PORT`.
## Building a release
@@ -106,8 +141,20 @@ NOTE: The `make` command in Windows will be `mingw32-make` with MingW.
## Cross compiling
This project uses a modification of [this](https://github.com/bep/dockerfiles/tree/master/ci-goreleaser) docker container to create an environment
This project uses a modification of the [CI-GoReleaser](https://github.com/bep/dockerfiles/tree/master/ci-goreleaser) docker container to create an environment
where the app can be cross-compiled. This process is kicked off by CI via the `scripts/cross-compile.sh` script. Run the following
command to open a bash shell to the container to poke around:
`docker run --rm --mount type=bind,source="$(pwd)",target=/stash -w /stash -i -t stashappdev/compiler:latest /bin/bash`
## Profiling
Stash can be profiled using the `--cpuprofile <output profile filename>` command line flag.
The resulting file can then be used with pprof as follows:
`go tool pprof <path to binary> <path to profile filename>`
With `graphviz` installed and in the path, a call graph can be generated with:
`go tool pprof -svg <path to binary> <path to profile filename> > <output svg file>`

View File

@@ -0,0 +1,61 @@
# this dockerfile must be built from the top-level stash directory
# ie from top=level stash:
# docker build -t stash/build -f docker/build/x86_64/Dockerfile .
FROM golang:1.13.15 as compiler
RUN apt-get update && apt-get install -y apt-transport-https
RUN curl -sL https://deb.nodesource.com/setup_lts.x | bash -
# prevent caching of the key
ADD https://dl.yarnpkg.com/debian/pubkey.gpg yarn.gpg
RUN cat yarn.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
rm yarn.gpg
RUN apt-get update && \
apt-get install -y nodejs yarn xz-utils --no-install-recommends || exit 1; \
rm -rf /var/lib/apt/lists/*;
ENV PACKR2_VERSION=2.0.2
ENV PACKR2_SHA=f95ff4c96d7a28813220df030ad91700b8464fe292ab3e1dc9582305c2a338d2
ENV PACKR2_DOWNLOAD_FILE=packr_${PACKR2_VERSION}_linux_amd64.tar.gz
ENV PACKR2_DOWNLOAD_URL=https://github.com/gobuffalo/packr/releases/download/v${PACKR2_VERSION}/${PACKR2_DOWNLOAD_FILE}
WORKDIR /
RUN wget ${PACKR2_DOWNLOAD_URL}; \
echo "$PACKR2_SHA $PACKR2_DOWNLOAD_FILE" | sha256sum -c - || exit 1; \
tar -xzf $PACKR2_DOWNLOAD_FILE -C /usr/bin/ packr2; \
rm $PACKR2_DOWNLOAD_FILE;
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN wget -O /ffmpeg.tar.xz https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \
tar xf /ffmpeg.tar.xz && \
rm ffmpeg.tar.xz && \
mv /ffmpeg*/ /ffmpeg/
# copy the ui yarn stuff so that it doesn't get rebuilt every time
COPY ./ui/v2.5/package.json ./ui/v2.5/yarn.lock /stash/ui/v2.5/
WORKDIR /stash
RUN yarn --cwd ui/v2.5 install --frozen-lockfile
COPY . /stash/
ENV GO111MODULE=on
RUN make generate
RUN make ui
RUN make build
FROM ubuntu:20.04 as app
RUN apt-get update && apt-get -y install ca-certificates
COPY --from=compiler /stash/stash /ffmpeg/ffmpeg /ffmpeg/ffprobe /usr/bin/
ENV STASH_CONFIG_FILE=/root/.stash/config.yml
EXPOSE 9999
CMD ["stash"]

View File

@@ -0,0 +1,67 @@
# Introduction
This dockerfile is used to build a stash docker container using the current source code.
# Building the docker container
From the top-level directory (should contain `main.go` file):
```
docker build -t stash/build -f ./docker/build/x86_64/Dockerfile .
```
# Running the docker container
## Using docker-compose
See the `README.md` file in `docker/production` for instructions on how to get docker-compose if needed.
The `stash/build` container can be run with the `docker-compose.yml` file in `docker/production` by changing the `image` value to be `stash/build`. See the instructions in `docker/production` for how to run docker-compose.
## Using `docker run`
After building the container:
```
docker run \
-e STASH_STASH=/data/ \
-e STASH_METADATA=/metadata/ \
-e STASH_CACHE=/cache/ \
-e STASH_GENERATED=/generated/ \
-v <path to config dir>:/root/.stash \
-v <path to media>:/data \
-v <path to metadata>:/metadata \
-v <path to cache>:/cache \
-v <path to generated>:/generated \
-p 9999:9999 \
stash/build:latest
```
Change the `<xxx>` to the appropriate paths. Note that the `<path to media>` directory should be separate from the cache, generated and metadata directories. It is recommended to have the cache, generated and metadata directories in the same parent directory, for example:
```
/stash
/config
/metadata
/generated
/cache
/media
```
Using this example directory structure, the above command would be:
```
docker run \
-e STASH_STASH=/data/ \
-e STASH_METADATA=/metadata/ \
-e STASH_CACHE=/cache/ \
-e STASH_GENERATED=/generated/ \
-v /stash/config:/root/.stash \
-v /media:/data \
-v /stash/metadata:/metadata \
-v /stash/cache:/cache \
-v /stash/generated:/generated \
-p 9999:9999 \
stash/build:latest
```

View File

@@ -0,0 +1,22 @@
FROM --platform=$BUILDPLATFORM ubuntu:20.04 AS prep
ARG TARGETPLATFORM
WORKDIR /
COPY stash-* /
RUN if [ "$TARGETPLATFORM" = "linux/arm/v6" ]; then BIN=stash-pi; \
elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then BIN=stash-linux-arm32v7; \
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then BIN=stash-linux-arm64v8; \
elif [ "$TARGETPLATFORM" = "linux/amd64" ]; then BIN=stash-linux; \
fi; \
mv $BIN /stash
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y python3 python-is-python3 python3-requests python3-requests-toolbelt python3-lxml python3-pip && pip3 install cloudscraper
FROM ubuntu:20.04 as app
run apt update && apt install -y python3 python-is-python3 python3-requests python3-requests-toolbelt python3-lxml python3-mechanicalsoup ffmpeg && rm -rf /var/lib/apt/lists/*
COPY --from=prep /stash /usr/bin/
COPY --from=prep /usr/local/lib/python3.8/dist-packages /usr/local/lib/python3.8/dist-packages
ENV STASH_CONFIG_FILE=/root/.stash/config.yml
EXPOSE 9999
CMD ["stash"]

View File

@@ -0,0 +1 @@
This dockerfile is used by travis to build the stash image. It must be run after cross-compiling - that is, `stash-linux` must exist in the `dist` directory. This image must be built from the `dist` directory.

View File

@@ -0,0 +1,14 @@
#!/bin/bash
DOCKER_TAGS=""
for TAG in "$@"
do
DOCKER_TAGS="$DOCKER_TAGS -t stashapp/stash:$TAG"
done
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
# must build the image from dist directory
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --push $DOCKER_TAGS -f docker/ci/x86_64/Dockerfile dist/

View File

@@ -1,4 +1,4 @@
FROM golang:1.11.5
FROM golang:1.13.15
LABEL maintainer="stashappdev@gmail.com"
@@ -9,17 +9,22 @@ ENV PACKR2_DOWNLOAD_URL=https://github.com/gobuffalo/packr/releases/download/v${
# Install tools
RUN apt-get update && apt-get install -y apt-transport-https
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN curl -sL https://deb.nodesource.com/setup_lts.x | bash -
# prevent caching of the key
ADD https://dl.yarnpkg.com/debian/pubkey.gpg yarn.gpg
RUN cat yarn.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
rm yarn.gpg
RUN apt-get update && \
apt-get install -y automake autogen \
libtool libxml2-dev uuid-dev libssl-dev bash \
patch make tar xz-utils bzip2 gzip sed cpio \
gcc-6-multilib g++-6-multilib gcc-mingw-w64 g++-mingw-w64 clang llvm-dev \
gcc-8-multilib gcc-mingw-w64 g++-mingw-w64 clang llvm-dev \
gcc-arm-linux-gnueabi libc-dev-armel-cross linux-libc-dev-armel-cross \
gcc-arm-linux-gnueabihf libc-dev-armhf-cross \
gcc-aarch64-linux-gnu libc-dev-arm64-cross \
nodejs yarn --no-install-recommends || exit 1; \
rm -rf /var/lib/apt/lists/*;

View File

@@ -1,6 +1,6 @@
user=stashappdev
user=stashapp
repo=compiler
version=2
version=4
latest:
docker build -t ${user}/${repo}:latest .

View File

@@ -1 +1,3 @@
Modified from https://github.com/bep/dockerfiles/tree/master/ci-goreleaser
Modified from https://github.com/bep/dockerfiles/tree/master/ci-goreleaser
When the dockerfile is changed, the version number should be incremented in the Makefile and the new version tag should be pushed to docker hub. The `scripts/cross-compile.sh` script should also be updated to use the new version number tag, and `.travis.yml` needs to be updated to pull the correct image tag.

View File

@@ -0,0 +1,27 @@
FROM ubuntu:20.04 as prep
LABEL MAINTAINER="https://discord.gg/Uz29ny"
RUN apt-get update && \
apt-get -y install curl xz-utils && \
apt-get autoclean -y && \
rm -rf /var/lib/apt/lists/*
WORKDIR /
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# added " to end of stash-linux clause so that it doesn't pick up the arm builds
RUN curl -L -o /stash $(curl -s https://api.github.com/repos/stashapp/stash/releases/tags/latest_develop | awk '/browser_download_url/ && /stash-linux"/' | sed -e 's/.*: "\(.*\)"/\1/') && \
chmod +x /stash
RUN curl --http1.1 -o /ffmpeg.tar.xz https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \
tar xf /ffmpeg.tar.xz && \
rm ffmpeg.tar.xz && \
mv /ffmpeg*/ /ffmpeg/
FROM ubuntu:20.04 as app
RUN apt-get update && apt-get -y install ca-certificates
COPY --from=prep /stash /ffmpeg/ffmpeg /ffmpeg/ffprobe /usr/bin/
ENV STASH_CONFIG_FILE=/root/.stash/config.yml
EXPOSE 9999
CMD ["stash"]

View File

@@ -11,7 +11,7 @@ services:
driver: "json-file"
options:
max-file: "10"
max-size: "200k"
max-size: "2m"
environment:
- STASH_STASH=/data/
- STASH_GENERATED=/generated/
@@ -19,13 +19,16 @@ services:
- STASH_CACHE=/cache/
volumes:
- /etc/localtime:/etc/localtime:ro
## Adjust below paths (the left part) to your liking.
## E.g. you can change ./config:/root/.stash to ./stash:/root/.stash
## Keep configs here.
- ./config:/root/.stash
## Point this at your collection.
- ./data:/data
## This is where pre-generated transcodes live.
- ./transcodes:/transcodes
## This is where your stash's metadata lives
- ./metadata:/metadata
## Any other cache content.
- ./cache:/cache
## Where to store generated content (screenshots,previews,transcodes,sprites)
- ./generated:/generated

View File

@@ -1,4 +1,4 @@
FROM ubuntu:18.04 as prep
FROM ubuntu:20.04 as prep
LABEL MAINTAINER="leopere [at] nixc [dot] us"
RUN apt-get update && \
@@ -7,17 +7,21 @@ RUN apt-get update && \
rm -rf /var/lib/apt/lists/*
WORKDIR /
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN curl -L -o /stash $(curl -s https://api.github.com/repos/stashapp/stash/releases | grep -F 'stash-linux' | grep download | head -n 1 | cut -d'"' -f4) && \
chmod +x /stash && \
curl -o /ffmpeg.tar.xz https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \
# added " to end of stash-linux clause so that it doesn't pick up the arm builds
RUN curl -L -o /stash $(curl -s https://api.github.com/repos/stashapp/stash/releases/latest | awk '/browser_download_url/ && /stash-linux/"' | sed -e 's/.*: "\(.*\)"/\1/') && \
chmod +x /stash
RUN curl --http1.1 -o /ffmpeg.tar.xz https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \
tar xf /ffmpeg.tar.xz && \
rm ffmpeg.tar.xz && \
mv /ffmpeg*/ /ffmpeg/
FROM ubuntu:18.04 as app
RUN apt-get update && \
apt-get -y install ca-certificates && \
adduser stash --gecos GECOS --shell /bin/bash --disabled-password --home /home/stash
FROM ubuntu:20.04 as app
RUN apt-get update && apt-get -y install ca-certificates
COPY --from=prep /stash /ffmpeg/ffmpeg /ffmpeg/ffprobe /usr/bin/
ENV STASH_CONFIG_FILE=/root/.stash/config.yml
EXPOSE 9999
CMD ["stash"]

14
docs/CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,14 @@
## Technical Debt
Please be sure to consider how heavily your contribution impacts the maintainability of the project long term, sometimes less is more. We don't want to merge collossal pull requests with hundreds of dependencies by a driveby contributor.
## Contributor Checklist
Please make sure that you've considered the following before you submit your Pull Requests as ready for merging.
* I've run Code linters and [gofmt](https://golang.org/cmd/gofmt/) to make sure that my code is readable.
* I have read through formerly submitted [pull requests](https://github.com/stashapp/stash/pulls) and [git issues](https://github.com/stashapp/stash/issues) to make sure that this contribution is required and isn't a duplicate. Also, so that I can manage to close any git Issues needing closed relating to this feature submission.
* I commented adequately on my code with the expectation in mind that anyone else should be able to look at this code I've submitted and know exactly what's happening and what the expectations are.
### Legal Agreements
* I acknowledge that if applicable to me, submitting and subsequent acceptance of this Pull Request I, the code contributor of this Pull Request, agree and acknowledge my understanding that the new code license has now been updated to [AGPL](/LICENSE.md). I agree that all code before this Pull Request, which I've previously submitted, is now to be re-licensed under the new license AGPL and no longer the former MIT license.
**In case you were unable to follow any of the above include an explanation as to why not in your Pull Request.**

55
go.mod
View File

@@ -1,30 +1,53 @@
module github.com/stashapp/stash
require (
github.com/99designs/gqlgen v0.9.0
github.com/PuerkitoBio/goquery v1.5.0
github.com/antchfx/htmlquery v1.2.0
github.com/antchfx/xpath v1.1.2 // indirect
github.com/bmatcuk/doublestar v1.1.5
github.com/99designs/gqlgen v0.12.2
github.com/Yamashou/gqlgenc v0.0.0-20200902035953-4dbef3551953
github.com/anacrolix/dms v1.2.2
github.com/antchfx/htmlquery v1.2.3
github.com/chromedp/cdproto v0.0.0-20210622022015-fe1827b46b84
github.com/chromedp/chromedp v0.7.3
github.com/corona10/goimagehash v1.0.3
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/disintegration/imaging v1.6.0
github.com/fvbommel/sortorder v1.0.2
github.com/go-chi/chi v4.0.2+incompatible
github.com/gobuffalo/packr/v2 v2.0.2
github.com/gobuffalo/logger v1.0.4 // indirect
github.com/gobuffalo/packr/v2 v2.8.1
github.com/golang-migrate/migrate/v4 v4.3.1
github.com/gorilla/websocket v1.4.0
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/sessions v1.2.0
github.com/gorilla/websocket v1.4.2
github.com/h2non/filetype v1.0.8
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
github.com/jmoiron/sqlx v1.2.0
github.com/mattn/go-sqlite3 v1.10.0
github.com/json-iterator/go v1.1.9
github.com/karrick/godirwalk v1.16.1 // indirect
github.com/mattn/go-sqlite3 v1.14.6
github.com/natefinch/pie v0.0.0-20170715172608-9a0d72014007
github.com/remeh/sizedwaitgroup v1.0.0
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac
github.com/rs/cors v1.6.0
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f
github.com/sirupsen/logrus v1.4.2
github.com/sirupsen/logrus v1.8.1
github.com/spf13/afero v1.2.0 // indirect
github.com/spf13/pflag v1.0.3
github.com/spf13/viper v1.4.0
github.com/vektah/gqlparser v1.1.2
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/image v0.0.0-20190118043309-183bebdce1b2 // indirect
golang.org/x/net v0.0.0-20190522155817-f3200d17e092
gopkg.in/yaml.v2 v2.2.2
github.com/spf13/viper v1.7.0
github.com/stretchr/testify v1.5.1
github.com/tidwall/gjson v1.8.1
github.com/tidwall/pretty v1.2.0 // indirect
github.com/vektah/gqlparser/v2 v2.0.1
github.com/vektra/mockery/v2 v2.2.1
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/tools v0.0.0-20200915031644-64986481280e // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.3.0
)
replace git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999
go 1.13

827
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,10 @@ struct_tag: gqlgen
models:
Gallery:
model: github.com/stashapp/stash/pkg/models.Gallery
Image:
model: github.com/stashapp/stash/pkg/models.Image
ImageFileType:
model: github.com/stashapp/stash/pkg/models.ImageFileType
Performer:
model: github.com/stashapp/stash/pkg/models.Performer
Scene:
@@ -26,6 +30,8 @@ models:
model: github.com/stashapp/stash/pkg/models.ScrapedItem
Studio:
model: github.com/stashapp/stash/pkg/models.Studio
Movie:
model: github.com/stashapp/stash/pkg/models.Movie
Tag:
model: github.com/stashapp/stash/pkg/models.Tag
ScrapedPerformer:
@@ -36,7 +42,17 @@ models:
model: github.com/stashapp/stash/pkg/models.ScrapedScenePerformer
ScrapedSceneStudio:
model: github.com/stashapp/stash/pkg/models.ScrapedSceneStudio
ScrapedSceneMovie:
model: github.com/stashapp/stash/pkg/models.ScrapedSceneMovie
ScrapedSceneTag:
model: github.com/stashapp/stash/pkg/models.ScrapedSceneTag
SceneFileType:
model: github.com/stashapp/stash/pkg/models.SceneFileType
ScrapedMovie:
model: github.com/stashapp/stash/pkg/models.ScrapedMovie
ScrapedMovieStudio:
model: github.com/stashapp/stash/pkg/models.ScrapedMovieStudio
SavedFilter:
model: github.com/stashapp/stash/pkg/models.SavedFilter
StashID:
model: github.com/stashapp/stash/pkg/models.StashID

View File

@@ -1,26 +1,76 @@
fragment ConfigGeneralData on ConfigGeneralResult {
stashes
stashes {
path
excludeVideo
excludeImage
}
databasePath
generatedPath
cachePath
calculateMD5
videoFileNamingAlgorithm
parallelTasks
previewAudio
previewSegments
previewSegmentDuration
previewExcludeStart
previewExcludeEnd
previewPreset
maxTranscodeSize
maxStreamingTranscodeSize
apiKey
username
password
maxSessionAge
logFile
logOut
logLevel
logAccess
createGalleriesFromFolders
videoExtensions
imageExtensions
galleryExtensions
excludes
imageExcludes
customPerformerImageLocation
scraperUserAgent
scraperCertCheck
scraperCDPPath
stashBoxes {
name
endpoint
api_key
}
}
fragment ConfigInterfaceData on ConfigInterfaceResult {
menuItems
soundOnPreview
wallShowTitle
wallPlayback
maximumLoopDuration
autostartVideo
showStudioAsText
css
cssEnabled
language
slideshowDelay
handyKey
funscriptOffset
}
fragment ConfigDLNAData on ConfigDLNAResult {
serverName
enabled
whitelistedIPs
interfaces
}
fragment ConfigScrapingData on ConfigScrapingResult {
scraperUserAgent
scraperCertCheck
scraperCDPPath
excludeTagPatterns
}
fragment ConfigData on ConfigResult {
@@ -30,4 +80,10 @@ fragment ConfigData on ConfigResult {
interface {
...ConfigInterfaceData
}
dlna {
...ConfigDLNAData
}
scraping {
...ConfigScrapingData
}
}

View File

@@ -0,0 +1,6 @@
fragment SavedFilterData on SavedFilter {
id
mode
name
filter
}

View File

@@ -0,0 +1,44 @@
fragment SlimGalleryData on Gallery {
id
checksum
path
title
date
url
details
rating
organized
image_count
cover {
file {
size
width
height
}
paths {
thumbnail
}
}
studio {
id
name
image_path
}
tags {
id
name
}
performers {
id
name
gender
favorite
image_path
}
scenes {
id
title
path
}
}

View File

@@ -3,9 +3,28 @@ fragment GalleryData on Gallery {
checksum
path
title
files {
index
name
path
date
url
details
rating
organized
images {
...SlimImageData
}
cover {
...SlimImageData
}
studio {
...SlimStudioData
}
tags {
...SlimTagData
}
performers {
...PerformerData
}
scenes {
...SlimSceneData
}
}

View File

@@ -0,0 +1,45 @@
fragment SlimImageData on Image {
id
checksum
title
rating
organized
o_counter
path
file {
size
width
height
}
paths {
thumbnail
image
}
galleries {
id
path
title
}
studio {
id
name
image_path
}
tags {
id
name
}
performers {
id
name
gender
favorite
image_path
}
}

View File

@@ -0,0 +1,36 @@
fragment ImageData on Image {
id
checksum
title
rating
organized
o_counter
path
file {
size
width
height
}
paths {
thumbnail
image
}
galleries {
...GalleryData
}
studio {
...SlimStudioData
}
tags {
...SlimTagData
}
performers {
...PerformerData
}
}

View File

@@ -0,0 +1,10 @@
fragment JobData on Job {
id
status
subTasks
description
progress
startTime
endTime
addTime
}

View File

@@ -0,0 +1,5 @@
fragment SlimMovieData on Movie {
id
name
front_image_path
}

View File

@@ -0,0 +1,20 @@
fragment MovieData on Movie {
id
checksum
name
aliases
duration
date
rating
director
studio {
...SlimStudioData
}
synopsis
url
front_image_path
back_image_path
scene_count
}

View File

@@ -1,5 +1,16 @@
fragment SlimPerformerData on Performer {
id
name
gender
image_path
favorite
tags {
id
name
}
stash_ids {
endpoint
stash_id
}
rating
}

View File

@@ -3,6 +3,7 @@ fragment PerformerData on Performer {
checksum
name
url
gender
twitter
instagram
birthdate
@@ -19,4 +20,20 @@ fragment PerformerData on Performer {
favorite
image_path
scene_count
image_count
gallery_count
tags {
...SlimTagData
}
stash_ids {
stash_id
endpoint
}
rating
details
death_date
hair_color
weight
}

View File

@@ -12,10 +12,12 @@ fragment SceneMarkerData on SceneMarker {
primary_tag {
id
name
aliases
}
tags {
id
name
aliases
}
}

View File

@@ -1,12 +1,17 @@
fragment SlimSceneData on Scene {
id
checksum
oshash
title
details
url
date
rating
o_counter
organized
path
phash
interactive
file {
size
@@ -26,6 +31,8 @@ fragment SlimSceneData on Scene {
webp
vtt
chapters_vtt
sprite
funscript
}
scene_markers {
@@ -34,7 +41,7 @@ fragment SlimSceneData on Scene {
seconds
}
gallery {
galleries {
id
path
title
@@ -46,6 +53,15 @@ fragment SlimSceneData on Scene {
image_path
}
movies {
movie {
id
name
front_image_path
}
scene_index
}
tags {
id
name
@@ -54,7 +70,13 @@ fragment SlimSceneData on Scene {
performers {
id
name
gender
favorite
image_path
}
stash_ids {
endpoint
stash_id
}
}

View File

@@ -1,12 +1,17 @@
fragment SceneData on Scene {
id
checksum
oshash
title
details
url
date
rating
o_counter
organized
path
phash
interactive
file {
size
@@ -26,27 +31,39 @@ fragment SceneData on Scene {
webp
vtt
chapters_vtt
sprite
funscript
}
scene_markers {
...SceneMarkerData
}
is_streamable
gallery {
...GalleryData
galleries {
...SlimGalleryData
}
studio {
...StudioData
...SlimStudioData
}
movies {
movie {
...MovieData
}
scene_index
}
tags {
...TagData
...SlimTagData
}
performers {
...PerformerData
}
stash_ids {
endpoint
stash_id
}
}

View File

@@ -1,22 +1,6 @@
fragment ScrapedPerformerData on ScrapedPerformer {
name
url
birthdate
ethnicity
country
eye_color
height
measurements
fake_tits
career_length
tattoos
piercings
aliases
}
fragment ScrapedScenePerformerData on ScrapedScenePerformer {
id
name
gender
url
twitter
instagram
@@ -31,16 +15,90 @@ fragment ScrapedScenePerformerData on ScrapedScenePerformer {
tattoos
piercings
aliases
tags {
...ScrapedSceneTagData
}
image
details
death_date
hair_color
weight
remote_site_id
}
fragment ScrapedSceneStudioData on ScrapedSceneStudio {
fragment ScrapedScenePerformerData on ScrapedScenePerformer {
stored_id
name
gender
url
twitter
instagram
birthdate
ethnicity
country
eye_color
height
measurements
fake_tits
career_length
tattoos
piercings
aliases
tags {
...ScrapedSceneTagData
}
remote_site_id
images
details
death_date
hair_color
weight
}
fragment ScrapedMovieStudioData on ScrapedMovieStudio {
id
name
url
}
fragment ScrapedMovieData on ScrapedMovie {
name
aliases
duration
date
rating
director
url
synopsis
front_image
back_image
studio {
...ScrapedMovieStudioData
}
}
fragment ScrapedSceneMovieData on ScrapedSceneMovie {
stored_id
name
aliases
duration
date
rating
director
url
synopsis
}
fragment ScrapedSceneStudioData on ScrapedSceneStudio {
stored_id
name
url
remote_site_id
}
fragment ScrapedSceneTagData on ScrapedSceneTag {
id
stored_id
name
}
@@ -49,6 +107,7 @@ fragment ScrapedSceneData on ScrapedScene {
details
url
date
image
file {
size
@@ -72,4 +131,77 @@ fragment ScrapedSceneData on ScrapedScene {
performers {
...ScrapedScenePerformerData
}
}
movies {
...ScrapedSceneMovieData
}
}
fragment ScrapedGalleryData on ScrapedGallery {
title
details
url
date
studio {
...ScrapedSceneStudioData
}
tags {
...ScrapedSceneTagData
}
performers {
...ScrapedScenePerformerData
}
}
fragment ScrapedStashBoxSceneData on ScrapedScene {
title
details
url
date
image
remote_site_id
duration
file {
size
duration
video_codec
audio_codec
width
height
framerate
bitrate
}
fingerprints {
hash
algorithm
duration
}
studio {
...ScrapedSceneStudioData
}
tags {
...ScrapedSceneTagData
}
performers {
...ScrapedScenePerformerData
}
movies {
...ScrapedSceneMovieData
}
}
fragment ScrapedStashBoxPerformerData on StashBoxPerformerQueryResult {
query
results {
...ScrapedScenePerformerData
}
}

View File

@@ -2,4 +2,13 @@ fragment SlimStudioData on Studio {
id
name
image_path
}
stash_ids {
endpoint
stash_id
}
parent_studio {
id
}
details
rating
}

View File

@@ -3,6 +3,25 @@ fragment StudioData on Studio {
checksum
name
url
parent_studio {
id
name
url
image_path
}
child_studios {
id
name
image_path
}
image_path
scene_count
image_count
gallery_count
stash_ids {
stash_id
endpoint
}
details
rating
}

View File

@@ -0,0 +1,6 @@
fragment SlimTagData on Tag {
id
name
aliases
image_path
}

View File

@@ -1,6 +1,11 @@
fragment TagData on Tag {
id
name
aliases
image_path
scene_count
scene_marker_count
image_count
gallery_count
performer_count
}

View File

@@ -1,3 +1,11 @@
mutation Setup($input: SetupInput!) {
setup(input: $input)
}
mutation Migrate($input: MigrateInput!) {
migrate(input: $input)
}
mutation ConfigureGeneral($input: ConfigGeneralInput!) {
configureGeneral(input: $input) {
...ConfigGeneralData
@@ -8,4 +16,20 @@ mutation ConfigureInterface($input: ConfigInterfaceInput!) {
configureInterface(input: $input) {
...ConfigInterfaceData
}
}
}
mutation ConfigureDLNA($input: ConfigDLNAInput!) {
configureDLNA(input: $input) {
...ConfigDLNAData
}
}
mutation ConfigureScraping($input: ConfigScrapingInput!) {
configureScraping(input: $input) {
...ConfigScrapingData
}
}
mutation GenerateAPIKey($input: GenerateAPIKeyInput!) {
generateAPIKey(input: $input)
}

View File

@@ -0,0 +1,15 @@
mutation EnableDLNA($input: EnableDLNAInput!) {
enableDLNA(input: $input)
}
mutation DisableDLNA($input: DisableDLNAInput!) {
disableDLNA(input: $input)
}
mutation AddTempDLNAIP($input: AddTempDLNAIPInput!) {
addTempDLNAIP(input: $input)
}
mutation RemoveTempDLNAIP($input: RemoveTempDLNAIPInput!) {
removeTempDLNAIP(input: $input)
}

View File

@@ -0,0 +1,13 @@
mutation SaveFilter($input: SaveFilterInput!) {
saveFilter(input: $input) {
...SavedFilterData
}
}
mutation DestroySavedFilter($input: DestroyFilterInput!) {
destroySavedFilter(input: $input)
}
mutation SetDefaultFilter($input: SetDefaultFilterInput!) {
setDefaultFilter(input: $input)
}

View File

@@ -0,0 +1,41 @@
mutation GalleryCreate(
$input: GalleryCreateInput!) {
galleryCreate(input: $input) {
...GalleryData
}
}
mutation GalleryUpdate(
$input: GalleryUpdateInput!) {
galleryUpdate(input: $input) {
...GalleryData
}
}
mutation BulkGalleryUpdate(
$input: BulkGalleryUpdateInput!) {
bulkGalleryUpdate(input: $input) {
...GalleryData
}
}
mutation GalleriesUpdate($input : [GalleryUpdateInput!]!) {
galleriesUpdate(input: $input) {
...GalleryData
}
}
mutation GalleryDestroy($ids: [ID!]!, $delete_file: Boolean, $delete_generated : Boolean) {
galleryDestroy(input: {ids: $ids, delete_file: $delete_file, delete_generated: $delete_generated})
}
mutation AddGalleryImages($gallery_id: ID!, $image_ids: [ID!]!) {
addGalleryImages(input: {gallery_id: $gallery_id, image_ids: $image_ids})
}
mutation RemoveGalleryImages($gallery_id: ID!, $image_ids: [ID!]!) {
removeGalleryImages(input: {gallery_id: $gallery_id, image_ids: $image_ids})
}

View File

@@ -0,0 +1,41 @@
mutation ImageUpdate(
$input: ImageUpdateInput!) {
imageUpdate(input: $input) {
...SlimImageData
}
}
mutation BulkImageUpdate(
$input: BulkImageUpdateInput!) {
bulkImageUpdate(input: $input) {
...SlimImageData
}
}
mutation ImagesUpdate($input : [ImageUpdateInput!]!) {
imagesUpdate(input: $input) {
...SlimImageData
}
}
mutation ImageIncrementO($id: ID!) {
imageIncrementO(id: $id)
}
mutation ImageDecrementO($id: ID!) {
imageDecrementO(id: $id)
}
mutation ImageResetO($id: ID!) {
imageResetO(id: $id)
}
mutation ImageDestroy($id: ID!, $delete_file: Boolean, $delete_generated : Boolean) {
imageDestroy(input: {id: $id, delete_file: $delete_file, delete_generated: $delete_generated})
}
mutation ImagesDestroy($ids: [ID!]!, $delete_file: Boolean, $delete_generated : Boolean) {
imagesDestroy(input: {ids: $ids, delete_file: $delete_file, delete_generated: $delete_generated})
}

View File

@@ -0,0 +1,7 @@
mutation StopJob($job_id: ID!) {
stopJob(job_id: $job_id)
}
mutation StopAllJobs {
stopAllJobs
}

View File

@@ -0,0 +1,39 @@
mutation MetadataImport {
metadataImport
}
mutation MetadataExport {
metadataExport
}
mutation ExportObjects($input: ExportObjectsInput!) {
exportObjects(input: $input)
}
mutation ImportObjects($input: ImportObjectsInput!) {
importObjects(input: $input)
}
mutation MetadataScan($input: ScanMetadataInput!) {
metadataScan(input: $input)
}
mutation MetadataGenerate($input: GenerateMetadataInput!) {
metadataGenerate(input: $input)
}
mutation MetadataAutoTag($input: AutoTagMetadataInput!) {
metadataAutoTag(input: $input)
}
mutation MetadataClean($input: CleanMetadataInput!) {
metadataClean(input: $input)
}
mutation MigrateHashNaming {
migrateHashNaming
}
mutation BackupDatabase($input: BackupDatabaseInput!) {
backupDatabase(input: $input)
}

View File

@@ -0,0 +1,31 @@
mutation MovieCreate(
$name: String!,
$aliases: String,
$duration: Int,
$date: String,
$rating: Int,
$studio_id: ID,
$director: String,
$synopsis: String,
$url: String,
$front_image: String,
$back_image: String) {
movieCreate(input: { name: $name, aliases: $aliases, duration: $duration, date: $date, rating: $rating, studio_id: $studio_id, director: $director, synopsis: $synopsis, url: $url, front_image: $front_image, back_image: $back_image }) {
...MovieData
}
}
mutation MovieUpdate($input: MovieUpdateInput!) {
movieUpdate(input: $input) {
...MovieData
}
}
mutation MovieDestroy($id: ID!) {
movieDestroy(input: { id: $id })
}
mutation MoviesDestroy($ids: [ID!]!) {
moviesDestroy(ids: $ids)
}

View File

@@ -1,89 +1,31 @@
mutation PerformerCreate(
$name: String,
$url: String,
$birthdate: String,
$ethnicity: String,
$country: String,
$eye_color: String,
$height: String,
$measurements: String,
$fake_tits: String,
$career_length: String,
$tattoos: String,
$piercings: String,
$aliases: String,
$twitter: String,
$instagram: String,
$favorite: Boolean,
$image: String) {
$input: PerformerCreateInput!) {
performerCreate(input: {
name: $name,
url: $url,
birthdate: $birthdate,
ethnicity: $ethnicity,
country: $country,
eye_color: $eye_color,
height: $height,
measurements: $measurements,
fake_tits: $fake_tits,
career_length: $career_length,
tattoos: $tattoos,
piercings: $piercings,
aliases: $aliases,
twitter: $twitter,
instagram: $instagram,
favorite: $favorite,
image: $image
}) {
performerCreate(input: $input) {
...PerformerData
}
}
mutation PerformerUpdate(
$id: ID!,
$name: String,
$url: String,
$birthdate: String,
$ethnicity: String,
$country: String,
$eye_color: String,
$height: String,
$measurements: String,
$fake_tits: String,
$career_length: String,
$tattoos: String,
$piercings: String,
$aliases: String,
$twitter: String,
$instagram: String,
$favorite: Boolean,
$image: String) {
$input: PerformerUpdateInput!) {
performerUpdate(input: {
id: $id,
name: $name,
url: $url,
birthdate: $birthdate,
ethnicity: $ethnicity,
country: $country,
eye_color: $eye_color,
height: $height,
measurements: $measurements,
fake_tits: $fake_tits,
career_length: $career_length,
tattoos: $tattoos,
piercings: $piercings,
aliases: $aliases,
twitter: $twitter,
instagram: $instagram,
favorite: $favorite,
image: $image
}) {
performerUpdate(input: $input) {
...PerformerData
}
}
mutation BulkPerformerUpdate(
$input: BulkPerformerUpdateInput!) {
bulkPerformerUpdate(input: $input) {
...PerformerData
}
}
mutation PerformerDestroy($id: ID!) {
performerDestroy(input: { id: $id })
}
}
mutation PerformersDestroy($ids: [ID!]!) {
performersDestroy(ids: $ids)
}

View File

@@ -0,0 +1,7 @@
mutation ReloadPlugins {
reloadPlugins
}
mutation RunPluginTask($plugin_id: ID!, $task_name: String!, $args: [PluginArgInput!]) {
runPluginTask(plugin_id: $plugin_id, task_name: $task_name, args: $args)
}

View File

@@ -1,58 +1,16 @@
mutation SceneUpdate(
$id: ID!,
$title: String,
$details: String,
$url: String,
$date: String,
$rating: Int,
$studio_id: ID,
$gallery_id: ID,
$performer_ids: [ID!] = [],
$tag_ids: [ID!] = [],
$cover_image: String) {
$input: SceneUpdateInput!) {
sceneUpdate(input: {
id: $id,
title: $title,
details: $details,
url: $url,
date: $date,
rating: $rating,
studio_id: $studio_id,
gallery_id: $gallery_id,
performer_ids: $performer_ids,
tag_ids: $tag_ids,
cover_image: $cover_image
}) {
...SceneData
sceneUpdate(input: $input) {
...SceneData
}
}
mutation BulkSceneUpdate(
$ids: [ID!] = [],
$title: String,
$details: String,
$url: String,
$date: String,
$rating: Int,
$studio_id: ID,
$gallery_id: ID,
$performer_ids: [ID!],
$tag_ids: [ID!]) {
$input: BulkSceneUpdateInput!) {
bulkSceneUpdate(input: {
ids: $ids,
title: $title,
details: $details,
url: $url,
date: $date,
rating: $rating,
studio_id: $studio_id,
gallery_id: $gallery_id,
performer_ids: $performer_ids,
tag_ids: $tag_ids
}) {
...SceneData
bulkSceneUpdate(input: $input) {
...SceneData
}
}
@@ -62,6 +20,26 @@ mutation ScenesUpdate($input : [SceneUpdateInput!]!) {
}
}
mutation SceneIncrementO($id: ID!) {
sceneIncrementO(id: $id)
}
mutation SceneDecrementO($id: ID!) {
sceneDecrementO(id: $id)
}
mutation SceneResetO($id: ID!) {
sceneResetO(id: $id)
}
mutation SceneDestroy($id: ID!, $delete_file: Boolean, $delete_generated : Boolean) {
sceneDestroy(input: {id: $id, delete_file: $delete_file, delete_generated: $delete_generated})
}
}
mutation ScenesDestroy($ids: [ID!]!, $delete_file: Boolean, $delete_generated : Boolean) {
scenesDestroy(input: {ids: $ids, delete_file: $delete_file, delete_generated: $delete_generated})
}
mutation SceneGenerateScreenshot($id: ID!, $at: Float) {
sceneGenerateScreenshot(id: $id, at: $at)
}

View File

@@ -0,0 +1,3 @@
mutation ReloadScrapers {
reloadScrapers
}

View File

@@ -0,0 +1,7 @@
mutation SubmitStashBoxFingerprints($input: StashBoxFingerprintSubmissionInput!) {
submitStashBoxFingerprints(input: $input)
}
mutation StashBoxBatchPerformerTag($input: StashBoxBatchPerformerTagInput!) {
stashBoxBatchPerformerTag(input: $input)
}

View File

@@ -1,24 +1,19 @@
mutation StudioCreate(
$name: String!,
$url: String,
$image: String) {
studioCreate(input: { name: $name, url: $url, image: $image }) {
mutation StudioCreate($input: StudioCreateInput!) {
studioCreate(input: $input) {
...StudioData
}
}
mutation StudioUpdate(
$id: ID!
$name: String,
$url: String,
$image: String) {
studioUpdate(input: { id: $id, name: $name, url: $url, image: $image }) {
mutation StudioUpdate($input: StudioUpdateInput!) {
studioUpdate(input: $input) {
...StudioData
}
}
mutation StudioDestroy($id: ID!) {
studioDestroy(input: { id: $id })
}
}
mutation StudiosDestroy($ids: [ID!]!) {
studiosDestroy(ids: $ids)
}

View File

@@ -1,5 +1,5 @@
mutation TagCreate($name: String!) {
tagCreate(input: { name: $name }) {
mutation TagCreate($input: TagCreateInput!) {
tagCreate(input: $input) {
...TagData
}
}
@@ -8,8 +8,18 @@ mutation TagDestroy($id: ID!) {
tagDestroy(input: { id: $id })
}
mutation TagUpdate($id: ID!, $name: String!) {
tagUpdate(input: { id: $id, name: $name }) {
mutation TagsDestroy($ids: [ID!]!) {
tagsDestroy(ids: $ids)
}
mutation TagUpdate($input: TagUpdateInput!) {
tagUpdate(input: $input) {
...TagData
}
}
}
mutation TagsMerge($source: [ID!]!, $destination: ID!) {
tagsMerge(input: { source: $source, destination: $destination }) {
...TagData
}
}

View File

@@ -0,0 +1,11 @@
query DLNAStatus {
dlnaStatus {
running
until
recentIPAddresses
allowedIPAddresses {
ipAddress
until
}
}
}

View File

@@ -0,0 +1,11 @@
query FindSavedFilters($mode: FilterMode!) {
findSavedFilters(mode: $mode) {
...SavedFilterData
}
}
query FindDefaultFilter($mode: FilterMode!) {
findDefaultFilter(mode: $mode) {
...SavedFilterData
}
}

View File

@@ -1,8 +1,8 @@
query FindGalleries($filter: FindFilterType) {
findGalleries(filter: $filter) {
query FindGalleries($filter: FindFilterType, $gallery_filter: GalleryFilterType) {
findGalleries(gallery_filter: $gallery_filter, filter: $filter) {
count
galleries {
...GalleryData
...SlimGalleryData
}
}
}
@@ -11,4 +11,4 @@ query FindGallery($id: ID!) {
findGallery(id: $id) {
...GalleryData
}
}
}

View File

@@ -0,0 +1,14 @@
query FindImages($filter: FindFilterType, $image_filter: ImageFilterType, $image_ids: [Int!]) {
findImages(filter: $filter, image_filter: $image_filter, image_ids: $image_ids) {
count
images {
...SlimImageData
}
}
}
query FindImage($id: ID!, $checksum: String) {
findImage(id: $id, checksum: $checksum) {
...ImageData
}
}

View File

@@ -0,0 +1,11 @@
query JobQueue {
jobQueue {
...JobData
}
}
query FindJob($input: FindJobInput!) {
findJob(input: $input) {
...JobData
}
}

View File

@@ -1,9 +1,3 @@
query FindTag($id: ID!) {
findTag(id: $id) {
...TagData
}
}
query MarkerStrings($q: String, $sort: String) {
markerStrings(q: $q, sort: $sort) {
id
@@ -29,27 +23,31 @@ query AllStudiosForFilter {
...SlimStudioData
}
}
query AllMoviesForFilter {
allMovies {
...SlimMovieData
}
}
query AllTagsForFilter {
allTags {
id
name
}
}
query ValidGalleriesForScene($scene_id: ID!) {
validGalleriesForScene(scene_id: $scene_id) {
id
path
aliases
}
}
query Stats {
stats {
scene_count,
scenes_size,
scenes_duration,
image_count,
images_size,
gallery_count,
performer_count,
studio_count,
movie_count,
tag_count
}
}
@@ -66,3 +64,10 @@ query Version {
build_time
}
}
query LatestVersion {
latestversion {
shorthash
url
}
}

View File

@@ -0,0 +1,14 @@
query FindMovies($filter: FindFilterType, $movie_filter: MovieFilterType) {
findMovies(filter: $filter, movie_filter: $movie_filter) {
count
movies {
...MovieData
}
}
}
query FindMovie($id: ID!) {
findMovie(id: $id) {
...MovieData
}
}

View File

@@ -11,4 +11,4 @@ query FindPerformer($id: ID!) {
findPerformer(id: $id) {
...PerformerData
}
}
}

View File

@@ -0,0 +1,31 @@
query Plugins {
plugins {
id
name
description
url
version
tasks {
name
description
}
hooks {
name
description
hooks
}
}
}
query PluginTasks {
pluginTasks {
name
description
plugin {
id
name
}
}
}

View File

@@ -16,6 +16,12 @@ query FindScenesByPathRegex($filter: FindFilterType) {
}
}
query FindDuplicateScenes($distance: Int) {
findDuplicateScenes(distance: $distance) {
...SlimSceneData
}
}
query FindScene($id: ID!, $checksum: String) {
findScene(id: $id, checksum: $checksum) {
...SceneData
@@ -45,9 +51,20 @@ query ParseSceneFilenames($filter: FindFilterType!, $config: SceneParserInput!)
date
rating
studio_id
gallery_id
gallery_ids
movies {
movie_id
}
performer_ids
tag_ids
}
}
}
}
query SceneStreams($id: ID!) {
sceneStreams(id: $id) {
url
mime_type
label
}
}

View File

@@ -15,6 +15,10 @@ query ScrapeFreeones($performer_name: String!) {
tattoos
piercings
aliases
details
death_date
hair_color
weight
}
}

View File

@@ -20,6 +20,28 @@ query ListSceneScrapers {
}
}
query ListGalleryScrapers {
listGalleryScrapers {
id
name
gallery {
urls
supported_scrapes
}
}
}
query ListMovieScrapers {
listMovieScrapers {
id
name
movie {
urls
supported_scrapes
}
}
}
query ScrapePerformerList($scraper_id: ID!, $query: String!) {
scrapePerformerList(scraper_id: $scraper_id, query: $query) {
...ScrapedPerformerData
@@ -48,4 +70,34 @@ query ScrapeSceneURL($url: String!) {
scrapeSceneURL(url: $url) {
...ScrapedSceneData
}
}
}
query ScrapeGallery($scraper_id: ID!, $gallery: GalleryUpdateInput!) {
scrapeGallery(scraper_id: $scraper_id, gallery: $gallery) {
...ScrapedGalleryData
}
}
query ScrapeGalleryURL($url: String!) {
scrapeGalleryURL(url: $url) {
...ScrapedGalleryData
}
}
query ScrapeMovieURL($url: String!) {
scrapeMovieURL(url: $url) {
...ScrapedMovieData
}
}
query QueryStashBoxScene($input: StashBoxSceneQueryInput!) {
queryStashBoxScene(input: $input) {
...ScrapedStashBoxSceneData
}
}
query QueryStashBoxPerformer($input: StashBoxPerformerQueryInput!) {
queryStashBoxPerformer(input: $input) {
...ScrapedStashBoxPerformerData
}
}

View File

@@ -4,6 +4,10 @@ query Configuration {
}
}
query Directories($path: String) {
directories(path: $path)
}
query Directory($path: String) {
directory(path: $path) {
path
parent
directories
}
}

View File

@@ -1,35 +1,9 @@
query MetadataImport {
metadataImport
}
query MetadataExport {
metadataExport
}
query MetadataScan($input: ScanMetadataInput!) {
metadataScan(input: $input)
}
query MetadataGenerate($input: GenerateMetadataInput!) {
metadataGenerate(input: $input)
}
query MetadataAutoTag($input: AutoTagMetadataInput!) {
metadataAutoTag(input: $input)
}
query MetadataClean {
metadataClean
}
query JobStatus {
jobStatus {
progress
query SystemStatus {
systemStatus {
databaseSchema
databasePath
appSchema
status
message
configPath
}
}
query StopJob {
stopJob
}

View File

@@ -1,5 +1,5 @@
query FindStudios($filter: FindFilterType) {
findStudios(filter: $filter) {
query FindStudios($filter: FindFilterType, $studio_filter: StudioFilterType ) {
findStudios(filter: $filter, studio_filter: $studio_filter) {
count
studios {
...StudioData
@@ -11,4 +11,4 @@ query FindStudio($id: ID!) {
findStudio(id: $id) {
...StudioData
}
}
}

View File

@@ -0,0 +1,14 @@
query FindTags($filter: FindFilterType, $tag_filter: TagFilterType ) {
findTags(filter: $filter, tag_filter: $tag_filter) {
count
tags {
...TagData
}
}
}
query FindTag($id: ID!) {
findTag(id: $id) {
...TagData
}
}

View File

@@ -1,8 +1,13 @@
subscription MetadataUpdate {
metadataUpdate {
progress
status
message
subscription JobsSubscribe {
jobsSubscribe {
type
job {
id
status
subTasks
description
progress
}
}
}
@@ -10,4 +15,8 @@ subscription LoggingSubscribe {
loggingSubscribe {
...LogEntryData
}
}
subscription ScanCompleteSubscribe {
scanCompleteSubscribe
}

View File

@@ -1,17 +1,34 @@
"""The query root for this schema"""
type Query {
# Filters
findSavedFilters(mode: FilterMode!): [SavedFilter!]!
findDefaultFilter(mode: FilterMode!): SavedFilter
"""Find a scene by ID or Checksum"""
findScene(id: ID, checksum: String): Scene
findSceneByHash(input: SceneHashInput!): Scene
"""A function which queries Scene objects"""
findScenes(scene_filter: SceneFilterType, scene_ids: [Int!], filter: FindFilterType): FindScenesResultType!
findScenesByPathRegex(filter: FindFilterType): FindScenesResultType!
""" Returns any groups of scenes that are perceptual duplicates within the queried distance """
findDuplicateScenes(distance: Int): [[Scene!]!]!
"""Return valid stream paths"""
sceneStreams(id: ID): [SceneStreamEndpoint!]!
parseSceneFilenames(filter: FindFilterType, config: SceneParserInput!): SceneParserResultType!
"""A function which queries SceneMarker objects"""
findSceneMarkers(scene_marker_filter: SceneMarkerFilterType filter: FindFilterType): FindSceneMarkersResultType!
findImage(id: ID, checksum: String): Image
"""A function which queries Scene objects"""
findImages(image_filter: ImageFilterType, image_ids: [Int!], filter: FindFilterType): FindImagesResultType!
"""Find a performer by ID"""
findPerformer(id: ID!): Performer
"""A function which queries Performer objects"""
@@ -20,12 +37,18 @@ type Query {
"""Find a studio by ID"""
findStudio(id: ID!): Studio
"""A function which queries Studio objects"""
findStudios(filter: FindFilterType): FindStudiosResultType!
findStudios(studio_filter: StudioFilterType, filter: FindFilterType): FindStudiosResultType!
"""Find a movie by ID"""
findMovie(id: ID!): Movie
"""A function which queries Movie objects"""
findMovies(movie_filter: MovieFilterType, filter: FindFilterType): FindMoviesResultType!
findGallery(id: ID!): Gallery
findGalleries(filter: FindFilterType): FindGalleriesResultType!
findGalleries(gallery_filter: GalleryFilterType, filter: FindFilterType): FindGalleriesResultType!
findTag(id: ID!): Tag
findTags(tag_filter: TagFilterType, filter: FindFilterType): FindTagsResultType!
"""Retrieve random scene markers for the wall"""
markerWall(q: String): [SceneMarker!]!
@@ -34,8 +57,6 @@ type Query {
"""Get marker strings"""
markerStrings(q: String, sort: String): [MarkerStringsResultType]!
"""Get the list of valid galleries for a given scene ID"""
validGalleriesForScene(scene_id: ID): [Gallery!]!
"""Get stats"""
stats: StatsResultType!
"""Organize scene markers by tag for a given scene ID"""
@@ -48,6 +69,9 @@ type Query {
"""List available scrapers"""
listPerformerScrapers: [Scraper!]!
listSceneScrapers: [Scraper!]!
listGalleryScrapers: [Scraper!]!
listMovieScrapers: [Scraper!]!
"""Scrape a list of performers based on name"""
scrapePerformerList(scraper_id: ID!, query: String!): [ScrapedPerformer!]!
"""Scrapes a complete performer record based on a scrapePerformerList result"""
@@ -58,82 +82,202 @@ type Query {
scrapeScene(scraper_id: ID!, scene: SceneUpdateInput!): ScrapedScene
"""Scrapes a complete performer record based on a URL"""
scrapeSceneURL(url: String!): ScrapedScene
"""Scrapes a complete gallery record based on an existing gallery"""
scrapeGallery(scraper_id: ID!, gallery: GalleryUpdateInput!): ScrapedGallery
"""Scrapes a complete gallery record based on a URL"""
scrapeGalleryURL(url: String!): ScrapedGallery
"""Scrapes a complete movie record based on a URL"""
scrapeMovieURL(url: String!): ScrapedMovie
"""Scrape a performer using Freeones"""
scrapeFreeones(performer_name: String!): ScrapedPerformer
"""Scrape a list of performers from a query"""
scrapeFreeonesPerformerList(query: String!): [String!]!
"""Query StashBox for scenes"""
queryStashBoxScene(input: StashBoxSceneQueryInput!): [ScrapedScene!]!
queryStashBoxPerformer(input: StashBoxPerformerQueryInput!): [StashBoxPerformerQueryResult!]!
# Plugins
"""List loaded plugins"""
plugins: [Plugin!]
"""List available plugin operations"""
pluginTasks: [PluginTask!]
# Config
"""Returns the current, complete configuration"""
configuration: ConfigResult!
"""Returns an array of paths for the given path"""
directories(path: String): [String!]!
directory(path: String): Directory!
# Metadata
# System status
systemStatus: SystemStatus!
"""Start an import. Returns the job ID"""
metadataImport: String!
"""Start an export. Returns the job ID"""
metadataExport: String!
"""Start a scan. Returns the job ID"""
metadataScan(input: ScanMetadataInput!): String!
"""Start generating content. Returns the job ID"""
metadataGenerate(input: GenerateMetadataInput!): String!
"""Start auto-tagging. Returns the job ID"""
metadataAutoTag(input: AutoTagMetadataInput!): String!
"""Clean metadata. Returns the job ID"""
metadataClean: String!
# Job status
jobQueue: [Job!]
findJob(input: FindJobInput!): Job
jobStatus: MetadataUpdateStatus!
stopJob: Boolean!
dlnaStatus: DLNAStatus!
# Get everything
allPerformers: [Performer!]!
allStudios: [Studio!]!
allMovies: [Movie!]!
allTags: [Tag!]!
# Get everything with minimal metadata
# Version
version: Version!
# LatestVersion
latestversion: ShortVersion!
}
type Mutation {
setup(input: SetupInput!): Boolean!
migrate(input: MigrateInput!): Boolean!
sceneUpdate(input: SceneUpdateInput!): Scene
bulkSceneUpdate(input: BulkSceneUpdateInput!): [Scene!]
sceneDestroy(input: SceneDestroyInput!): Boolean!
scenesDestroy(input: ScenesDestroyInput!): Boolean!
scenesUpdate(input: [SceneUpdateInput!]!): [Scene]
"""Increments the o-counter for a scene. Returns the new value"""
sceneIncrementO(id: ID!): Int!
"""Decrements the o-counter for a scene. Returns the new value"""
sceneDecrementO(id: ID!): Int!
"""Resets the o-counter for a scene to 0. Returns the new value"""
sceneResetO(id: ID!): Int!
"""Generates screenshot at specified time in seconds. Leave empty to generate default screenshot"""
sceneGenerateScreenshot(id: ID!, at: Float): String!
sceneMarkerCreate(input: SceneMarkerCreateInput!): SceneMarker
sceneMarkerUpdate(input: SceneMarkerUpdateInput!): SceneMarker
sceneMarkerDestroy(id: ID!): Boolean!
imageUpdate(input: ImageUpdateInput!): Image
bulkImageUpdate(input: BulkImageUpdateInput!): [Image!]
imageDestroy(input: ImageDestroyInput!): Boolean!
imagesDestroy(input: ImagesDestroyInput!): Boolean!
imagesUpdate(input: [ImageUpdateInput!]!): [Image]
"""Increments the o-counter for an image. Returns the new value"""
imageIncrementO(id: ID!): Int!
"""Decrements the o-counter for an image. Returns the new value"""
imageDecrementO(id: ID!): Int!
"""Resets the o-counter for a image to 0. Returns the new value"""
imageResetO(id: ID!): Int!
galleryCreate(input: GalleryCreateInput!): Gallery
galleryUpdate(input: GalleryUpdateInput!): Gallery
bulkGalleryUpdate(input: BulkGalleryUpdateInput!): [Gallery!]
galleryDestroy(input: GalleryDestroyInput!): Boolean!
galleriesUpdate(input: [GalleryUpdateInput!]!): [Gallery]
addGalleryImages(input: GalleryAddInput!): Boolean!
removeGalleryImages(input: GalleryRemoveInput!): Boolean!
performerCreate(input: PerformerCreateInput!): Performer
performerUpdate(input: PerformerUpdateInput!): Performer
performerDestroy(input: PerformerDestroyInput!): Boolean!
performersDestroy(ids: [ID!]!): Boolean!
bulkPerformerUpdate(input: BulkPerformerUpdateInput!): [Performer!]
studioCreate(input: StudioCreateInput!): Studio
studioUpdate(input: StudioUpdateInput!): Studio
studioDestroy(input: StudioDestroyInput!): Boolean!
studiosDestroy(ids: [ID!]!): Boolean!
movieCreate(input: MovieCreateInput!): Movie
movieUpdate(input: MovieUpdateInput!): Movie
movieDestroy(input: MovieDestroyInput!): Boolean!
moviesDestroy(ids: [ID!]!): Boolean!
tagCreate(input: TagCreateInput!): Tag
tagUpdate(input: TagUpdateInput!): Tag
tagDestroy(input: TagDestroyInput!): Boolean!
tagsDestroy(ids: [ID!]!): Boolean!
tagsMerge(input: TagsMergeInput!): Tag
# Saved filters
saveFilter(input: SaveFilterInput!): SavedFilter!
destroySavedFilter(input: DestroyFilterInput!): Boolean!
setDefaultFilter(input: SetDefaultFilterInput!): Boolean!
"""Change general configuration options"""
configureGeneral(input: ConfigGeneralInput!): ConfigGeneralResult!
configureInterface(input: ConfigInterfaceInput!): ConfigInterfaceResult!
configureDLNA(input: ConfigDLNAInput!): ConfigDLNAResult!
configureScraping(input: ConfigScrapingInput!): ConfigScrapingResult!
"""Generate and set (or clear) API key"""
generateAPIKey(input: GenerateAPIKeyInput!): String!
"""Returns a link to download the result"""
exportObjects(input: ExportObjectsInput!): String
"""Performs an incremental import. Returns the job ID"""
importObjects(input: ImportObjectsInput!): ID!
"""Start an full import. Completely wipes the database and imports from the metadata directory. Returns the job ID"""
metadataImport: ID!
"""Start a full export. Outputs to the metadata directory. Returns the job ID"""
metadataExport: ID!
"""Start a scan. Returns the job ID"""
metadataScan(input: ScanMetadataInput!): ID!
"""Start generating content. Returns the job ID"""
metadataGenerate(input: GenerateMetadataInput!): ID!
"""Start auto-tagging. Returns the job ID"""
metadataAutoTag(input: AutoTagMetadataInput!): ID!
"""Clean metadata. Returns the job ID"""
metadataClean(input: CleanMetadataInput!): ID!
"""Migrate generated files for the current hash naming"""
migrateHashNaming: ID!
"""Reload scrapers"""
reloadScrapers: Boolean!
"""Run plugin task. Returns the job ID"""
runPluginTask(plugin_id: ID!, task_name: String!, args: [PluginArgInput!]): ID!
reloadPlugins: Boolean!
stopJob(job_id: ID!): Boolean!
stopAllJobs: Boolean!
"""Submit fingerprints to stash-box instance"""
submitStashBoxFingerprints(input: StashBoxFingerprintSubmissionInput!): Boolean!
"""Backup the database. Optionally returns a link to download the database file"""
backupDatabase(input: BackupDatabaseInput!): String
"""Run batch performer tag task. Returns the job ID."""
stashBoxBatchPerformerTag(input: StashBoxBatchPerformerTagInput!): String!
"""Enables DLNA for an optional duration. Has no effect if DLNA is enabled by default"""
enableDLNA(input: EnableDLNAInput!): Boolean!
"""Disables DLNA for an optional duration. Has no effect if DLNA is disabled by default"""
disableDLNA(input: DisableDLNAInput!): Boolean!
"""Enables an IP address for DLNA for an optional duration"""
addTempDLNAIP(input: AddTempDLNAIPInput!): Boolean!
"""Removes an IP address from the temporary DLNA whitelist"""
removeTempDLNAIP(input: RemoveTempDLNAIPInput!): Boolean!
}
type Subscription {
"""Update from the metadata manager"""
metadataUpdate: MetadataUpdateStatus!
jobsSubscribe: JobStatusUpdate!
loggingSubscribe: [LogEntry!]!
scanCompleteSubscribe: Boolean!
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
}

View File

@@ -1,3 +1,13 @@
input SetupInput {
"""Empty to indicate $HOME/.stash/config.yml default"""
configLocation: String!
stashes: [StashConfigInput!]!
"""Empty to indicate default"""
databaseFile: String!
"""Empty to indicate default"""
generatedLocation: String!
}
enum StreamingResolutionEnum {
"240p", LOW
"480p", STANDARD
@@ -7,13 +17,48 @@ enum StreamingResolutionEnum {
"Original", ORIGINAL
}
enum PreviewPreset {
"X264_ULTRAFAST", ultrafast
"X264_VERYFAST", veryfast
"X264_FAST", fast
"X264_MEDIUM", medium
"X264_SLOW", slow
"X264_SLOWER", slower
"X264_VERYSLOW", veryslow
}
enum HashAlgorithm {
MD5
"oshash", OSHASH
}
input ConfigGeneralInput {
"""Array of file paths to content"""
stashes: [String!]
stashes: [StashConfigInput!]
"""Path to the SQLite database"""
databasePath: String
"""Path to generated files"""
generatedPath: String
"""Path to cache"""
cachePath: String
"""Whether to calculate MD5 checksums for scene video files"""
calculateMD5: Boolean!
"""Hash algorithm to use for generated file naming"""
videoFileNamingAlgorithm: HashAlgorithm!
"""Number of parallel tasks to start during scan/generate"""
parallelTasks: Int
"""Include audio stream in previews"""
previewAudio: Boolean!
"""Number of segments in a preview file"""
previewSegments: Int
"""Preview segment duration, in seconds"""
previewSegmentDuration: Float
"""Duration of start of video to exclude when generating previews"""
previewExcludeStart: String
"""Duration of end of video to exclude when generating previews"""
previewExcludeEnd: String
"""Preset when generating preview"""
previewPreset: PreviewPreset
"""Max generated transcode size"""
maxTranscodeSize: StreamingResolutionEnum
"""Max streaming transcode size"""
@@ -22,6 +67,8 @@ input ConfigGeneralInput {
username: String
"""Password"""
password: String
"""Maximum session cookie age"""
maxSessionAge: Int
"""Name of the log file"""
logFile: String
"""Whether to also output to stderr"""
@@ -30,25 +77,73 @@ input ConfigGeneralInput {
logLevel: String!
"""Whether to log http access"""
logAccess: Boolean!
"""Array of file regexp to exclude from Scan"""
"""True if galleries should be created from folders with images"""
createGalleriesFromFolders: Boolean!
"""Array of video file extensions"""
videoExtensions: [String!]
"""Array of image file extensions"""
imageExtensions: [String!]
"""Array of gallery zip file extensions"""
galleryExtensions: [String!]
"""Array of file regexp to exclude from Video Scans"""
excludes: [String!]
"""Array of file regexp to exclude from Image Scans"""
imageExcludes: [String!]
"""Custom Performer Image Location"""
customPerformerImageLocation: String
"""Scraper user agent string"""
scraperUserAgent: String @deprecated(reason: "use mutation ConfigureScraping(input: ConfigScrapingInput) instead")
"""Scraper CDP path. Path to chrome executable or remote address"""
scraperCDPPath: String @deprecated(reason: "use mutation ConfigureScraping(input: ConfigScrapingInput) instead")
"""Whether the scraper should check for invalid certificates"""
scraperCertCheck: Boolean @deprecated(reason: "use mutation ConfigureScraping(input: ConfigScrapingInput) instead")
"""Stash-box instances used for tagging"""
stashBoxes: [StashBoxInput!]!
}
type ConfigGeneralResult {
"""Array of file paths to content"""
stashes: [String!]!
stashes: [StashConfig!]!
"""Path to the SQLite database"""
databasePath: String!
"""Path to generated files"""
generatedPath: String!
"""Max generated transcode size"""
"""Path to the config file used"""
configFilePath: String!
"""Path to scrapers"""
scrapersPath: String!
"""Path to cache"""
cachePath: String!
"""Whether to calculate MD5 checksums for scene video files"""
calculateMD5: Boolean!
"""Hash algorithm to use for generated file naming"""
videoFileNamingAlgorithm: HashAlgorithm!
"""Number of parallel tasks to start during scan/generate"""
parallelTasks: Int!
"""Include audio stream in previews"""
previewAudio: Boolean!
"""Number of segments in a preview file"""
previewSegments: Int!
"""Preview segment duration, in seconds"""
previewSegmentDuration: Float!
"""Duration of start of video to exclude when generating previews"""
previewExcludeStart: String!
"""Duration of end of video to exclude when generating previews"""
previewExcludeEnd: String!
"""Preset when generating preview"""
previewPreset: PreviewPreset!
"""Max generated transcode size"""
maxTranscodeSize: StreamingResolutionEnum
"""Max streaming transcode size"""
maxStreamingTranscodeSize: StreamingResolutionEnum
"""API Key"""
apiKey: String!
"""Username"""
username: String!
"""Password"""
password: String!
"""Maximum session cookie age"""
maxSessionAge: Int!
"""Name of the log file"""
logFile: String
"""Whether to also output to stderr"""
@@ -57,15 +152,39 @@ type ConfigGeneralResult {
logLevel: String!
"""Whether to log http access"""
logAccess: Boolean!
"""Array of file regexp to exclude from Scan"""
"""Array of video file extensions"""
videoExtensions: [String!]!
"""Array of image file extensions"""
imageExtensions: [String!]!
"""Array of gallery zip file extensions"""
galleryExtensions: [String!]!
"""True if galleries should be created from folders with images"""
createGalleriesFromFolders: Boolean!
"""Array of file regexp to exclude from Video Scans"""
excludes: [String!]!
"""Array of file regexp to exclude from Image Scans"""
imageExcludes: [String!]!
"""Custom Performer Image Location"""
customPerformerImageLocation: String
"""Scraper user agent string"""
scraperUserAgent: String @deprecated(reason: "use ConfigResult.scraping instead")
"""Scraper CDP path. Path to chrome executable or remote address"""
scraperCDPPath: String @deprecated(reason: "use ConfigResult.scraping instead")
"""Whether the scraper should check for invalid certificates"""
scraperCertCheck: Boolean! @deprecated(reason: "use ConfigResult.scraping instead")
"""Stash-box instances used for tagging"""
stashBoxes: [StashBox!]!
}
input ConfigInterfaceInput {
"""Ordered list of items that should be shown in the menu"""
menuItems: [String!]
"""Enable sound on mouseover previews"""
soundOnPreview: Boolean
"""Show title and tags in wall view"""
wallShowTitle: Boolean
"""Wall playback type"""
wallPlayback: String
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
maximumLoopDuration: Int
"""If true, video will autostart on load in the scene player"""
@@ -75,26 +194,114 @@ input ConfigInterfaceInput {
"""Custom CSS"""
css: String
cssEnabled: Boolean
"""Interface language"""
language: String
"""Slideshow Delay"""
slideshowDelay: Int
"""Handy Connection Key"""
handyKey: String
"""Funscript Time Offset"""
funscriptOffset: Int
}
type ConfigInterfaceResult {
"""Ordered list of items that should be shown in the menu"""
menuItems: [String!]
"""Enable sound on mouseover previews"""
soundOnPreview: Boolean
"""Show title and tags in wall view"""
wallShowTitle: Boolean
"""Wall playback type"""
wallPlayback: String
"""Maximum duration (in seconds) in which a scene video will loop in the scene player"""
maximumLoopDuration: Int
"""If true, video will autostart on load in the scene player"""
autostartVideo: Boolean
"""If true, studio overlays will be shown as text instead of logo images"""
"""If true, studio overlays will be shown as text instead of logo images"""
showStudioAsText: Boolean
"""Custom CSS"""
css: String
cssEnabled: Boolean
"""Interface language"""
language: String
"""Slideshow Delay"""
slideshowDelay: Int
"""Handy Connection Key"""
handyKey: String
"""Funscript Time Offset"""
funscriptOffset: Int
}
input ConfigDLNAInput {
serverName: String
"""True if DLNA service should be enabled by default"""
enabled: Boolean
"""List of IPs whitelisted for DLNA service"""
whitelistedIPs: [String!]
"""List of interfaces to run DLNA on. Empty for all"""
interfaces: [String!]
}
type ConfigDLNAResult {
serverName: String!
"""True if DLNA service should be enabled by default"""
enabled: Boolean!
"""List of IPs whitelisted for DLNA service"""
whitelistedIPs: [String!]!
"""List of interfaces to run DLNA on. Empty for all"""
interfaces: [String!]!
}
input ConfigScrapingInput {
"""Scraper user agent string"""
scraperUserAgent: String
"""Scraper CDP path. Path to chrome executable or remote address"""
scraperCDPPath: String
"""Whether the scraper should check for invalid certificates"""
scraperCertCheck: Boolean!
"""Tags blacklist during scraping"""
excludeTagPatterns: [String!]
}
type ConfigScrapingResult {
"""Scraper user agent string"""
scraperUserAgent: String
"""Scraper CDP path. Path to chrome executable or remote address"""
scraperCDPPath: String
"""Whether the scraper should check for invalid certificates"""
scraperCertCheck: Boolean!
"""Tags blacklist during scraping"""
excludeTagPatterns: [String!]!
}
"""All configuration settings"""
type ConfigResult {
general: ConfigGeneralResult!
interface: ConfigInterfaceResult!
dlna: ConfigDLNAResult!
scraping: ConfigScrapingResult!
}
"""Directory structure of a path"""
type Directory {
path: String!
parent: String
directories: [String!]!
}
"""Stash configuration details"""
input StashConfigInput {
path: String!
excludeVideo: Boolean!
excludeImage: Boolean!
}
type StashConfig {
path: String!
excludeVideo: Boolean!
excludeImage: Boolean!
}
input GenerateAPIKeyInput {
clear: Boolean
}

View File

@@ -0,0 +1,35 @@
type DLNAIP {
ipAddress: String!
"""Time until IP will be no longer allowed/disallowed"""
until: Time
}
type DLNAStatus {
running: Boolean!
"""If not currently running, time until it will be started. If running, time until it will be stopped"""
until: Time
recentIPAddresses: [String!]!
allowedIPAddresses: [DLNAIP!]!
}
input EnableDLNAInput {
"""Duration to enable, in minutes. 0 or null for indefinite."""
duration: Int
}
input DisableDLNAInput {
"""Duration to enable, in minutes. 0 or null for indefinite."""
duration: Int
}
input AddTempDLNAIPInput {
address: String!
"""Duration to enable, in minutes. 0 or null for indefinite."""
duration: Int
}
input RemoveTempDLNAIPInput {
address: String!
}

View File

@@ -6,20 +6,41 @@ enum SortDirectionEnum {
input FindFilterType {
q: String
page: Int
"""use per_page = -1 to indicate all results. Defaults to 25."""
per_page: Int
sort: String
direction: SortDirectionEnum
}
enum ResolutionEnum {
"144p", VERY_LOW
"240p", LOW
"360p", R360P
"480p", STANDARD
"540p", WEB_HD
"720p", STANDARD_HD
"1080p", FULL_HD
"1440p", QUAD_HD
"1920p", VR_HD
"4k", FOUR_K
"5k", FIVE_K
"6k", SIX_K
"8k", EIGHT_K
}
input ResolutionCriterionInput {
value: ResolutionEnum!
modifier: CriterionModifier!
}
input PerformerFilterType {
AND: PerformerFilterType
OR: PerformerFilterType
NOT: PerformerFilterType
name: StringCriterionInput
details: StringCriterionInput
"""Filter by favorite"""
filter_favorites: Boolean
"""Filter by birth year"""
@@ -38,7 +59,7 @@ input PerformerFilterType {
measurements: StringCriterionInput
"""Filter by fake tits value"""
fake_tits: StringCriterionInput
"""Filter by career length"""
"""Filter by career length"""
career_length: StringCriterionInput
"""Filter by tattoos"""
tattoos: StringCriterionInput
@@ -46,6 +67,34 @@ input PerformerFilterType {
piercings: StringCriterionInput
"""Filter by aliases"""
aliases: StringCriterionInput
"""Filter by gender"""
gender: GenderCriterionInput
"""Filter to only include performers missing this property"""
is_missing: String
"""Filter to only include performers with these tags"""
tags: MultiCriterionInput
"""Filter by tag count"""
tag_count: IntCriterionInput
"""Filter by scene count"""
scene_count: IntCriterionInput
"""Filter by image count"""
image_count: IntCriterionInput
"""Filter by gallery count"""
gallery_count: IntCriterionInput
"""Filter by StashID"""
stash_id: StringCriterionInput
"""Filter by rating"""
rating: IntCriterionInput
"""Filter by url"""
url: StringCriterionInput
"""Filter by hair color"""
hair_color: StringCriterionInput
"""Filter by weight"""
weight: IntCriterionInput
"""Filter by death year"""
death_year: IntCriterionInput
"""Filter by studios where performer appears in scene/image/gallery"""
studios: HierarchicalMultiCriterionInput
}
input SceneMarkerFilterType {
@@ -60,20 +109,201 @@ input SceneMarkerFilterType {
}
input SceneFilterType {
AND: SceneFilterType
OR: SceneFilterType
NOT: SceneFilterType
title: StringCriterionInput
details: StringCriterionInput
"""Filter by file oshash"""
oshash: StringCriterionInput
"""Filter by file checksum"""
checksum: StringCriterionInput
"""Filter by file phash"""
phash: StringCriterionInput
"""Filter by path"""
path: StringCriterionInput
"""Filter by rating"""
rating: IntCriterionInput
"""Filter by organized"""
organized: Boolean
"""Filter by o-counter"""
o_counter: IntCriterionInput
"""Filter by resolution"""
resolution: ResolutionEnum
resolution: ResolutionCriterionInput
"""Filter by duration (in seconds)"""
duration: IntCriterionInput
"""Filter to only include scenes which have markers. `true` or `false`"""
has_markers: String
"""Filter to only include scenes missing this property"""
is_missing: String
"""Filter to only include scenes with this studio"""
studios: MultiCriterionInput
studios: HierarchicalMultiCriterionInput
"""Filter to only include scenes with this movie"""
movies: MultiCriterionInput
"""Filter to only include scenes with these tags"""
tags: MultiCriterionInput
"""Filter by tag count"""
tag_count: IntCriterionInput
"""Filter to only include scenes with performers with these tags"""
performer_tags: MultiCriterionInput
"""Filter to only include scenes with these performers"""
performers: MultiCriterionInput
"""Filter by performer count"""
performer_count: IntCriterionInput
"""Filter by StashID"""
stash_id: StringCriterionInput
"""Filter by url"""
url: StringCriterionInput
"""Filter by interactive"""
interactive: Boolean
}
input MovieFilterType {
name: StringCriterionInput
director: StringCriterionInput
synopsis: StringCriterionInput
"""Filter by duration (in seconds)"""
duration: IntCriterionInput
"""Filter by rating"""
rating: IntCriterionInput
"""Filter to only include movies with this studio"""
studios: HierarchicalMultiCriterionInput
"""Filter to only include movies missing this property"""
is_missing: String
"""Filter by url"""
url: StringCriterionInput
}
input StudioFilterType {
name: StringCriterionInput
details: StringCriterionInput
"""Filter to only include studios with this parent studio"""
parents: MultiCriterionInput
"""Filter by StashID"""
stash_id: StringCriterionInput
"""Filter to only include studios missing this property"""
is_missing: String
"""Filter by rating"""
rating: IntCriterionInput
"""Filter by scene count"""
scene_count: IntCriterionInput
"""Filter by image count"""
image_count: IntCriterionInput
"""Filter by gallery count"""
gallery_count: IntCriterionInput
"""Filter by url"""
url: StringCriterionInput
}
input GalleryFilterType {
AND: GalleryFilterType
OR: GalleryFilterType
NOT: GalleryFilterType
title: StringCriterionInput
details: StringCriterionInput
"""Filter by file checksum"""
checksum: StringCriterionInput
"""Filter by path"""
path: StringCriterionInput
"""Filter to only include galleries missing this property"""
is_missing: String
"""Filter to include/exclude galleries that were created from zip"""
is_zip: Boolean
"""Filter by rating"""
rating: IntCriterionInput
"""Filter by organized"""
organized: Boolean
"""Filter by average image resolution"""
average_resolution: ResolutionCriterionInput
"""Filter to only include galleries with this studio"""
studios: HierarchicalMultiCriterionInput
"""Filter to only include galleries with these tags"""
tags: MultiCriterionInput
"""Filter by tag count"""
tag_count: IntCriterionInput
"""Filter to only include galleries with performers with these tags"""
performer_tags: MultiCriterionInput
"""Filter to only include galleries with these performers"""
performers: MultiCriterionInput
"""Filter by performer count"""
performer_count: IntCriterionInput
"""Filter by number of images in this gallery"""
image_count: IntCriterionInput
"""Filter by url"""
url: StringCriterionInput
}
input TagFilterType {
AND: TagFilterType
OR: TagFilterType
NOT: TagFilterType
"""Filter by tag name"""
name: StringCriterionInput
"""Filter by tag aliases"""
aliases: StringCriterionInput
"""Filter to only include tags missing this property"""
is_missing: String
"""Filter by number of scenes with this tag"""
scene_count: IntCriterionInput
"""Filter by number of images with this tag"""
image_count: IntCriterionInput
"""Filter by number of galleries with this tag"""
gallery_count: IntCriterionInput
"""Filter by number of performers with this tag"""
performer_count: IntCriterionInput
"""Filter by number of markers with this tag"""
marker_count: IntCriterionInput
}
input ImageFilterType {
AND: ImageFilterType
OR: ImageFilterType
NOT: ImageFilterType
title: StringCriterionInput
"""Filter by file checksum"""
checksum: StringCriterionInput
"""Filter by path"""
path: StringCriterionInput
"""Filter by rating"""
rating: IntCriterionInput
"""Filter by organized"""
organized: Boolean
"""Filter by o-counter"""
o_counter: IntCriterionInput
"""Filter by resolution"""
resolution: ResolutionCriterionInput
"""Filter to only include images missing this property"""
is_missing: String
"""Filter to only include images with this studio"""
studios: HierarchicalMultiCriterionInput
"""Filter to only include images with these tags"""
tags: MultiCriterionInput
"""Filter by tag count"""
tag_count: IntCriterionInput
"""Filter to only include images with performers with these tags"""
performer_tags: MultiCriterionInput
"""Filter to only include images with these performers"""
performers: MultiCriterionInput
"""Filter by performer count"""
performer_count: IntCriterionInput
"""Filter to only include images with these galleries"""
galleries: MultiCriterionInput
}
enum CriterionModifier {
@@ -93,6 +323,14 @@ enum CriterionModifier {
INCLUDES_ALL,
INCLUDES,
EXCLUDES,
"""MATCHES REGEX"""
MATCHES_REGEX,
"""NOT MATCHES REGEX"""
NOT_MATCHES_REGEX,
""">= AND <="""
BETWEEN,
"""< OR >"""
NOT_BETWEEN,
}
input StringCriterionInput {
@@ -102,10 +340,60 @@ input StringCriterionInput {
input IntCriterionInput {
value: Int!
value2: Int
modifier: CriterionModifier!
}
input MultiCriterionInput {
value: [ID!]
modifier: CriterionModifier!
}
}
input GenderCriterionInput {
value: GenderEnum
modifier: CriterionModifier!
}
input HierarchicalMultiCriterionInput {
value: [ID!]
modifier: CriterionModifier!
depth: Int!
}
enum FilterMode {
SCENES,
PERFORMERS,
STUDIOS,
GALLERIES,
SCENE_MARKERS,
MOVIES,
TAGS,
IMAGES,
}
type SavedFilter {
id: ID!
mode: FilterMode!
name: String!
"""JSON-encoded filter string"""
filter: String!
}
input SaveFilterInput {
"""provide ID to overwrite existing filter"""
id: ID
mode: FilterMode!
name: String!
"""JSON-encoded filter string"""
filter: String!
}
input DestroyFilterInput {
id: ID!
}
input SetDefaultFilterInput {
mode: FilterMode!
"""JSON-encoded filter string - null to clear"""
filter: String
}

View File

@@ -2,11 +2,26 @@
type Gallery {
id: ID!
checksum: String!
path: String!
path: String
title: String
url: String
date: String
details: String
rating: Int
organized: Boolean!
created_at: Time!
updated_at: Time!
file_mod_time: Time
"""The files in the gallery"""
files: [GalleryFilesType!]! # Resolver
scenes: [Scene!]!
studio: Studio
image_count: Int!
tags: [Tag!]!
performers: [Performer!]!
"""The images in the gallery"""
images: [Image!]! # Resolver
cover: Image
}
type GalleryFilesType {
@@ -15,7 +30,65 @@ type GalleryFilesType {
path: String
}
input GalleryCreateInput {
title: String!
url: String
date: String
details: String
rating: Int
organized: Boolean
scene_ids: [ID!]
studio_id: ID
tag_ids: [ID!]
performer_ids: [ID!]
}
input GalleryUpdateInput {
clientMutationId: String
id: ID!
title: String
url: String
date: String
details: String
rating: Int
organized: Boolean
scene_ids: [ID!]
studio_id: ID
tag_ids: [ID!]
performer_ids: [ID!]
}
input BulkGalleryUpdateInput {
clientMutationId: String
ids: [ID!]
url: String
date: String
details: String
rating: Int
organized: Boolean
scene_ids: BulkUpdateIds
studio_id: ID
tag_ids: BulkUpdateIds
performer_ids: BulkUpdateIds
}
input GalleryDestroyInput {
ids: [ID!]!
delete_file: Boolean
delete_generated: Boolean
}
type FindGalleriesResultType {
count: Int!
galleries: [Gallery!]!
}
}
input GalleryAddInput {
gallery_id: ID!
image_ids: [ID!]!
}
input GalleryRemoveInput {
gallery_id: ID!
image_ids: [ID!]!
}

View File

@@ -0,0 +1,74 @@
type Image {
id: ID!
checksum: String
title: String
rating: Int
o_counter: Int
organized: Boolean!
path: String!
created_at: Time!
updated_at: Time!
file_mod_time: Time
file: ImageFileType! # Resolver
paths: ImagePathsType! # Resolver
galleries: [Gallery!]!
studio: Studio
tags: [Tag!]!
performers: [Performer!]!
}
type ImageFileType {
size: Int
width: Int
height: Int
}
type ImagePathsType {
thumbnail: String # Resolver
image: String # Resolver
}
input ImageUpdateInput {
clientMutationId: String
id: ID!
title: String
rating: Int
organized: Boolean
studio_id: ID
performer_ids: [ID!]
tag_ids: [ID!]
gallery_ids: [ID!]
}
input BulkImageUpdateInput {
clientMutationId: String
ids: [ID!]
title: String
rating: Int
organized: Boolean
studio_id: ID
performer_ids: BulkUpdateIds
tag_ids: BulkUpdateIds
gallery_ids: BulkUpdateIds
}
input ImageDestroyInput {
id: ID!
delete_file: Boolean
delete_generated: Boolean
}
input ImagesDestroyInput {
ids: [ID!]!
delete_file: Boolean
delete_generated: Boolean
}
type FindImagesResultType {
count: Int!
images: [Image!]!
}

View File

@@ -0,0 +1,33 @@
enum JobStatus {
READY
RUNNING
FINISHED
STOPPING
CANCELLED
}
type Job {
id: ID!
status: JobStatus!
subTasks: [String!]
description: String!
progress: Float
startTime: Time
endTime: Time
addTime: Time!
}
input FindJobInput {
id: ID!
}
enum JobStatusUpdateType {
ADD
REMOVE
UPDATE
}
type JobStatusUpdate {
type: JobStatusUpdateType!
job: Job!
}

View File

@@ -1,15 +1,60 @@
scalar Upload
input GenerateMetadataInput {
sprites: Boolean!
previews: Boolean!
imagePreviews: Boolean!
previewOptions: GeneratePreviewOptionsInput
markers: Boolean!
transcodes: Boolean!
phashes: Boolean!
"""scene ids to generate for"""
sceneIDs: [ID!]
"""marker ids to generate for"""
markerIDs: [ID!]
"""overwrite existing media"""
overwrite: Boolean
}
input GeneratePreviewOptionsInput {
"""Number of segments in a preview file"""
previewSegments: Int
"""Preview segment duration, in seconds"""
previewSegmentDuration: Float
"""Duration of start of video to exclude when generating previews"""
previewExcludeStart: String
"""Duration of end of video to exclude when generating previews"""
previewExcludeEnd: String
"""Preset when generating preview"""
previewPreset: PreviewPreset
}
input ScanMetadataInput {
useFileMetadata: Boolean!
paths: [String!]
"""Set name, date, details from metadata (if present)"""
useFileMetadata: Boolean
"""Strip file extension from title"""
stripFileExtension: Boolean
"""Generate previews during scan"""
scanGeneratePreviews: Boolean
"""Generate image previews during scan"""
scanGenerateImagePreviews: Boolean
"""Generate sprites during scan"""
scanGenerateSprites: Boolean
"""Generate phashes during scan"""
scanGeneratePhashes: Boolean
}
input CleanMetadataInput {
"""Do a dry run. Don't delete any files"""
dryRun: Boolean!
}
input AutoTagMetadataInput {
"""Paths to tag, null for all files"""
paths: [String!]
"""IDs of performers to tag files with, or "*" for all"""
performers: [String!]
"""IDs of studios to tag files with, or "*" for all"""
@@ -18,8 +63,58 @@ input AutoTagMetadataInput {
tags: [String!]
}
type MetadataUpdateStatus {
progress: Float!
status: String!
message: String!
}
input ExportObjectTypeInput {
ids: [String!]
all: Boolean
}
input ExportObjectsInput {
scenes: ExportObjectTypeInput
images: ExportObjectTypeInput
studios: ExportObjectTypeInput
performers: ExportObjectTypeInput
tags: ExportObjectTypeInput
movies: ExportObjectTypeInput
galleries: ExportObjectTypeInput
includeDependencies: Boolean
}
enum ImportDuplicateEnum {
IGNORE
OVERWRITE
FAIL
}
enum ImportMissingRefEnum {
IGNORE
FAIL
CREATE
}
input ImportObjectsInput {
file: Upload!
duplicateBehaviour: ImportDuplicateEnum!
missingRefBehaviour: ImportMissingRefEnum!
}
input BackupDatabaseInput {
download: Boolean
}
enum SystemStatusEnum {
SETUP
NEEDS_MIGRATION
OK
}
type SystemStatus {
databaseSchema: Int
databasePath: String
configPath: String
appSchema: Int!
status: SystemStatusEnum!
}
input MigrateInput {
backupPath: String!
}

View File

@@ -0,0 +1,63 @@
type Movie {
id: ID!
checksum: String!
name: String!
aliases: String
"""Duration in seconds"""
duration: Int
date: String
rating: Int
studio: Studio
director: String
synopsis: String
url: String
created_at: Time!
updated_at: Time!
front_image_path: String # Resolver
back_image_path: String # Resolver
scene_count: Int # Resolver
}
input MovieCreateInput {
name: String!
aliases: String
"""Duration in seconds"""
duration: Int
date: String
rating: Int
studio_id: ID
director: String
synopsis: String
url: String
"""This should be a URL or a base64 encoded data URL"""
front_image: String
"""This should be a URL or a base64 encoded data URL"""
back_image: String
}
input MovieUpdateInput {
id: ID!
name: String
aliases: String
duration: Int
date: String
rating: Int
studio_id: ID
director: String
synopsis: String
url: String
"""This should be a URL or a base64 encoded data URL"""
front_image: String
"""This should be a URL or a base64 encoded data URL"""
back_image: String
}
input MovieDestroyInput {
id: ID!
}
type FindMoviesResultType {
count: Int!
movies: [Movie!]!
}

View File

@@ -1,8 +1,18 @@
enum GenderEnum {
MALE
FEMALE
TRANSGENDER_MALE
TRANSGENDER_FEMALE
INTERSEX
NON_BINARY
}
type Performer {
id: ID!
checksum: String!
name: String
url: String
gender: GenderEnum
twitter: String
instagram: String
birthdate: String
@@ -17,15 +27,27 @@ type Performer {
piercings: String
aliases: String
favorite: Boolean!
tags: [Tag!]!
image_path: String # Resolver
scene_count: Int # Resolver
image_count: Int # Resolver
gallery_count: Int # Resolver
scenes: [Scene!]!
stash_ids: [StashID!]!
rating: Int
details: String
death_date: String
hair_color: String
weight: Int
created_at: Time!
updated_at: Time!
}
input PerformerCreateInput {
name: String
name: String!
url: String
gender: GenderEnum
birthdate: String
ethnicity: String
country: String
@@ -40,14 +62,22 @@ input PerformerCreateInput {
twitter: String
instagram: String
favorite: Boolean
"""This should be base64 encoded"""
tag_ids: [ID!]
"""This should be a URL or a base64 encoded data URL"""
image: String
stash_ids: [StashIDInput!]
rating: Int
details: String
death_date: String
hair_color: String
weight: Int
}
input PerformerUpdateInput {
id: ID!
name: String
url: String
gender: GenderEnum
birthdate: String
ethnicity: String
country: String
@@ -62,8 +92,42 @@ input PerformerUpdateInput {
twitter: String
instagram: String
favorite: Boolean
"""This should be base64 encoded"""
tag_ids: [ID!]
"""This should be a URL or a base64 encoded data URL"""
image: String
stash_ids: [StashIDInput!]
rating: Int
details: String
death_date: String
hair_color: String
weight: Int
}
input BulkPerformerUpdateInput {
clientMutationId: String
ids: [ID!]
url: String
gender: GenderEnum
birthdate: String
ethnicity: String
country: String
eye_color: String
height: String
measurements: String
fake_tits: String
career_length: String
tattoos: String
piercings: String
aliases: String
twitter: String
instagram: String
favorite: Boolean
tag_ids: BulkUpdateIds
rating: Int
details: String
death_date: String
hair_color: String
weight: Int
}
input PerformerDestroyInput {
@@ -73,4 +137,4 @@ input PerformerDestroyInput {
type FindPerformersResultType {
count: Int!
performers: [Performer!]!
}
}

View File

@@ -0,0 +1,43 @@
type Plugin {
id: ID!
name: String!
description: String
url: String
version: String
tasks: [PluginTask!]
hooks: [PluginHook!]
}
type PluginTask {
name: String!
description: String
plugin: Plugin!
}
type PluginHook {
name: String!
description: String
hooks: [String!]
plugin: Plugin!
}
type PluginResult {
error: String
result: String
}
input PluginArgInput {
key: String!
value: PluginValueInput
}
input PluginValueInput {
str: String
i: Int
b: Boolean
f: Float
o: [PluginArgInput!]
a: [PluginValueInput!]
}

View File

@@ -5,6 +5,8 @@ type SceneMarker {
seconds: Float!
primary_tag: Tag!
tags: [Tag!]!
created_at: Time!
updated_at: Time!
"""The path to stream this marker"""
stream: String! # Resolver

View File

@@ -16,27 +16,48 @@ type ScenePathsType {
webp: String # Resolver
vtt: String # Resolver
chapters_vtt: String # Resolver
sprite: String # Resolver
funscript: String # Resolver
}
type SceneMovie {
movie: Movie!
scene_index: Int
}
type Scene {
id: ID!
checksum: String!
checksum: String
oshash: String
title: String
details: String
url: String
date: String
rating: Int
organized: Boolean!
o_counter: Int
path: String!
phash: String
interactive: Boolean!
created_at: Time!
updated_at: Time!
file_mod_time: Time
file: SceneFileType! # Resolver
paths: ScenePathsType! # Resolver
is_streamable: Boolean! # Resolver
scene_markers: [SceneMarker!]!
gallery: Gallery
galleries: [Gallery!]!
studio: Studio
movies: [SceneMovie!]!
tags: [Tag!]!
performers: [Performer!]!
stash_ids: [StashID!]!
}
input SceneMovieInput {
movie_id: ID!
scene_index: Int
}
input SceneUpdateInput {
@@ -47,12 +68,26 @@ input SceneUpdateInput {
url: String
date: String
rating: Int
organized: Boolean
studio_id: ID
gallery_id: ID
gallery_ids: [ID!]
performer_ids: [ID!]
movies: [SceneMovieInput!]
tag_ids: [ID!]
"""This should be base64 encoded"""
"""This should be a URL or a base64 encoded data URL"""
cover_image: String
stash_ids: [StashIDInput!]
}
enum BulkUpdateIdMode {
SET
ADD
REMOVE
}
input BulkUpdateIds {
ids: [ID!]
mode: BulkUpdateIdMode!
}
input BulkSceneUpdateInput {
@@ -63,10 +98,11 @@ input BulkSceneUpdateInput {
url: String
date: String
rating: Int
organized: Boolean
studio_id: ID
gallery_id: ID
performer_ids: [ID!]
tag_ids: [ID!]
gallery_ids: BulkUpdateIds
performer_ids: BulkUpdateIds
tag_ids: BulkUpdateIds
}
input SceneDestroyInput {
@@ -75,6 +111,12 @@ input SceneDestroyInput {
delete_generated: Boolean
}
input ScenesDestroyInput {
ids: [ID!]!
delete_file: Boolean
delete_generated: Boolean
}
type FindScenesResultType {
count: Int!
scenes: [Scene!]!
@@ -83,7 +125,13 @@ type FindScenesResultType {
input SceneParserInput {
ignoreWords: [String!],
whitespaceCharacters: String,
capitalizeTitle: Boolean
capitalizeTitle: Boolean,
ignoreOrganized: Boolean
}
type SceneMovieID {
movie_id: ID!
scene_index: String
}
type SceneParserResult {
@@ -94,12 +142,24 @@ type SceneParserResult {
date: String
rating: Int
studio_id: ID
gallery_id: ID
gallery_ids: [ID!]
performer_ids: [ID!]
movies: [SceneMovieID!]
tag_ids: [ID!]
}
type SceneParserResultType {
count: Int!
results: [SceneParserResult!]!
}
}
input SceneHashInput {
checksum: String
oshash: String
}
type SceneStreamEndpoint {
url: String!
mime_type: String
label: String
}

View File

@@ -0,0 +1,35 @@
type ScrapedMovieStudio {
"""Set if studio matched"""
id: ID
name: String!
url: String
}
"""A movie from a scraping operation..."""
type ScrapedMovie {
name: String
aliases: String
duration: String
date: String
rating: String
director: String
url: String
synopsis: String
studio: ScrapedMovieStudio
"""This should be a base64 encoded data URL"""
front_image: String
"""This should be a base64 encoded data URL"""
back_image: String
}
input ScrapedMovieInput {
name: String
aliases: String
duration: String
date: String
rating: String
director: String
url: String
synopsis: String
}

View File

@@ -1,6 +1,7 @@
"""A performer from a scraping operation..."""
type ScrapedPerformer {
name: String
gender: String
url: String
twitter: String
instagram: String
@@ -15,10 +16,21 @@ type ScrapedPerformer {
tattoos: String
piercings: String
aliases: String
# Should be ScrapedPerformerTag - but would be identical types
tags: [ScrapedSceneTag!]
"""This should be a base64 encoded data URL"""
image: String
details: String
death_date: String
hair_color: String
weight: String
remote_site_id: String
}
input ScrapedPerformerInput {
name: String
gender: String
url: String
twitter: String
instagram: String
@@ -33,4 +45,12 @@ input ScrapedPerformerInput {
tattoos: String
piercings: String
aliases: String
# not including tags for the input
# not including image for the input
details: String
death_date: String
hair_color: String
weight: String
remote_site_id: String
}

View File

@@ -20,13 +20,17 @@ type Scraper {
performer: ScraperSpec
"""Details for scene scraper"""
scene: ScraperSpec
"""Details for gallery scraper"""
gallery: ScraperSpec
"""Details for movie scraper"""
movie: ScraperSpec
}
type ScrapedScenePerformer {
"""Set if performer matched"""
id: ID
stored_id: ID
name: String!
gender: String
url: String
twitter: String
instagram: String
@@ -41,18 +45,41 @@ type ScrapedScenePerformer {
tattoos: String
piercings: String
aliases: String
tags: [ScrapedSceneTag!]
remote_site_id: String
images: [String!]
details: String
death_date: String
hair_color: String
weight: String
}
type ScrapedSceneMovie {
"""Set if movie matched"""
stored_id: ID
name: String!
aliases: String
duration: String
date: String
rating: String
director: String
synopsis: String
url: String
}
type ScrapedSceneStudio {
"""Set if studio matched"""
id: ID
stored_id: ID
name: String!
url: String
remote_site_id: String
}
type ScrapedSceneTag {
"""Set if tag matched"""
id: ID
stored_id: ID
name: String!
}
@@ -62,9 +89,65 @@ type ScrapedScene {
url: String
date: String
"""This should be a base64 encoded data URL"""
image: String
file: SceneFileType # Resolver
studio: ScrapedSceneStudio
tags: [ScrapedSceneTag!]
performers: [ScrapedScenePerformer!]
movies: [ScrapedSceneMovie!]
remote_site_id: String
duration: Int
fingerprints: [StashBoxFingerprint!]
}
type ScrapedGallery {
title: String
details: String
url: String
date: String
studio: ScrapedSceneStudio
tags: [ScrapedSceneTag!]
performers: [ScrapedScenePerformer!]
}
input StashBoxSceneQueryInput {
"""Index of the configured stash-box instance to use"""
stash_box_index: Int!
"""Instructs query by scene fingerprints"""
scene_ids: [ID!]
"""Query by query string"""
q: String
}
input StashBoxPerformerQueryInput {
"""Index of the configured stash-box instance to use"""
stash_box_index: Int!
"""Instructs query by scene fingerprints"""
performer_ids: [ID!]
"""Query by query string"""
q: String
}
type StashBoxPerformerQueryResult {
query: String!
results: [ScrapedScenePerformer!]!
}
type StashBoxFingerprint {
algorithm: String!
hash: String!
duration: Int!
}
input StashBoxBatchPerformerTagInput {
endpoint: Int!
exclude_fields: [String!]
refresh: Boolean!
performer_ids: [ID!]
performer_names: [String!]
}

View File

@@ -0,0 +1,26 @@
type StashBox {
endpoint: String!
api_key: String!
name: String!
}
input StashBoxInput {
endpoint: String!
api_key: String!
name: String!
}
type StashID {
endpoint: String!
stash_id: String!
}
input StashIDInput {
endpoint: String!
stash_id: String!
}
input StashBoxFingerprintSubmissionInput {
scene_ids: [String!]!
stash_box_index: Int!
}

View File

@@ -1,7 +1,12 @@
type StatsResultType {
scene_count: Int!
scenes_size: Float!
scenes_duration: Float!
image_count: Int!
images_size: Float!
gallery_count: Int!
performer_count: Int!
studio_count: Int!
movie_count: Int!
tag_count: Int!
}
}

View File

@@ -3,24 +3,41 @@ type Studio {
checksum: String!
name: String!
url: String
parent_studio: Studio
child_studios: [Studio!]!
image_path: String # Resolver
scene_count: Int # Resolver
image_count: Int # Resolver
gallery_count: Int # Resolver
stash_ids: [StashID!]!
rating: Int
details: String
created_at: Time!
updated_at: Time!
}
input StudioCreateInput {
name: String!
url: String
"""This should be base64 encoded"""
parent_id: ID
"""This should be a URL or a base64 encoded data URL"""
image: String
stash_ids: [StashIDInput!]
rating: Int
details: String
}
input StudioUpdateInput {
id: ID!
name: String
url: String
"""This should be base64 encoded"""
parent_id: ID,
"""This should be a URL or a base64 encoded data URL"""
image: String
stash_ids: [StashIDInput!]
rating: Int
details: String
}
input StudioDestroyInput {
@@ -30,4 +47,4 @@ input StudioDestroyInput {
type FindStudiosResultType {
count: Int!
studios: [Studio!]!
}
}

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