|
Joined: Nov 2023
Posts: 7
Nutrimatic drinks dispenser
|
OP
Nutrimatic drinks dispenser
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.
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:
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)
<- 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:
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
Hoopy frood
|
Hoopy frood
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
Nutrimatic drinks dispenser
|
OP
Nutrimatic drinks dispenser
Joined: Nov 2023
Posts: 7 |
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?
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
Hoopy frood
|
Hoopy frood
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
|
Pikka bird
Joined: Oct 2023
Posts: 16 |
Did you mean $len(%data) in the SOCKREAD Event?
Best Regards from Germany -=[atomic10]=-
|
|
|
|
Joined: Nov 2023
Posts: 7
Nutrimatic drinks dispenser
|
OP
Nutrimatic drinks dispenser
Joined: Nov 2023
Posts: 7 |
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:
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:
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 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
Hoopy frood
|
Hoopy frood
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
Nutrimatic drinks dispenser
|
OP
Nutrimatic drinks dispenser
Joined: Nov 2023
Posts: 7 |
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
Hoopy frood
|
Hoopy frood
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
Fjord artisan
|
Fjord artisan
Joined: Dec 2002
Posts: 253 |
Here's a rather crude example here to get you rolling with $urlget()
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"):
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
Nutrimatic drinks dispenser
|
OP
Nutrimatic drinks dispenser
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
Fjord artisan
|
Fjord artisan
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.
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:
* 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
Nutrimatic drinks dispenser
|
OP
Nutrimatic drinks dispenser
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
Hoopy frood
|
Hoopy frood
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
|
|
|
|
|