Skip to content

Instantly share code, notes, and snippets.

@gyakoo
Created February 25, 2016 23:29
Show Gist options
  • Save gyakoo/b1e862cce1f8abbfa926 to your computer and use it in GitHub Desktop.
Save gyakoo/b1e862cce1f8abbfa926 to your computer and use it in GitHub Desktop.
Download all Tickets and Attachments from Parature for a given Account in HTML format.
// This program downloads all tickets from Parature using Parature SDK you can find here:
// https://github.com/Parature/ParatureSDK
// Create a c# project like the Parature SDK - Exercises.csproj and put this code.
// You must fill your credentials in the .config file
// It will create a folder for every ticket that will contain the text with details in html format
// and the attachment files.
// It also will create a table of content for all downloaded tickets.
// To build, download the ParatureSDK and override one of the examples with this program.
// You must have a .config file like following:
/*
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<appSettings>
<add key="AcctID" value=""/>
<add key="DeptID" value=""/>
<add key="ServerDomain" value=""/>
<add key="APIToken" value=""/>
</appSettings>
</configuration>
*/
// Fill the four fields with your case.
// Manu
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ParatureSDK;
using System.Diagnostics;
using ParatureSDK.Query.ModuleQuery;
using ParatureSDK.ParaObjects;
using System.Net;
using System.Configuration;
namespace Exercises
{
class CommandLineOpts
{
public CommandLineOpts(string[] args)
{
for ( int i = 0; i < args.Count(); ++i )
{
switch ( args[i].ToLower() )
{
case "-accounts":
m_listAccounts = true;
break;
case "-customer":
m_customerId = (i + 1) < args.Count() ? args[++i] : "";
break;
case "-folder":
m_dstFolder = (i + 1) < args.Count() ? args[++i] : "";
break;
case "-help":
Console.Out.WriteLine("Dump info from parature.");
Console.Out.WriteLine("You must fill the .config file with your credentials.");
Console.Out.WriteLine("\nOptions:");
Console.Out.WriteLine("\t-accounts : Only lists the account names and Ids");
Console.Out.WriteLine("\t-customer <Id>: Specify the customer Id to extract the info from (see -accounts)");
Console.Out.WriteLine("\t-folder <name>: (Optional) destination folder\n");
m_customerId = "";
return;
}
}
if ( m_dstFolder.Length== 0)
m_dstFolder = m_customerId;
}
public bool Exit{ get { return m_customerId.Length == 0; } }
public string m_customerId = "";
public string m_dstFolder = "";
public bool m_listAccounts = false;
};
class Program
{
/// <summary>
/// Lists all accounts given a parature service connection in html format into the outfile
/// </summary>
/// <param name="serv">Service connection object</param>
/// <param name="outfile">Output file name</param>
static void ListAccounts(ParaService serv, string outfile)
{
Trace.WriteLine("Extracting account names and IDs only...");
var aq = new AccountQuery();
aq.RetrieveAllRecords = true;
var accounts = serv.GetList<Account>(aq).OrderBy(x => x.Account_Name);
var acctStr = new System.IO.FileStream(outfile, System.IO.FileMode.Create);
var acctWriter = new System.IO.StreamWriter(acctStr, Encoding.UTF8);
acctWriter.WriteLine("<html><body>");
acctWriter.WriteLine("<h1>Accounts</h1>");
acctWriter.WriteLine("Count: {0}<br/>", accounts.Count());
acctWriter.WriteLine("<table border=\"1\"");
acctWriter.WriteLine("<tr><th>ID</th><th>Account Name</th></tr>");
foreach (var acct in accounts)
acctWriter.WriteLine("<tr><td>{1}</td><td>{0}</td></tr>", acct.Account_Name, acct.Id);
acctWriter.WriteLine("</table>");
acctWriter.WriteLine("</body></html>");
}
/// <summary>
/// Dumps tickets from parature into disk. Use -help for more info.
/// </summary>
static void Main(string[] args)
{
// Parsing command line
CommandLineOpts opts = new CommandLineOpts(args);
// Is it just account listing? do it and exit
if (opts.m_listAccounts)
{
Console.Out.WriteLine("Dumping accounts information...");
ListAccounts(new ParaService(CredentialProvider.Creds), "accounts.html");
return;
}
if ( opts.Exit )
{
Console.Out.WriteLine("Not a valid customer account Id provided");
return;
}
// Configure trace output
Trace.Listeners.Add(new TextWriterTraceListener(new System.IO.StreamWriter("log-" + opts.m_customerId + ".txt")));
Trace.Listeners.Add(new ConsoleTraceListener(true));
Trace.AutoFlush = true;
// Output folder
if (!System.IO.Directory.Exists(opts.m_dstFolder))
System.IO.Directory.CreateDirectory(opts.m_dstFolder);
// Connecting to Parature
ParaService serv = null;
try
{
Trace.WriteLine("Connecting...");
serv = new ParaService(CredentialProvider.Creds);
var acct = serv.Get<Account>(long.Parse(opts.m_customerId));
Trace.WriteLine("Account: " + opts.m_customerId + " - " + acct.Account_Name);
}
catch (SystemException e)
{
Trace.WriteLine("Error connecting to service: " + e.Message);
return;
}
Trace.WriteLine("Retrieving tickets...");
var tq = new TicketQuery();
tq.AddStaticFieldFilter(TicketQuery.TicketStaticFields.Account, ParaEnums.QueryCriteria.Equal, opts.m_customerId);
//tq.AddStaticFieldFilter(TicketQuery.TicketStaticFields.Status, ParaEnums.QueryCriteria.Equal, "686");
tq.RetrieveAllRecords = true;
var tickets = serv.GetList<Ticket>(tq);
// Creating the Index.html
var index = new System.IO.FileStream(opts.m_dstFolder+ "\\index.html", System.IO.FileMode.Create);
var indexWriter = new System.IO.StreamWriter(index, Encoding.UTF8);
indexWriter.WriteLine("<html><body>");
Account act = serv.GetDetails<Account>(long.Parse(opts.m_customerId));
indexWriter.WriteLine("<h1>" + act.Account_Name + "</h1>");
indexWriter.WriteLine("Ticket Count: {0}<br/>", tickets.Data.Count);
indexWriter.WriteLine("<table border=\"1\"");
indexWriter.WriteLine("<tr><th>Ticket #</th><th>Date Created</th><th>Summary</th></tr>");
Trace.WriteLine(tickets.Count().ToString()+ " tickets");
// For each Ticket
int ticketNo = 0;
foreach (var t in tickets)
{
++ticketNo;
// Create directory for ticket
var dirname = string.Format(opts.m_dstFolder+"\\{0}", t.Ticket_Number);
try
{
System.IO.Directory.CreateDirectory(dirname);
}
catch (System.IO.IOException e)
{
Trace.WriteLine("Error creating dir: " + e.Message);
};
dirname += "\\";
// Retrieve ticket details (only public and not from system)
var ticketDetails = serv.GetDetailsWithHistory<Ticket>(t.Id);
var publicHistory = ticketDetails.ActionHistory.Where(x => x.Show_To_Customer && x.Action_Performer.ActionHistoryPerformerType != ParaEnums.ActionHistoryPerformerType.System ).ToList<ActionHistory>();
// Creates the html file and writes the ticket header information
var ticketStream = new System.IO.FileStream(dirname + t.Ticket_Number.ToString() + ".html", System.IO.FileMode.Create);
var ticketWriter = new System.IO.StreamWriter(ticketStream, Encoding.UTF8);
ticketWriter.WriteLine("<html><body>");
try
{
var summary = ticketDetails.CustomFields.Find(x => x.Name.ToLower() == "summary").Value;
ticketWriter.WriteLine("<h1>{0}: {1}</h1>", ticketDetails.Ticket_Number, summary);
indexWriter.WriteLine("<tr><td><a href=\"{3}.html\">{0}</a></td><td>{1}</td><td>{2}</td></tr>"
, new object[] { t.Ticket_Number, t.Date_Created.ToString(), summary, t.Ticket_Number+"/"+t.Ticket_Number});
Trace.WriteLine(string.Format("{2}: {0} - {1}", new object[] { t.Ticket_Number, summary, ticketNo }));
}catch(SystemException e)
{
Trace.WriteLine("Error getting summary: " + e.Message);
}
ticketWriter.WriteLine("<b>Ticket:</b> <a href=\"{0}\">{1}</a><br/>", ticketDetails.ServiceDeskUri, ticketDetails.Ticket_Number);
ticketWriter.WriteLine("<b>Customer:</b> {0}<br/>", ticketDetails.Ticket_Customer.Customer.Full_Name);
ticketWriter.WriteLine("<b>Date:</b> {0}<br/>", ticketDetails.Date_Created.ToString());
ticketWriter.WriteLine("<b>Assigned To:</b> {0}<br/>", t.Assigned_To.Csr.Full_Name);
try
{
ticketWriter.WriteLine("<b>Details:</b><br/>");
var details = ticketDetails.CustomFields.Find(x => x.Name.ToLower() == "details").Value.Replace("\n","<br/>");
ticketWriter.WriteLine(string.Format("<p style=\"border-style:solid; border-width:1px; background-color:rgb(245,245,245)\">{0}</p>",details));
}catch(SystemException e)
{
Trace.WriteLine("Error getting details: " + e.Message);
}
// Writes the ticket's comments
foreach (var thd in publicHistory )
{
// if from us, uses blue-ish color
string bgColor = "initial";
if ( thd.Action_Performer.ActionHistoryPerformerType == ParaEnums.ActionHistoryPerformerType.Csr )
bgColor = "rgb(240, 248, 255)";
ticketWriter.WriteLine("<hr/><b>" + thd.Action_Date.ToString() + "</b><br/>");
ticketWriter.WriteLine(string.Format("<b>{0} ({1})</b><br/>", thd.Action_Performer.GetDisplayName(), thd.Action_Performer.ActionHistoryPerformerType.ToString()));
ticketWriter.WriteLine("<p style=\"background-color:{0}\">", bgColor);
{
// attachment links
if (thd.History_Attachments.Count > 0)
{
ticketWriter.WriteLine("Attachments: ");
foreach (var att in thd.History_Attachments)
ticketWriter.WriteLine(string.Format("<a href=\"{0}\">{1}</a>, ", new object[] { thd.Action_Date.ToShortDateString().Replace('/', '_') + "_" + att.Name, att.Name }));
ticketWriter.WriteLine("<br/>");
}
// comment
ticketWriter.WriteLine("<br/>"+thd.Comments.Replace("\n","<br/>")+ "<br/>");
}
ticketWriter.WriteLine("</p>");
// Downloading attachments to disk
if ( thd.History_Attachments.Count > 0 )
{
foreach (var att in thd.History_Attachments)
{
try
{
WebClient client = new WebClient();
string finalname = dirname + thd.Action_Date.ToShortDateString().Replace('/','_') + "_" + att.Name;
client.DownloadFile(att.Href, finalname);
}
catch (System.Net.WebException e)
{
Trace.WriteLine("Error downloading: " + e.Message);
}
}
}
}
// finishes ticket html and flush index.html
ticketWriter.WriteLine("</body></html>");
ticketWriter.Close();
ticketStream.Close();
indexWriter.Flush();
}
indexWriter.WriteLine("</table>");
indexWriter.WriteLine("</body></html>");
} // Main
} // Program
} // namespace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment