Last active
November 1, 2020 19:03
-
-
Save tangyl/e95d92a017813f5176404dab4c2238fa to your computer and use it in GitHub Desktop.
instaclip.user.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name InstaClip Poster | |
// @namespace http://tampermonkey.net/ | |
// @version 0.1 | |
// @description Create InstaClip post from current video page | |
// @author Yilong Tang yilongt@opera.com | |
// @match https://www.facebook.com/* | |
// @match https://www.instagram.com/* | |
// @match https://www.youtube.com/* | |
// @match http://road-to-champion-2018.op-mobile.opera.com/assets/view/instaclip.html | |
// @grant GM_registerMenuCommand | |
// @grant GM_xmlhttpRequest | |
// @grant GM_addStyle | |
// @grant GM_getValue | |
// @grant GM_setValue | |
// @grant GM_openInTab | |
// @grant GM_log | |
// @grant window.close | |
// @grant unsafeWindow | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
if (window.location.href == "http://road-to-champion-2018.op-mobile.opera.com/assets/view/instaclip.html"){ | |
unsafeWindow.__auth_callback__ = function(auth){ | |
GM_setValue("instaclip_auth", auth); | |
} | |
return; | |
} | |
GM_addStyle(` | |
.instaclip-modal { | |
display: none; /* Hidden by default */ | |
position: fixed; /* Stay in place */ | |
z-index: 10000; /* Sit on top */ | |
padding-top: 100px; /* Location of the box */ | |
left: 0; | |
top: 0; | |
width: 100%; /* Full width */ | |
height: 100%; /* Full height */ | |
overflow: auto; /* Enable scroll if needed */ | |
background-color: rgb(0,0,0); /* Fallback color */ | |
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */ | |
} | |
/* Modal Content */ | |
.instaclip-modal-content { | |
position: relative; | |
background-color: #fefefe; | |
margin: auto; | |
padding: 20px; | |
border: 1px solid #888; | |
width: 30%; | |
max-height: 80%; | |
overflow-y: auto; | |
font-size: 24px; | |
line-height: 28px; | |
} | |
.instaclip-user-bar{ | |
position: relative; | |
width: 100%; | |
height: 60px; | |
margin-top: 5px; | |
margin-bottom: 5px; | |
} | |
.instaclip-avatar { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 60px; | |
height: 60px; | |
} | |
.instaclip-user { | |
position: absolute; | |
top: 0; | |
left: 60px; | |
font-size: 28px; | |
line-height: 60px; | |
} | |
.instaclip-board { | |
margin-top: 5px; | |
margin-bottom: 5px; | |
} | |
.instaclip-modal-content h1 { | |
font-size: 36px; | |
line-height: 40px; | |
} | |
.instaclip-modal-content textarea { | |
margin: 4px; | |
resize: vertical; | |
width: 100%; | |
font-size: 18px; | |
box-sizing: border-box; | |
-webkit-box-sizing: border-box; | |
-moz-box-sizing: border-box; | |
} | |
.instaclip-modal-content select { | |
font-size: 18px; | |
} | |
.instaclip-thumb { | |
border: none; | |
border-radius: 8px; | |
} | |
.instaclip-btn { | |
padding: .5rem; | |
background: #86d1f0; | |
border: none; | |
border-radius: 4px; | |
margin: 4px; | |
font-size: 18px; | |
} | |
/* The Close Button */ | |
.instaclip-close { | |
position: absolute; | |
color: #aaaaaa; | |
font-size: 28px; | |
font-weight: bold; | |
right: 28px; | |
top: 28px; | |
} | |
.instaclip-close:hover, | |
.instaclip-close:focus { | |
color: #000; | |
text-decoration: none; | |
cursor: pointer; | |
} | |
.instaclip-progress-current { | |
padding: .5rem; | |
background: #86d1f0; | |
border: none; | |
border-radius: 4px; | |
box-sizing: border-box; | |
-webkit-box-sizing: border-box; | |
-moz-box-sizing: border-box; | |
font-size: 18px; | |
position: absolute; | |
top: 0; | |
left: 0; | |
height: 100%; | |
opacity: 0.4; | |
} | |
.instaclip-progress-bar { | |
position: relative; | |
background: #eee; | |
border: none; | |
text-align: center; | |
margin: 4px; | |
padding: 0; | |
width: 100%; | |
font-size: 18px; | |
height: 40px; | |
line-height: 40px; | |
} | |
`); | |
function uuidv4() { | |
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => | |
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) | |
) | |
} | |
var deviceID = GM_getValue("instaclip_device_id", uuidv4()); | |
GM_setValue("instaclip_device_id", deviceID); | |
var app = { | |
headers: null, | |
auth: null, | |
deviceID: null, | |
boards: null, | |
formID: "__instaclip_form__", | |
ensure_login: function(){ | |
var auth = GM_getValue("instaclip_auth", null); | |
if (auth == null){ | |
GM_openInTab("http://road-to-champion-2018.op-mobile.opera.com/assets/view/instaclip.html", { | |
active: true, | |
insert: true, | |
setParent: true | |
}); | |
return null; | |
} | |
else { | |
this.auth = auth; | |
this.headers = { | |
"User-ID": auth.id, | |
"Country": "KE", | |
"Language": "en", | |
"Version": "0.0.0", | |
"Device-Id": deviceID, | |
"Content-Type": "application/json" | |
} | |
return auth; | |
} | |
}, | |
list_boards: function(){ | |
var self = this; | |
return new Promise(function(resolve, reject){ | |
if (self.boards) { | |
resolve(self.boards); | |
} else { | |
var qid = uuidv4(); | |
GM_xmlhttpRequest({ | |
url: `http://clip-content-test.social.op-mobile.opera.com/v1/video/boards?qid=${qid}`, | |
headers: self.headers, | |
method: "GET", | |
onload: function(res) { | |
GM_log(res.responseText); | |
if (res.status == 200){ | |
var doc = JSON.parse(res.responseText); | |
self.boards = doc.content; | |
resolve(doc.content) | |
} else { | |
reject(res) | |
} | |
} | |
}); | |
} | |
}); | |
}, | |
create_modal_dialog: function(boards){ | |
var div = document.querySelector(`#${this.formId}`); | |
if (div == null) { | |
var newHTML = document.createElement ('div'); | |
var board_options = ''; | |
boards.forEach(b => { | |
board_options += `<option value="${b.id}">${b.name}</option>`; | |
}); | |
newHTML.id = this.formID; | |
newHTML.innerHTML = `<div id="__instaclip_modal__" class="instaclip-modal"> | |
<!-- Modal content --> | |
<div class="instaclip-modal-content"> | |
<span class="instaclip-close">×</span> | |
<h1> | |
Create InstaClip | |
</h1> | |
<div class="instaclip-user-bar"> | |
<img class="instaclip-avatar" src="${this.auth.avatar}"/><span class="instaclip-user">${this.auth.username}</span> | |
</div> | |
<div class="instaclip-board"> | |
Board | |
<select> | |
${board_options} | |
</select> | |
</div> | |
<div id="instaclip-content"> | |
Extracting Video Info... | |
</div> | |
</div> | |
</div>`; | |
document.body.append(newHTML); | |
document.querySelector(".instaclip-close").addEventListener("click", function(){ | |
document.querySelector(".instaclip-modal").style.display = "none"; | |
}, false); | |
} else { | |
GM_log("ok"); | |
} | |
}, | |
get_post_id: function(doc){ | |
var self = this; | |
return new Promise(function(resolve, reject){ | |
var qid = uuidv4(); | |
GM_xmlhttpRequest({ | |
url: `http://clip-content-test.social.op-mobile.opera.com/v1/video/activity/post/id?qid=${qid}`, | |
headers: self.headers, | |
method: "GET", | |
onload: function(res) { | |
GM_log(res.responseText); | |
if (res.status == 200) { | |
var data = JSON.parse(res.responseText); | |
GM_log("get_post_id"); | |
GM_log(doc); | |
resolve({post_id: data.content, doc:doc}); | |
} else { | |
GM_log(res); | |
reject(res); | |
} | |
} | |
}) | |
}) | |
}, | |
track_progress: function(post_id, callback){ | |
GM_log("show_progress"); | |
var self = this; | |
return new Promise(function(resolve, reject){ | |
function check_progress(){ | |
var qid = uuidv4(); | |
GM_xmlhttpRequest({ | |
url: `http://clip-content-test.social.op-mobile.opera.com/v1/video/activity/upload_progress?qid=${qid}`, | |
headers: self.headers, | |
method: "POST", | |
data: JSON.stringify({share_ids: [post_id]}), | |
onload: function(res) { | |
GM_log(res.responseText); | |
var doc = JSON.parse(res.responseText); | |
callback(doc.content); | |
if (doc.result.code == 0 && doc.content.progress[0].status == 1) { | |
resolve(doc.content); | |
} | |
else if (doc.result.code != 0){ | |
reject(doc); | |
} else { | |
setTimeout(check_progress, 1000); | |
} | |
} | |
}); | |
} | |
check_progress(); | |
}); | |
}, | |
show_progress: function(prog){ | |
var progress = prog.progress[0].downloaded_bytes*100/prog.progress[0].total_bytes; | |
var rest = 100 - progress; | |
var currSize = (prog.progress[0].downloaded_bytes/1024/1024).toPrecision(2); | |
var totalSize = (prog.progress[0].total_bytes/1024/1024).toPrecision(2); | |
document.querySelector("#instaclip-status").innerHTML = ` | |
<div class="instaclip-progress-bar" style="width:100%"> | |
<div class="instaclip-progress-current" style="width:${progress}%"></div> | |
${currSize}MB/${totalSize}MB | |
</div> | |
`; | |
}, | |
show_success: function(prog){ | |
document.querySelector("#instaclip-status").innerHTML = `<div class="instaclip-progress-bar" style="width:100%"> | |
<div class="instaclip-progress-current" style="width:100%"></div> | |
Success! | |
</div>`; | |
}, | |
create_post: function(attr){ | |
var post_id = attr.post_id; | |
var doc = attr.doc; | |
var boardSel = document.querySelector(".instaclip-modal-content select"); | |
var title = document.querySelector(".instaclip-modal-content textarea").value; | |
var board_id = boardSel.options[boardSel.selectedIndex].value; | |
GM_log(`select board ${board_id}`); | |
GM_log(doc); | |
var self = this; | |
return new Promise(function(resolve, reject){ | |
var qid = uuidv4(); | |
var desc = title; | |
GM_log(desc); | |
var body = JSON.stringify({ | |
"source_url": window.location.href, | |
"post_content": { | |
"post_id": post_id, | |
"description": desc, | |
"thumbnail": doc.video.thumbnail, | |
"board_id": board_id, | |
"source_url": doc.source_url, | |
"video_id": doc.video.id, | |
"width": doc.video.width, | |
"height": doc.video.height, | |
"duration": doc.video.duration, | |
"size": doc.video.size, | |
"format": doc.video.format, | |
"notify_user_list": [] | |
}}); | |
GM_log(body); | |
GM_xmlhttpRequest({ | |
url: `http://clip-content-test.social.op-mobile.opera.com/v1/video/activity/share_post?qid=${qid}`, | |
headers: self.headers, | |
method: "POST", | |
data: body, | |
onload: function(res) { | |
GM_log(res.responseText); | |
var doc = JSON.parse(res.responseText); | |
var post_id = doc.content; | |
resolve(post_id); | |
} | |
}); | |
}) | |
}, | |
show_video: function(doc){ | |
var contentDiv = document.querySelector("#instaclip-content"); | |
var title = (doc.content.title == "" ? doc.content.description : doc.content.title); | |
var thumbnail = doc.content.thumbnail.url; | |
contentDiv.innerHTML = ` | |
<b>Title</b> | |
<textarea rols="4">${title}</textarea> | |
<div id="instaclip-status"> | |
<input id="instaclip-btn" class="instaclip-btn" type="button" value="Create Post"/> | |
</div> | |
<div class="instaclip-thumb-div" style="width:100%"> | |
<img class="instaclip-thumb" src="${thumbnail}" style="width:100%" alt="thumbnail"/> | |
</div> | |
`; | |
document.querySelector("#instaclip-btn").addEventListener("click", function(){ | |
GM_log("create_post"); | |
GM_log(doc); | |
app.get_post_id(doc.content) | |
.then(function(doc){ | |
GM_log(doc); | |
return app.create_post(doc); | |
}, function(err){ | |
GM_log(`get_post_id failed ${err}`); | |
}) | |
.then(function(post_id){ | |
return app.track_progress(post_id, function(prog){ | |
app.show_progress(prog); | |
}); | |
}, function(err){ | |
GM_log(`get progress failed ${err}`); | |
}) | |
.then(function(prog){ | |
return app.show_success(prog); | |
}, function(err){ | |
GM_log(`track_progress failed ${err}`); | |
}); | |
}, false); | |
}, | |
show_extract_error: function(){ | |
var contentDiv = document.querySelector("#instaclip-content"); | |
contentDiv.innerHTML = "Sorry, can't extract video"; | |
}, | |
extract_video: function(){ | |
var self = this; | |
return new Promise(function(resolve, reject){ | |
document.querySelector("#instaclip-content").innerHTML = "Extracting Video ..."; | |
document.querySelector(".instaclip-modal").style.display = "block"; | |
var url = window.location.href; | |
var qid = uuidv4(); | |
GM_xmlhttpRequest({url: `http://clip-content-test.social.op-mobile.opera.com/v1/video/activity/share_url?qid=${qid}&operator_kind=share`, | |
method: "POST", | |
headers: self.headers, | |
data: JSON.stringify({"source_url": window.location.href}), | |
onload: function(res) { | |
GM_log(res.responseText); | |
var doc = JSON.parse(res.responseText); | |
if (doc.result.code == 0){ | |
resolve(doc); | |
} else { | |
reject(doc); | |
} | |
} | |
}); | |
}); | |
} | |
} | |
// Your code here... | |
GM_registerMenuCommand('InstaClip', function() { | |
console.log(app); | |
var auth = app.ensure_login(); | |
if (auth != null){ | |
app.list_boards() | |
.then(function(boards){ | |
app.create_modal_dialog(boards); | |
return app.extract_video(); | |
}, function(err){ | |
GM_log(`error list boards ${err}`); | |
}) | |
.then(function(doc){ | |
GM_log("show_video show doc"); | |
GM_log(doc); | |
app.show_video(doc); | |
}, function(err){ | |
app.show_extract_error(); | |
GM_log(`error extract_video ${err}`); | |
}); | |
} | |
}, 'i'); | |
GM_registerMenuCommand('InstaClip Logout', function() { | |
GM_setValue("instaclip_auth", null); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment