Compare commits

...

219 Commits

Author SHA1 Message Date
DebaucheryLibrarian 33a327a04b Merge branch 'master' into experimental 2022-03-30 23:00:29 +02:00
DebaucheryLibrarian a46061e247 1.212.9 2022-03-30 16:11:09 +02:00
DebaucheryLibrarian 94e07ff23d Added Bang! Podcast channel. 2022-03-30 16:11:07 +02:00
DebaucheryLibrarian 4811befcf6 1.212.8 2022-03-30 15:45:51 +02:00
DebaucheryLibrarian c455f02c66 Updated Men URLs. 2022-03-30 15:45:41 +02:00
DebaucheryLibrarian efc5620a28 1.212.7 2022-03-30 01:17:56 +02:00
DebaucheryLibrarian 61123fdb6a Added Accept-Language header to MindGeek requests, seems to help with acquiring sessions. 2022-03-30 01:17:54 +02:00
DebaucheryLibrarian 3ec6911d46 1.212.6 2022-03-29 23:24:58 +02:00
DebaucheryLibrarian 2021093645 Marked Dane Jones and Lesbea as native sites. 2022-03-29 23:24:55 +02:00
DebaucheryLibrarian 1c72dc202f 1.212.5 2022-03-28 23:44:44 +02:00
DebaucheryLibrarian 1ef946fa77 Marked Mile High sites as native. 2022-03-28 23:44:42 +02:00
DebaucheryLibrarian 3b6bbc39ff 1.212.4 2022-03-28 20:05:28 +02:00
DebaucheryLibrarian 481c9feada Fixed missing scenes photos breaking album. 2022-03-28 20:05:25 +02:00
DebaucheryLibrarian 953b3e9568 1.212.3 2022-03-28 00:36:05 +02:00
DebaucheryLibrarian bdd2e68f49 Fixed centering logic in banner. 2022-03-28 00:36:04 +02:00
DebaucheryLibrarian e4cc349302 1.212.2 2022-03-28 00:32:00 +02:00
DebaucheryLibrarian 6547b93e55 Fixed broken scene photo length check in release banner. 2022-03-28 00:31:59 +02:00
DebaucheryLibrarian bb9649d23b 1.212.1 2022-03-28 00:22:59 +02:00
DebaucheryLibrarian 9e2eaef9d1 Added dedicated serie photos table, renamed serie scene photo function. Fixed covers and scene photos in banner and album. 2022-03-28 00:22:57 +02:00
DebaucheryLibrarian 1c3ee75d3b 1.212.0 2022-03-27 23:42:06 +02:00
DebaucheryLibrarian 15c9af8057 Added dedicated movie photo table, renamed scene photo function. 2022-03-27 23:42:03 +02:00
DebaucheryLibrarian 295573c1ef 1.211.2 2022-03-27 00:27:29 +01:00
DebaucheryLibrarian e93e8ace5c Added deep scene force parameter to MindGeek scraper. 2022-03-27 00:27:26 +01:00
DebaucheryLibrarian 43af7ba777 1.211.1 2022-03-26 17:56:24 +01:00
DebaucheryLibrarian 0dad5b0d68 Added series removal utils. 2022-03-26 17:56:22 +01:00
DebaucheryLibrarian ae9b793318 1.211.0 2022-03-26 17:40:23 +01:00
DebaucheryLibrarian fd8170f223 Added series. 2022-03-26 17:40:20 +01:00
DebaucheryLibrarian 661b8b716b 1.210.1 2022-03-09 23:26:50 +01:00
DebaucheryLibrarian 5ff076cac3 Added DP Star Sex Challenges to Digital Playground. 2022-03-09 23:26:48 +01:00
DebaucheryLibrarian 41c100ac4e 1.210.0 2022-03-04 23:32:28 +01:00
DebaucheryLibrarian c6e977f842 Added movie support to MindGeek scraper. 2022-03-04 23:32:09 +01:00
DebaucheryLibrarian 50b7f521b5 1.209.5 2022-02-27 21:15:07 +01:00
DebaucheryLibrarian f0d0ee3acc Removed redundant scenes path from Digital Playground main channel. 2022-02-27 21:15:05 +01:00
DebaucheryLibrarian 7b3bdadd44 1.209.4 2022-02-25 22:13:43 +01:00
DebaucheryLibrarian 5deba6b90f Passing resolved parameters into before-scrape methods. 2022-02-25 22:13:41 +01:00
DebaucheryLibrarian a5afffc968 1.209.3 2022-02-25 00:00:21 +01:00
DebaucheryLibrarian a239a5c593 Fixed entity scenes function for studios. Added triple anal tag alias. 2022-02-25 00:00:18 +01:00
DebaucheryLibrarian e56e7333e3 1.209.2 2022-02-24 23:33:26 +01:00
DebaucheryLibrarian d55e3c37cd Updated media seeds from LegalPorno to AnalVids. 2022-02-24 23:33:19 +01:00
DebaucheryLibrarian 97b78ea016 1.209.1 2022-02-24 23:30:49 +01:00
DebaucheryLibrarian 3e290b74dc Updated affiliates from LegalPorno to AnalVids. 2022-02-24 23:30:47 +01:00
DebaucheryLibrarian 65141207ae 1.209.0 2022-02-24 23:28:27 +01:00
DebaucheryLibrarian 17dfeac1af Renamed LegalPorno to AnalVids, added missing studios. 2022-02-24 23:28:24 +01:00
DebaucheryLibrarian 4a9c428d69 1.208.1 2022-02-24 22:43:01 +01:00
DebaucheryLibrarian 333f252099 Added BJ Raw to Radical. 2022-02-24 22:42:59 +01:00
DebaucheryLibrarian 38232f258a 1.208.0 2022-02-24 22:33:03 +01:00
DebaucheryLibrarian 582269cfaa Added Radical metadata layout scraper and the Got Filled and Inserted channels. 2022-02-24 22:33:00 +01:00
DebaucheryLibrarian 0b646429fd 1.207.5 2022-02-20 23:40:23 +01:00
DebaucheryLibrarian fecef6c1cf Added missing MOFOS serie channels. 2022-02-20 23:40:20 +01:00
DebaucheryLibrarian 73e5404c44 1.207.4 2022-02-20 16:52:32 +01:00
DebaucheryLibrarian 690d2bb3ed Added MOFOS to default rate limit config, added light logos. 2022-02-20 16:52:29 +01:00
DebaucheryLibrarian 1dd935e1e9 1.207.3 2022-02-14 01:27:58 +01:00
DebaucheryLibrarian 8386230f33 Added missing Team Skeet sites. 2022-02-14 01:27:56 +01:00
DebaucheryLibrarian 5a68b06137 1.207.2 2022-02-13 01:34:41 +01:00
DebaucheryLibrarian 5918364cf5 Preventing unnecessary deep scrapes in Team Skeet scraper. 2022-02-13 01:34:39 +01:00
DebaucheryLibrarian df4d860d35 1.207.1 2022-02-12 17:19:49 +01:00
DebaucheryLibrarian d9f0db6e3c Fixed reading screen ID from non-existent item in Bang scraper. 2022-02-12 17:19:47 +01:00
DebaucheryLibrarian 7372b560b2 1.207.0 2022-02-12 17:16:26 +01:00
DebaucheryLibrarian 9d638c685c 1.206.12 2022-02-12 17:16:23 +01:00
DebaucheryLibrarian 5da1acc38d Added media resize. 2022-02-12 17:16:20 +01:00
DebaucheryLibrarian c7c62e220d Removed console log from Bang scraper. 2022-02-12 16:22:41 +01:00
DebaucheryLibrarian 9edd652a2c 1.206.11 2022-02-12 16:22:03 +01:00
DebaucheryLibrarian cde760c1ea Preventing Bang! scraper from redundant deep scraping when base release is available. 2022-02-12 16:22:00 +01:00
DebaucheryLibrarian 19c7f958e1 1.206.10 2022-02-12 03:26:43 +01:00
DebaucheryLibrarian c7710afdbf Fixed Bang! scraped failing when scene has no photos. 2022-02-12 03:26:40 +01:00
DebaucheryLibrarian ba18a3dadb 1.206.9 2022-02-11 22:14:46 +01:00
DebaucheryLibrarian 496c29e569 Configured Reality Kings to fetch session from RK scene overview. 2022-02-11 22:14:44 +01:00
DebaucheryLibrarian 98a72a4929 1.206.8 2022-02-09 00:19:56 +01:00
DebaucheryLibrarian c4f0b48932 Fixed cover dimensions on movie tile to show lazy image, showing missing cover icon. 2022-02-09 00:19:54 +01:00
DebaucheryLibrarian 93abbab873 1.206.7 2022-02-08 23:59:48 +01:00
DebaucheryLibrarian f7bbab08bd Added Porn Pros main channel and working URLs for Flexible Positions, Public Violations and Squirt Disgrace. Added bisexual tag photos. 2022-02-08 23:59:44 +01:00
DebaucheryLibrarian 1e4ddf2bbf 1.206.6 2022-02-08 00:19:36 +01:00
DebaucheryLibrarian 9b7879bff7 Removed channel ID from Gamma update query to prevent duplicate scenes. Added sexuality tags with covers to overview. 2022-02-08 00:19:34 +01:00
DebaucheryLibrarian 03d96d4dec 1.206.5 2022-02-07 22:29:11 +01:00
DebaucheryLibrarian 1dfa034332 Handling 'page not found' with 200 OK in Gamma scraper. 2022-02-07 22:29:09 +01:00
DebaucheryLibrarian 196a1d33e3 1.206.4 2022-02-07 22:16:46 +01:00
DebaucheryLibrarian 3d349c413f Fixed Adult Time scraper. 2022-02-07 22:16:43 +01:00
DebaucheryLibrarian bd5babd37e 1.206.3 2022-02-07 21:58:31 +01:00
DebaucheryLibrarian fffe9080f3 Added stand-alone Spizoo sites. 2022-02-07 21:58:27 +01:00
DebaucheryLibrarian 5630b16e99 1.206.2 2022-02-07 01:57:14 +01:00
DebaucheryLibrarian 4bcf7ef45b Storing associations if existing media are found. 2022-02-07 01:57:09 +01:00
DebaucheryLibrarian 9abc1d48ac 1.206.1 2022-02-05 17:14:37 +01:00
DebaucheryLibrarian ceaf5a3217 Not storing shallow movie data when argument is disabled. 2022-02-05 17:14:34 +01:00
DebaucheryLibrarian 36d84fb98b 1.206.0 2022-02-03 00:04:51 +01:00
DebaucheryLibrarian 3d80e9d77b Added movie URL file support. Fixed Gamma movie API scraper movie URL. 2022-02-03 00:04:48 +01:00
DebaucheryLibrarian 1dc38ffacc 1.205.20 2022-02-02 23:53:44 +01:00
DebaucheryLibrarian ee210b5c68 Replaced Gender X with Gender X Films, fixed Zero Tolerance movie URLs. 2022-02-02 23:53:42 +01:00
DebaucheryLibrarian 3aae3cd3a1 1.205.19 2022-02-02 23:51:20 +01:00
DebaucheryLibrarian f1a7f2f905 Added Gamma movie API scraper. 2022-02-02 23:51:15 +01:00
DebaucheryLibrarian 0b7e0319f1 1.205.18 2022-02-02 22:25:06 +01:00
DebaucheryLibrarian 10b8abf706 Updated Zero Tolerance channel to Zero Tolerance Films. 2022-02-02 22:25:04 +01:00
DebaucheryLibrarian b163223ff1 1.205.17 2022-02-01 21:18:58 +01:00
DebaucheryLibrarian b9f3eb85f9 Ignoring Gamma master categories in update scrape as these seem to contain irrelevant tags. 2022-02-01 21:18:54 +01:00
DebaucheryLibrarian 285a65f018 1.205.16 2022-01-30 22:15:09 +01:00
DebaucheryLibrarian 815d56d334 Preventing media associations when use-reference is unavailable. 2022-01-30 22:15:07 +01:00
DebaucheryLibrarian 27a9a233e2 1.205.15 2022-01-30 17:05:20 +01:00
DebaucheryLibrarian 22864105ac Writing media associations to disk for debugging. 2022-01-30 17:05:18 +01:00
DebaucheryLibrarian 7cf47cbf8d 1.205.14 2022-01-30 00:18:17 +01:00
DebaucheryLibrarian 502c588958 Updated Bang Bros product ID for Haze Her, removed wrong ones. 2022-01-30 00:18:15 +01:00
DebaucheryLibrarian 81792a7c2f 1.205.13 2022-01-30 00:08:41 +01:00
DebaucheryLibrarian 784d326584 Updated Bang Bros product ID for College Rules. 2022-01-30 00:08:39 +01:00
DebaucheryLibrarian 83dc7aa578 1.205.12 2022-01-29 23:50:01 +01:00
DebaucheryLibrarian 5a3b27fbf7 Fixed movie cover index for overview in GraphQL query. 2022-01-29 23:49:59 +01:00
DebaucheryLibrarian 5ff83a9497 1.205.11 2022-01-29 23:39:13 +01:00
DebaucheryLibrarian 07cb39c756 Fixed movie cover index in GraphQL query. 2022-01-29 23:39:12 +01:00
DebaucheryLibrarian fffd54995d 1.205.10 2022-01-29 17:13:13 +01:00
DebaucheryLibrarian 5302176f0b Re-added channel count to networks page. 2022-01-29 17:13:09 +01:00
DebaucheryLibrarian efd7cf8acc 1.205.9 2022-01-29 16:38:42 +01:00
DebaucheryLibrarian 52218c30f8 Not fetching mobile Gamma page when photos are not expected. 2022-01-29 16:38:36 +01:00
DebaucheryLibrarian 04c176fa8b 1.205.8 2022-01-29 03:34:31 +01:00
DebaucheryLibrarian af320684b4 Added Bang Bros sites. 2022-01-29 03:34:26 +01:00
DebaucheryLibrarian b2ba14ce45 1.205.7 2022-01-29 02:39:17 +01:00
DebaucheryLibrarian d776cc2f71 Added Abuse Me to Bang Bros network. 2022-01-29 02:39:14 +01:00
DebaucheryLibrarian b4bed2f623 1.205.6 2022-01-29 01:21:45 +01:00
DebaucheryLibrarian 5c5a11fdca Added Bang Bros members page scraper (not for full scenes). 2022-01-29 01:21:41 +01:00
DebaucheryLibrarian a22c62d893 1.205.5 2022-01-28 04:05:38 +01:00
DebaucheryLibrarian 90bc2f3724 Changed release media association existence check, added log for details. 2022-01-28 04:05:29 +01:00
DebaucheryLibrarian 8cdc794a3a 1.205.4 2022-01-26 13:52:41 +01:00
DebaucheryLibrarian 250618df8b Added entity scene count function. 2022-01-26 13:52:39 +01:00
DebaucheryLibrarian b62ae00c54 1.205.3 2022-01-26 01:47:36 +01:00
DebaucheryLibrarian 67d0a9e0e0 Fixed scene entity tag association. 2022-01-26 01:47:34 +01:00
ThePendulum b4425bc3bb Merge pull request 'Add Facials4k' (#44) from boiii/traxxx:add-facials-4k into master
Reviewed-on: http://gitea.unknown.name/DebaucheryLibrarian/traxxx/pulls/44
2022-01-25 22:29:10 +00:00
boiii d77c145de3 Update 'seeds/02_sites.js' 2022-01-25 20:56:11 +00:00
DebaucheryLibrarian 6753f923d9 1.205.2 2022-01-25 15:34:17 +01:00
DebaucheryLibrarian 452f725332 Switched poster URL preference in Gamma scraper to prevent cropped image on XEmpire. 2022-01-25 15:34:15 +01:00
DebaucheryLibrarian 7c1f45bcfb 1.205.1 2022-01-24 22:29:29 +01:00
DebaucheryLibrarian 11ea54f6e8 Fixed outdated alerts query. 2022-01-24 22:29:27 +01:00
DebaucheryLibrarian 5b623ee46f 1.205.0 2022-01-24 00:15:19 +01:00
DebaucheryLibrarian 7ceec1c739 Added indexes to scene tag and movie scene tables improve performance. Removed scene count from channel overview, too expensive. 2022-01-24 00:15:11 +01:00
DebaucheryLibrarian fc318536aa 1.204.13 2022-01-23 02:46:44 +01:00
DebaucheryLibrarian cd8f690ac6 Preferring network over channel in deep URL channel matching. 2022-01-23 02:46:42 +01:00
DebaucheryLibrarian 240a8e86fd 1.204.12 2022-01-22 23:20:10 +01:00
DebaucheryLibrarian c557f0f1f0 Improved Gamma image sources to prevent cropped images. 2022-01-22 23:20:08 +01:00
DebaucheryLibrarian 86f56695e2 1.204.11 2022-01-20 00:54:13 +01:00
DebaucheryLibrarian 20da2d1cf6 Reusing batch ID for movies to preserve new-flag. 2022-01-20 00:54:10 +01:00
DebaucheryLibrarian 372db86927 Disabled MindGeek session bundling to analyze Too Many Requests errors. 2022-01-16 22:24:47 +01:00
DebaucheryLibrarian 4c503a3177 1.204.10 2022-01-16 17:17:49 +01:00
DebaucheryLibrarian 57d46f5842 Fixed latest query in Gamma scraper. 2022-01-16 17:17:45 +01:00
DebaucheryLibrarian 7f11d0ca91 1.204.9 2022-01-12 17:50:27 +01:00
DebaucheryLibrarian bbd788699e Fixed GraphQL query for scenes REST API. Added entry ID to scene search document. 2022-01-12 17:50:23 +01:00
DebaucheryLibrarian e24add98ea 1.204.8 2022-01-10 02:17:21 +01:00
DebaucheryLibrarian 506971b44b Chunked duplicate check to prevent postgres stack depth errors. 2022-01-10 02:17:17 +01:00
DebaucheryLibrarian 43a0bc8a2c 1.204.7 2022-01-07 01:07:43 +01:00
DebaucheryLibrarian baebdbc0bb Adding comment listing sister sites for non-exclusive Gamma API scenes. 2022-01-07 01:07:41 +01:00
DebaucheryLibrarian 1c24cae3b1 1.204.6 2022-01-07 01:02:36 +01:00
DebaucheryLibrarian b9146aee5f Removed exclusive filter from Evil Angel parameters. 2022-01-07 01:02:34 +01:00
DebaucheryLibrarian 09bfcb01f5 1.204.5 2022-01-06 01:41:29 +01:00
DebaucheryLibrarian 5d80b6dc21 Added and improved Reality Kings logos. Added tag photos. 2022-01-06 01:41:26 +01:00
DebaucheryLibrarian 140a38c349 1.204.4 2021-12-31 01:45:06 +01:00
DebaucheryLibrarian 6760c11881 Disabled why-is-node-running to assess OOM. 2021-12-31 01:45:03 +01:00
DebaucheryLibrarian 2dcdbf9c37 1.204.3 2021-12-27 22:36:03 +01:00
DebaucheryLibrarian 3b958a02ef Added memory profiler configuration options. 2021-12-27 22:36:01 +01:00
DebaucheryLibrarian 605242b399 1.204.2 2021-12-27 17:29:33 +01:00
DebaucheryLibrarian 299f257a01 Logging memory usage on media fetch. 2021-12-27 17:29:23 +01:00
DebaucheryLibrarian 0ad64ef5f4 1.204.1 2021-12-20 03:29:16 +01:00
DebaucheryLibrarian 3bfe1e8fdb Storing scenes before fetching movies. 2021-12-20 03:29:14 +01:00
DebaucheryLibrarian 7d992f4129 Added triggers to memory dump. 2021-12-20 02:28:59 +01:00
DebaucheryLibrarian 280032937f Added centralized movie page fetcher. Added memory heap dump. 2021-12-20 02:22:10 +01:00
DebaucheryLibrarian d93670842b 1.204.0 2021-12-19 23:03:48 +01:00
DebaucheryLibrarian dc187a9a3a Added execute method to qu, removed runScripts from Gamma's fetchMovie to observe effect on memory usage. 2021-12-19 23:03:44 +01:00
DebaucheryLibrarian 5f89c6e14c 1.203.13 2021-12-19 00:08:22 +01:00
DebaucheryLibrarian 9f10420eb9 Fixed tag search GraphQL query. 2021-12-19 00:08:21 +01:00
DebaucheryLibrarian 9568370132 1.203.12 2021-12-18 23:44:54 +01:00
DebaucheryLibrarian 1c0c30be11 Improved and re-enabled why-is-node-running logger. 2021-12-18 23:44:51 +01:00
DebaucheryLibrarian cdb7dcd6e9 1.203.11 2021-12-18 23:22:38 +01:00
DebaucheryLibrarian 8e4be06675 Closing JSDOM window after deep scrapes in an attempt to save memory. 2021-12-18 23:22:35 +01:00
DebaucheryLibrarian de7a8c756a 1.203.10 2021-12-13 01:20:04 +01:00
DebaucheryLibrarian 65e2b72c6a Fixed Gamma movie scraper failing when data object is not available. 2021-12-13 01:20:02 +01:00
DebaucheryLibrarian 523c36ecd4 1.203.9 2021-12-11 22:46:58 +01:00
DebaucheryLibrarian 5b5688438c Fixed Gamma movie scene query. Added tag photos. 2021-12-11 22:46:55 +01:00
DebaucheryLibrarian 4ca07631c7 1.203.8 2021-12-05 23:59:20 +01:00
DebaucheryLibrarian ec4e7bc12a Updated Jules Jordan scraper for Sperm Swallowers and The Ass Factory. 2021-12-05 23:59:17 +01:00
DebaucheryLibrarian 26d15c0a6f Updated Jules Jordan scraper for Manuel Ferrara and Girl Girl. 2021-12-05 23:43:23 +01:00
DebaucheryLibrarian a484396db4 Hiding scenes with missing dates from network overview. Using computed effective date column. 2021-12-05 23:29:27 +01:00
DebaucheryLibrarian 681db02784 1.203.7 2021-12-05 02:54:57 +01:00
DebaucheryLibrarian e88554666c Reduced media concurrency to assess effect on memory. Moved qu context removal to deep scrape runner. Updated movie graphql queries. 2021-12-05 02:54:55 +01:00
DebaucheryLibrarian 9f37ec4cff 1.203.6 2021-12-04 00:32:31 +01:00
DebaucheryLibrarian abd063a578 Removed window map from http module to prevent memory pile-up with update scraping. 2021-12-04 00:32:28 +01:00
DebaucheryLibrarian 883e57ce1f 1.203.5 2021-12-02 15:51:33 +01:00
DebaucheryLibrarian ad04502a8c Added Radical favicons. 2021-12-02 15:51:30 +01:00
DebaucheryLibrarian f65ed16842 1.203.4 2021-12-02 00:45:24 +01:00
DebaucheryLibrarian 1918dd4ad5 Removing query methods from XEmpire release. 2021-12-02 00:45:22 +01:00
DebaucheryLibrarian 3983d3464f 1.203.3 2021-12-01 23:44:27 +01:00
DebaucheryLibrarian 61daf5f037 Added debug log for jsdom window closing. 2021-12-01 23:44:25 +01:00
DebaucheryLibrarian eafa144104 1.203.2 2021-12-01 23:39:11 +01:00
DebaucheryLibrarian 60c151ff6a Reduced deep scrape concurrency to 1. 2021-12-01 23:39:09 +01:00
DebaucheryLibrarian c97d18fcf9 1.203.1 2021-12-01 23:30:12 +01:00
DebaucheryLibrarian e41f9fa937 Added waitImmediate to deep scrape, reduced concurrency. 2021-12-01 23:30:10 +01:00
DebaucheryLibrarian 56a7fb0ad9 1.203.0 2021-12-01 17:26:34 +01:00
DebaucheryLibrarian e29cbc9fea Closing JSDOM window after deep scrape in an attempt to save memory. Reduced deep scrape concurrency to 5. 2021-12-01 17:26:13 +01:00
DebaucheryLibrarian 08f725a0b6 1.202.3 2021-12-01 00:00:26 +01:00
DebaucheryLibrarian b93a5715cb Updated Jules Jordan scraper for new update page layout. 2021-12-01 00:00:24 +01:00
DebaucheryLibrarian 2018d5c298 1.202.2 2021-11-29 02:49:12 +01:00
DebaucheryLibrarian 87094a9498 Replaced cheerio with qu in Gamma scraper. 2021-11-29 02:49:07 +01:00
DebaucheryLibrarian 53a1c697d0 1.202.1 2021-11-28 01:20:41 +01:00
DebaucheryLibrarian f04eb72891 Added upcoming scraper to PurgatoryX. 2021-11-28 01:20:39 +01:00
DebaucheryLibrarian dfeb0c08cf 1.202.0 2021-11-27 23:55:22 +01:00
DebaucheryLibrarian 9d7183ac69 Added PurgatoryX scraper. 2021-11-27 23:55:16 +01:00
DebaucheryLibrarian 2539e88f47 1.201.6 2021-11-22 02:51:55 +01:00
DebaucheryLibrarian 20d0d860d3 Fixed MindGeek scraper trying to acquire session from mindgeek.com 2021-11-22 02:51:52 +01:00
DebaucheryLibrarian 6b4aa64d74 Improved MindGeek scraper session check to prevent crash when network session isn't available yet. 2021-11-22 02:44:03 +01:00
DebaucheryLibrarian c7b9ec7a4b 1.201.5 2021-11-21 00:47:34 +01:00
DebaucheryLibrarian e81864ebde Removed verbose http queued output. 2021-11-21 00:47:32 +01:00
DebaucheryLibrarian 0305a22a24 Removed stray console log from media module. 2021-11-21 00:43:35 +01:00
DebaucheryLibrarian a406eb584d 1.201.4 2021-11-21 00:41:15 +01:00
DebaucheryLibrarian 2be3ea9bbb Explicitly adding headers to http module result. 2021-11-21 00:41:12 +01:00
DebaucheryLibrarian 0a8a7ff9a5 1.201.3 2021-11-21 00:31:12 +01:00
DebaucheryLibrarian 98c103c625 Fixed uuid import. Changed fs rmdir to rm. 2021-11-21 00:31:09 +01:00
DebaucheryLibrarian e0908a5f5e 1.201.2 2021-11-21 00:19:13 +01:00
DebaucheryLibrarian f0b7678444 Fixed upsert failing on empty insert array due breaking Knex API change. 2021-11-21 00:19:10 +01:00
DebaucheryLibrarian 64e9efe095 1.201.1 2021-11-21 00:15:21 +01:00
DebaucheryLibrarian ab29ab053e Increased tile heart button size. Hiding entity tile info under hover effect. 2021-11-21 00:15:19 +01:00
DebaucheryLibrarian a5081bc7c9 Updated primary color. 2021-11-21 00:04:21 +01:00
DebaucheryLibrarian da9c628f9b 1.201.0 2021-11-21 00:00:14 +01:00
DebaucheryLibrarian 26539b74a5 Updated dependencies. Added periodic memory logger. 2021-11-20 23:59:48 +01:00
DebaucheryLibrarian ccb99e278c Added periodic memory logger. 2021-11-20 23:59:15 +01:00
DebaucheryLibrarian a867817dc1 Improved scene tile scaling. 2021-10-31 01:00:12 +02:00
DebaucheryLibrarian d1e05915b5 Tweaked scene and actor tile design, tags grid breakpoints. 2021-10-31 00:31:18 +02:00
DebaucheryLibrarian b764fdec85 Showing scene and channel count on entity page and tile. 2021-10-30 22:41:58 +02:00
1180 changed files with 17171 additions and 12489 deletions

View File

@ -2,7 +2,7 @@
"root": true,
"extends": ["airbnb-base", "plugin:vue/recommended"],
"parserOptions": {
"parser": "babel-eslint",
"parser": "@babel/eslint-parser",
"ecmaVersion": 2019,
"sourceType": "module"
},
@ -17,10 +17,11 @@
"vue/html-indent": ["error", "tab"],
"vue/multiline-html-element-content-newline": 0,
"vue/singleline-html-element-content-newline": 0,
"vue/multi-word-component-names": 0,
"no-param-reassign": ["error", {
"props": true,
"ignorePropertyModificationsFor": ["state", "acc"]
}],
}]
},
"globals": {
"CONFIG": true

2
.gitignore vendored
View File

@ -2,6 +2,7 @@ node_modules/
dist/
log/
media/
html/
public/js/*
public/css/*
config/*
@ -9,3 +10,4 @@ config/*
assets/js/config/
!assets/js/config/default.js
*.heapprofile
*.heapsnapshot

2
.nvmrc
View File

@ -1 +1 @@
14.15.4
16.13.0

View File

@ -6,7 +6,7 @@
<div class="actor-header">
<h2 class="header-name">
<span v-if="actor.entity">{{ actor.name }} ({{ actor.entity.name }})</span>
<span v-else="">{{ actor.name }}</span>
<span v-else>{{ actor.name }}</span>
<Gender
:gender="actor.gender"

View File

@ -272,7 +272,7 @@ import Pagination from '../pagination/pagination.vue';
const toggleValues = [true, null, false];
const boobSizes = 'ABCDEFGHIJKZ'.split('');
const topCountries = ['AU', 'BR', 'DE', 'JP', 'RU', 'GB', 'US'];
const topCountries = ['AU', 'BR', 'CZ', 'DE', 'JP', 'RU', 'GB', 'US'];
function updateFilters() {
this.$router.push({

View File

@ -214,7 +214,7 @@ export default {
display: inline-block;
position: relative;
box-shadow: 0 0 3px var(--darken-weak);
background: var(--background);
background: var(--info);
overflow: hidden;
&::before {
@ -237,12 +237,8 @@ export default {
position: absolute;
top: 0;
left: 0;
color: var(--text);
color: var(--text-light);
text-decoration: none;
&:hover {
color: var(--primary);
}
}
.handle {
@ -253,7 +249,8 @@ export default {
box-shadow: 0 0 3px var(--shadow);
.name {
padding: .5rem;
padding: .25rem .5rem;
font-size: .9rem;
}
.alias {
@ -316,8 +313,8 @@ export default {
}
.stash {
width: 1.25rem;
height: 1.25rem;
width: 1.5rem;
height: 1.5rem;
padding: .25rem .25rem .5rem .5rem;
position: absolute;
top: 0;

View File

@ -46,7 +46,7 @@
/>
</li>
<template v-slot:tooltip>
<template #tooltip>
<Search
content="actors"
@select="actor => addActor(actor)"
@ -88,7 +88,7 @@
/>
</li>
<template v-slot:tooltip>
<template #tooltip>
<Search
content="tags"
:defaults="['anal', 'blowbang', 'mfm', 'dp', 'gangbang', 'airtight']"
@ -126,7 +126,7 @@
/>
</div>
<template v-slot:tooltip>
<template #tooltip>
<Search
label="Search channels"
content="entities"
@ -181,7 +181,7 @@
/>
</li>
<template v-slot:tooltip>
<template #tooltip>
<Search
content="stashes"
@select="stash => addStash(stash)"
@ -194,6 +194,7 @@
<div class="dialog-actions right">
<button
:disabled="actors.length === 0 && tags.length === 0 && !entity"
type="submit"
class="button button-primary"
>Add alert</button>
@ -210,19 +211,19 @@ import Search from './search.vue';
async function addAlert() {
await this.$store.dispatch('addAlert', {
actors: this.actors.map(actor => actor.id),
tags: this.tags.map(tag => tag.id),
actors: this.actors.map((actor) => actor.id),
tags: this.tags.map((tag) => tag.id),
entity: this.entity?.id,
notify: this.notify,
email: this.email,
stashes: this.stashes.map(stash => stash.id),
stashes: this.stashes.map((stash) => stash.id),
});
this.$emit('close', true);
}
function addActor(actor) {
if (!this.actors.some(selectedActor => selectedActor.id === actor.id)) {
if (!this.actors.some((selectedActor) => selectedActor.id === actor.id)) {
this.actors = this.actors.concat(actor);
}
@ -235,7 +236,7 @@ function addEntity(entity) {
}
function addTag(tag) {
if (!this.tags.some(selectedTag => selectedTag.id === tag.id)) {
if (!this.tags.some((selectedTag) => selectedTag.id === tag.id)) {
this.tags = this.tags.concat(tag);
}
@ -243,7 +244,7 @@ function addTag(tag) {
}
function removeActor(actor) {
this.actors = this.actors.filter(listedActor => listedActor.id !== actor.id);
this.actors = this.actors.filter((listedActor) => listedActor.id !== actor.id);
}
function removeEntity() {
@ -251,11 +252,11 @@ function removeEntity() {
}
function removeTag(tag) {
this.tags = this.tags.filter(listedTag => listedTag.id !== tag.id);
this.tags = this.tags.filter((listedTag) => listedTag.id !== tag.id);
}
function addStash(stash) {
if (!this.stashes.some(selectedStash => selectedStash.id === stash.id)) {
if (!this.stashes.some((selectedStash) => selectedStash.id === stash.id)) {
this.stashes = this.stashes.concat(stash);
}
@ -263,7 +264,7 @@ function addStash(stash) {
}
function removeStash(stash) {
this.stashes = this.stashes.filter(listedStash => listedStash.id !== stash.id);
this.stashes = this.stashes.filter((listedStash) => listedStash.id !== stash.id);
}
export default {
@ -273,6 +274,7 @@ export default {
Entity,
Search,
},
emits: ['close'],
data() {
return {
actors: [],
@ -284,7 +286,6 @@ export default {
availableStashes: this.$store.state.auth.user.stashes,
};
},
emits: ['close'],
methods: {
addActor,
addAlert,

View File

@ -62,7 +62,7 @@ async function setConsent(consent, includeQueer) {
}
if (includeQueer) {
this.$store.dispatch('setTagFilter', this.$store.state.ui.tagFilter.filter(tag => !['gay', 'bisexual', 'transsexual'].includes(tag)));
this.$store.dispatch('setTagFilter', this.$store.state.ui.tagFilter.filter((tag) => !['gay', 'bisexual', 'transsexual'].includes(tag)));
return;
}

View File

@ -51,7 +51,7 @@
>{{ tag.name }}</li>
</ul>
<router-link
<RouterLink
v-if="entity.parent"
:to="`/${entity.parent.type}/${entity.parent.slug}`"
class="link link-parent"
@ -74,7 +74,7 @@
>{{ entity.parent.name }}</h3>
<Icon icon="device_hub" />
</router-link>
</RouterLink>
</div>
<div
@ -108,6 +108,7 @@
:fetch-releases="fetchEntity"
:items-total="totalCount"
:items-per-page="limit"
:available-tags="entity.tags"
/>
<div class="releases">
@ -153,8 +154,8 @@ async function fetchEntity(scroll = true) {
this.pageTitle = entity.name;
const campaign = entity.campaigns.find(campaignX => !campaignX.banner)
|| entity.parent?.campaigns.find(campaignX => !campaignX.banner);
const campaign = entity.campaigns.find((campaignX) => !campaignX.banner)
|| entity.parent?.campaigns.find((campaignX) => !campaignX.banner);
const affiliateParams = new URLSearchParams({
...(entity.url && Object.fromEntries(new URL(entity.url).searchParams)), // preserve any query in entity URL, e.g. ?siteId=5

View File

@ -4,6 +4,7 @@
:title="entity.name"
class="tile"
>
<div class="tile-logo">
<template v-if="entity.hasLogo">
<img
v-if="entity.type === 'network' || entity.independent"
@ -37,6 +38,15 @@
v-else
class="name"
>{{ entity.name }}</span>
</div>
<span
v-if="entity.childrenTotal > 0 || typeof entity.sceneTotal !== 'undefined'"
class="count"
>
<span v-if="typeof entity.sceneTotal !== 'undefined'">{{ entity.sceneTotal }} scenes</span>
<span v-if="entity.type === 'network'">{{ entity.childrenTotal }} channels</span>
</span>
</router-link>
</template>
@ -59,15 +69,28 @@ export default {
height: 100%;
background: var(--tile);
display: flex;
flex-direction: column;
flex-shrink: 0;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding: .5rem 1rem;
border-radius: .25rem;
position: relative;
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
text-align: center;
text-decoration: none;
overflow: hidden;
&:hover .count {
bottom: 0;
}
}
.tile-logo {
display: flex;
flex-grow: 1;
padding: .5rem 1rem;
overflow: hidden;
}
.logo {
@ -75,11 +98,30 @@ export default {
max-height: 100%;
display: flex;
align-items: center;
align-self: center;
}
.name {
display: flex;
align-items: center;
color: var(--text-light);
font-size: 1.25rem;
font-weight: bold;
}
.count {
display: flex;
justify-content: space-between;
width: 100%;
position: absolute;
bottom: -1.75rem;
box-sizing: border-box;
padding: .25rem .5rem;
background: var(--darken-strong);
box-shadow: 0 0 3px var(--darken);
color: var(--text-light);
text-align: center;
text-shadow: 1px 1px var(--darken);
transition: bottom .1s ease;
}
</style>

View File

@ -1,31 +1,33 @@
<template>
<div class="filter-bar noselect">
<div class="sort">
<router-link
<RouterLink
v-for="section in ranges"
:key="section"
:to="{ params: { range: section, pageNumber: 1 }, query: $route.query }"
:class="{ active: $route.name === section || range === section }"
class="range range-button"
>{{ section }}</router-link>
>{{ section }}</RouterLink>
</div>
<span
v-if="itemsTotal && showTotal"
class="total"
>{{ itemsTotal }} <template v-if="itemsTotal === 1">scene</template><template v-else>scenes</template></span>
<div class="filters">
<ActorFilter
class="filters-filter"
:filter="filter"
:available-actors="availableActors"
/>
<ChannelFilter
class="filters-filter"
:filter="filter"
:available-channels="availableChannels"
/>
<TagFilter
class="filters-filter"
:filter="filter"
:available-tags="availableTags"
/>
</div>
@ -39,10 +41,6 @@ import ActorFilter from './actor-filter.vue';
import ChannelFilter from './channel-filter.vue';
import TagFilter from './tag-filter.vue';
function filter(state) {
return state.ui.filter;
}
function range() {
return this.$route.params.range;
}
@ -78,6 +76,10 @@ export default {
type: Boolean,
default: false,
},
showTotal: {
type: Boolean,
default: true,
},
itemsTotal: {
type: Number,
default: 0,
@ -105,7 +107,6 @@ export default {
},
computed: {
...mapState({
filter,
range,
batch,
}),
@ -120,6 +121,43 @@ export default {
<style lang="scss">
@import 'breakpoints';
.filter {
color: var(--shadow);
display: inline-flex;
align-items: center;
.filter-applied {
flex-grow: 1;
padding: .75rem .5rem;
font-size: 1rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: right;
&.empty {
color: var(--shadow);
}
}
.icon {
fill: var(--shadow);
margin: -.1rem 0 0 0;
}
&:hover {
cursor: pointer;
.applied {
color: var(--shadow-strong);
}
.icon {
fill: var(--shadow-strong);
}
}
}
.filter-mode {
width: 100%;
color: var(--shadow);
@ -240,6 +278,10 @@ export default {
.filters-filter:last-child .filter {
padding: .5rem 0 .5rem .5rem;
}
.total {
display: none;
}
}
</style>
@ -261,43 +303,6 @@ export default {
}
}
::v-deep(.filter) {
color: var(--shadow);
display: inline-flex;
align-items: center;
.filter-applied {
flex-grow: 1;
padding: .75rem .5rem;
font-size: 1rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: right;
&.empty {
color: var(--shadow);
}
}
.icon {
fill: var(--shadow);
margin: -.1rem 0 0 0;
}
&:hover {
cursor: pointer;
.applied {
color: var(--shadow-strong);
}
.icon {
fill: var(--shadow-strong);
}
}
}
.filters {
flex-shrink: 0;
}
@ -351,4 +356,11 @@ export default {
margin: 0 1rem 0 0;
}
}
.total {
flex-shrink: 0;
padding: 0 1rem;
color: var(--shadow);
font-size: .8rem;
}
</style>

View File

@ -14,7 +14,7 @@
>Tags</div>
</div>
<template v-slot:tooltip>
<template #tooltip>
<div
class="filter-options"
@click.stop
@ -70,7 +70,7 @@
<script>
function getNewRange(tag) {
if (this.selectedTags.includes(tag)) {
return { tags: this.selectedTags.filter(selectedTag => selectedTag !== tag).join(',') || undefined };
return { tags: this.selectedTags.filter((selectedTag) => selectedTag !== tag).join(',') || undefined };
}
return { tags: this.selectedTags.concat(tag).join(',') };
@ -82,10 +82,6 @@ function selectedTags() {
export default {
props: {
filter: {
type: Array,
default: () => [],
},
compact: {
type: Boolean,
default: false,

View File

@ -8,6 +8,7 @@
:items-total="totalCount"
:items-per-page="limit"
:content="$refs.content"
:show-total="false"
/>
<Releases

View File

@ -28,7 +28,7 @@ export default {
};
},
beforeMount() {
this.svg = require(`../../img/icons/${this.icon}.svg`).default;
this.svg = require(`../../img/icons/${this.icon}.svg`).default; // eslint-disable-line global-require, import/no-dynamic-require
},
};
</script>

View File

@ -11,8 +11,22 @@
class="empty"
>No results for "{{ $route.query.query }}"</span>
<template v-else>
<h2 class="heading">Popular</h2>
<div
class="entity-tiles"
>
<Entity
v-for="entity in popularEntities"
:key="entity.parent ? `entity-tile-${entity.parent.slug}-${entity.slug}` : `entity-tile-${entity.slug}`"
:entity="entity"
/>
</div>
<h2 class="heading">All networks</h2>
<div
v-else
class="entity-tiles"
>
<Entity
@ -21,6 +35,7 @@
:entity="entity"
/>
</div>
</template>
</div>
<Footer />
@ -58,6 +73,45 @@ async function searchEntities() {
this.done = true;
}
function popularEntities() {
const entitiesBySlug = Object.fromEntries(this.entities.map((entity) => [entity.slug, entity]));
return [
'21sextury',
'amateurallure',
'analvids',
'bamvisions',
'bang',
'bangbros',
'blowpass',
'brazzers',
'burningangel',
'digitalplayground',
'dogfartnetwork',
'dorcel',
'elegantangel',
'evilangel',
'fakehub',
'girlsway',
'hookuphotshot',
'hussiepass',
'insex',
'julesjordan',
'kellymadison',
'kink',
'mofos',
'naughtyamerica',
'newsensations',
'pervcity',
'pornpros',
'private',
'realitykings',
'twistys',
'vixen',
'xempire',
].map((slug) => entitiesBySlug[slug]).filter(Boolean);
}
async function mounted() {
this.pageTitle = 'Channels';
@ -82,6 +136,7 @@ export default {
},
computed: {
channelCount,
popularEntities,
},
watch: {
$route: fetchEntities,
@ -130,6 +185,10 @@ export default {
font-weight: bold;
}
.heading {
margin: 1rem 0 0 0;
}
@media(max-width: $breakpoint2) {
.entity-tiles {
grid-gap: .5rem;

View File

@ -2,7 +2,7 @@
<div class="media-container">
<div
class="media"
:class="{ center: release.photos.length < 2, preview: !me }"
:class="{ center: (release.photos?.length || 0) + (release.scenesPhotos?.length || 0) < 2, preview: !me }"
>
<div
v-if="release.trailer || release.teaser"
@ -71,10 +71,13 @@
</span>
</div>
<template v-if="release.covers && release.covers.length > 0">
<a
<template v-if="release.covers?.length > 0">
<div
v-for="cover in release.covers"
:key="`cover-${cover.id}`"
class="item-container"
>
<a
:href="getPath(cover)"
target="_blank"
rel="noopener noreferrer"
@ -89,6 +92,7 @@
@load="$emit('load', $event)"
>
</a>
</div>
</template>
<div
@ -164,8 +168,8 @@ function poster() {
function photos() {
const clips = this.release.clips || [];
const clipPostersById = clips.reduce((acc, clip) => ({ ...acc, [clip.poster.id]: clip.poster }), {});
const uniqueClipPosters = Array.from(new Set(clips.map(clip => clip.poster.id) || [])).map(posterId => clipPostersById[posterId]);
const photosWithClipPosters = (this.release.photos || []).concat(uniqueClipPosters);
const uniqueClipPosters = Array.from(new Set(clips.map((clip) => clip.poster.id) || [])).map((posterId) => clipPostersById[posterId]);
const photosWithClipPosters = (this.release.photos || []).concat(this.release.scenesPhotos || []).concat(uniqueClipPosters);
if (this.release.trailer || (this.release.teaser && this.release.teaser.mime !== 'image/gif')) {
// poster will be on trailer video

View File

@ -14,6 +14,12 @@
loading="lazy"
>
<div
v-else
:title="movie.title"
class="unavailable"
><Icon icon="blocked" /></div>
<Icon
v-show="(!stash || stash.primary) && favorited"
icon="heart7"
@ -161,7 +167,6 @@ export default {
}
.movie {
height: 16rem;
display: flex;
}
@ -171,18 +176,30 @@ export default {
}
.cover {
height: 100%;
height: 16rem;
width: 11.25rem;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
position: relative;
box-shadow: 0 0 3px var(--darken-weak);
background-color: var(--shadow-hint);
img {
height: 100%;
max-width: 12rem;
width: 100%;
background-position: center;
background-size: cover;
object-fit: cover;
object-position: center;
}
.unavailable .icon {
width: 2rem;
height: 2rem;
fill: var(--shadow-hint);
}
}
.info {
@ -252,12 +269,12 @@ export default {
}
.stash {
width: 1.25rem;
height: 1.25rem;
padding: .25rem .5rem .5rem .25rem;
width: 1.5rem;
height: 1.5rem;
padding: .25rem .5rem .5rem .5rem;
position: absolute;
top: 0;
right: 0;
left: 0;
fill: var(--lighten-weak);
filter: drop-shadow(0 0 2px var(--darken));
@ -273,8 +290,9 @@ export default {
}
@media(max-width: $breakpoint-kilo) {
.movie {
.cover {
height: 12rem;
width: 8.25rem;
}
/* ensure no half actor names show */

View File

@ -21,14 +21,14 @@
<Details :release="release" />
<button
v-if="release.photos.length > 0"
v-if="release.photos?.length > 0 || release.scenesPhotos?.length > 0"
class="album-toggle"
@click="$router.push({ hash: '#album' })"
><Icon icon="grid3" />View album</button>
<Album
v-if="showAlbum"
:items="[release.poster, ...release.photos]"
:items="[release.poster, ...(release.photos || []), ...(release.scenesPhotos || [])]"
:title="release.title"
:path="config.media.mediaPath"
@close="$router.replace({ hash: undefined })"
@ -79,22 +79,23 @@
/>
<div
v-if="release.movies && release.movies.length > 0"
v-if="release.movies?.length > 0 || release.series?.length > 0"
class="row"
>
<span class="row-label">Part of</span>
<div class="movies">
<router-link
v-for="movie in release.movies"
v-for="movie in [...release.movies, ...release.series]"
:key="`movie-${movie.id}`"
:to="{ name: 'movie', params: { releaseId: movie.id, releaseSlug: movie.slug } }"
:to="{ name: movie.type || 'movie', params: { releaseId: movie.id, releaseSlug: movie.slug } }"
class="movie"
>
<span class="movie-title">{{ movie.title }}</span>
<img
v-if="movie.covers.length > 0"
:src="getPath(movie.covers[0], 'thumbnail')"
v-if="movie.covers.length > 0 || movie.poster"
:src="getPath(movie.covers[0] || movie.poster, 'thumbnail')"
class="movie-cover"
>
</router-link>
@ -243,6 +244,10 @@ async function fetchRelease(scroll = true) {
this.release = await this.$store.dispatch('fetchMovieById', this.$route.params.releaseId);
}
if (this.$route.name === 'serie') {
this.release = await this.$store.dispatch('fetchSerieById', this.$route.params.releaseId);
}
if (scroll && this.$refs.content) {
this.$refs.content.scrollTop = 0;
}
@ -278,11 +283,11 @@ function bannerBackground() {
function pageTitle() {
return this.release
&& (this.release.title
|| (this.release.actors.length > 0 ? `${this.release.actors.map(actor => actor.name).join(', ')} for ${this.release.entity.name}` : null));
|| (this.release.actors.length > 0 ? `${this.release.actors.map((actor) => actor.name).join(', ')} for ${this.release.entity.name}` : null));
}
function showAlbum() {
return this.release.photos?.length > 0 && this.$route.hash === '#album';
return (this.release.photos?.length > 0 || this.release.scenesPhotos?.length > 0) && this.$route.hash === '#album';
}
export default {

View File

@ -126,10 +126,29 @@ export default {
font-weight: bold;
}
@media(max-width: $breakpoint-mega) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
}
}
@media(max-width: $breakpoint-kilo) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(18.5rem, 1fr));
grid-gap: .5rem;
padding: .5rem;
}
}
@media(max-width: $breakpoint) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
}
}
@media(max-width: $breakpoint-micro) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
}
}
</style>

View File

@ -113,21 +113,22 @@
:key="actor.id"
class="actor"
>
<router-link
<RouterLink
:to="{ name: 'actor', params: { actorId: actor.id, actorSlug: actor.slug } }"
:class="{ [actor.gender]: !!actor.gender }"
class="actor-link"
>{{ actor.name }}</router-link>
>{{ actor.name }}</RouterLink>
</li>
</ul>
</span>
<div class="labels">
<router-link
<RouterLink
v-if="release.shootId && release.studio"
:to="`/studio/${release.studio.slug}`"
:title="release.studio && release.studio.name"
class="shoot nolink"
>{{ release.shootId }}</router-link>
>{{ release.shootId }}</RouterLink>
<span
v-else-if="release.shootId"
@ -145,10 +146,10 @@
:key="`tag-${tag.slug}`"
class="tag"
>
<router-link
<RouterLink
:to="`/tag/${tag.slug}`"
class="tag-link"
>{{ tag.name }}</router-link>
>{{ tag.name }}</RouterLink>
</li>
</ul>
</div>
@ -233,20 +234,23 @@ export default {
box-shadow: 0 0 3px var(--darken-weak);
&.new .poster::after {
content: '';
content: 'new';
position: absolute;
top: 0;
left: 0;
width: 1rem;
height: 1rem;
display: flex;
align-items: center;
justify-content: center;
bottom: 0;
right: .5rem;
width: 2rem;
box-sizing: border-box;
margin: .25rem;
border-radius: 0 0 .5rem 0;
color: var(--primary);
font-size: 1rem;
padding: .1rem 0 .05rem 0;
border-radius: .25rem .25rem 0 0;
background: var(--info);
color: var(--text-light);
font-size: .7rem;
font-weight: bold;
line-height: 1;
text-shadow: 0 0 2px var(--darken-weak);
box-shadow: 0 0 3px var(--shadow);
}
&:hover .unstashed,
@ -295,8 +299,8 @@ export default {
}
.stash {
width: 1.25rem;
height: 1.25rem;
width: 1.5rem;
height: 1.5rem;
position: absolute;
top: 0;
right: 0;
@ -317,17 +321,18 @@ export default {
}
.row {
max-width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 0 .5rem;
margin: 0 0 .1rem 0;
}
.info {
display: flex;
flex-direction: column;
align-items: flex-start;
flex-grow: 1;
overflow: hidden;
}
@ -339,7 +344,7 @@ export default {
.title {
margin: 0;
color: var(--text);
font-size: 1rem;
font-size: .9rem;
line-height: 1.5;
white-space: nowrap;
text-overflow: ellipsis;
@ -365,8 +370,9 @@ export default {
}
.actor-link {
color: var(--link);
color: var(--text);
text-decoration: none;
font-size: .9rem;
&:hover {
color: var(--primary);
@ -374,7 +380,7 @@ export default {
}
.labels {
padding: 0 .5rem 1.5rem .5rem;
padding: 0 .5rem 1.25rem .5rem;
max-height: .5rem;
overflow-y: hidden;
font-size: 0;
@ -405,11 +411,11 @@ export default {
}
.tag-link {
background: var(--background);
background: var(--shadow-touch);
color: var(--shadow);
display: inline-block;
padding: .25rem .5rem;
border: solid 1px var(--shadow-hint);
margin: 0 1px 0 0;
font-size: .75rem;
font-weight: bold;
text-decoration: none;
@ -421,14 +427,20 @@ export default {
}
.details-wide {
margin: 0 0 .5rem 0;
margin: 0 0 .4rem 0;
}
.details-compact {
display: none;
}
@media(max-width: $breakpoint-kilo) {
@media(max-width: $breakpoint) {
.thumbnail {
height: 11rem;
}
}
@media(max-width: $breakpoint-micro) {
.tile-body {
flex-direction: row;
}
@ -474,14 +486,15 @@ export default {
}
.tile.new .poster::after {
bottom: 0;
top: auto;
margin: .1rem .25rem;
top: 0;
right: .25rem;
bottom: auto;
border-radius: 0 0 .25rem .25rem;
padding: .05rem 0 .1rem 0;
}
.stash {
left: 0;
right: auto;
padding: .25rem .5rem .5rem .25rem;
}
}

View File

@ -57,10 +57,7 @@
target="_blank"
rel="noopener noreferrer"
class="date"
><Icon
v-if="release.url"
icon="share2"
/>{{ formatDate(release.date, 'MMMM D, YYYY', release.datePrecision) }}</a>
>{{ formatDate(release.date, 'MMMM D, YYYY', release.datePrecision) }}</a>
<a
v-else
@ -91,27 +88,17 @@ export default {
width: 100%;
display: flex;
justify-content: space-between;
z-index: 1;
white-space: nowrap;
background: var(--profile);
background: var(--info);
font-size: 0;
font-weight: bold;
.favicon {
width: 2rem;
box-sizing: border-box;
padding: .5rem;
padding: .4rem .5rem;
}
/*
&.new .date::before {
content: '';
width: .5rem;
height: .5rem;
border-radius: 50%;
margin: 0 .25rem 0 0;
background: var(--primary);
}
*/
}
.site,
@ -120,7 +107,7 @@ export default {
align-items: center;
position: relative;
font-size: .8rem;
padding: .5rem;
padding: .4rem .5rem;
color: var(--text-light);
text-decoration: none;

View File

@ -45,6 +45,8 @@ const tagSlugsByCategory = {
'teen',
'milf',
'blowjob',
'gay',
'transsexual',
'dp',
'gangbang',
'facial',
@ -64,6 +66,11 @@ const tagSlugsByCategory = {
'tattoos',
'piercings',
],
sexuality: [
'gay',
'bisexual',
'transsexual',
],
oral: [
'blowjob',
'pussy-eating',
@ -80,7 +87,6 @@ const tagSlugsByCategory = {
'titty-fucking',
'fisting',
'anal-fisting',
'fisting-dp',
],
group: [
'mfm',
@ -101,16 +107,6 @@ const tagSlugsByCategory = {
'bukkake',
'fake-cum',
],
toys: [
'toys',
'toy-anal',
'toy-dp',
'double-dildo',
'double-dildo-blowjob',
'double-dildo-kiss',
'double-dildo-anal',
'double-dildo-dp',
],
roleplay: [
'family',
'parody',
@ -119,6 +115,15 @@ const tagSlugsByCategory = {
'maid',
'nun',
],
extreme: [
'dp',
'airtight',
'dap',
'dvp',
'triple-penetration',
'tap',
'tvp',
],
fetish: [
'bdsm',
'femdom',
@ -127,15 +132,15 @@ const tagSlugsByCategory = {
'latex',
'blindfold',
],
extreme: [
'dp',
'airtight',
'dap',
'dvp',
'da-tp',
'dv-tp',
'tap',
'tvp',
toys: [
'toys',
'toy-anal',
'toy-dp',
'double-dildo',
'double-dildo-blowjob',
'double-dildo-kiss',
'double-dildo-anal',
'double-dildo-dp',
],
misc: [
'gaping',
@ -162,10 +167,18 @@ async function fetchTags() {
const tagsBySlug = tags.reduce((acc, tag) => ({ ...acc, [tag.slug]: tag }), {});
this.categories = Object.entries(tagSlugsByCategory).reduce((acc, [category, tagSlugs]) => ({
this.categories = Object.entries(tagSlugsByCategory).reduce((acc, [category, tagSlugs]) => {
const categoryTags = tagSlugs.map((tagSlug) => tagsBySlug[tagSlug]).filter(Boolean);
if (categoryTags.length === 0) {
return acc;
}
return {
...acc,
[category]: tagSlugs.map(tagSlug => tagsBySlug[tagSlug]),
}), {});
[category]: categoryTags,
};
}, {});
}
async function searchTags() {
@ -202,6 +215,7 @@ export default {
},
watch: {
$route: fetchTags,
'$store.state.ui.tagFilter': fetchTags,
},
mounted,
methods: {
@ -212,7 +226,7 @@ export default {
</script>
<style lang="scss" scoped>
@import 'theme';
@import 'breakpoints';
.tags {
display: flex;
@ -244,22 +258,81 @@ export default {
margin: 0 0 .25rem 0;
}
@media(max-width: $breakpoint3) {
@media(max-width: $breakpoint-mega) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(18rem, .5fr));
grid-template-columns: repeat(auto-fill, minmax(17.75rem, .5fr));
}
::v-deep(.poster),
::v-deep(.blank) {
height: 12rem;
}
}
@media(max-width: $breakpoint-kilo) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
grid-gap: .5rem;
}
::v-deep(.poster),
::v-deep(.blank) {
height: 14rem;
}
}
@media(max-width: $breakpoint) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
grid-template-columns: repeat(auto-fill, minmax(14.5rem, 1fr));
grid-gap: .5rem;
}
::v-deep(.poster),
::v-deep(.blank) {
height: 11rem;
}
}
@media(max-width: $breakpoint0) {
@media(max-width: $breakpoint-small) {
::v-deep(.poster),
::v-deep(.blank) {
height: 10rem;
}
}
@media(max-width: $breakpoint-micro) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
}
::v-deep(.poster),
::v-deep(.blank) {
height: 7.5rem;
}
}
@media(max-width: $breakpoint-mini) {
.tiles {
grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
}
::v-deep(.poster),
::v-deep(.blank) {
height: 12rem;
}
}
@media(max-width: $breakpoint-nano) {
::v-deep(.poster),
::v-deep(.blank) {
height: 10rem;
}
}
@media(max-width: $breakpoint-pico) {
::v-deep(.poster),
::v-deep(.blank) {
height: 8rem;
}
}
</style>

View File

@ -44,6 +44,11 @@
&:hover {
background: var(--primary-strong);
}
&:disabled {
background: var(--shadow-weak);
cursor: default;
}
}
.button-secondary {

View File

@ -5,10 +5,17 @@ $breakpoint3: 1200px;
$breakpoint4: 1500px;
:root {
--primary: #f65596;
--primary-strong: #f90071;
--primary-faded: #ffcce4;
/*
--primary: #f04288;
--primary: #ff6c88;
--primary-strong: #ff4166;
--primary-faded: #ffdfee;
/*
--primary: #f28;
--primary-strong: #f90071;
--primary-faded: #ffcce4;
@ -39,6 +46,8 @@ $breakpoint4: 1500px;
--logo-shadow: drop-shadow(1px 0 0 $shadow-weak) drop-shadow(-1px 0 0 $shadow-weak) drop-shadow(0 1px 0 $shadow-weak) drop-shadow(0 -1px 0 $shadow-weak);
--logo-highlight: drop-shadow(0 0 1px $highlight);
--info: #321b24;
--male: #0af;
--female: #f0a;

View File

@ -281,7 +281,7 @@ function initActorActions(store, router) {
return {
actor: curateActor(actor, null, curateRelease),
releases: actor.scenesConnection.releases.map(release => curateRelease(release)),
releases: actor.scenesConnection.releases.map((release) => curateRelease(release)),
totalCount: actor.scenesConnection.totalCount,
};
}
@ -429,7 +429,7 @@ function initActorActions(store, router) {
});
return {
actors: actors.map(actor => curateActor(actor)),
actors: actors.map((actor) => curateActor(actor)),
totalCount,
countries,
};

View File

@ -1,5 +1,5 @@
function favoritesStash(state) {
return state.user.stashes.find(stash => stash.slug === 'favorites');
return state.user.stashes.find((stash) => stash.slug === 'favorites');
}
module.exports = {

View File

@ -31,8 +31,8 @@ function curateActor(actor, release) {
if (actor.profiles) {
const photos = actor.profiles
.map(profile => ({ entity: profile.entity, ...profile.avatar }))
.filter(avatar => avatar.id && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash));
.map((profile) => ({ entity: profile.entity, ...profile.avatar }))
.filter((avatar) => avatar.id && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash));
const descriptions = actor.profiles.reduce((acc, profile) => ({
...acc,
@ -57,34 +57,38 @@ function curateActor(actor, release) {
}
if (actor.stashes) {
curatedActor.stashes = actor.stashes.filter(Boolean).map(stash => curateStash(stash.stash || stash)); // eslint-disable-line no-use-before-define
curatedActor.stashes = actor.stashes.filter(Boolean).map((stash) => curateStash(stash.stash || stash)); // eslint-disable-line no-use-before-define
}
curatedActor.stashes = actor.stashes?.map(stash => stash.stash || stash) || [];
curatedActor.stashes = actor.stashes?.map((stash) => stash.stash || stash) || [];
return curatedActor;
}
function curateRelease(release) {
function curateRelease(release, type = 'scene') {
const curatedRelease = {
...release,
type: release.type || type,
actors: [],
poster: release.poster && release.poster.media,
tags: release.tags ? release.tags.map(tag => tag.tag || tag) : [],
tags: release.tags ? release.tags.map((tag) => tag.tag || tag) : [],
};
if (release.scenes) curatedRelease.scenes = release.scenes.filter(Boolean).map(({ scene }) => curateRelease(scene));
if (release.movies) curatedRelease.movies = release.movies.filter(Boolean).map(({ movie }) => curateRelease(movie));
if (release.chapters) curatedRelease.chapters = release.chapters.filter(Boolean).map(chapter => curateRelease(chapter));
if (release.photos) curatedRelease.photos = release.photos.filter(Boolean).map(photo => photo.media || photo);
if (release.covers) curatedRelease.covers = release.covers.filter(Boolean).map(({ media }) => media);
curatedRelease.scenes = release.scenes?.filter(Boolean).map(({ scene }) => curateRelease(scene, 'scene')) || [];
curatedRelease.movies = release.movies?.filter(Boolean).map(({ movie }) => curateRelease(movie, 'movie')) || [];
curatedRelease.series = release.series?.filter(Boolean).map(({ serie }) => curateRelease(serie, 'serie')) || [];
curatedRelease.chapters = release.chapters?.filter(Boolean).map((chapter) => curateRelease(chapter)) || [];
curatedRelease.photos = release.photos?.filter(Boolean).map((photo) => photo.media || photo) || [];
curatedRelease.scenesPhotos = release.scenesPhotos?.filter(Boolean).map((photo) => photo.media || photo) || [];
curatedRelease.covers = release.covers?.filter(Boolean).map(({ media }) => media) || [];
if (release.trailer) curatedRelease.trailer = release.trailer.media;
if (release.teaser) curatedRelease.teaser = release.teaser.media;
if (release.actors) curatedRelease.actors = release.actors.filter(Boolean).map(actor => curateActor(actor.actor || actor, curatedRelease));
if (release.directors) curatedRelease.directors = release.directors.filter(Boolean).map(director => curateActor(director.director || director, curatedRelease));
if (release.actors) curatedRelease.actors = release.actors.filter(Boolean).map((actor) => curateActor(actor.actor || actor, curatedRelease));
if (release.directors) curatedRelease.directors = release.directors.filter(Boolean).map((director) => curateActor(director.director || director, curatedRelease));
if (release.movieTags && release.movieTags.length > 0) curatedRelease.tags = release.movieTags.filter(Boolean).map(({ tag }) => tag);
if (release.movieActors && release.movieActors.length > 0) curatedRelease.actors = release.movieActors.filter(Boolean).map(({ actor }) => curateActor(actor, curatedRelease));
if (release.stashes) curatedRelease.stashes = release.stashes.filter(Boolean).map(stash => curateStash(stash.stash || stash)); // eslint-disable-line no-use-before-define
if (release.stashes) curatedRelease.stashes = release.stashes.filter(Boolean).map((stash) => curateStash(stash.stash || stash)); // eslint-disable-line no-use-before-define
if (release.productionLocation) {
curatedRelease.productionLocation = {
@ -105,17 +109,20 @@ function curateEntity(entity, parent, releases) {
};
if (entity.tags) curatedEntity.tags = entity.tags.map(({ tag }) => tag);
if (entity.sceneTags) curatedEntity.sceneTags = entity.sceneTags;
if (entity.children) {
if (entity.children.nodes) {
curatedEntity.children = entity.children.nodes.map(childEntity => curateEntity(childEntity, curatedEntity));
curatedEntity.children = entity.children.nodes.map((childEntity) => curateEntity(childEntity, curatedEntity));
}
curatedEntity.childrenTotal = entity.children.totalCount;
}
if (entity.parent || parent) curatedEntity.parent = curateEntity(entity.parent || parent);
if (releases) curatedEntity.releases = releases.map(release => curateRelease(release));
if (releases) curatedEntity.releases = releases.map((release) => curateRelease(release));
curatedEntity.sceneTotal = entity.sceneTotal;
return curatedEntity;
}
@ -138,7 +145,7 @@ function curateStash(stash) {
if (stash.scenes || stash.scenesConnection?.scenes) {
curatedStash.sceneTotal = stash.scenesConnection?.totalCount || null;
curatedStash.scenes = (stash.scenesConnection?.scenes || stash.scenes).map(item => ({
curatedStash.scenes = (stash.scenesConnection?.scenes || stash.scenes).map((item) => ({
...item,
scene: curateRelease(item.scene),
}));
@ -146,7 +153,7 @@ function curateStash(stash) {
if (stash.actors || stash.actorsConnection?.actors) {
curatedStash.actorTotal = stash.actorsConnection?.totalCount || null;
curatedStash.actors = (stash.actorsConnection?.actors || stash.actors).map(item => ({
curatedStash.actors = (stash.actorsConnection?.actors || stash.actors).map((item) => ({
...item,
actor: curateActor(item.actor),
}));
@ -154,7 +161,7 @@ function curateStash(stash) {
if (stash.movies || stash.moviesConnection?.movies) {
curatedStash.movieTotal = stash.moviesConnection?.totalCount || null;
curatedStash.movies = (stash.moviesConnection?.movies || stash.movies).map(item => ({
curatedStash.movies = (stash.moviesConnection?.movies || stash.movies).map((item) => ({
...item,
movie: curateRelease(item.movie),
}));
@ -171,11 +178,11 @@ function curateAlert(alert) {
const curatedAlert = alert;
if (alert.actors) {
curatedAlert.actors = alert.actors.map(actor => curateActor(actor.actor || actor));
curatedAlert.actors = alert.actors.map((actor) => curateActor(actor.actor || actor));
}
if (alert.tags) {
curatedAlert.tags = alert.tags.map(tag => curateTag(tag.tag || tag));
curatedAlert.tags = alert.tags.map((tag) => curateTag(tag.tag || tag));
}
if (alert.entity) {
@ -183,7 +190,7 @@ function curateAlert(alert) {
}
if (alert.stashes) {
curatedAlert.stashes = alert.stashes.map(stash => curateStash(stash.stash || stash));
curatedAlert.stashes = alert.stashes.map((stash) => curateStash(stash.stash || stash));
}
return curatedAlert;
@ -197,11 +204,11 @@ function curateUser(user) {
const curatedUser = user;
if (user.stashes) {
curatedUser.stashes = user.stashes.map(stash => curateStash(stash.stash || stash));
curatedUser.stashes = user.stashes.map((stash) => curateStash(stash.stash || stash));
}
if (user.alerts) {
curatedUser.alerts = user.alerts.map(alert => curateAlert(alert.alert || alert));
curatedUser.alerts = user.alerts.map((alert) => curateAlert(alert.alert || alert));
}
return curatedUser;

View File

@ -14,7 +14,7 @@ function initEntitiesActions(store, router) {
}) {
const { before, after, orderBy } = getDateRange(range);
const { entity, connection: { releases, totalCount } } = await graphql(`
const { entity } = await graphql(`
query Entity(
$entitySlug: String!
$entityType: String! = "channel"
@ -22,8 +22,6 @@ function initEntitiesActions(store, router) {
$offset: Int = 0,
$after: Datetime = "1900-01-01",
$before: Datetime = "2100-01-01",
$afterTime: Datetime = "1900-01-01",
$beforeTime: Datetime = "2100-01-01",
$orderBy: [ReleasesOrderBy!]
$exclude: [String!]
$hasAuth: Boolean!
@ -43,6 +41,11 @@ function initEntitiesActions(store, router) {
slug
}
}
sceneTags {
id
name
slug
}
children: childEntitiesConnection(
orderBy: [PRIORITY_DESC, NAME_ASC],
filter: {
@ -64,6 +67,10 @@ function initEntitiesActions(store, router) {
independent
hasLogo
${campaignsFragment}
sceneTotal
children: childEntitiesConnection {
totalCount
}
}
}
${campaignsFragment}
@ -77,66 +84,27 @@ function initEntitiesActions(store, router) {
hasLogo
${campaignsFragment}
}
}
connection: releasesConnection(
connection: scenesConnection(
first: $limit
offset: $offset
orderBy: $orderBy
filter: {
and: [
{
entity: {
or: [
{
slug: { equalTo: $entitySlug }
},
{
parent: {
slug: { equalTo: $entitySlug }
type: { equalTo: $entityType }
}
},
{
parent: {
parent: {
slug: { equalTo: $entitySlug }
type: { equalTo: $entityType }
}
}
}
{
parent: {
parent: {
parent: {
slug: { equalTo: $entitySlug }
type: { equalTo: $entityType }
}
},
},
},
]
}
}
{
or: [
{
date: {
isNull: ${entityType !== 'network'}
}
}
{
date: {
isNull: false
}
}
]
effectiveDate: {
lessThan: $before,
greaterThan: $after
}
},
{
date: {
isNull: true
},
createdAt: {
lessThan: $beforeTime,
greaterThan: $afterTime,
}
}
]
}
]
releasesTagsConnection: {
none: {
tag: {
@ -154,6 +122,7 @@ function initEntitiesActions(store, router) {
totalCount
}
}
}
`, {
entitySlug,
entityType,
@ -162,8 +131,6 @@ function initEntitiesActions(store, router) {
after,
before,
orderBy,
afterTime: store.getters.after,
beforeTime: store.getters.before,
exclude: store.state.ui.tagFilter,
hasAuth: !!store.state.auth.user,
userId: store.state.auth.user?.id,
@ -175,8 +142,8 @@ function initEntitiesActions(store, router) {
}
return {
entity: curateEntity(entity, null, releases),
totalCount,
entity: curateEntity(entity, null, entity.connection.releases),
totalCount: entity.connection.totalCount,
};
}
@ -240,7 +207,7 @@ function initEntitiesActions(store, router) {
entitySlugs,
});
return entities.map(entity => curateEntity(entity));
return entities.map((entity) => curateEntity(entity));
}
async function searchEntities({ _commit }, { query, limit = 20 }) {
@ -274,7 +241,7 @@ function initEntitiesActions(store, router) {
limit,
});
return entities.map(entity => curateEntity(entity));
return entities.map((entity) => curateEntity(entity));
}
return {

View File

@ -5,7 +5,7 @@ export function formatDuration(duration, forceHours) {
const minutes = Math.floor((duration % 3600) / 60);
const seconds = Math.floor(duration % 60);
const [formattedHours, formattedMinutes, formattedSeconds] = [hours, minutes, seconds].map(segment => segment.toString().padStart(2, '0'));
const [formattedHours, formattedMinutes, formattedSeconds] = [hours, minutes, seconds].map((segment) => segment.toString().padStart(2, '0'));
if (duration >= 3600 || forceHours) {
return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;

View File

@ -125,7 +125,7 @@ const movieFields = `
type
}
}
covers: moviesCovers {
covers: moviesCovers(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
media {
id
path
@ -260,7 +260,7 @@ const releaseTagsFragment = `
`;
const releasePosterFragment = `
poster: releasesPosterByReleaseId {
poster: releasesPoster {
media {
id
index
@ -335,7 +335,7 @@ const releasePhotosFragment = `
`;
const releaseTrailerFragment = `
trailer: releasesTrailerByReleaseId {
trailer: releasesTrailer {
media {
id
index
@ -349,7 +349,7 @@ const releaseTrailerFragment = `
`;
const releaseTeaserFragment = `
teaser: releasesTeaserByReleaseId {
teaser: releasesTeaser {
media {
id
index
@ -442,6 +442,29 @@ const releasesFragment = `
}
`;
const mediaFields = `
id
index
path
thumbnail
lazy
isS3
comment
sfw: sfwMedia {
id
thumbnail
lazy
path
comment
}
`;
const mediaFragment = `
media {
${mediaFields}
}
`;
const releaseFragment = `
release(id: $releaseId) {
id
@ -487,7 +510,7 @@ const releaseFragment = `
slug
}
}
poster: chaptersPosterByChapterId {
poster: chaptersPoster {
media {
id
index
@ -516,7 +539,7 @@ const releaseFragment = `
id
title
slug
covers: moviesCovers {
covers: moviesCovers(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
media {
id
index
@ -536,6 +559,19 @@ const releaseFragment = `
}
}
}
series: seriesScenesBySceneId {
serie {
id
title
slug
covers: seriesCoversBySerieId(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
${mediaFragment}
}
poster: seriesPosterBySerieId {
${mediaFragment}
}
}
}
isFavorited
isStashed(includeFavorites: false)
stashes: stashesScenesBySceneId(
@ -624,6 +660,8 @@ export {
actorFields,
actorStashesFields,
campaignsFragment,
mediaFields,
mediaFragment,
movieFields,
releaseActorsFragment,
releaseFields,

View File

@ -3,30 +3,6 @@ import dayjs from 'dayjs';
dayjs.extend(utc);
const dateRanges = {
latest: () => ({
after: '1900-01-01',
before: dayjs.utc().toDate(),
orderBy: ['DATE_DESC', 'CREATED_AT_DESC'],
}),
upcoming: () => ({
after: dayjs.utc().toDate(),
before: '2100-01-01',
orderBy: ['DATE_ASC', 'CREATED_AT_ASC'],
}),
new: () => ({
after: '1900-01-01 00:00:00',
before: '2100-01-01',
orderBy: ['CREATED_AT_DESC', 'DATE_ASC'],
}),
all: () => ({
after: '1900-01-01',
before: '2100-01-01',
orderBy: ['DATE_DESC', 'CREATED_AT_DESC'],
}),
};
/* requires PostgreSQL 12.x> not available in production yet
const dateRanges = {
latest: () => ({
after: '1900-01-01',
@ -49,7 +25,6 @@ const dateRanges = {
orderBy: ['EFFECTIVE_DATE_DESC'],
}),
};
*/
function getDateRange(range) {
return (dateRanges[range] || dateRanges.all)();

View File

@ -109,6 +109,10 @@ async function init() {
document.title = 'traxxx';
},
},
beforeCreate() {
this.uid = uid;
uid += 1;
},
methods: {
formatDate,
formatDuration,
@ -117,10 +121,6 @@ async function init() {
getPath,
getBgPath: (media, type) => `url(${getPath(media, type)})`,
},
beforeCreate() {
this.uid = uid;
uid += 1;
},
});
app.directive('tooltip', {

View File

@ -4,6 +4,8 @@ import {
releaseFragment,
releaseFields,
movieFields,
mediaFragment,
mediaFields,
} from '../fragments';
import { curateRelease } from '../curate';
import getDateRange from '../get-date-range';
@ -37,7 +39,7 @@ function initReleasesActions(store, router) {
});
return {
releases: releases.map(release => curateRelease(release)),
releases: releases.map((release) => curateRelease(release)),
totalCount,
};
}
@ -99,7 +101,7 @@ function initReleasesActions(store, router) {
});
return {
movies: movies.map(release => curateRelease(release)),
movies: movies.map((release) => curateRelease(release)),
totalCount,
};
}
@ -110,6 +112,8 @@ function initReleasesActions(store, router) {
$query: String!
$limit:Int = 20
$offset:Int = 0
$hasAuth: Boolean!
$userId: Int
) {
connection: searchMoviesConnection(
query: $query
@ -126,6 +130,8 @@ function initReleasesActions(store, router) {
}
}
`, {
hasAuth: !!store.state.auth.user,
userId: store.state.auth.user?.id,
query,
limit,
offset: Math.max(0, (pageNumber - 1)) * limit,
@ -137,16 +143,16 @@ function initReleasesActions(store, router) {
};
}
async function fetchMovieById({ _commit }, movieId) {
async function fetchCollectionById({ _commit }, movieId, type = 'movie') {
// const release = await get(`/releases/${releaseId}`);
const { movie } = await graphql(`
const result = await graphql(`
query Movie(
$movieId: Int!
$hasAuth: Boolean!
$userId: Int
) {
movie(id: $movieId) {
${type}(id: $movieId) {
id
title
description
@ -178,7 +184,7 @@ function initReleasesActions(store, router) {
isS3
}
}
poster: moviesPosterByMovieId {
poster: ${type === 'series' ? 'seriesPosterBySerieId' : 'moviesPoster'} {
media {
id
path
@ -191,7 +197,7 @@ function initReleasesActions(store, router) {
isS3
}
}
covers: moviesCovers {
covers: ${type === 'series' ? 'seriesCoversBySerieId' : 'moviesCovers'}(orderBy: MEDIA_BY_MEDIA_ID__INDEX_ASC) {
media {
id
path
@ -204,14 +210,14 @@ function initReleasesActions(store, router) {
isS3
}
}
trailer: moviesTrailerByMovieId {
trailer: ${type === 'series' ? 'seriesTrailerBySerieId' : 'moviesTrailer'} {
media {
id
path
isS3
}
}
scenes: moviesScenes {
scenes: ${type === 'series' ? 'seriesScenesBySerieId' : 'moviesScenes'} {
scene {
${releaseFields}
}
@ -221,25 +227,11 @@ function initReleasesActions(store, router) {
slug
name
}
photos {
id
index
path
thumbnail
lazy
width
height
thumbnailWidth
thumbnailHeight
isS3
comment
sfw: sfwMedia {
id
thumbnail
lazy
path
comment
photos: ${type === 'series' ? 'seriesPhotosBySerieId' : 'moviesPhotos'} {
${mediaFragment}
}
scenesPhotos {
${mediaFields}
}
entity {
id
@ -255,7 +247,7 @@ function initReleasesActions(store, router) {
hasLogo
}
}
stashes: stashesMovies(
stashes: ${type === 'series' ? 'stashesSeriesBySerieId' : 'stashesMovies'}(
filter: {
stash: {
userId: {
@ -279,12 +271,20 @@ function initReleasesActions(store, router) {
userId: store.state.auth.user?.id,
});
if (!movie) {
if (!result[type]) {
router.replace('/not-found');
return null;
}
return curateRelease(movie);
return curateRelease(result[type]);
}
async function fetchMovieById(context, movieId) {
return fetchCollectionById(context, movieId, 'movie');
}
async function fetchSerieById(context, serieId) {
return fetchCollectionById(context, serieId, 'series');
}
return {
@ -292,6 +292,7 @@ function initReleasesActions(store, router) {
fetchReleaseById,
fetchMovies,
fetchMovieById,
fetchSerieById,
searchMovies,
};
}

View File

@ -71,10 +71,15 @@ const routes = [
component: Release,
name: 'movie',
},
{
path: '/serie/:releaseId/:releaseSlug?',
component: Release,
name: 'serie',
},
{
path: '/actor/:actorId/:actorSlug',
name: 'actor',
redirect: from => ({
redirect: (from) => ({
name: 'actorRange',
params: {
...from.params,
@ -91,7 +96,7 @@ const routes = [
{
path: '/director/:actorId/:actorSlug',
name: 'director',
redirect: from => ({
redirect: (from) => ({
name: 'directorRange',
params: {
...from.params,
@ -107,7 +112,7 @@ const routes = [
},
{
path: '/channel/:entitySlug',
redirect: from => ({
redirect: (from) => ({
name: 'channel',
params: {
...from.params,
@ -123,7 +128,7 @@ const routes = [
},
{
path: '/network/:entitySlug',
redirect: from => ({
redirect: (from) => ({
name: 'network',
params: {
...from.params,
@ -139,7 +144,7 @@ const routes = [
},
{
path: '/studio/:entitySlug',
redirect: from => ({
redirect: (from) => ({
name: 'studio',
params: {
...from.params,
@ -155,7 +160,7 @@ const routes = [
},
{
path: '/tag/:tagSlug',
redirect: from => ({
redirect: (from) => ({
name: 'tag',
params: {
...from.params,
@ -171,7 +176,7 @@ const routes = [
},
{
path: '/actors',
redirect: from => ({
redirect: (from) => ({
name: 'actors',
params: {
...from.params,
@ -229,7 +234,7 @@ const routes = [
},
{
path: '/stash/:stashId/:stashSlug',
redirect: from => ({
redirect: (from) => ({
name: 'stash',
params: {
...from.params,

View File

@ -35,7 +35,7 @@ function initTagsActions(store, _router) {
name
slug
}
poster: tagsPosterByTagId {
poster: tagsPoster {
media {
id
thumbnail
@ -188,14 +188,14 @@ function initTagsActions(store, _router) {
before,
orderBy,
offset: Math.max(0, (pageNumber - 1)) * limit,
exclude: store.state.ui.tagFilter.filter(tagFilter => tagFilter !== tagSlug),
exclude: store.state.ui.tagFilter.filter((tagFilter) => tagFilter !== tagSlug),
hasAuth: !!store.state.auth.user,
userId: store.state.auth.user?.id,
});
return {
tag: curateTag(tagBySlug, null, curateRelease),
releases: tagBySlug.scenesConnection.releases.map(release => curateRelease(release)),
releases: tagBySlug.scenesConnection.releases.map((release) => curateRelease(release)),
totalCount: tagBySlug.scenesConnection.totalCount,
};
}
@ -210,15 +210,21 @@ function initTagsActions(store, _router) {
query Tags(
$slugs: [String!] = [],
$limit: Int = 100
$exclude: [String!]
) {
tags(
filter: { slug: { in: $slugs } },
filter: {
slug: {
in: $slugs
notIn: $exclude
}
},
first: $limit
) {
id
name
slug
poster: tagsPosterByTagId {
poster: tagsPoster {
media {
thumbnail
comment
@ -257,9 +263,10 @@ function initTagsActions(store, _router) {
`, {
slugs,
limit,
exclude: store.state.ui.tagFilter,
});
return tags.map(tag => curateTag(tag, store.state.ui.sfw));
return tags.map((tag) => curateTag(tag, store.state.ui.sfw));
}
async function searchTags({ _commit }, {
@ -283,7 +290,7 @@ function initTagsActions(store, _router) {
id
name
slug
poster: tagsPosterByTagId {
poster: tagsPoster {
media {
thumbnail
comment
@ -325,7 +332,7 @@ function initTagsActions(store, _router) {
minLength,
});
return tags.map(tag => curateTag(tag, store.state.ui.sfw));
return tags.map((tag) => curateTag(tag, store.state.ui.sfw));
}
async function fetchTagReleases({ _commit }, tagId) {

View File

@ -70,7 +70,7 @@ function initUiActions(store, _router) {
slug
}
}
entity: alertsEntityByAlertId {
entity: alertsEntity {
entity {
id
name
@ -103,7 +103,7 @@ function initUiActions(store, _router) {
};
}
const curatedNotifications = notifications.nodes.map(notification => curateNotification(notification));
const curatedNotifications = notifications.nodes.map((notification) => curateNotification(notification));
return {
notifications: curatedNotifications,
@ -222,8 +222,8 @@ function initUiActions(store, _router) {
});
return {
releases: res?.results.map(result => curateRelease(result.release)) || [],
actors: res?.actors.map(actor => curateActor(actor)) || [],
releases: res?.results.map((result) => curateRelease(result.release)) || [],
actors: res?.actors.map((actor) => curateActor(actor)) || [],
};
}

View File

@ -3,7 +3,7 @@ async function initUiObservers(store, _router) {
body.classList.add(store.state.ui.theme);
store.watch(state => state.ui.theme, (newTheme, oldTheme) => {
store.watch((state) => state.ui.theme, (newTheme, oldTheme) => {
body.classList.add(newTheme);
body.classList.remove(oldTheme);
});

View File

@ -90,7 +90,7 @@ function initUsersActions(store, _router) {
${actorFields}
}
}
entity: alertsEntityByAlertId {
entity: alertsEntity {
entity {
id
name

View File

@ -66,10 +66,7 @@ module.exports = {
// pornpros
'milfhumiliation',
'humiliated',
'flexiblepositions',
'publicviolations',
'amateurviolations',
'squirtdisgrace',
'cumdisgrace',
'webcamhackers',
'collegeteens',
@ -301,10 +298,6 @@ module.exports = {
interval: 1000,
concurrency: 1,
},
'www.realitykings.com': {
interval: 1000,
concurrency: 1,
},
'westcoastproductions.com': {
interval: 100,
concurrency: 1,
@ -316,8 +309,15 @@ module.exports = {
},
fetchAfter: [1, 'week'],
missingDateLimit: 3,
memorySampling: {
enabled: false,
sampleDuration: 300000, // 5 minutes
snapshotIntervals: [],
},
media: {
path: './media',
maxSize: 1000,
quality: 80,
thumbnailSize: 320, // width for 16:9 will be exactly 576px
thumbnailQuality: 100,
lazySize: 90,

View File

@ -1,6 +1,6 @@
const config = require('config');
exports.up = knex => Promise.resolve()
exports.up = (knex) => Promise.resolve()
.then(() => knex.schema.createTable('countries', (table) => {
table.text('alpha2', 2)
.unique()

View File

@ -0,0 +1,29 @@
exports.up = async (knex) => knex.raw(`
CREATE FUNCTION entities_scenes(entity entities) RETURNS SETOF releases AS $$
WITH RECURSIVE children AS (
SELECT entities.id
FROM entities
WHERE entities.id = entity.id
UNION ALL
SELECT entities.id
FROM entities
INNER JOIN children ON children.id = entities.parent_id
)
SELECT releases FROM releases
INNER JOIN children ON children.id = releases.entity_id
UNION
SELECT releases FROM releases
INNER JOIN children ON children.id = releases.studio_id;
$$ LANGUAGE SQL STABLE;
COMMENT ON FUNCTION entities_scenes IS E'@sortable';
`);
exports.down = async (knex) => knex.raw(`
DROP FUNCTION IF EXISTS entities_scenes;
`);

View File

@ -0,0 +1,15 @@
exports.up = async (knex) => Promise.resolve()
.then(() => knex.schema.alterTable('releases_tags', (table) => {
table.index('release_id');
}))
.then(() => knex.schema.alterTable('movies_scenes', (table) => {
table.index('scene_id');
}));
exports.down = async (knex) => Promise.resolve()
.then(() => knex.schema.alterTable('releases_tags', (table) => {
table.dropIndex('release_id');
}))
.then(() => knex.schema.alterTable('movies_scenes', (table) => {
table.dropIndex('scene_id');
}));

View File

@ -0,0 +1,11 @@
exports.up = async (knex) => knex.raw(`
CREATE OR REPLACE FUNCTION entities_scene_total(entity entities) RETURNS bigint AS $$
SELECT COUNT(id)
FROM releases
WHERE releases.entity_id = entity.id;
$$ LANGUAGE SQL STABLE;
`);
exports.down = async (knex) => knex.raw(`
DROP FUNCTION IF EXISTS entities_scene_total;
`);

View File

@ -0,0 +1,23 @@
exports.up = async (knex) => knex.raw(`
CREATE FUNCTION entities_scene_tags(entity entities, selectable_tags text[]) RETURNS SETOF tags AS $$
SELECT tags.*
FROM releases
LEFT JOIN
releases_tags ON releases_tags.release_id = releases.id
LEFT JOIN
tags ON tags.id = releases_tags.tag_id
WHERE
releases.entity_id = entity.id
AND
CASE WHEN array_length(selectable_tags, 1) IS NOT NULL
THEN tags.slug = ANY(selectable_tags)
ELSE true
END
GROUP BY tags.id
ORDER BY tags.name;
$$ LANGUAGE SQL STABLE;
`);
exports.down = async (knex) => knex.raw(`
DROP FUNCTION IF EXISTS entities_scene_tags;
`);

View File

@ -0,0 +1,215 @@
const config = require('config');
exports.up = async (knex) => Promise.resolve()
.then(() => knex.schema.createTable('series', (table) => {
table.increments('id', 16);
table.integer('entity_id', 12)
.references('id')
.inTable('entities')
.notNullable();
table.integer('studio_id', 12)
.references('id')
.inTable('entities');
table.text('entry_id');
table.unique(['entity_id', 'entry_id']);
table.text('url', 1000);
table.text('title');
table.text('slug');
table.timestamp('date');
table.index('date');
table.enum('date_precision', ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'])
.defaultTo('day');
table.text('description');
table.boolean('deep');
table.text('deep_url', 1000);
table.text('comment');
table.integer('created_batch_id', 12)
.references('id')
.inTable('batches')
.onDelete('cascade');
table.integer('updated_batch_id', 12)
.references('id')
.inTable('batches')
.onDelete('cascade');
table.datetime('created_at')
.defaultTo(knex.fn.now());
}))
.then(() => knex.schema.createTable('series_scenes', (table) => {
table.integer('serie_id', 16)
.notNullable()
.references('id')
.inTable('series')
.onDelete('cascade');
table.integer('scene_id', 16)
.notNullable()
.references('id')
.inTable('releases')
.onDelete('cascade');
table.unique(['serie_id', 'scene_id']);
table.datetime('created_at')
.defaultTo(knex.fn.now());
}))
.then(() => knex.schema.createTable('series_trailers', (table) => {
table.integer('serie_id', 16)
.unique()
.notNullable()
.references('id')
.inTable('series')
.onDelete('cascade');
table.text('media_id', 21)
.notNullable()
.references('id')
.inTable('media');
}))
.then(() => knex.schema.createTable('series_posters', (table) => {
table.integer('serie_id', 16)
.notNullable()
.references('id')
.inTable('series')
.onDelete('cascade');
table.text('media_id', 21)
.notNullable()
.references('id')
.inTable('media')
.onDelete('cascade');
table.unique('serie_id');
}))
.then(() => knex.schema.createTable('series_covers', (table) => {
table.integer('serie_id', 16)
.notNullable()
.references('id')
.inTable('series')
.onDelete('cascade');
table.text('media_id', 21)
.notNullable()
.references('id')
.inTable('media');
table.unique(['serie_id', 'media_id']);
}))
.then(() => knex.schema.createTable('series_search', (table) => {
table.integer('serie_id', 16)
.references('id')
.inTable('series')
.onDelete('cascade');
}))
.then(() => knex.schema.createTable('stashes_series', (table) => {
table.integer('stash_id')
.notNullable()
.references('id')
.inTable('stashes')
.onDelete('cascade');
table.integer('serie_id')
.notNullable()
.references('id')
.inTable('series')
.onDelete('cascade');
table.unique(['stash_id', 'serie_id']);
table.string('comment');
table.datetime('created_at')
.notNullable()
.defaultTo(knex.fn.now());
}))
.then(() => knex.raw(`
ALTER TABLE series_search ADD COLUMN document tsvector;
CREATE UNIQUE INDEX series_search_unique ON series_search (serie_id);
CREATE INDEX series_search_index ON series_search USING GIN (document);
CREATE FUNCTION series_actors(serie series) RETURNS SETOF actors AS $$
SELECT actors.*
FROM series_scenes
LEFT JOIN
releases ON releases.id = series_scenes.scene_id
LEFT JOIN
releases_actors ON releases_actors.release_id = releases.id
LEFT JOIN
actors ON actors.id = releases_actors.actor_id
WHERE series_scenes.serie_id = serie.id
AND actors.id IS NOT NULL
GROUP BY actors.id
ORDER BY actors.name, actors.gender
$$ LANGUAGE SQL STABLE;
CREATE FUNCTION series_tags(serie series) RETURNS SETOF tags AS $$
SELECT tags.*
FROM series_scenes
LEFT JOIN
releases ON releases.id = series_scenes.scene_id
LEFT JOIN
releases_tags ON releases_tags.release_id = releases.id
LEFT JOIN
tags ON tags.id = releases_tags.tag_id
WHERE series_scenes.serie_id = serie.id
AND tags.id IS NOT NULL
GROUP BY tags.id
ORDER BY tags.priority DESC
$$ LANGUAGE SQL STABLE;
CREATE FUNCTION series_photos(serie series) RETURNS SETOF media AS $$
SELECT media.*
FROM series_scenes
LEFT JOIN
releases ON releases.id = series_scenes.scene_id
INNER JOIN
releases_photos ON releases_photos.release_id = releases.id
LEFT JOIN
media ON media.id = releases_photos.media_id
WHERE series_scenes.serie_id = serie.id
GROUP BY media.id
ORDER BY media.index ASC
$$ LANGUAGE SQL STABLE;
GRANT ALL ON ALL TABLES IN SCHEMA public TO :visitor;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO :visitor;
ALTER TABLE stashes_series ENABLE ROW LEVEL SECURITY;
CREATE POLICY stashes_policy ON stashes_series
USING (EXISTS (
SELECT *
FROM stashes
WHERE stashes.id = stashes_series.stash_id
AND (stashes.user_id = current_user_id() OR stashes.public)
));
`, {
visitor: knex.raw(config.database.query.user),
}));
exports.down = async (knex) => Promise.resolve()
.then(() => knex.raw(`
DROP FUNCTION IF EXISTS series_actors;
DROP FUNCTION IF EXISTS series_tags;
DROP FUNCTION IF EXISTS series_photos;
DROP TABLE IF EXISTS stashes_series CASCADE;
DROP TABLE IF EXISTS series_scenes CASCADE;
DROP TABLE IF EXISTS series_trailers CASCADE;
DROP TABLE IF EXISTS series_posters CASCADE;
DROP TABLE IF EXISTS series_covers CASCADE;
DROP TABLE IF EXISTS series_search CASCADE;
DROP TABLE IF EXISTS series CASCADE;
`));

View File

@ -0,0 +1,49 @@
const config = require('config');
exports.up = async (knex) => Promise.resolve()
.then(() => knex.raw(`
ALTER FUNCTION movies_photos(movie movies) RENAME TO movies_scenes_photos;
ALTER FUNCTION series_photos(serie series) RENAME TO series_scenes_photos;
`))
.then(() => knex.schema.createTable('movies_photos', (table) => {
table.integer('movie_id', 16)
.notNullable()
.references('id')
.inTable('movies')
.onDelete('cascade');
table.text('media_id', 21)
.notNullable()
.references('id')
.inTable('media');
table.unique(['movie_id', 'media_id']);
}))
.then(() => knex.schema.createTable('series_photos', (table) => {
table.integer('serie_id', 16)
.notNullable()
.references('id')
.inTable('series')
.onDelete('cascade');
table.text('media_id', 21)
.notNullable()
.references('id')
.inTable('media');
table.unique(['serie_id', 'media_id']);
}))
.then(() => knex.raw(`
GRANT ALL ON ALL TABLES IN SCHEMA public TO :visitor;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO :visitor;
`, {
visitor: knex.raw(config.database.query.user),
}));
exports.down = async (knex) => knex.raw(`
DROP TABLE IF EXISTS movies_photos CASCADE;
DROP TABLE IF EXISTS series_photos CASCADE;
ALTER FUNCTION movies_scenes_photos(movie movies) RENAME TO movies_photos;
ALTER FUNCTION series_scenes_photos(serie series) RENAME TO series_photos;
`);

20032
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,13 @@
{
"name": "traxxx",
"version": "1.200.2",
"version": "1.212.9",
"description": "All the latest porn releases in one place",
"main": "src/app.js",
"scripts": {
"start": "node -r source-map-support/register src/init.js",
"webpack": "webpack --env=production --mode=production",
"webpack-dev": "webpack --env=development --mode=development",
"webpack-watch": "webpack --progress --colors --watch --env=development --mode=development",
"webpack-watch": "webpack --progress --color --watch --env=development --mode=development",
"babel": "babel src --source-maps -d dist",
"babel-watch": "babel src -w --source-maps -d dist",
"build": "babel src --source-maps -d dist && webpack --env=production --mode=production",
@ -40,38 +40,37 @@
"devDependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.8.4",
"@babel/eslint-parser": "^7.16.0",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/preset-env": "^7.8.4",
"@babel/register": "^7.8.3",
"@vue/compiler-sfc": "^3.0.4",
"autoprefixer": "^9.7.4",
"babel-eslint": "^10.1.0",
"autoprefixer": "^10.4.0",
"babel-loader": "^8.0.6",
"babel-preset-airbnb": "^3.3.2",
"css-loader": "^5.0.1",
"eslint": "^7.20.0",
"eslint-config-airbnb": "^17.1.1",
"eslint-config-airbnb-base": "^13.2.0",
"babel-preset-airbnb": "^5.0.0",
"css-loader": "^6.5.0",
"eslint": "^8.1.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.18.3",
"eslint-plugin-vue": "^6.2.1",
"eslint-watch": "^4.0.2",
"eslint-webpack-plugin": "^2.5.2",
"mini-css-extract-plugin": "^1.3.3",
"node-sass": "^5.0.0",
"postcss-loader": "^3.0.0",
"eslint-plugin-vue": "^8.0.3",
"eslint-watch": "^7.0.0",
"eslint-webpack-plugin": "^3.1.0",
"mini-css-extract-plugin": "^2.4.3",
"node-sass": "^6.0.1",
"postcss-loader": "^6.2.0",
"raw-loader": "^4.0.2",
"sass-loader": "^11.0.1",
"style-loader": "^0.23.1",
"vue-loader": "^16.1.2",
"sass-loader": "^12.3.0",
"style-loader": "^3.3.1",
"vue-loader": "^16.8.2",
"webpack": "^5.11.0",
"webpack-cli": "^3.3.11"
"webpack-cli": "^4.9.1"
},
"dependencies": {
"@casl/ability": "^5.2.2",
"@graphile-contrib/pg-order-by-related": "^1.0.0-beta.6",
"@graphile-contrib/pg-simplify-inflector": "^5.0.0-beta.1",
"@graphile-contrib/pg-simplify-inflector": "^6.1.0",
"acorn": "^8.0.4",
"array-equal": "^1.0.0",
"aws-sdk": "^2.847.0",
@ -88,63 +87,62 @@
"cloudscraper": "^4.6.0",
"config": "^3.2.5",
"connect-session-knex": "^2.0.0",
"convert": "^1.6.2",
"convert": "^4.2.4",
"cookie": "^0.4.0",
"csv-stringify": "^5.3.6",
"dayjs": "^1.8.21",
"dompurify": "^2.0.11",
"ejs": "^3.0.1",
"express": "^4.17.1",
"express-promise-router": "^3.0.3",
"express-promise-router": "^4.1.0",
"express-react-views": "^0.11.0",
"express-session": "^1.17.1",
"face-api.js": "^0.22.2",
"faker": "^5.1.0",
"file-type": "^14.1.4",
"file-type": "^16.5.3",
"fluent-ffmpeg": "^2.1.2",
"fs-extra": "^7.0.1",
"graphile-utils": "^4.5.6",
"graphql": "^14.6.0",
"fs-extra": "^10.0.0",
"graphile-utils": "^4.12.2",
"graphql": "^15.4.0",
"html-entities": "^2.3.2",
"iconv-lite": "^0.5.1",
"inquirer": "^7.3.3",
"iconv-lite": "^0.6.3",
"inquirer": "^8.2.0",
"inspector-api": "^1.4.2",
"jsdom": "^16.3.0",
"knex": "^0.21.13",
"jsdom": "^18.0.0",
"knex": "^0.95.12",
"knex-migrate": "^1.7.4",
"longjohn": "^0.2.12",
"mime": "^2.4.4",
"mitt": "^2.1.0",
"mitt": "^3.0.0",
"moment": "^2.24.0",
"nanoid": "^2.1.11",
"nanoid": "^3.1.30",
"node-fetch": "^2.6.7",
"object-merge-advanced": "^12.1.0",
"object.omit": "^3.0.0",
"opn": "^5.5.0",
"opn": "^6.0.0",
"pg": "^8.5.1",
"postgraphile": "^4.10.0",
"postgraphile-plugin-connection-filter": "^1.1.3",
"postgraphile-plugin-connection-filter": "^2.2.2",
"promise-task-queue": "^1.2.0",
"prop-types": "^15.7.2",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"sharp": "^0.27.2",
"sharp": "^0.29.2",
"showdown": "^1.9.1",
"source-map-support": "^0.5.16",
"template-format": "^1.2.5",
"tippy.js": "^6.3.1",
"tough-cookie": "^3.0.1",
"tty-table": "^2.8.12",
"tough-cookie": "^4.0.0",
"tunnel": "0.0.6",
"undici": "^4.13.0",
"url-pattern": "^1.0.3",
"v-tooltip": "^2.0.3",
"video.js": "^7.11.4",
"videojs-vr": "^1.7.1",
"vue": "^3.0.4",
"vue-router": "^4.0.1",
"vuex": "^4.0.0-rc.2",
"vue": "^3.2.20",
"vue-router": "^4.0.12",
"vuex": "^4.0.2",
"why-is-node-running": "^2.2.0",
"winston": "^3.2.1",
"winston-daily-rotate-file": "^4.4.2",
"yargs": "^13.3.0"
"yargs": "^17.2.1"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

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