DrKain / scrape-youtube

A lightning fast package to scrape YouTube search results
MIT License
112 stars 30 forks source link

TypeError: The "listener" argument must be of type Function. Received type object #59

Closed matteomontipo closed 2 years ago

matteomontipo commented 2 years ago

Getting error TypeError: The "listener" argument must be of type Function. Received type object

Any idea why?

Code is in react with a contentEditable div checking for keyboard esacpe command this way:

console.log(term) // correct value typed inside the contentEditable field

const checkReturns = (event) => {
        if(event.key === 'Enter'){

            const options = {
                requestOptions: {
                    headers: {
                        Cookie: 'PREF=f2=8000000'
                    }
                }
            };

            youtube.search(term, options).then(results => {   // this throws the error at .search
                console.log(results.videos)
            });
        }
    }

The react return is as follow:

return (
        <div id="namebox" className="areatext list-group">
            <div
                ref={ref}
                id="first_line"
                contentEditable="true"
                style={{ minHeight: '26px' }}
                onInput={(e) => setTerm(e.currentTarget.textContent)}
                onKeyPress={(event) => checkReturns(event)}>
            </div>
        </div>
    )
DrKain commented 2 years ago

Can you please post the full error/stack trace and node version?

matteomontipo commented 2 years ago

Node version is: v14.18.0 (also tried with latest version 16, same error)

Hope this is the stack trace you asked, in case it's not let me know thanks ```ts Unhandled Runtime Error TypeError: The "listener" argument must be of type Function. Received type object Source checkListener node_modules\next\dist\compiled\events\events.js (1:936) _addListener node_modules\next\dist\compiled\events\events.js (1:2571) e.exports.addListener node_modules\next\dist\compiled\events\events.js (1:3300) f.request node_modules\next\dist\compiled\stream-http\index.js (1:45287) Object.get node_modules\next\dist\compiled\stream-http\index.js (1:45345) i.get node_modules\next\dist\compiled\https-browserify\index.js (1:247) eval node_modules\scrape-youtube\lib\index.js (184:0) new Promise Youtube.load node_modules\scrape-youtube\lib\index.js (183:0) Youtube.eval node_modules\scrape-youtube\lib\index.js (204:0) step node_modules\scrape-youtube\lib\index.js (33:0) Object.eval [as next] node_modules\scrape-youtube\lib\index.js (14:45) eval node_modules\scrape-youtube\lib\index.js (8:0) new Promise __awaiter node_modules\scrape-youtube\lib\index.js (4:0) eval node_modules\scrape-youtube\lib\index.js (198:56) new Promise Youtube.search node_modules\scrape-youtube\lib\index.js (198:0) components\youtube\Search.js (30:12) @ checkReturns 28 | }; 29 | > 30 | youtube.search(term, options).then((results) => { | ^ 31 | console.log(results.videos) 32 | setGVideo(results.videos.id) 33 | }); Call Stack onKeyPress components\youtube\Search.js (63:39) HTMLUnknownElement.callCallback node_modules\react-dom\cjs\react-dom.development.js (3945:0) Object.invokeGuardedCallbackDev node_modules\react-dom\cjs\react-dom.development.js (3994:0) invokeGuardedCallback node_modules\react-dom\cjs\react-dom.development.js (4056:0) invokeGuardedCallbackAndCatchFirstError node_modules\react-dom\cjs\react-dom.development.js (4070:0) executeDispatch node_modules\react-dom\cjs\react-dom.development.js (8243:0) processDispatchQueueItemsInOrder node_modules\react-dom\cjs\react-dom.development.js (8275:0) processDispatchQueue node_modules\react-dom\cjs\react-dom.development.js (8288:0) dispatchEventsForPlugins node_modules\react-dom\cjs\react-dom.development.js (8299:0) eval node_modules\react-dom\cjs\react-dom.development.js (8508:0) batchedEventUpdates$1 node_modules\react-dom\cjs\react-dom.development.js (22396:0) batchedEventUpdates node_modules\react-dom\cjs\react-dom.development.js (3745:0) dispatchEventForPluginEventSystem node_modules\react-dom\cjs\react-dom.development.js (8507:0) attemptToDispatchEvent node_modules\react-dom\cjs\react-dom.development.js (6005:0) dispatchEvent node_modules\react-dom\cjs\react-dom.development.js (5924:0) unstable_runWithPriority node_modules\scheduler\cjs\scheduler.development.js (468:0) runWithPriority$1 node_modules\react-dom\cjs\react-dom.development.js (11276:0) discreteUpdates$1 node_modules\react-dom\cjs\react-dom.development.js (22413:0) discreteUpdates node_modules\react-dom\cjs\react-dom.development.js (3756:0) dispatchDiscreteEvent node_modules\react-dom\cjs\react-dom.development.js (5889:0) ```
DrKain commented 2 years ago

It looks like you're using https-browserify. Request options are not supported by https-browserify so it breaks any request made by this package.
Related issue: https://github.com/substack/https-browserify/issues/9

You're not the first one to report this issue but unfortunately it looks like that package is not being updated. Your best solution would be to serve the search results through an API of your own.

DrKain commented 2 years ago

@matteomontipo If you want to give 2.3.0 this should work better with https-browserify and other similar packages. I'll reopen the issue to give you some time to try it if you want, otherwise I'll close again after a week.

matteomontipo commented 2 years ago

@matteomontipo If you want to give 2.3.0 this should work better with https-browserify and other similar packages. I'll reopen the issue to give you some time to try it if you want, otherwise I'll close again after a week.

Awesome thanks, tried with 2.3.1 and that error is gone still not sure what's loading the https-browserify mentioned (maybe webpack 5 which is included in next.js 12 ?)

Although I now receive a Failed fetch, but I bet is more about some parameters I'm missing in the options than a bug, should I post it here in the same thread? It throws error:

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('<URL>') does not match the recipient window's origin ('<URL>').

And

Access to fetch at 'https://www.youtube.com/results?search_query=test&sp=EgIQAQ%253D%253D' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

This also happen when I tested it on vercel, not only on localhost

I tried to modify the options as:

const options = {
    requestOptions: {
        headers: {
            Cookie: 'PREF=f2=8000000',
            'Access-Control-Allow-Origin': 'localhost:3000'
        },
        host: 'http://localhost:3000'
    }
};

But it doesn't change, I think it happens because the url _https://www.youtube.com/results?search_query=test&sp=EgIQAQ%253D%253D_ is missing the parameter "&origin=http://localhost:3000" but I'm not sure

DrKain commented 2 years ago

There's not much I can do about a CORS error, that's controlled by YouTube's servers.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
You're welcome to try using the origin parameter but as far as I know that's only used in the API.

DrKain commented 2 years ago

Another user mentioned they had some success with a reverse proxy like cors-anywhere (#6) but these methods are hacky and out of the scope of this package.
Again, my best recommendation would be a simple API to serve the results to your app.

const { youtube } = require('scrape-youtube');
const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors({ origin: 'http://example.com' }));

// host:3000/search?query=Poets of the fall
app.get('/search', async (req, res) => {
    res.json(await youtube.search(req.query.query));
});

app.listen(3000);
matteomontipo commented 2 years ago

thanks using Next.js so I went for next-cors, and fetch, doing the api query returns the json correctly!

DrKain commented 2 years ago

Glad to hear it. Let me know if you encounter any other issues and I'll be happy to help.