Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File matching with stash hashs #1587

Merged
merged 2 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion pkg/api/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,14 @@ type RequestSCustomSiteCreate struct {
Company string `json:"scraperCompany"`
}

type GetStorageResponse struct {
Volumes []models.Volume `json:"volumes"`
MatchOhash bool `json:"match_ohash"`
}
type RequestSaveOptionsStorage struct {
MatchOhash bool `json:"match_ohash"`
}

type ConfigResource struct{}

func (i ConfigResource) WebService() *restful.WebService {
Expand Down Expand Up @@ -225,6 +233,9 @@ func (i ConfigResource) WebService() *restful.WebService {
Param(ws.PathParameter("storage-id", "Storage ID").DataType("int")).
Metadata(restfulspec.KeyOpenAPITags, tags))

ws.Route(ws.PUT("/storage").To(i.saveOptionsStorage).
Metadata(restfulspec.KeyOpenAPITags, tags))

// "DLNA" section endpoints
ws.Route(ws.PUT("/interface/dlna").To(i.saveOptionsDLNA).
Metadata(restfulspec.KeyOpenAPITags, tags))
Expand Down Expand Up @@ -468,7 +479,10 @@ func (i ConfigResource) listStorage(req *restful.Request, resp *restful.Response
(select sum(files.size) from files where files.volume_id = volumes.id) as total_size
from volumes order by last_scan desc;`).Scan(&vol)

resp.WriteHeaderAndEntity(http.StatusOK, vol)
var out GetStorageResponse
out.Volumes = vol
out.MatchOhash = config.Config.Storage.MatchOhash
resp.WriteHeaderAndEntity(http.StatusOK, out)
}

func (i ConfigResource) addStorage(req *restful.Request, resp *restful.Response) {
Expand Down Expand Up @@ -940,3 +954,16 @@ func (i ConfigResource) createCustomSite(req *restful.Request, resp *restful.Res

resp.WriteHeader(http.StatusOK)
}
func (i ConfigResource) saveOptionsStorage(req *restful.Request, resp *restful.Response) {
var r RequestSaveOptionsStorage
err := req.ReadEntity(&r)
if err != nil {
log.Error(err)
return
}

config.Config.Storage.MatchOhash = r.MatchOhash
config.SaveConfig()

resp.WriteHeaderAndEntity(http.StatusOK, r)
}
3 changes: 3 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ type ObjectConfig struct {
RunAtStartDelay int `default:"0" json:"runAtStartDelay"`
} `json:"stashdbRescrapeSchedule"`
} `json:"cron"`
Storage struct {
MatchOhash bool `default:"false" json:"match_ohash"`
} `json:"storage"`
}

var (
Expand Down
17 changes: 9 additions & 8 deletions pkg/scrape/stashdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func findStudio(studio string, field string) FindStudioResult {
// Define the variables needed for your query as a Go map
variables := `{"` + field + `": "` + studio + `"}`

resp := callStashDb(query, variables)
resp := CallStashDb(query, variables)
var data FindStudioResult
json.Unmarshal(resp, &data)
return data
Expand Down Expand Up @@ -191,7 +191,7 @@ func getPerformersPage(studioId string, page int) QueryPerformerResult {
}
`

resp := callStashDb(query, variables)
resp := CallStashDb(query, variables)
var data QueryPerformerResult
json.Unmarshal(resp, &data)
return data
Expand All @@ -214,7 +214,7 @@ func getScenes(studioId string, parentId string, tagId string) QueryScenesResult
} else {
variables = getStudioSceneQueryVariable(studioId, page, count)
}
sceneList = getScenePage(variables)
sceneList = GetScenePage(variables)
nextList = sceneList
for len(nextList.Data.QueryScenes.Scenes) > 0 &&
len(sceneList.Data.QueryScenes.Scenes) < sceneList.Data.QueryScenes.Count && // {
Expand All @@ -225,7 +225,7 @@ func getScenes(studioId string, parentId string, tagId string) QueryScenesResult
} else {
variables = getStudioSceneQueryVariable(studioId, page, count)
}
nextList = getScenePage(variables)
nextList = GetScenePage(variables)
sceneList.Data.QueryScenes.Scenes = append(sceneList.Data.QueryScenes.Scenes, nextList.Data.QueryScenes.Scenes...)
}
return sceneList
Expand Down Expand Up @@ -267,7 +267,7 @@ func getParentSceneQueryVariable(parentId string, tagId string, page int, count
}

// calls graphql scene query and return a list of scenes
func getScenePage(variables string) QueryScenesResult {
func GetScenePage(variables string) QueryScenesResult {
query := `
query queryScenes($input: SceneQueryInput!) {
queryScenes(input: $input) {
Expand Down Expand Up @@ -325,7 +325,7 @@ func getScenePage(variables string) QueryScenesResult {
`

// Define the variables needed for your query as a Go map
resp := callStashDb(query, variables)
resp := CallStashDb(query, variables)
var data QueryScenesResult
json.Unmarshal(resp, &data)
return data
Expand Down Expand Up @@ -492,14 +492,15 @@ func getStashPerformer(performer string) FindPerformerResult {
// Define the variables needed for your query as a Go map
var data FindPerformerResult
variables := `{"id": "` + performer + `"}`
resp := callStashDb(query, variables)
resp := CallStashDb(query, variables)
err := json.Unmarshal(resp, &data)
if err != nil {
log.Errorf("Eror extracting actor json")
}
return data
}
func callStashDb(query string, rawVariables string) []byte {

func CallStashDb(query string, rawVariables string) []byte {
var variables map[string]interface{}
json.Unmarshal([]byte(rawVariables), &variables)

Expand Down
46 changes: 46 additions & 0 deletions pkg/tasks/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import (
"github.com/sirupsen/logrus"
"github.com/thoas/go-funk"
"github.com/xbapps/xbvr/pkg/common"
"github.com/xbapps/xbvr/pkg/config"
"github.com/xbapps/xbvr/pkg/ffprobe"
"github.com/xbapps/xbvr/pkg/models"
"github.com/xbapps/xbvr/pkg/scrape"
)

var allowedVideoExt = []string{".mp4", ".avi", ".wmv", ".mpeg4", ".mov", ".mkv"}
Expand Down Expand Up @@ -84,6 +86,50 @@ func RescanVolumes(id int) {
files[i].SceneID = scenes[0].ID
files[i].Save()
scenes[0].UpdateStatus()
} else {
if config.Config.Storage.MatchOhash && config.Config.Advanced.StashApiKey != "" {
hash := files[i].OsHash
if len(hash) < 16 {
// the has in xbvr is sometiomes < 16 pad with zeros
paddingLength := 16 - len(hash)
hash = strings.Repeat("0", paddingLength) + hash
}
queryVariable := `
{"input":{
"fingerprints": {
"value": "` + hash + `",
"modifier": "INCLUDES"
},
"page": 1
}
}`
// call Stashdb graphql searching for os_hash
stashMatches := scrape.GetScenePage(queryVariable)
for _, match := range stashMatches.Data.QueryScenes.Scenes {
if match.ID != "" {
var externalRefLink models.ExternalReferenceLink
db.Where(&models.ExternalReferenceLink{ExternalSource: "stashdb scene", ExternalId: match.ID}).First(&externalRefLink)
if externalRefLink.ID != 0 {
files[i].SceneID = externalRefLink.InternalDbId
files[i].Save()
var scene models.Scene
scene.GetIfExistByPK(externalRefLink.InternalDbId)

// add filename tyo the array
var pfTxt []string
json.Unmarshal([]byte(scene.FilenamesArr), &pfTxt)
pfTxt = append(pfTxt, files[i].Filename)
tmp, _ := json.Marshal(pfTxt)
scene.FilenamesArr = string(tmp)
scene.Save()
models.AddAction(scene.SceneID, "match", "filenames_arr", scene.FilenamesArr)

scene.UpdateStatus()
log.Infof("File %s matched to Scene %s matched using stashdb hash %s", path.Base(files[i].Filename), scene.SceneID, hash)
}
}
}
}
}

if (i % 50) == 0 {
Expand Down
16 changes: 13 additions & 3 deletions ui/src/store/optionsStorage.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import ky from 'ky'

const state = {
items: []
items: [],
options: {
match_ohash: false,
},
}

const mutations = {
}

const actions = {
async load ({ state }, params) {
state.items = await ky.get('/api/options/storage').json()
}
await ky.get('/api/options/storage').json()
.then(data => {
state.items = data.volumes
state.options.match_ohash = data.match_ohash
})
},
async save ({ state }, enabled) {
ky.put('/api/options/storage', { json: { ...state.options } })
},
}

export default {
Expand Down
29 changes: 28 additions & 1 deletion ui/src/views/options/sections/Storage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,22 @@
</div>
</div>

<hr/>

<div>
<h3 class="title">{{ $t('Options') }}</h3>
<b-field>
<b-switch v-model="match_ohash" type="is-default">
Match StashDB Hashes
</b-switch>
</b-field>
<b-field>
<b-button type="is-primary" @click="save">Save options</b-button>
</b-field>


</div>

</div>

</template>
Expand Down Expand Up @@ -161,9 +177,20 @@ export default {
},
rescanFolder: function (folder) {
ky.get(`/api/task/rescan/${folder.id}`)
}
},
save () {
this.$store.dispatch('optionsStorage/save')
},
},
computed: {
match_ohash: {
get () {
return this.$store.state.optionsStorage.options.match_ohash
},
set (value) {
this.$store.state.optionsStorage.options.match_ohash = value
},
},
total () {
let files = 0; let unmatched = 0; let size = 0
this.$store.state.optionsStorage.items.map(v => {
Expand Down
Loading