Dans notre entreprise, nous exploitions le PukiWiki sur site avant de rejoindre l'entreprise, mais cette fois j'ai déménagé vers esa.io \ (⁰⊖⁰) / La raison principale est que je suis entré dans esa, mais j'ai aussi eu beaucoup d'insatisfaction avec la gestion sur site mendokuse et le désir d'utiliser Markdown plutôt que la notation Wiki. Cet article est comme un journal de travail qui migre rapidement les articles stockés dans PukiWiki vers esa.io. J'ai honte d'annoncer le programme de migration, donc si vous voulez faire la même chose, veuillez vous y référer.
https://esa.io/ En termes simples, c'est un outil de partage d'informations de type Wiki. J'aime le fait que les obstacles au partage d'informations sont très faibles, et les différentes fonctionnalités «accessibles aux endroits qui piquent» qui facilitent l'édition et la gestion des articles. Quand je l'ai utilisé dans l'essai gratuit, c'était une série de "Oh!".
Le fichier txt de l'article est stocké dans le dossier "wiki" sur le serveur PukiWiki. Copiez-le à l'emplacement désigné. Ensuite, exécutez le programme de migration ci-dessous et vous êtes prêt à partir. Le programme de migration a été réalisé avec java.
Puisqu'il utilise l'API Web d'ESA, obtenez un jeton d'accès à l'avance. Vous pouvez l'obtenir depuis "Applications" dans les paramètres de l'équipe, dans la partie "Jetons d'accès personnels".
C'est un programme jetable, donc je l'ai fait avec une grande dynamique. Je n'ai fait aucun effort pour le rendre plus facile à lire, donc je pense que c'est difficile à faire quand on veut jouer un peu avec. .. .. Si vous avez quelque chose comme "Je ne sais pas ce que cela signifie ici", veuillez demander dans les commentaires. Veuillez changer la partie marquée avec ★ dans le programme en fonction de votre environnement avant de l'exécuter. L'API esa est une spécification qui ne peut être appelée que jusqu'à 75 fois en 15 minutes, mais si cette limite est dépassée, j'essaye d'attendre de pouvoir la rappeler.
public class WikiMigrationToEsa
{
private static Client apiClient = ClientBuilder.newClient();
private static MutableList<Pair<Integer, Twin<String>>> documentList = Lists.mutable.empty();
//★ Spécifiez le dossier où se trouvent les fichiers de l'article wiki
private static final String wikiFilePath = "C:\\Users\\hoge\\wiki";
//★esa.jeton d'accès io
private static final String authorizationKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
//★ Nom de l'équipe
private static final String teamName = "hogehoge";
public static void main(String[] args)
{
//Les fichiers d'article du wiki Esa un par un.Publier sur io
try (final Stream<Path> pathStream = Files.walk(Paths.get(wikiFilePath)))
{
pathStream
.map(path -> path.toFile())
.filter(file -> !file.isDirectory())
.filter(file -> file.getName().toLowerCase().endsWith(".txt"))
.forEach(file -> postWikiFile(file.toPath()));
} catch (final IOException e) {
e.printStackTrace();
return;
}
//Liens Esa dans le wiki pour les articles publiés.Mettre à jour au format io
patchInnerLink();
}
public static void postWikiFile(Path wikiItemFile)
{
EsaPostItemDto content = new EsaPostItemDto();
content.post = new EsaPostBodyDto();
StringBuilder bodyText = new StringBuilder();
//Titre
String wikiFileName = StringUtils.substringBefore(wikiItemFile.toFile().getName(), ".");
byte[] bytes;
try
{
bytes = Hex.decodeHex(wikiFileName);
} catch (DecoderException e)
{
e.printStackTrace();
return;
}
String itemName = "";
try
{
itemName = new String(bytes, "EUC-JP");
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
return;
}
//Correction d'un problème où les barres obliques demi-largeur dans les titres étaient reconnues comme des catégories
itemName = RegExUtils.replaceAll(itemName, "/", "/");
try (FileInputStream fileInputStream = new FileInputStream(wikiItemFile.toFile());
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "EUC-JP");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
)
{
String lineTmp;
int lineNo = 0;
boolean isCodeBlock = false;
boolean isTable = false;
while ((lineTmp = bufferedReader.readLine()) != null) {
lineNo++;
byte[] lineBytes = lineTmp.getBytes();
String line = new String(lineBytes, "UTF-8");
if(lineNo == 1)
{
if(StringUtils.startsWithIgnoreCase(line, "#freeze"))
{
return;
}
}
if(StringUtils.startsWithIgnoreCase(line, "#ref") || StringUtils.startsWithIgnoreCase(line, "&ref"))
{
String fileName = StringUtils.substringBetween(line, "(", ")");
fileName = RegExUtils.replaceAll(fileName, "(^[^\\.]+\\.[^,]+),.+", "$1");
line = "![" + fileName + "](http://hoge/fuga/index.php?plugin=attach&refer="+URLEncoder.encode(itemName,"EUC-JP")+"&openfile="+URLEncoder.encode(fileName,"EUC-JP")+")";
}
if(!isCodeBlock && StringUtils.startsWith(line, " "))
{
isCodeBlock = true;
bodyText.append("```");
bodyText.append(System.getProperty("line.separator"));
}
if(isCodeBlock)
{
if(StringUtils.startsWith(line, " "))
{
bodyText.append(line);
bodyText.append(System.getProperty("line.separator"));
continue;
}
else
{
bodyText.append("```");
bodyText.append(System.getProperty("line.separator"));
isCodeBlock = false;
}
}
if(!isTable && StringUtils.startsWith(line, "|"))
{
isTable = true;
int columnCount = StringUtils.countMatches(line, "|");
bodyText.append(System.getProperty("line.separator"));
if(StringUtils.endsWith(line, "h"))
{
bodyText.append(StringUtils.substringBeforeLast(line, "h"));
bodyText.append(System.getProperty("line.separator"));
bodyText.append(StringUtils.repeat("|", "-----", columnCount));
bodyText.append(System.getProperty("line.separator"));
continue;
}
else
{
bodyText.append(StringUtils.repeat("|", "header", columnCount));
bodyText.append(System.getProperty("line.separator"));
bodyText.append(StringUtils.repeat("|", "-----", columnCount));
bodyText.append(System.getProperty("line.separator"));
bodyText.append(line);
bodyText.append(System.getProperty("line.separator"));
continue;
}
}
if(isTable)
{
if(StringUtils.startsWith(line, "|"))
{
bodyText.append(line);
bodyText.append(System.getProperty("line.separator"));
continue;
}
else
{
bodyText.append(System.getProperty("line.separator"));
isTable = false;
}
}
line = RegExUtils.replaceAll(line, "\\[#[0-9a-z]+\\]$", "");
line = RegExUtils.replaceAll(line, "^\\*\\*\\*", "### ");
line = RegExUtils.replaceAll(line, "^\\*\\*", "## ");
line = RegExUtils.replaceAll(line, "^\\*", "# ");
line = RegExUtils.replaceAll(line, "^---", " - ");
line = RegExUtils.replaceAll(line, "^--", " - ");
line = RegExUtils.replaceAll(line, "^-", "- ");
line = RegExUtils.replaceAll(line, "^\\+\\+\\+", " 1\\. ");
line = RegExUtils.replaceAll(line, "^\\+\\+", " 1\\. ");
line = RegExUtils.replaceAll(line, "^\\+", "1\\. ");
line = RegExUtils.replaceAll(line, "^\\+", "1\\. ");
line = RegExUtils.replaceAll(line, "''", "\\*\\*");
line = RegExUtils.replaceAll(line, "%%", "~~");
line = RegExUtils.replaceAll(line, "\\[\\[([^\\]^:^>]+)[:|>]([^:^/^\\]]+://[^\\]]+)\\]\\]","\\[$1\\]\\($2\\)");
bodyText.append(line);
bodyText.append(System.getProperty("line.separator"));
}
}
catch (IOException e)
{
e.printStackTrace();
return;
}
content.post.body_md = bodyText.toString();
content.post.name = itemName;
content.post.wip = false;
content.post.message = "Migrer depuis le wiki";
content.post.user = "esa_bot";
Response apiResponse = apiClient.target("https://api.esa.io/v1/teams/" + teamName + "/posts")
.request()
.header("Authorization", "Bearer " + authorizationKey)
.header("Content-Type", "application/json")
.post(Entity.entity(content, MediaType.APPLICATION_JSON));
System.out.println(apiResponse.getStatus());
JSONObject postResponseBody = new JSONObject(apiResponse.readEntity(String.class));
System.out.println("number : " + postResponseBody.getLong("number"));
documentList.add(
Tuples.pair(
postResponseBody.getInt("number")
,Tuples.twin(
itemName
, bodyText.toString()
)
)
);
waitAPILimit(apiResponse);
}
private static void patchInnerLink()
{
Pattern linkPattern = Pattern.compile("(\\[\\[[^\\]^>]+>[^\\]^:^/]+\\]\\]|\\[\\[[^\\]^>]+\\]\\])");
documentList.each(post -> {
Twin<String> postItem = post.getTwo();
Matcher postMatcher = linkPattern.matcher(postItem.getTwo());
StringBuffer sb = new StringBuffer();
while(postMatcher.find())
{
String linkString = postMatcher.group();
//linkString peut avoir ou non un alias, donc dans le cas d'un alias>Sortez après
if(StringUtils.contains(linkString, ">"))
{
linkString = StringUtils.substringAfter(linkString, ">");
}
final String linkItemName = RegExUtils.removeAll(linkString, "\\[|\\]");
Pair<Integer, Twin<String>> linkedItem = documentList.select(post2 -> StringUtils.equals(linkItemName, post2.getTwo().getOne())).getFirst();
if(linkedItem != null)
{
postMatcher.appendReplacement(sb, "[#" + linkedItem.getOne() + ": " + linkItemName + "](/posts/"+linkedItem.getOne()+")");
}
}
postMatcher.appendTail(sb);
EsaPostItemDto content = new EsaPostItemDto();
content.post = new EsaPostBodyDto();
content.post.body_md = sb.toString();
content.post.name = postItem.getOne();
content.post.wip = false;
content.post.message = "Mise à jour du lien interne";
content.post.updated_by = "esa_bot";
Response patchResponse = apiClient
.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true)
.target("https://api.esa.io/v1/teams/" + teamName + "/posts/" + post.getOne())
.request()
.header("Authorization", "Bearer " + authorizationKey)
.header("Content-Type", "application/json")
.method("PATCH", Entity.entity(content, MediaType.APPLICATION_JSON))
;
System.out.println(patchResponse.getStatus());
waitAPILimit(patchResponse);
});
}
private static void waitAPILimit(Response apiResponse)
{
String remaining = apiResponse.getHeaderString("X-RateLimit-Remaining");
System.out.println("X-RateLimit-Remaining : " + remaining);
if(StringUtils.equals(remaining, "0"))
{
System.out.println("X-Rate-Limit-Reset : " + apiResponse.getHeaderString("X-RateLimit-Reset"));
OffsetDateTime reset = OffsetDateTime.ofInstant(Instant.ofEpochSecond(Long.valueOf(apiResponse.getHeaderString("X-RateLimit-Reset"))), ZoneId.systemDefault());
System.out.println("X-Rate-Limit-Reset : " + reset.format(DateTimeFormatter.ISO_DATE_TIME));
//Ajouter 1 minute compte tenu de la possibilité que l'horloge ne soit pas correcte
reset = reset.plusMinutes(1);
while(reset.isAfter(OffsetDateTime.now(ZoneId.systemDefault())))
{
try
{
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e)
{
e.printStackTrace();
System.exit(0);
}
}
}
}
}
EsaPostBodyDto.java
public class EsaPostBodyDto
{
public String name;
public String body_md;
public List<String> tags;
public String category;
public boolean wip;
public String message;
public String user;
public String updated_by;
}
EsaPostItemDto.java
public class EsaPostItemDto
{
public EsaPostBodyDto post;
}
pom.xml
<dependencies>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- servlet-api -->
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Apache Commons Lang -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<!-- jersey -->
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.25</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.25</version>
</dependency>
<!-- eclipse collections -->
<dependency>
<groupId>org.eclipse.collections</groupId>
<artifactId>eclipse-collections-api</artifactId>
<version>8.0.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.collections</groupId>
<artifactId>eclipse-collections</artifactId>
<version>8.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
Recommended Posts