标签归档:聊天

使用SkPy创建Skype群组会话

每一次产品发布或故障支持,都需要将相关人员拉到同一个Skype群聊会话,以便讨论、测试、支持。如果每次都需要手动做这些动作是比较累;如果复用已有会话,又会影响本次无关人员。于是有了这样一个需求:在Web后台定义相关组员及关联关系,在Web前台点击即可以创建或加入相关会话。这要求提供一个HTTP的接口,接收会话人员及主题,创建聊天室。搜了一圈,发现SkPy这个库最简单,支持创建会话,发送/接收消息,事件监听等等,其他的库要么功能太简单不满足,要么需要安装Skype客户端,要么不支持最新(live)注册的Skype用户,决定使用这个来开发。由于只是一个简单的HTTP接口,决定使用web.py
首先安装SkPy和web.py,注意如果是CentOS 6,Python certifi版本只能是2015.04.28,否则会报错

sudo pip install SkPy
sudo pip install web.py
#you need to do follow steps on Centos 6.x, to make requests works
sudo pip uninstall -y certifi
sudo pip install certifi==2015.04.28

web.py只要单个文件就可以工作了,创建chat.py如下

import web
from skpy import Skype
from skpy import SkypeAuthException
import logging
import hashlib
import os.path
import io
 
 
urls = (
    '/', 'index',
    '/chat', 'chat'
)
'''
try:
    import http.client as http_client
except ImportError:
    # Python 2
    import httplib as http_client
http_client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
'''
 
 
class SkypeService:
    def __init__(self):
        self.username = '<skype account>'
        self.password = '<skype password>'
        self.token_file="/tmp/tokens-app"
        self.skype = Skype(connect=False)
        self.skype.conn.setTokenFile(self.getTokenFile())
 
    def getTokenFile(self):
        if not os.path.isfile(self.token_file):
            with io.open(self.token_file, 'a') as file:
                file.close()
        return self.token_file
 
    def connect(self):
        try:
            self.skype.conn.readToken()
        except SkypeAuthException:
            self.skype.conn.setUserPwd(self.username, self.password)
            self.skype.conn.getSkypeToken()
 
    def creatChatRoom(self, member, topic):
        ch = self.skype.chats.create(members=member)
        ch.setTopic(topic)
        return ch
 
    def getShardLink(self, channel):
        return channel.joinUrl
 
    def createAndGetSharedLink(self, member, topic):
        self.connect()
        ch = self.creatChatRoom(member, topic)
        # ch.sendMsg("welcome")
        # return {"id": ch.id, "url": self.getShardLink(ch)}
        return self.getShardLink(ch)

    def getConversationIdByUrl(self, url):
        id = self.skype.chats.urlToIds(url)["Resource"]
        return id
    
    def getChatroomByUrl(self, url):
        id = self.getConversationIdByUrl(url)
        ch = getChatroomByConversationId(id)
        return ch

    def getChatroomByConversationId(self, id):
        ch = self.skype.chats.chat(id)
        return ch

    def sendMessageByConversationId(self, id, message):
        ch = self.getChatroomByConversationId(id)
        return ch.sendMsg("Hello world!")

    def getMessagesByConversationId(self, id):
        ch = self.getChatroomByConversationId(id)
        return ch.getMsgs()
 
 
class Storage:
    def __init__(self):
        self.cache_path = '/tmp/'
 
    def set(self, key, value):
        cache_file = self.cache_path + key
        try:
            with io.open(cache_file, 'w') as file:
                file.write(value)
        except:
            raise Exception('file: {0} write failure'.format(cache_file))
        return True
 
    def get(self, key):
        cache_file = self.cache_path + key
        try:
            with io.open(cache_file) as file:
                value = file.read()
        except:
            raise Exception('file: {0} not exists'.format(cache_file))
        return value
 
 
class index:
    def GET(self):
        return "Hello, world!"
 
 
class chat:
    def GET(self):
        url = web.ctx.home + web.ctx.path + web.ctx.query
        key = hashlib.md5(url).hexdigest()
        storage = Storage()
        try:
            join_url = storage.get(key)
        except:
            param = web.input()
            users = param.user
            member = tuple(users.split(','))
            topic = param.topic
            sk = SkypeService()
            join_url = sk.createAndGetSharedLink(member, topic)
            storage.set(key, join_url)
 
        return join_url
 
 
if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

然后运行chat.py,默认监听8080端口

python chat.py [port]

在浏览器访问,

http://127.0.0.1:8080/chat?user=user1,user2&topic=19.5Release

即可以创建一个聊天会话,并且返回join url,点击这个URL会尝试打开Skype应用。注意这个会话默认是开放的,允许任何人加入

https://join.skype.com/LRRUuan7kNH3

去掉logging注释,可以看到API调用的过程,作者也作了详细的协议文档,可以看出登录流程相当复杂,也可以根据这个开放出其他语言的SDK。
注意这个bot运行的是个人账号,使用的是与web.skype.com相同的HTTP API,最好是在Skype 开发者平台上注册,官方也提供了NodeJS的SDK
之前许多QQ机器人使用都是Web QQ的接口,目前已关闭。同时官方的API,发现并没有创建任意群聊的API。对比国外软件,国内的API真的是不开放。国外公司甚至有专门的API Platform团队,负责API开发开放,以及与第三方平台的集成。

参考连接:
SkPy