├── .eslintignore
├── .eslintrc.js
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── build-app.yml
│ ├── build-server.yml
│ ├── lint.yml
│ ├── push.yml
│ └── release.yml
├── .gitignore
├── .mocharc.js
├── .prettierrc.js
├── Dockerfile
├── README.md
├── app
├── .browserslistrc
├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│ └── index.html
├── src
│ ├── App.vue
│ ├── apollo.ts
│ ├── components
│ │ ├── ActorGrid.vue
│ │ ├── ActorSelector.vue
│ │ ├── AppBar
│ │ │ ├── ActorDetails.vue
│ │ │ ├── MovieDetails.vue
│ │ │ ├── SceneDetails.vue
│ │ │ └── StudioDetails.vue
│ │ ├── BindTitle.vue
│ │ ├── Cards
│ │ │ └── Actor.vue
│ │ ├── Collabs.vue
│ │ ├── CreatedCustomField.vue
│ │ ├── CustomFieldCreator.vue
│ │ ├── CustomFieldFilter.vue
│ │ ├── CustomFieldSelector.vue
│ │ ├── DVDRenderer.vue
│ │ ├── DateInput.vue
│ │ ├── Divider.vue
│ │ ├── Flag.vue
│ │ ├── HomeWidgets
│ │ │ ├── ActorLabelUsage.vue
│ │ │ ├── Base.vue
│ │ │ ├── QueueInfo.vue
│ │ │ ├── RemainingTime.vue
│ │ │ ├── Scan.vue
│ │ │ ├── SceneLabelUsage.vue
│ │ │ ├── SearchTimes.vue
│ │ │ ├── Stats.vue
│ │ │ ├── TopActors.vue
│ │ │ └── UnwatchedActors.vue
│ │ ├── ImageCard.vue
│ │ ├── ImageUploader.vue
│ │ ├── LabelFilter.vue
│ │ ├── LabelSelector.vue
│ │ ├── Lightbox.vue
│ │ ├── Loading.vue
│ │ ├── MarkerCard.vue
│ │ ├── MarkerItem.vue
│ │ ├── MovieCard.vue
│ │ ├── MovieItem.vue
│ │ ├── NoResults.vue
│ │ ├── Plugins
│ │ │ └── Item.vue
│ │ ├── Rating.vue
│ │ ├── SceneCard.vue
│ │ ├── SceneSelector.vue
│ │ ├── SceneUploader.vue
│ │ ├── StudioCard.vue
│ │ ├── StudioSelector.vue
│ │ └── VideoPlayer.vue
│ ├── fragments
│ │ ├── actor.ts
│ │ ├── image.ts
│ │ ├── movie.ts
│ │ ├── scene.ts
│ │ └── studio.ts
│ ├── main.ts
│ ├── mixins
│ │ ├── drawer.ts
│ │ └── scene.ts
│ ├── plugins
│ │ └── vuetify.ts
│ ├── router
│ │ └── index.ts
│ ├── shims-tsx.d.ts
│ ├── shims-vue.d.ts
│ ├── store
│ │ ├── actor.ts
│ │ ├── context.ts
│ │ ├── image.ts
│ │ ├── index.ts
│ │ ├── markers.ts
│ │ ├── movie.ts
│ │ ├── scene.ts
│ │ └── studio.ts
│ ├── types
│ │ ├── actor.ts
│ │ ├── image.ts
│ │ ├── label.ts
│ │ ├── movie.ts
│ │ └── scene.ts
│ ├── util
│ │ ├── color.ts
│ │ ├── countries.ts
│ │ ├── object.ts
│ │ └── scene.ts
│ └── views
│ │ ├── About.vue
│ │ ├── ActorDetails.vue
│ │ ├── Actors.vue
│ │ ├── Graph.vue
│ │ ├── Home.vue
│ │ ├── Images.vue
│ │ ├── Labels.vue
│ │ ├── Logs.vue
│ │ ├── Markers.vue
│ │ ├── MovieDetails.vue
│ │ ├── Movies.vue
│ │ ├── Plugins.vue
│ │ ├── SceneDetails.vue
│ │ ├── Scenes.vue
│ │ ├── StudioDetails.vue
│ │ ├── Studios.vue
│ │ └── Views.vue
├── tsconfig.json
└── vue.config.js
├── assets
├── OrbitControls.js
├── bump.jpg
├── favicon.png
├── flags
│ ├── ad.svg
│ ├── ae.svg
│ ├── af.svg
│ ├── ag.svg
│ ├── ai.svg
│ ├── al.svg
│ ├── am.svg
│ ├── ao.svg
│ ├── aq.svg
│ ├── ar.svg
│ ├── as.svg
│ ├── at.svg
│ ├── au.svg
│ ├── aw.svg
│ ├── ax.svg
│ ├── az.svg
│ ├── ba.svg
│ ├── bb.svg
│ ├── bd.svg
│ ├── be.svg
│ ├── bf.svg
│ ├── bg.svg
│ ├── bh.svg
│ ├── bi.svg
│ ├── bj.svg
│ ├── bl.svg
│ ├── bm.svg
│ ├── bn.svg
│ ├── bo.svg
│ ├── bq.svg
│ ├── br.svg
│ ├── bs.svg
│ ├── bt.svg
│ ├── bv.svg
│ ├── bw.svg
│ ├── by.svg
│ ├── bz.svg
│ ├── ca.svg
│ ├── cc.svg
│ ├── cd.svg
│ ├── cf.svg
│ ├── cg.svg
│ ├── ch.svg
│ ├── ci.svg
│ ├── ck.svg
│ ├── cl.svg
│ ├── cm.svg
│ ├── cn.svg
│ ├── co.svg
│ ├── cr.svg
│ ├── cu.svg
│ ├── cv.svg
│ ├── cw.svg
│ ├── cx.svg
│ ├── cy.svg
│ ├── cz.svg
│ ├── de.svg
│ ├── dj.svg
│ ├── dk.svg
│ ├── dm.svg
│ ├── do.svg
│ ├── dz.svg
│ ├── ec.svg
│ ├── ee.svg
│ ├── eg.svg
│ ├── eh.svg
│ ├── er.svg
│ ├── es-ct.svg
│ ├── es.svg
│ ├── et.svg
│ ├── eu.svg
│ ├── fi.svg
│ ├── fj.svg
│ ├── fk.svg
│ ├── fm.svg
│ ├── fo.svg
│ ├── fr.svg
│ ├── ga.svg
│ ├── gb-eng.svg
│ ├── gb-nir.svg
│ ├── gb-sct.svg
│ ├── gb-wls.svg
│ ├── gb.svg
│ ├── gd.svg
│ ├── ge.svg
│ ├── gf.svg
│ ├── gg.svg
│ ├── gh.svg
│ ├── gi.svg
│ ├── gl.svg
│ ├── gm.svg
│ ├── gn.svg
│ ├── gp.svg
│ ├── gq.svg
│ ├── gr.svg
│ ├── gs.svg
│ ├── gt.svg
│ ├── gu.svg
│ ├── gw.svg
│ ├── gy.svg
│ ├── hk.svg
│ ├── hm.svg
│ ├── hn.svg
│ ├── hr.svg
│ ├── ht.svg
│ ├── hu.svg
│ ├── id.svg
│ ├── ie.svg
│ ├── il.svg
│ ├── im.svg
│ ├── in.svg
│ ├── io.svg
│ ├── iq.svg
│ ├── ir.svg
│ ├── is.svg
│ ├── it.svg
│ ├── je.svg
│ ├── jm.svg
│ ├── jo.svg
│ ├── jp.svg
│ ├── ke.svg
│ ├── kg.svg
│ ├── kh.svg
│ ├── ki.svg
│ ├── km.svg
│ ├── kn.svg
│ ├── kp.svg
│ ├── kr.svg
│ ├── kw.svg
│ ├── ky.svg
│ ├── kz.svg
│ ├── la.svg
│ ├── lb.svg
│ ├── lc.svg
│ ├── li.svg
│ ├── lk.svg
│ ├── lr.svg
│ ├── ls.svg
│ ├── lt.svg
│ ├── lu.svg
│ ├── lv.svg
│ ├── ly.svg
│ ├── ma.svg
│ ├── mc.svg
│ ├── md.svg
│ ├── me.svg
│ ├── mf.svg
│ ├── mg.svg
│ ├── mh.svg
│ ├── mk.svg
│ ├── ml.svg
│ ├── mm.svg
│ ├── mn.svg
│ ├── mo.svg
│ ├── mp.svg
│ ├── mq.svg
│ ├── mr.svg
│ ├── ms.svg
│ ├── mt.svg
│ ├── mu.svg
│ ├── mv.svg
│ ├── mw.svg
│ ├── mx.svg
│ ├── my.svg
│ ├── mz.svg
│ ├── na.svg
│ ├── nc.svg
│ ├── ne.svg
│ ├── nf.svg
│ ├── ng.svg
│ ├── ni.svg
│ ├── nl.svg
│ ├── no.svg
│ ├── np.svg
│ ├── nr.svg
│ ├── nu.svg
│ ├── nz.svg
│ ├── om.svg
│ ├── pa.svg
│ ├── pe.svg
│ ├── pf.svg
│ ├── pg.svg
│ ├── ph.svg
│ ├── pk.svg
│ ├── pl.svg
│ ├── pm.svg
│ ├── pn.svg
│ ├── pr.svg
│ ├── ps.svg
│ ├── pt.svg
│ ├── pw.svg
│ ├── py.svg
│ ├── qa.svg
│ ├── re.svg
│ ├── ro.svg
│ ├── rs.svg
│ ├── ru.svg
│ ├── rw.svg
│ ├── sa.svg
│ ├── sb.svg
│ ├── sc.svg
│ ├── sd.svg
│ ├── se.svg
│ ├── sg.svg
│ ├── sh.svg
│ ├── si.svg
│ ├── sj.svg
│ ├── sk.svg
│ ├── sl.svg
│ ├── sm.svg
│ ├── sn.svg
│ ├── so.svg
│ ├── sr.svg
│ ├── ss.svg
│ ├── st.svg
│ ├── sv.svg
│ ├── sx.svg
│ ├── sy.svg
│ ├── sz.svg
│ ├── tc.svg
│ ├── td.svg
│ ├── tf.svg
│ ├── tg.svg
│ ├── th.svg
│ ├── tj.svg
│ ├── tk.svg
│ ├── tl.svg
│ ├── tm.svg
│ ├── tn.svg
│ ├── to.svg
│ ├── tr.svg
│ ├── tt.svg
│ ├── tv.svg
│ ├── tw.svg
│ ├── tz.svg
│ ├── ua.svg
│ ├── ug.svg
│ ├── um.svg
│ ├── un.svg
│ ├── us.svg
│ ├── uy.svg
│ ├── uz.svg
│ ├── va.svg
│ ├── vc.svg
│ ├── ve.svg
│ ├── vg.svg
│ ├── vi.svg
│ ├── vn.svg
│ ├── vu.svg
│ ├── wf.svg
│ ├── ws.svg
│ ├── ye.svg
│ ├── yt.svg
│ ├── za.svg
│ ├── zm.svg
│ └── zw.svg
└── three.min.js
├── config.json.example
├── doc
├── build_from_source.md
├── config.md
├── docker.md
├── guides.md
├── img
│ ├── actor_collection.jpg
│ ├── actor_details.jpg
│ ├── btc.png
│ ├── image_collection.jpg
│ ├── image_details.jpg
│ ├── movie_collection.jpg
│ ├── movie_details.jpg
│ ├── parent_studio.jpg
│ ├── plugin_filter.png
│ ├── scene_collection.jpg
│ ├── scene_details.jpg
│ └── studio_collection.jpg
├── import.md
├── pipe_plugins.md
├── plugin_development.md
└── plugins_intro.md
├── nodemon.json
├── package-lock.json
├── package.json
├── run.sh
├── src
├── apollo.ts
├── args.ts
├── backup.ts
├── broken_image.ts
├── config
│ ├── default.ts
│ ├── index.ts
│ ├── schema.ts
│ └── validate.ts
├── data
│ └── countries.ts
├── database
│ ├── index.ts
│ └── internal
│ │ └── index.ts
├── dvd_renderer.ts
├── exit.ts
├── extractor.ts
├── ffmpeg-download.ts
├── ffmpeg
│ └── screenshot.ts
├── fs
│ ├── async.ts
│ └── index.ts
├── gianna.ts
├── graphql
│ ├── mutation.ts
│ ├── mutations
│ │ ├── actor.ts
│ │ ├── custom_field.ts
│ │ ├── image.ts
│ │ ├── label.ts
│ │ ├── marker.ts
│ │ ├── movie.ts
│ │ ├── scene.ts
│ │ └── studio.ts
│ ├── resolvers.ts
│ ├── resolvers
│ │ ├── actor.ts
│ │ ├── custom_field.ts
│ │ ├── image.ts
│ │ ├── label.ts
│ │ ├── marker.ts
│ │ ├── movie.ts
│ │ ├── query.ts
│ │ ├── scene.ts
│ │ ├── scene_view.ts
│ │ ├── search
│ │ │ ├── actor.ts
│ │ │ ├── image.ts
│ │ │ ├── marker.ts
│ │ │ ├── movie.ts
│ │ │ ├── scene.ts
│ │ │ └── studio.ts
│ │ └── studio.ts
│ ├── schema
│ │ ├── actor.ts
│ │ ├── custom_field.ts
│ │ ├── image.ts
│ │ ├── index.ts
│ │ ├── label.ts
│ │ ├── marker.ts
│ │ ├── movie.ts
│ │ ├── scene.ts
│ │ └── studio.ts
│ └── types.ts
├── hash.ts
├── import
│ ├── create.ts
│ ├── index.ts
│ ├── schemas
│ │ ├── actor.ts
│ │ ├── common.ts
│ │ ├── custom_field.ts
│ │ ├── label.ts
│ │ ├── marker.ts
│ │ ├── movie.ts
│ │ ├── scene.ts
│ │ └── studio.ts
│ ├── types.ts
│ ├── validate.ts
│ └── verify.ts
├── index.ts
├── izzy.ts
├── logger.ts
├── mem.ts
├── middlewares
│ └── cors.ts
├── password.ts
├── plugin_events
│ ├── actor.ts
│ ├── movie.ts
│ └── scene.ts
├── plugins
│ ├── index.ts
│ └── validate.ts
├── query_extractor.ts
├── queue
│ ├── check.ts
│ └── processing.ts
├── queue_loop.ts
├── queue_router.ts
├── render.ts
├── scanner.ts
├── search
│ ├── actor.ts
│ ├── common.ts
│ ├── image.ts
│ ├── index.ts
│ ├── internal
│ │ └── index.ts
│ ├── marker.ts
│ ├── movie.ts
│ ├── scene.ts
│ └── studio.ts
├── server.ts
├── setup.ts
├── types
│ ├── actor.ts
│ ├── actor_reference.ts
│ ├── countries.ts
│ ├── custom_field.ts
│ ├── image.ts
│ ├── label.ts
│ ├── labelled_item.ts
│ ├── marker.ts
│ ├── movie.ts
│ ├── movie_scene.ts
│ ├── scene.ts
│ ├── studio.ts
│ ├── utility.ts
│ └── watch.ts
└── typings
│ ├── js-sha512.d.ts
│ └── merge-img.d.ts
├── test
├── config
│ ├── index.fixture.ts
│ ├── index.spec.ts
│ ├── schema.fixture.ts
│ └── schema.spec.ts
├── fixtures
│ ├── files
│ │ ├── image001.jpg
│ │ ├── image002.jpg
│ │ ├── image003.jpg
│ │ ├── image004.jpg
│ │ ├── image005.jpg
│ │ ├── some_folder
│ │ │ ├── image006.jpg
│ │ │ ├── image007.jpg
│ │ │ ├── image008.jpg
│ │ │ ├── image009.jpg
│ │ │ └── image010.jpg
│ │ └── video001.mp4
│ ├── matching_actor.fixture.ts
│ ├── matching_label.fixture.ts
│ ├── remove_extension.fixture.ts
│ ├── strip_string.fixture.ts
│ ├── url_ext.fixture.ts
│ └── walk.fixture.ts
├── init.ts
├── string.spec.ts
├── url_ext.spec.ts
├── util.ts
└── walk.spec.ts
├── tsconfig.dev.json
├── tsconfig.json
└── views
├── dvd-renderer.html
├── error.html
├── setup.html
└── signin.html
/.eslintignore:
--------------------------------------------------------------------------------
1 | # will probably be deprecated after 0.23 anyway
2 | src/compat/index.ts
3 | # TODO: do later
4 | src/import/**/*.ts
5 | dvd_renderer.ts
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | es6: true,
4 | node: true,
5 | },
6 | extends: [
7 | "eslint:recommended",
8 | "standard",
9 | "plugin:@typescript-eslint/recommended",
10 | "plugin:@typescript-eslint/recommended-requiring-type-checking",
11 | "prettier/@typescript-eslint",
12 | "plugin:prettier/recommended",
13 | ],
14 | globals: {
15 | Atomics: "readonly",
16 | SharedArrayBuffer: "readonly",
17 | },
18 | parser: "@typescript-eslint/parser",
19 | parserOptions: {
20 | ecmaVersion: 11,
21 | project: ["./tsconfig.json"],
22 | sourceType: "module",
23 | tsconfigRootDir: __dirname,
24 | },
25 | plugins: ["@typescript-eslint", "simple-import-sort"],
26 | root: true,
27 | rules: {
28 | "@typescript-eslint/restrict-template-expressions": "off",
29 | "@typescript-eslint/no-misused-promises": "off",
30 | "no-async-promise-executor": "off",
31 | "@typescript-eslint/no-namespace": "off",
32 | // Turn off default import rules
33 | "sort-imports": "off",
34 | "import/order": "off",
35 | // Use simple-import-sort instead
36 | "simple-import-sort/sort": "error",
37 | "@typescript-eslint/unbound-method": [
38 | "error",
39 | {
40 | ignoreStatic: true,
41 | },
42 | ],
43 | "@typescript-eslint/restrict-template-expressions": [
44 | "error",
45 | {
46 | allowNumber: true,
47 | allowBoolean: true,
48 | allowNullish: true,
49 | },
50 | ],
51 | },
52 | };
53 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[Bug]
"
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[Feature] "
5 | labels: new feature
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/workflows/build-app.yml:
--------------------------------------------------------------------------------
1 | name: Build app
2 |
3 | on:
4 | push:
5 | branches:
6 | - dev
7 | pull_request:
8 | branches:
9 | - dev
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | node-version: [8.x]
17 | steps:
18 | - uses: actions/checkout@v1
19 | - name: Use Node.js ${{ matrix.node-version }}
20 | uses: actions/setup-node@v1
21 | with:
22 | node-version: ${{ matrix.node-version }}
23 | - name: Test app
24 | run: |
25 | npm run install:app
26 | npm run build:app
27 | env:
28 | CI: true
29 |
--------------------------------------------------------------------------------
/.github/workflows/build-server.yml:
--------------------------------------------------------------------------------
1 | name: Build server
2 |
3 | on:
4 | push:
5 | branches:
6 | - dev
7 | pull_request:
8 | branches:
9 | - dev
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | node-version: [8.x]
17 | steps:
18 | - uses: actions/checkout@v1
19 | - name: Use Node.js ${{ matrix.node-version }}
20 | uses: actions/setup-node@v1
21 | with:
22 | node-version: ${{ matrix.node-version }}
23 | - name: Test server
24 | run: |
25 | npm install
26 | npm run transpile
27 | npm run test
28 | env:
29 | CI: true
30 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: reviewdog
2 | on: [pull_request]
3 | jobs:
4 | eslint-added:
5 | name: runner / eslint-added
6 | runs-on: ubuntu-latest
7 | steps:
8 | - uses: actions/checkout@v1
9 | - name: eslint
10 | uses: reviewdog/action-eslint@v1
11 | with:
12 | github_token: ${{ secrets.GITHUB_TOKEN }}
13 | reporter: github-check
14 | eslint_flags: "src/**/*.ts"
15 | fail_on_error: true
16 | filter_mode: added
17 |
--------------------------------------------------------------------------------
/.github/workflows/push.yml:
--------------------------------------------------------------------------------
1 | name: Push dev
2 |
3 | on:
4 | push:
5 | branches:
6 | - dev
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v1
13 | - name: Discord notification
14 | env:
15 | DISCORD_USERNAME: GitHub
16 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_HOOK }}
17 | uses: Ilshidur/action-discord@master
18 | with:
19 | args: 'New commit to *dev* by **{{ EVENT_PAYLOAD.pusher.name }}**'
20 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | release:
5 | types: [created]
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v1
12 | - uses: actions/setup-node@v1
13 | with:
14 | node-version: '10.x'
15 | - name: Install
16 | run: |
17 | npm ci
18 | npm run install:app
19 | - name: Build
20 | run: |
21 | npm run build:all
22 | - name: Release
23 | uses: softprops/action-gh-release@v1
24 | if: startsWith(github.ref, 'refs/tags/')
25 | with:
26 | files: |
27 | releases/mac.zip
28 | releases/linux.zip
29 | releases/win.zip
30 | env:
31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32 | - name: Discord notification
33 | env:
34 | DISCORD_USERNAME: GitHub
35 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_HOOK }}
36 | uses: Ilshidur/action-discord@master
37 | with:
38 | args: 'Version **{{ EVENT_PAYLOAD.release.tag_name }}** released!!'
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
18 | .grunt
19 |
20 | # node-waf configuration
21 | .lock-wscript
22 |
23 | # Dependency directory
24 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
25 | node_modules
26 | build/
27 | db\.json
28 |
29 |
30 | config\.json
31 |
32 | library/*
33 | bin/
34 |
35 | configg\.json
36 | /ffmpeg
37 | /ffprobe
38 | app/dist/
39 | release/
40 | releases/
41 | tmp/
42 | backups/
43 | /plugins/
44 | imports/
45 |
46 | config\.yaml
47 |
48 | images\.json
49 |
50 | izzy
51 | izzy.exe
52 | compat/cross_references\.db
53 |
54 | .vscode
55 |
56 | config.test.json
57 | config.test.yaml
58 |
59 | gianna
60 | gianna.exe
61 | ffmpeg.exe
62 | ffprobe.exe
63 |
64 | config\.old\.yaml
65 |
--------------------------------------------------------------------------------
/.mocharc.js:
--------------------------------------------------------------------------------
1 | process.env.PREVENT_STARTUP = "true";
2 | process.env.NODE_ENV = "test";
3 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true,
3 | trailingComma: "es5",
4 | singleQuote: false,
5 | printWidth: 100,
6 | tabWidth: 2,
7 | };
8 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:lts-buster as build-env
2 | WORKDIR /app
3 | ADD . /app
4 | RUN cd /app && \
5 | npm install && \
6 | npm run install:app && \
7 | cd /app && \
8 | npm run build
9 |
10 | from debian:buster
11 | COPY --from=build-env /app/release/porn-vault /
12 | COPY --from=build-env /app/release/app/ /app
13 | COPY --from=build-env /app/release/views/ /views
14 | RUN apt-get update && apt-get -y install ca-certificates ffmpeg && rm -rf /var/lib/apt/lists/*
15 |
16 | COPY assets /assets
17 |
18 | COPY config.json.example /
19 | COPY run.sh /
20 | VOLUME [ "/config" ]
21 | EXPOSE 3000
22 | ENTRYPOINT ["/run.sh"]
23 |
--------------------------------------------------------------------------------
/app/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/app/README.md:
--------------------------------------------------------------------------------
1 | # app
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Customize configuration
19 | See [Configuration Reference](https://cli.vuejs.org/config/).
20 |
--------------------------------------------------------------------------------
/app/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/app/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | app
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/apollo.ts:
--------------------------------------------------------------------------------
1 | import ApolloClient from "apollo-client";
2 | import { InMemoryCache } from "apollo-cache-inmemory";
3 | import { setContext } from "apollo-link-context";
4 | import { createUploadLink } from "apollo-upload-client";
5 |
6 | const port = 3000; // Server port set in config
7 |
8 | export const serverBase =
9 | process.env.NODE_ENV == "development" ? `http://localhost:${port}` : "";
10 |
11 | const authLink = setContext((_, { headers }) => {
12 | return {
13 | headers: {
14 | ...headers,
15 | "X-PASS": localStorage.getItem("password"),
16 | },
17 | };
18 | });
19 |
20 | export default new ApolloClient({
21 | link: authLink.concat(createUploadLink({ uri: `${serverBase}/ql` })),
22 | cache: new InMemoryCache(),
23 | defaultOptions: {
24 | watchQuery: { fetchPolicy: "no-cache", errorPolicy: "ignore" },
25 | query: { fetchPolicy: "no-cache", errorPolicy: "all" },
26 | },
27 | });
28 |
--------------------------------------------------------------------------------
/app/src/components/BindTitle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
42 |
--------------------------------------------------------------------------------
/app/src/components/Divider.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ icon }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/components/Flag.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ name }}
8 |
9 |
10 |
11 |
12 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/components/HomeWidgets/Base.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ icon }}
5 | {{ title }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/components/HomeWidgets/QueueInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ info.length }}
5 | videos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/components/HomeWidgets/TopActors.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Show more
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/components/HomeWidgets/UnwatchedActors.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 | Show more
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/components/ImageCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/components/Loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Loading...
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/components/NoResults.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Nothing found
5 |
6 |
mdi-magnify-close
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/fragments/actor.ts:
--------------------------------------------------------------------------------
1 | import gql from "graphql-tag";
2 |
3 | export default gql`
4 | fragment ActorFragment on Actor {
5 | _id
6 | name
7 | description
8 | bornOn
9 | age
10 | aliases
11 | rating
12 | favorite
13 | bookmark
14 | customFields
15 | availableFields {
16 | _id
17 | name
18 | type
19 | values
20 | unit
21 | }
22 | nationality {
23 | name
24 | alpha2
25 | nationality
26 | }
27 | }
28 | `;
29 |
--------------------------------------------------------------------------------
/app/src/fragments/image.ts:
--------------------------------------------------------------------------------
1 | import gql from "graphql-tag";
2 |
3 | export default gql`
4 | fragment ImageFragment on Image {
5 | _id
6 | name
7 | bookmark
8 | favorite
9 | rating
10 | }
11 | `;
12 |
--------------------------------------------------------------------------------
/app/src/fragments/movie.ts:
--------------------------------------------------------------------------------
1 | import gql from "graphql-tag";
2 |
3 | export default gql`
4 | fragment MovieFragment on Movie {
5 | _id
6 | name
7 | releaseDate
8 | description
9 | rating
10 | favorite
11 | bookmark
12 | labels {
13 | _id
14 | name
15 | }
16 | frontCover {
17 | _id
18 | color
19 | }
20 | backCover {
21 | _id
22 | }
23 | spineCover {
24 | _id
25 | }
26 | studio {
27 | _id
28 | name
29 | }
30 | duration
31 | size
32 | }
33 | `;
34 |
--------------------------------------------------------------------------------
/app/src/fragments/scene.ts:
--------------------------------------------------------------------------------
1 | import gql from "graphql-tag";
2 |
3 | export default gql`
4 | fragment SceneFragment on Scene {
5 | _id
6 | addedOn
7 | name
8 | releaseDate
9 | description
10 | rating
11 | favorite
12 | bookmark
13 | studio {
14 | _id
15 | name
16 | }
17 | labels {
18 | _id
19 | name
20 | }
21 | thumbnail {
22 | _id
23 | color
24 | }
25 | meta {
26 | size
27 | duration
28 | fps
29 | dimensions {
30 | width
31 | height
32 | }
33 | }
34 | watches
35 | streamLinks
36 | path
37 | customFields
38 | availableFields {
39 | _id
40 | name
41 | type
42 | values
43 | unit
44 | }
45 | }
46 | `;
47 |
--------------------------------------------------------------------------------
/app/src/fragments/studio.ts:
--------------------------------------------------------------------------------
1 | import gql from "graphql-tag";
2 |
3 | export default gql`
4 | fragment StudioFragment on Studio {
5 | _id
6 | name
7 | description
8 | aliases
9 | rating
10 | favorite
11 | bookmark
12 | }
13 | `;
14 |
--------------------------------------------------------------------------------
/app/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 | import store from "./store";
5 | import vuetify from "./plugins/vuetify";
6 | import "roboto-fontface/css/roboto/roboto-fontface.css";
7 | import "@mdi/font/css/materialdesignicons.css";
8 | import VueTheMask from "vue-the-mask";
9 | import vueScrollBehavior from "vue-scroll-behavior";
10 |
11 | import BindTitle from "./components/BindTitle.vue";
12 | import DateInput from "./components/DateInput.vue";
13 | import Rating from "./components/Rating.vue";
14 | import LabelFilter from "./components/LabelFilter.vue";
15 | import Divider from "./components/Divider.vue";
16 | import NoResults from "./components/NoResults.vue";
17 | import Loading from "./components/Loading.vue";
18 | import Flag from "./components/Flag.vue";
19 | import WidgetCard from "./components/HomeWidgets/Base.vue";
20 |
21 | Vue.use(vueScrollBehavior, { router: router });
22 | Vue.use(VueTheMask);
23 |
24 | Vue.component("BindTitle", BindTitle);
25 | Vue.component("DateInput", DateInput);
26 | Vue.component("Rating", Rating);
27 | Vue.component("LabelFilter", LabelFilter);
28 | Vue.component("Divider", Divider);
29 | Vue.component("NoResults", NoResults);
30 | Vue.component("Loading", Loading);
31 | Vue.component("Flag", Flag);
32 | Vue.component("WidgetCard", WidgetCard);
33 |
34 | Vue.config.productionTip = false;
35 |
36 | new Vue({
37 | router,
38 | store,
39 | vuetify,
40 | render: (h) => h(App),
41 | }).$mount("#app");
42 |
--------------------------------------------------------------------------------
/app/src/mixins/drawer.ts:
--------------------------------------------------------------------------------
1 | // mixin.js
2 | import Vue from "vue";
3 | import Component from "vue-class-component";
4 | import { contextModule } from "../store/context";
5 |
6 | @Component
7 | export default class DrawerMixin extends Vue {
8 | get drawer() {
9 | return this.$vuetify.breakpoint.lgAndUp || contextModule.showFilters;
10 | }
11 |
12 | set drawer(val: boolean) {
13 | contextModule.toggleFilters(val);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/plugins/vuetify.ts:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuetify from "vuetify/lib";
3 | import colors from "vuetify/lib/util/colors";
4 |
5 | Vue.use(Vuetify);
6 |
7 | export default new Vuetify({
8 | theme: {
9 | options: {
10 | customProperties: true
11 | },
12 | themes: {
13 | light: {
14 | primary: colors.blue.base,
15 | error: colors.red.accent3,
16 | info: colors.blue.darken2,
17 | success: colors.green.base,
18 | warning: colors.orange.darken2
19 | },
20 | dark: {
21 | primary: colors.blue.lighten3,
22 | error: colors.red.accent2,
23 | info: colors.blue.darken2,
24 | success: colors.green.base,
25 | warning: colors.orange.lighten2
26 | }
27 | }
28 | }
29 | });
30 |
--------------------------------------------------------------------------------
/app/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue'
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue'
3 | export default Vue
4 | }
5 |
--------------------------------------------------------------------------------
/app/src/store/context.ts:
--------------------------------------------------------------------------------
1 | import { VuexModule, Module, Mutation, Action } from "vuex-class-modules";
2 |
3 | @Module
4 | class ContextModule extends VuexModule {
5 | showFilters = false;
6 |
7 | sceneAspectRatio = 1;
8 | actorAspectRatio = 1;
9 | scenePauseOnUnfocus = false;
10 | showCardLabels = true;
11 |
12 | fillActorCards = true;
13 |
14 | showSidenav = true; // TODO: store and load from localStorage
15 | scenePreviewOnMouseHover = false;
16 |
17 | @Mutation
18 | toggleSidenav(bool: boolean) {
19 | this.showSidenav = bool;
20 | }
21 |
22 | @Mutation
23 | toggleActorCardStyle(bool: boolean) {
24 | this.fillActorCards = bool;
25 | }
26 |
27 | @Mutation
28 | toggleCardLabels(bool: boolean) {
29 | this.showCardLabels = bool;
30 | }
31 |
32 | @Mutation
33 | toggleFilters(bool: boolean) {
34 | this.showFilters = bool;
35 | }
36 |
37 | @Mutation
38 | setScenePauseOnUnfocus(val: boolean) {
39 | this.scenePauseOnUnfocus = val;
40 | }
41 |
42 | @Mutation
43 | setSceneAspectRatio(val: number) {
44 | this.sceneAspectRatio = val;
45 | }
46 |
47 | @Mutation
48 | setActorAspectRatio(val: number) {
49 | this.actorAspectRatio = val;
50 | }
51 |
52 | @Mutation
53 | setScenePreviewOnMouseHover(val: boolean) {
54 | this.scenePreviewOnMouseHover = val;
55 | }
56 | }
57 |
58 | import store from "./index";
59 | export const contextModule = new ContextModule({ store, name: "context" });
60 |
--------------------------------------------------------------------------------
/app/src/store/image.ts:
--------------------------------------------------------------------------------
1 | import { VuexModule, Module, Mutation, Action } from "vuex-class-modules";
2 |
3 | @Module
4 | class ImageModule extends VuexModule {
5 | page = 1;
6 | numResults = 0;
7 | numPages = 0;
8 | // items = [] as IImage[];
9 |
10 | /* @Mutation
11 | unshift(items: IImage[]) {
12 | this.items.unshift(...items);
13 | } */
14 |
15 | @Mutation
16 | resetPagination() {
17 | // this.items = [];
18 | this.numPages = 0;
19 | this.numResults = 0;
20 | this.page = 1;
21 | }
22 |
23 | @Mutation
24 | setPage(num: number) {
25 | this.page = num;
26 | }
27 |
28 | /* @Mutation
29 | removeImages(ids: string[]) {
30 | for (const id of ids) {
31 | this.items = this.items.filter((img) => img._id != id);
32 | }
33 | } */
34 |
35 | @Mutation
36 | setPagination({
37 | // items,
38 | numResults,
39 | numPages,
40 | }: {
41 | // items: IImage[];
42 | numResults: number;
43 | numPages: number;
44 | }) {
45 | // this.items = items;
46 | this.numResults = numResults;
47 | this.numPages = numPages;
48 | }
49 | }
50 |
51 | import store from "./index";
52 | import IImage from "@/types/image";
53 | export const imageModule = new ImageModule({ store, name: "images" });
54 |
--------------------------------------------------------------------------------
/app/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | Vue.use(Vuex)
5 |
6 | export default new Vuex.Store({})
7 |
--------------------------------------------------------------------------------
/app/src/store/markers.ts:
--------------------------------------------------------------------------------
1 | import { VuexModule, Module, Mutation, Action } from "vuex-class-modules";
2 |
3 | @Module
4 | class MarkerModule extends VuexModule {
5 | page = 1;
6 | numResults = 0;
7 | numPages = 0;
8 |
9 | @Mutation
10 | resetPagination() {
11 | // this.items = [];
12 | this.numPages = 0;
13 | this.numResults = 0;
14 | this.page = 1;
15 | }
16 |
17 | @Mutation
18 | setPage(num: number) {
19 | this.page = num;
20 | }
21 |
22 | @Mutation
23 | setPagination({
24 | // items,
25 | numResults,
26 | numPages,
27 | }: {
28 | // items: IMarker[];
29 | numResults: number;
30 | numPages: number;
31 | }) {
32 | // this.items = items;
33 | this.numResults = numResults;
34 | this.numPages = numPages;
35 | }
36 | }
37 |
38 | import store from "./index";
39 | export const markerModule = new MarkerModule({ store, name: "markers" });
40 |
--------------------------------------------------------------------------------
/app/src/types/actor.ts:
--------------------------------------------------------------------------------
1 | type AttachedImage = {
2 | _id: string;
3 | } | null;
4 |
5 | export interface ICollabActor {
6 | _id: string;
7 | name: string;
8 | thumbnail: AttachedImage;
9 | avatar: AttachedImage;
10 | }
11 |
12 | export default interface IActor {
13 | _id: string;
14 | name: string;
15 | description: string | null;
16 | bornOn: number | null;
17 | age: number | null;
18 | aliases: string[];
19 | rating: number | null;
20 | favorite: boolean;
21 | bookmark: number | null;
22 | labels: {
23 | _id: string;
24 | name: string;
25 | }[];
26 | thumbnail: {
27 | _id: string;
28 | color: string | null;
29 | } | null;
30 | altThumbnail: {
31 | _id: string;
32 | color?: string | null;
33 | } | null;
34 | hero?: {
35 | _id: string;
36 | color?: string | null;
37 | } | null;
38 | avatar?: {
39 | _id: string;
40 | color?: string | null;
41 | } | null;
42 | customFields: { _id: string; name: string; values?: string[]; type: string };
43 | availableFields: {
44 | _id: string;
45 | name: string;
46 | values?: string[];
47 | type: string;
48 | unit: string | null;
49 | }[];
50 | nationality: {
51 | name: string;
52 | alpha2: string;
53 | nationality: string;
54 | };
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/types/image.ts:
--------------------------------------------------------------------------------
1 | import IActor from "./actor";
2 |
3 | export default interface IImage {
4 | _id: string;
5 | name: string;
6 | labels: {
7 | _id: string;
8 | name: string;
9 | }[];
10 | scene: {
11 | _id: string;
12 | name: string;
13 | };
14 | actors: IActor[];
15 | bookmark: boolean;
16 | favorite: boolean;
17 | rating: number | null;
18 | color?: string | null;
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/types/label.ts:
--------------------------------------------------------------------------------
1 | export default interface ILabel {
2 | _id: string;
3 | name: string;
4 | aliases: string[];
5 | thumbnail: {
6 | _id: string;
7 | };
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/types/movie.ts:
--------------------------------------------------------------------------------
1 | import IActor from "./actor";
2 | import IScene from "./scene";
3 |
4 | export default interface IMovie {
5 | _id: string;
6 | name: string;
7 | description: string | null;
8 | releaseDate: number | null;
9 | rating: number | null;
10 | favorite: boolean;
11 | bookmark: number | null;
12 |
13 | frontCover: {
14 | _id: string;
15 | color: string | null;
16 | } | null;
17 | backCover: {
18 | _id: string;
19 | } | null;
20 | spineCover: {
21 | _id: string;
22 | } | null;
23 | studio: any;
24 | scenes: IScene[];
25 | actors: IActor[];
26 | labels: {
27 | _id: string;
28 | name: string;
29 | }[];
30 |
31 | duration: number | null;
32 | size: number | null;
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/types/scene.ts:
--------------------------------------------------------------------------------
1 | import IActor from "./actor";
2 |
3 | export default interface IScene {
4 | _id: string;
5 | addedOn: number;
6 | name: string;
7 | releaseDate: number | null;
8 | description: string | null;
9 | rating: number | null;
10 | favorite: boolean;
11 | bookmark: number | null;
12 | actors: IActor[];
13 | studio: any;
14 | labels: {
15 | _id: string;
16 | name: string;
17 | }[];
18 | thumbnail: {
19 | _id: string;
20 | color: string | null;
21 | } | null;
22 | preview: {
23 | _id: string;
24 | } | null;
25 | meta: {
26 | size: number;
27 | duration: number;
28 | dimensions: {
29 | width: number;
30 | height: number;
31 | };
32 | };
33 | watches: number[];
34 | streamLinks: string[];
35 | customFields: { [key: string]: any };
36 | availableFields: {
37 | _id: string;
38 | name: string;
39 | values?: string[];
40 | type: string;
41 | unit: string | null;
42 | }[];
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/util/color.ts:
--------------------------------------------------------------------------------
1 | import Color from "color";
2 |
3 | export function ensureDarkColor(hex: string) {
4 | const col = Color(hex);
5 | if (col.value() > 50) {
6 | return Color(
7 | [col.hue(), col.saturationv(), col.value() - (col.value() - 30)],
8 | "hsv"
9 | ).hex();
10 | }
11 | return hex;
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/util/object.ts:
--------------------------------------------------------------------------------
1 | export function copy(t: T) {
2 | return JSON.parse(JSON.stringify(t)) as T;
3 | }
4 |
--------------------------------------------------------------------------------
/app/src/util/scene.ts:
--------------------------------------------------------------------------------
1 | import ApolloClient from "../apollo";
2 | import gql from "graphql-tag";
3 | import IScene from "@/types/scene";
4 | import { sceneModule } from "../store/scene";
5 |
6 | export function watch(scene: IScene) {
7 | ApolloClient.mutate({
8 | mutation: gql`
9 | mutation($id: String!) {
10 | watchScene(id: $id) {
11 | watches
12 | }
13 | }
14 | `,
15 | variables: {
16 | id: scene._id
17 | }
18 | })
19 | .then(res => {
20 | sceneModule.pushWatch(res.data.watchScene.watches.pop());
21 | })
22 | .catch(err => {
23 | console.error(err);
24 | });
25 | }
26 |
27 | export function unwatch(scene: IScene) {
28 | ApolloClient.mutate({
29 | mutation: gql`
30 | mutation($id: String!) {
31 | unwatchScene(id: $id) {
32 | watches
33 | }
34 | }
35 | `,
36 | variables: {
37 | id: scene._id
38 | }
39 | })
40 | .then(res => {
41 | sceneModule.popWatch();
42 | })
43 | .catch(err => {
44 | console.error(err);
45 | });
46 | }
47 |
--------------------------------------------------------------------------------
/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "noImplicitAny": false,
9 | "moduleResolution": "node",
10 | "experimentalDecorators": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "sourceMap": true,
14 | "baseUrl": ".",
15 | "types": [
16 | "vue",
17 | "webpack-env",
18 | "vuetify"
19 | ],
20 | "paths": {
21 | "@/*": [
22 | "src/*"
23 | ]
24 | },
25 | "lib": [
26 | "esnext",
27 | "dom",
28 | "dom.iterable",
29 | "scripthost"
30 | ]
31 | },
32 | "include": [
33 | "src/**/*.ts",
34 | "src/**/*.tsx",
35 | "src/**/*.vue",
36 | "tests/**/*.ts",
37 | "tests/**/*.tsx"
38 | ],
39 | "exclude": [
40 | "node_modules"
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/app/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "transpileDependencies": [
3 | "vuetify"
4 | ]
5 | }
--------------------------------------------------------------------------------
/assets/bump.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/assets/bump.jpg
--------------------------------------------------------------------------------
/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/assets/favicon.png
--------------------------------------------------------------------------------
/assets/flags/ae.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/ag.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/am.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/at.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/au.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/ax.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/assets/flags/az.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/ba.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/assets/flags/bb.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/bd.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/flags/be.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/bf.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/bg.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/bh.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/flags/bi.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/bj.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/bl.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/bq.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/bs.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/bv.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/bw.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/ca.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/flags/cd.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/cf.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/cg.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/assets/flags/ch.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/ci.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/cl.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/cm.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/cn.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/flags/co.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/cr.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/cu.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/cv.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/cw.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/cz.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/assets/flags/de.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/dj.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/dk.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/dz.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/ee.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/eh.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/es-ct.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/flags/et.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/eu.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/assets/flags/fi.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/fm.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/flags/fo.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/assets/flags/fr.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/ga.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/gb-eng.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/gb-sct.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/flags/gb.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/ge.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/gf.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/gg.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/gh.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/gl.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/flags/gm.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/gn.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/gp.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/gr.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/assets/flags/gw.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/gy.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/hm.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/hn.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/assets/flags/hu.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/id.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/ie.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/il.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/in.svg:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/assets/flags/iq.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/assets/flags/is.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/assets/flags/it.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/jm.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/jo.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/flags/jp.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/flags/ke.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/assets/flags/km.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/flags/kn.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/kp.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/kw.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/la.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/assets/flags/lc.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/lr.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/ls.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/lt.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/lu.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/lv.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/ly.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/ma.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/flags/mc.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/mf.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/mg.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/mh.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/mk.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/ml.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/mm.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/flags/mn.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/mo.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/mq.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/mr.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/mu.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/mv.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/my.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/na.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/flags/nc.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/ne.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/ng.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/nl.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/no.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/np.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/nr.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/assets/flags/pa.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/ph.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/pk.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/pl.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/pm.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/pr.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/ps.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/pw.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/flags/qa.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/flags/re.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/ro.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/ru.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/rw.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/sb.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/sc.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/sd.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/se.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/flags/sg.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/sj.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/sk.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/assets/flags/sl.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/sn.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/so.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/flags/sr.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/ss.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/st.svg:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/assets/flags/sy.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/td.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/tf.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/assets/flags/tg.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/th.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/tk.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/tl.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/tn.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/to.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/assets/flags/tr.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/tt.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/assets/flags/tw.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/assets/flags/tz.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/assets/flags/ua.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/assets/flags/uz.svg:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/assets/flags/vc.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/assets/flags/ve.svg:
--------------------------------------------------------------------------------
1 |
27 |
--------------------------------------------------------------------------------
/assets/flags/vn.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/assets/flags/wf.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/ws.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/ye.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/yt.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/assets/flags/za.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/doc/build_from_source.md:
--------------------------------------------------------------------------------
1 | ## Build from source
2 |
3 | - Install [Git](https://git-scm.com/)
4 | - Install [Node.js](https://nodejs.org/en/)
5 | - Clone the repository
6 | - `git clone https://github.com/boi123212321/porn-vault.git`
7 | - Install dependencies
8 | - `npm install`
9 | - Build web app dependencies
10 | - `cd app`
11 | - `npm install`
12 | - Run web app in dev mode (in app/ folder)
13 | - `npm run serve`
14 | - Build web app (in app/ folder)
15 | - `npm run build`
16 | - Transpile server (in root folder)
17 | - `npm run transpile`
18 | - OR
19 | - `npm run watch` (same as above, but will retranspile every time the sources change)
20 | - Run server in dev mode (in root folder)
21 | - `npm run mon`
22 | - Run server in release mode (in root folder)
23 | - `npm run build`
24 | - And run the built executable in the release/ folder
25 |
26 |
27 | ## Debugging in Visual Studio Code
28 |
29 | 1. First transpile the sources with the `transpile` or `watch` script
30 |
31 | 2. Add the following to your `.vscode/launch.json` configuration in the project folder:
32 | ```json
33 | {
34 | "name": "Launch pre-transpiled build/ via nodemon",
35 | "type": "node",
36 | "request": "launch",
37 | "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/nodemon",
38 | "program": "${workspaceFolder}/build",
39 | "restart": true,
40 | "console": "externalTerminal",
41 | "internalConsoleOptions": "neverOpen"
42 | }
43 | ```
44 | > This corresponds to the `mon` script
45 |
46 | 3. ????
47 | 4. PROFIT!!!
--------------------------------------------------------------------------------
/doc/img/actor_collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/actor_collection.jpg
--------------------------------------------------------------------------------
/doc/img/actor_details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/actor_details.jpg
--------------------------------------------------------------------------------
/doc/img/btc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/btc.png
--------------------------------------------------------------------------------
/doc/img/image_collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/image_collection.jpg
--------------------------------------------------------------------------------
/doc/img/image_details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/image_details.jpg
--------------------------------------------------------------------------------
/doc/img/movie_collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/movie_collection.jpg
--------------------------------------------------------------------------------
/doc/img/movie_details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/movie_details.jpg
--------------------------------------------------------------------------------
/doc/img/parent_studio.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/parent_studio.jpg
--------------------------------------------------------------------------------
/doc/img/plugin_filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/plugin_filter.png
--------------------------------------------------------------------------------
/doc/img/scene_collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/scene_collection.jpg
--------------------------------------------------------------------------------
/doc/img/scene_details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/scene_details.jpg
--------------------------------------------------------------------------------
/doc/img/studio_collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CyyberFroggy/porn-vault-1/bbe3dfb2ee7948c6bb5b71dc57ad9423ec005da0/doc/img/studio_collection.jpg
--------------------------------------------------------------------------------
/doc/import.md:
--------------------------------------------------------------------------------
1 | # Import format
2 |
3 | Add one or more folders to import from to `BULK_IMPORT_PATHS` in your config
4 | Then add .json or .yaml files containing data:
5 |
6 | ```
7 | {
8 | "movies": {
9 | "[iid]":
10 | },
11 | "scenes": {
12 | "[iid]":
13 | },
14 | "actors": {
15 | "[iid]":
16 | },
17 | "studios": {
18 | "[iid]":
19 | },
20 | "labels": {
21 | "[iid]":
22 | },
23 | "markers": {
24 | "[iid]":
25 | },
26 | "customFields": {
27 | "[iid]":
28 | }
29 | }
30 | ```
31 |
32 | IIDs can reference objects with IIDs **only** in that file, or, if a "real" ID is used, it will reference an object in the database.
33 |
34 | Check [here](https://github.com/boi123212321/porn-vault/tree/dev/src/import/schemas) for schemas.
35 |
36 | Use `--commit-import` to actually add stuff, omit, if you want to check the validity of your import.
37 |
--------------------------------------------------------------------------------
/doc/pipe_plugins.md:
--------------------------------------------------------------------------------
1 | ## Pipe plugin results into another plugin
2 |
3 | Take this plugin as an example of an imaginary API that we have fetched data from:
4 |
5 | ```js
6 | // ./plugins/imaginaryapi.js
7 | module.exports = () => {
8 | return {
9 | labels: ["anal", "dp", "gangbang", "blonde"],
10 | };
11 | };
12 | ```
13 |
14 | ```javascript
15 | // config.json
16 |
17 | {
18 | "plugins": {
19 | "events": {
20 | "actorCreated": ["imaginaryapi"]
21 | },
22 | "register": {
23 | "imaginaryapi": {
24 | "path": "./plugins/imaginaryapi.js"
25 | }
26 | }
27 | }
28 | }
29 | ```
30 |
31 | What if we don't want any hair color associated via a label?
32 | This can be solved by transforming the plugin result with another plugin, instead of filtering in the API plugin.
33 |
34 | ```js
35 | // ./plugins/nohaircolor.js
36 |
37 | module.exports = ({ data }) => {
38 | if (data.labels) {
39 | return {
40 | labels: data.labels.filter((s) => s != "blonde"),
41 | };
42 | }
43 | return {};
44 | };
45 | ```
46 |
47 | ```javascript
48 | // config.json
49 |
50 | {
51 | "plugins": {
52 | "events": {
53 | "actorCreated": ["imaginaryapi", "nohaircolor"]
54 | },
55 | "register": {
56 | "imaginaryapi": {
57 | "path": "./plugins/imaginaryapi.js"
58 | },
59 | "nohaircolor": {
60 | "path": "./plugins/nohaircolor.js"
61 | }
62 | }
63 | }
64 | }
65 | ```
66 |
67 | ### Result
68 |
69 | 
70 |
--------------------------------------------------------------------------------
/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["plugins/*", "assets/*"]
3 | }
4 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # We want a configuration file in /config so it can be stored in a persistant volume and not whiped out if we update the container.
3 | # Check if this symlink exists
4 | if [ ! -L config.json ]
5 | then
6 | if [ ! -f /config/config.json ]
7 | then
8 | echo "copying example configuration"
9 | mv config.json.example /config/config.json
10 | ln -s config/config.json config.json
11 | fi
12 | fi
13 | if [ ! -d /videos ]
14 | then
15 | mkdir /videos
16 | fi
17 | if [ ! -d /images ]
18 | then
19 | mkdir /images
20 | fi
21 | /porn-vault
22 |
--------------------------------------------------------------------------------
/src/apollo.ts:
--------------------------------------------------------------------------------
1 | import { ApolloServer } from "apollo-server-express";
2 | // import responseCachePlugin from "apollo-server-plugin-response-cache";
3 | import express from "express";
4 |
5 | // import { getConfig } from "./config";
6 | import schema from "./graphql/types";
7 |
8 | export function mountApolloServer(app: express.Application): void {
9 | // const config = getConfig();
10 | const server = new ApolloServer({
11 | plugins: [
12 | /* responseCachePlugin() */
13 | ],
14 | schema,
15 | /* cacheControl: {
16 | defaultMaxAge: Math.max(0, config.),
17 | }, */
18 | context: ({ req }) => ({
19 | req,
20 | }),
21 | });
22 | server.applyMiddleware({ app, path: "/ql" });
23 | }
24 |
--------------------------------------------------------------------------------
/src/args.ts:
--------------------------------------------------------------------------------
1 | import yargs from "yargs";
2 |
3 | import * as logger from "./logger";
4 |
5 | const argv = yargs
6 | .boolean("process-queue")
7 | .boolean("commit-import")
8 | .boolean("ignore-integrity")
9 | .boolean("skip-compaction")
10 | .boolean("update-izzy")
11 | .boolean("update-gianna")
12 | .number("index-slice-size").argv;
13 | logger.log(argv);
14 | export default argv;
15 |
--------------------------------------------------------------------------------
/src/config/validate.ts:
--------------------------------------------------------------------------------
1 | import { existsSync } from "fs";
2 |
3 | import { IConfig } from "../config/schema";
4 | import * as logger from "../logger";
5 |
6 | export function validateFFMPEGPaths(config: IConfig): void {
7 | if (config.binaries.ffmpeg) {
8 | const found = existsSync(config.binaries.ffmpeg);
9 | if (!found) {
10 | logger.error(`FFMPEG binary not found at ${config.binaries.ffmpeg}`);
11 | process.exit(1);
12 | }
13 | } else {
14 | logger.error(`No FFMPEG path defined in config.json`);
15 | process.exit(1);
16 | }
17 |
18 | if (config.binaries.ffprobe) {
19 | const found = existsSync(config.binaries.ffprobe);
20 | if (!found) {
21 | logger.error(`FFPROBE binary not found at ${config.binaries.ffprobe}`);
22 | process.exit(1);
23 | }
24 | } else {
25 | logger.error(`No FFPROBE path defined in config.json`);
26 | process.exit(1);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/dvd_renderer.ts:
--------------------------------------------------------------------------------
1 | import * as express from "express";
2 |
3 | import { getConfig } from "./config/index";
4 | import { renderHandlebars } from "./render";
5 | import Image from "./types/image";
6 | import Movie from "./types/movie";
7 | import Studio from "./types/studio";
8 |
9 | export async function dvdRenderer(req: express.Request, res: express.Response): Promise {
10 | const config = getConfig();
11 | const movie = await Movie.getById(req.params.id);
12 |
13 | if (!movie) {
14 | res.status(404).send(
15 | await renderHandlebars("./views/error.html", {
16 | code: 404,
17 | message: `Movie ${req.params.id} not found`,
18 | })
19 | );
20 | } else {
21 | const color = movie.frontCover ? (await Image.getById(movie.frontCover))?.color : "";
22 |
23 | const studioName = movie.studio ? (await Studio.getById(movie.studio))?.name : "";
24 |
25 | const imageOrNull = function (id: string | null) {
26 | return id ? `/image/${id}?password=${config.auth.password}` : null;
27 | };
28 |
29 | res.status(200).send(
30 | await renderHandlebars("./views/dvd-renderer.html", {
31 | color,
32 | movieName: movie.name,
33 | studioName,
34 | light: req.query.light === "true",
35 | frontCover: imageOrNull(movie.frontCover),
36 | backCover: imageOrNull(movie.backCover),
37 | spineCover: imageOrNull(movie.spineCover),
38 | })
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/exit.ts:
--------------------------------------------------------------------------------
1 | import { giannaProcess } from "./gianna";
2 | import { izzyProcess } from "./izzy";
3 | import * as logger from "./logger";
4 |
5 | function killProcess(code = 0) {
6 | return () => {
7 | if (izzyProcess) {
8 | logger.log("Killing izzy...");
9 | izzyProcess.kill();
10 | }
11 | if (giannaProcess) {
12 | logger.log("Killing gianna...");
13 | giannaProcess.kill();
14 | }
15 |
16 | // When running tests, we want to be able to cleanup any services,
17 | // but we cannot overload the actual 'exit' otherwise mocha's
18 | // exit code will not reflect the actual result of the tests
19 | if (process.env.NODE_ENV !== "test") {
20 | process.exit(code);
21 | }
22 | };
23 | }
24 |
25 | export function applyExitHooks(): void {
26 | process.on("exit", killProcess(0));
27 | process.on("SIGTERM", killProcess(0));
28 | process.on("SIGINT", killProcess(0));
29 | process.on("SIGUSR1", killProcess(0));
30 | process.on("SIGUSR2", killProcess(0));
31 | process.on("uncaughtException", (e) => {
32 | console.log("Uncaught Exception...");
33 | console.log(e.stack);
34 | killProcess(99)();
35 | });
36 | }
37 |
--------------------------------------------------------------------------------
/src/ffmpeg/screenshot.ts:
--------------------------------------------------------------------------------
1 | import ffmpeg from "fluent-ffmpeg";
2 |
3 | export function singleScreenshot(
4 | video: string,
5 | output: string,
6 | time: number,
7 | maxWidth = 960
8 | ): Promise {
9 | return new Promise((resolve, reject) => {
10 | ffmpeg(video)
11 | .seekInput(time)
12 | .output(output)
13 | .outputOptions("-frames", "1")
14 | .size(`"${maxWidth}x?"`)
15 | .on("end", () => {
16 | resolve(output);
17 | })
18 | .on("error", (err: Error) => {
19 | reject(err);
20 | })
21 | .run();
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/src/fs/index.ts:
--------------------------------------------------------------------------------
1 | import { lstatSync } from "fs";
2 |
3 | export const isDirectory = (path: string): boolean => lstatSync(path).isDirectory();
4 |
--------------------------------------------------------------------------------
/src/graphql/mutation.ts:
--------------------------------------------------------------------------------
1 | import ActorMutations from "./mutations/actor";
2 | import CustomFieldMutations from "./mutations/custom_field";
3 | import ImageMutations from "./mutations/image";
4 | import LabelMutations from "./mutations/label";
5 | import MarkerMutations from "./mutations/marker";
6 | import MovieMutations from "./mutations/movie";
7 | import SceneMutations from "./mutations/scene";
8 | import StudioMutations from "./mutations/studio";
9 |
10 | export default {
11 | ...ImageMutations,
12 | ...ActorMutations,
13 | ...LabelMutations,
14 | ...SceneMutations,
15 | ...MovieMutations,
16 | ...StudioMutations,
17 | ...MarkerMutations,
18 | ...CustomFieldMutations,
19 | };
20 |
--------------------------------------------------------------------------------
/src/graphql/resolvers.ts:
--------------------------------------------------------------------------------
1 | import { GraphQLJSONObject } from "graphql-type-json";
2 | import GraphQLLong from "graphql-type-long";
3 |
4 | import MutationResolver from "./mutation";
5 | import ActorResolver from "./resolvers/actor";
6 | import CustomFieldResolver from "./resolvers/custom_field";
7 | import ImageResolver from "./resolvers/image";
8 | import LabelResolver from "./resolvers/label";
9 | import MarkerResolver from "./resolvers/marker";
10 | import MovieResolver from "./resolvers/movie";
11 | import QueryResolvers from "./resolvers/query";
12 | import SceneResolver from "./resolvers/scene";
13 | import SceneViewResolver from "./resolvers/scene_view";
14 | import StudioResolver from "./resolvers/studio";
15 |
16 | const resolvers = {
17 | Long: GraphQLLong,
18 | Object: GraphQLJSONObject,
19 |
20 | Actor: ActorResolver,
21 | Scene: SceneResolver,
22 | Image: ImageResolver,
23 | Query: QueryResolvers,
24 | Mutation: MutationResolver,
25 | Label: LabelResolver,
26 | Movie: MovieResolver,
27 | Studio: StudioResolver,
28 | CustomField: CustomFieldResolver,
29 | Marker: MarkerResolver,
30 | SceneView: SceneViewResolver,
31 | };
32 |
33 | export default resolvers;
34 |
--------------------------------------------------------------------------------
/src/graphql/resolvers/custom_field.ts:
--------------------------------------------------------------------------------
1 | export default {};
2 |
--------------------------------------------------------------------------------
/src/graphql/resolvers/image.ts:
--------------------------------------------------------------------------------
1 | import Actor from "../../types/actor";
2 | import Image from "../../types/image";
3 | import Label from "../../types/label";
4 | import Scene from "../../types/scene";
5 | import Studio from "../../types/studio";
6 |
7 | export default {
8 | async actors(image: Image): Promise {
9 | return await Image.getActors(image);
10 | },
11 | async scene(image: Image): Promise {
12 | if (image.scene) return await Scene.getById(image.scene);
13 | return null;
14 | },
15 | async labels(image: Image): Promise