private void version(String channel) { try { String v = IOUtils.toString(getClass().getClassLoader().getResourceAsStream("version.txt")); sendMessage(channel,"My version is "+v); } catch (IOException e) { e.printStackTrace(); sendMessage(channel,"I don't know who I am"); } }
private void removeAutoVoice(String channel, String sender, String target) { if (!isSenderAuthorized(channel,sender)) { insufficientPermissionError(channel); return; } sendMessage("CHANSERV", "flags " + channel + " " + target + " -V"); sendMessage("CHANSERV", "devoice " + channel + " " + target); sendMessage(channel, "Voice priviledge (-V) removed for " + target); }
private void createGitHubRepository(String channel, String name, String collaborator) { try { GitHub github = GitHub.connect(); GHOrganization org = github.getOrganization("jenkinsci"); GHRepository r = org.createRepository(name, "", "", "Everyone", true); setupRepository(r); GHTeam t = getOrCreateRepoLocalTeam(org, r); if (collaborator!=null) t.add(github.getUser(collaborator)); sendMessage(channel,"New github repository created at "+r.getUrl()); } catch (IOException e) { sendMessage(channel,"Failed to create a repository: "+e.getMessage()); e.printStackTrace(); } }
/** * Creates an issue tracker component. */ private void setDefaultAssignee(String channel, String sender, String subcomponent, String owner) { if (!isSenderAuthorized(channel,sender)) { insufficientPermissionError(channel); return; } sendMessage(channel,String.format("Changing default assignee of subcomponent %s to %s",subcomponent,owner)); try { JiraScraper js = new JiraScraper(); js.setDefaultAssignee("JENKINS", subcomponent, AssigneeType.COMPONENT_LEAD, owner); sendMessage(channel,"Default assignee set to " + owner); } catch (Exception e) { sendMessage(channel,"Failed to set default assignee: "+e.getMessage()); e.printStackTrace(); } }
/** * Creates an issue tracker component. */ private void createComponent(String channel, String sender, String subcomponent, String owner) { if (!isSenderAuthorized(channel,sender)) { insufficientPermissionError(channel); return; } sendMessage(channel,String.format("Adding a new subcomponent %s to the bug tracker, owned by %s",subcomponent,owner)); try { JiraScraper js = new JiraScraper(); js.createComponent("JENKINS", subcomponent, owner, AssigneeType.COMPONENT_LEAD); sendMessage(channel,"New component created"); } catch (Exception e) { sendMessage(channel,"Failed to create a new component: "+e.getMessage()); e.printStackTrace(); } }
/** * @param newName * If not null, rename a epository after a fork. */ private void forkGitHub(String channel, String owner, String repo, String newName) { try { sendMessage(channel, "Forking "+repo); GitHub github = GitHub.connect(); GHUser user = github.getUser(owner); if (user==null) { sendMessage(channel,"No such user: "******"No such repository: "+repo); return; } GHOrganization org = github.getOrganization("jenkinsci"); GHRepository r; try { r = orig.forkTo(org); } catch (IOException e) { // we started seeing 500 errors, presumably due to time out. // give it a bit of time, and see if the repository is there System.out.println("GitHub reported that it failed to fork "+owner+"/"+repo+". But we aren't trusting"); Thread.sleep(3000); r = org.getRepository(repo); if (r==null) throw e; } if (newName!=null) r.renameTo(newName); // GitHub adds a lot of teams to this repo by default, which we don't want Set<GHTeam> legacyTeams = r.getTeams(); GHTeam t = getOrCreateRepoLocalTeam(org, r); t.add(user); // the user immediately joins this team // the Everyone group gets access to this new repository, too. GHTeam everyone = org.getTeams().get("Everyone"); everyone.add(r); setupRepository(r); sendMessage(channel, "Created https://github.com/jenkinsci/" + (newName != null ? newName : repo)); // remove all the existing teams for (GHTeam team : legacyTeams) team.remove(r); } catch (InterruptedException e) { sendMessage(channel,"Failed to fork a repository: "+e.getMessage()); e.printStackTrace(); } catch (IOException e) { sendMessage(channel,"Failed to fork a repository: "+e.getMessage()); e.printStackTrace(); } }
/** * Adds a new collaborator to existing repositories. * * @param justForThisRepo * Null to add to "Everyone", otherwise add him to a team specific repository. */ private void addGitHubCommitter(String channel, String sender, String collaborator, String justForThisRepo) { if (!isSenderAuthorized(channel,sender)) { insufficientPermissionError(channel); return; } try { GitHub github = GitHub.connect(); GHUser c = github.getUser(collaborator); GHOrganization o = github.getOrganization("jenkinsci"); GHTeam t = justForThisRepo==null ? o.getTeams().get("Everyone") : getOrCreateRepoLocalTeam(o, o.getRepository(justForThisRepo)); if (t==null) { sendMessage(channel,"No team for "+justForThisRepo); return; } t.add(c); o.publicize(c); sendMessage(channel,"Added "+collaborator+" as a GitHub committer"); } catch (IOException e) { sendMessage(channel,"Failed to create a repository: "+e.getMessage()); e.printStackTrace(); } }
private void replyBugStatus(String channel, String number) { Long time = (Long)recentIssues.get(number); recentIssues.put(number,System.currentTimeMillis()); if (time!=null) { if (System.currentTimeMillis()-time < 60*1000) { return; // already mentioned recently. don't repeat } } try { sendMessage(channel, getSummary(number)); } catch (Exception e) { e.printStackTrace(); } }
@Override protected void onMessage(String channel, String sender, String login, String hostname, String message) { if (!channel.equals("#jenkins")) return; // not in this channel if (sender.equals("jenkinsci_builds")) return; // ignore messages from other bots message = message.trim(); String prefix = getNick() + ":"; if (!message.startsWith(prefix)) { // not send to me Matcher m = Pattern.compile("(?:hudson-|jenkins-|bug )([0-9]+)",CASE_INSENSITIVE).matcher(message); while (m.find()) { replyBugStatus(channel,m.group(1)); } return; } String payload = message.substring(prefix.length(), message.length()).trim(); // replace duplicate whitespace with a single space payload = payload.replaceAll("\\s+", " "); Matcher m; m = Pattern.compile("(?:create|make|add) (\\S+)(?: repository)? (?:on|in) github(?: for (\\S+))?",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { createGitHubRepository(channel, m.group(1), m.group(2)); return; } m = Pattern.compile("fork (\\S+)/(\\S+)(?: on github)?(?: as (\\S+))?",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { forkGitHub(channel, m.group(1),m.group(2),m.group(3)); return; } m = Pattern.compile("(?:make|give|grant|add) (\\S+)(?: as)? (?:a )?(?:committ?er|commit access) (?:of|on|to|at) (\\S+)",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { addGitHubCommitter(channel,sender,m.group(1),m.group(2)); return; } m = Pattern.compile("(?:make|give|grant|add) (\\S+)(?: as)? (a )?(committ?er|commit access).*",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { addGitHubCommitter(channel,sender,m.group(1),null); return; } m = Pattern.compile("(?:create|make|add) (\\S+)(?: component)? in (?:the )?(?:issue|bug)(?: tracker| database)? for (\\S+)",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { createComponent(channel, sender, m.group(1), m.group(2)); return; } m = Pattern.compile("(?:make|set) (\\S+) (?:the |as )?(?:lead|default assignee) (?:for|of) (\\S+)",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { setDefaultAssignee(channel, sender, m.group(2), m.group(1)); return; } m = Pattern.compile("(?:make|give|grant|add) (\\S+) voice(?: on irc)?",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { grantAutoVoice(channel,sender,m.group(1)); return; } m = Pattern.compile("(?:rem|remove|ungrant|del|delete) (\\S+) voice(?: on irc)?",CASE_INSENSITIVE).matcher(payload); if (m.matches()) { removeAutoVoice(channel,sender,m.group(1)); return; } if (payload.equalsIgnoreCase("version")) { version(channel); return; } if (payload.equalsIgnoreCase("help")) { help(channel); return; } if (payload.equalsIgnoreCase("refresh")) { // get the updated list sendRawLine("NAMES #jenkins"); return; } sendMessage(channel,"I didn't understand the command"); try { PrintWriter w = new PrintWriter(new FileWriter(unknownCommands, true)); w.println(payload); w.close(); } catch (IOException e) {// if we fail to write, let it be. e.printStackTrace(); } }
private void insufficientPermissionError(String channel) { sendMessage(channel,"Only people with + or @ can run this command."); // I noticed that sometimes the bot just get out of sync, so ask the sender to retry sendRawLine("NAMES #jenkins"); sendMessage(channel,"I'll refresh the member list, so if you think this is an error, try again in a few seconds."); }
private void help(String channel) { sendMessage(channel,"See http://wiki.jenkins-ci.org/display/JENKINS/IRC+Bot"); }