Closed JustArchi closed 6 years ago
A minimal example using jquery can be found here: https://github.com/JustArchi/ArchiSteamFarm/pull/615
Sending commands and reading replys works in firefox and chrome (rest unchecked), loading the log, only in firefox. (and not in chrome).
For reading the logs nothing but jquery.load worked. But I am not sure if this functionality is really needed. Sending commands could be done without jquery.
I'm using this ruby script to communicate with ASF through IPC. This script can be compiled into an .EXE file which executes the commands and returns the value. the compiled file would be approximatively 2.8MBs This script assumes that the user did not edit neither IPChost nor IPCport, there can be some workarounds to get IPChost and IPCport without the user input.
require 'open-uri'
x = 0
until x == 5
begin
puts "write the command to execute/'exit' to exit"
command = gets.chomp
if command == "exit"
puts "Exiting the program"
x = 5
else
remove_exclamation = command.sub "!", ""
space_command = remove_exclamation.gsub " ", "%20"
output = open("https://127.0.0.1:1242:1242/IPC?command=#{space_command}", :read_timeout => 900).read
output.strip!
puts "#{output}"
puts ""
end
rescue
puts "Something went wrong"
puts ""
end
end
<body>
<form action="http://127.0.0.1:1242/IPC" method="get" target="output">
<input name="command" /><input type="submit" value="Send" />
</form>
<iframe name="output"/>
</body>
I would say use a grid, like the one from syncfusion or bootstrap, with a bar on top for all possible actions. Then if you want to execute an action on one or multiple bots, just check the boxes before each bot (or just all) and click the corresponding button. A second tab in the menu could show a log. AdminLTE, which uses Bootstrap and could be a nice looking framework.
@kaoyusu - how to use it?
EDIT: hehe - yo soy muy stupido xD simply make it as html and "run" it
ASF-IPC-GUI.zip works and has some stuff in it
@JustArchi Could we keep compatibility with ASFui's? With 3.0.5.1 it ain't working anymore.
Then ASFui should be updated to match new structure - it was clearly stated in V3 migration article that current way of accessing IPC is considered to be temporary until a good idea of a proper API is ready. I don't plan supporting obsolete and much more problematic to execute ways such as /IPC?command=version
if user can just call /Api/Command/version
instead.
Now the API is ready and I do plan to keep it as compatible as possible in future versions, but I don't want to hold on obsolete temporary dependencies that were announced to be temporary in the first place.
It'd be a good idea to make use of extra time the version still being in pre-release and let @alvr correct the URL, since the change is really misc.
OK, would be nice if you could update the wiki then to include the changed IPC endpoint.
BTW, doesn't ASF output received IPC commands to console anymore? This was rather useful.
OK, would be nice if you could update the wiki then to include the changed IPC endpoint.
Would be nice if people read 🤔
Is there any way to setup SSL for IPC server? 🤔
Nope, that would require from ASF server to have valid SSL certificate and add extra overhead.
If you need ASF IPC interface over SSL then I strongly recommend to use reverse-proxy. Nginx can be a very good solution for that.
location / {
proxy_pass http://127.0.0.1:1242;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Then you can just set your website to use any protocol and port you want to, including securing it with SSL and certificate.
Oh, forgot that I can use nginx as a proxy. 👍 Thank you very much.
Another way, change IPC server to *:80 and use Cloudflare Flexible SSL. Point domain to server's IP 😁 https://i.imgur.com/WH55QL7.jpg
i always get 404 when i run it on my rootserver it runs and it farms - and IPC also is active - but i cant hand over and correct commands
I'm not sure if IPC isn't completely ready yet (as of update V3.0.5.1), but issuing commands via POST request isn't working for me. Here's what I'm trying to do:
curl -v -X POST 'http://127.0.0.1:1242/Api/Command/version'
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 1242 (#0)
> POST /Api/Command/version HTTP/1.1
> Host: 127.0.0.1:1242
> User-Agent: curl/7.57.0
> Accept: */*
>
< HTTP/1.1 411 Length Required
< Content-Type: text/html
< Server: Microsoft-NetCore/2.0
< Date: Sat, 09 Dec 2017 18:46:13 GMT
< Content-Length: 24
< Connection: close
<
* Closing connection 0
<h1>Length Required</h1>%
I also got this on ASF:
2017-12-09 16:40:59|dotnet-16064|FATAL|ASF|OnUnobservedTaskException() System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Cannot access a disposed object.
Object name: 'System.Net.HttpListenerResponse'.) ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.HttpListenerResponse'.
at System.Net.HttpListenerResponse.CheckDisposed()
at System.Net.HttpListenerResponse.set_ContentType(String value)
at ArchiSteamFarm.IPC.<ResponseString>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<ResponseJson>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<ResponseJsonObject>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleApiCommandGeneric>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleApiCommand>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleApi>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleAuthenticatedRequest>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleRequest>d__17.MoveNext()
--- End of inner exception stack trace ---
---> (Inner Exception #0) System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.HttpListenerResponse'.
at System.Net.HttpListenerResponse.CheckDisposed()
at System.Net.HttpListenerResponse.set_ContentType(String value)
at ArchiSteamFarm.IPC.<ResponseString>d__23.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<ResponseJson>d__20.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<ResponseJsonObject>d__21.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleApiCommandGeneric>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleApiCommand>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleApi>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleAuthenticatedRequest>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at ArchiSteamFarm.IPC.<HandleRequest>d__17.MoveNext()<---
new IPC is broken old IPC of version 1.0.4.9 is working
@GUiHKX You have your error clearly stated in the response:
< HTTP/1.1 411 Length Required
You can't send POST request without specifying Content-Length
. Refer to HTTP RFC if you're confused - https://tools.ietf.org/html/rfc7231#section-6.5.10
As for the exception it's good that you reported it, will cover it in V3.0.5.2.
@Benman2785 Nothing is broken, thanks for your concern.
@GUiHKX You can continue hunting bugs in V3.0.5.2, especially all IPC-related exceptions 🙂
I just tried to replicate the request as stated in this section of the Wiki... Am I missing something? I really don't know.
I just told you what you're missing - read again.
Yes, the Content-Length
header, but what should I put in the request body? The example in the Wiki doesn't tell me what.
The example on the wiki doesn't require request body 🙂
Okay I got it now. I must send Content-Length: 0
. I didn't know that header was required when I'm not sending anything. It just seems a bit weird for me... But it's working. Thanks. If anyone uses curl
to send commands to IPC, like I do, you can use this:
curl --data '' 'http://127.0.0.1:1242/Api/Command/version'
{"Message":"OK","Result":"\n<and> ASF V3.0.5.1","Success":true}
Okay I got it now. I must send
Content-Length: 0
. I didn't know that header was required when I'm not sending anything. It just seems a bit weird for me... But it's working. Thanks.
https://tools.ietf.org/html/rfc7230#section-3.3.2
A user agent SHOULD send a Content-Length in a request message when
no Transfer-Encoding is sent and the request method defines a meaning
for an enclosed payload body. (and POST request does ~archi)
Doesn't matter if it seems weird to you or not - RFC states how HTTP protocol works, not me neither you.
Yes, but the fact that is is a standard doesn't make it less stupid. lol. I also don't agree with the request design. If we're using POST
, then why don't we send the command in the request body rather than in the URL?
Yes, but the fact that is is a standard doesn't make it less stupid. lol. I also don't agree with the request design. If we're using POST, then why don't we send the command in the request body rather than in the URL?
Because of yet another set fo rules, this time RESTful URLs one - http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#restful
mh - i try tomorrow again with my server - but http://ip:port/Api/Command/* didnt worked for me when running it in browser - always got 404
If you got 404 then it means that your URL is wrong. Since you didn't say anything but "it's broken", you can only get a response "it works for me" 🙂
But we're not adding new information nor modifying them into ASF when we use POST
, at least that's my understanding of why the article recommended its use. A GET
would make more sense in that case. At least I've never seen POST
requests being used to send an empty request body. But who cares, this discussion is pointless...
"IPCHost": "XXX.XXX.XXX.XXX", "IPCPort": 1242,
i connect to http://XXX.XXX.XXX.XXX:1242/Api/Command/status and it only gives 404 from ASF (nginx looks different) - nginx isnt listening on 1242
404 is the only error i get
but i will test again tomorrow
But we're not adding new information nor modifying them into ASF when we use
POST
, at least that's my understanding of why the article recommended its use. AGET
would make more sense in that case. At least I've never seenPOST
requests being used to send an empty request body. But who cares, this discussion is pointless...
@GUiHKX Then your understanding is wrong once again, RFC 2616 this time, section 9.1.1 - https://www.ietf.org/rfc/rfc2616.txt
In particular, the convention has been established that the GET and
HEAD methods SHOULD NOT have the significance of taking an action
other than retrieval. These methods ought to be considered "safe".
This allows user agents to represent other methods, such as POST, PUT
and DELETE, in a special way, so that the user is made aware of the
fact that a possibly unsafe action is being requested.
Issuing command is not safe retrieval of data 🙂
You're free to agree or disagree with this, but like I said above - you're not defining how HTTP protocol should work, neither I do. RFCs were defined and written exactly for this reason, and I won't break a set of commonly-accepted and established standards only because somebody thinks he knows better - including my own person.
@Benman2785
"Works for me" 🙂
@Benman2785
If you are trying to connect from your PC to your rootserver and you have not opened up the IPC Port you will get 404. Maybe thats the issue?
@JustArchi I think you're misunderstanding the usage of GET
and POST
requests. Let's get into the "safeness" matter of using POST
in this case. What does it keep you safe from if we're sending all the data in the URL? What is the difference of these both commands security-wise?
POST:
curl -d '' 'http://127.0.0.1:1242/Api/Command/redeem 01 ABC-DEF-GHI'
GET:
curl 'http://127.0.0.1:1242/Api/Command/redeem 01 ABC-DEF-GHI'
It accomplishes nothing security-wise and it's simply bad design. That's why I said it's more sane to put the command in the request body, to hide any sensitive data from the URL (although I still think this is pedantic, since a MITM attacker would be able to see the request body anyway).
EDIT: Since we're talking security, passing passwords in query-strings?
This is my design for the IPC GUI using adminlte, bootstrap, fontawesome. I am currently using this design for my own bots so I customized it a bit to fit my needs.
If you like it I would be happy to work together and share my ides for the IPC GUI.
Wow, I like it, very good job! I'm not much of a designer myself, but I would love a dark theme too.
@JustArchi I think you're misunderstanding the usage of GET and POST requests. Let's get into the "safeness" matter of using POST in this case. What does it keep you safe from if we're sending all the data in the URL?
@GUiHKX
You're interpreting safeness in entirely wrong way - safe in context of RFC means that the HTTP server's state doesn't change when issuing a command. Whether you issue GET /Api/Bot/ASF
one or 100 times, it'll not result in any specific action altering the state of the ASF as a process, hence data retrieval. Nothing is being updated in a way that the next GET
request will be unavailable or have data altered.
POST
indicates that action is unsafe, as in - it can alter HTTP server's state. For example !exit
command will do that, as first !exit
command will make ASF close, making HTTP server no longer accessible, which will make all other requests fail due to that, hence being unsafe by altering server's state (and the rest of the process).
The security of the actual data is completely irrelevant since including key in POST body isn't any different from including it right in the URL for potential attacker - it's exactly in the same place, in the message of the packet. If you want to secure this message over the internet then you should use HTTPS protocol, for which I already gave a solution above. And in this case once again it does not matter whether you use POST or GET because it's still in the same place, but this time the message is entirely encrypted.
If you don't have anything apart from "I think it's stupid" reason for violating RFC standards, REST guidelines and HTTP protocol definition, then it'd probably be best if I could stop wasting time proving you that you have no idea what you're talking about 😕
@MrBurrBurr
I love it ❤️. When you consider your design more or less finished, pack everything into zip file and upload on GitHub - I'll be happy to integrate this, so you as well as all other people can further improve it in pull requests 🙂
@GUiHKX
Glad to hear that you like it! You are a lucky guy, adminlte comes in 12 different themes (6 light - 6 dark).
Here is dark blue for example: https://imgur.com/a/rdM8c
@JustArchi
🙂 I will have to do some code cleanup and finish some other parts of the GUI. Also I need to make it work with the new IPC (I am running latest stable version). But I will contact you in some way when I got it on GitHub.
With new API endpoints you can do far more - not only getting rid of probably dirty parsing of !api
or !status ASF
with finally proper GET /Api/Bot/ASF
, but also you can add basic bots management, as new API endpoints allow you to create/update/delete bot configs.
Take your time 🙂
Thats exactly why I need to do the code cleanup! :D
Also bot management via IPC will be neat.
I love it how you claim knowing the context of RFC standards as you please, just to fit your speech. And only decides to follow standards to your convenience.
So, for you, it does not make a difference if you send sensitive data as a query-string (I somewhat agree, it doesn't in the context of ASF, but it's just good practice to not do so), but it does make a difference if we use badly designed POST
requests for commands like: !version
, !2fa
, !bl
, !ib
, !iq
, !password
, !help
, !stats
, !status
, which simply read stuff from memory and don't change anything in the ASF process? Which, according to you, the only reason you're using POST
requests for such commands is because they're "unsafe"... Interesting.
And for the third and last time: I never told you to stop using POST
requests, I suggested you to put the actual command in the body of the request, which would be the most sane usage. OR, I suggested using GET
requests instead, since you're simply passing the command in the URL anyway, so it wouldn't make a difference and we wouldn't have to send an empty body request or add the Content-Length: 0
header.
Still on that topic, the thing I said it was stupid about the standard is having to send a Content-Length
when your not sending any body to your POST
request. But I mistakenly called that stupid because of your stupid design instead. Sending a POST
request with an empty body and sending the actual data in the URL as a query-string? Ugh...
Another thing to add about your dumb "RESTful" requests. If anyone have a bot named with a #
or a ?
, requests will simply not work (assuming you have a bot named archi#clueless
):
curl 'http://127.0.0.1:1242/Api/Bot/archi#clueless'
{"Message":"Couldn't find any bot named archi!","Result":null,"Success":false}
Because of the design of that request, you're creating conflicts with already defined URL standards (since you seem to like them so much) when you can have absolutely every character in your bot's name.
Now people will have to adapt their bot names because of your crappy design choice.
It's not the first time I saw you being rude to people and assume you're right about everything, so if you want to keep these garbage requests like they are right now, it's your call. It will not make any difference for me because I'l adapt anyway, but it won't change the fact that it's wrong and bad design.
I'm done with you, I won't make any further comments regarding this issue anymore.
but it does make a difference if we use badly designed POST requests for commands like: !version, !2fa, !bl, !ib, !iq, !password, !help, !stats, !status, which simply read stuff from memory and don't change anything in the ASF process?
It's the potential of a request that is considered safe or unsafe, not specific example. /Api/Command
is designed as POST
because it has potential to be unsafe, but without a requirement of being used in unsafe context all the time. I guess that part was obvious.
I suggested you to put the actual command in the body of the request
Which violates RESTful way of creating URLs.
OR, I suggested using GET requests instead
Which violates RFC 2616, section 9.1.1.
Sending a POSTrequest with an empty body and sending the actual data in the URL as a query-string?
Unbelievable, right? This situation is so uncommon that it's even mentioned in the RFC.
Because of the design of that request, you're creating conflicts with already defined URL standards (since you seem to like them so much) when you can have absolutely every character in your bot's name.
Now people will have to adapt their bot names because of your crappy design choice.
If only you could read the RFC you linked fully 🤔
If data for a URI component would conflict with a reserved
character's purpose as a delimiter, then the conflicting data must be
percent-encoded before the URI is formed.
curl 'http://127.0.0.1:1242/Api/Bot/archi%23smart'
{"Message":"OK","Result":[{"BotName":"archi#smart","KeepRunning":false}],"Success":true}
But it's fine, you tried really hard, I appreciate the effort 🙂
It's not the first time I saw you being rude to people and assume you're right about everything
It's not the first time I'm seeing somebody who can't accept for a second that he actually might be the wrong one, even when presented with bunch of rules, RFCs, standards and protocol implementations used worldwide. The best thing is how you used your last possible argument with being impossible to use #
in URL encoding, which isn't only completely wrong, it's even more funny when you realize that according to this I should make all requests POST
-based with a body, because user could always use some special character in a query 🙂. And with your prime example of even fetching bot status as a POST
request, now THAT would be just lovely, I'd expect at least a dozen of folks asking me if I got hit in my head when deciding upon this.
I'm done with you, I won't make any further comments regarding this issue anymore.
Me neither, and I'll actually remove any further comments to this matter from now on, just to enforce it in case you change your mind, since it doesn't contribute anything to the development - but you're more than welcome to suggest enhancements that bring more advantages than disadvantages, assuming that you still want to do that of course. And I know you won't hold grudge in a few days when you realize your mistake and feel embarassed for it, happened to me more than dozen of times 😊.
Here is a peace dove for you 🕊
And now back onto development 🔧
@MrBurrBurr I added one new API endpoint, GET /Api/Structure/{Structure}
which might help you with generating configs for bots. In general you must keep in mind that BotConfig
returned by /Api/Bot/{Bot}
lacks sensitive details, which is wanted scenario. This is why I added a new endpoint, so you can make updating bot configs possible.
This is how I see it:
BotConfig
structure with GET /Api/Structure/BotConfig
- it has full structure.BotConfig
of given Bot
with GET /Api/Bot/{Bot}
- it gets bot structure, which is almost full but lacking sensitive details.null
(alternatively use bot structure, detect which fields are missing and assign null
value for them)null
values if user is not changing them.POST /Api/Bot/{Bot}
with updated config, default value of KeepSensitiveDetails: true
will change your nulls for sensitive details into proper values on ASF side.A bit much, but it should work just awesome. Normally you could just skip entire 3rd point and modify current bot config as it is, and missing fields would be assumed automatically, but this sadly won't work for SteamParentalPIN
, as it has default value of 0
and not null
, so if user is using custom pin then your "just edited bot config" would re-define his value back to 0
. On the other hand if I assumed that default value of sensitive detail == keep, then re-defining that PIN from custom value like 1337
back to 0
would not be possible with KeepSensitiveDetails: true
. This is why I decided to stick with this way and make KeepSensitiveDetails: true
make all nulls defined for sensitive details to inherit, I think it's quite good approach, unless somebody has better one.
Since you're the main user of the API, you're free to suggest possible improvements and changes as you see fit. In other words - if you need something, just ask, and I'll try my best to solve the issue in one way or another, depending how it's appropriate. For now I consider API enough to make basic bots management with bot statuses and sending commands, once we have that we can think about future improvements 🙂
@MrBurrBurr would you share your GUI? ;)
I'm very keen to see his GUI implemented, looks good.
I done this (some time ago and I updated it today to what I am using) to me so maybe someone it will use or make it better until new gui is finished...
@Nuklon
Could we keep compatibility with ASFui's? With 3.0.5.1 it ain't working anymore.
Good thing current ver. of ASFui aint working. This can help the author finally look into the Issues while making new one.
@Botan626 https://github.com/KlappPc/ASFui/releases/tag/0.61
Read the notes.
Since we have a nicely working HTTP IPC in ASF V3 now, we could make use of that fact and code a nice ASF GUI purely in html, javascript and css. IPC can easily communicate with ASF and execute commands, fetch status and expose other things over friendly HTTP interface, with all sort of needed events and stuff. Something like typical web-admin interface for a game server.
Of course, as usual I'm not interested in doing any of that myself, so I'm just putting up issue on hold in case anybody would want to make it happen. I'm too awful at html/css/js to start working on that, but I can help gluing everything together if somebody has html/css/js ready and general idea how entire thing should work/look like.