Skip to content

Instantly share code, notes, and snippets.

@GaProgMan
Last active March 22, 2017 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GaProgMan/d49329198e78191d620f178f94d9c73c to your computer and use it in GitHub Desktop.
Save GaProgMan/d49329198e78191d620f178f94d9c73c to your computer and use it in GitHub Desktop.
Code snippets for the blog post /2017/03/23/hack24-2017
<div class="jumbotron">
<h1>Customer Service Logger</h1>
<div class="row">
<div class="col-xs-6">
<input type="text" id="username" placeholder="username" />
</div>
<div class="col-xs-6">
<a id="btn-signin" class="btn btn-success btn-lg">Sign in</a>
</div>
</div>
<p class="lead">Log your customer service interaction by clicking "Start" when you begin your conversation with a customer</p>
<p class="lead">Once the customer is satisfied with the service you have suplied, click "Stop"</p>
<div class="pull-left"><a id="btn-start" class="btn btn-success btn-lg">Start</a></div>
<div class="pull-left"><a id="btn-stop" class="btn btn-success btn-lg" style="display:none;">Stop</a></div>
<div id="clockdiv" style="display:none;">
<div>
<span class="minutes"></span>
<div class="smalltext">Minutes</div>
</div>
<div>
<span class="seconds"></span>
<div class="smalltext">Seconds</div>
</div>
</div>
</div>
@section scripts{
<script type="text/javascript">
var running = false;
var timeInterval = null;
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
return {
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
if (running) {
var t = getTimeRemaining(endtime);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
$(document).ready(function () {
$('#btn-signin').on('click', function () {
$('#username').attr('disabled', 'disabled');
$('#btn-signin').hide();
});
$('#btn-start').on('click', function () {
if ($('#username').val().length === 0) {
alert('Please sign in');
} else {
$('#btn-start').hide();
$('#btn-stop').show();
$('#clockdiv').show();
running = true;
var deadline = new Date(Date.parse(new Date()) + 2 * 60 * 1000);
initializeClock('clockdiv', deadline);
}
});
$('#btn-stop').on('click', function () {
$('#btn-start').hide();
$('#btn-stop').hide();
running = false;
var timeRemaining = ($('.minutes').text() * 60) + $('.seconds').text();
var route = 'game-server-url';
var model = {
username: $('#username').val(),
completed: timeRemaining > 0,
timeRemaining: timeRemaining
}
$.post(route, model, function () {
}).fail(function () {
}).always(function () {
$('#btn-start').show();
$('#btn-stop').hide();
var deadline = new Date(Date.parse(new Date()) + 15 * 60 * 1000);
initializeClock('clockdiv', deadline);
});
});
});
</script>
}
namespace asti.GitHubHookApi.Models
{
public class GitHubCommitJson
{
[JsonProperty("files")]
public ICollection<GitHubCommitFileDetails> Files { get; set; }
[JsonProperty("commit")]
public GitHubCommitDetails CommitDetails { get; set; }
}
public class GitHubCommitDetails
{
[JsonProperty("author")]
public GitHubAuthorDetails Author { get; set; }
}
public class GitHubAuthorDetails
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
}
public class GitHubCommitFileDetails
{
[JsonProperty("filename")]
public string Filename { get; set; }
[JsonProperty("modified")]
// TODO make this into an enum
public string Status { get; set; }
[JsonProperty("raw_url")]
public string RawUrl { get; set; }
[JsonProperty("additions")]
public int Additions { get; set; }
[JsonProperty("deletions")]
public int Deletions { get; set; }
public int NumberOfModifications()
{
return Additions + Deletions;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace asti.GitHubHookApi.Helpers
{
public static class GitHubGetHelper
{
public static async Task<string> PerformGetAsync(string urlToResource)
{
var fullUrlWithAuth = GitHubApiUrlHelper.AddOathToApiCall(urlToResource);
using (var client = new HttpClient())
{
try
{
var request = new HttpRequestMessage()
{
RequestUri = fullUrlWithAuth,
Method = HttpMethod.Get
};
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent",
"Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
var response = await client.SendAsync(request);
var taskData = response.Content.ReadAsStringAsync();
return await taskData;
}
catch (HttpRequestException)
{
return String.Empty;
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
namespace asti.GitHubHookApi.Helpers
{
public static class GitHubGetHelper
{
public static async Task<string> PerformGetAsync(string urlToResource)
{
var fullUrlWithAuth = GitHubApiUrlHelper.AddOathToApiCall(urlToResource);
using (var client = new HttpClient())
{
try
{
var request = new HttpRequestMessage()
{
RequestUri = fullUrlWithAuth,
Method = HttpMethod.Get
};
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent",
"Mozilla/5.0 (Windows NT 6.2; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0");
var response = await client.SendAsync(request);
var taskData = response.Content.ReadAsStringAsync();
return await taskData;
}
catch (HttpRequestException)
{
return String.Empty;
}
}
}
}
}
namespace asti.GitHubHookApi.Models
{
public class GitHubPushJson
{
[JsonProperty("ref")]
public string Ref { get; set; }
[JsonProperty("compare")]
public string CompareUrl { get; set; }
[JsonProperty("after")]
public string AfterSha { get; set; }
[JsonProperty("pusher")]
public PullPusherJson Pusher { get; set; }
[JsonProperty("commits")]
public ICollection<PushCommitJson> Commits { get; set; }
[JsonProperty("head_commit")]
public PushHeadCommitJson HeadCommit { get; set; }
[JsonProperty("repository")]
public PullRepositoryJson Repository { get; set; }
public string CommitsApiUrl()
{
return Repository != null ? Repository.CommitsUrl.Replace("{/sha}", $"/{AfterSha}") : string.Empty;
}
/*
"pusher": {
"name": "baxterthehacker",
"email": "baxterthehacker@users.noreply.github.com"
},
*/
/// <summary>
/// Represents the user who pushed the commit to a push JSON
/// (all fields mapped)
/// https://developer.github.com/v3/activity/events/types/#pushevent
/// </summary>
public class PullPusherJson
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
}
/*
{
"id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
"tree_id": "f9d2a07e9488b91af2641b26b9407fe22a451433",
"distinct": true,
"message": "Update README.md",
"timestamp": "2015-05-05T19:40:15-04:00",
"url": "https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
"author": {
"name": "baxterthehacker",
"email": "baxterthehacker@users.noreply.github.com",
"username": "baxterthehacker"
},
"committer": {
"name": "baxterthehacker",
"email": "baxterthehacker@users.noreply.github.com",
"username": "baxterthehacker"
},
"added": [
],
"removed": [
],
"modified": [
"README.md"
]
}
*/
/// <summary>
/// Represents a commit form a Push event
/// (not all fields represented here)
/// https://developer.github.com/v3/activity/events/types/#pushevent
/// </summary>
public class PushCommitJson
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("message")]
public string CommitMessage { get; set; }
[JsonProperty("timestamp")]
public string TimeStampAsString { get; set; }
[JsonProperty("url")]
public string CommitUrl { get; set; }
[JsonProperty("added")]
public ICollection<string> Added { get; set; }
[JsonProperty("removed")]
public ICollection<string> Removed { get; set; }
[JsonProperty("modified")]
public ICollection<string> Modified { get; set; }
}
/*
"head_commit": {
"id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
"tree_id": "f9d2a07e9488b91af2641b26b9407fe22a451433",
"distinct": true,
"message": "Update README.md",
"timestamp": "2015-05-05T19:40:15-04:00",
"url": "https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c",
"author": {
"name": "baxterthehacker",
"email": "baxterthehacker@users.noreply.github.com",
"username": "baxterthehacker"
},
}
*/
public class PushHeadCommitJson
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("distinct")]
public bool Distinct { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("timestamp")]
public string TimestampAsString { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
}
public class PushHeadCommitAuthor : PullPusherJson
{
[JsonProperty("username")]
public string UserName { get; set; }
}
/*
"repository": {
"id": 35129377,
"name": "public-repo",
"full_name": "baxterthehacker/public-repo",
"owner": {
"name": "baxterthehacker",
"email": "baxterthehacker@users.noreply.github.com"
},
"private": false,
"html_url": "https://github.com/baxterthehacker/public-repo",
"description": "",
"fork": false,
"url": "https://github.com/baxterthehacker/public-repo",
"forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks",
"keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams",
"hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks",
"issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}",
"events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events",
"assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}",
"branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}",
"tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags",
"blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages",
"stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers",
"contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors",
"subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers",
"subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription",
"commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}",
"compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges",
"archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads",
"issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}",
"pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}",
"releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}",
"created_at": 1430869212,
"updated_at": "2015-05-05T23:40:12Z",
"pushed_at": 1430869217,
"git_url": "git://github.com/baxterthehacker/public-repo.git",
"ssh_url": "git@github.com:baxterthehacker/public-repo.git",
"clone_url": "https://github.com/baxterthehacker/public-repo.git",
"svn_url": "https://github.com/baxterthehacker/public-repo",
"homepage": null,
"size": 0,
"stargazers_count": 0,
"watchers_count": 0,
"language": null,
"has_issues": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": true,
"forks_count": 0,
"mirror_url": null,
"open_issues_count": 0,
"forks": 0,
"open_issues": 0,
"watchers": 0,
"default_branch": "master",
"stargazers": 0,
"master_branch": "master"
}
*/
public class PullRepositoryJson
{
[JsonProperty("html_url")]
public string HtmlUrl { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("commits_url")]
public string CommitsUrl { get; set; }
}
}
}
using asti.GitHubHookApi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace asti.GitHubHookApi.Helpers
{
public class LinterHelper
{
private static string LinterPostUrl = "list-post-url";
public static async Task<string> PerformPostAsyc(string data)
{
using (var client = new HttpClient())
{
var responce = await client.PostAsync(LinterPostUrl,
new StringContent(data, Encoding.UTF8, "application/json"));
var responseData = await responce.Content.ReadAsStringAsync();
return responseData;
}
}
}
}
using asti.GitHubHookApi.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace asti.GitHubHookApi.Helpers
{
public sealed class LinterSingleton
{
private static readonly LinterSingleton instance = new LinterSingleton();
static LinterSingleton()
{
}
private LinterSingleton()
{
}
public static LinterSingleton Instance
{
get
{
return instance;
}
}
public string SendFilesToLinter(List<LintData> fileData)
{
var json = JsonConvert.SerializeObject(fileData);
var response = LinterHelper.PerformPostAsyc(json);
return response.Result;
}
}
}
[HttpPost]
[Route("/PushEndPoint")]
public async string PushEndPoint(string payload)
{
try
{
var pushDetails = JsonConvert.DeserializeObject<GitHubPushJson>(payload);
var commitsString = await GitHubGetHelper.PerformGetAsync(pushDetails.CommitsApiUrl());
}
catch (Exception e)
{
return "fail";
}
return "parsed Ok";
}
[HttpPost]
[Route("/PushEndPoint")]
public async string PushEndPoint(string payload)
{
try
{
var pushDetails = JsonConvert.DeserializeObject<GitHubPushJson>(payload);
}
catch (Exception e)
{
return "fail";
}
return "parsed Ok";
}
[HttpPost]
[Route("/PushEndPoint")]
public async void PushEndPoint(string payload)
{
var pushDetails = JsonConvert.DeserializeObject<GitHubPushJson>(payload);
var commitsString = await GitHubGetHelper.PerformGetAsync(pushDetails.CommitsApiUrl());
var commits = JsonConvert.DeserializeObject<GitHubCommitJson>(commitsString);
var jsFileUrls = commits.Files
.Where(fi => fi.Filename.EndsWith(".js"))
.Select(fi => new LintData
{
FileUrl = fi.RawUrl,
ModCount = fi.NumberOfModifications(),
UserName = commits.CommitDetails.Author.Email
}).ToList();
LinterSingleton.Instance.SendFilesToLinter(jsFileUrls);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment