Skip to content

Commit

Permalink
feat: scrape SLR passthrough information and provide it to DeoVR play…
Browse files Browse the repository at this point in the history
…er (xbapps#1308)

* SLR Passthrough

all or nothing for now... stupid icon on every vid in menu...

* Passthrough for DeoVR
  • Loading branch information
theRealKLH authored Jul 12, 2023
1 parent 5d4398e commit 2479b0f
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 11 deletions.
99 changes: 98 additions & 1 deletion pkg/api/deovr.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
restfulspec "github.com/emicklei/go-restful-openapi/v2"
"github.com/emicklei/go-restful/v3"
"github.com/markphelps/optional"
"github.com/tidwall/gjson"
"github.com/xbapps/xbvr/pkg/common"
"github.com/xbapps/xbvr/pkg/config"
"github.com/xbapps/xbvr/pkg/models"
Expand Down Expand Up @@ -113,6 +114,46 @@ type DeoSceneHSPFile struct {
URL string `json:"url"`
}

type DeoSceneChromaKey struct {
Enabled string `json:"enabled"`
HasAlpha string `json:"hasAlpha"`
H float64 `json:"h"`
Opacity float64 `json:"opacity"`
S float64 `json:"s"`
Threshold float64 `json:"threshold"`
V float64 `json:"v"`
}

type DeoScenePassthrough struct {
ID uint `json:"id"`
Title string `json:"title"`
Authorized uint `json:"authorized"`
Description string `json:"description"`
Date int64 `json:"date"`
Paysite DeoScenePaysite `json:"paysite"`
IsFavorite bool `json:"isFavorite"`
IsScripted bool `json:"isScripted"`
IsWatchlist bool `json:"isWatchlist"`
Is3D bool `json:"is3d"`
ThumbnailURL string `json:"thumbnailUrl"`
RatingAvg float64 `json:"rating_avg"`
ScreenType string `json:"screenType"`
StereoMode string `json:"stereoMode"`
VideoLength int `json:"videoLength"`
VideoThumbnail string `json:"videoThumbnail"`
VideoPreview string `json:"videoPreview,omitempty"`
Encodings []DeoSceneEncoding `json:"encodings"`
EncodingsSpatial []DeoSceneEncoding `json:"encodings_spatial"`
Timestamps []DeoSceneTimestamp `json:"timeStamps"`
Actors []DeoSceneActor `json:"actors"`
Categories []DeoSceneCategory `json:"categories,omitempty"`
Fleshlight []DeoSceneScriptFile `json:"fleshlight,omitempty"`
HSProfile []DeoSceneHSPFile `json:"hsp,omitempty"`
FullVideoReady bool `json:"fullVideoReady"`
FullAccess bool `json:"fullAccess"`
ChromaKey DeoSceneChromaKey `json:"chromakey"`
}

func isDeoAuthEnabled() bool {
if config.Config.Interfaces.DeoVR.AuthEnabled &&
config.Config.Interfaces.DeoVR.Username != "" &&
Expand Down Expand Up @@ -458,6 +499,30 @@ func (i DeoVRResource) getDeoScene(req *restful.Request, resp *restful.Response)
title := scene.Title
thumbnailURL := session.DeoRequestHost + "/img/700x/" + strings.Replace(scene.CoverURL, "://", ":/", -1)

//Passthrough
var ckdata map[string]interface{}
// nochromaKey := `{"enabled":false,"hasAlpha":false,"h":0,"opacity":0,"s":0,"threshold":0,"v":0}`
chromaKey := gjson.Parse(scene.ChromaKey)
_ = chromaKey
if gjson.Valid(scene.ChromaKey) {
if err := json.Unmarshal([]byte(scene.ChromaKey), &ckdata); err != nil {
fmt.Println("Error:", err)
}
result := gjson.Get(scene.ChromaKey, "hasAlpha")
if !result.Exists() || ckdata["hasAlpha"] == "" {
// if ckdata["."].(map[string]interface{})["hasAlpha"] = "false" || ckdata["."].(map[string]interface{})["hasAlpha"] = "" {

//setting hasAlpha to false
ckdata["hasAlpha"] = "false"
}
// Convert back to JSON string
ckup, err := json.Marshal(ckdata)
if err != nil {
fmt.Println("Error:", err)
}
chromaKey = gjson.ParseBytes(ckup)
}

if scene.IsScripted {
title = scene.GetFunscriptTitle()
if config.Config.Interfaces.DeoVR.RenderHeatmaps {
Expand Down Expand Up @@ -502,7 +567,39 @@ func (i DeoVRResource) getDeoScene(req *restful.Request, resp *restful.Response)
deoScene.VideoPreview = fmt.Sprintf("%v/api/dms/preview/%v", session.DeoRequestHost, scene.SceneID)
}

resp.WriteHeaderAndEntity(http.StatusOK, deoScene)
if gjson.Valid(scene.ChromaKey) {
deoPtScene := DeoScenePassthrough{
ID: scene.ID,
Authorized: 1,
Title: title,
Description: scene.Synopsis,
Date: finalDate,
Actors: actors,
Paysite: DeoScenePaysite{ID: 1, Name: scene.Site, Is3rdParty: true},
IsFavorite: scene.Favourite,
IsScripted: scene.IsScripted,
IsWatchlist: scene.Watchlist,
RatingAvg: scene.StarRating,
FullVideoReady: true,
FullAccess: true,
ThumbnailURL: thumbnailURL,
StereoMode: stereoMode,
Is3D: true,
ScreenType: screenType,
Encodings: sources,
EncodingsSpatial: sourcesSpatial,
VideoLength: int(videoLength),
Timestamps: cuepoints,
Categories: categories,
Fleshlight: deoScriptFiles,
HSProfile: deoHSPFiles,
ChromaKey: DeoSceneChromaKey{Enabled: chromaKey.Get("enabled").String(), HasAlpha: chromaKey.Get("hasAlpha").String(), H: chromaKey.Get("h").Float(), Opacity: chromaKey.Get("opacity").Float(), S: chromaKey.Get("s").Float(), Threshold: chromaKey.Get("threshold").Float(), V: chromaKey.Get("v").Float()},
VideoPreview: deoScene.VideoPreview,
}
resp.WriteHeaderAndEntity(http.StatusOK, deoPtScene)
} else {
resp.WriteHeaderAndEntity(http.StatusOK, deoScene)
}
}

func (i DeoVRResource) getDeoLibrary(req *restful.Request, resp *restful.Response) {
Expand Down
9 changes: 9 additions & 0 deletions pkg/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,15 @@ func Migrate() {
return nil
},
},
{
ID: "0065-scenes-add-chromakey-for-passthrough",
Migrate: func(tx *gorm.DB) error {
type Scene struct {
ChromaKey string `json:"chromakey" xbvrbackup:"chromakey"`
}
return tx.AutoMigrate(Scene{}).Error
},
},

// ===============================================================================================
// Put DB Schema migrations above this line and migrations that rely on the updated schema below
Expand Down
3 changes: 3 additions & 0 deletions pkg/models/model_scene.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ type Scene struct {
EditsApplied bool `json:"edits_applied" gorm:"default:false" xbvrbackup:"-"`
TrailerType string `json:"trailer_type" xbvrbackup:"trailer_type"`
TrailerSource string `gorm:"size:1000" json:"trailer_source" xbvrbackup:"trailer_source"`
ChromaKey string `json:"passthrough" xbvrbackup:"passthrough"`
Trailerlist bool `json:"trailerlist" gorm:"default:false" xbvrbackup:"trailerlist"`
IsSubscribed bool `json:"is_subscribed" gorm:"default:false"`
IsHidden bool `json:"is_hidden" gorm:"default:false" xbvrbackup:"is_hidden"`
Expand Down Expand Up @@ -431,6 +432,8 @@ func SceneCreateUpdateFromExternal(db *gorm.DB, ext ScrapedScene) error {
o.SceneURL = ext.HomepageURL
o.MemberURL = ext.MembersUrl

o.ChromaKey = ext.ChromaKey

// Trailers
o.TrailerType = ext.TrailerType
o.TrailerSource = ext.TrailerSrc
Expand Down
1 change: 1 addition & 0 deletions pkg/models/model_scraper.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type ScrapedScene struct {
MembersUrl string `json:"members_url"`
TrailerType string `json:"trailer_type"`
TrailerSrc string `json:"trailer_source"`
ChromaKey string `json:"chromakey"`

ActorDetails map[string]ActorDetails `json:"actor_details"`
}
Expand Down
48 changes: 38 additions & 10 deletions pkg/scrape/slrstudios.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"sync"

"github.com/go-resty/resty/v2"
"github.com/gocolly/colly/v2"
"github.com/thoas/go-funk"
"github.com/tidwall/gjson"
Expand Down Expand Up @@ -74,6 +75,7 @@ func SexLikeReal(wg *sync.WaitGroup, updateSite bool, knownScenes []string, out
// Could split by / but would run into issues with "f/f/m" and "shorts / skirts"
var videotype string
var FB360 string
alphA := "false"
e.ForEach(`ul.c-meta--scene-tags li a`, func(id int, e *colly.HTMLElement) {
if !skiptags[e.Attr("title")] {
sc.Tags = append(sc.Tags, e.Attr("title"))
Expand All @@ -87,6 +89,11 @@ func SexLikeReal(wg *sync.WaitGroup, updateSite bool, knownScenes []string, out
FB360 = "_FB360.MKV"
}

// Passthrough?
if e.Attr("title") == "Passthrough" || e.Attr("title") == "Passthrough hack" || e.Attr("title") == "Passthrough AR" {
alphA = "PT"
}

})

// Duration
Expand Down Expand Up @@ -158,8 +165,6 @@ func SexLikeReal(wg *sync.WaitGroup, updateSite bool, knownScenes []string, out
}
}

// Filenames
appendFilenames(&sc, siteID, filenameRegEx, videotype, FB360)
}

})
Expand All @@ -177,7 +182,7 @@ func SexLikeReal(wg *sync.WaitGroup, updateSite bool, knownScenes []string, out

// Filenames
// trans videos don't appear to follow video type naming conventions
appendFilenames(&sc, siteID, filenameRegEx, "", "")
// appendFilenames(&sc, siteID, filenameRegEx, "", "", alphA)
}
})

Expand All @@ -192,6 +197,21 @@ func SexLikeReal(wg *sync.WaitGroup, updateSite bool, knownScenes []string, out
})
}

// Passthrough "chromaKey":{"enabled":false,"hasAlpha":true,"h":0,"opacity":1,"s":0,"threshold":0,"v":0}
if alphA == "PT" {
s, _ := resty.New().R().
SetHeader("User-Agent", UserAgent).
Get(sc.TrailerSrc)
JsonMetadataA := s.String()
if gjson.Get(JsonMetadataA, "chromaKey").Exists() {
sc.ChromaKey = gjson.Get(JsonMetadataA, "chromaKey").String()
}
alphA = gjson.Get(JsonMetadataA, "chromaKey.hasAlpha").String()
}

// Filenames
appendFilenames(&sc, siteID, filenameRegEx, videotype, FB360, alphA)

// actor details
sc.ActorDetails = make(map[string]models.ActorDetails)
e.ForEach(`a[data-qa="scene-model-list-item-photo-link-to-profile"]`, func(id int, e_a *colly.HTMLElement) {
Expand Down Expand Up @@ -244,10 +264,10 @@ func SexLikeReal(wg *sync.WaitGroup, updateSite bool, knownScenes []string, out
return nil
}

func appendFilenames(sc *models.ScrapedScene, siteID string, filenameRegEx *regexp.Regexp, videotype string, FB360 string) {
func appendFilenames(sc *models.ScrapedScene, siteID string, filenameRegEx *regexp.Regexp, videotype string, FB360 string, AlphA string) {
// Only shown for logged in users so need to generate them
// Format: SLR_siteID_Title_<Resolutions>_SceneID_<LR/TB>_<180/360>.mp4
resolutions := []string{"_6400p_", "_4000p_", "_3840p_", "_3360p_", "_3160p_", "_3072p_", "_2900p_", "_2880p_", "_2700p_", "_2650p_", "_2160p_", "_1920p_", "_1440p_", "_1080p_", "_original_"}
resolutions := []string{"_6400p_", "_4096p_", "_4000p_", "_3840p_", "_3360p_", "_3160p_", "_3072p_", "_3000p_", "_2900p_", "_2880p_", "_2700p_", "_2650p_", "_2160p_", "_1920p_", "_1440p_", "_1080p_", "_original_"}
baseName := "SLR_" + strings.TrimSuffix(siteID, " (SLR)") + "_" + filenameRegEx.ReplaceAllString(sc.Title, "_")
switch videotype {
case "360°": // Sadly can't determine if TB or MONO so have to add both
Expand All @@ -257,11 +277,19 @@ func appendFilenames(sc *models.ScrapedScene, siteID string, filenameRegEx *rege
}
case "Fisheye": // 200° videos named with MKX200
for i := range resolutions {
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_MKX200.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_MKX220.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_RF52.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_FISHEYE190.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_VRCA220.mp4")
if AlphA == "true" {
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_MKX200_alpha.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_MKX220_alpha.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_RF52_alpha.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_FISHEYE190_alpha.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_VRCA220_alpha.mp4")
} else {
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_MKX200.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_MKX220.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_RF52.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_FISHEYE190.mp4")
sc.Filenames = append(sc.Filenames, baseName+resolutions[i]+sc.SiteID+"_VRCA220.mp4")
}
}
default: // Assuming everything else is 180 and LR, yet to find a TB_180
for i := range resolutions {
Expand Down

0 comments on commit 2479b0f

Please sign in to comment.