do auth check on view of video
This commit is contained in:
parent
9ad5e657d4
commit
64a4bb214c
|
@ -7,7 +7,6 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
B408F0D7251F6B760043E3A4 /* Tools.swift in Sources */ = {isa = PBXBuildFile; fileRef = B408F0D6251F6B760043E3A4 /* Tools.swift */; };
|
|
||||||
B408F0DD251F6D180043E3A4 /* AsyncImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B408F0DC251F6D180043E3A4 /* AsyncImage.swift */; };
|
B408F0DD251F6D180043E3A4 /* AsyncImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B408F0DC251F6D180043E3A4 /* AsyncImage.swift */; };
|
||||||
B408F0E5251F7AC50043E3A4 /* Just.swift in Sources */ = {isa = PBXBuildFile; fileRef = B408F0E4251F7AC50043E3A4 /* Just.swift */; };
|
B408F0E5251F7AC50043E3A4 /* Just.swift in Sources */ = {isa = PBXBuildFile; fileRef = B408F0E4251F7AC50043E3A4 /* Just.swift */; };
|
||||||
B408F0ED251F9D2C0043E3A4 /* loading.jpg in Resources */ = {isa = PBXBuildFile; fileRef = B408F0EC251F9D2C0043E3A4 /* loading.jpg */; };
|
B408F0ED251F9D2C0043E3A4 /* loading.jpg in Resources */ = {isa = PBXBuildFile; fileRef = B408F0EC251F9D2C0043E3A4 /* loading.jpg */; };
|
||||||
|
@ -39,7 +38,6 @@
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
B408F0D6251F6B760043E3A4 /* Tools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tools.swift; sourceTree = "<group>"; };
|
|
||||||
B408F0DC251F6D180043E3A4 /* AsyncImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncImage.swift; sourceTree = "<group>"; };
|
B408F0DC251F6D180043E3A4 /* AsyncImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncImage.swift; sourceTree = "<group>"; };
|
||||||
B408F0E4251F7AC50043E3A4 /* Just.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Just.swift; sourceTree = "<group>"; };
|
B408F0E4251F7AC50043E3A4 /* Just.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Just.swift; sourceTree = "<group>"; };
|
||||||
B408F0EC251F9D2C0043E3A4 /* loading.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = loading.jpg; sourceTree = "<group>"; };
|
B408F0EC251F9D2C0043E3A4 /* loading.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = loading.jpg; sourceTree = "<group>"; };
|
||||||
|
@ -125,7 +123,6 @@
|
||||||
B4F0CC80251BE62F00E9EA74 /* Preview Content */,
|
B4F0CC80251BE62F00E9EA74 /* Preview Content */,
|
||||||
B4F0CCA9251BFD6F00E9EA74 /* video.swift */,
|
B4F0CCA9251BFD6F00E9EA74 /* video.swift */,
|
||||||
B4F0CCB6251D6B5400E9EA74 /* VrtNuLayout.swift */,
|
B4F0CCB6251D6B5400E9EA74 /* VrtNuLayout.swift */,
|
||||||
B408F0D6251F6B760043E3A4 /* Tools.swift */,
|
|
||||||
);
|
);
|
||||||
path = vrtnu;
|
path = vrtnu;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -292,7 +289,6 @@
|
||||||
B4F0CC7B251BE62B00E9EA74 /* vrtnuApp.swift in Sources */,
|
B4F0CC7B251BE62B00E9EA74 /* vrtnuApp.swift in Sources */,
|
||||||
B4F0CCAA251BFD6F00E9EA74 /* video.swift in Sources */,
|
B4F0CCAA251BFD6F00E9EA74 /* video.swift in Sources */,
|
||||||
B408F0DD251F6D180043E3A4 /* AsyncImage.swift in Sources */,
|
B408F0DD251F6D180043E3A4 /* AsyncImage.swift in Sources */,
|
||||||
B408F0D7251F6B760043E3A4 /* Tools.swift in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,12 +15,7 @@ import TVUIKit
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let vrtNu = VRTNu()
|
VRTNuView(vrtNu: VRTNu())
|
||||||
if vrtNu.loggedIN() {
|
|
||||||
VRTNuView(vrtNu: vrtNu)
|
|
||||||
}else{
|
|
||||||
LoginView(vrtNu: vrtNu)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,12 +23,31 @@ struct LoginView: View{
|
||||||
var vrtNu: VRTNu
|
var vrtNu: VRTNu
|
||||||
@State private var password: String = ""
|
@State private var password: String = ""
|
||||||
@State private var username: String = ""
|
@State private var username: String = ""
|
||||||
|
@State var authenticationDidFail: Bool = false
|
||||||
|
// needed to update parent view when login was succesful
|
||||||
|
@Binding var loginaction: Bool
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
||||||
|
if authenticationDidFail {
|
||||||
|
Text("Information not correct. Try again.")
|
||||||
|
.offset(y: -10)
|
||||||
|
.foregroundColor(.red)
|
||||||
|
}
|
||||||
TextField("VRTNu username", text: $username)
|
TextField("VRTNu username", text: $username)
|
||||||
SecureField("VRTNu password", text: $password)
|
SecureField("VRTNu password", text: $password)
|
||||||
Button("Inloggen", action: {
|
Button("Inloggen", action: {
|
||||||
vrtNu.login(username: username, password: password)
|
|
||||||
|
let loginok = vrtNu.login(username: username, password: password)
|
||||||
|
if loginok{
|
||||||
|
// reload parent view here
|
||||||
|
withAnimation {
|
||||||
|
self.loginaction.toggle()
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
authenticationDidFail = true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,18 +128,21 @@ struct SeasonView: View {
|
||||||
|
|
||||||
struct VideoView: View {
|
struct VideoView: View {
|
||||||
var episode: Episode
|
var episode: Episode
|
||||||
|
@State var loginaction: Bool = false
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let url = episode.getVideo().hlsUrl
|
if episode.authenticated() || loginaction {
|
||||||
let player = AVPlayer(url: url);
|
let player = AVPlayer(url: episode.getVideo().hlsUrl);
|
||||||
VideoPlayer(player: player).fixedSize().onAppear(){
|
VideoPlayer(player: player).fixedSize().onAppear(){
|
||||||
player.play()
|
player.play()
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
LoginView(vrtNu: episode.season.show.vrtNu, loginaction: $loginaction)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContentView_Previews: PreviewProvider {
|
struct ContentView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
SeasonView(season: VRTNu().getShows()[0].getSeasons()[0])
|
SeasonView(season: VRTNu().getShows()[0].getSeasons()[0])
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
//
|
|
||||||
// Tools.swift
|
|
||||||
// vrtnu
|
|
||||||
//
|
|
||||||
// Created by Jens Timmerman on 26/09/2020.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
//
|
//
|
||||||
// VrtNuLayout.swift
|
// VrtNuLayout.swift
|
||||||
// vrtnu
|
// vrtnu website scrapping (not gui layout but website scrapping layout)
|
||||||
|
// The VRTNu object is built up as:
|
||||||
|
// VRTNu -> Shows -> Seasons -> Episodes
|
||||||
|
// An episode has a reference to it's season, a season has a reference to it's show and a show has a reference to the VRTNu main struct
|
||||||
|
// Most of this is implemented as lazy vars to only parse the webpages that the user realy wants
|
||||||
|
// We use a global just object so we just have one session and we can remain logged in over all our requests
|
||||||
//
|
//
|
||||||
// Created by Jens Timmerman on 25/09/2020.
|
// Created by Jens Timmerman on 25/09/2020.
|
||||||
//
|
//
|
||||||
|
@ -18,15 +23,57 @@ struct Episode: Hashable, Comparable{
|
||||||
let name: String
|
let name: String
|
||||||
let season: Season
|
let season: Season
|
||||||
let imageURL: URL
|
let imageURL: URL
|
||||||
|
let metadataurl: URL
|
||||||
|
|
||||||
|
func authenticated() -> Bool{
|
||||||
|
//check if current token is valid
|
||||||
|
let videojson = getVideoJson()
|
||||||
|
print(videojson)
|
||||||
|
if videojson.object(forKey: "code") != nil{
|
||||||
|
if videojson.value(forKey: "code") as! String == "AUTHENTICATION_REQUIRED"
|
||||||
|
{
|
||||||
|
print("not authenticated")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
print("maybe vrt authentication logic changed? please report this")
|
||||||
|
}
|
||||||
|
print("authenticated")
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
lazy var video: Video = {
|
lazy var video: Video = {
|
||||||
let token = self.season.show.vrtNu.getToken()
|
let videojson = getVideoJson()
|
||||||
//`requests.get('https://www.vrt.be/vrtnu/a-z/%s/%s/%s.mssecurevideo.json' % (show, season, episode)).json()`
|
print(videojson)
|
||||||
let url = "https://www.vrt.be/vrtnu/a-z/" + season.show.showName + "/" + season.seasonName + "/" + name + ".mssecurevideo.json"
|
|
||||||
print(url)
|
|
||||||
|
|
||||||
let msecjson = just.get(url).json!
|
let duration = videojson.value(forKey: "duration") as! Double
|
||||||
|
let title = videojson.value(forKey: "title") as! String
|
||||||
|
let targetURLs = videojson.value(forKey: "targetUrls") as! [NSDictionary]
|
||||||
|
let videourl = targetURLs[0].value(forKey: "url") as! String
|
||||||
|
print(videourl)
|
||||||
|
//session.get('https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/external/v1/videos/%s?vrtPlayerToken=%s&client=%s@PROD' %(video_id, token, clientid)).json()
|
||||||
|
var video = Video(hlsUrl: URL(string: videourl)!,
|
||||||
|
title: title,
|
||||||
|
duration: duration)
|
||||||
|
return video
|
||||||
|
}()
|
||||||
|
|
||||||
|
init(season: Season, episodeName: String, imageURL: URL){
|
||||||
|
self.name = episodeName
|
||||||
|
self.season = season
|
||||||
|
self.imageURL = imageURL
|
||||||
|
self.metadataurl = URL(string: "https://www.vrt.be/vrtnu/a-z/" + season.show.showName + "/" + season.seasonName + "/" + episodeName + ".mssecurevideo.json")!
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVideo() -> Video{
|
||||||
|
var lazyself = self
|
||||||
|
return lazyself.video
|
||||||
|
}
|
||||||
|
|
||||||
|
func getVideoJson() -> NSDictionary{
|
||||||
|
//`requests.get('https://www.vrt.be/vrtnu/a-z/%s/%s/%s.mssecurevideo.json' % (show, season, episode)).json()`
|
||||||
|
|
||||||
|
let msecjson = just.get(metadataurl).json!
|
||||||
let mssecdict = msecjson as! NSDictionary
|
let mssecdict = msecjson as! NSDictionary
|
||||||
print(msecjson)
|
print(msecjson)
|
||||||
let intmssecdict = mssecdict.allValues[0] as! NSDictionary
|
let intmssecdict = mssecdict.allValues[0] as! NSDictionary
|
||||||
|
@ -38,29 +85,8 @@ struct Episode: Hashable, Comparable{
|
||||||
mediaurl = mediaurl + self.season.show.vrtNu.getToken() + "&client="
|
mediaurl = mediaurl + self.season.show.vrtNu.getToken() + "&client="
|
||||||
mediaurl = mediaurl + clientid + "@PROD"
|
mediaurl = mediaurl + clientid + "@PROD"
|
||||||
print(mediaurl)
|
print(mediaurl)
|
||||||
let videojson = just.get(mediaurl).json!
|
let videojson = just.get(mediaurl).json! as! NSDictionary
|
||||||
print(videojson)
|
return videojson
|
||||||
let videodict = videojson as! NSDictionary
|
|
||||||
let duration = videodict.value(forKey: "duration") as! Double
|
|
||||||
let title = videodict.value(forKey: "title") as! String
|
|
||||||
let targetURLs = videodict.value(forKey: "targetUrls") as! [NSDictionary]
|
|
||||||
let videourl = targetURLs[0].value(forKey: "url") as! String
|
|
||||||
print(videourl)
|
|
||||||
//session.get('https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/external/v1/videos/%s?vrtPlayerToken=%s&client=%s@PROD' %(video_id, token, clientid)).json()
|
|
||||||
return Video(hlsUrl: URL(string: videourl)!,
|
|
||||||
title: title,
|
|
||||||
duration: duration)
|
|
||||||
}()
|
|
||||||
|
|
||||||
init(season: Season, episodeName: String, imageURL: URL){
|
|
||||||
self.name = episodeName
|
|
||||||
self.season = season
|
|
||||||
self.imageURL = imageURL
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVideo() -> Video{
|
|
||||||
var lazyself = self
|
|
||||||
return lazyself.video
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -197,7 +223,6 @@ extension NSTextCheckingResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VRTNu: Hashable {
|
struct VRTNu: Hashable {
|
||||||
lazy var loggedin: Bool = loggedIN()
|
|
||||||
|
|
||||||
lazy var shows: [Show] = {
|
lazy var shows: [Show] = {
|
||||||
let regexPattern = "a href=\"/vrtnu/a-z/(.*).relevant"
|
let regexPattern = "a href=\"/vrtnu/a-z/(.*).relevant"
|
||||||
|
@ -230,24 +255,8 @@ struct VRTNu: Hashable {
|
||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
func loggedIN() -> Bool{
|
|
||||||
|
|
||||||
//check if current token is valid
|
|
||||||
let testtoken = self.getToken()
|
|
||||||
let testurl = URL(string: "https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/external/v1/videos/pbs-pub-414bb095-6c5c-4c0e-b998-649fe03f07d7$vid-7ed5d7e0-e284-4df0-a76d-ff497e667d04?vrtPlayerToken=" + testtoken + "&client=vrtvideo@PROD")!
|
|
||||||
|
|
||||||
let videojson = just.get(testurl).json! as! NSDictionary
|
|
||||||
if videojson.object(forKey: "code") != nil{
|
|
||||||
if videojson.value(forKey: "code") as! String == "AUTHENTICATION_REQUIRED"
|
|
||||||
{
|
|
||||||
print("not authenticated")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
print("maybe vrt authentication logic changed? please report this")
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
|
|
||||||
}
|
|
||||||
func login(username: String, password:String) -> Bool {
|
func login(username: String, password:String) -> Bool {
|
||||||
let auth_data = [
|
let auth_data = [
|
||||||
"ApiKey": "3_0Z2HujMtiWq_pkAjgnS2Md2E11a1AwZjYiBETtwNE-EoEHDINgtnvcAOpNgmrVGy",
|
"ApiKey": "3_0Z2HujMtiWq_pkAjgnS2Md2E11a1AwZjYiBETtwNE-EoEHDINgtnvcAOpNgmrVGy",
|
||||||
|
@ -280,7 +289,8 @@ struct VRTNu: Hashable {
|
||||||
]
|
]
|
||||||
|
|
||||||
)
|
)
|
||||||
return loggedIN()
|
print("authenticated")
|
||||||
|
return true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,17 +30,3 @@ struct Video: Hashable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Video {
|
|
||||||
|
|
||||||
static func makeVideos() -> [Video] {
|
|
||||||
return [
|
|
||||||
Video(hlsUrl: URL(string: "https://remix-cf.lwc.vrtcdn.be/remix/ecd69313-4a39-4297-95b1-aede167725b7/remix.ism/.m3u8")!,
|
|
||||||
title: "best of dinges",
|
|
||||||
duration: 2946),
|
|
||||||
Video(hlsUrl: URL(string: "https://remix-cf.lwc.vrtcdn.be/remix/ecd69313-4a39-4297-95b1-aede167725b7/remix.ism/.m3u8")!,
|
|
||||||
title: "best of dinges 2",
|
|
||||||
duration: 2946),
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue