RienNeVaPlus / wikifolio

📊 Wikifolio (unofficial) API
18 stars 6 forks source link

Error: Cannot find module 'request' #5

Closed drkthng closed 3 years ago

drkthng commented 3 years ago

Hi RienNeVaPlus,

thank you for publishing this great project! you're the only one on the net that I found that provides a wikifolio api solution. I tried to rebuild it in C# from your code-base but got stuck with my http post requests, that did not result in the same response of the authCookie as your code does or as the wikifolio page itself does when you login.

So I tried to run your code, unfortunately I'm a total noob in typescript.

Working with Visual Studio Code, I created a very small sample script:

import Api from 'wikifolio'

const email = "myemail";
const password = "mypassword";

const api = new Api({email, password});

const wikifolio = api.wikifolio('wfobserver')

const details = async () => {
    await wikifolio.details()
}
console.log( details )

and then ran tsc test.ts which worked fine, followed by node test.js which throws the following error:

PS C:\Users\Gordon\nodeWikifolio\execution> node test.js
internal/modules/cjs/loader.js:905
  throw err;
  ^

Error: Cannot find module 'request'
Require stack:
- C:\Users\Gordon\nodeWikifolio\node_modules\request-promise-native\lib\rp.js
- C:\Users\Gordon\nodeWikifolio\node_modules\wikifolio\dist\utils.js
- C:\Users\Gordon\nodeWikifolio\node_modules\wikifolio\dist\models\Api.js
- C:\Users\Gordon\nodeWikifolio\node_modules\wikifolio\dist\models\index.js
- C:\Users\Gordon\nodeWikifolio\node_modules\wikifolio\dist\index.js
- C:\Users\Gordon\nodeWikifolio\execution\test.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
    at Function.Module._load (internal/modules/cjs/loader.js:746:27)
    at Module.require (internal/modules/cjs/loader.js:974:19)
    at require (internal/modules/cjs/helpers.js:92:18)
    at C:\Users\Gordon\nodeWikifolio\node_modules\request-promise-native\lib\rp.js:8:12
    at module.exports (C:\Users\Gordon\nodeWikifolio\node_modules\stealthy-require\lib\index.js:62:23)
    at Object.<anonymous> (C:\Users\Gordon\nodeWikifolio\node_modules\request-promise-native\lib\rp.js:7:15)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'C:\\Users\\Gordon\\nodeWikifolio\\node_modules\\request-promise-native\\lib\\rp.js',
    'C:\\Users\\Gordon\\nodeWikifolio\\node_modules\\wikifolio\\dist\\utils.js',
    'C:\\Users\\Gordon\\nodeWikifolio\\node_modules\\wikifolio\\dist\\models\\Api.js',
    'C:\\Users\\Gordon\\nodeWikifolio\\node_modules\\wikifolio\\dist\\models\\index.js',
    'C:\\Users\\Gordon\\nodeWikifolio\\node_modules\\wikifolio\\dist\\index.js',
    'C:\\Users\\Gordon\\nodeWikifolio\\execution\\test.js'
  ]
}

Can you see where I am doing something wrong? I am trying to solve/google the problem for multiple hours now without success.

Thanks for the great work and greetings!

RienNeVaPlus commented 3 years ago

Hi, did you run yarn install? Also, check out the example repo. If that doesn't work, make sure your node version is compatible with request-promise-native and request is installed (should be a dependency of request-promise-native) by trying yarn add request.

drkthng commented 3 years ago

Hi RienNeVaPlus, thank you for

Hi, did you run yarn install? Also, check out the example repo. If that doesn't work, make sure your node version is compatible with request-promise-native and request is installed (should be a dependency of request-promise-native) by trying yarn add request.

Hi RienNeVaPlus! Thank you for that fast answer! I used yarn and it worked like a charm!! Was now able to capture the post request made by your code and tried to port it to C# I am able to make a request that looks quite similar to yours, but still it won't give me the "theAuthCookie", rather this request does not return cookies at all, I cannot figure out why. Would you mind having a quick look, on where I am still doing something wrong in the request?

Here is my request captured by fiddler:

POST https://www.wikifolio.com/dynamic/de/de/login/login HTTP/1.1
Content-Type: multipart/form-data; boundary=--------------------------063906911996927377214277
Host: www.wikifolio.com
Cookie: ASP.NET_SessionId=vb2pjm2h4wjknkp31ju2qgbu; RemarketingRandomGroup=30; __RequestVerificationToken=A5RFKw2ofwWdgiGhHEjyScKenmbRdeBqtiZDhSm8XlGUJA_v__1lARVCvPHXBUHbc1yU9EMJpFUXaeL0Vpfpj7PEiss1
Content-Length: 824
Expect: 100-continue
Connection: Close

--------------------------063906911996927377214277
Content-Disposition: form-data; name="Username"

some@email.com
--------------------------063906911996927377214277
Content-Disposition: form-data; name="Password"

somePassword
--------------------------063906911996927377214277
Content-Disposition: form-data; name="ufprt"

2B7154B27514C23696DD992B6ACFE625A229B9BE4F77DC3179DD7097C60965B2B0C89025689E547F8C22FF75FA39557F87F94C67597A90DB8D8CF0FE9FC3F1BA63E943E5AAB634671134DB561B469AD3B8EF1F03CCA8E3BB4D50C885D65907D39C4E8D94
--------------------------063906911996927377214277
Content-Disposition: form-data; name="__RequestVerificationToken"

ArKzqwl21FI-HKWSLyeaNlslZ_9jLugDG6R89LrapmUogiW-OEpsl1ceHDFwvyryXXlEwFJ1msWnoE4J20lkbU-Db9Y1
--------------------------063906911996927377214277--
RienNeVaPlus commented 3 years ago

Make sure to request the session data (ufprt and __RequestVerificationToken) before the login. Theses values change with every request and cannot be reused. Therefore you need to two requests to sing in:

const url = Api.url + 'dynamic/de/de/login/login'

// request form for session vars
const form = await request({url, resolveWithFullResponse:true})

const {window: {document}} = new JSDOM(form.body)
const __RequestVerificationToken = (document.querySelector('[name=__RequestVerificationToken]') as HTMLInputElement).value
const ufprt = (document.querySelector('[name=ufprt]') as HTMLInputElement).value

// login with session vars
const res = await request.post({
    url,
    formData: {
        Username: email,
        Password: password,
        ufprt, __RequestVerificationToken
    },
    simple: false,
    resolveWithFullResponse: true
})

Source

  1. Request the login form
  2. Grab the values of the hidden inputs called __RequestVerificationToken and ufprt
  3. Send your credentials along with these two values to the same endpoint

Hope that helps

drkthng commented 3 years ago

Yeah, I saw that in your code, and that's what I already do. Firing the first request, extracting ufprt und and the token and sending those 2 together with the login credentials. No the only difference is, that for whatever reason, when doing this via C# HttpWebRequest Post, I do not get the "theAuthCookie" back... But after a lot of research I have the feeling that this might be more of a problem that this cookies is probably a "secure" cookie and that the .Net HttpWebRequest is not returning this kind of cookie properly. For all I know, the request itself that I posted in the earlier message looks pretty ok.

Anyways, thanks for helping and responding so quickly! Will now try to find a way to execute your code via my C# app.

drkthng commented 3 years ago

Hey RienNeVaPlus! Since I already took so much of your time moaning about my problem with transferring your great solution onto C#, I also wanted to let you know that I just right now was able to resolve it. The problem was indeed not the cookies or the data to send itself but the "carrier", ie the C# HttpWebRequest. I changed the code to use HttpClient instead and now was successful in getting the authCookie back!

Thank you so much again for your solution and for your help!!

RienNeVaPlus commented 3 years ago

Glad it worked out!