Duplicate Firing of `active chat message received` handler - macos

While Manu G E asked a similar question twice, neither got an adequate answer, and I'm hoping I'll have better luck.
I'm writing an AppleScript to execute a handler when Messages.app receives a message. The script is being saved to ~/Library/Application\ Scripts/com.apple.iChat and is set in the Messages preferences to be the AppleScript handler.
When Messages is the frontmost application and a message is received, the active chat message received handler is fired twice. This doesn't seem to be a problem when Messages is in the background (received messages then fire message received, and that handler only once). I know which handler is fired because the portion that deals with the handlers looks like this:
using terms from application "Messages"
on message received _msg from _sender for _chat with _text_desc
if DEBUG then display dialog "message received"
message_received(_sender)
end message received
on chat room message received _msg from _sender for _chat with _text_desc
if DEBUG then display dialog "chat room message received"
message_received(_sender)
end chat room message received
on active chat message received _msg from _sender for _chat with _text_desc
if DEBUG then display dialog "active chat message received"
message_received(_sender)
end active chat message received
-- More handlers below, mostly like the above or empty
end using terms from
I set a DEBUG property to true and can see which handler gets fired.
I've tried working around this by writing a temporary file (using the UUID of the _sender). The message_received handler checks for the existence of the file and is supposed to do nothing if it's present. But this hasn't worked, even with random delays. I tried extending the length of the random delays, but this brings up errors about the AppleScript running for more than 10 seconds, even when enclosing the code within a with timeout of block.
Regardless of Apple's apparent support for executing AppleScripts in response to Messages events, perhaps I should look at some other mechanism to support this request from the client. I'm open to ideas.

Somehow I managed to find a simple but (very) dirty hack that seems to work for me, but I can't say if it will work on any machine. So "active chat message received" seems to be called twice at the same time, but I noticed something like do shell script "php -r 'echo microtime() >> file.txt'" sometimes reveals slightly different values.
I also use a property as a flag and try to take advantage of that shell execution tiny interval by writing to a file:
echo 0 > ~/Documents/flag.txt
then:
property flag : 0
using terms from application "Messages"
#...
on active chat message received theMessage from theBuddy
set response to false
set the_script to "cat ~/Documents/flag.txt"
set flag to do shell script the_script
do shell script "echo 1 > ~/Documents/flag.txt"
if flag is "0" then
set response to true
else
do shell script "echo 0 > ~/Documents/flag.txt"
end if
if response then
#this should be executed only once
end if
end active chat message received
#...
end using terms from
And voilà. Again I cannot say if that solution works everytime, and explaining why it actually works in my case is way beyond my capabilities right now. Still, I hope it will be useful. Cheers

Related

Trigger/Handle events between programs in different ABAP sessions

I have two programs running in separated sessions. I want to send a event from program A and catch this event in program B.
How can I do that ?
Using class-based events is not really an option, as these cannot be used to communicate between user sessions.
There is a mechanism that you can use to send messages between sessions: ABAP Messaging Channels. You can send anything that is either a text string, a byte string or can be serialised in any of the above.
You will need to create such a message channel using the repository browser SE80 (Create > Connectivity > ABAP Messaging Channel) or with the Eclipse ADT (New > ABAP Messaging Channel Application).
In there, you will have to define:
The message type (text vs binary)
The ABAP programs that are authorised to access the message channel.
The scope of the messages (i.e. do you want to send messages between users? or just for the same user? what about between application servers?)
The message channels work through a publish - subscribe mechanism. You will have to use specialised classes to publish to the channel (inside report A) and to read from the channel (inside report B). In order to wait for a message to arrive once you have subscribed, you can use the statement WAIT FOR MESSAGE CHANNELS.
Example code:
" publishing a message
CAST if_amc_message_producer_text(
cl_amc_channel_manager=>create_message_producer(
i_application_id = 'DEMO_AMC'
i_channel_id = '/demo_text'
i_suppress_echo = abap_true )
)->send( i_message = text_message ).
" subscribing to a channel
DATA(lo_receiver) = NEW message_receiver( ).
cl_amc_channel_manager=>create_message_consumer(
i_application_id = 'DEMO_AMC'
i_channel_id = '/demo_text'
)->start_message_delivery( i_receiver = lo_receiver )
" waiting for a message
WAIT FOR MESSAGING CHANNELS
UNTIL lo_receiver->text_message IS NOT INITIAL
UP TO time SECONDS.
If you want to avoid waiting inside your subscriber report B and to do something else in the meanwhile, then you can wrap the WAIT FOR... statement inside a RFC and call this RFC using the aRFC variant. This would allow you to continue doing stuff inside report B while waiting for an event to happen. When this event happens, the aRFC callback method that you defined inside your report when calling the RFC would be executed.
Inside the RFC, you would simply have the subscription part and the WAIT statement plus an assignment of the message itself to an EXPORTING parameter. In your report, you could have something like:
CALL FUNCTION 'ZMY_AMC_WRAPPER' STARTING NEW TASK 'MY_TASK'
CALLING lo_listener->my_method ON END OF TASK.
" inside your 'listener' class implementation
METHOD my_method.
DATA lv_message TYPE my_message_type.
RECEIVE RESULTS FROM FUNCTION 'ZMY_AMC_WRAPPER'
IMPORTING ev_message = lv_message.
" do something with the lv_message
ENDMETHOD.
You could emulate it by checking in program B if a parameter in SAP memory has changed. program A will set this parameter to send the event. (ie SET/ GET PARAMETER ...). In effect you're polling event in B.
There a a lot of unknown in your desription. For example is the event a one-shot operation or can A send several event ? if so B will have to clear the parameter when done treating the event so that A know it's OK to send a new one (and A will have to wait for the parameter to clear after having set it)...
edited : removed the part about having no messaging in ABAP, since Seban shown i was wrong

How to test when the end of an SMS message has been reached

I am writing an application which acts on commands received via SMS (in Python, but the problem occurs in other languages).
This page on the CMGL command shows the following command and response:
AT+CMGL="ALL"
+CMGL: 1,"REC UNREAD","+31628870634",,"11/01/09,10:26:26+04"
This is text message 1
+CMGL: 2,"REC UNREAD","+31628870634",,"11/01/09,10:26:49+04"
This is text message 2
OK
Most implementations I have looked at look for a valid status such as OK or ERROR to detect the end of the response.
I am trying to find a way to determine the difference between this status code and the end of the message.
Otherwise it would be possible for a malicious sender to send a message of
Hello<CR><LF>OK<CR><LF>+CMGL: 1,(rest of fake message...)
Because I am receiving data on the serial port, there is no clear way to tell when I have reached the end of one message from the GSM board.
Could anyone point me to some information on the best practice here please? Other implementations I have seen do not seem to cover this issue.
The only idea I have had so far (but feels quite messy) is to keep reading until a timeout has been hit. Then check the number of OK / ERROR lines in the message and only accept the last.

Applescript content of incoming iMessage

I need to extract/read the content of an incoming Message received via iMessage. I am having a hard time finding out the right command to extract the info. Could someone point me in the right direction ?
I know I don't have much so far, I am a newbie :(
using terms from application "Messages"
on message received theMessage
return theMessage
end message received
end using terms from
I suggest you to look examples provided in ElCapitain your user Library / Application Scripts / com.apple.iChat, there is "Mix message Case.applescript file which contains syntax for each case of message (received, send, invitation,...)
According to that file, you must add attribute to the "on message received" like :
on message received theMessage from theBuddy for theChat

How Can I Use xmpp4r To Detect The Online/Offline Status Of A Given Jabber ID?

What is the proper xmpp4r way to know if a given contact is online before sending them a message?
Can you post sample xmpp4r code for doing this?
Here is my use case:
If contact online, send :normal message
Else, email contact
Here are things I have working code for:
Send messages of various types
Get a roster/contact list
Register a call back to detect changes in presence
However, I can't find a place that directly addresses a work flow like this:
Loop through each JID in your roster
If jid.is_online? == true, send IM
Else, send email
I've read that you should send a JID a message of type :headline and if that fails, you know the user is offline. In my tests, if the user is ONLINE, they'll receive a message of type headline. This is suboptimal, as users should only receive messages to read, not noise to determine online status.
I've read that on sign on, all of your contacts will bounce a presence status back at you, and that status is the sole indication that they are online - assuming that there isn't a disconnect or presence change you've yet to receive. So you should register a presence call back, record the initial users who ping you back, and then add or remove from the list based on your running roster presence callback.
If this is truly the way to do it:
Can I get some example code of how to collect all the "I'm here" presence confirmations on sign on via xmpp4r?
Why, oh why, was xmpp designed this way and why is this better than offering an "is_online_and_available" method?
So the answer here is adding a message call back and checking inside the block for the type:
m = Message.new(to, body)
cl.send(m)
cl.add_message_callback do |m|
if m.type == :error
puts "type: #{m.type}"
else
puts "not an error"
end
end
This requires threading as you have to be listening for the response.

Windows: How to display a non-blocking Alert/Confirmation window?

I want to realize a simple confirmation/alert box which can be called using a Windows XP/Vista batch script by CLI.
The standard alert box seems to be blocking which means that the whole batch script will stop at the time of the alert window call which is NOT what I want.
If it needs to be coded, please supply an example or documentation. Language can be anything that is compileable without requiring a virtual machine in between.
You can use the msg tool:
Send a message to a user.
MSG {username | sessionname | sessionid | #filename | *}
[/SERVER:servername] [/TIME:seconds] [/V] [/W] [message]
username Identifies the specified username.
sessionname The name of the session.
sessionid The ID of the session.
#filename Identifies a file containing a list of usernames,
sessionnames, and sessionids to send the message to.
* Send message to all sessions on specified server.
/SERVER:servername server to contact (default is current).
/TIME:seconds Time delay to wait for receiver to acknowledge msg.
/V Display information about actions being performed.
/W Wait for response from user, useful with /V.
message Message to send. If none specified, prompts for it
or reads from stdin.
The call
msg * Some text
doesn't block. It also has the nice capability of closing the message box again after a set amount of time if required.
On a side note, though, you shouldn't really use those things. Monologs (like message boxes with exactly an OK button) have an information efficiency of 0 % (cf. Jef Raskin: The Humane Interface. Section 4–3: Measurement of Interface Efficiency or Aza Raskin: Monolog Boxes and Transparent Messages or Aza Raskin: Know When to Stop Designing, Quantitatively).
start MessageBox.vbs
...where MessageBox.vbs contains a call to the MsgBox function.

Resources