Feature - Implemented Request a Fax from CLI

Veracity

Developer
Staff member
Not everything that FaxBot makes available translates into a specific KoLmafia "monster". Well, they could, but, all three Butts (Riff, Mr. Skullhead, lethal @ 1000 ML) would presumably become "Somebody else's butt" with completely inaccurate monster stats.

It wouldn't be hard to add functions to the FaxBotDatabase to translate between faxbot command and faxbot monster name, or vice versa, and use those to allow FaxBot's monster names as an argument to the CLI command.

But that's as far as I've thought about. I have no particular plans to do even that, myself, much less make spiffy ASH functions.
 

Banana Lord

Member
That's a good idea. I was wondering if there was a page somewhere with the data on it. But I don't have much experience with parsing pages like that. I could do something very cumbersome with string handling (looking up the indices for characters and adding/subtracting based on that information). I haven't done any regex, so unless someone was to post a fully or semi-functional function for parsing that page it would probably be best if I just copy pasted from here and used a text editor to whip the file into shape.

EDIT: re Veracity's post, I was just going to ignore the non-monster entires, but I suppose that would be more relevant if you were going to do anything in-built. But as far as preliminary support goes would it matter if you just left them out?

EDIT2: The other thing I'll have to do is make sure that the character has access to FaxBot, i.e.: check that FaxBot has a whitelist into their clan, or maybe implement a clan-hopping feature. But that's way out of the scope of what you'd do here. All I'm really hoping for is a neat and tidy faxbot($monster[MONSTERNAME]) -> Returns False if the monster isn't available to FaxBot, True if the command is successfully sent.
 
Last edited:

heeheehee

Developer
Staff member
Code:
matcher m = create_matcher('quotecontent"><div style="display: none;">(.*?): (.*?)<(/div|br /)>', visit_url(url));
while (m.find()) {
  if (m.group(1).index_of("Butt") == m.group(1).length  - 4) {
    map[$monster[Somebody else's Butt]] = true;
  } else {
    map[to_monster(m.group(1))] = true;
  }
  if (m.group(3) == "/div") {
    break;
  }
}
boolean faxbot(monster m) {
  return map[m] && cli_execute("faxbot " + m);
}
Something like that, perhaps? (it'll most likely need some tweaking. :p)
 

Veracity

Developer
Staff member
The main issue with automating it is that you have to be in chat in order for KoLmafia to get the message from FaxBot and know that the monster is in the fax machine ready to pick up. You can either be in KoLmafia's own chat GUI or in the Relay Browser; in either case, KoLmafia will pick up the message and let the FaxRequestFrame (and by extension, the CLI command, if that's how it's invoked) know.

There is some disabled code to enforce that you are in chat before sending the request. It is disabled because we currently have no way of knowing that you are logged into chat in the Relay Browser. I would like it if there was some reliable method I could call within KoLmafia to check that.

For that matter, I would like it if there was some reliable way to programmatically open a chat connection, regardless of whether you are in KoLmafia chat or KoL's chat, in which I could submit a chat message and wait for a reply. The first half - submitting the message - we have. The second half - waiting for a reply - depends on you being in chat elsewhere.

It is almost certainly true that I don't understand the guts of the chat system well enough to deal with this. Perhaps Grotfang - our "chat guts" expert - would care to comment.
 

Banana Lord

Member
Why is it necessary to retrieve the PM that FaxBot sends? The most important part is sending the command to FaxBot in the first place isn't it? But I suppose you'd need to be in chat to do that anyway.
 

Veracity

Developer
Staff member
Why is it necessary to retrieve the PM that FaxBot sends?
So you can tell when the Fax is ready for you to retrieve. FaxBot tells you via chat PM. Note that it also gives you error messages via chat PM: "I just copied in a fax for somebody else; try again in a minute", "You've asked for enough faxes today already", "that was a bogus command" and so on.

The most important part is sending the command to FaxBot in the first place isn't it?
No, clearly not! The most important part is pulling the requested monster out of the fax machine after FaxBot has placed it there for you.

But I suppose you'd need to be in chat to do that anyway.
Interestingly enough, you do not have to be in chat to SEND a chat message. KoLmafia is perfectly happy to do a "/whois" to check whether a player is online, whether or not you are currently in chat.
 

Banana Lord

Member
Hold the phone. So the CLI command will actually pull the monster out? I thought it was just sending a message to the bot and returning true if the command went through OK, not doing spiffy stuff like that! Epic!
 

Veracity

Developer
Staff member
It does exactly what the Fax Request Frame does: it sends the command to FaxBot, waits for it to respond, retries if necessary, and gets the monster when Faxbot says it is ready. It uses exactly the same code the Fax Request Frame does; I refactored the guts of the Fax Request Frame into a function which both the CLI command and the Fax Request Frame call to do the job.

As coded, it was never really intended to be called from a script, given the chat requirement, but it will work fine from the CLI (or a script) if you are already in chat in the Relay Browser or in KoLmafia's "Loathing Chat" window.
 

Banana Lord

Member
Nifty. But I take it it won't actually use the photocopy? OK, that''ll make it much easier for me to implement auto-FaxBotting in Harvest then, even if I do have to work around the chat thing. Is there any way to check if a player's in chat? Otherwise that code for forcing the player into chat might be useful. Maybe if there ever was an ash function for faxbotting it could have an optional parameter to force the player into chat if they're not already? I don't know, just thinking out loud.
 

fronobulax

Developer
Staff member
Otherwise that code for forcing the player into chat might be useful.

Not that this edge case is mainstream enough to worry about, but I have at least one character that has never visited the Altar of Literacy. A well behaved script would detect and respect that decision.
 

Veracity

Developer
Staff member
Is there any way to check if a player's in chat?
As I mentioned earlier, I was unable to find a way to check that inside KoLmafia. If I could, I would un-disable the "you must be in chat" message. I'd like it if Hola or Grotfang could tell me how to do that. :)

Otherwise that code for forcing the player into chat might be useful. Maybe if there ever was an ash function for faxbotting it could have an optional parameter to force the player into chat if they're not already?
Other than starting the Chat Manager - which is associated with KoLmafia's Loathing Chat GUI, I believe - I don't know how to "force a player into chat". I wish there was an API within KoLmafia (and presumably within KoL, to enable this) to allow having a private chat channel, so to speak, for exchanging PMs with a particular other player, rather than having to be in some public channel and having PMs just appear there. I want a channel with nothing but PMs, so that we could connect to it and not see any public chatter.

Not that this edge case is mainstream enough to worry about, but I have at least one character that has never visited the Altar of Literacy. A well behaved script would detect and respect that decision.
Your character will never interact with FaxBot, either in KoLmafia or Kol itself. Your decision forces that consequence; you CANNOT interact with it. If your character tries to open KoLmafia's Chat Manager, its first action is to look at the Altar of Literacy and simply bail if you can't go to chat.

There is no code anywhere inside KoLmafia to complete the Altar's quest, so there is nothing that KoLmafia can do EXCEPT "respect your decision."
 

fronobulax

Developer
Staff member
Your character will never interact with FaxBot, either in KoLmafia or Kol itself. Your decision forces that consequence; you CANNOT interact with it.

Understood and accepted. The phrase "code for forcing the player into chat" suggested opportunities for the creator of such code to introduce undesired or unexpected behavior if they failed to account for the possibility. Since such code does not exist and is unlikely to exist the point is moot.
 

Banana Lord

Member
Could I do it with visit_url and contains_text? That is, could I use those functions to see if the character has a) been to the altar and b) is in chat?

EDIT: It'd be easy to check the quest log to determine the character's literacy status, so I guess the real question is, as Veracity said, to work out a way of seeing if the player is in chat or not. Is there a way to grab the html from the chat pane? If it contains some predictable string ("Trivial Updates" for example) it could be deduced that the player is not in chat, otherwise they are. Veracity's probably been over all this, but it can't hurt to try :).
 
Last edited:

Grotfang

Developer
It is almost certainly true that I don't understand the guts of the chat system well enough to deal with this. Perhaps Grotfang - our "chat guts" expert - would care to comment.

Sorry it's taken me so long to get around to this. I had my last final today, so have finally had some time to get to things.

I don't think I have the expertise to produce an infallible way of determining whether we are in chat or not, unfortunately. Chat messages either come in through mafia hitting newchatmessages.php directly via the ChatPoller when our internal chat is used, or (and this is the catch) the relay browser sending requests. They are dealt with separately -- RelayRequest.java [1439] handleChat() is the function for how we handle the relay messages, while ChatPoller [63] run() is how we handle it internally.

One method (a bit of a hack) would be to have an internal boolean that is true if the user opens mafia chat or accesses lchat.php for the first time. However, it would be prone to error, as closing the relay browser wouldn't (I don't think) be able to turn it to false, despite closing chat.

What I could do is make the altar check simpler (only hitting chatlaunch.php if we haven't previously found it to be completed) and separate it off as a function so it can be used elsewhere. Could the Faxbot request check if the ChatManager is running and initialize it if not, remembering to reset it at the end if needed? Could we then do something with the faxbot messages received? Chat could be made to check to see if faxbot is being requested and send those message somewhere to be accessed when they arrive. It's convoluted, but I can't see a simple method of doing it. I think it has to be at the point of receipt rather than separating the requests.
 

Veracity

Developer
Staff member
Sorry it's taken me so long to get around to this. I had my last final today, so have finally had some time to get to things.
No problem. Thanks for the attention now, though. :)

I don't think I have the expertise to produce an infallible way of determining whether we are in chat or not, unfortunately. Chat messages either come in through mafia hitting newchatmessages.php directly via the ChatPoller when our internal chat is used, or (and this is the catch) the relay browser sending requests. They are dealt with separately -- RelayRequest.java [1439] handleChat() is the function for how we handle the relay messages, while ChatPoller [63] run() is how we handle it internally.
What prompts the relay browser to send a chat request? Yes, the user typing something will submit a message, but what prompts it to poll to get incoming messages? Is it Javascript running in the chat frame, or something?

We could detect when the user opened lchat.php, since we see that being submitted, but they can close it - by closing the browser window, if nothing else - undetectably, I think.

One method (a bit of a hack) would be to have an internal boolean that is true if the user opens mafia chat or accesses lchat.php for the first time. However, it would be prone to error, as closing the relay browser wouldn't (I don't think) be able to turn it to false, despite closing chat.
...and I typed the above before reading this. Heh.

What I could do is make the altar check simpler (only hitting chatlaunch.php if we haven't previously found it to be completed) and separate it off as a function so it can be used elsewhere.
That would be useful, anyway. Have a KoLCharacter.canChat(), say, which accesses a reset-upon-login variable. Note that when we log in, we access all pages of the Quest Log - and the altar of literacy is a miscellaneous accomplishment. The only reason for actually looking at the altar is that we don't detect when you complete it in a session.

Frono would appreciate it if scripts could call an ASH can_chat() function and not bother his illiterate character. Perhaps we could call it is_illiterate(). :)

Could the Faxbot request check if the ChatManager is running and initialize it if not, remembering to reset it at the end if needed?
Isn't ChatManager intimately connected to the Chat Frame? Is it possible to run ChatManager without LoathingChat being open?

I was concerned about starting chat - and appearing in a chat channel and accepting messages until FaxBot writes to you - and then simply discarding the other messages. But, you know, if you weren't in chat, you obviously didn't care about those messages, anyway, so that shouldn't be a problem.

Could we then do something with the faxbot messages received? Chat could be made to check to see if faxbot is being requested and send those message somewhere to be accessed when they arrive. It's convoluted, but I can't see a simple method of doing it. I think it has to be at the point of receipt rather than separating the requests.
We already do this. The message is stored in ChatManager.faxbotMessage. It's a kludge, but it works. Perhaps "convoluted" = "kludge"? :)

I like the idea of simplifying the altar of literacy check, reading it from the quest log and setting a flag, detecting when you become literate and setting a flag, and having ChatManager look at that flag rather than hitting the server to look at the Altar of Literacy.

I like the idea of starting ChatManager (if not running), doing Fax work, and stopping it (if not previously running).

I like the idea of having a mode of operation for ChatManger that does not require the Loathing Chat frame to be open.
 

Grotfang

Developer
I like the idea of simplifying the altar of literacy check, reading it from the quest log and setting a flag, detecting when you become literate and setting a flag, and having ChatManager look at that flag rather than hitting the server to look at the Altar of Literacy.

I like the idea of starting ChatManager (if not running), doing Fax work, and stopping it (if not previously running).

I like the idea of having a mode of operation for ChatManger that does not require the Loathing Chat frame to be open.

I'll get on it! :)
 

fronobulax

Developer
Staff member
Frono would appreciate it if scripts could call an ASH can_chat() function and not bother his illiterate character. Perhaps we could call it is_illiterate(). :)

*snicker*

I remember things that didn't happen, but I seem to recall that when KoL added chat commands there was a version of KoLmafia that did not work with the character. KoLmafia changed to only use the chat commands rather than do things "the old way" when chat was not possible. See this and perhaps this for some of the background.
 

Veracity

Developer
Staff member
I like the idea of simplifying the altar of literacy check, reading it from the quest log and setting a flag, detecting when you become literate and setting a flag, and having ChatManager look at that flag rather than hitting the server to look at the Altar of Literacy.

I just did some of this. Not the Quest Log, yet (although that should be trivial), but I added an AltarOfLiteracyRequest to handle visiting the altar and noticing what it says. That happens even if you visit in the Relay Browser, so, if you complete the Ghost's challenge in the Relay Browser, we should recognize it and immediately tell Chat Manager that you are good to go. Untested.

Chat Manager hits the Altar - once - now, when you initialize it. Checking the Quest Log looks like a one line fix; we already have a flag and a function there, called QuestLogRequest.isChatAvailable(). Huh.
 
Top