Skip to content

Instantly share code, notes, and snippets.

@kmnk
Created January 5, 2018 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kmnk/69f594df1437ef4a9f8495994827c2fb to your computer and use it in GitHub Desktop.
Save kmnk/69f594df1437ef4a9f8495994827c2fb to your computer and use it in GitHub Desktop.
TwitterKit for Unity API test
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
public class SampleBehaviour : MonoBehaviour
{
[SerializeField]
InputField messageInput;
[SerializeField]
Button postButton;
static readonly string Uri = "https://api.twitter.com/1.1/statuses/update.json";
static readonly string OauthVersion = "1.0";
static readonly string SignatureMethod = "HMAC-SHA1";
static readonly string RequestMethod = "POST";
static readonly System.Random Random = new System.Random();
static readonly string[] OAuathAuthorizationHeaderParameters
= new string[]
{
"oauth_consumer_key",
"oauth_token",
"oauth_signature_method",
"oauth_signature",
"oauth_timestamp",
"oauth_nonce",
"oauth_version",
"oauth_verifier",
};
Dictionary<string, string> headerParameters = null;
public Dictionary<string, string> CreateHeaderParameters(TwitterKit.Unity.TwitterSession session)
{
headerParameters = new Dictionary<string, string>()
{
{ "oauth_consumer_key", TwitterKit.Unity.Settings.TwitterSettings.ConsumerKey },
{ "oauth_nonce", Random.Next(123400, int.MaxValue).ToString("X") },
{ "oauth_signature_method", SignatureMethod },
{ "oauth_timestamp", System.Convert.ToInt64(System.DateTime.UtcNow.Subtract(new System.DateTime(1970, 1, 1)).TotalSeconds).ToString() },
{ "oauth_token", session.authToken.token },
{ "oauth_version", OauthVersion },
};
return headerParameters;
}
void Awake()
{
}
void Start()
{
postButton.onClick.AddListener(PostMessage);
TwitterKit.Unity.Twitter.Init();
}
public void PostMessage()
{
TwitterKit.Unity.Twitter.LogIn(
session => UpdateStatuses(session),
error => UnityEngine.Debug.LogError(error)
);
}
void UpdateStatuses(TwitterKit.Unity.TwitterSession session)
{
var message = messageInput.text;
var headerParameters = CreateHeaderParameters(session);
var parameters = new Dictionary<string, string>()
{
{ "status", message },
};
headerParameters.Add(
"oauth_signature",
GenerateSignature(RequestMethod, Uri, parameters)
);
WWWForm form = new WWWForm();
form.AddField("status", message);
var headers = form.headers;
headers.Add("Authorization", "OAuth " + string.Join(", ",
headerParameters
.OrderBy(kvp => kvp.Key)
.ThenBy(kvp => kvp.Value)
.Select(p => string.Format("{0}=\"{1}\"", EscapeRfc3986(p.Key), EscapeRfc3986(p.Value)))
.ToArray()
));
StartCoroutine(Post(Uri, form, headers));
}
System.Collections.IEnumerator Post(string uri, WWWForm form, Dictionary<string, string> headers)
{
using (WWW www = new WWW(uri, form.data, headers))
{
yield return www;
if (www.error != null)
{
Debug.Log(www.error);
Debug.Log(www.text);
}
else
{
Debug.Log(www.text);
}
}
}
string GenerateSignature(
string method,
string uri,
Dictionary<string, string> parameters
)
{
var p = headerParameters
.Concat(parameters)
.ToDictionary(x => x.Key, x => x.Value);
var key = string.Format("{0}&{1}",
EscapeRfc3986(TwitterKit.Unity.Settings.TwitterSettings.ConsumerSecret),
EscapeRfc3986(TwitterKit.Unity.Twitter.Session.authToken.secret)
);
var text = string.Format("{0}&{1}&{2}",
method.ToUpper(),
EscapeRfc3986(uri),
EscapeRfc3986(NormalizeParametersForTwitter(p))
);
var hmacsha1 = new HMACSHA1(Encoding.ASCII.GetBytes(key));
byte[] signatureBytes = hmacsha1.ComputeHash(Encoding.ASCII.GetBytes(text));
return System.Convert.ToBase64String(signatureBytes);
}
static string NormalizeParametersForTwitter(Dictionary<string, string> parameters)
{
var sortedParameters
= parameters
.Select(kvp =>
{
if (OAuathAuthorizationHeaderParameters.Contains(kvp.Key))
{
return new KeyValuePair<string, string>(EscapeRfc3986(kvp.Key), EscapeRfc3986(kvp.Value));
}
else
{
// Twitter の場合 OAuth のパラメーター以外のEscapeでは一部仕様と変える
return new KeyValuePair<string, string>(EscapeForTwitter(kvp.Key), EscapeForTwitter(kvp.Value));
}
})
.OrderBy(kvp => kvp.Key)
.ThenBy(kvp => kvp.Value);
return string.Join("&",
sortedParameters.Select(kvp => string.Format("{0}={1}", kvp.Key, kvp.Value)).ToArray()
);
}
static string NormalizeParameters(Dictionary<string, string> parameters)
{
var sortedParameters
= parameters
.Select(kvp => new KeyValuePair<string, string>(EscapeRfc3986(kvp.Key), EscapeRfc3986(kvp.Value)))
.OrderBy(kvp => kvp.Key)
.ThenBy(kvp => kvp.Value);
return string.Join("&",
sortedParameters.Select(kvp => string.Format("{0}={1}", kvp.Key, kvp.Value)).ToArray()
);
}
static string EscapeRfc3986(string val)
{
return System.Uri.EscapeDataString(val)
.Replace("!", "%21")
.Replace("'", "%27")
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("*", "%2A");
}
static string EscapeForTwitter(string val)
{
return System.Uri.EscapeDataString(val)
.Replace("!", "%21")
.Replace("'", "%27");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment