mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 16:02:00 +02:00
Move all file operations code to single file
This commit is contained in:
27
src/dash.js
27
src/dash.js
@@ -1,4 +1,3 @@
|
|||||||
const { Gio, GLib } = imports.gi;
|
|
||||||
const Debug = imports.src.debug;
|
const Debug = imports.src.debug;
|
||||||
const FileOps = imports.src.fileOps;
|
const FileOps = imports.src.fileOps;
|
||||||
const Misc = imports.src.misc;
|
const Misc = imports.src.misc;
|
||||||
@@ -50,32 +49,6 @@ function generateDash(info)
|
|||||||
return dash;
|
return dash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveDashPromise(dash)
|
|
||||||
{
|
|
||||||
debug('saving dash file');
|
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
const tempDir = await FileOps.createTempDirPromise().catch(debug);
|
|
||||||
if(!tempDir)
|
|
||||||
return reject(new Error('could not create folder in temp directory'));
|
|
||||||
|
|
||||||
const dashFile = tempDir.get_child('.clapper.mpd');
|
|
||||||
|
|
||||||
dashFile.replace_contents_bytes_async(
|
|
||||||
GLib.Bytes.new_take(dash),
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
Gio.FileCreateFlags.NONE,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
debug('saved dash file');
|
|
||||||
resolve(dashFile.get_uri());
|
|
||||||
})
|
|
||||||
.catch(err => reject(err));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function _addAdaptationSet(streamsArr)
|
function _addAdaptationSet(streamsArr)
|
||||||
{
|
{
|
||||||
const mimeInfo = _getMimeInfo(streamsArr[0].mimeType);
|
const mimeInfo = _getMimeInfo(streamsArr[0].mimeType);
|
||||||
|
@@ -4,7 +4,9 @@ const Misc = imports.src.misc;
|
|||||||
|
|
||||||
const { debug } = Debug;
|
const { debug } = Debug;
|
||||||
|
|
||||||
|
Gio._promisify(Gio._LocalFilePrototype, 'load_bytes_async', 'load_bytes_finish');
|
||||||
Gio._promisify(Gio._LocalFilePrototype, 'make_directory_async', 'make_directory_finish');
|
Gio._promisify(Gio._LocalFilePrototype, 'make_directory_async', 'make_directory_finish');
|
||||||
|
Gio._promisify(Gio._LocalFilePrototype, 'replace_contents_bytes_async', 'replace_contents_finish');
|
||||||
|
|
||||||
function createCacheDirPromise()
|
function createCacheDirPromise()
|
||||||
{
|
{
|
||||||
@@ -24,6 +26,7 @@ function createTempDirPromise()
|
|||||||
return createDirPromise(dir);
|
return createDirPromise(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Creates dir and resolves with it */
|
||||||
function createDirPromise(dir)
|
function createDirPromise(dir)
|
||||||
{
|
{
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -32,7 +35,7 @@ function createDirPromise(dir)
|
|||||||
|
|
||||||
dir.make_directory_async(
|
dir.make_directory_async(
|
||||||
GLib.PRIORITY_DEFAULT,
|
GLib.PRIORITY_DEFAULT,
|
||||||
null,
|
null
|
||||||
)
|
)
|
||||||
.then(success => {
|
.then(success => {
|
||||||
if(success)
|
if(success)
|
||||||
@@ -43,3 +46,76 @@ function createDirPromise(dir)
|
|||||||
.catch(err => reject(err));
|
.catch(err => reject(err));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Saves file in optional subdirectory and resolves with it */
|
||||||
|
function saveFilePromise(place, subdirName, fileName, data)
|
||||||
|
{
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
let destPath = GLib[`get_${place}_dir`]() + '/' + Misc.appId;
|
||||||
|
|
||||||
|
if(subdirName)
|
||||||
|
destPath += `/${subdirName}`;
|
||||||
|
|
||||||
|
const destDir = Gio.File.new_for_path(destPath);
|
||||||
|
debug(`saving file: ${destPath}`);
|
||||||
|
|
||||||
|
const checkFolders = (subdirName)
|
||||||
|
? [destDir.get_parent(), destDir]
|
||||||
|
: [destDir];
|
||||||
|
|
||||||
|
for(let dir of checkFolders) {
|
||||||
|
const createdDir = await createDirPromise(dir).catch(debug);
|
||||||
|
if(!createdDir)
|
||||||
|
return reject(new Error(`could not create dir: ${dir.get_path()}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
const destFile = destDir.get_child(fileName);
|
||||||
|
destFile.replace_contents_bytes_async(
|
||||||
|
GLib.Bytes.new_take(data),
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
Gio.FileCreateFlags.NONE,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
debug(`saved file: ${destPath}`);
|
||||||
|
resolve(destFile);
|
||||||
|
})
|
||||||
|
.catch(err => reject(err));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFileContentsPromise(place, folderName, fileName)
|
||||||
|
{
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const destPath = [
|
||||||
|
GLib[`get_${place}_dir`](),
|
||||||
|
Misc.appId,
|
||||||
|
folderName,
|
||||||
|
fileName
|
||||||
|
].join('/');
|
||||||
|
|
||||||
|
const file = Gio.File.new_for_path(destPath);
|
||||||
|
debug(`reading data from: ${destPath}`);
|
||||||
|
|
||||||
|
if(!file.query_exists(null)) {
|
||||||
|
debug(`no such file: ${file.get_path()}`);
|
||||||
|
return resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.load_bytes_async(null)
|
||||||
|
.then(result => {
|
||||||
|
const data = result[0].get_data();
|
||||||
|
if(!data || !data.length)
|
||||||
|
return reject(new Error('source file is empty'));
|
||||||
|
|
||||||
|
debug(`read data from: ${destPath}`);
|
||||||
|
|
||||||
|
if(data instanceof Uint8Array)
|
||||||
|
resolve(ByteArray.toString(data));
|
||||||
|
else
|
||||||
|
resolve(data);
|
||||||
|
})
|
||||||
|
.catch(err => reject(err));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@@ -1,11 +1,8 @@
|
|||||||
imports.gi.versions.Gdk = '4.0';
|
imports.gi.versions.Gdk = '4.0';
|
||||||
imports.gi.versions.Gtk = '4.0';
|
imports.gi.versions.Gtk = '4.0';
|
||||||
|
|
||||||
const { Gio, Gst } = imports.gi;
|
const { Gst } = imports.gi;
|
||||||
|
|
||||||
Gst.init(null);
|
Gst.init(null);
|
||||||
Gio._promisify(Gio._LocalFilePrototype, 'load_bytes_async', 'load_bytes_finish');
|
|
||||||
Gio._promisify(Gio._LocalFilePrototype, 'replace_contents_bytes_async', 'replace_contents_finish');
|
|
||||||
|
|
||||||
const { App } = imports.src.app;
|
const { App } = imports.src.app;
|
||||||
|
|
||||||
|
@@ -2,6 +2,7 @@ const { Gdk, Gio, GObject, Gst, GstClapper, Gtk } = imports.gi;
|
|||||||
const ByteArray = imports.byteArray;
|
const ByteArray = imports.byteArray;
|
||||||
const Dash = imports.src.dash;
|
const Dash = imports.src.dash;
|
||||||
const Debug = imports.src.debug;
|
const Debug = imports.src.debug;
|
||||||
|
const FileOps = imports.src.fileOps;
|
||||||
const Misc = imports.src.misc;
|
const Misc = imports.src.misc;
|
||||||
const YouTube = imports.src.youtube;
|
const YouTube = imports.src.youtube;
|
||||||
const { PlayerBase } = imports.src.playerBase;
|
const { PlayerBase } = imports.src.playerBase;
|
||||||
@@ -88,9 +89,19 @@ class ClapperPlayer extends PlayerBase
|
|||||||
throw new Error('no YouTube video info');
|
throw new Error('no YouTube video info');
|
||||||
|
|
||||||
const dash = Dash.generateDash(info);
|
const dash = Dash.generateDash(info);
|
||||||
const videoUri = (dash)
|
let videoUri = null;
|
||||||
? await Dash.saveDashPromise(dash).catch(debug)
|
|
||||||
: this.ytClient.getBestCombinedUri(info);
|
if(dash) {
|
||||||
|
const dashFile = await FileOps.saveFilePromise(
|
||||||
|
'tmp', null, 'clapper.mpd', dash
|
||||||
|
).catch(debug);
|
||||||
|
|
||||||
|
if(dashFile)
|
||||||
|
videoUri = dashFile.get_uri();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!videoUri)
|
||||||
|
videoUri = this.ytClient.getBestCombinedUri(info);
|
||||||
|
|
||||||
if(!videoUri)
|
if(!videoUri)
|
||||||
throw new Error('no YouTube video URI');
|
throw new Error('no YouTube video URI');
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
const { Gio, GLib, GObject, Gst, Soup } = imports.gi;
|
const { GObject, Gst, Soup } = imports.gi;
|
||||||
const ByteArray = imports.byteArray;
|
const ByteArray = imports.byteArray;
|
||||||
const Debug = imports.src.debug;
|
const Debug = imports.src.debug;
|
||||||
const FileOps = imports.src.fileOps;
|
const FileOps = imports.src.fileOps;
|
||||||
@@ -96,7 +96,7 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
let isFoundInTemp = false;
|
let isFoundInTemp = false;
|
||||||
let isUsingPlayerResp = false;
|
let isUsingPlayerResp = false;
|
||||||
|
|
||||||
const tempInfo = await this._getFileContentsPromise('tmp', 'yt-info', videoId).catch(debug);
|
const tempInfo = await FileOps.getFileContentsPromise('tmp', 'yt-info', videoId).catch(debug);
|
||||||
if(tempInfo) {
|
if(tempInfo) {
|
||||||
debug('checking temp info for requested video');
|
debug('checking temp info for requested video');
|
||||||
let parsedTempInfo;
|
let parsedTempInfo;
|
||||||
@@ -191,7 +191,7 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
debug(`found player URI: ${ytUri}`);
|
debug(`found player URI: ${ytUri}`);
|
||||||
|
|
||||||
const ytId = ytPath.split('/').find(el => Misc.isHex(el));
|
const ytId = ytPath.split('/').find(el => Misc.isHex(el));
|
||||||
let ytSigData = await this._getFileContentsPromise('user_cache', 'yt-sig', ytId).catch(debug);
|
let ytSigData = await FileOps.getFileContentsPromise('user_cache', 'yt-sig', ytId).catch(debug);
|
||||||
if(ytSigData) {
|
if(ytSigData) {
|
||||||
ytSigData = ytSigData.split(';');
|
ytSigData = ytSigData.split(';');
|
||||||
|
|
||||||
@@ -229,7 +229,8 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
if(actions) {
|
if(actions) {
|
||||||
debug('deciphered, saving cipher actions to cache file');
|
debug('deciphered, saving cipher actions to cache file');
|
||||||
const saveData = sts + ';' + actions;
|
const saveData = sts + ';' + actions;
|
||||||
this._createSubdirFileAsync('user_cache', 'yt-sig', ytId, saveData);
|
/* We do not need to wait for it */
|
||||||
|
FileOps.saveFilePromise('user_cache', 'yt-sig', ytId, saveData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!actions || !actions.length) {
|
if(!actions || !actions.length) {
|
||||||
@@ -275,7 +276,8 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
/* Estimated safe time for rewatching video */
|
/* Estimated safe time for rewatching video */
|
||||||
info.streamingData.expireDate = dateSeconds + Number(exp);
|
info.streamingData.expireDate = dateSeconds + Number(exp);
|
||||||
|
|
||||||
this._createSubdirFileAsync(
|
/* Last info is stored in variable, so don't wait here */
|
||||||
|
FileOps.saveFilePromise(
|
||||||
'tmp', 'yt-info', videoId, JSON.stringify(info)
|
'tmp', 'yt-info', videoId, JSON.stringify(info)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -643,69 +645,6 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
return `${url}&${sig}=${encodeURIComponent(key)}`;
|
return `${url}&${sig}=${encodeURIComponent(key)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _createSubdirFileAsync(place, folderName, fileName, data)
|
|
||||||
{
|
|
||||||
const destPath = [
|
|
||||||
GLib[`get_${place}_dir`](),
|
|
||||||
Misc.appId,
|
|
||||||
folderName
|
|
||||||
].join('/');
|
|
||||||
|
|
||||||
const destDir = Gio.File.new_for_path(destPath);
|
|
||||||
debug(`saving file: ${destPath}`);
|
|
||||||
|
|
||||||
for(let dir of [destDir.get_parent(), destDir]) {
|
|
||||||
const createdDir = await FileOps.createDirPromise(dir).catch(debug);
|
|
||||||
if(!createdDir) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const destFile = destDir.get_child(fileName);
|
|
||||||
destFile.replace_contents_bytes_async(
|
|
||||||
GLib.Bytes.new_take(data),
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
Gio.FileCreateFlags.NONE,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
.then(() => debug(`saved file: ${destPath}`))
|
|
||||||
.catch(debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getFileContentsPromise(place, folderName, fileName)
|
|
||||||
{
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const destPath = [
|
|
||||||
GLib[`get_${place}_dir`](),
|
|
||||||
Misc.appId,
|
|
||||||
folderName,
|
|
||||||
fileName
|
|
||||||
].join('/');
|
|
||||||
|
|
||||||
const file = Gio.File.new_for_path(destPath);
|
|
||||||
debug(`reading data from: ${destPath}`);
|
|
||||||
|
|
||||||
if(!file.query_exists(null)) {
|
|
||||||
debug(`no such file: ${file.get_path()}`);
|
|
||||||
return resolve(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
file.load_bytes_async(null)
|
|
||||||
.then(result => {
|
|
||||||
const data = result[0].get_data();
|
|
||||||
if(!data || !data.length)
|
|
||||||
return reject(new Error('source file is empty'));
|
|
||||||
|
|
||||||
debug(`read data from: ${destPath}`);
|
|
||||||
|
|
||||||
if(data instanceof Uint8Array)
|
|
||||||
resolve(ByteArray.toString(data));
|
|
||||||
else
|
|
||||||
resolve(data);
|
|
||||||
})
|
|
||||||
.catch(err => reject(err));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_getPlayerPostData(videoId)
|
_getPlayerPostData(videoId)
|
||||||
{
|
{
|
||||||
const cliVer = this.postInfo.clientVersion;
|
const cliVer = this.postInfo.clientVersion;
|
||||||
|
Reference in New Issue
Block a user