!752 static S team; // null if not on slack static S botName; p { load("team"); load("botName"); } synchronized answer { if (matchAny(litlist("are we on slack", "are you on slack"), s)) if (joined()) ret "Yes, in team " + domain() + (hasToken() ? ", with token" : ", but need a token in " + getTokenFile().getAbsolutePath()); else ret "No, type 'please join slack team nlbots' or similar to join a team."; if "please join slack team *" { if (!master()) ret "You're not my master"; if (joined()) ret "Joined already (team " + domain() + "), type 'please leave slack' to leave."; S teamName = dropSuffix(".slack.com", m.unq(0)); if (!checkTeamName(teamName)) ret "Bad team name: " + teamName; team = teamName; save("team"); if (hasToken()) ret "OK."; else ret "OK. Now I need a token for " + domain() + " in " + getTokenFile().getAbsolutePath(); } if "please leave slack" { if (!master()) ret "You're not my master"; if (!joined()) ret "Not there anyway, type 'please join slack' to join."; team = null; save("team"); ret "OK, left slack team " + domain(); } if "slack bot name" { if (!joined()) ret "I'm not on slack.com, type 'please join slack' to join it."; ret botName == null ? botName : "No bot name - posting as user as defined by token"; } if "set slack bot name to *" { S name = m.unq(0); if (!isIdentifier(name)) ret "Oops, not an identifier."; if (eq(name, "none")) name = null; botName = name; save("botName"); ret "OK, bot name saved."; } if "list slack channels" exceptionToUser { if (!joined()) ret "I'm not on slack.com, type 'please join slack' to join it."; Map map = slack("channels.list", "exclude_archived", "1"); new L l; l.add("Channels list for " + domain()); l.add(""); int numJoined = 0; L channels = cast map.get("channels"); for (Map c : channels) { S name = getString(c, "name"); L members = cast c.get("members"); boolean in = isTrue(c.get("isMember")); if (in) ++numJoined; l.add("#" + name + ", members: " + l(members) + (in ? " (JOINED)" : "")); } l.add(""); l.add(numJoined == 0 ? "I have not joined any channels, please type 'join slack channel *' to do it." : "I am in " + n(numJoined, "channel") + "."); ret slackSnippet(joinLines(l)); } if "join slack channel *" { S name = dropPrefix("#", m.unq(0)); if (!isIdentifier(name)) ret "Bad channel name: " + name; Map map = slack("channels.join", "name", name); boolean ok = isTrue(map.get("ok")); boolean alreadyIn = isTrue(map.get("already_in_channel")); ret !ok ? "Error... " + structure(map) : (alreadyIn ? "OK (already in)" : "OK, joined " + quote(name) + "!"); } if "leave slack channel *" { //TODO } if "slack test post in *" exceptionToUser { S name = dropPrefix("#", m.unq(0)); if (!isIdentifier(name)) ret "Bad channel name: " + name; S channelID = slackGetChannelID(getToken(), name); if (empty(channelID)) ret "Channel " + quote(name) + "not found"; Map map = slack("chat.postMessage", "channel", channelID, "text", "Test post from Eleutheria", "username", botName, "as_user", botName == null? "true" : null); boolean ok = isTrue(map.get("ok")); ret ok ? "OK!" : "Error... " + structure(map); } } static S domain() { ret team == null ? null : team + ".slack.com"; } static boolean joined() { ret team != null; } static boolean checkTeamName(S teamName) { ret isIdentifier(teamName); } static File getTokenFile() { ret secretProgramFile(team); } static boolean hasToken() { File file = getTokenFile(); if (!file.exists()) saveTextFile(file, ""); ret nempty(getToken()); } static S getToken() { ret trim(loadTextFile(getTokenFile())); } static Map slack(S cmd, S... params) { ret slack(cmd, litmap(params)); } static Map slack(S cmd, Map params) { Map postData = new TreeMap(params); postData.put("token", getToken()); ret jsonDecodeMap(doPost(postData, "https://slack.com/api/" + cmd)); }