2016年5月3日 星期二

skype api,用C#發送skype訊息(附上主要Source code)

智慧型手機越來越方便,有些事情想透過skype 發送訊息通知我自己,
需求:一隻監控遊戲的程式,有什麼特別的事情時,就可以發送skype訊息到我的手機。
可是不久前skype 竟然把舊的api 禁止了,所以無法再透過dll 發送訊息。

這時候skype 推出了 web版!
一開始想透過 WebBrowser 載入 此網頁,並透過注入JS的方式達到傳送訊息。(這是可行的。)

但是不太人性化,如果能更簡單就好了。

所以往另一個方向去做了研究。

Post !

研究過後,Skype 給我的感覺大概像這樣




一個使用者發送了一條訊息給Server,而Server 會通知另一個User 要接收這條訊息。
也就是說,你所傳的所有訊息,在Server 上都有一份紀錄。。。










知道大概的流程之後,接下來就是如何實作這段橋梁,讓我們透過程式做到想做的。


透過 HttpWebRequest  這個類別,建立一個 Request 然後發送我要的訊息,給Skype Server

那要傳什麼呢?

其實你只要透過 Chrome 的F12  觀察Skype Web版就知道 他發出了多少的要求給server,
而我們要做的只是 模擬同樣的要求即可。

觀察結果我們需要這兩個認證碼
1.SkypeToken         →透過輸入帳號密碼取得的認證碼
2.RegistrationToken→如果要發送訊息,必須使用SkypeToken 換取這個RegistrationToken才能發送。

就像skype網頁一樣
1.輸入帳號密碼並取得SkypeToken
2.開始使用Skype (SkypeToken換取RegistrationToken)
3.選取使用者
4.發送訊息



附上寫好的Sample

https://drive.google.com/open?id=0B1XxIr6Ve-glc1lhN19fbjdzVGs


ps. 參考來源 https://github.com/Mrmaxmeier/web_skype4py/blob/master/main.py


麻煩請先學習 Chrome 的F12 開發人員工具
http://wayneprogramcity.blogspot.tw/2016/06/chrome.html#more
簡單的說就是去登入網頁版的Skype,並模擬他所需要的資料,這部分麻煩自行學習,如何透過Chrome 的 (F12)開發人員工具獲得你所需要的資料。


主要的Source code :
 private string 取得SkypeToken(string 帳號, string 密碼)
        {
            HiddenObj obj = 取得HiddenObj();
            string Url = @"https://login.skype.com/login?client_id=578134&redirect_uri=https%3A%2F%2Fweb.skype.com&intsrc=client-_-webapp-_-production-_-go-signin";
            HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
            request.Method = "POST";    // 方法 
            request.KeepAlive = false;
            string postData = "";
            postData += @"username=" + 帳號;
            postData += @"&password=" + 密碼;
            postData += @"&timezone_field=" + obj.timezone_field;
            postData += @"&pie=" + obj.pie;
            postData += @"&etm=" + obj.etm;
            postData += @"&js_time=" + DateTime.Now.Ticks;
            postData += @"&client_id=" + @"578134";
            postData += @"&redirect_uri=" + @"https://web.skype.com/";
            postData += @"&intsrc=" + @"client-_-webapp-_-production-_-go-signin";

            byte[] bs = Encoding.UTF8.GetBytes(postData);
            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
            }
            using (WebResponse response = request.GetResponse())
            {
                StreamReader sr = new StreamReader(response.GetResponseStream());
                string 要解析的字串 = sr.ReadToEnd();
                sr.Close();

                string skypetokenRegex = @"=""skypetoken"" value="".*?""";
                string skypetoken = "";
                Regex.Replace(要解析的字串, skypetokenRegex,
                                 (Match 這個) =>
                                 {
                                     skypetoken = 這個.Value.Substring(21, 這個.Value.Length - 22);
                                     return "";
                                 }
                                 );
                if (skypetoken != "")
                {
                    return "skypetoken=" + skypetoken;
                }
                else
                {
                    throw new Exception("無法取得SkypeToken。" + 要解析的字串);
                }            

            }

        }

  private class HiddenObj
        {
            public string timezone_field { getset; }
            public string pie { getset; }
            public string etm { getset; }
        }




 private string 取得registrationToken(string skypetoken)
        {
            string Url = @"https://client-s.gateway.messenger.live.com/v1/users/ME/endpoints";

            HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
            request.Method = "POST";     
            request.UserAgent = @"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0";
            request.Accept = @"*/*";
            request.Headers.Add("Accept-Language""zh-tw,zh;q=0.8,en-us;q=0.5,en;q=0.3");
            request.Headers.Add("Accept-Encoding""gzip, deflate");
            request.Headers.Add("ClientInfo"@"os=Windows; osVer=8.1; proc=Win32; lcid=en-us; deviceType=1; country=n/a; clientName=skype.com; clientVer=908/1.9.0.232//skype.com");
            request.Headers.Add("Cache-Control"@"no-cache, no-store, must-revalidate");
            request.Headers.Add("Pragma""no-cache");
            request.Headers.Add("Expires""0");
            request.Headers.Add("BehaviorOverride"@"redirectAs404");
            request.Headers.Add("Authentication", skypetoken);
            request.ContentType = @"application/json; charset=UTF-8";
            request.Referer = @"https://web.skype.com/zh-Hant/";
            request.Headers.Add("Origin"@"https://web.skype.com");
            request.KeepAlive = false;


            Dictionary<stringobject> obj = new Dictionary<stringobject>();

            string param = JsonConvert.SerializeObject(obj);
            byte[] bs = Encoding.UTF8.GetBytes(param);
            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
            }

            using (WebResponse response = request.GetResponse())
            {
                return response.Headers["Set-RegistrationToken"];
            }

        }


 private void 傳送訊息(string RegistrationToken, string 接收者, string 訊息)
        {
            string Url = @"https://client-s.gateway.messenger.live.com/v1/users/ME/conversations/" + 接收者 + @"/messages";

            HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
            request.Method = "POST";    // 方法 
            request.UserAgent = @"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0";
            request.Accept = @"application/json, text/javascript";
            request.Headers.Add("Accept-Language""zh-tw,zh;q=0.8,en-us;q=0.5,en;q=0.3");
            request.Headers.Add("Accept-Encoding""gzip, deflate");
            request.Headers.Add("ClientInfo"@"os=Windows; osVer=8.1; proc=Win32; lcid=en-us; deviceType=1; country=n/a; clientName=skype.com; clientVer=908/1.9.0.232//skype.com");
            request.Headers.Add("Cache-Control"@"no-cache, no-store, must-revalidate");
            request.Headers.Add("Pragma""no-cache");
            request.Headers.Add("Expires""0"); 
            request.Headers.Add("BehaviorOverride"@"redirectAs404");
            request.Headers.Add("RegistrationToken", RegistrationToken);
            request.ContentType = @"application/json; charset=UTF-8";
            request.Referer = @"https://web.skype.com/zh-Hant/";
            request.Headers.Add("Origin"@"https://web.skype.com");
            request.KeepAlive = true;


            Dictionary<stringobject> obj = new Dictionary<stringobject>();
            obj.Add("content", 訊息);
            obj.Add("messagetype""RichText");
            obj.Add("contenttype""text");
            obj.Add("clientmessageid"DateTime.Now.Ticks);
            string param = JsonConvert.SerializeObject(obj);
            byte[] bs = Encoding.UTF8.GetBytes(param);
            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
            }

            using (WebResponse response = request.GetResponse())
            {

            }
        }


  private List<ComboboxItem取得使用者(string 使用者帳號, string SkypeToken)
        {
            string Url = @"https://contacts.skype.com/contacts/v1/users/" + 使用者帳號.ToLower() + @"/contacts/";

            string skypetoken = SkypeToken.Substring(11, SkypeToken.Length - 11);


            HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
            request.Method = "GET";    // 方法  
            request.Headers.Add("X-Skypetoken", skypetoken);
            List<ComboboxItem> itemlist = new List<ComboboxItem>();

            using (WebResponse response = request.GetResponse())
            {
                StreamReader sr = new StreamReader(response.GetResponseStream());
                string 要解析的字串 = sr.ReadToEnd();
                sr.Close();

                Newtonsoft.Json.Linq.JObject jo = Newtonsoft.Json.Linq.JObject.Parse(要解析的字串);

                for (int i = 0; i < jo.Value<Newtonsoft.Json.Linq.JArray>("contacts").Count; i++)
                {
                    if (jo.Value<Newtonsoft.Json.Linq.JArray>("contacts")[i].Value<string>("id") == "echo123")
                    {
                        continue;
                    }
                    ComboboxItem item = new ComboboxItem(
                          jo.Value<Newtonsoft.Json.Linq.JArray>("contacts")[i].Value<string>("display_name") + jo.Value<Newtonsoft.Json.Linq.JArray>("contacts")[i].Value<string>("id"),
                               "8:" + jo.Value<Newtonsoft.Json.Linq.JArray>("contacts")[i].Value<string>("id")
                          );
                    itemlist.Add(item);
                }
            }
            return itemlist;
        }
         

        public class ComboboxItem
        {
            public string Text { getset; }
            public object Value { getset; }

            public ComboboxItem(string Itemtext, string Itemvalue)
            {
                this.Text = Itemtext;
                this.Value = Itemvalue;
            }

            public override string ToString()
            {
                return Text;
            }
        }


 private HiddenObj 取得HiddenObj()
        {
            HiddenObj obj = new HiddenObj();

            string Url = @"https://login.skype.com/login";

            HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
            request.Method = "GET";    // 方法  

            using (WebResponse response = request.GetResponse())
            {

                StreamReader sr = new StreamReader(response.GetResponseStream());
                string 要解析的字串 = sr.ReadToEnd();
                sr.Close();

                string pieRegex = @"=""pie"" value="".*?""";
                string etmRegex = @"=""etm"" value="".*?""";
                string pie = "";
                string etm = "";
                Regex.Replace(要解析的字串, pieRegex,
                                 (Match 這個) =>
                                 {
                                     pie = 這個.Value.Substring(14, 這個.Value.Length - 15);
                                     return "";
                                 }
                                 );
                Regex.Replace(要解析的字串, etmRegex,
                                (Match 這個) =>
                                {
                                    etm = 這個.Value.Substring(14, 這個.Value.Length - 15);
                                    return "";
                                }
                                );

                obj.pie = pie;
                obj.etm = etm;
            }

            obj.timezone_field = @"+08|00";

            return obj;
        }








1 則留言:

  1. titanium dive knife - Stainless Steel & Iron Cloth | TITanium
    Stainless Steel & Iron Cloth apple watch titanium is made of steel, with a cast iron mens wedding bands titanium core that is suitable oakley titanium glasses for corrosion in stainless steel. It is made with two $47.99 titanium hair trimmer · ‎In titanium watch band stock

    回覆刪除