Skip to content

Instantly share code, notes, and snippets.

@mfakane
Created July 14, 2012 05:28
Show Gist options
  • Save mfakane/3109524 to your computer and use it in GitHub Desktop.
Save mfakane/3109524 to your computer and use it in GitHub Desktop.
Royal/RoyalFlare/Selena/SelenaClient.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Collections.Specialized;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
namespace Royal.Selena
{
public class SelenaClient
{
public event EventHandler LoggingIn;
public event EventHandler LoggedIn;
public event EventHandler LoggedOut;
private int logSize = 0;
private DateTime lastNames = DateTime.MinValue;
public bool IsLoggedIn
{
get
{
return this.ID != null;
}
}
public string Name
{
get;
private set;
}
public string ID
{
get;
private set;
}
public Uri BaseUri
{
get;
private set;
}
private string IndexUri
{
get
{
return this.BaseUri.AbsoluteUri + "index.php";
}
}
private string LogUri
{
get
{
return this.BaseUri.AbsoluteUri + "dat/log.txt";
}
}
private string NamesUri
{
get
{
return this.BaseUri.AbsoluteUri + "dat/names.dat";
}
}
public List<ChatEntry> Log
{
get;
private set;
}
public IList<string> Names
{
get;
private set;
}
public SelenaClient(Uri baseUri)
{
this.Log = new List<ChatEntry>();
this.BaseUri = baseUri;
}
private Dictionary<string, string> GetJson(byte[] p)
{
var s = Encoding.GetEncoding(932).GetString(p);
return GetJson(s);
}
private Dictionary<string, string> GetJson(string s)
{
var rt = new Dictionary<string, string>();
s = s.Trim().Trim('{', '}');
foreach (var i in Regex.Split(s, "\",\""))
{
if (string.IsNullOrEmpty(i))
continue;
var set = Regex.Split(i.Trim(), "\": \"");
if (set.Length >= 2)
rt.Add(set[0].Trim('"'), set[1].Trim('"').Replace("\\\"", "\"").Replace("\\'", "'").Replace("\\\\", "\\"));
}
return rt;
}
private NameValueCollection CreateNameValueCollection(params string[] nvset)
{
var rt = new NameValueCollection();
for (int i = 0; i < nvset.Length; i += 2)
rt.Add(nvset[i], nvset[i + 1]);
return rt;
}
public void SendPing()
{
if (!this.IsLoggedIn)
return;
try
{
using (var wc = new WebClient())
wc.UploadValues(this.IndexUri + "?mode=ping", CreateNameValueCollection("id", this.ID));
}
catch
{
}
}
public List<string> GetNames()
{
try
{
var req = (HttpWebRequest)WebRequest.Create(this.NamesUri);
req.Timeout = 5000;
if (lastNames != DateTime.MinValue)
req.IfModifiedSince = lastNames;
var res = (HttpWebResponse)req.GetResponse();
if (res.StatusCode == HttpStatusCode.OK)
using (var sr = new StreamReader(res.GetResponseStream()))
{
lastNames = res.LastModified;
var l = new List<string>();
foreach (var i in Regex.Split(sr.ReadToEnd(), @"\},\n*\{"))
if (!string.IsNullOrEmpty(i) && !string.IsNullOrEmpty(i.Trim().Trim('\0')))
{
var set = GetJson(i.Trim('\0'));
l.Add(set["name"]);
}
this.Names = l;
return l;
}
}
catch (WebException)
{
}
return null;
}
public IList<ChatEntry> GetNewEntries()
{
var req = (HttpWebRequest)WebRequest.Create(this.LogUri);
req.Timeout = 5000;
if (logSize != 0)
req.AddRange(logSize - 1);
try
{
var res = (HttpWebResponse)req.GetResponse();
using (var sr = new StreamReader(res.GetResponseStream()))
{
var s = sr.ReadToEnd().Substring(logSize == 0 ? 0 : 1);
if (!string.IsNullOrEmpty(s.Trim()))
{
if (res.StatusCode == HttpStatusCode.OK)
logSize = (int)res.ContentLength;
else if (res.StatusCode == HttpStatusCode.PartialContent)
logSize += (int)res.ContentLength - 1;
var entries = new List<ChatEntry>();
foreach (var i in s.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
{
var set = GetJson(i.Trim(','));
if (set.ContainsKey("time") && set.ContainsKey("message"))
if (!set.ContainsKey("name") || string.IsNullOrEmpty(set["name"]))
entries.Add(new ChatEntry(set["time"], null, set["message"]));
else
entries.Add(new ChatEntry(set["time"], set["name"], set["message"]));
}
this.Log.AddRange(entries);
return entries;
}
}
}
catch (WebException ex)
{
var res = (HttpWebResponse)ex.Response;
if (res != null && res.StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable)
logSize = 0;
}
return null;
}
public void SendMessage(string message)
{
SendMessage(this.Name, message);
}
public void SendMessage(string name, string message)
{
if (message != null)
using (var wc = new WebClient())
wc.UploadValues(this.IndexUri + "?mode=post", CreateNameValueCollection("id", this.ID, "name", name, "msg", message.Replace("\r", "").Replace("\n", "")));
}
public void Login(string name)
{
if (this.IsLoggedIn)
return;
if (LoggingIn != null)
LoggingIn(this, EventArgs.Empty);
using (var wc = new WebClient())
{
var dat = GetJson(wc.UploadValues(this.IndexUri + "?mode=login", CreateNameValueCollection("name", name)));
this.Name = dat["name"];
this.ID = dat["id"];
if (LoggedIn != null)
LoggedIn(this, EventArgs.Empty);
}
}
public void Logout(string message)
{
if (!this.IsLoggedIn)
return;
using (var wc = new WebClient())
wc.UploadValues(this.IndexUri + "?mode=logout", CreateNameValueCollection("name", this.Name, "id", this.ID, "msg", message));
this.ID = null;
this.Name = null;
if (LoggedOut != null)
LoggedOut(this, EventArgs.Empty);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment