diff --git a/examples/TwitterExample/Form1.Designer.cs b/examples/TwitterExample/Form1.Designer.cs
new file mode 100644
index 0000000..c1ae91c
--- /dev/null
+++ b/examples/TwitterExample/Form1.Designer.cs
@@ -0,0 +1,116 @@
+namespace TwitterExample
+{
+ partial class Form1
+ {
+ ///
+ /// Обязательная переменная конструктора.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Освободить все используемые ресурсы.
+ ///
+ /// истинно, если управляемый ресурс должен быть удален; иначе ложно.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Код, автоматически созданный конструктором форм Windows
+
+ ///
+ /// Требуемый метод для поддержки конструктора — не изменяйте
+ /// содержимое этого метода с помощью редактора кода.
+ ///
+ private void InitializeComponent()
+ {
+ this.btnTweet = new System.Windows.Forms.Button();
+ this.Message = new System.Windows.Forms.TextBox();
+ this.btnAddPhoto = new System.Windows.Forms.Button();
+ this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
+ this.btnMore = new System.Windows.Forms.Button();
+ this.UploadedImages = new System.Windows.Forms.FlowLayoutPanel();
+ this.SuspendLayout();
+ //
+ // btnTweet
+ //
+ this.btnTweet.Location = new System.Drawing.Point(367, 66);
+ this.btnTweet.Name = "btnTweet";
+ this.btnTweet.Size = new System.Drawing.Size(75, 23);
+ this.btnTweet.TabIndex = 0;
+ this.btnTweet.Text = "Tweet";
+ this.btnTweet.UseVisualStyleBackColor = true;
+ this.btnTweet.Click += new System.EventHandler(this.btnTweet_Click);
+ //
+ // Message
+ //
+ this.Message.Location = new System.Drawing.Point(12, 12);
+ this.Message.Multiline = true;
+ this.Message.Name = "Message";
+ this.Message.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.Message.Size = new System.Drawing.Size(430, 48);
+ this.Message.TabIndex = 1;
+ //
+ // btnAddPhoto
+ //
+ this.btnAddPhoto.Location = new System.Drawing.Point(12, 66);
+ this.btnAddPhoto.Name = "btnAddPhoto";
+ this.btnAddPhoto.Size = new System.Drawing.Size(75, 23);
+ this.btnAddPhoto.TabIndex = 2;
+ this.btnAddPhoto.Text = "Add photo";
+ this.btnAddPhoto.UseVisualStyleBackColor = true;
+ this.btnAddPhoto.Click += new System.EventHandler(this.btnAddPhoto_Click);
+ //
+ // openFileDialog1
+ //
+ this.openFileDialog1.Filter = "Images (*.jpg;*.png;*.gif;*.bmp) | *.jpg;*.png;*.gif;*.bmp | All files (*.*) | *." +
+ "*";
+ //
+ // btnMore
+ //
+ this.btnMore.Location = new System.Drawing.Point(322, 281);
+ this.btnMore.Name = "btnMore";
+ this.btnMore.Size = new System.Drawing.Size(75, 23);
+ this.btnMore.TabIndex = 3;
+ this.btnMore.UseVisualStyleBackColor = true;
+ //
+ // UploadedImages
+ //
+ this.UploadedImages.Location = new System.Drawing.Point(12, 95);
+ this.UploadedImages.Name = "UploadedImages";
+ this.UploadedImages.Size = new System.Drawing.Size(430, 129);
+ this.UploadedImages.TabIndex = 4;
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(634, 363);
+ this.Controls.Add(this.UploadedImages);
+ this.Controls.Add(this.btnMore);
+ this.Controls.Add(this.btnAddPhoto);
+ this.Controls.Add(this.Message);
+ this.Controls.Add(this.btnTweet);
+ this.Name = "Form1";
+ this.Text = "Form1";
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button btnTweet;
+ private System.Windows.Forms.TextBox Message;
+ private System.Windows.Forms.Button btnAddPhoto;
+ private System.Windows.Forms.OpenFileDialog openFileDialog1;
+ private System.Windows.Forms.Button btnMore;
+ private System.Windows.Forms.FlowLayoutPanel UploadedImages;
+ }
+}
+
diff --git a/examples/TwitterExample/Form1.cs b/examples/TwitterExample/Form1.cs
new file mode 100644
index 0000000..31cf264
--- /dev/null
+++ b/examples/TwitterExample/Form1.cs
@@ -0,0 +1,416 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using Nemiro.OAuth;
+using Nemiro.OAuth.LoginForms;
+
+namespace TwitterExample
+{
+
+ public partial class Form1 : Form
+ {
+
+ private Properties.Settings Settings = Properties.Settings.Default;
+
+ private int MediaUploadChunkSize = (3 * 1024 * 1024); // 3 MB
+
+ public string LastTweetId { get; set; }
+
+ public Form1()
+ {
+ InitializeComponent();
+ }
+
+ private OAuthAuthorization GetAuth()
+ {
+ OAuthAuthorization auth = new OAuthAuthorization();
+ auth.ConsumerKey = this.Settings.ConsumerKey;
+ auth.ConsumerSecret = this.Settings.ConsumerSecret;
+ auth.SignatureMethod = SignatureMethods.HMACSHA1;
+ auth.Token = this.Settings.AccessToken;
+ auth.TokenSecret = this.Settings.TokenSecret;
+
+ return auth;
+ }
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ if (String.IsNullOrEmpty(this.Settings.AccessToken) || String.IsNullOrEmpty(this.Settings.TokenSecret) || String.IsNullOrEmpty(this.Settings.UserId))
+ {
+ // access token is empty
+ // get access token
+ this.GetAccessToken();
+ }
+ else
+ {
+ // check token
+ this.CheckAccessToken();
+ }
+ }
+
+ private void btnAddPhoto_Click(object sender, EventArgs e)
+ {
+ if (openFileDialog1.ShowDialog() != DialogResult.OK)
+ {
+ return;
+ }
+
+ this.MediaUploadInit(openFileDialog1.FileName);
+ }
+
+ private void GetAccessToken()
+ {
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new Action(GetAccessToken));
+ return;
+ }
+
+ var login = new TwitterLogin
+ (
+ this.Settings.ConsumerKey,
+ this.Settings.ConsumerSecret
+ );
+
+ login.Owner = this;
+
+ login.ShowDialog();
+
+ if (login.IsSuccessfully)
+ {
+ // save access token to application settings
+ this.Settings.AccessToken = ((OAuthAccessToken)login.AccessToken).Value;
+ this.Settings.TokenSecret = ((OAuthAccessToken)login.AccessToken).TokenSecret;
+ this.Settings.UserId = login.AccessToken["user_id"].ToString();
+ this.Settings.Save();
+
+ // get tweets
+ //this.GetTweets();
+ }
+ else
+ {
+ if (MessageBox.Show("Please Click OK to login on Twitter or CANCEL for exit from the program.", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.Cancel)
+ {
+ this.Close();
+ }
+ else
+ {
+ this.GetAccessToken();
+ }
+ }
+ }
+
+ private void CheckAccessToken()
+ {
+ //this.RequestStart();
+
+ //btnMore.Enabled = false;
+ //btnTweet.Enabled = false;
+
+ var parameters = new HttpParameterCollection
+ {
+ new HttpUrlParameter("user_id", this.Settings.UserId),
+ new HttpUrlParameter("include_entities", "false")
+ };
+
+ OAuthUtility.GetAsync
+ (
+ "https://api.twitter.com/1.1/users/show.json",
+ parameters: parameters,
+ authorization: this.GetAuth(),
+ callback: CheckAccessToken_Result
+ );
+ }
+
+ private void CheckAccessToken_Result(RequestResult result)
+ {
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new Action(CheckAccessToken_Result), result);
+ return;
+ }
+
+ if (!result.IsSuccessfully)
+ {
+ this.Settings.AccessToken = "";
+ this.Settings.TokenSecret = "";
+ this.Settings.Save();
+
+ this.GetAccessToken();
+ }
+ else
+ {
+ //this.GetTweets();
+ }
+ }
+
+ private void btnTweet_Click(object sender, EventArgs e)
+ {
+ HttpParameterCollection parameters = new HttpParameterCollection();
+ parameters.AddFormParameter("status", this.Message.Text);
+
+ // images
+ if (UploadedImages.Controls.Count > 0)
+ {
+ var media_ids = new List();
+
+ foreach (PictureBox image in UploadedImages.Controls)
+ {
+ media_ids.Add(image.Tag.ToString());
+ }
+
+ // add to query
+ parameters.AddFormParameter("media_ids", String.Join(",", media_ids));
+ }
+
+ OAuthUtility.PostAsync
+ (
+ "https://api.twitter.com/1.1/statuses/update.json",
+ parameters: parameters,
+ authorization: this.GetAuth(),
+ callback: SendTweet_Result,
+ contentType: "application/x-www-form-urlencoded"
+ );
+ }
+
+ private void SendTweet_Result(RequestResult result)
+ {
+ /*if (this.InvokeRequired)
+ {
+ this.Invoke(new Action(SendTweet_Result), result);
+ return;
+ }*/
+
+ if (result.IsSuccessfully)
+ {
+ /*TwitterItem tweet = new TwitterItem();
+ //{
+ // Dock = DockStyle.Top,
+ // Username = string.Format("@{0}", result["user"]["screen_name"]),
+ // Nickname = result["user"]["name"],
+ // DateCreated = System.DateTime.ParseExact(result["created_at"], "ddd MMM dd HH:mm:ss zzzz yyyy", System.Globalization.CultureInfo.InvariantCulture).ToString(),
+ // Text = result["text"]
+ //};
+ pnlList.Controls.Add(tweet);
+ pnlList.Controls.SetChildIndex(tweet, 0);
+ pnlList.ScrollControlIntoView(pnlList.Controls[0]);
+ tbMessage.Text = tbMessage.Tag.ToString();*/
+ }
+
+ //RequestEnd(result);
+
+ //tbMessage.Enabled = true;
+ //btnTweet.Enabled = true;
+ }
+
+ ///
+ /// https://dev.twitter.com/rest/reference/post/media/upload-init
+ ///
+ /// File path.
+ private void MediaUploadInit(string path)
+ {
+ var file = new FileInfo(path);
+
+ string media_type = "image/jpeg";
+
+ switch (file.Extension.ToLower())
+ {
+ case ".png":
+ media_type = "image/png";
+ break;
+ case ".gif":
+ media_type = "image/gif";
+ break;
+ case ".bmp":
+ media_type = "image/bmp";
+ break;
+ }
+
+ var parameters = new HttpParameterCollection();
+ parameters.AddFormParameter("command", "INIT");
+ parameters.AddFormParameter("total_bytes", file.Length.ToString());
+ parameters.AddFormParameter("media_type", media_type);
+ parameters.AddFormParameter("media_category", "tweet_image");
+
+ OAuthUtility.PostAsync
+ (
+ "https://upload.twitter.com/1.1/media/upload.json",
+ parameters: parameters, authorization: this.GetAuth(),
+ contentType: "multipart/form-data",
+ callback: (RequestResult result) =>
+ {
+ if (result.IsSuccessfully)
+ {
+ this.MeadiaUploadAppend(path, result["media_id"].ToString());
+ }
+ else
+ {
+ this.ErrorResult(result);
+ }
+ }
+ );
+ }
+
+ ///
+ /// https://dev.twitter.com/rest/reference/post/media/upload-append
+ ///
+ /// File path.
+ /// Media id.
+ /// Chunk. Default: 0.
+ private void MeadiaUploadAppend(string path, string media_id, int chunk = 0)
+ {
+ var file = new FileInfo(path);
+ bool isUploded = false;
+ byte[] media = null;
+
+ if (chunk > 0)
+ {
+ // multiple chunks
+ using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.Inheritable))
+ using (var reader = new BinaryReader(stream))
+ {
+ stream.Position = (this.MediaUploadChunkSize * chunk); // + 1;
+ media = reader.ReadBytes(this.MediaUploadChunkSize);
+ isUploded = (stream.Position == stream.Length);
+ }
+ }
+ else
+ {
+ if (file.Length <= this.MediaUploadChunkSize)
+ {
+ // one chunk
+ using (var reader = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Inheritable)))
+ {
+ media = reader.ReadBytes(Convert.ToInt32(file.Length));
+ isUploded = true;
+ }
+ }
+ else
+ {
+ // multiple chunks
+ using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.Inheritable))
+ using (var reader = new BinaryReader(stream))
+ {
+ media = reader.ReadBytes(this.MediaUploadChunkSize);
+ isUploded = (stream.Position == stream.Length);
+ }
+ }
+ }
+
+ var parameters = new HttpParameterCollection();
+ parameters.AddFormParameter("command", "APPEND");
+ parameters.AddFormParameter("media_id", media_id);
+ parameters.AddFormParameter("segment_index", chunk.ToString());
+ parameters.Add("media", Path.GetFileName(path), media);
+
+ OAuthUtility.PostAsync
+ (
+ "https://upload.twitter.com/1.1/media/upload.json",
+ parameters: parameters, authorization: this.GetAuth(),
+ contentType: "multipart/form-data",
+ callback: (RequestResult result) =>
+ {
+ if (!result.IsSuccessfully)
+ {
+ // error
+ this.ErrorResult(result);
+ return;
+ }
+
+ if (file.Length > this.MediaUploadChunkSize && !isUploded)
+ {
+ // next chunk
+ this.MeadiaUploadAppend(path, media_id, chunk + 1);
+ }
+ else
+ {
+ // finalize
+ this.MeadiaUploadFinalize(path, media_id);
+ }
+ }
+ );
+ }
+
+ ///
+ /// https://dev.twitter.com/rest/reference/post/media/upload-finalize
+ ///
+ /// Media id.
+ private void MeadiaUploadFinalize(string path, string media_id)
+ {
+ var parameters = new HttpParameterCollection();
+ parameters.AddFormParameter("command", "FINALIZE");
+ parameters.AddFormParameter("media_id", media_id);
+
+ OAuthUtility.PostAsync
+ (
+ "https://upload.twitter.com/1.1/media/upload.json",
+ parameters: parameters, authorization: this.GetAuth(),
+ contentType: "multipart/form-data",
+ callback: (RequestResult result) =>
+ {
+ if (result.IsSuccessfully)
+ {
+ // ok
+ this.MeadiaUploadFinalize_Result(path, result);
+ }
+ else
+ {
+ // error
+ this.ErrorResult(result);
+ }
+ }
+ );
+ }
+
+ private void MeadiaUploadFinalize_Result(string path, RequestResult result)
+ {
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new Action(MeadiaUploadFinalize_Result), path, result);
+ return;
+ }
+
+ // add photo to uploaded list
+ var image = new PictureBox();
+ image.Height = UploadedImages.Height;
+ image.Width = UploadedImages.Height;
+ image.SizeMode = PictureBoxSizeMode.StretchImage;
+
+ // save media_id to tag
+ image.Tag = result["media_id"].ToString();
+
+ using (var file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Inheritable))
+ {
+ image.Image = Image.FromStream(file);
+ }
+
+ UploadedImages.Controls.Add(image);
+ }
+
+ private void ErrorResult(RequestResult result)
+ {
+ if (this.InvokeRequired)
+ {
+ this.Invoke(new Action(ErrorResult), result);
+ return;
+ }
+
+ if (result["errors"].HasValue)
+ {
+ MessageBox.Show(String.Join("\r\n", result["errors"].Select(itm => itm["message"].ToString())), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ else
+ {
+ MessageBox.Show(result.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ }
+
+}
diff --git a/examples/TwitterExample/Form1.resx b/examples/TwitterExample/Form1.resx
new file mode 100644
index 0000000..9bad2f5
--- /dev/null
+++ b/examples/TwitterExample/Form1.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/examples/TwitterExample/Program.cs b/examples/TwitterExample/Program.cs
new file mode 100644
index 0000000..b73995e
--- /dev/null
+++ b/examples/TwitterExample/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace TwitterExample
+{
+ static class Program
+ {
+ ///
+ /// Главная точка входа для приложения.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Form1());
+ }
+ }
+}
diff --git a/examples/TwitterExample/Properties/AssemblyInfo.cs b/examples/TwitterExample/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..757a746
--- /dev/null
+++ b/examples/TwitterExample/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Управление общими сведениями о сборке осуществляется с помощью
+// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
+// связанные со сборкой.
+[assembly: AssemblyTitle("TwitterExample")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TwitterExample")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми
+// для COM-компонентов. Если требуется обратиться к типу в этой сборке через
+// COM, задайте атрибуту ComVisible значение TRUE для этого типа.
+[assembly: ComVisible(false)]
+
+// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
+[assembly: Guid("1404ed85-a0d3-49d8-b6e9-fb955bc2f5db")]
+
+// Сведения о версии сборки состоят из следующих четырех значений:
+//
+// Основной номер версии
+// Дополнительный номер версии
+// Номер сборки
+// Редакция
+//
+// Можно задать все значения или принять номера сборки и редакции по умолчанию
+// используя "*", как показано ниже:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/examples/TwitterExample/Properties/Resources.Designer.cs b/examples/TwitterExample/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..21444ff
--- /dev/null
+++ b/examples/TwitterExample/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// Этот код создан программой.
+// Исполняемая версия:4.0.30319.42000
+//
+// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
+// повторной генерации кода.
+//
+//------------------------------------------------------------------------------
+
+namespace TwitterExample.Properties {
+ using System;
+
+
+ ///
+ /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
+ ///
+ // Этот класс создан автоматически классом StronglyTypedResourceBuilder
+ // с помощью такого средства, как ResGen или Visual Studio.
+ // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
+ // с параметром /str или перестройте свой проект VS.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TwitterExample.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Перезаписывает свойство CurrentUICulture текущего потока для всех
+ /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/examples/TwitterExample/Properties/Resources.resx b/examples/TwitterExample/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/examples/TwitterExample/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/examples/TwitterExample/Properties/Settings.Designer.cs b/examples/TwitterExample/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..729a290
--- /dev/null
+++ b/examples/TwitterExample/Properties/Settings.Designer.cs
@@ -0,0 +1,86 @@
+//------------------------------------------------------------------------------
+//
+// Этот код создан программой.
+// Исполняемая версия:4.0.30319.42000
+//
+// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
+// повторной генерации кода.
+//
+//------------------------------------------------------------------------------
+
+namespace TwitterExample.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("cXzSHLUy57C4gTBgMGRDuqQtr")]
+ public string ConsumerKey {
+ get {
+ return ((string)(this["ConsumerKey"]));
+ }
+ set {
+ this["ConsumerKey"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("3SSldiSb5H4XeEMOIIF4osPWxOy19jrveDcPHaWtHDQqgDYP9P")]
+ public string ConsumerSecret {
+ get {
+ return ((string)(this["ConsumerSecret"]));
+ }
+ set {
+ this["ConsumerSecret"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string AccessToken {
+ get {
+ return ((string)(this["AccessToken"]));
+ }
+ set {
+ this["AccessToken"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string TokenSecret {
+ get {
+ return ((string)(this["TokenSecret"]));
+ }
+ set {
+ this["TokenSecret"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string UserId {
+ get {
+ return ((string)(this["UserId"]));
+ }
+ set {
+ this["UserId"] = value;
+ }
+ }
+ }
+}
diff --git a/examples/TwitterExample/Properties/Settings.settings b/examples/TwitterExample/Properties/Settings.settings
new file mode 100644
index 0000000..6ca2722
--- /dev/null
+++ b/examples/TwitterExample/Properties/Settings.settings
@@ -0,0 +1,21 @@
+
+
+
+
+
+ cXzSHLUy57C4gTBgMGRDuqQtr
+
+
+ 3SSldiSb5H4XeEMOIIF4osPWxOy19jrveDcPHaWtHDQqgDYP9P
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/TwitterExample/TwitterExample.csproj b/examples/TwitterExample/TwitterExample.csproj
new file mode 100644
index 0000000..5696e53
--- /dev/null
+++ b/examples/TwitterExample/TwitterExample.csproj
@@ -0,0 +1,97 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {1404ED85-A0D3-49D8-B6E9-FB955BC2F5DB}
+ WinExe
+ Properties
+ TwitterExample
+ TwitterExample
+ v4.0
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ packages\Nemiro.OAuth.1.10\lib\net40\Nemiro.OAuth.dll
+ True
+
+
+ packages\Nemiro.OAuth.LoginForms.1.4\lib\net40\Nemiro.OAuth.LoginForms.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+
+
+ Form1.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/TwitterExample/TwitterExample.sln b/examples/TwitterExample/TwitterExample.sln
new file mode 100644
index 0000000..5f0557d
--- /dev/null
+++ b/examples/TwitterExample/TwitterExample.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwitterExample", "TwitterExample.csproj", "{1404ED85-A0D3-49D8-B6E9-FB955BC2F5DB}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1404ED85-A0D3-49D8-B6E9-FB955BC2F5DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1404ED85-A0D3-49D8-B6E9-FB955BC2F5DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1404ED85-A0D3-49D8-B6E9-FB955BC2F5DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1404ED85-A0D3-49D8-B6E9-FB955BC2F5DB}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/examples/TwitterExample/app.config b/examples/TwitterExample/app.config
new file mode 100644
index 0000000..cb24213
--- /dev/null
+++ b/examples/TwitterExample/app.config
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+ cXzSHLUy57C4gTBgMGRDuqQtr
+
+
+ 3SSldiSb5H4XeEMOIIF4osPWxOy19jrveDcPHaWtHDQqgDYP9P
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/TwitterExample/packages.config b/examples/TwitterExample/packages.config
new file mode 100644
index 0000000..f35b739
--- /dev/null
+++ b/examples/TwitterExample/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file