From a5d02d19ff73d2eb895636edf800d9c2875719ef Mon Sep 17 00:00:00 2001 From: reality Date: Thu, 11 Jul 2013 15:25:45 +0000 Subject: [PATCH] add github as reg --- modules/github/LICENSE | 18 ++++ modules/github/README.md | 28 +++++ modules/github/config.json | 8 ++ modules/github/github.js | 200 ++++++++++++++++++++++++++++++++++++ modules/github/strings.json | 68 ++++++++++++ 5 files changed, 322 insertions(+) create mode 100644 modules/github/LICENSE create mode 100644 modules/github/README.md create mode 100644 modules/github/config.json create mode 100644 modules/github/github.js create mode 100644 modules/github/strings.json diff --git a/modules/github/LICENSE b/modules/github/LICENSE new file mode 100644 index 0000000..b52fb8d --- /dev/null +++ b/modules/github/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2013 Douglas Gardner + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/modules/github/README.md b/modules/github/README.md new file mode 100644 index 0000000..12d7a9d --- /dev/null +++ b/modules/github/README.md @@ -0,0 +1,28 @@ +## Github + +Grabs interesting data from the GitHub API. + +### Description + +This module for [depressionbot](https://github.com/reality/depressionbot) takes some interesting information about Github and parses it in a pleasing manner. + +### Configuration +#### defaultrepo +When repository information is lacking from the command, this repository will be used. +#### sortorder +Defines the behaviour of ~issue when no arguments are given. Options are ``created``, ``updated``, or ``comments``. +### Commands +#### ~commits +Returns the number of commits in the repository of the current depressionbot instance. +#### ~gstatus +Returns the [current status of Github](https://status.github.com), and a message explaining the current state of affairs. +#### ~issue (user/repo) [id] +Gives information about the isse pecified, from the default repository if one is not explicitly stated. +#### ~milestone [milestone name] +Returns milestone progress for any given milestone, with a link to the milestone in question. +#### ~repo (repo name) +Returns information about the repo given as a parameter. The repo should be specified as ``user/name``; for example, ``twitter/snowflake``. +#### ~repocount [user] +Returns the number of public Github repositories for the specified user. +### Dependencies +* [request](https://github.com/mikeal/request/):``$ npm install request`` diff --git a/modules/github/config.json b/modules/github/config.json new file mode 100644 index 0000000..2721da9 --- /dev/null +++ b/modules/github/config.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ "command" ], + "ignorable": true, + "help": "http://github.com/zuzak/dbot-github/blob/master/README.md", + "defaultrepo": "reality/dbot", + "sortorder": "updated", + "useragent": "reality/depressionbot github module" +} diff --git a/modules/github/github.js b/modules/github/github.js new file mode 100644 index 0000000..2ca7aa3 --- /dev/null +++ b/modules/github/github.js @@ -0,0 +1,200 @@ +/** + * Module Name: Github + * Description: Retrieves interesting Github information + */ +var request = require('request'), + exec = require('child_process').exec; + +var github = function(dbot) { + this.api = { + "githubStatus": function(callback){ + var reqUrl = "https://status.github.com/api/last-message.json"; + request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) { + callback(JSON.parse(body)); + }); + } + }; + + + var commands = { + '~repocount': function(event) { + var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos"; + request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) { + if(response.statusCode == "200") { + var result = JSON.parse(body); + event.reply(dbot.t("repocount",{"user": event.params[1], "count": result.length})); + } else { + event.reply(dbot.t("usernotfound")); + } + }); + }, + '~repo': function(event) { + var repo = event.params[1]; + if (typeof repo == 'undefined') { + repo = this.config.defaultrepo; + } + + var reqUrl = "https://api.github.com/"; + reqUrl += "repos/" + repo; + request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) { + + var data = JSON.parse(body); + if (data["fork"]) { + event.reply(dbot.t("forkedrepo",data)); + } else { + event.reply(dbot.t("unforkedrepo",data)); + } + // TODO: move this shizz into an api call + var longurl = "http://github.com/" + repo; + request({method: 'POST', uri: 'http://git.io', form:{url: longurl}}, function(error, response, body){ + event.reply(dbot.t('location')+" "+response.headers["location"]); + }); + }); + }, + '~gstatus': function(event) { + data = this.api.githubStatus(function(data){ + console.log(data); + event.reply(dbot.t("status"+data["status"])); + event.reply(data["body"]); + }.bind(this)); + }, + '~milestone': function(event) { + var repo = this.config.defaultrepo; + var name = event.params[1]; + if (event.params[2]){ + repo = name; + name = event.params[2]; + } + var reqUrl = "https://api.github.com/repos/"; + reqUrl += repo + "/milestones"; + + request({"url": reqUrl, "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) { + var data = JSON.parse(body); + for (var section in data) { + var milestone = data[section]; + if (milestone["title"] == name){ + var str = "Milestone " + milestone["title"]; + var progress = milestone["closed_issues"] / (milestone["open_issues"] + milestone["closed_issues"]); + progress = Math.round(progress*100); + var bar = "["; + for (var i = 10; i < 100; i += 10) { + if ((progress/i) > 1) { + bar += "█"; + } else { + bar += " "; + } + } + bar += "]"; + str += " is " + bar + progress + "% complete"; + + var longurl = "http://github.com/" + repo + "/issues?milestone=" + milestone["number"]; + request({method: 'POST', uri: 'http://git.io', form:{url: longurl}}, function(error, response, body){ + event.reply(response.headers["location"]); + }); + event.reply(str); + break; + } + } + }); + }, + '~repocount': function(event) { + // TODO: add handling for non existent user + var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos"; + request({"url": reqUrl,"headers": { "User-Agent": this.config.useragent}}, function(error, response, body) { + var result = JSON.parse(body); + event.reply(event.params[1] + " has " + result.length + " public repositories."); + }); + }, + '~grate': function(event) { + request.get({"url":"https://api.github.com/rate_limit", "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) { + var data = JSON.parse(body); + if (data.message){ + event.reply(data.message); + } else { + event.reply(data.rate.remaining + " requests of " + data.rate.limit + " remaining."); + } + }); + }, + '~issue': function(event) { + var repo, issue, randflag; + if (isNaN(event.params[1]) && event.params[1]){ // if ~issue foo/bar + repo = event.params[1]; + issue = event.params[2]; + } else { + repo = this.config.defaultrepo; + issue = event.params[1]; + } + + if (issue == "*" || issue == "random" || issue == "0") { + issue = ""; + randflag = true; + } else if (!issue) { // issue is undefined + issue = ""; + } else { + issue = "/" + issue; // got to be a better way + } + + var reqUrl = "https://api.github.com/repos/" + repo + "/issues" + + issue + "?sort=" + this.config.sortorder; + request.get({"url": reqUrl, headers: { "User-Agent": this.config.useragent}}, function(error,response, body) { + if (response.statusCode == "200") { + var data = JSON.parse(body); + if (!issue){ + if (randflag) { + data = data[Math.floor(Math.random() * data.length)]; + } else { + data = data[0]; + } + } + if (data["pull_request"]["html_url"]){ + console.log(data["pull_request"]["html_url"]); + data["pull_request"] = " with code"; + } else { + data["pull_request"] = ""; + } + if (data["state"]=="open") { + data["state"] = "\u000303" + data["state"]; + } else { + data["state"] = "\u000304" + data["state"]; + } + var labels = ""; + for (var i=0; i < data["labels"].length; i++) { // for-in doesn't like me + var color = "\u0003" + (parseInt(data["labels"][i]["color"],16) % 15); + labels += " " + color + data["labels"][i]["name"]; + } + data["label"] = labels; + event.reply(dbot.t("issue",data)); + event.reply(data["html_url"]); + } else { + event.reply(dbot.t("issuenotfound")); + } + }); + }, + '~commits': function(event) { + exec("git rev-list --all | wc -l", function(error, stdout, stderr) { + stdout = stdout.trim(); + request({"url":"http://numbersapi.com/" + stdout + "?fragment&default=XXX"}, function(error, response, body){ + if (body != "XXX"){ + event.reply(dbot.t("commitcountfun",{"fact": body, "count": stdout})); + } else { + // nothing fun about the number, let's try the year + request({"url":"http://numbersapi.com/" + stdout + "/year?fragment&default=XXX"}, function(error, response, body){ + if (body != "XXX"){ + event.reply(dbot.t("commitcountyear",{"fact": body, "count": stdout})); + } else { + event.reply(dbot.t("commitcountboring",{"count": stdout})); + } + }); + } + }); + }); + } + }; + this.commands = commands; + + this.on = 'PRIVMSG'; +}; + +exports.fetch = function(dbot) { + return new github(dbot); +}; diff --git a/modules/github/strings.json b/modules/github/strings.json new file mode 100644 index 0000000..bd1fec1 --- /dev/null +++ b/modules/github/strings.json @@ -0,0 +1,68 @@ +{ + "repocount": { + "en": "{user} has {count} public repos.", + "cy": "Mae {count} archifdai cyhoeddus gan {user}.", + "de": "{user} hat {count} öffnetliche Repos." + }, + "statusgood": { + "en": "\u000309Shit's fine", + "cy": "\u000309Cachu'n ddirwy", + "de": "\u000309Alles in Ordnung" + }, + "statusminor": { + "en": "\u000308Shit's touchy", + "cy": "\u000308Cachu'n fregus", + "de": "\u000308Kleinere Probleme vorhanden" + }, + "statusmajor": { + "en": "\u000304Shit's fucked:", + "cy": "\u000304Cachu wedi cyrraedd y ffan:", + "de": "\u000304Du bist am Arsch" + }, + "location": { + "en": "You can find that shit at:", + "cy": "Gallwch ddod o hyd y cachu yn:", + "de": "Kann nicht gefunden werden:" + }, + "forkedrepo": { + "en": "{name} is a forked {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]", + "cy": "{name} ydy archif {language} fforchog gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]", + "de": "{name} ist eine geteilte {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]" + }, + "unforkedrepo": { + "en": "{name} is a {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]", + "cy": "{name} ydy archif {language} gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]", + "de": "{name} ist eine {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]" + }, + "usernotfound": { + "en": "User not found.", + "cy": "Defnyddiwr heb ei ganfod.", + "de": "Benutzer nicht gefunden." + }, + "issuenotfound": { + "en": "Unable to find that issue.", + "cy": "Wedi methu dod o hyd mater hwnnw", + "de": "Kann dieses Problem nicht finden." + }, + "issue": { + "en": "Issue \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}", + "cy": "Mater \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} sylwadau]{label}", + "de": "Problem \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}" + }, + "commitcountboring": { + "en": "My code has been committed {count} times.", + "cy": "Mae fy cod wedi cael ei gyflawni ar {count} adegau.", + "de": "Mein Code wurde {count} mal überstellt." + }, + "commitcountfun": { + "en": "My repository has the same number of commits as {fact} ({count}).", + "cy": "Yr un nifer o ymrwymo fel {fact} gan fy archif ({count}).", + "de": "Meine Repository hat die gleiche Anzahl Commits wie {fact} ({count})." + }, + "commitcountyear": { + "en": "My repository's commits number {count}, the year that {fact}.", + "cy": "Nifer o ymrwymo gan fy archif: {count}, y flwyddyn y {fact}.", + "de": "Anzahl der Commits in meinem Repository {count}, des Jahres {fact}" + } +} +