mIRC Home    About    Download    Register    News    Help

Print Thread
#272216 22/11/23 05:17 PM
Joined: Nov 2023
Posts: 7
B
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
B
Joined: Nov 2023
Posts: 7
Hi guys,

I've been trying to make a script to display information about a certain user.

This script is still using the older HTTP post/get functions, but I've been trying to use the newer 'urlget' as well.

So this IRC script basically opens a connection to local NodeJS HTTP server (3000), makes a JSON request and expects data back.

Code
alias user {
    var %username = $1
    var %json = $+({ "username": " %username " })
    var %header = POST /user HTTP/1.1 $+ $crlf $+ Host: localhost $+ $crlf $+ Content-Type: application/json $+ $crlf $+ Content-Length: $+ $len(%json) $+ $crlf $+ $crlf
    var %request = %header $+ %json

    echo -a Send request: %request
    sockopen mysocket localhost 3000
    sockmark mysocket %request
}

on *:SOCKOPEN:mysocket: {
    if ($sockerr) return
    sockwrite -nt $sockname $gettok($sock($sockname).mark,1-,$crlf)
    ; Start loop to try and read data back
    .timer 1 1 sockread mysocket
}

on *:SOCKREAD:mysocket: {
    if ($sockerr) return
    var %data = $gettok($sock($sockname).mark,1-,$crlf);
    var %dataObj = $json(%data);
    var %username = $1;

    if ($length(%data) > 0) {
        ; Data available, so stop the loop
        .timer off
        if (%dataObj.success) {
            ; Send data back to IRC
            msg #ScriptTesting Information for user %username: %dataObj.data
        } else {
            ; Show errors in IRC chat
            echo %data
            echo %dataObj
            echo %username
            msg #ScriptTesting An error occurred while retrieving data for user %username: %dataObj.error
        }
        sockclose $sockname
    }
}

In previous version, I have not been succesful in receiving any data back, not even HTTP/JSON errors.

When trying this, it does give a small error: /sockread: socket unavailable (line 16, script2.ini)
But, the NodeJS script gets the data/username as requested and can do stuff with it.

To make it 'simple' for now, I want it to sendback the username as it was requested, to test the connection i/o. The part from IRC > NodeJS is working, but the other way around.. not so much.
The problems I first encountered was that the IRC script expected an instant answer, so it returned empty. At least I thought that was the problem. Now, I'm not so sure anymore..

The NodeJS script:
Code

import express from 'express';
import bodyParser from 'body-parser';
import puppeteer from 'puppeteer';

const app = express();
app.use(bodyParser.json());

app.post('/user', async (req, res) => {
    let username = req.body.username;
    // remove spaces
    username = username.replace(/\s/g, '');
    console.log(`Processing for user: ${username}`);

    try {
        // execute puppeteer script with username
        const userData = await fetchUserData(username);
        res.json({ success: true, data: userData });
        console.log(`Sending data "${userData}"`);
    } catch (error) {
        console.error('Error during processing the request:', error);
        res.status(500).json({ success: false, error: 'There was an error.' });
    }
});

app.listen(3000, () => {
    console.log('Server listening on port 3000');
});

async function fetchUserData(userName) {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();
    await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 });

    try {
        await page.goto('https://[redacted]/login.php');
        await page.type('#username', 'ballonnetje');
        await page.type('#password', '[redacted]]');
        await page.click('input[type="submit"][name="login"]');

        const targetUrl = `https://[redacted]]/user.php?action=search&search=${userName}`;
        await page.goto(targetUrl);

        const extractedData = `Info for user: ${userName}`; 

        await browser.close();
        return extractedData;
    } catch (error) {
        console.error('Error in Puppeteer-script:', error);
        throw new Error('Error executing Puppeteer-script.');
    }
}


When I insert user "test" the logs in IRC:
[time] Send request: POST /user HTTP/1.1 Host: localhost Content-Type: application/json Content-Length:24 { "username": " test " }
[time] * /sockread: socket unavailable (line 16, script2.ini)

The logs in NodeJS script:
Server listening on port 3000
Processing for user: test
Sending data "Info for user: test"

Debug script (AdiiRC)
Code

<- 22-11-2023 18:11:09 - var %username = $1 at line 2
-> 22-11-2023 18:11:09 - var %username test at line 2
<- 22-11-2023 18:11:09 - var %json = $+({ "username": " %username " }) at line 3
-> 22-11-2023 18:11:09 - var %json { "username": " test " } at line 3
<- 22-11-2023 18:11:09 - var %header = POST /user HTTP/1.1 $+ $crlf $+ Host: localhost $+ $crlf $+ Content-Type: application/json $+ $crlf $+ Content-Length: $+ $len(%json) $+ $crlf $+ $crlf at line 4
-> 22-11-2023 18:11:09 - var %header POST /user HTTP/1.1Host: localhostContent-Type: application/jsonContent-Length:24 at line 4
<- 22-11-2023 18:11:09 - var %request = %header $+ %json at line 5
-> 22-11-2023 18:11:09 - var %request POST /user HTTP/1.1Host: localhostContent-Type: application/jsonContent-Length:24{ "username": " test " } at line 5
<- 22-11-2023 18:11:09 - echo -a Send request: %request at line 7
-> 22-11-2023 18:11:09 - echo -a Send request: POST /user HTTP/1.1Host: localhostContent-Type: application/jsonContent-Length:24{ "username": " test " } at line 7
<- 22-11-2023 18:11:09 - sockopen mysocket localhost 3000 at line 8
-> 22-11-2023 18:11:09 - sockopen mysocket localhost 3000 at line 8
<- 22-11-2023 18:11:09 - sockmark mysocket %request at line 9
-> 22-11-2023 18:11:09 - sockmark mysocket POST /user HTTP/1.1Host: localhostContent-Type: application/jsonContent-Length:24{ "username": " test " } at line 9
<- 22-11-2023 18:11:09 - sockwrite -nt $sockname $gettok($sock($sockname).mark,1-,$crlf) at line 14
-> 22-11-2023 18:11:09 - sockwrite -nt mysocket POST /user HTTP/1.1Host: localhostContent-Type: application/jsonContent-Length:24{ "username": " test " }￿ at line 14
<- 22-11-2023 18:11:09 - .timer 1 1 sockread mysocket at line 16
-> 22-11-2023 18:11:09 - .timer 1 1 sockread mysocket at line 16
<- 22-11-2023 18:11:09 - var %data = $gettok($sock($sockname).mark,1-,$crlf); at line 21
-> 22-11-2023 18:11:09 - var %data POST /user HTTP/1.1Host: localhostContent-Type: application/jsonContent-Length:24{ "username": " test " }￿ at line 21
<- 22-11-2023 18:11:09 - var %dataObj = $json(%data); at line 22
-> 22-11-2023 18:11:09 - var %dataObj at line 22
<- 22-11-2023 18:11:09 - var %username = $1; at line 23
-> 22-11-2023 18:11:09 - var %username at line 23
<- 22-11-2023 18:11:10 - sockread mysocket at line 16


Oh yeah, so I tried the urlget as well. This constantly threw me an Parameters error: "USER Not enough parameters".

IRC Code:
Code
var %username = $1
var %json = { "username": %username }
var %url = http://localhost:3000/user
var %documents = $special(Documents)
var %filename = %documents\Gebruikersdata.txt
var %response = $urlget(%url, %filename, , , %json, , )

if (%response) {
   if (%response.status == 200) {
       echo -a Info for user %username: %response.data
   } else {
       echo -a Error getting info for username: %username: %response.error
   }
} else {
   echo -a Got no response from server
}

I'm hoping someone here can help me with this to at least get a response back to IRC.

Thanks in advantage!

Joined: Jul 2006
Posts: 4,185
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,185
Hello, your script is almost perfect, you get the /sockread error because /sockread cannot be used outside socket event (mainly on sockread anyway), mIRC will trigger the on sockread event automatically for you based on some rules, all made to make the reading easy.
Remove your timer with /Sockread and put a sockread command inside the event, if you want to read line by line into a %variable, here is what you must do:

on *:SOCKREAD:mysocket: {
if ($sockerr) return
var %read
sockread %read
if ($sockbr == 0) return
;a line is guarantee to be in %read at this point but can be empty line of course.
echo -ag > %read
}

If the last line does not end with a line ending sequence, it won't get caught in this event as it won't be retriggered by mIRC, you can solve this easily by requesting the connection to be close in the header and then handling the on sockclose event for the socket, where you will be guaranteed to have the last line which you must read with var %read | sockread -f %read | echo -ag > %read.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Nov 2023
Posts: 7
B
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
B
Joined: Nov 2023
Posts: 7
Originally Posted by Wims
Hello, your script is almost perfect, you get the /sockread error because /sockread cannot be used outside socket event (mainly on sockread anyway), mIRC will trigger the on sockread event automatically for you based on some rules, all made to make the reading easy.
Remove your timer with /Sockread and put a sockread command inside the event, if you want to read line by line into a %variable, here is what you must do:

on *:SOCKREAD:mysocket: {
if ($sockerr) return
var %read
sockread %read
if ($sockbr == 0) return
;a line is guarantee to be in %read at this point but can be empty line of course.
echo -ag > %read
}

If the last line does not end with a line ending sequence, it won't get caught in this event as it won't be retriggered by mIRC, you can solve this easily by requesting the connection to be close in the header and then handling the on sockclose event for the socket, where you will be guaranteed to have the last line which you must read with var %read | sockread -f %read | echo -ag > %read.

Like this?

Code
alias user {
    var %username = $1
    var %json = $+({ "username": " %username " })
    var %header = POST /user HTTP/1.1 $+ $crlf $+ Host: localhost $+ $crlf $+ Content-Type: application/json $+ $crlf $+ Content-Length: $+ $len(%json) $+ $crlf $+ $crlf
    var %request = %header $+ %json

    echo -a Send request: %request
    sockopen mysocket localhost 3000
    sockmark mysocket %request
}

on *:SOCKOPEN:mysocket: {
    if ($sockerr) return
    sockwrite -nt $sockname $gettok($sock($sockname).mark,1-,$crlf)
}

on *:SOCKREAD:mysocket: {
    if ($sockerr) return
    var %data = $gettok($sock($sockname).mark,1-,$crlf);
    var %dataObj = $json(%data);
    var %username = $1;

    if ($length(%data) > 0) {
        if (%dataObj.success) {
            ; Send data back to IRC
            msg #ScriptTesting Information for user %username: %dataObj.data
        } else {
            ; Show errors in IRC chat
            echo %data
            echo %dataObj
            echo %username
            msg #ScriptTesting An error occurred while retrieving data for user %username: %dataObj.error
        }
        sockclose $sockname
    }
}

Now I don't get any response. No errors, no logs. Only the Send request:
POST /user HTTP/1.1
Host: localhost
Content-Type: application/json
Content-Length:24

{ "username": " test " }

Joined: Jul 2006
Posts: 4,185
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,185
Of course not, as 1) it's not working as you want it to, the ultimate way to tell it's not "like this" no, and 2) you didn't listen to what I said.
You're not reading the data by using /sockread inside the on sockread event, I even gave you a full example of line by line reading which you completely ignored, so there you go, no more example for you.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Oct 2023
Posts: 16
Pikka bird
Offline
Pikka bird
Joined: Oct 2023
Posts: 16
Code
if ($length(%data)

Did you mean $len(%data) in the SOCKREAD Event?


Best Regards from Germany
-=[atomic10]=-
Joined: Nov 2023
Posts: 7
B
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
B
Joined: Nov 2023
Posts: 7
Originally Posted by Wims
Of course not, as 1) it's not working as you want it to, the ultimate way to tell it's not "like this" no, and 2) you didn't listen to what I said.
You're not reading the data by using /sockread inside the on sockread event, I even gave you a full example of line by line reading which you completely ignored, so there you go, no more example for you.

Dude.. relax. I'm sorry, I made a mistake by not copying the right actual code. I used your example:
Code
alias user {
    var %username = $1
    var %json = $+({ "username": " %username " })
    var %header = POST /user HTTP/1.1 $+ $crlf $+ Host: localhost $+ $crlf $+ Content-Type: application/json $+ $crlf $+ Content-Length: $+ $len(%json) $+ $crlf $+ $crlf
    var %request = %header $+ %json

    echo -a Send request: %request
    sockopen mysocket localhost 3000
    sockmark mysocket %request
}

on *:SOCKOPEN:mysocket: {
    if ($sockerr) return
    sockwrite -nt $sockname $gettok($sock($sockname).mark,1-,$crlf)
}

on *:SOCKREAD:mysocket: {
if ($sockerr) return
var %read
sockread %read
if ($sockbr == 0) return
;a line is guarantee to be in %read at this point but can be empty line of course.
echo -ag > %read
}

Also please note.. I'm a complete noob at mIRC coding. This now results in a 400 Bad request response:
Code
Send request: POST /user HTTP/1.1
Host: localhost
Content-Type: application/json
Content-Length:25

{ "username": " jaghj " }
> HTTP/1.1 400 Bad Request
> Connection: close
>

I would really appreciate it if you would give me another chance smile

Originally Posted by atomic10
Code
if ($length(%data)

Did you mean $len(%data) in the SOCKREAD Event?

Maybe. Tried this, then returns with the error (An error occurred while retrieving data for user) - so empty data again...

Joined: Jul 2006
Posts: 4,185
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,185
Remove the -n switch on your /sockwrite which is sending an extra $crlf at the end.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Nov 2023
Posts: 7
B
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
B
Joined: Nov 2023
Posts: 7
Originally Posted by Wims
Remove the -n switch on your /sockwrite which is sending an extra $crlf at the end.

Still same error..

Joined: Jul 2006
Posts: 4,185
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,185
Then I'm not sure, you can join the irc channel in my signature if you want, where I can help more in depth, possibly via teamviewer.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel
Joined: Dec 2002
Posts: 253
T
Fjord artisan
Offline
Fjord artisan
T
Joined: Dec 2002
Posts: 253
Here's a rather crude example here to get you rolling with $urlget()

Code
alias NJSUser {
  var %URI = http://localhost , %JSON = $+({"username":,",$1,"})

  bset -t &headers 1 Content-Type: application/json
  bset -t &body 1 %JSON

  noop $urlget(%URI,pbi,&NJSUser,processNJS,&headers,&body)
}
alias processNJS {
  var %id = $1 , %BV = $urlget(%id).target
  echo -ai2 * ID: %id , Bvar: %BV , Size: $bvar(%BV,0)
  if ($bvar(%BV,0)) { echo -ai2 * Data: $bvar(%BV,1-).text }
}

Example: /njsuser foo

mIRC's $URLGet() output to connection (socket spied upon to clarify what mIRC already adds to the "headers"):
Code
POST / HTTP/1.1
Accept: */*
Content-Type: application/json
Accept-Encoding: gzip, deflate
User-Agent: mIRC
Host: localhost
Content-Length: 18
Connection: Keep-Alive
Cache-Control: no-cache

{"username":"foo"}

Using urlget, you will notice things like Host, Content-Length, User-Agent, etc.. are already done for you, so we only need to add the content-type which is nice.

The breakdown: $urlget(%URI,pbi,&NJSUser,processNJS,&headers,&body)
uri = target...
p = post method, b = binary mode, i = ignore ssl errors (just in case it may be https:// and a self-signed cert or whatever error)

The first binvar is what we wish the results of request to be filled into (&NJSUser)
processNJS = the alias to call when the request finishes.
&headers = the additional headers we wish to pass
&body = the body of the request (our JSON)

Breakdown part 2:
when urlget is assigned a request, it assigns a unique ID to that request (if we didn't use noop here, the return from using $urlget() would be that ID number just for clarity). If using a callback alias, $1 is the ID of this particular request.
You can pull various information given this ID number via $urlget(id).[property]

Properties are as follows: url, redirect, method, type, target, alias, id, state, size, resume, rcvd, time, reply

In this "crude" example, it will upon completion echo out the ID, binvar used, and the size of the binvar which shows if any data at all was collected, and a very poorly broken (potential line too long error) echo of the return body if the binvar length isn't 0.

Hope this helps you in using $urlget() instead of the raw socket approach, kept it short and simple to not be too conviluted with info. This should get you into the ballpark of valid returns you can then decide what to do with that data.

Joined: Nov 2023
Posts: 7
B
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
B
Joined: Nov 2023
Posts: 7
Hey Talon thanks for your reply.

This echos "* ID: 1029 , Bvar: &NJSUser , Size: 0".

So I guess the size of the data retrieved back is 0?

Keep in mind that the nodeJS script is replying after a website has been scraped for data. this might take a while and i'm not sure the script waits for this.

Joined: Dec 2002
Posts: 253
T
Fjord artisan
Offline
Fjord artisan
T
Joined: Dec 2002
Posts: 253
I'd try checking the state: Did you change the URI from my test?

Here's an adaptation example using a free POST API Tester site to show it working with some debug output:
The website is: https://reqres.in/ and I'm using the /api/register "test" listed on this site. which shows the response that should be.


Code
alias NJSUser {
  var %URI = https://reqres.in/api/register , %JSON = {"email":"eve.holt@reqres.in","password":"pistol"}

  bset -t &headers 1 Content-Type: application/json
  bset -t &body 1 %JSON

  noop $urlget(%URI,pbi,&NJSUser,processNJS,&headers,&body)
}
alias processNJS {
  var %id = $1 , %BV = $urlget(%id).target

  echo -ai2 * url: $urlget(%id).url
  echo -ai2 * redirect: $urlget(%id).redirect
  echo -ai2 * method: $urlget(%id).method
  echo -ai2 * type: $urlget(%id).type
  echo -ai2 * target: $urlget(%id).target
  echo -ai2 * alias: $urlget(%id).alias
  echo -ai2 * id: $urlget(%id).id
  echo -ai2 * state: $urlget(%id).state
  echo -ai2 * size: $urlget(%id).size
  echo -ai2 * resume: $urlget(%id).resume
  echo -ai2 * rcvd: $urlget(%id).rcvd
  echo -ai2 * time: $urlget(%id).time
  echo -ai2 * reply: $urlget(%id).reply

  if ($bvar(%BV,0)) { echo -ai2 * Data : $bvar(%BV,1-).text }
}


once ran: I get the proper result I'm supposed to:

Code
* url: https://reqres.in/api/register
* redirect:
* method: post
* type: binvar
* target: &NJSUser
* alias: processNJS
* id: 1039
* state: ok
* size: 36
* resume: 0
* rcvd: 36
* time: 796
* reply: 
    HTTP/1.1 200 OK
    Date: Wed, 29 Nov 2023 19:32:29 GMT
    Content-Type: application/json; charset=utf-8
    Content-Length: 36
    Connection: keep-alive
    Report-To: {"group":"heroku-nel","max_age":3600,"endpoints":[{"url":"https://nel.heroku.com/reports?ts=1701286349&sid=c4c9725f-1ab0-44d8-820f-430df2718e11&s=kUDIZ1LCVjdUHeFjOJ6KPivCOTJTpaCrKKHLNdofljM%3D"}]}
  Reporting-Endpoints: heroku-nel=https://nel.heroku.com/reports?ts=1701286349&sid=c4c9725f-1ab0-44d8-820f-430df2718e11&s=kUDIZ1LCVjdUHeFjOJ6KPivCOTJTpaCrKKHLNdofljM%3D
    Nel: {"report_to":"heroku-nel","max_age":3600,"success_fraction":0.005,"failure_fraction":0.05,"response_headers":["Via"]}
    X-Powered-By: Express
    Access-Control-Allow-Origin: *
    Etag: W/"24-4iP0za1geN2he+ohu8F0FhCjLks"
    Via: 1.1 vegur
    CF-Cache-Status: DYNAMIC
    Server: cloudflare
    CF-RAY: 82dd46e0ff122c8c-ORD

* Data : {"id":4,"token":"QpwL5tke4Pnpja7X4"}

Joined: Nov 2023
Posts: 7
B
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
B
Joined: Nov 2023
Posts: 7
Hey guys,

Thank you all! It's now working!

Wims helped me a lot on IRC with the HTTP socket option and after we also fixed the urlget from Talon.

Thank you so much guys!

Joined: Jul 2006
Posts: 4,185
W
Hoopy frood
Offline
Hoopy frood
W
Joined: Jul 2006
Posts: 4,185
Just to clarify, the problem was invalid json from the beginning causing a 400 bad request, causing $urlget to not fill the binvar and see the request as a failure ($urlget().state is fail, which might be the only thing missing from your script if anything), the $urlget script was correct and nothing needed to be "fixed" there as OP said.


Worth mentioning that OP does not know mirc scripting at all and the original script was written by chatgpt, which, while the script had many wrong part, had the connecting/http part working.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel

Link Copied to Clipboard