305 lines
7.6 KiB
Go
305 lines
7.6 KiB
Go
// matrix-skype - A Matrix-WhatsApp puppeting bridge.
|
|
// Copyright (C) 2019 Tulir Asokan
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package skypeExt
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/kelaresg/go-skypeapi"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
OldUserSuffix = ""
|
|
NewUserSuffix = "@s.skype.net"
|
|
GroupSuffix = "@thread.skype"
|
|
)
|
|
|
|
type ExtendedConn struct {
|
|
*skype.Conn
|
|
|
|
handlers []skype.Handler
|
|
}
|
|
|
|
func ExtendConn(conn *skype.Conn) *ExtendedConn {
|
|
ext := &ExtendedConn{
|
|
Conn: conn,
|
|
}
|
|
ext.Conn.AddHandler(ext)
|
|
return ext
|
|
}
|
|
|
|
func (ext *ExtendedConn) AddHandler(handler skype.Handler) {
|
|
ext.Conn.AddHandler(handler)
|
|
ext.handlers = append(ext.handlers, handler)
|
|
}
|
|
|
|
|
|
func (ext *ExtendedConn) RemoveHandler(handler skype.Handler) bool {
|
|
ext.Conn.RemoveHandler(handler)
|
|
for i, v := range ext.handlers {
|
|
if v == handler {
|
|
ext.handlers = append(ext.handlers[:i], ext.handlers[i+1:]...)
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (ext *ExtendedConn) RemoveHandlers() {
|
|
ext.Conn.RemoveHandlers()
|
|
ext.handlers = make([]skype.Handler, 0)
|
|
}
|
|
|
|
func (ext *ExtendedConn) shouldCallSynchronously(handler skype.Handler) bool {
|
|
//sh, ok := handler.(skype.SyncHandler)
|
|
//return ok && sh.ShouldCallSynchronously()
|
|
return true
|
|
}
|
|
|
|
func (ext *ExtendedConn) ShouldCallSynchronously() bool {
|
|
return true
|
|
}
|
|
|
|
type GroupInfo struct {
|
|
JID string `json:"jid"`
|
|
OwnerJID string `json:"owner"`
|
|
|
|
Name string `json:"subject"`
|
|
NameSetTime int64 `json:"subjectTime"`
|
|
NameSetBy string `json:"subjectOwner"`
|
|
|
|
Topic string `json:"desc"`
|
|
TopicID string `json:"descId"`
|
|
TopicSetAt int64 `json:"descTime"`
|
|
TopicSetBy string `json:"descOwner"`
|
|
|
|
GroupCreated int64 `json:"creation"`
|
|
|
|
Status int16 `json:"status"`
|
|
|
|
Participants []struct {
|
|
JID string `json:"id"`
|
|
IsAdmin bool `json:"isAdmin"`
|
|
IsSuperAdmin bool `json:"isSuperAdmin"`
|
|
} `json:"participants"`
|
|
}
|
|
|
|
func (ext *ExtendedConn) GetGroupMetaData(jid string) (*GroupInfo, error) {
|
|
data, err := ext.Conn.GetConversation(jid)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get group metadata: %v", err)
|
|
}
|
|
//content := <-data
|
|
//info := data
|
|
membersStr := data.ThreadProperties.Members
|
|
var members []string
|
|
if len(membersStr) < 1 {
|
|
resp, _ := ext.Conn.GetConsumptionHorizons(jid)
|
|
for _, con := range resp.ConsumptionHorizons {
|
|
members = append(members, con.Id)
|
|
}
|
|
} else {
|
|
err = json.Unmarshal([]byte(membersStr), &members)
|
|
}
|
|
info := &GroupInfo{}
|
|
fmt.Println()
|
|
fmt.Println("GetGroupMetaData: ", members)
|
|
fmt.Println()
|
|
for _, participant := range members {
|
|
type a struct {
|
|
JID string `json:"id"`
|
|
IsAdmin bool `json:"isAdmin"`
|
|
IsSuperAdmin bool `json:"isSuperAdmin"`
|
|
}
|
|
isSuperAdmin := false
|
|
if "8:" + ext.Conn.UserProfile.Username == participant {
|
|
isSuperAdmin = true
|
|
}
|
|
info.Participants = append(info.Participants, a{
|
|
participant + NewUserSuffix,
|
|
false,
|
|
isSuperAdmin,
|
|
})
|
|
|
|
personId := participant + NewUserSuffix
|
|
if _, ok := ext.Conn.Store.Contacts[personId]; !ok {
|
|
participantArr := strings.Split(participant, "8:")
|
|
if participantArr[1] != "" {
|
|
ext.Conn.NameSearch(participantArr[1])
|
|
}
|
|
}
|
|
}
|
|
info.Topic = data.ThreadProperties.Topic
|
|
info.Name = data.ThreadProperties.Topic
|
|
fmt.Println()
|
|
fmt.Println("GetGroupMetaData:3 ")
|
|
fmt.Println()
|
|
//info.NameSetBy = info.NameSetBy + NewUserSuffix
|
|
//info.TopicSetBy = info.TopicSetBy + NewUserSuffix
|
|
|
|
return info, nil
|
|
}
|
|
|
|
type ProfilePicInfo struct {
|
|
URL string `json:"eurl"`
|
|
Tag string `json:"tag"`
|
|
|
|
Status int16 `json:"status"`
|
|
Authorization string `json:"authorization"`
|
|
}
|
|
|
|
func (ppi *ProfilePicInfo) Download() (io.ReadCloser, error) {
|
|
if ppi.Authorization != "" {
|
|
client := &http.Client{
|
|
Timeout: 20 * time.Second,
|
|
}
|
|
headers := map[string]string{
|
|
"X-Client-Version": "0/0.0.0.0",
|
|
"Authorization": ppi.Authorization, // "skype_token " + Conn.LoginInfo.SkypeToken,
|
|
}
|
|
req, err := http.NewRequest("GET", ppi.URL, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for k, v := range headers {
|
|
req.Header.Set(k, v)
|
|
}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return resp.Body, nil
|
|
}else {
|
|
resp, err := http.Get(ppi.URL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return resp.Body, nil
|
|
}
|
|
|
|
}
|
|
|
|
func (ppi *ProfilePicInfo) DownloadBytes() ([]byte, error) {
|
|
body, err := ppi.Download()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer body.Close()
|
|
data, err := ioutil.ReadAll(body)
|
|
return data, err
|
|
}
|
|
|
|
func (ext *ExtendedConn) GetProfilePicThumb(jid string) (*ProfilePicInfo, error) {
|
|
//data, err := ext.Conn.GetProfilePicThumb(jid)
|
|
//if err != nil {
|
|
// return nil, fmt.Errorf("failed to get avatar: %v", err)
|
|
//}
|
|
//content := <-data
|
|
//info := &ProfilePicInfo{}
|
|
//err = json.Unmarshal([]byte(content), info)
|
|
//if err != nil {
|
|
// return info, fmt.Errorf("failed to unmarshal avatar info: %v", err)
|
|
//}
|
|
//return info, nil
|
|
return nil, nil
|
|
}
|
|
|
|
func (ext *ExtendedConn) HandleGroupInvite(groupJid string, numbers[]string) (err error) {
|
|
var parts []string
|
|
parts = append(parts, numbers...)
|
|
members := skype.Members{}
|
|
members = skype.Members{}
|
|
for _, memberId := range numbers {
|
|
members.Members = append(members.Members, skype.Member{
|
|
Id: "8:"+memberId,
|
|
Role: "Admin",
|
|
})
|
|
}
|
|
err = ext.Conn.AddMember(members, groupJid)
|
|
if err != nil {
|
|
fmt.Printf("%s Handle Invite err", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ext *ExtendedConn) HandleGroupJoin(code string) (err error, codeinfo skype.JoinToConInfo) {
|
|
err, codeinfo = ext.Conn.JoinConByCode(code)
|
|
member := skype.Member{
|
|
Id: "8:"+ext.UserProfile.Username,
|
|
Role: "Admin",
|
|
}
|
|
Members := skype.Members{}
|
|
Members.Members = append(Members.Members, member)
|
|
//cli.AddMember(cli.LoginInfo.LocationHost, cli.LoginInfo.SkypeToken, cli.LoginInfo.RegistrationTokenStr, Members, rsp.Resource)
|
|
err = ext.AddMember(Members, codeinfo.Resource)
|
|
|
|
member2 := skype.Member{
|
|
Id: "8:"+ext.UserProfile.Username,
|
|
Role: "User",
|
|
}
|
|
mewMembers := skype.Members{}
|
|
mewMembers.Members = append(mewMembers.Members, member2)
|
|
err = ext.AddMember( mewMembers, codeinfo.Resource)
|
|
return
|
|
}
|
|
|
|
func (ext *ExtendedConn) HandleGroupShare(groupJid string) (err error, link string) {
|
|
|
|
res, err := ext.Conn.GetConJoinUrl(groupJid)
|
|
if err != nil {
|
|
return err, ""
|
|
}
|
|
link = res.Url
|
|
return
|
|
}
|
|
|
|
|
|
func (ext *ExtendedConn) HandleGroupKick(groupJid string, numbers[]string) (err error) {
|
|
for _, number := range numbers{
|
|
err = ext.Conn.RemoveMember(groupJid, number)
|
|
if err != nil {
|
|
fmt.Printf("%s Handle kick err", err)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (ext *ExtendedConn) HandleGroupCreate(numbers skype.Members) (err error) {
|
|
//var parts []string
|
|
//parts = append(parts, numbers...)
|
|
err = ext.Conn.CreateConversationGroup(numbers)
|
|
//if err != nil {
|
|
// fmt.Printf("%s HandleGroupCreate err", err)
|
|
//}
|
|
return
|
|
}
|
|
|
|
func (ext *ExtendedConn) HandleGroupLeave(groupJid string) (err error) {
|
|
fmt.Println("groyp id", groupJid)
|
|
fmt.Println("ext.UserProfile.Username", ext.UserProfile.Username)
|
|
err = ext.Conn.RemoveMember(groupJid, "8:"+ext.UserProfile.Username)
|
|
if err != nil {
|
|
fmt.Printf("%s HandleGroupLeave err", err)
|
|
}
|
|
return
|
|
}
|