mIRC Home    About    Download    Register    News    Help

Print Thread
Page 1 of 3 1 2 3
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
Can someone help me with a login script.

i have this.
Code
alias subc {
  echo -s *** Closing Cod.Stats
  sockclose cstats
  echo -s *** Opening Cod.Stats
  sockopen -e cstats my.callofduty.com 443
}

on *:sockopen:cstats: {
  sockwrite -n $sockname GET /api/papi-client/stats/cod/v1/title/mw/platform/battle/gamer/Ancientswede $+ % $+ 232802/profile/type/warzone HTTP/1.0
  sockwrite -n $sockname User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
  sockwrite -n $sockname Host: my.callofduty.com
  sockwrite -n $sockname Accept-Language: en-us
  sockwrite -n $sockname Accept: */*
  sockwrite -n $sockname
}

on *:sockread:cstats: {
  if ($sockerr) {
    echo -a Error.
    halt
  }
  else {
    var %temp
    sockread -f %temp
    echo -a %temp
  }
}


it works but i need to send the login/authenticated to the site so can i retrive the data, but i have no idea how to do that.

i need to send this
Code
POST Auth tokens
https://profile.callofduty.com/do_login?new_SiteId=cod
Obtain the auth tokens (atkn, rtkn) from the cookies of the response after triggering a login of a user. These tokens have a suspected lifetime of about 2 hours after which they have to be reobtained.

HEADERS
CookieXSRF-TOKEN={{XSRF-TOKEN}}
PARAMS
new_SiteIdcod
BODY formdata
username{{accountEmail}}
The e-mail address of your Activision account

password{{accountPassword}}
The password of your Activision account

remember_metrue
A boolean representing the option to save your login credentials

_csrf{{XSRF-TOKEN}}
The XSRF-TOKEN, needs to be obtained (or reobtained) if the reply throws a 403 Unauthorized error

Code
curl --location --request POST 'https://profile.callofduty.com/do_login?new_SiteId=cod' \
--header 'Cookie: XSRF-TOKEN={{XSRF-TOKEN}}' \
--form 'username={{accountEmail}}' \
--form 'password={{accountPassword}}' \
--form 'remember_me=true' \
--form '_csrf={{XSRF-TOKEN}}'


Code
GET CSRF-token
https://profile.callofduty.com/cod/login
Obtain a CSRF-token from the Call of Duty login form that we can send with our future requests. Without a CSRF-token in the cookies of our request headers we will be returned a 403 error (Unauthorized)



But as i said i have no idea how to send the stuff to the page so i can get the data, i know how to sort it afterwards, so if anyone can/want to help me with this it would be much appreciated.

Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
You can use $urlget() to do http requests.

Assuming your curl is correct you would do something such as:

Code
alias postit {

  // build the body as url-encoded form parameters
  bset -t &body 1 username={{accountEmail}}&password={{accountPassword}}&remember_me=true&_csrf={{XSRF-TOKEN}}

  // build a list of headers, seperated by crlf, inside a bvar:
  bset -t &headers 1 Content-Type: application/x-www-form-urlencoded $+ $crlf
  bset -t &headers -1 Content-Length: $bvar(&body, 0) $+ $crlf
  bset -t &headers -1 Cookie: XSRF-TOKEN={{XSRF-TOKEN}}

  // start the request
  noop $urlget(https://profile.callofduty.com/do_login?new_SiteId=cod, pb, &response, postit_response, &headers, &body)
}

alias postit_response {

  var %id = $1

  var %response_bvar = $urlget(%id).target

  // do something with %response_bvar
  echo -s >> $bvar(%response_bvar, 1-3000).text
}

Last edited by FroggieDaFrog; 17/10/20 07:22 AM.

I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
tank you. But i dont understand that code at all smile
And it throws me No such identifier: $urlget

But i have looked at it more and the login page is this one https://profile.callofduty.com/cod/login
wich i need to put in my mail and password.
then i need to request this site after https://www.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/battle/gamer/Ancientswede%232802/profile/type/warzone
i have tried and googled it and cant find any answer at all.
But looks like im able to do a POST first or am i wrong?

Havent been tuching coding in 5 years and i never messed around with the sock thingy. smile

Last edited by Bast; 18/10/20 01:32 AM.
Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Urlget was added in version 7.56, so if you're needing help for an older version, please mention your version when asking for help. Or, if able to upgrade, try that.

Last edited by maroon; 18/10/20 04:40 AM.
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
o my bad,i was a couple of version off that. Did the update so im on the latest atm.
That code still shows me a
Code
Invalid parameters: $bvar (line 171, twitch.mrc)

Last edited by Bast; 18/10/20 07:11 AM.
Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
Your problem is likely because there was no response data. This can happen based on the http status code. You can echo $urlget(%id).reply to see the headers.

But I think I've identified a problem using $urlget for this purpose. When you finally get the correct POST sent, the response is a 302 redirect which mIRC follows and eventually responds with a 200 OK. But the original response headers with the 302 are no longer available so you cannot retrieve the auth cookies. It took me a while to realize this was the problem rather than something I was doing wrong.

mIRC needs to add the ability not to follow redirects; I could imagine other ways to work around this but that's probably the easiest. Until this is added you'll need to use raw sockets, use curl to obtain these cookies, or use another script like JSON-For-Mirc.

Edit: Looks like jsonformirc also follows redirects after a POST?

Last edited by Loki12583; 18/10/20 09:53 PM.
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
i get a 403 Respons.
But i have tried like alot of different login path since it seems to be multiple adresses, byt they all give me the same respons.
So im guessing im getting to the wrong page?

well it beats me since i have no idea to tackle this problem. The code to login should be good since its the same person who has coded the call of duty stats plugin for discord and he has documented the login process here

Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
I have a proof-of-concept working: HERE

Currently it's using my old script for custom sockets and JSON-For-Mirc

I left in all the test functions and debug text. /cod.login.jfm and /cod.login.urlget both result in a 200 OK when I expect to receive a 302 Temporary Redirect.

Cookie handling in the script will need to be improved regardless of which socket method is used.

Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
wow thats super awesome of you.

if i do /cod.stats it shows me this

Code
url https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/battle/gamer/Ancientswede%232802/profile/type/warzone
redirect
method post
type binvar
target &response
alias urlget.callback
id 1046
state fail
size 0
resume 0
rcvd 0
time 469
reply


/cod.login i just get the * /echo: insufficient parameters (line 86, script4.mrc)

so in what way should i call the script? i have set the password and email in the vars.

Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
The echo error is caused when there's a blank line or a line containing only spaces. You can either do checking to avoid echoing 'nothing', or have a prefix at the front of the echo.

echo -a %temp

would change to one of these:

echo -a >>: %temp
if ($remove(%temp,$chr(32)) != $null) echo -a %temp

Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
The error on that specific line indicates no cookies were stored.

Did you also install the JSON-For-mIRC script? You'll want that anyway to parse the json responses.

If you enter these commands do they produce real values? Don't post the actual cookie values here they could be used to access your account. You should be getting a lot of debug text in your current window while these are executing.

Code
//echo -ag token: $cod.token
//echo -ag cookies: $cod.cookies


Edit:
Hopefully you can get the login working. I added a new function to cache and print some stats:
Code
/cod.login
/cod.stats.display

Username: Ancientswede#2802
Level: 153
Kills: 64154


Last edited by Loki12583; 19/10/20 03:54 AM.
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
I did mess up before it seems like.
If i do a /cod.login now it shows me alot of text
Code
HTTP/1.1 403 Forbidden
Content-Type: text/html;charset=utf-8
Content-Length: 431
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Language: en
Date: Mon, 19 Oct 2020 04:45:11 GMT
Connection: close
X-Activision-Regioncode: AB
Set-Cookie:ALOT.OF.TEXT
2
2 :: _abck=ALOT.OF.TEXT
2 :: Domain=.callofduty.com; Path=/; Expires=Tue, 19 Oct 2021 04:45:11 GMT; Max-Age=31536000; Secure

-
_abck=ALOT.OF.TEXT-1;


if i do
//echo -ag token: $cod.token
//echo -ag cookies: $cod.cookies

Code
token: ALOT.OF.TEXTk
cookies: _abck=ALOT.OF.TEXT;


on cod.stats i get

Code
url https://my.callofduty.com/api/papi-client/stats/cod/v1/title/mw/platform/battle/gamer/%232802/profile/type/warzone
redirect
method post
type binvar
target &response
alias urlget.callback
id 1065
state ok
size 0
resume 0
rcvd 148
time 1141
reply HTTP/1.1 200 OK
Content-Type: application/json
Expires: Mon, 19 Oct 2020 05:48:59 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Mon, 19 Oct 2020 05:48:59 GMT
Connection: keep-alive
Set-Cookie: API_CSRF_TOKEN=07cbdb71-3fbf-4ab3-bc62-80a612c159c9; Secure; SameSite=Strict; Path=/


response {"status":"error","data":{"type":"com.activision.mt.common.stdtools.exceptions.NoStackTraceException","message":"Not permitted: not authenticated"}}





btw, the remember me thing in the code is that something that need to be there for the cookie? caus its no such box on the login page which i asume its for?

Last edited by Bast; 19/10/20 05:49 AM.
Joined: Dec 2002
Posts: 253
T
Fjord artisan
Offline
Fjord artisan
T
Joined: Dec 2002
Posts: 253
You can be given multiple cookies, all on individual "Set-Cookie:" header lines. They normally have more information than what you're showing... You can't pass back an identical cookie for this reason, there's a proper protocol to follow.

For instance:

Set-Cookie: item=value;Max-Age=N;Path=/

With the provided information, we have a cookie "item" with the value of "value" which expires at age N, and this cookie applies to a Path relevant to the root directory "/".

If we made a request which applies to this cookies path, we must return this cookie within our own request header, minus the additional information. If our request path does NOT apply to the relative cookies acceptable path, this cookie should NOT be relayed, but in this cause, the path is "/" which is the root directory, so all paths "/some/other/location/etc.." would apply, so our response would look something like:

Cookie: item=value

Now what if we're delivered multiple cookies that all apply?
like:

Set-Cookie: item=value;Max-Age=N;Path=/
Set-Cookie: item2=value2;Max-Age=N;Path=/

Well now we must combine our request header cookies into a return (although I think it's also possible to submit multiple cookie lines too, haven't read up on http/1.1 protocol in a while)

Which would look something like:

Cookie: item=value; item2=value2

Your Regex capture group appears to not be greedy and find up-to the first ";" and include this within the capture, I do believe the last relayed cookie should not end in a semi-colon.

I've tested this locally and watched the response headers from both Firefox and Chrome, and this is how they both appear to re-represent a stored cookie string. I haven't exploited deliberately sending a crazy amount of cookies to see how it handles what can fit in a "Cookie:" header line, to witness how it might break-up such a long string.

Firefox Test:
Code
GET /cp HTTP/1.1
Host: xxxx
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: https://xxxx/cp/
Cookie: ClientID=xxxx; OtherData=xxxx
If-Modified-Since: Fri, 09 Mar 2018 02:34:29 GMT
Cache-Control: max-age=0


Not sure if this could be a culprit or not. Also, the value's should be unpacked (uri-compliant, the whole + for space, %XX for illegal characters, etc..) but I do believe you aren't re-packing the value from the httpd request response anyways, but that was another thought I had.

I've never used JSON-4-mIRC so I can't help much beyond that, but I have done plenty of API-related things dealing with cookies over http/https with raw sockets, long before the existance of json-4-mirc and $urlget. It's not too terribly difficult if you understand http/1.1 protocol, which is quite an extensive RFC read.

Also you've posted your response as "A-LOT-OF-TEXT" which makes me wonder if you might be getting any line too long errors? maybe you should be hadding these to a table with -b and saving a binvar? If you go that route, make sure to noop $hget(table,item,&bvar) to load it up, then you could /bcopy whatever data you wish to append, then once again /hadd -b it back to the table, to keep extending your cookie tokenized list.

Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
thanks Talon, But i dint understand anything of that cry

i just want to login to one page then its going to redirect me to the api page, never thought that would be so hard smile

maybe i have to look into a php script that can output a txt file or something instead.

Last edited by Bast; 20/10/20 12:11 AM.
Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
In the remote editor, in the variable tab do you have %username and %password set? Originally my comments were missing the % in the set commands.

I have not seen you post anything with the csrf token, this may indicate json-for-mirc is not working. You have "JSON For Mirc.js" in the same folder as the mrc script? Can you enter this and reply with the response?

Code
//echo -ag $jsonversion :: $cod.token


But the script is working. The cookie regex is fine, it's global //g and I loop over the set-cookie values to include them in the next request. SReject is looking into changing json-for-mirc to disable redirects. I have made this change locally and can now skip my custom sockets in lieu of an entire json-for-mirc approach.

Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
Yes i did set the username and password and i have done an ¤echo to make sure its there.
and yes i have both JSON files in the mirc dir

i get this on your command

Code
SReject/JSONForMirc v2.0.4000 :: UFSRAnlnfH7OI8P_1r_6iwxop5T22E7iYdLlcEAebhIij7Ky-c7rKk2iT8dJyjAk

Last edited by Bast; 20/10/20 01:44 AM.
Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
SReject has updated his script to support redirect disabling, you'll have to grab the master files directly:
JSON For mIRC.mrc
JSON For mIRC.js

I have updated my script accordingly, $urlget and custom sockets are no longer used:
CallOfDuty.mrc

It will now log you in automatically upon your first API access if cookies are not detected. Still need to add support for cookie expiration and failure handling.

Just restart mIRC to start fresh and enter /cod.stats.show Ancientswede#2802

Last edited by Loki12583; 20/10/20 03:08 PM.
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
thanks.
Now i actually got a respons
Code
Status: 200
Head: 200 OK
Cache-Control: max-age=590134
Connection: keep-alive
Connection: Transfer-Encoding
Date: Tue, 20 Oct 2020 23:47:18 GMT
Transfer-Encoding: chunked
Content-Type: text/html;charset=utf-8
Expires: Tue, 27 Oct 2020 19:42:52 GMT
Last-Modified: Tue, 20 Oct 2020 19:42:52 GMT
ETag: W/"ceeee-5b21f6fc79192-gzip"
Server: Apache/2.4.39 (Amazon) Communique/4.2.2
X-Akamai-Path-Stats: [3:103990:7043010],[1:19224:8776]
X-Activision-Regioncode: AB
X-Activision-Countrycode: SE


<!DOCTYPE HTML>
<html lang="sv">


 <head>
 <meta charset="UTF-8"/>

		<script>


but its seems to get stuck, caus i can only do that respons 1 time, then nothing happends if i try and do it more time withour restarting mirc and i dont get any values from the api page its going to next.

Last edited by Bast; 21/10/20 03:43 AM.
Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
It looks like you're getting the 200 response after following the 302 redirect (means login request was successful). When this happens the cookies are set to $null (because none are received in the subsequent 200 response), so that explains the behavior you're seeing. But it shouldn't be following the 302 to the 200 with the latest jsonformirc, can you enter the following command? Modifying the path if you don't have these in the mirc script directory.

Code
//echo -ag $jsonversion :: $md5($mircdirscripts\Json For mIRC.js,2)
SReject/JSONForMirc v3.0.1002 :: 230784d5928a75c2fb92a6e41f983b9f


Included is the current version and hash at the time of this comment.

Last edited by Loki12583; 21/10/20 01:07 PM.
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
then i get an error

Code
* Error accessing file: $md5
-
SReject/JSONForMirc v3.0.1002




EDIT

I did mess up somehwre along the line.
Did a fresh install of the json and your script on the stats/login and now i got the correct respons.


Damn your are awesome , BIG thank You for all the help and patience from you. You Rock

So next one would be how do i get more data out of it, from what i see in the echo i only get like a 4th of all the stats.


Last edited by Bast; 21/10/20 04:57 PM.
Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
mIRC has a line limit of ~4000 characters and the responses are often too long to fit. The easiest way to get the full information is just to open the relevant URL in your web browser, then you can examine the JSON structure.

Look at the user commands I've added to the script, you can see how I access specific data:

Code
var %matches = $CoD.Matches($1,$2,$3,$4)

var %match = $json(%matches,data,matches,0)
var %kills = $json(%match,playerStats,kills).value

or

var %kills = $json(%matches,data,matches,0,playerStats,kills).value


I've made some more changes to CallOfDuty.mrc and changed the $CoD.Call alias so that it opens the URL when debugging is enabled.

Last edited by Loki12583; 21/10/20 07:02 PM.
Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
v7.53 increased the line length to 8kb, and 7.62 increased it again to 10kb. But there's always a website out there who can create longer string lengths between carriage returns.

I'm not sure how these lengths apply to extending the max for things like /sockread, so you'd have to test. As applied to %string the line length generally means 'characters' but to &binvar it often means 'bytes'. As long as the website has normal text there won't be a difference. But if there are characters above $chr(127) your &binvar can sometimes be unexpectedly shortchanged.

//var %string $str($chr(10004),6000) | bset -t &var 1 %string | echo -a $len($bvar(&var,1-).text) = 1/3rd *$maxlenl vs $len(%string)

You can now see the line length limit with $maxlenl, but you can't easily use lengths near that amount since that's the limit for the entire line, including commands, other parameters, and the %variable name itself.

Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Some useful info about my JSON For Mirc script:

Explaination of what JSON is and JSON for mIRC Reference


I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
Awesome that you keep adding stuff to this one.

I figured out how to get the data from the JSON
like
Code
$json(%stats,data,lifetime,all,properties,br,properties,wins).value


but it takes the first value it hits, but i want to take the Br wins for example.
looks like this
Code
"br":{"properties":{"wins":76.0


tried alot of different stuff to get down to that one but i have failed.

Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Do you have an example of the full plain-text JSON data? Use pastebin.com or similar to post it, if it can't be accessed from a browser.

Once we have an example of the data, could you tell us each piece of data you want to extract from it


I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38

Last edited by Bast; 22/10/20 04:24 AM.
Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Here's a handy site that makes viewing the JSON data far easier: jsonviewer. Paste the JSON text in then click the "Viewer" button at the very top


Now lets say you want to access various items in the br mode's data, all you have to do is make a call to $json for each piece of data you want to retrieve:

Code
alias example {
  ;; ... code that retrieves the json and parses it

  ;; assume the JSON handler's name is stored in %stats


  ;; echos: BR Wins: 76
  echo -ag BR Wins: $json(%stats, data, lifetime, mode, br, properties, wins).value 

  ;; echos: BR Kills: 10843
  echo -ag BR Kills: $json(%stats, data, lifetime, mode, br, properties, kills).value

  ;; Or if you want both on the same line
  ;; echos: BR Wins: 76 - BR Kills: 10843
  echo -ag BR Wins: $json(%stats, data, lifetime, mode, br, properties, wins).value - BR Kills: $json(%stats, data, lifetime, mode, br, properties, kills).value
}

Last edited by FroggieDaFrog; 22/10/20 04:44 AM.

I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
right now i got it when i see it in the format. whistle


You are an awesome person who has helped alot, dont know how you coop with us noobs. grin

so now i just need to add some commands to my twitch, but i think i will be abel to do that myself.

so again. Thank You very much

Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Originally Posted by Bast
dont know how you coop with us noobs.


We were all a newbie at one point. I'm sure we've given plenty of people headaches when we first started, so its only fair we take our share of em now.


I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
im making so all values is saved to an ini file.
looks like this
Code
    ;;-------------------;;
    ;;      CrossBow     ;;
    ;;-------------------;;
    var %weaponname CrossBow | var %weaponapiname iw8_sn_crossbow
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Hits $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,hits).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Kills $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kills).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname KD $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kdRatio).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname HeadShots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,headshots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Accuracy $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,accuracy).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Shots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,shots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Deaths $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,deaths).value
    ;;-------------------;;
    ;;       Kar98k      ;;
    ;;-------------------;;
    var %weaponname Kar98k | var %weaponapiname iw8_sn_kilo98
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Hits $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,hits).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Kills $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kills).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname KD $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kdRatio).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname HeadShots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,headshots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Accuracy $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,accuracy).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Shots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,shots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Deaths $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,deaths).value
    ;;-------------------;;
    ;;       EBR-14      ;;
    ;;-------------------;;
    var %weaponname EBR-14 | var %weaponapiname iw8_sn_mike14
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Hits $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,hits).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Kills $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kills).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname KD $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kdRatio).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname HeadShots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,headshots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Accuracy $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,accuracy).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Shots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,shots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Deaths $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,deaths).value


but can i make a loop,instead of typing like 1000 rows of almost the same thing?
to something like

Code
    ;;-------------------;;
    ;;      CrossBow     ;;
    ;;-------------------;;
    var %weaponname CrossBow | var %weaponapiname iw8_sn_crossbow

    ;;-------------------;;
    ;;       Kar98k      ;;
    ;;-------------------;;
    var %weaponname Kar98k | var %weaponapiname iw8_sn_kilo98

    ;;-------------------;;
    ;;       EBR-14      ;;
    ;;-------------------;;
    var %weaponname EBR-14 | var %weaponapiname iw8_sn_mike14

;Write stuff to ini
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Hits $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,hits).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Kills $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kills).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname KD $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,kdRatio).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname HeadShots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,headshots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Accuracy $round($json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,accuracy).value,2)
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Shots $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,shots).value
    writeini $shortfn($mircdirscripts) $+ %statsfiles $+ Stats.ini %weaponname Deaths $json(%stats, data, lifetime, itemData, weapon_marksman, %weaponapiname $+ ,properties,deaths).value


Last edited by Bast; 22/10/20 06:06 PM.
Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
You can have an alias which does the writing to the .ini, and you can pass "CrossBow" as the $1 parm, and "iw8_sn_crossbow" as the $2.
If you have a place where all the weapons are stored, you can loop through that list to fetch the pair of parameters to be passed to the alias.

If the list of weapons is short enough to fit in 1 big long line, you could loop through that until the list is empty, passing 1 pair at a time.

Code
tokenize 32 weapon1 weapon1api weapon2 weapon1api etc

while ($1 != $null) {
aliasname_that_does_the_ini_write $1 $2 %stats %statsfiles
tokenize 32 $3-
}


note there's a -n switch for writeini related to .ini files larger than 64k, and it looks like you're writing a lot of data to it.

Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
There is looping built into jsonformirc. You might consider adding these items to hash tables before writing to ini, I don't know if mIRC will keep the file handle open between all the operations and so many writeinis could take much longer. It takes 10 seconds just to loop and assign variables.

This will loop over every property of every weapon:

Code
alias weapons.store {
  var %stats = $$CoD.Stats($1,$2,$3,$4)

  if (!$hget(cod.weapons)) { weapons.init }

  var %file = $shortfn($mircdirscripts\stats\UserStats.ini)

  var %ref = $json(%stats,data,lifetime,itemData)

  noop $JSONForEach(%ref,weapons.foreach %file).walk
}

alias weapons.foreach {
  var %target = $1, %ref = $2
  var %path = $json(%ref).pathLength
  var %weaponapi = $jsonpath(%ref,$calc(%path - 2))
  var %weapon = $weapons.enum(%weaponapi)
  var %prop = $jsonpath(%ref,%path)
  var %value = $round($json(%ref).value,2)

  echo -ag %target %weapon %prop %value
}

alias weapons.enum {
  if ($hget(cod.weapons,$1)) { return $v1 }
  return $1
}

alias weapons.init {
  hmake cod.weapons
  hadd cod.weapons iw8_sn_crossbow CrossBow
  hadd cod.weapons iw8_sn_kilo98 Kar98k
  hadd cod.weapons iw8_sn_miki14 EBR-14
}


But are these going to be read by something else which only supports INI? You could just save the json itself and use $json whenever you want to access something.

Last edited by Loki12583; 22/10/20 08:37 PM.
Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Originally Posted by Loki12583
You could just save the json itself and use $json whenever you want to access something.
This.

My JSON script supports saving data to a file via the $JSON()'s toFile suffix. Here's an example of saving the URL's response to a file:
Code
$JSON(name, path/to/file.json).HttpBodyToFile


Then to load that file:
Code
/JSONOpen -f name path/to/file.json

Last edited by FroggieDaFrog; 22/10/20 09:02 PM.

I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
gonna give it a try.
The reason i save it to an ini is that i know how to and im using a timer to access the api every 30min. so when ever someone does the !warzone command it reads from the ini instead of requesting new data from the api.
im thinking this is better for the api then just spamming it if you would have alot of users in chat that want to know my stats.

Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
After thinking of it would be smarter to just read the json file.
But i cant figure out where to put the save thing.
i did try and put it under Cod.Stats.show
and im asuming the Name is %stats
Code
$json( %stats $+ , $mircdirscripts $+ / $+ CodStats.json).HttpBodyToFile


it saves the file but gives me an unknow command.
So im messing something up.

Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
Code
/noop $json( %stats $+ , $mircdirscripts $+ / $+ CodStats.json).HttpBodyToFile


I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
Thanks that was it. wink

It seems it dosent overwrite the last file if it exsist or does it just overwrite if if there is any changes maybe?

Last edited by Bast; 23/10/20 06:31 AM.
Joined: Jan 2004
Posts: 1,361
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Jan 2004
Posts: 1,361
It sounds like you don't need to keep these values in a file at all then, you have a few other options. Saving the json response to file might still be your best option, but these are worth considering.

1. Use hash tables. Parse all values for fastest lookup later. This is closest to your INI storage, and can even be saved to INI if you want to persist when mIRC is closed.
Code
/hmake weapon.stats
/hadd weapon.stats Kar98.Kills 300
/hadd weapon stats Kar98.Accuracy 45
...
var %Kar98.Kills = $hget(weapon.stats,Kar98.Kills)


2. Save json to binvar. I'm not sure exactly how much faster this would be than using a file.
Code
var %bvar = $json(%ref).HttpBodyToBvar
hadd -mb cod.responses stats %bvar
...
var %bvar = $hget(cod.responses,stats)
/JSONOpen -bd cod.response.stats %bvar
var %Kar98.Kills = $json(cod.response.stats,data,lifetime,...)


3. Don't close the json handle until you replace it. Whenever /JSONOpen is called currently the -d switch is used. Remove that, and either open it with a custom %ref name or save the returned %ref for later. Then you just access with $json(%ref,data,lifetime,stats,...) later on without having to request from the API again. You can /JSONClose on a timer to remove it later then refresh stats. Could be adding unnecessary complexity.

Last edited by Loki12583; 23/10/20 12:06 PM.
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
nice.

The whole reason that i want to save it to a file is that i fo example just want my own stats to be lookup and saved ever = x and the person(s) in chat should only be allowed to request fresh stats every = x
So then i want to save these values either to a json with their name on it and i just calculate time to for my = x

But as i said above, i cant get it to overwrite the last file for some reason.

i have tested the open/close and got that to work.

and if you would build a DB you can add later a !compare <weaon> to my stats.
But im guessing it would be better with a mysqldb for this maybe.

Last edited by Bast; 23/10/20 10:31 PM.
Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
The json script will not overwrite the file if it exists, so you'll need to delete the file before making a call to $json. This is to prevent accidental overwrites.

Code
var %file = path/to/file
.remove $qt(%file)
noop $JSON(name, %file).HttpBodyToFile

Last edited by FroggieDaFrog; 23/10/20 11:12 PM.

I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
ok i see, but wouldent it be better if there was a switch for overwrite? wink

But what are you thoughts on saving user stats.
Should i use the hashtables and then save it to an ini file or is my thinking viable to save the json then access it?

Last edited by Bast; 23/10/20 11:17 PM.
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
Why cant i grab the null value in this string?
Code
$json(%stats,data,weekly,all,properties).value


the json looks like this.

Code
{
  "status": "success",
  "data": {
    "title": "mw",
    "platform": "battle",
    "username": "Ancientskull#1576",
    "type": "wz",
    "level": 55.0,
    "maxLevel": 0.0,
    "levelXpRemainder": 3000.0,
    "levelXpGained": 7000.0,
    "prestige": 0.0,
    "prestigeId": 0.0,
    "maxPrestige": 0.0,
    "totalXp": 960000.0,
    "paragonRank": 0.0,
    "paragonId": 0.0,
    "s": 0.0,
    "p": 0.0,
    "lifetime": {
      "all": {
        "properties": {

    "weekly": {
      "all": {
        "properties": null
      },
      "mode": {
        
      },
      "map": {
        
      }
    },
    "engagement": null
  }
}


so there is no data for weekly so i would want it to add null to my ini, so can check it and say, hey, there is no data for weekly.

Joined: Apr 2010
Posts: 969
F
Hoopy frood
Offline
Hoopy frood
F
Joined: Apr 2010
Posts: 969
In JSON null means "no value", so the json script converts it to $null; that is, an empty string


I am SReject
My Stuff
Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
ofcource, i was seeing it as a text so i tried to do an if statement with null instead of $null blush

Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
Why cant i use this line? it always get stuck on this one even i thou i have the 4th word like that.

Code
f (($strip($4) != battle) || ($strip($4) != psn) || ($strip($4) != xbl)) { u need to type in battle,psn,xbl not $strip($4) 


This works just how it should.

Code
if (($strip($4) == battle) || ($strip($4) == psn) || ($strip($4) == xbl)) {


What am i doing wrong? my brain might be fried atm. laugh
or cant you use "or with not equal to"

Last edited by Bast; 28/10/20 12:07 AM.
Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Your first statement will always be true. Just like this will always be true:

if ( (%var != 1) || (%var != 2) )

Since a variable can't be both values, then at least 1 of them must be true. Maybe you want to do something like:

if (!$istok(battle psn xbl,$strip($4),32)) echo -a u need to type in battle,psn,xbl not $strip($4)

Or, you could do
if (($strip($4) == battle) || ($strip($4) == psn) || ($strip($4) == xbl)) { do stuff }
else { echo -a error }

Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
Thanks maroon for that explanation.

My brain felt like it melted whan i was looking att that row and felt like it should really work, but i couldent for my life figure out why. cool

Joined: Nov 2011
Posts: 38
B
Bast Offline OP
Ameglian cow
OP Offline
Ameglian cow
B
Joined: Nov 2011
Posts: 38
I do have this loop that does the job.
But
guns has 50 entrys
tactical 5
leathal 10

Question: Does this break the scipt? i dont get any error, but since their is different amount of entrys in every one!
should i make a loop on every single section or is it a better way of doing things?

Code
  var %i = 1 | while (%i <= $ini($shortfn($mircdirscripts) $+ %dstats $+ MW-Weapons.ini,GUNS,0)) {
    if ($readini($shortfn($mircdirscripts) $+ %dstats $+ MW-Weapons.ini,GUNS,%i) == %weapon $+ ) { .msg chan}
    if ($readini($shortfn($mircdirscripts) $+ %dstats $+ MW-Weapons.ini,TACTiCAL,%i) == %weapon $+ ) { .msg chan }
    if ($readini($shortfn($mircdirscripts) $+ %dstats $+ MW-Weapons.ini,LETHALS,%i) == %weapon $+ ) { .msg %chan }
    inc %i
  }
[u][/u]

Page 1 of 3 1 2 3

Link Copied to Clipboard