273 lines
10 KiB
C#
273 lines
10 KiB
C#
using Microsoft.VisualBasic.FileIO;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System;
|
|
|
|
namespace Contacts
|
|
{
|
|
|
|
/// <summary>
|
|
/// Represents a file, and provides implementations for parsing contacts from a file.
|
|
/// </summary>
|
|
public class Resolver
|
|
{
|
|
public List<Contact> Contacts { get; set; }
|
|
internal string _filepath;
|
|
private bool isGoogleCsv;
|
|
|
|
public Resolver(string filepath)
|
|
{
|
|
_filepath = filepath;
|
|
if (!File.Exists(_filepath))
|
|
throw new InvalidOperationException("File does not exist.");
|
|
|
|
Contacts = new List<Contact>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Manages the parsing process and determines the correct parser to use based upon the filetype.
|
|
/// </summary>
|
|
public void Parse()
|
|
{
|
|
string filetype = _filepath.Substring(_filepath.LastIndexOf('.'));
|
|
|
|
switch (filetype)
|
|
{
|
|
case ".csv":
|
|
ParseCsv();
|
|
break;
|
|
case ".vcf":
|
|
ParseVCF();
|
|
break;
|
|
case ".card":
|
|
ParseVCF();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a CSV file into a List<string>, and determine if the input csv is in the Google contact format or the Outlook contact format.
|
|
/// </summary>
|
|
private void ParseCsv()
|
|
{
|
|
List<string> contactInfo = new List<string>();
|
|
using (TextFieldParser parser = new TextFieldParser(_filepath))
|
|
{
|
|
if (parser.PeekChars(5).Equals("Name,"))
|
|
isGoogleCsv = true;
|
|
else
|
|
isGoogleCsv = false;
|
|
|
|
parser.ReadLine(); // skip header row
|
|
parser.TextFieldType = FieldType.Delimited;
|
|
parser.SetDelimiters(",");
|
|
while (!parser.EndOfData)
|
|
{
|
|
//Processing row
|
|
string[] fields = parser.ReadFields();
|
|
foreach (string field in fields)
|
|
if (!field.Equals("")) // skip blank fields
|
|
contactInfo.Add(field);
|
|
|
|
parser.ReadLine(); // move to next line to read the next contact.
|
|
ConvertToContact(contactInfo); // with current contact information, generate and add the new contact.
|
|
contactInfo.Clear(); // clear contact information for next contact.
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse the information contained by a Google formatted .csv file to generate a new Contacts object.
|
|
/// </summary>
|
|
private void ConvertToContact(List<string> csv)
|
|
{
|
|
Phone home = null;
|
|
Phone work = null;
|
|
Phone cell = null;
|
|
Phone other = null;
|
|
Contact c;
|
|
string[] contact = csv.ToArray();
|
|
|
|
// Check if the csv is a google or outlook formatted csv.
|
|
if (isGoogleCsv)
|
|
c = new Contact(contact[1], contact[2].Contains("*") ? "" : contact[2], null);
|
|
else
|
|
c = new Contact(contact[0], contact[1].Contains("*") ? "" : contact[1], null);
|
|
|
|
// iterate through csv array
|
|
for (int i = 0; i < contact.Length; i++)
|
|
{
|
|
// if current element is labeled as a number,
|
|
switch (contact[i])
|
|
{
|
|
case "Home":
|
|
home = ParsePhone(PhoneType.Home, contact[i + 1]);
|
|
if (home != null)
|
|
c.AddPhone(home);
|
|
break;
|
|
case "Work":
|
|
work = ParsePhone(PhoneType.Work, contact[i + 1]);
|
|
if (work != null)
|
|
c.AddPhone(work);
|
|
break;
|
|
case "Job":
|
|
work = ParsePhone(PhoneType.Work, contact[i + 1]);
|
|
if (work != null)
|
|
c.AddPhone(work);
|
|
break;
|
|
case "Mobile":
|
|
cell = ParsePhone(PhoneType.Cell, contact[i + 1]);
|
|
if (cell != null)
|
|
c.AddPhone(cell);
|
|
break;
|
|
case "Cell":
|
|
cell = ParsePhone(PhoneType.Cell, contact[i + 1]);
|
|
if (cell != null)
|
|
c.AddPhone(cell);
|
|
break;
|
|
case "Other":
|
|
other = ParsePhone(PhoneType.Other, contact[i + 1]);
|
|
if (other != null)
|
|
c.AddPhone(other);
|
|
break;
|
|
default:
|
|
other = ParsePhone(PhoneType.Other, contact[i]);
|
|
if (other != null)
|
|
c.AddPhone(other);
|
|
break;
|
|
}
|
|
|
|
if (contact[i].Contains("@")) // detect an email address and add to the current contact.
|
|
c.AddEmail(contact[i]);
|
|
if (contact[i].Contains("http") ||
|
|
contact[i].Contains("www.")) // detect a URL and add to the current contact.
|
|
c.PictureUrl = contact[i];
|
|
}
|
|
|
|
Contacts.Add(c);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parse the information contained by the .vcf file to generate a new Contacts object.
|
|
/// </summary>
|
|
private void ParseVCF()
|
|
{
|
|
using (StreamReader reader = new StreamReader(_filepath))
|
|
{
|
|
string line;
|
|
Contact contact = null;
|
|
while ((line = reader.ReadLine()) != null)
|
|
{
|
|
if (line.StartsWith("BEGIN:VCARD"))
|
|
{
|
|
contact = new Contact();
|
|
}
|
|
else if (line.StartsWith("FN:") && contact != null)
|
|
{
|
|
//mabye wrong
|
|
string myLine = line;
|
|
int i = 0;
|
|
while (true)
|
|
{
|
|
if (myLine[i].Equals(" "))
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
contact.FirstName += myLine[i];
|
|
i++;
|
|
}
|
|
}
|
|
//now at last name
|
|
while (true)
|
|
{
|
|
//mabye change
|
|
if (i == myLine.Length)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
contact.LastName += myLine[i];
|
|
}
|
|
}
|
|
}
|
|
else if (line.StartsWith("TEL;TYPE=") && contact != null)
|
|
{
|
|
int typeEndIndex = line.IndexOf(':', 9);
|
|
string phoneType = line.Substring(9, typeEndIndex - 9).ToUpper();
|
|
string phoneNumber = line.Substring(typeEndIndex + 1);
|
|
|
|
PhoneType parsedPhoneType = PhoneType.Other;
|
|
|
|
switch (phoneType)
|
|
{
|
|
case "HOME":
|
|
parsedPhoneType = PhoneType.Home;
|
|
break;
|
|
case "WORK":
|
|
parsedPhoneType = PhoneType.Work;
|
|
break;
|
|
case "CELL":
|
|
parsedPhoneType = PhoneType.Cell;
|
|
break;
|
|
case "OTHER":
|
|
parsedPhoneType = PhoneType.Other;
|
|
break;
|
|
}
|
|
|
|
Phone phone = ParsePhone(parsedPhoneType, phoneNumber);
|
|
if (phone != null)
|
|
{
|
|
contact.AddPhone(phone);
|
|
}
|
|
}
|
|
else if (line.StartsWith("EMAIL:") && contact != null)
|
|
{
|
|
string email = line.Substring(6);
|
|
contact.AddEmail(email);
|
|
}
|
|
else if (line.StartsWith("PHOTO;VALUE=URI:") && contact != null)
|
|
{
|
|
string pictureUrl = line.Substring(15);
|
|
contact.PictureUrl = pictureUrl;
|
|
}
|
|
else if (line.StartsWith("END:VCARD") && contact != null)
|
|
{
|
|
Contacts.Add(contact);
|
|
contact = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parses any format of a phone number into the acceptable format 1234567890.
|
|
/// </summary>
|
|
/// <param name="type"></param>
|
|
/// <param name="number"></param>
|
|
/// <returns></returns>
|
|
private Phone ParsePhone(PhoneType type, string number)
|
|
{
|
|
List<char> list = new List<char>();
|
|
char[] characters = number.ToCharArray();
|
|
|
|
for (int i = 0; i < characters.Length; i++)
|
|
if (char.IsDigit(characters[i])) // if the character is a digit, add it to the list
|
|
list.Add(characters[i]);
|
|
|
|
if (list.Count == 11) // remove the international code
|
|
list.RemoveAt(0);
|
|
|
|
string outputNumber = string.Join("", list);
|
|
if (outputNumber.Length > 10 ||
|
|
outputNumber.Length <
|
|
10) // detect if this was an email or address labeled as a generic category, ie. "Home".
|
|
return null;
|
|
|
|
return new Phone(outputNumber, type);
|
|
}
|
|
}
|
|
}
|