How to send/receive text message via nativeMessaging in Chrome? - javascript

I'm trying to send the url of the currently active tab to a python script. My extension already starts running the script and tries to send the url. However I have so far been unsuccessfull in receiving the url with the running script.
popup.js:
dlvideo.addEventListener("click", async () => {
chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => {
// Get current url
url = tabs[0].url;
// Connect to python script
port = chrome.runtime.connectNative('com.ytdlp.batdlvideo');
port.onDisconnect.addListener(function() {
console.log("Disconnected");
});
port.onMessage.addListener(function(msg) {
console.log("Received" + msg);
});
// Send url to script
port.postMessage({ text: url });
});
});
dlvideo.py (the code seems to get stuck here at the start of the while-loop):
import sys
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
url = None
while True:
# The loop seems to get stuck here:
text_length_bytes = sys.stdin.read(4)
if len(text_length_bytes) == 0:
print("test.py: sys.exit0")
sys.exit(0)
text_length = struct.unpack('i', text_length_bytes)[0]
text = sys.stdin.read(text_length).decode('utf-8')
if text.startswith('http'):
url = text
print(str(url))
break
else:
print(text)
Other files are probably not relevant, but I'll put them here just in case:
yt_dlp.bat:
#echo off
start cmd /k python "%~dp0/dlvideo.py" %*
manifestAPP.json:
{
"name": "com.ytdlp.batdlvideo",
"description": "Youtube-dlp",
"path": "C:\\Users\\.....\\native-apps\\dlvideo\\yt_dlp.bat",
"type": "stdio",
"allowed_origins": [
"chrome-extension://-extensionid-/"
]
}
Can someone help?

Ok, I think in my case the problem was that only one message is sent to the host and the host is not yet ready by the time it is sent?
Well, this at least is the code that worked for me:
popup.js and manifestAPP.json can stay the same.
dlvideo.py:
import struct
import json
import sys
import os
# Changes the stdio-mode
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
# Read native message from chrome window
text_message_length = sys.stdin.buffer.read(4)
text_length = struct.unpack("i", text_message_length)[0]
text_decoded = sys.stdin.buffer.read(text_length).decode("utf-8")
text_asstr = json.loads(text_decoded)
# Get URL
url = text_asstr['text']
yt_dlp.bat:
#echo off
python dlvideo.py %*

Related

Is there a way to jump back and forth from python and JS?

I'm trying to create a chrome extension which are made in JS, however I built the main part of the code in python because it is the language I know, and I'm not sure if what I'm trying to do is even possible in JS. Is there a way to take in a variable I get from JS, use it to run a python function, and then continue with the JS code?
chrome.browserAction.onClicked.addListener(function(activeTab){
chrome.tabs.getSelected(null, function(tab) {
var tabId = tab.id;
tabUrl = tab.url;
id = tabUrl.split("=")[1];
//call python func here
});
var newURL = "frame.html";
chrome.tabs.create({ url: newURL});
});
from youtube_transcript_api import YouTubeTranscriptApi
import webbrowser
def func(id):
html_file = open('frame.html','w')
list = YouTubeTranscriptApi.get_transcript(id)
webbrowser.get('C:/Program Files/Google/Chrome/Application/chrome.exe %s')
data = '<html>\n<head>\n<link rel="stylesheet" href="styles.css">\n</head>\n<body>\n<p>\n'
for i in list:
data += i.get('text') + ' '
data += '</p>\n</body>\n</html>'
html_file.write(data)
html_file.close()
#func(id from java)

Pass params like variable to evaluate in casperjs and login into site

I'm writing a python script that pass username and password like params to my casperjs script, describe below. But I don't know why a receive the error:
CasperError: casper.test property is only available using the `casperjs test` command
C:/casperjs/modules/casper.js:179
Can someone help me about this issue?
CasperJS.py:
import os
import subprocess
# PATH to files
casperjs = 'c:\casperjs\bin\casperjs.exe'
app_root = os.path.dirname(os.path.realpath(__file__))
script = os.path.join(app_root, 'test2.js')
# Request username and password
username = raw_input("Usuario:")
password = raw_input("Senha:")
# Username and password like
auth = [username, password]
# Execute process casperjs via python
subprocess.Popen(['casperjs', script, auth[0], auth[1]], shell=True)
CasperJS.js:
var casper = require('casper').create({
clientScript: ['jquery.min.js'],
verbose: true,
logLevel: "debug",
// Disable load images
pageSettings: {
loadImages: true
}
});
# variables
var url = 'http://minha.oi.com.br';
var username = casper.echo(casper.cli.raw.get(0));
var password = casper.echo(casper.cli.raw.get(1));
# start casperjs
casper.start(url);
# Try login on the website
casper.thenEvaluate(function(usuario, senha) {
document.querySelector('input#Ecom_User_ID').setAttribute('value', usuario);
document.querySelector('input#Ecom_Password').setAttribute('value', password);
}, { usuario: username, senha: password });
# Check the current URL
casper.then(function() {
this.echo(this.getCurrentUrl());
});
casper.run();
The issue was an old version of phantomjs that did not work properly with casperjs. The issues below provide corrections to the code in the question.
Your scripts have multiple issues
You can't echo something and try to assign the value in your casperjs script. So change those two lines to:
casper.echo(casper.cli.raw.get(0));
casper.echo(casper.cli.raw.get(1));
var username = casper.cli.raw.get(0);
var password = casper.cli.raw.get(1);
In the same script: Your comments are python comments and not js comments, so change # to //
In casper: You should actually select the correct input fields:
document.querySelector('input[name="Ecom_User_ID"]').setAttribute('value', usuario);
document.querySelector('input[name="Ecom_Password"]').setAttribute('value', senha);
Or even use a function that is provided by casperjs (replacing the complete thenEvaluate call):
this.fillSelectors("form[name='IDPLogin']", {
'input[name="Ecom_User_ID"]': username,
'input[name="Ecom_Password"]': password
});
you may change the thenEvaluate call to:
casper.thenEvaluate(function(usuario, senha) {
// setAttribute here like above
}, username, password);
In your python script you don't actually use the casperjs variable, but that's fine since you assume that it is in PATH.
If the error persists or a new one comes up, try updating to a newer version of phantomjs.
The resulting code might look like this:
var casper = require('casper').create();
// variables
var url = 'http://minha.oi.com.br';
var username = casper.cli.raw.get(0);
var password = casper.cli.raw.get(1);
// start casperjs
casper.start(url);
// Try login on the website
casper.then(function(){
this.fillSelectors("form[name='IDPLogin']", {
'input[name="Ecom_User_ID"]': username,
'input[name="Ecom_Password"]': password
}, true);
// this also sents the form
});
// Check the current URL
casper.then(function() {
this.echo(this.getCurrentUrl());
});
casper.run();

SkyDrive API Displaying a file

I'm working with Skydrive APIs, and I would like my user tobe able to open a view about a file where you can edit it (the same view as we can have about a file when you're on the skydrive web page).
There may be a WL function for it but I can't find it. An other solution would be for me to get the URL of the view page and open it in a new window with javascript.
I have implemented this solution using SkyDrive and its API. You can try this script out within Microsoft's Interactive Live SDK online tool as well. The key is to obtain SkyDrive's redirect link for the file you are looking to open. This redirect link is returned for each file in the Get api's json result.
Processing Steps:
Initializes Windows Live jscript api client
Authenticate with Windows Live (skydrive) OAuth
GetFiles: Get a list of all files within your SkyDrive account. This could be adjusted for your needs and focused to just get a list for a specific folder with your SkyDrive account
onFilesComplete: iterate through json response looking for an item with a type='file' and file name you are looking to open. In this, case a file name 'robots.txt'
display details about the found file
using the found file's "link" attribute, open url in a new window browser window. This will open the file using SkyDrive default action. For known file types such as code files, this will open them in SkyDrive's online file editor. Otherwise, the default action will be to download the found file
Example Code:
WL.init({ client_id: clientId, redirect_uri: redirectUri });
WL.login({ "scope": "wl.skydrive" }).then(
function(response) {
getFiles();
},
function(response) {
log("Could not connect, status = " + response.status);
}
);
function getFiles() {
var files_path = "/me/skydrive/files";
WL.api({ path: files_path, method: "GET" }).then(
onGetFilesComplete,
function(response) {
log("Cannot get files and folders: " +
JSON.stringify(response.error).replace(/,/g, ",\n"));
}
);
}
function onGetFilesComplete(response) {
var items = response.data;
var foundFolder = 0;
for (var i = 0; i < items.length; i++) {
if (items[i].type === "file" &&
items[i].name === "robots.txt") {
log("Found a file with the following information: " +
JSON.stringify(items[i]).replace(/,/g, ",\n"));
foundFolder = 1;
//open file in a new browser window
window.open(items[i].link);
break;
}
}
if (foundFolder == 0) {
log("Unable to find any file(s)");
}
}
function log(message) {
var child = document.createTextNode(message);
var parent = document.getElementById('JsOutputDiv') || document.body;
parent.appendChild(child);
parent.appendChild(document.createElement("br"));
}

Why does my javascript WebSocket just die? python server

trying to make a simple text chat socket server. I am very new to coding servers. I have this working code but the problem is that the WebSocket() dies silently on me:
the output in the javascript console is
open
closed
There is very little resources to help me understand this behaviour. Why does my python server kill the connection once the header is sent? Am i sending the response in the correct way? Any help at all would be amazing.
Python code:
import socketserver
import re
from base64 import b64encode
from hashlib import sha1
inited = 0
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
global inited
if(inited==0):
print(self)
text = self.request.recv(1024).strip()
self.upgradeConnection(text)
self.request.send("a sweet message from the server!".encode("utf-8"));
inited = 1
else:
self.request.sendall("second response!".encode("utf-8"));
def upgradeConnection(self,text):
#print("Client wants to upgrade:")
#print(text);
websocket_answer = (
'HTTP/1.1 101 Switching Protocols',
'Upgrade: websocket',
'Connection: Upgrade',
'Sec-WebSocket-Accept: {key}\r\n\r\n',
)
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
#print(re.search(b'Sec-WebSocket-Key:\s+(.*?)[\n\r]+', text))
key = (re.search(b'Sec-WebSocket-Key:\s+(.*?)[\n\r]+', text)
.groups()[0]
.strip())
#print(key.decode("utf-8"))
#print(key.decode("utf-8") + GUID)
#print(sha1((key.decode("utf-8") + GUID).encode("utf-8")))
response_key = b64encode(sha1((key.decode("utf-8") + GUID).encode("utf-8")).digest()).decode("utf-8")
#print(response_key)
response = '\r\n'.join(websocket_answer).format(key=response_key)
self.request.send(response.encode("utf-8"));
HOST, PORT = "localhost", 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
Webpage code:
url = "ws://127.0.0.1:9999/";
var sk = new WebSocket(url);
sk.onopen = function(e){
console.log("open");
sk.send("the client is here!!");
}
sk.onmessage = function(e){
console.log("message");
console.log(e.data);
}
sk.onerror = function(e){
console.log("error");
}
sk.onclose = function(e){
console.log("closed");
}

Delay in websocket communication using Autobahn Python and Google Chrome

Here is what I am working with:
webserver.py:
import sys
from twisted.internet import reactor
from twisted.python import log
from autobahn.websocket import WebSocketServerFactory, \
WebSocketServerProtocol, \
listenWS
class EchoServerProtocol(WebSocketServerProtocol):
def onMessage(self, msg, binary):
print "sending echo:", msg
self.sendMessage(msg, binary)
if __name__ == '__main__':
log.startLogging(sys.stdout)
factory = WebSocketServerFactory("ws://localhost:9000", debug = False)
factory.protocol = EchoServerProtocol
listenWS(factory)
reactor.run()
background.js:
function updateCookies(info) {
send();
console.log(info.cookie.domain);
}
function send() {
msg = "TEST";
sock.send(msg);
};
var sock = null;
sock = new WebSocket("ws://localhost:9000");
console.log("Websocket created...");
sock.onopen = function() {
console.log("connected to server");
sock.send("CONNECTED TO YOU");
}
sock.onclose = function(e) {
console.log("connection closed (" + e.code + ")");
}
sock.onmessage = function(e) {
console.log("message received: " + e.data);
}
chrome.cookies.onChanged.addListener(updateCookies);
Now, upon running webserver.py and running background.js, nothing happens. The client see's no echo and the server doesn't report any connections or messages. However, if I reload background.js, all the sudden the previous message of "CONNECTED TO YOU" is shown by the server. Reloading again produces the same effect, showing the delayed "CONNECTED TO YOU" message. I've tried running sock.close() after sending the message, but that still produces nothing. I'm really confused at what is causing this random delay. Leaving the server running for 10 - 15 minutes also produces nothing, I must manually refresh the page before I see any messages. Any idea what might be causing this?

Categories