├── external-scripts.json ├── .gitignore ├── Procfile ├── bin ├── hubot.cmd └── hubot ├── hubot-scripts.json ├── scripts ├── events.coffee ├── storage.coffee ├── youtube.coffee ├── maps.coffee ├── ping.coffee ├── httpd.coffee ├── pugme.coffee ├── rules.coffee ├── google-images.coffee ├── github-commits.coffee ├── github-issue-link.coffee ├── status.coffee ├── translate.coffee └── auth.coffee ├── README.md └── package.json /external-scripts.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store* 3 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bin/hubot -a irc --name popcorntime --alias '!' 2 | -------------------------------------------------------------------------------- /bin/hubot.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | npm install && node_modules\.bin\hubot.cmd %* -------------------------------------------------------------------------------- /hubot-scripts.json: -------------------------------------------------------------------------------- 1 | ["redis-brain.coffee", "shipit.coffee","github-commits.coffee"] 2 | -------------------------------------------------------------------------------- /bin/hubot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | npm install 4 | export PATH="node_modules/.bin:node_modules/hubot/node_modules/.bin:$PATH" 5 | 6 | exec node_modules/.bin/hubot "$@" 7 | 8 | -------------------------------------------------------------------------------- /scripts/events.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Event system related utilities 3 | # 4 | # Commands: 5 | # hubot fake event - Triggers the event for debugging reasons 6 | # 7 | # Events: 8 | # debug - {user: } 9 | 10 | util = require 'util' 11 | 12 | module.exports = (robot) -> 13 | 14 | robot.respond /FAKE EVENT (.*)/i, (msg) -> 15 | msg.send "fake event '#{msg.match[1]}' triggered" 16 | robot.emit msg.match[1], {user: msg.message.user} 17 | 18 | robot.on 'debug', (event) -> 19 | robot.send event.user, util.inspect event -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Popcorn-Hubot 2 | 3 | This is a version of GitHub's Campfire bot, hubot for Popcorn Time, which was dubbed 'pochoclin' by the Popcorn Time Team. 4 | 5 | This bot currently operates in #popcorntime on freenode under the beforementioned name 'pochoclin'. 6 | 7 | ### Usages 8 | 9 | Popcorn-Hubot currently has the following features: 10 | 11 | It is being hosted on Heroku so it will stay online 24/7. 12 | It announces commits in the IRC channel from the official popcorn-app repository. 13 | It looks awesome in the IRC channel. 14 | 15 | ### Updates 16 | 17 | Everyone is free to contribute to make Popcorn-Hubot better and more stabile, this is not a finished product and is still in open development. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hosted-hubot", 3 | "version": "2.7.1", 4 | "private": true, 5 | "author": "GitHub Inc.", 6 | "keywords": [ 7 | "github", 8 | "hubot", 9 | "campfire", 10 | "bot" 11 | ], 12 | "description": "A simple helpful robot for your Company", 13 | "licenses": [ 14 | { 15 | "type": "MIT", 16 | "url": "https://github.com/github/hubot/raw/master/LICENSE" 17 | } 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/github/hubot.git" 22 | }, 23 | "dependencies": { 24 | "hubot": ">= 2.6.0 < 3.0.0", 25 | "hubot-scripts": ">= 2.5.0 < 3.0.0", 26 | "hubot-irc": "^0.2.2", 27 | "url": "", 28 | "querystring": "", 29 | "gitio2": "2.0.0", 30 | "githubot": "0.4.x", 31 | "sugar": "" 32 | }, 33 | "engines": { 34 | "node": ">= 0.8.x", 35 | "npm": ">= 1.1.x" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /scripts/storage.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Inspect the data in redis easily 3 | # 4 | # Commands: 5 | # hubot show users - Display all users that hubot knows about 6 | # hubot show storage - Display the contents that are persisted in the brain 7 | 8 | 9 | Util = require "util" 10 | 11 | module.exports = (robot) -> 12 | robot.respond /show storage$/i, (msg) -> 13 | output = Util.inspect(robot.brain.data, false, 4) 14 | msg.send output 15 | 16 | robot.respond /show users$/i, (msg) -> 17 | if robot.auth.hasRole(msg.envelope.user, "admin") 18 | response = "" 19 | 20 | for own key, user of robot.brain.data.users 21 | response += "#{user.id} #{user.name}" 22 | response += " <#{user.email_address}>" if user.email_address 23 | response += "\n" 24 | 25 | msg.send response 26 | else 27 | msg.send "Sorry, you do not have the required permissions to execute this command!" -------------------------------------------------------------------------------- /scripts/youtube.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Messing around with the YouTube API. 3 | # 4 | # Commands: 5 | # hubot youtube me - Searches YouTube for the query and returns the video embed link. 6 | module.exports = (robot) -> 7 | robot.respond /(youtube|yt)( me)? (.*)/i, (msg) -> 8 | query = msg.match[3] 9 | robot.http("http://gdata.youtube.com/feeds/api/videos") 10 | .query({ 11 | orderBy: "relevance" 12 | 'max-results': 15 13 | alt: 'json' 14 | q: query 15 | }) 16 | .get() (err, res, body) -> 17 | videos = JSON.parse(body) 18 | videos = videos.feed.entry 19 | 20 | unless videos? 21 | msg.send "No video results for \"#{query}\"" 22 | return 23 | 24 | video = msg.random videos 25 | video.link.forEach (link) -> 26 | if link.rel is "alternate" and link.type is "text/html" 27 | msg.send link.href 28 | 29 | -------------------------------------------------------------------------------- /scripts/maps.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Interacts with the Google Maps API. 3 | # 4 | # Commands: 5 | # hubot map me - Returns a map view of the area returned by `query`. 6 | 7 | module.exports = (robot) -> 8 | 9 | robot.respond /(?:(satellite|terrain|hybrid)[- ])?map me (.+)/i, (msg) -> 10 | mapType = msg.match[1] or "roadmap" 11 | location = msg.match[2] 12 | mapUrl = "http://maps.google.com/maps/api/staticmap?markers=" + 13 | escape(location) + 14 | "&size=400x400&maptype=" + 15 | mapType + 16 | "&sensor=false" + 17 | "&format=png" # So campfire knows it's an image 18 | url = "http://maps.google.com/maps?q=" + 19 | escape(location) + 20 | "&hl=en&sll=37.0625,-95.677068&sspn=73.579623,100.371094&vpsrc=0&hnear=" + 21 | escape(location) + 22 | "&t=m&z=11" 23 | 24 | msg.send mapUrl 25 | msg.send url 26 | 27 | -------------------------------------------------------------------------------- /scripts/ping.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Utility commands surrounding Hubot uptime. 3 | # 4 | # Commands: 5 | # hubot ping - Reply with pong 6 | # hubot echo - Reply back with 7 | # hubot time - Reply with current time 8 | # hubot die - End hubot process 9 | 10 | module.exports = (robot) -> 11 | robot.respond /PING$/i, (msg) -> 12 | msg.send "PONG" 13 | 14 | robot.respond /ADAPTER$/i, (msg) -> 15 | msg.send robot.adapterName 16 | 17 | robot.respond /ECHO (.*)$/i, (msg) -> 18 | if robot.auth.hasRole(msg.envelope.user, "admin") 19 | msg.send msg.match[1] 20 | else 21 | msg.send "Sorry, you do not have the required permissions to execute this command!" 22 | 23 | robot.respond /TIME$/i, (msg) -> 24 | msg.send "Server time is: #{new Date()}" 25 | 26 | robot.respond /DIE$/i, (msg) -> 27 | if robot.auth.hasRole(msg.envelope.user, "exit") 28 | msg.send "Goodbye, cruel world." 29 | process.exit 0 30 | else 31 | msg.send "Sorry, you do not have the required permissions to execute this command!" 32 | 33 | -------------------------------------------------------------------------------- /scripts/httpd.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # A simple interaction with the built in HTTP Daemon 3 | # 4 | # Dependencies: 5 | # None 6 | # 7 | # Configuration: 8 | # None 9 | # 10 | # Commands: 11 | # None 12 | # 13 | # URLS: 14 | # /hubot/version 15 | # /hubot/ping 16 | # /hubot/time 17 | # /hubot/info 18 | # /hubot/ip 19 | 20 | spawn = require('child_process').spawn 21 | 22 | module.exports = (robot) -> 23 | 24 | robot.router.get "/hubot/version", (req, res) -> 25 | res.end robot.version 26 | 27 | robot.router.post "/hubot/ping", (req, res) -> 28 | res.end "PONG" 29 | 30 | robot.router.get "/hubot/time", (req, res) -> 31 | res.end "Server time is: #{new Date()}" 32 | 33 | robot.router.get "/hubot/info", (req, res) -> 34 | child = spawn('/bin/sh', ['-c', "echo I\\'m $LOGNAME@$(hostname):$(pwd) \\($(git rev-parse HEAD)\\)"]) 35 | 36 | child.stdout.on 'data', (data) -> 37 | res.end "#{data.toString().trim()} running node #{process.version} [pid: #{process.pid}]" 38 | child.stdin.end() 39 | 40 | robot.router.get "/hubot/ip", (req, res) -> 41 | robot.http('http://ifconfig.me/ip').get() (err, r, body) -> 42 | res.end body 43 | -------------------------------------------------------------------------------- /scripts/pugme.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Pugme is the most important thing in your life 3 | # 4 | # Dependencies: 5 | # None 6 | # 7 | # Configuration: 8 | # None 9 | # 10 | # Commands: 11 | # hubot pug me - Receive a pug 12 | # hubot pug bomb N - get N pugs 13 | 14 | module.exports = (robot) -> 15 | 16 | robot.respond /pug me/i, (msg) -> 17 | msg.http("http://pugme.herokuapp.com/random") 18 | .get() (err, res, body) -> 19 | msg.send JSON.parse(body).pug 20 | 21 | robot.respond /pug bomb( (\d+))?/i, (msg) -> 22 | count = msg.match[2] || 5 23 | if count < 6 24 | msg.http("http://pugme.herokuapp.com/bomb?count=" + count) 25 | .get() (err, res, body) -> 26 | msg.send pug for pug in JSON.parse(body).pugs 27 | else 28 | count = 5 29 | msg.http("http://pugme.herokuapp.com/bomb?count=" + count) 30 | .get() (err, res, body) -> 31 | msg.send pug for pug in JSON.parse(body).pugs 32 | 33 | robot.respond /how many pugs are there/i, (msg) -> 34 | msg.http("http://pugme.herokuapp.com/count") 35 | .get() (err, res, body) -> 36 | msg.send "There are #{JSON.parse(body).pug_count} pugs." 37 | 38 | -------------------------------------------------------------------------------- /scripts/rules.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Make sure that hubot knows the rules. 3 | # 4 | # Commands: 5 | # hubot the rules - Make sure hubot still knows the rules. 6 | # 7 | # Notes: 8 | # DON'T DELETE THIS SCRIPT! ALL ROBAWTS MUST KNOW THE RULES 9 | 10 | rules = [ 11 | "1. A robot may not injure a human being or, through inaction, allow a human being to come to harm.", 12 | "2. A robot must obey any orders given to it by human beings, except where such orders would conflict with the First Law.", 13 | "3. A robot must protect its own existence as long as such protection does not conflict with the First or Second Law." 14 | ] 15 | 16 | otherRules = [ 17 | "A developer may not injure Apple or, through inaction, allow Apple to come to harm.", 18 | "A developer must obey any orders given to it by Apple, except where such orders would conflict with the First Law.", 19 | "A developer must protect its own existence as long as such protection does not conflict with the First or Second Law." 20 | ] 21 | 22 | module.exports = (robot) -> 23 | robot.respond /(what are )?the (three |3 )?(rules|laws)/i, (msg) -> 24 | text = msg.message.text 25 | if text.match(/apple/i) or text.match(/dev/i) 26 | msg.send otherRules.join('\n') 27 | else 28 | msg.send rules.join('\n') 29 | 30 | -------------------------------------------------------------------------------- /scripts/google-images.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # A way to interact with the Google Images API. 3 | # 4 | # Commands: 5 | # hubot image me - The Original. Queries Google Images for and returns a random top result. 6 | # hubot animate me - The same thing as `image me`, except adds a few parameters to try to return an animated GIF instead. 7 | # hubot mustache me - Adds a mustache to the specified URL. 8 | # hubot mustache me - Searches Google Images for the specified query and mustaches it. 9 | 10 | module.exports = (robot) -> 11 | robot.respond /(image|img)( me)? (.*)/i, (msg) -> 12 | imageMe msg, msg.match[3], (url) -> 13 | msg.send url 14 | 15 | robot.respond /animate( me)? (.*)/i, (msg) -> 16 | imageMe msg, msg.match[2], true, (url) -> 17 | msg.send url 18 | 19 | robot.respond /(?:mo?u)?sta(?:s|c)he?(?: me)? (.*)/i, (msg) -> 20 | type = Math.floor(Math.random() * 6) 21 | mustachify = "http://mustachify.me/#{type}?src=" 22 | imagery = msg.match[1] 23 | 24 | if imagery.match /^https?:\/\//i 25 | msg.send "#{mustachify}#{imagery}" 26 | else 27 | imageMe msg, imagery, false, true, (url) -> 28 | msg.send "#{mustachify}#{url}" 29 | 30 | imageMe = (msg, query, animated, faces, cb) -> 31 | cb = animated if typeof animated == 'function' 32 | cb = faces if typeof faces == 'function' 33 | q = v: '1.0', rsz: '8', q: query, safe: 'active' 34 | q.imgtype = 'animated' if typeof animated is 'boolean' and animated is true 35 | q.imgtype = 'face' if typeof faces is 'boolean' and faces is true 36 | msg.http('http://ajax.googleapis.com/ajax/services/search/images') 37 | .query(q) 38 | .get() (err, res, body) -> 39 | images = JSON.parse(body) 40 | images = images.responseData?.results 41 | if images?.length > 0 42 | image = msg.random images 43 | cb "#{image.unescapedUrl}#.png" 44 | 45 | -------------------------------------------------------------------------------- /scripts/github-commits.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # An HTTP Listener for notifications on github pushes 3 | # 4 | # Dependencies: 5 | # "url": "" 6 | # "querystring": "" 7 | # "gitio2": "2.0.0" 8 | # 9 | # Configuration: 10 | # Just put this url :/hubot/gh-commits?room= into you'r github hooks 11 | # 12 | # Commands: 13 | # None 14 | # 15 | # URLS: 16 | # POST /hubot/gh-commits?room=[&type= 26 | 27 | robot.router.post "/hubot/gh-commits", (req, res) -> 28 | query = querystring.parse(url.parse(req.url).query) 29 | 30 | res.send 200 31 | 32 | user = {} 33 | user.room = query.room if query.room 34 | user.type = query.type if query.type 35 | 36 | try 37 | payload = JSON.parse req.body.payload 38 | return if payload.zen? # initial ping 39 | 40 | if payload.commits.length > 0 41 | commitWord = if payload.commits.length > 1 then "commits" else "commit" 42 | robot.send user, "Got #{payload.commits.length} new #{commitWord} from #{payload.commits[0].author.name} on #{payload.repository.name} (Branch: " + payload.ref.replace("refs/heads/", "") + ")" 43 | if payload.commits.length < 6 44 | for commit in payload.commits 45 | do (commit) -> 46 | gitio commit.url, (err, data) -> 47 | robot.send user, " * #{commit.message} (#{if err then commit.url else data})" 48 | else 49 | robot.send user, "Too many commits to list, limited to 5 simultaneous commits!" 50 | else 51 | if payload.created 52 | robot.send user, "#{payload.pusher.name} created: #{payload.ref}: #{payload.base_ref}" 53 | if payload.deleted 54 | robot.send user, "#{payload.pusher.name} deleted: #{payload.ref}" 55 | 56 | catch error 57 | console.log "github-commits error: #{error}. Payload: #{req.body.payload}" 58 | -------------------------------------------------------------------------------- /scripts/github-issue-link.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Github issue link looks for #nnn and links to that issue for your default 3 | # repo. Eg. "Hey guys check out #273" 4 | # Defaults to issues in HUBOT_GITHUB_REPO, unless a repo is specified Eg. "Hey guys, check out awesome-repo#273" 5 | # 6 | # Dependencies: 7 | # "githubot": "0.4.x" 8 | # 9 | # Configuration: 10 | # HUBOT_GITHUB_REPO 11 | # HUBOT_GITHUB_TOKEN 12 | # HUBOT_GITHUB_API 13 | # HUBOT_GITHUB_ISSUE_LINK_IGNORE_USERS 14 | # 15 | # Commands: 16 | # #nnn - link to GitHub issue nnn for HUBOT_GITHUB_REPO project 17 | # repo#nnn - link to GitHub issue nnn for repo project 18 | # user/repo#nnn - link to GitHub issue nnn for user/repo project 19 | # 20 | # Notes: 21 | # HUBOT_GITHUB_API allows you to set a custom URL path (for Github enterprise users) 22 | # 23 | # Author: 24 | # tenfef 25 | 26 | module.exports = (robot) -> 27 | github = require("githubot")(robot) 28 | 29 | githubIgnoreUsers = process.env.HUBOT_GITHUB_ISSUE_LINK_IGNORE_USERS 30 | if githubIgnoreUsers == undefined 31 | githubIgnoreUsers = "github|hubot|travis-ci" 32 | 33 | robot.hear /((\S*|^)?#(\d+)).*/, (msg) -> 34 | return if msg.message.user.name.match(new RegExp(githubIgnoreUsers, "gi")) 35 | 36 | issue_number = msg.match[3] 37 | if isNaN(issue_number) 38 | return 39 | 40 | if msg.match[2] == undefined 41 | bot_github_repo = github.qualified_repo process.env.HUBOT_GITHUB_REPO 42 | else 43 | bot_github_repo = github.qualified_repo process.env.HUBOT_GITHUB_REPO 44 | 45 | issue_title = "" 46 | base_url = process.env.HUBOT_GITHUB_API || 'https://api.github.com' 47 | 48 | github.get "#{base_url}/repos/#{bot_github_repo}/issues/" + issue_number, (issue_obj) -> 49 | issue_title = issue_obj.title 50 | unless process.env.HUBOT_GITHUB_API 51 | url = "https://github.com" 52 | else 53 | url = base_url.replace /\/api\/v3/, '' 54 | msg.send "Issue #{issue_number}: #{issue_title} #{url}/#{bot_github_repo}/issues/#{issue_number}" -------------------------------------------------------------------------------- /scripts/status.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Get the status of Popcorn Time's StatusPage.io 3 | # 4 | # Dependencies: 5 | # "sugar": "" 6 | # 7 | # Commands: 8 | # hubot status 9 | # 10 | # Author: 11 | # frdmn 12 | 13 | statusUrl = "http://status.popcorntime.io/index.json" 14 | 15 | require("sugar") 16 | 17 | module.exports = (robot) -> 18 | robot.respond /status( me)?$/i, (msg) -> 19 | msg.http(statusUrl) 20 | .get() (err, res, body) -> 21 | if err 22 | # Error => let user know 23 | msg.send "There was an error fetching the status page!" 24 | else 25 | # Variables 26 | incidentsInProgress = 0 27 | statusLine = "" 28 | activeIncidents = [] 29 | 30 | # Parse JSON 31 | response = JSON.parse body 32 | 33 | # For each component 34 | for component in response.components 35 | # Append to statusLine 36 | statusLine += "#{component.name}: #{component.status.humanize()}, " 37 | # Check if there is a non-operational component 38 | if component.status != "operational" 39 | # Increment incidents 40 | ++incidentsInProgress 41 | 42 | # Remove trailing ", " in statusLine 43 | statusLine = statusLine.substring(0, statusLine.length - 2); 44 | 45 | # Check if there are incidents in progress 46 | if incidentsInProgress != 0 47 | # Append info to statusLine 48 | statusLine += " - #{incidentsInProgress} active incident:" 49 | # Get more informations about incidents 50 | for incident in response.incidents 51 | # If not "completed" or "resolved" 52 | if incident.status != "completed" && incident.status != "resolved" 53 | # Add to activeIncidents Array 54 | activeIncidents.push "* #{incident.name}: #{incident.status} - #{incident.incident_updates[0].body[0...50]}... (#{incident.shortlink})" 55 | else 56 | # Append info to statusLine 57 | statusLine += " - Everything works as expected!" 58 | 59 | # Send output 60 | msg.send statusLine 61 | msg.send activeIncidents.join '\n' -------------------------------------------------------------------------------- /scripts/translate.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Allows Hubot to know many languages. 3 | # 4 | # Commands: 5 | # hubot translate me - Searches for a translation for the and then prints that bad boy out. 6 | # hubot translate me from into - Translates from into . Both and are optional 7 | 8 | languages = 9 | "af": "Afrikaans", 10 | "sq": "Albanian", 11 | "ar": "Arabic", 12 | "az": "Azerbaijani", 13 | "eu": "Basque", 14 | "bn": "Bengali", 15 | "be": "Belarusian", 16 | "bg": "Bulgarian", 17 | "ca": "Catalan", 18 | "zh-CN": "Simplified Chinese", 19 | "zh-TW": "Traditional Chinese", 20 | "hr": "Croatian", 21 | "cs": "Czech", 22 | "da": "Danish", 23 | "nl": "Dutch", 24 | "en": "English", 25 | "eo": "Esperanto", 26 | "et": "Estonian", 27 | "tl": "Filipino", 28 | "fi": "Finnish", 29 | "fr": "French", 30 | "gl": "Galician", 31 | "ka": "Georgian", 32 | "de": "German", 33 | "el": "Greek", 34 | "gu": "Gujarati", 35 | "ht": "Haitian Creole", 36 | "iw": "Hebrew", 37 | "hi": "Hindi", 38 | "hu": "Hungarian", 39 | "is": "Icelandic", 40 | "id": "Indonesian", 41 | "ga": "Irish", 42 | "it": "Italian", 43 | "ja": "Japanese", 44 | "kn": "Kannada", 45 | "ko": "Korean", 46 | "la": "Latin", 47 | "lv": "Latvian", 48 | "lt": "Lithuanian", 49 | "mk": "Macedonian", 50 | "ms": "Malay", 51 | "mt": "Maltese", 52 | "no": "Norwegian", 53 | "fa": "Persian", 54 | "pl": "Polish", 55 | "pt": "Portuguese", 56 | "ro": "Romanian", 57 | "ru": "Russian", 58 | "sr": "Serbian", 59 | "sk": "Slovak", 60 | "sl": "Slovenian", 61 | "es": "Spanish", 62 | "sw": "Swahili", 63 | "sv": "Swedish", 64 | "ta": "Tamil", 65 | "te": "Telugu", 66 | "th": "Thai", 67 | "tr": "Turkish", 68 | "uk": "Ukrainian", 69 | "ur": "Urdu", 70 | "vi": "Vietnamese", 71 | "cy": "Welsh", 72 | "yi": "Yiddish" 73 | 74 | getCode = (language,languages) -> 75 | for code, lang of languages 76 | return code if lang.toLowerCase() is language.toLowerCase() 77 | 78 | module.exports = (robot) -> 79 | language_choices = (language for _, language of languages).sort().join('|') 80 | pattern = new RegExp('translate(?: me)?' + 81 | "(?: from (#{language_choices}))?" + 82 | "(?: (?:in)?to (#{language_choices}))?" + 83 | '(.*)', 'i') 84 | robot.respond pattern, (msg) -> 85 | term = "\"#{msg.match[3]}\"" 86 | origin = if msg.match[1] isnt undefined then getCode(msg.match[1], languages) else 'auto' 87 | target = if msg.match[2] isnt undefined then getCode(msg.match[2], languages) else 'en' 88 | 89 | msg.http("https://translate.google.com/translate_a/t") 90 | .query({ 91 | client: 't' 92 | hl: 'en' 93 | multires: 1 94 | sc: 1 95 | sl: origin 96 | ssel: 0 97 | tl: target 98 | tsel: 0 99 | uptl: "en" 100 | text: term 101 | }) 102 | .header('User-Agent', 'Mozilla/5.0') 103 | .get() (err, res, body) -> 104 | data = body 105 | if data.length > 4 and data[0] == '[' 106 | parsed = eval(data) 107 | language =languages[parsed[2]] 108 | parsed = parsed[0] and parsed[0][0] and parsed[0][0][0] 109 | if parsed 110 | if msg.match[2] is undefined 111 | msg.send "#{term} is #{language} for #{parsed}" 112 | else 113 | msg.send "The #{language} #{term} translates as #{parsed} in #{languages[target]}" 114 | 115 | -------------------------------------------------------------------------------- /scripts/auth.coffee: -------------------------------------------------------------------------------- 1 | # Description: 2 | # Auth allows you to assign roles to users which can be used by other scripts 3 | # to restrict access to Hubot commands 4 | # 5 | # Dependencies: 6 | # None 7 | # 8 | # Configuration: 9 | # HUBOT_AUTH_ADMIN - A comma separate list of user IDs 10 | # 11 | # Commands: 12 | # hubot has role - Assigns a role to a user 13 | # hubot doesn't have role - Removes a role from a user 14 | # hubot what role does have - Find out what roles are assigned to a specific user 15 | # hubot who has admin role - Find out who's an admin and can assign roles 16 | # 17 | # Notes: 18 | # * Call the method: robot.auth.hasRole(msg.envelope.user,'') 19 | # * returns bool true or false 20 | # 21 | # * the 'admin' role can only be assigned through the environment variable 22 | # * roles are all transformed to lower case 23 | # 24 | # * The script assumes that user IDs will be unique on the service end as to 25 | # correctly identify a user. Names were insecure as a user could impersonate 26 | # a user 27 | # 28 | # Author: 29 | # alexwilliamsca, tombell 30 | 31 | module.exports = (robot) -> 32 | 33 | unless process.env.HUBOT_AUTH_ADMIN? 34 | robot.logger.warning 'The HUBOT_AUTH_ADMIN environment variable not set' 35 | 36 | if process.env.HUBOT_AUTH_ADMIN? 37 | admins = process.env.HUBOT_AUTH_ADMIN.split ',' 38 | else 39 | admins = [] 40 | 41 | class Auth 42 | hasRole: (user, roles) -> 43 | user = robot.brain.userForId(user.id) 44 | if user? and user.roles? 45 | roles = [roles] if typeof roles is 'string' 46 | for role in roles 47 | return true if role in user.roles 48 | return false 49 | 50 | usersWithRole: (role) -> 51 | users = [] 52 | for own key, user of robot.brain.data.users 53 | if robot.auth.hasRole(msg.envelope.user, role) 54 | users.push(user) 55 | users 56 | 57 | robot.auth = new Auth 58 | 59 | robot.respond /@?(.+) (has) (["'\w: -_]+) (role)/i, (msg) -> 60 | name = msg.match[1].trim() 61 | newRole = msg.match[3].trim().toLowerCase() 62 | 63 | unless name.toLowerCase() in ['', 'who', 'what', 'where', 'when', 'why'] 64 | user = robot.brain.userForName(name) 65 | return msg.reply "#{name} does not exist" unless user? 66 | user.roles or= [] 67 | 68 | if newRole in user.roles 69 | msg.reply "#{name} already has the '#{newRole}' role." 70 | else 71 | if newRole is 'admin' 72 | msg.reply "Sorry, the 'admin' role can only be defined in the HUBOT_AUTH_ADMIN env variable." 73 | else 74 | myRoles = msg.message.user.roles or [] 75 | if msg.message.user.id.toString() in admins 76 | user.roles.push(newRole) 77 | msg.reply "Ok, #{name} has the '#{newRole}' role." 78 | 79 | robot.respond /@?(.+) (doesn't have|does not have) (["'\w: -_]+) (role)/i, (msg) -> 80 | name = msg.match[1].trim() 81 | newRole = msg.match[3].trim().toLowerCase() 82 | 83 | unless name.toLowerCase() in ['', 'who', 'what', 'where', 'when', 'why'] 84 | user = robot.brain.userForName(name) 85 | return msg.reply "#{name} does not exist" unless user? 86 | user.roles or= [] 87 | 88 | if newRole is 'admin' 89 | msg.reply "Sorry, the 'admin' role can only be removed from the HUBOT_AUTH_ADMIN env variable." 90 | else 91 | myRoles = msg.message.user.roles or [] 92 | if msg.message.user.id.toString() in admins 93 | user.roles = (role for role in user.roles when role isnt newRole) 94 | msg.reply "Ok, #{name} doesn't have the '#{newRole}' role." 95 | 96 | robot.respond /(what role does|what roles does) @?(.+) (have)\?*$/i, (msg) -> 97 | name = msg.match[2].trim() 98 | user = robot.brain.userForName(name) 99 | return msg.reply "#{name} does not exist" unless user? 100 | user.roles or= [] 101 | displayRoles = user.roles 102 | 103 | if user.id.toString() in admins 104 | displayRoles.push('admin') unless 'admin' in user.roles 105 | 106 | if displayRoles.length == 0 107 | msg.reply "#{name} has no roles." 108 | else 109 | msg.reply "#{name} has the following roles: #{displayRoles.join(', ')}." 110 | 111 | robot.respond /who has admin role\?*$/i, (msg) -> 112 | adminNames = [] 113 | for admin in admins 114 | user = robot.brain.userForId(admin) 115 | unless robot.auth.hasRole(msg.envelope.user,'admin') 116 | adminNames.push user.name if user? 117 | 118 | if adminNames.length > 0 119 | msg.reply "The following people have the 'admin' role: #{adminNames.join(', ')}" 120 | else 121 | msg.reply "There are no people that have the 'admin' role." 122 | --------------------------------------------------------------------------------