Writing a Skype listener using skpy

I implemented a Skype listener service that listens to messages posted on our common Skype channels. The Skype listener is written using an excellent Python module skpy. This listener serves as a building block for a few AI-based internal applications. This post outlines the implementation details. I hope it helps companies that still use Skype as their instant messaging tool.

Background

You can safely skip this section. I wrote this section mostly for myself and partly for my colleagues. I am not happy with Qxf2’s technical footprint. We struggle to think properly about testing applications that are loosely coupled micro-services with asynchronous inputs, applications that live on the AWS tech stack, applications with AI capabilities, etc. All internal introspection always leads to the same problem – we lack the exposure to such applications on a daily basis!

To fix this problem, we have been developing several such applications for internal use. Qxf2 employees can use these applications, get familiar with testing them and develop better mental models on how to test such applications when they encounter them at a client. The Skype listener is a good building block to produce the raw material (human-generated content) that AI applications can consume. You will see follow up posts outlining the apps we build and detailed notes on how we test them.


Skype listener implementation

This post will cover the following sections:
1. Architecture
2. Skype listener code
3. Post received messages to an SNS
4. Create a Unix service for our Skype listener
5. Check if the messages are being relayed
6. The full code

For those in a hurry, section 6 has a link to the entire code base. Please use that. Note: I know my code quality can be improved. But given I’m not a professional developer, I thought I would share my code as it is and let developers improve upon it.

 

1. Architecture

The Skype listener (as of Sep 2020) looks like the image below:

Skype listener
Skype Listener Architecture

The Skype listener is a Python script. A Unix service wraps around the Python script to make sure it is always running. The Python script listens to any new message event on Skype. It extracts the message, user and channel from the event and posts it to an SNS

2. Skype listener code

The Skype listener code was easy to write thanks to the Python module SkPy. It looks something like this:

from skpy import SkypeEventLoop, SkypeNewMessageEvent
import skype_credentials as skype_creds
 
class SkypeListener(SkypeEventLoop):
    "Listen to a channel continuously"
    def __init__(self):
        username = skype_creds.USERNAME
        password = skype_creds.PASSWORD
        token_file = '.tokens-app'
        super(SkypeListener, self).__init__(username, password, token_file)
 
    def onEvent(self, event):
        if isinstance(event, SkypeNewMessageEvent):
            default = "Skype listener: Investigate if you see this."
            message = {"user_id":event.msg.userId,
                    "chat_id":event.msg.chatId,
                    "msg":event.msg.content}
            print(message)
 
#----START OF SCRIPT
if __name__ == "__main__":
    big_bro = SkypeListener()
    big_bro.loop()

We create a class based off SkypeEventLoop. We override the onEvent method to check for a SkypeNewMessageEvent. When we see a SkypeNewMessageEvent we extract the user, channel and the message and print them. Finally, we have this running in a loop.

As an aside, make sure you are logging in with a token file. Skype does not like multiple logins from different machines and often makes you fill out a captcha making programmatically logging into Skype a bit of a hassle.

3. Post received messages to an SNS

I expect several of our applications to use the data captured by our listener. Rather than having many such listeners running everywhere, I decided to simply post these messages on to an SNS topic. Any application that wishes to use the Skype Listener output can simply subscribe to that SNS topic. I figured that this kills two birds with one stone. One, this works well. Two, it increases our testers’ exposure to applications that live on the AWS tech stack.

To post to an SNS topic, we modify our above script in a couple of ways. We modify __init__() to create SNS boto3 client. We can do that by adding the following lines to __init__()

self.sns = boto3.client('sns',
                aws_access_key_id=aws_creds.ACCESS_KEY,
                aws_secret_access_key=aws_creds.SECRET_KEY,
                region_name=aws_creds.AWS_REGION)

Then, instead of printing what we capture in onEvent() let us publish it to the SNS topic by replacing the print statement with the following lines of code to onEvent()

send_message = json.dumps({"default":json.dumps(message)})
response = self.sns.publish(TopicArn = aws_creds.SNS_TOPIC,
                    Message = send_message,
                    MessageStructure='json')
4. Create a Unix service for our Skype listener

I put the code on an EC2 (Ubuntu) instance. After verifying that the code worked, I created a Unix service file for our listener. The most basic version of my service file looks like this:

[Unit]
Description=The Skype listener service
 
[Service]
user=your_user
WorkingDirectory=path_of_py_file
VIRTUAL_ENV=path_to_bin_of_virtual_env
Environment=PATH=$VIRTUAL_ENV:$PATH
ExecStart=path_to_bin_of_virtual_env/python qxf2_skype_listener.py
Restart=on-failure
 
[Install]
WantedBy=multi-user.target

If you are completely new to creating a service on Unix, follow the steps here and use the code above. But please understand that this is just a quick and dirty way to implement your first service. A well implemented service will take a bit more effort and I doubt I can do justice to it in this post.

5. Check if the messages are being relayed

Once the service was ready and running, I subscribed an SQS queue to my SNS topic. I posted a message on one of the channels that the Skype listener user was present on and checked my SQS queue for messages.

Skype listener SQS message confirmation
We received the right message!

Voila! The most basic check passed.

6. The full code

The entire code can be found on this GitHub gist: https://gist.github.com/qxf2/6cb146a9b61a699aa5a0e37b08951f7f


This is just one of the several posts we have lined up about the applications we are using to hone our testing skills. Stay tuned to see how this Skype listener is used to verify the working of our daily messaging application.


One thought on “%1$s”

Leave a Reply

Your email address will not be published. Required fields are marked *