637 lines
23 KiB
C#
637 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
using Virtuoso.Miranda.Plugins.Helpers;
|
|
using Virtuoso.Miranda.Plugins.Infrastructure;
|
|
using Virtuoso.Miranda.Plugins.Native;
|
|
using Speak.Core;
|
|
using Speak.HPP;
|
|
using Speak.RichEdit;
|
|
using Speak.Sites;
|
|
using Speak.Structs;
|
|
using Speak.UI;
|
|
using Speak.Utils;
|
|
|
|
namespace Speak.Fork
|
|
{
|
|
class ContactManager : IDisposable
|
|
{
|
|
internal class SettingOwner : ISettingOwner
|
|
{
|
|
private string name;
|
|
|
|
public SettingOwner(string name)
|
|
{
|
|
this.name = name;
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return name; }
|
|
set { name = value; }
|
|
}
|
|
|
|
}
|
|
|
|
private string ownerProtocol;
|
|
//private ContactContainer juickContact;
|
|
private List<ContactContainer> siteContacts;
|
|
|
|
// todo: FIX IT!!!111
|
|
private const string namePrefix = "[xJuick] ";
|
|
private const string xJuickSiteField = "Site";
|
|
private List<ContactContainer> forkContacts;
|
|
private SettingOwner pOwner;
|
|
private SettingOwner mpOwner;
|
|
private SettingOwner clOwner;
|
|
private SettingOwner sOwner;
|
|
private IntPtr rootName;
|
|
private bool addAsTemporary;
|
|
private StatusModes mode;
|
|
private Dictionary<string, ISite> additionalContacts;
|
|
|
|
|
|
public ContactManager(IntPtr rootName, ISite[] currentSites, string ownerProtocol)
|
|
{
|
|
|
|
siteContacts = new List<ContactContainer>();
|
|
|
|
|
|
this.rootName = rootName;
|
|
mode = StatusModes.OnThePhone;
|
|
additionalContacts = new Dictionary<string, ISite>();
|
|
forkContacts = new List<ContactContainer>();
|
|
|
|
pOwner = new SettingOwner("Protocol");
|
|
mpOwner = new SettingOwner(ownerProtocol);
|
|
clOwner = new SettingOwner("CList");
|
|
sOwner = new SettingOwner("xJuickSite");
|
|
|
|
List<string> mainContacts = new List<string>();
|
|
for (int i = 0, iCount = currentSites.Length; i < iCount; i++)
|
|
{
|
|
mainContacts.Add(currentSites[i].MainContact);
|
|
|
|
ISite site = currentSites[i];
|
|
for (int j = 0, jCount = currentSites[i].AdditionalContacts.Length; j < jCount; j++)
|
|
{
|
|
additionalContacts[currentSites[i].AdditionalContacts[j]] = site;
|
|
}
|
|
}
|
|
|
|
if (!FillContactList(mainContacts, ownerProtocol))
|
|
throw new Exception("No protocols found");
|
|
|
|
addAsTemporary = false;
|
|
|
|
MirandaContext.Current.MirandaDatabase.ContactDeleted += MirandaDatabase_ContactDeleted;
|
|
}
|
|
|
|
private bool MirandaDatabase_ContactDeleted(object sender, MirandaContactEventArgs e)
|
|
{
|
|
int deleteIndex = -1;
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Contact.MirandaHandle == e.ContactInfo.MirandaHandle)
|
|
{
|
|
if (IsAdditional(forkContacts[i].Contact.UniqueID.ToString()))
|
|
return false;
|
|
|
|
deleteIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (deleteIndex != -1)
|
|
{
|
|
CopyHistory(e.ContactInfo.MirandaHandle, GetMainContactHandle(e.ContactInfo.MirandaHandle), null);
|
|
forkContacts.RemoveAt(deleteIndex);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsMainContact(IntPtr hMainContact)
|
|
{
|
|
return GetMainContactContainer(hMainContact) != null;
|
|
}
|
|
|
|
private ContactContainer GetMainContactContainer(IntPtr hMainContact)
|
|
{
|
|
for (int i = 0, iCount = siteContacts.Count; i < iCount; i++)
|
|
{
|
|
if (hMainContact == siteContacts[i].Contact.MirandaHandle)
|
|
return siteContacts[i];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public IntPtr GetMainContactHandle(IntPtr childHContact)
|
|
{
|
|
ISite site = SitesManager.GetContactSite(childHContact);
|
|
|
|
if (site == null)
|
|
return IntPtr.Zero;
|
|
|
|
for (int i = 0, iCount = siteContacts.Count; i < iCount; i++)
|
|
{
|
|
if (siteContacts[i].Contact.UniqueID.ToString() == site.MainContact)
|
|
{
|
|
return siteContacts[i].Contact.MirandaHandle;
|
|
}
|
|
}
|
|
|
|
return IntPtr.Zero; // yeah. maybe will implement multi-juick later :)
|
|
}
|
|
|
|
private bool FillContactList(List<string> mainContacts, string ownerProtocol)
|
|
{
|
|
// quiet unload
|
|
if (Util.EnumProtocols().Count == 0)
|
|
return false;
|
|
|
|
Dictionary<string, Dictionary<string, ContactInfo>> protocols = new Dictionary<string, Dictionary<string, ContactInfo>>();
|
|
int contactsCount = 0;
|
|
|
|
IEnumerable<IntPtr> hContacts = MirandaContext.Current.MirandaDatabase.GetContactHandles();
|
|
foreach (IntPtr hContact in hContacts)
|
|
{
|
|
contactsCount++;
|
|
ContactInfo ci = ContactInfo.FromHandle(hContact);
|
|
|
|
if (ci == null || ci.UniqueID == null)
|
|
continue;
|
|
|
|
string jid = ci.UniqueID.ToString();
|
|
|
|
bool isAdditional = IsAdditional(jid);
|
|
if (jid.StartsWith(namePrefix) || isAdditional)
|
|
{
|
|
if (!IsOnContact(ci.MirandaHandle))
|
|
AddToContact(ci.MirandaHandle);
|
|
|
|
forkContacts.Add(new ContactContainer(this, ci));
|
|
|
|
string contactSite = (string)ci.ReadSetting(xJuickSiteField, sOwner, DatabaseSettingType.AsciiString);
|
|
if (!String.IsNullOrEmpty(contactSite))
|
|
{
|
|
ISite contactSiteObject = SitesManager.GetContactSite(contactSite, true);
|
|
if (contactSiteObject != null)
|
|
SitesManager.SitesInfo[ci.MirandaHandle] = contactSiteObject;
|
|
}
|
|
else if (isAdditional)
|
|
{
|
|
SitesManager.SitesInfo[ci.MirandaHandle] = additionalContacts[jid];
|
|
}
|
|
}
|
|
else if (mainContacts.IndexOf(jid) != -1)
|
|
{
|
|
ISite site = SitesManager.GetContactSite(jid, false);
|
|
if (site != null)
|
|
SitesManager.SitesInfo[hContact] = site;
|
|
|
|
string ownerProto = (string)ci.ReadSetting("p", pOwner, DatabaseSettingType.AsciiString);
|
|
if (!protocols.ContainsKey(jid))
|
|
protocols[jid] = new Dictionary<string, ContactInfo>();
|
|
|
|
protocols[jid].Add(ownerProto, ci);
|
|
}
|
|
}
|
|
|
|
if (contactsCount == 0)
|
|
return false;
|
|
|
|
bool found = false;
|
|
foreach (KeyValuePair<string, Dictionary<string, ContactInfo>> jp in protocols)
|
|
{
|
|
foreach (KeyValuePair<string, ContactInfo> p in jp.Value)
|
|
{
|
|
if (p.Key.Equals(ownerProtocol, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
this.ownerProtocol = ownerProtocol;
|
|
ContactInfo ci = jp.Value[this.ownerProtocol];
|
|
ContactContainer mainContact = new ContactContainer(this, ci);
|
|
siteContacts.Add(mainContact);
|
|
if (!IsOnContact(ci.MirandaHandle))
|
|
AddToContact(ci.MirandaHandle);
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
return true;
|
|
|
|
if (String.IsNullOrEmpty(this.ownerProtocol))
|
|
{
|
|
if (protocols.Count == 0)
|
|
{
|
|
System.Windows.Forms.MessageBox.Show("Found ZERO protocols with main accounts (check options)" + Environment.NewLine +
|
|
"xJuick plugin will be unloaded now.", "[xJuick] Jabber Protocol error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return false;
|
|
}
|
|
|
|
/*ProtocolSelect ps = new ProtocolSelect(protocols);
|
|
if (ps.ShowDialog() != DialogResult.OK)
|
|
return false;
|
|
|
|
if (String.IsNullOrEmpty(ps.ResultProtocol) || ps.ResultContactInfo == null)
|
|
return false;
|
|
|
|
this.ownerProtocol = ps.ResultProtocol;
|
|
ContactInfo ci = ps.ResultContactInfo;
|
|
|
|
ContactContainer mainContact = new ContactContainer(this, ci);
|
|
siteContacts.Add(mainContact);
|
|
if (!IsOnContact(ci.MirandaHandle))
|
|
AddToContact(ci.MirandaHandle);
|
|
|
|
Settings.Instance.JabberProtocolName = this.ownerProtocol;
|
|
Settings.Save();*/
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public bool IsForked(IntPtr hContact)
|
|
{
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Contact.MirandaHandle == hContact)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsAdditional(string UID)
|
|
{
|
|
return additionalContacts.ContainsKey(UID);
|
|
}
|
|
|
|
public ContactInfo GetContactInfo(string mainContact, string name)
|
|
{
|
|
ContactInfo result = null;
|
|
|
|
string sname = namePrefix + name;
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Contact != null && forkContacts[i].Contact.UniqueID != null)
|
|
{
|
|
if (forkContacts[i].Contact.UniqueID.ToString().Equals(sname, StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
result = forkContacts[i].Contact;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("GetContactInfo() -> Null ID [???]");
|
|
}
|
|
}
|
|
|
|
|
|
if (result == null && Settings.Instance.AutoFork)
|
|
{
|
|
result = MakeFork(mainContact, name);
|
|
}
|
|
else if (result != null)
|
|
ChangeStatus(result, mode);
|
|
|
|
return result;
|
|
}
|
|
|
|
private ContactInfo MakeFork(string mainContact, string name)
|
|
{
|
|
ContactInfo result = AddNewContact(mainContact, name);
|
|
if (result != null)
|
|
{
|
|
SitesManager.SitesInfo[result.MirandaHandle] = SitesManager.GetContactSite(mainContact, false);
|
|
|
|
if (!IsOnContact(result.MirandaHandle))
|
|
AddToContact(result.MirandaHandle);
|
|
|
|
forkContacts.Add(new ContactContainer(this, result));
|
|
ChangeStatus(result, mode);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void CopyHistory(IntPtr fromContact, IntPtr toContact, Regex condition)
|
|
{
|
|
MirandaDB.DirectCopyHistory(fromContact, toContact, condition);
|
|
}
|
|
|
|
public void SettingsChanged()
|
|
{
|
|
for (int i = 0, iCount = siteContacts.Count; i < iCount; i++)
|
|
{
|
|
if (siteContacts[i].Processor != null)
|
|
siteContacts[i].Processor.SettingsChanged();
|
|
}
|
|
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Processor != null)
|
|
{
|
|
forkContacts[i].Processor.SettingsChanged();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OpenChat(IntPtr hContact, IntPtr hWnd)
|
|
{
|
|
ContactContainer contact = GetMainContactContainer(hContact);
|
|
ISite site = SitesManager.GetContactSite(hContact);
|
|
|
|
if (site == null)
|
|
{
|
|
if (contact != null)
|
|
{
|
|
string cintactID = contact.Contact.UniqueID.ToString();
|
|
site = SitesManager.GetContactSite(cintactID, true);
|
|
if (site != null)
|
|
SitesManager.SitesInfo[hContact] = site;
|
|
}
|
|
else
|
|
{
|
|
ContactInfo ci = ContactInfo.FromHandle(hContact);
|
|
string contactSite = (string)ci.ReadSetting(xJuickSiteField, pOwner, DatabaseSettingType.AsciiString);
|
|
if (!String.IsNullOrEmpty(contactSite))
|
|
{
|
|
site = SitesManager.GetContactSite(contactSite, false);
|
|
}
|
|
else if (IsAdditional(ci.UniqueID.ToString()))
|
|
{
|
|
site = additionalContacts[ci.UniqueID.ToString()];
|
|
}
|
|
}
|
|
|
|
if (site == null)
|
|
return;
|
|
}
|
|
|
|
|
|
if (contact != null)
|
|
{
|
|
contact.InitMessageProcessor(site, hContact, hWnd);
|
|
return;
|
|
}
|
|
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Contact.MirandaHandle == hContact)
|
|
{
|
|
forkContacts[i].InitMessageProcessor(site, hContact, hWnd);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void CloseChat(IntPtr hContact)
|
|
{
|
|
//SitesManager.SitesInfo.Remove(hContact);
|
|
|
|
ContactContainer contact = GetMainContactContainer(hContact);
|
|
if (contact != null)
|
|
{
|
|
contact.Close();
|
|
return;
|
|
}
|
|
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Contact.MirandaHandle == hContact)
|
|
{
|
|
forkContacts[i].Close();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ProcessHistoryItem(IntPtr smallHandle, ItemRenderDetails ird)
|
|
{
|
|
ContactContainer item = null;
|
|
|
|
ContactContainer contact = GetMainContactContainer(ird.hContact);
|
|
if (contact != null)
|
|
{
|
|
item = contact;
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Contact.MirandaHandle == ird.hContact)
|
|
{
|
|
item = forkContacts[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (item == null)
|
|
return;
|
|
|
|
if (item.Processor is HistoryppHandler)
|
|
((HistoryppHandler)item.Processor).ProcessHistoryItem(smallHandle, ird);
|
|
}
|
|
|
|
public void Avatars()
|
|
{
|
|
for (int i = 0, iCount = siteContacts.Count; i < iCount; i++)
|
|
{
|
|
if (siteContacts[i].Processor != null)
|
|
siteContacts[i].Processor.Avatars();
|
|
}
|
|
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Processor != null)
|
|
forkContacts[i].Processor.Avatars();
|
|
}
|
|
}
|
|
|
|
public void Update(IntPtr hContact)
|
|
{
|
|
ContactContainer contact = GetMainContactContainer(hContact);
|
|
if (contact != null)
|
|
{
|
|
contact.UpdateProcessor();
|
|
return;
|
|
}
|
|
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
if (forkContacts[i].Contact.MirandaHandle == hContact)
|
|
{
|
|
forkContacts[i].UpdateProcessor();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private ContactInfo AddNewContact(string mainContact, string uid)
|
|
{
|
|
if (String.IsNullOrEmpty(ownerProtocol))
|
|
return null;
|
|
try
|
|
{
|
|
ContactInfo ci = ContactInfo.CreateContact();
|
|
|
|
ci.WriteSetting("FullName", mpOwner, uid, DatabaseSettingType.AsciiString);
|
|
ci.WriteSetting("jid", mpOwner, namePrefix + uid, DatabaseSettingType.AsciiString);
|
|
ci.WriteSetting("p", pOwner, ownerProtocol, DatabaseSettingType.AsciiString);
|
|
ci.WriteSetting(xJuickSiteField, sOwner, mainContact, DatabaseSettingType.AsciiString);
|
|
|
|
if (addAsTemporary)
|
|
{
|
|
ci.WriteSetting("NotOnList", clOwner, 1, DatabaseSettingType.Byte);
|
|
ci.WriteSetting("Delete", clOwner, 1, DatabaseSettingType.Byte);
|
|
}
|
|
|
|
return ci;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
/*QuickDebug qd = new QuickDebug(ex.Message + Environment.NewLine + ex.StackTrace);
|
|
qd.ShowDialog();*/
|
|
MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public ContactInfo CheckForHandle(IntPtr hContact, string message)
|
|
{
|
|
Match m = Regexps.ReplyRegEx.Match(message);
|
|
if (m.Success)
|
|
{
|
|
string mainContact = SitesManager.GetContactSite(hContact).MainContact;
|
|
return GetContactInfo(mainContact, "#" + m.Groups["post"].Value);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public ContactInfo CheckForHandlePure(IntPtr hContact, string message)
|
|
{
|
|
Match m = Regexps.PureReplyRegEx.Match(message);
|
|
if (m.Success)
|
|
{
|
|
ISite site = SitesManager.GetContactSite(hContact);
|
|
string mainContact = site == null ? String.Empty : site.MainContact;
|
|
return GetContactInfo(mainContact, "#" + m.Groups["post"].Value);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void ChangeForkState(IntPtr hContact, string name)
|
|
{
|
|
string mainContact = SitesManager.GetContactSite(hContact).MainContact;
|
|
ContactInfo result = GetContactInfo(mainContact, name);
|
|
if (result == null)
|
|
{
|
|
result = MakeFork(mainContact, name);
|
|
if (result != null)
|
|
CopyHistory(GetMainContactHandle(hContact), result.MirandaHandle, Regexps.GetHistoryRegEx(name));
|
|
}
|
|
else
|
|
{
|
|
result.OpenMessageWindow();
|
|
}
|
|
}
|
|
|
|
private void AddToContact(IntPtr hContact)
|
|
{
|
|
MirandaContext.Current.CallService(API.MS_PROTO_ADDTOCONTACT, hContact, rootName);
|
|
}
|
|
|
|
private bool IsOnContact(IntPtr hContact)
|
|
{
|
|
return Convert.ToBoolean(MirandaContext.Current.CallService(API.MS_PROTO_ISPROTOONCONTACT, hContact, rootName));
|
|
}
|
|
|
|
private void ChangeStatus(ContactInfo ci, StatusModes status)
|
|
{
|
|
try
|
|
{
|
|
ci.WriteSetting("Status", mpOwner, (UInt16)status, DatabaseSettingType.UInt16);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
public void ClearContacts()
|
|
{
|
|
ContactContainer[] fk = forkContacts.ToArray();
|
|
for (int i = 0, iCount = fk.Length; i < iCount; i++)
|
|
{
|
|
if (!IsAdditional(fk[i].Contact.UniqueID.ToString()))
|
|
{
|
|
fk[i].Contact.Delete();
|
|
}
|
|
}
|
|
forkContacts.Clear();
|
|
forkContacts = new List<ContactContainer>();
|
|
}
|
|
|
|
public void OnJuickClicked(object sender, ActionClickEvent e)
|
|
{
|
|
IntPtr hContact = ((ContactContainer) sender).Contact.MirandaHandle;
|
|
if (!e.AutoSend)
|
|
{
|
|
UnmanagedStringHandle str = new UnmanagedStringHandle(e.Action, StringEncoding.Ansi);
|
|
MirandaContext.Current.CallService(API.MS_MSG_SENDMESSAGE, hContact, str.IntPtr);
|
|
str.Free();
|
|
}
|
|
else
|
|
{
|
|
if (e.Action.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
Util.OpenURL(e.Action);
|
|
}
|
|
else if (e.Action.StartsWith("xJuick://", StringComparison.InvariantCultureIgnoreCase))
|
|
{
|
|
InvokeOnAction(hContact, e.Action.Substring(9).ToLower());
|
|
}
|
|
else
|
|
{
|
|
CSSData css = new CSSData();
|
|
css.hContact = hContact; //juickContact.Contact.MirandaHandle;
|
|
css.szProtoService = API.PSS_MESSAGE;
|
|
css.wParam = IntPtr.Zero;
|
|
css.lParam = new UnmanagedStringHandle(e.Action, StringEncoding.Ansi).IntPtr;
|
|
|
|
IntPtr cmdPtr = Marshal.AllocHGlobal(Marshal.SizeOf(css));
|
|
Marshal.StructureToPtr(css, cmdPtr, false);
|
|
MirandaContext.Current.CallService(API.MS_PROTO_CALLCONTACTSERVICE, IntPtr.Zero, cmdPtr);
|
|
}
|
|
}
|
|
}
|
|
|
|
public event EventHandler<ActionEvent> OnAction;
|
|
public void InvokeOnAction(IntPtr hContact, string action)
|
|
{
|
|
if (OnAction == null)
|
|
return;
|
|
OnAction(this, new ActionEvent(hContact, action));
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
for (int i = 0, iCount = forkContacts.Count; i < iCount; i++)
|
|
{
|
|
forkContacts[i].Dispose();
|
|
}
|
|
}
|
|
}
|
|
}
|