!7 // TODO: check user's rights when accepting an upload !include once #1026298 // DynTalkBot2 for JDA 4.0 standardBot1 RolesExporter { init { myName = "HyperCubes"; preprocessAtSelfToMyName = true; } sync S processSimplifiedLine(S s, O... _) null { try answer super.processSimplifiedLine(s, _); optPar long channelID; if (channelID == 0) null; optPar Message msg; Message.Attachment attachment = msg == null ? null : first(msg.getAttachments()); if (attachment != null) { File file = downloadFileForChannel(channelID); print("Downloading attachment " + attachment.getFileName() + " to " + file); deleteFile(file); attachment.downloadToFile(file) .exceptionally(error -> { temp enter(); print("download fail"); ret null with postInChannel(channelID, "Couldn't download attachment"); }) .thenAccept(file2 -> postInChannel(channelID, handleAttachment(file2))); } if null (s = dropMyPrefixOrNull(s)) null; if "help" ret trimAllLines([[ @myName export - export roles + members as JSON @myName rights - check bot's rights @myName diff - diff last upload against server Upload a JSON file to get it diffed with current server ]].replace("@myName", myName); if "rights" ret "Manage roles: " + yesNo(canManageRoles()); if "diff" { File f = downloadFileForChannel(channelID); if (!fileExists(f)) ret "No past upload found in this channel"; ret pairA(diff(f)); } if "add roles" { if (!msg.getMember().hasPermission(Permission.MANAGE_ROLES)) ret "You have no permission to do that you sneaky boy"; File f = downloadFileForChannel(channelID); if (!fileExists(f)) ret "No past upload found in this channel"; Pair p = diff(f); if (p == null) ret "There was an error with the last upload"; Map diff = cast p.b; mapGet(diff, "roles"); } } File downloadFileForChannel(long channelID) { ret prepareCacheProgramFile(guildID + "/" + channelID); } bool canManageRoles() { ret guild.getSelfMember().hasPermission(Permission.MANAGE_ROLES); } Map makeData() { L roles = map(guild.getRoles(), r -> litorderedmap( "name" := r.getName(), "id" := r.getIdLong(), "permissions" := r.getPermissionsRaw())); L members = map(guild.getMembers(), m -> litorderedmap( "nickName" := m.getNickname(), "effectiveName" := m.getEffectiveName(), "userName" := m.getUser().getName(), "id" := m.getIdLong(), "isOwner" := trueOrNull(m.isOwner()), "roles" := map(m.getRoles(), r -> litorderedmap("name" := r.getName(), "id" := r.getIdLong())))); ret litorderedmap( dataType := "members and roles for guild", dateExported := dateWithSecondsGMT(), guild := litorderedmap( name := guild.getName(), id := guild.getIdLong()), +roles, +members); } S handleAttachment(File file) enter { try { print("Handling attachment " + f2s(file)); ret pairA(diff(file)); } catch print e { ret "Internal error"; } } // returns null if error // else: result for user, diff Pair diff(File file) { O json; try { json = decodeJson(loadTextFile(file)); } catch e { ret null with print("Not a JSON file: " + f2s(file)); } new JsonDiff differ; // identify roles by names and members by ID differ.getListKey = path -> eq(last(path), 'allRoles) ? 'name : 'id; fixImportedData(json); O diff = differ.diff(makeData(), json); //ret "Differences: " + structForUser(diff); ret t3("Differences:\n" + nicelyFormatJsonDiff(diff), true, diff); } void fixImportedData(O data) { changeKey((Map) data, 'allRoles, 'roles); } }