Initial import
This commit is contained in:
parent
0b463863c1
commit
40b0204508
25 changed files with 875 additions and 0 deletions
41
.github/GitHub-Actions.org
vendored
Normal file
41
.github/GitHub-Actions.org
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
* Deploying using Github Actions
|
||||||
|
|
||||||
|
** Actions definition: workflow/sonatype-deploy.yml
|
||||||
|
|
||||||
|
When a GitHub Release is created, usually from a tag, this action will trigger.
|
||||||
|
|
||||||
|
Using JDK8 the software will be packaged, including running any tests.
|
||||||
|
|
||||||
|
Then the Deploy script will sign the created artifacts then deploy them according to the distributionManagement configuration in the `pom.xml`.
|
||||||
|
|
||||||
|
** Deploy Script
|
||||||
|
|
||||||
|
Uses a signing key provided from the GitHub Actions Secrets as an environment variable to sign the artifact(s) before they are then deployed.
|
||||||
|
|
||||||
|
*** Inputs
|
||||||
|
|
||||||
|
**** DEPLOY_PROJECTS (optional)
|
||||||
|
|
||||||
|
An optional list of modules in a multi-module project to be deployed. If this value is not specified, then all projects will be deployed.
|
||||||
|
|
||||||
|
** Maven Configuration
|
||||||
|
|
||||||
|
Picks up the credentials from Environment variables for authenticating both with GPG and with the target deployment server (e.g. sonatype-nexus).
|
||||||
|
|
||||||
|
*** Inputs
|
||||||
|
|
||||||
|
**** NEXUS_USERNAME
|
||||||
|
|
||||||
|
The username for your account on the deployment server.
|
||||||
|
|
||||||
|
**** NEXUS_PASSWORD
|
||||||
|
|
||||||
|
The password for your account on the deployement server.
|
||||||
|
|
||||||
|
**** GPG_KEYNAME
|
||||||
|
|
||||||
|
The key to use when signing.
|
||||||
|
|
||||||
|
**** GPG_PASSPHRASE
|
||||||
|
|
||||||
|
The passphrase to unlock the key to use when signing.
|
45
.github/NOTES
vendored
Normal file
45
.github/NOTES
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
Add subkeys:
|
||||||
|
|
||||||
|
????
|
||||||
|
|
||||||
|
Backup:
|
||||||
|
|
||||||
|
gpg --export --armor pcampbell@kemitix.net > gpg-key-backup.asc
|
||||||
|
gpg --export-secret-keys --armor pcampbell@kemitix.net >> gpg-key-backup.asc
|
||||||
|
|
||||||
|
Export sub-keys:
|
||||||
|
|
||||||
|
gpg --export-secret-subkeys pcampbell@kemitix.net > subkeys
|
||||||
|
|
||||||
|
Remove master keys:
|
||||||
|
|
||||||
|
gpg --delete-secret-key pcampbell@kemitix.net
|
||||||
|
|
||||||
|
Import sub-keys and clean up:
|
||||||
|
|
||||||
|
gpg --import subkeys
|
||||||
|
|
||||||
|
shred --remove subkeys
|
||||||
|
|
||||||
|
Delete any encryption subkeys:
|
||||||
|
|
||||||
|
gpg --edit-key pcampbell@kemitix.net
|
||||||
|
|
||||||
|
2
|
||||||
|
delkey
|
||||||
|
save
|
||||||
|
|
||||||
|
Change passphrase:
|
||||||
|
|
||||||
|
gpg --edit-key pcampbell@kemitix.net
|
||||||
|
passwd
|
||||||
|
save
|
||||||
|
|
||||||
|
Export keys:
|
||||||
|
|
||||||
|
gpg --export --armor pcampbell@kemitix.net > codesigning.asc
|
||||||
|
gpg --export-secret-keys --armor pcampbell@kemitix.net >> codesigning.asc
|
||||||
|
|
||||||
|
Encrypt keys:
|
||||||
|
|
||||||
|
gpg --symmetric --cipher-algo AES256 codesigning.asc
|
BIN
.github/codesigning.asc.gpg
vendored
Normal file
BIN
.github/codesigning.asc.gpg
vendored
Normal file
Binary file not shown.
43
.github/deploy.sh
vendored
Normal file
43
.github/deploy.sh
vendored
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Decrypts the signing key in .github/codesigning.asc.enc
|
||||||
|
# Imports that key
|
||||||
|
# Uses .github/settings.xml and the release profile to deploy
|
||||||
|
|
||||||
|
echo "deploy.sh: Starting..."
|
||||||
|
|
||||||
|
(
|
||||||
|
cd .github
|
||||||
|
|
||||||
|
echo "Retrieving GPG Private KEY"
|
||||||
|
gpg --quiet \
|
||||||
|
--batch \
|
||||||
|
--yes \
|
||||||
|
--decrypt \
|
||||||
|
--passphrase="${GPG_PASSPHRASE}" \
|
||||||
|
--output codesigning.asc \
|
||||||
|
codesigning.asc.gpg
|
||||||
|
|
||||||
|
echo "Loading signing key"
|
||||||
|
gpg --batch \
|
||||||
|
--fast-import codesigning.asc
|
||||||
|
)
|
||||||
|
|
||||||
|
if test -z ${DEPLOY_PROJECTS}
|
||||||
|
then
|
||||||
|
PROJECTS=""
|
||||||
|
echo "Deploying Projects: all"
|
||||||
|
else
|
||||||
|
PROJECTS="-pl ${DEPLOY_PROJECTS}"
|
||||||
|
echo "Deploying Projects: $DEPLOY_PROJECTS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Releasing..."
|
||||||
|
mvn ${PROJECTS} \
|
||||||
|
--settings .github/settings.xml \
|
||||||
|
-Dskip-Tests=true \
|
||||||
|
-P release \
|
||||||
|
-B \
|
||||||
|
deploy
|
||||||
|
|
||||||
|
echo "deploy.sh: Done."
|
28
.github/settings.xml
vendored
Normal file
28
.github/settings.xml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
|
||||||
|
<servers>
|
||||||
|
<server>
|
||||||
|
<id>sonatype-nexus-snapshots</id>
|
||||||
|
<username>${env.NEXUS_USERNAME}</username>
|
||||||
|
<password>${env.NEXUS_PASSWORD}</password>
|
||||||
|
</server>
|
||||||
|
<server>
|
||||||
|
<id>sonatype-nexus-staging</id>
|
||||||
|
<username>${env.NEXUS_USERNAME}</username>
|
||||||
|
<password>${env.NEXUS_PASSWORD}</password>
|
||||||
|
</server>
|
||||||
|
</servers>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>gpg-sign</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<gpg.executable>gpg</gpg.executable>
|
||||||
|
<gpg.keyname>${env.GPG_KEYNAME}</gpg.keyname>
|
||||||
|
<gpg.passphrase>${env.GPG_PASSPHRASE}</gpg.passphrase>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</settings>
|
22
.github/workflows/maven-build.yml
vendored
Normal file
22
.github/workflows/maven-build.yml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# This workflow will build a Java project with Maven
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||||
|
|
||||||
|
name: Java CI with Maven
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 1.8
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 1.8
|
||||||
|
- name: Build with Maven
|
||||||
|
run: mvn -B package --file pom.xml
|
24
.github/workflows/sonatype-deploy.yml
vendored
Normal file
24
.github/workflows/sonatype-deploy.yml
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
name: Deploy to Sonatype Nexus
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 1.8
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 1.8
|
||||||
|
- name: Build with Maven
|
||||||
|
run: mvn -B package
|
||||||
|
- name: Nexus Repo Publish
|
||||||
|
run: sh .github/deploy.sh
|
||||||
|
env:
|
||||||
|
NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
|
||||||
|
NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
|
||||||
|
GPG_KEYNAME: ${{ secrets.GPG_KEYNAME }}
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
32
.gitignore
vendored
Normal file
32
.gitignore
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
nohup.out
|
||||||
|
.install
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jetbrains
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
7
README.md
Normal file
7
README.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Kemitix Trello
|
||||||
|
|
||||||
|
Wrapper for Trello.
|
||||||
|
|
||||||
|
This wraps the `com.taskadapter:trello-java-wrapper` library.
|
||||||
|
|
||||||
|
It is intended for use on my `slushy` and `fuller` projects. It was originally developed as part of `slushy` and was extracted when preparing to start on `fuller` which would need some of the same functionality.
|
79
pom.xml
Normal file
79
pom.xml
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>net.kemitix</groupId>
|
||||||
|
<artifactId>kemitix-parent</artifactId>
|
||||||
|
<version>5.3.0</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>kemitix-trello</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<tiles-maven-plugin.version>2.18</tiles-maven-plugin.version>
|
||||||
|
<kemitix-tiles.version>2.10.0</kemitix-tiles.version>
|
||||||
|
|
||||||
|
<trello-java-wrapper.version>0.14</trello-java-wrapper.version>
|
||||||
|
<lombok.version>1.18.16</lombok.version>
|
||||||
|
<camel-api.version>3.6.0</camel-api.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.taskadapter</groupId>
|
||||||
|
<artifactId>trello-java-wrapper</artifactId>
|
||||||
|
<version>${trello-java-wrapper.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.inject</groupId>
|
||||||
|
<artifactId>javax.inject</artifactId>
|
||||||
|
<version>1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.annotation</groupId>
|
||||||
|
<artifactId>javax.annotation-api</artifactId>
|
||||||
|
<version>1.3.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.camel</groupId>
|
||||||
|
<artifactId>camel-api</artifactId>
|
||||||
|
<version>${camel-api.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.enterprise</groupId>
|
||||||
|
<artifactId>jakarta.enterprise.cdi-api</artifactId>
|
||||||
|
<version>2.0.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.repaint.maven</groupId>
|
||||||
|
<artifactId>tiles-maven-plugin</artifactId>
|
||||||
|
<version>${tiles-maven-plugin.version}</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<tiles>
|
||||||
|
<tile>net.kemitix.tiles:maven-plugins:${kemitix-tiles.version}</tile>
|
||||||
|
<tile>net.kemitix.tiles:compiler-jdk-lts:${kemitix-tiles.version}</tile>
|
||||||
|
</tiles>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
28
src/main/java/net/kemitix/trello/Attachment.java
Normal file
28
src/main/java/net/kemitix/trello/Attachment.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public interface Attachment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the attachment file.
|
||||||
|
*
|
||||||
|
* @return the name of the file
|
||||||
|
*/
|
||||||
|
File getFilename();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downlaods the file to local file system.
|
||||||
|
*
|
||||||
|
* @return the name of the local file.
|
||||||
|
*/
|
||||||
|
LocalAttachment download();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The original filename.
|
||||||
|
*
|
||||||
|
* @return the name of the file originally
|
||||||
|
*/
|
||||||
|
File getOriginalFilename();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public interface AttachmentDirectory {
|
||||||
|
File createFile(File fileName);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AttachmentDirectoryImpl implements AttachmentDirectory {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(
|
||||||
|
AttachmentDirectoryImpl.class.getName());
|
||||||
|
|
||||||
|
private Path dir;
|
||||||
|
private List<File> toDelete = new ArrayList<>();
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
void init() throws IOException {
|
||||||
|
dir = Files.createTempDirectory("attachments");
|
||||||
|
LOG.info("Attachments directory: " + dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File createFile(File fileName) {
|
||||||
|
File file = dir.resolve(fileName.getName()).toFile();
|
||||||
|
LOG.info("Created attachment: " + file);
|
||||||
|
toDelete.add(file);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void deleteFiles() {
|
||||||
|
toDelete.stream()
|
||||||
|
.peek(file -> LOG.info("Deleting: " + file))
|
||||||
|
.map(File::delete)
|
||||||
|
.filter(deleted -> !deleted)
|
||||||
|
.forEach(r -> LOG.warning("Could not delete file"));
|
||||||
|
if (dir.toFile().delete()) {
|
||||||
|
LOG.info("Deleted directory: " + dir);
|
||||||
|
} else {
|
||||||
|
LOG.warning("Could not delete directory: " + dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
src/main/java/net/kemitix/trello/CardWithAttachments.java
Normal file
40
src/main/java/net/kemitix/trello/CardWithAttachments.java
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import com.julienvey.trello.Trello;
|
||||||
|
import com.julienvey.trello.domain.Card;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class CardWithAttachments {
|
||||||
|
private final com.julienvey.trello.domain.Card tcard;
|
||||||
|
private final Trello trello;
|
||||||
|
private AttachmentDirectory attachmentDir;
|
||||||
|
|
||||||
|
private CardWithAttachments(
|
||||||
|
Card tcard,
|
||||||
|
Trello trello,
|
||||||
|
AttachmentDirectory attachmentDir
|
||||||
|
) {
|
||||||
|
this.tcard = tcard;
|
||||||
|
this.trello = trello;
|
||||||
|
this.attachmentDir = attachmentDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CardWithAttachments create(
|
||||||
|
Card tcard,
|
||||||
|
Trello trello,
|
||||||
|
AttachmentDirectory attachmentDir
|
||||||
|
) {
|
||||||
|
return new CardWithAttachments(tcard, trello, attachmentDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<Attachment> findAttachments() {
|
||||||
|
return trello.getCardAttachments(tcard.getId()).stream()
|
||||||
|
.map(attachment -> TrelloAttachment
|
||||||
|
.create(attachment, tcard, attachmentDir));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return tcard.getName();
|
||||||
|
}
|
||||||
|
}
|
18
src/main/java/net/kemitix/trello/KemitixTrelloClient.java
Normal file
18
src/main/java/net/kemitix/trello/KemitixTrelloClient.java
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import com.julienvey.trello.TrelloHttpClient;
|
||||||
|
import com.julienvey.trello.impl.TrelloImpl;
|
||||||
|
|
||||||
|
public class KemitixTrelloClient
|
||||||
|
extends TrelloImpl
|
||||||
|
implements TrelloClient {
|
||||||
|
|
||||||
|
public KemitixTrelloClient(
|
||||||
|
String applicationKey,
|
||||||
|
String accessToken,
|
||||||
|
TrelloHttpClient httpClient
|
||||||
|
) {
|
||||||
|
super(applicationKey, accessToken, httpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
src/main/java/net/kemitix/trello/ListUtils.java
Normal file
15
src/main/java/net/kemitix/trello/ListUtils.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ListUtils {
|
||||||
|
|
||||||
|
public static <A, B> List<B> map(List<A> a, Function<A, B> f) {
|
||||||
|
return a.stream()
|
||||||
|
.map(f)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/main/java/net/kemitix/trello/LoadCard.java
Normal file
26
src/main/java/net/kemitix/trello/LoadCard.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import org.apache.camel.Header;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class LoadCard {
|
||||||
|
|
||||||
|
private final TrelloBoard trelloBoard;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public LoadCard(TrelloBoard trelloBoard) {
|
||||||
|
this.trelloBoard = trelloBoard;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrelloCard loadCard(@Header("SlushyCardId") String cardId) {
|
||||||
|
return Objects.requireNonNull(
|
||||||
|
trelloBoard.getCard(cardId),
|
||||||
|
"Card Not Found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
src/main/java/net/kemitix/trello/LocalAttachment.java
Normal file
38
src/main/java/net/kemitix/trello/LocalAttachment.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An attachment that has already been downloaded.
|
||||||
|
*
|
||||||
|
* Calling download, is a noop that returns the local file.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class LocalAttachment
|
||||||
|
implements Attachment {
|
||||||
|
|
||||||
|
private final File filename;
|
||||||
|
private final File originalFilename;
|
||||||
|
private final long length;
|
||||||
|
|
||||||
|
public LocalAttachment(
|
||||||
|
File filename,
|
||||||
|
File originalFilename,
|
||||||
|
long length
|
||||||
|
) {
|
||||||
|
this.filename = filename;
|
||||||
|
this.originalFilename = originalFilename;
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isZero() {
|
||||||
|
return length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalAttachment download() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
87
src/main/java/net/kemitix/trello/TrelloAttachment.java
Normal file
87
src/main/java/net/kemitix/trello/TrelloAttachment.java
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import com.julienvey.trello.domain.Card;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class TrelloAttachment implements Attachment {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(
|
||||||
|
TrelloAttachment.class.getName());
|
||||||
|
|
||||||
|
private static final String[] EXTENSIONS = new String[]{"doc", "docx", "odt"};
|
||||||
|
private final com.julienvey.trello.domain.Attachment attachment;
|
||||||
|
private final Card card;
|
||||||
|
private final AttachmentDirectory attachmentDirectory;
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
private TrelloAttachment(
|
||||||
|
com.julienvey.trello.domain.Attachment attachment,
|
||||||
|
Card card,
|
||||||
|
AttachmentDirectory attachmentDirectory
|
||||||
|
) {
|
||||||
|
this.attachment = attachment;
|
||||||
|
this.card = card;
|
||||||
|
this.attachmentDirectory = attachmentDirectory;
|
||||||
|
this.id = card.getIdShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Attachment create(
|
||||||
|
com.julienvey.trello.domain.Attachment attachment,
|
||||||
|
Card card,
|
||||||
|
AttachmentDirectory dir
|
||||||
|
) {
|
||||||
|
return new TrelloAttachment(attachment, card, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFilename() {
|
||||||
|
return new File(String.format("%4s - %s.%s",
|
||||||
|
id, card.getName(), extension()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extension() {
|
||||||
|
URI uri = URI.create(attachment.getUrl());
|
||||||
|
String path = uri.getPath();
|
||||||
|
for (String ex : EXTENSIONS) {
|
||||||
|
if (path.endsWith("." + ex)) {
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalAttachment download() {
|
||||||
|
try (var source = Channels.newChannel(getUrl().openStream());){
|
||||||
|
File filename = new File(attachment.getName());
|
||||||
|
LOG.info("Downloading from " + filename);
|
||||||
|
var file = attachmentDirectory.createFile(getFilename());
|
||||||
|
LOG.info("Downloading to " + file.getCanonicalPath());
|
||||||
|
try (var channel = new FileOutputStream(file).getChannel()) {
|
||||||
|
long length = channel.transferFrom(source, 0, Long.MAX_VALUE);
|
||||||
|
LOG.info("Downloaded length: " + length);
|
||||||
|
return new LocalAttachment(file, filename, length);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getOriginalFilename() {
|
||||||
|
return getFilename();
|
||||||
|
}
|
||||||
|
|
||||||
|
private URL getUrl() throws MalformedURLException {
|
||||||
|
return URI.create(attachment.getUrl()).toURL();
|
||||||
|
}
|
||||||
|
}
|
108
src/main/java/net/kemitix/trello/TrelloBoard.java
Normal file
108
src/main/java/net/kemitix/trello/TrelloBoard.java
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import com.julienvey.trello.NotFoundException;
|
||||||
|
import com.julienvey.trello.Trello;
|
||||||
|
import com.julienvey.trello.domain.*;
|
||||||
|
import com.julienvey.trello.domain.Attachment;
|
||||||
|
import lombok.extern.java.Log;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static net.kemitix.trello.ListUtils.map;
|
||||||
|
|
||||||
|
@Log
|
||||||
|
@ApplicationScoped
|
||||||
|
public class TrelloBoard {
|
||||||
|
|
||||||
|
private final Trello trello;
|
||||||
|
private final TrelloConfig trelloConfig;
|
||||||
|
|
||||||
|
private List<TList> lists;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TrelloBoard(
|
||||||
|
Trello trello,
|
||||||
|
TrelloConfig trelloConfig
|
||||||
|
) {
|
||||||
|
this.trello = trello;
|
||||||
|
this.trelloConfig = trelloConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
void init () {
|
||||||
|
lists = board().fetchLists();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Board board() {
|
||||||
|
String userName = trelloConfig.getUserName();
|
||||||
|
log.info("User: " + userName);
|
||||||
|
String boardName = trelloConfig.getBoardName();
|
||||||
|
log.info("Loading Board: " + boardName);
|
||||||
|
return trello
|
||||||
|
.getMemberBoards(userName)
|
||||||
|
.stream()
|
||||||
|
.filter(board -> board.getName().equals(boardName))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new NotFoundException("Board: " + boardName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TList getList(String listName) {
|
||||||
|
return lists
|
||||||
|
.stream()
|
||||||
|
.filter(list -> list.getName().equals(listName))
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow(() -> new NotFoundException("List: " + listName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateCard(TrelloCard card) {
|
||||||
|
trello.updateCard(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TrelloCard> getListCards(String listName) {
|
||||||
|
return trello.getListCards(getListId(listName)).stream()
|
||||||
|
.map(card -> TrelloCard.from(card, trello))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Attachment> getAttachments(Card card) {
|
||||||
|
return trello.getCardAttachments(card.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrelloCard addMemberToCard(TrelloCard card, Member member) {
|
||||||
|
var members = trello.addMemberToCard(card.getId(), member.getId());
|
||||||
|
card.setIdMembers(map(members, Member::getId));
|
||||||
|
trello.updateCard(card);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrelloCard removeMemberFromCard(TrelloCard card, Member member) {
|
||||||
|
var members = trello.removeMemberFromCard(card.getId(), member.getId());
|
||||||
|
card.setIdMembers(map(members, Member::getId));
|
||||||
|
trello.updateCard(card);
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getListId(String listName) {
|
||||||
|
return getList(listName).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBoardId() {
|
||||||
|
return board().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<String> getListNames() {
|
||||||
|
return lists.stream()
|
||||||
|
.map(TList::getName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrelloCard getCard(String cardId) {
|
||||||
|
Card card = trello.getCard(cardId);
|
||||||
|
return TrelloCard.from(card, trello);
|
||||||
|
}
|
||||||
|
}
|
43
src/main/java/net/kemitix/trello/TrelloCard.java
Normal file
43
src/main/java/net/kemitix/trello/TrelloCard.java
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.julienvey.trello.Trello;
|
||||||
|
import com.julienvey.trello.domain.Card;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class TrelloCard extends Card {
|
||||||
|
|
||||||
|
private boolean dueComplete;
|
||||||
|
|
||||||
|
public static TrelloCard from(Card card, Trello trello) {
|
||||||
|
TrelloCard s = new TrelloCard();
|
||||||
|
s.setInternalTrello(trello);
|
||||||
|
s.setId(card.getId());
|
||||||
|
s.setName(card.getName());
|
||||||
|
s.setIdList(card.getIdList());
|
||||||
|
s.setDesc(card.getDesc());
|
||||||
|
s.setUrl(card.getUrl());
|
||||||
|
s.setDue(card.getDue());
|
||||||
|
s.setIdMembers(card.getIdMembers());
|
||||||
|
s.setLabels(card.getLabels());
|
||||||
|
s.setBadges(card.getBadges());
|
||||||
|
s.setCheckItemStates(card.getCheckItemStates());
|
||||||
|
s.setClosed(card.isClosed());
|
||||||
|
s.setDateLastActivity(card.getDateLastActivity());
|
||||||
|
s.setIdBoard(card.getIdBoard());
|
||||||
|
s.setIdChecklists(card.getIdChecklists());
|
||||||
|
s.setIdMembersVoted(card.getIdMembersVoted());
|
||||||
|
s.setIdShort(card.getIdShort());
|
||||||
|
s.setIdAttachmentCover(card.getIdAttachmentCover());
|
||||||
|
s.setManualCoverAttachment(card.isManualCoverAttachment());
|
||||||
|
s.setPos(card.getPos());
|
||||||
|
s.setShortLink(card.getShortLink());
|
||||||
|
s.setShortUrl(card.getShortUrl());
|
||||||
|
s.setSubscribed(card.isSubscribed());
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
7
src/main/java/net/kemitix/trello/TrelloClient.java
Normal file
7
src/main/java/net/kemitix/trello/TrelloClient.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import com.julienvey.trello.Trello;
|
||||||
|
|
||||||
|
public interface TrelloClient
|
||||||
|
extends Trello {
|
||||||
|
}
|
48
src/main/java/net/kemitix/trello/TrelloConfig.java
Normal file
48
src/main/java/net/kemitix/trello/TrelloConfig.java
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
public interface TrelloConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Trello Developer API Key.
|
||||||
|
*
|
||||||
|
* <p>https://trello.com/app-key</p>
|
||||||
|
*/
|
||||||
|
String getTrelloKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Trello Developer API Key Token.
|
||||||
|
*
|
||||||
|
* <p>https://trello.com/app-key</p>
|
||||||
|
*/
|
||||||
|
String getTrelloSecret();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the user with access to the Trello Slush Pile Board.
|
||||||
|
*/
|
||||||
|
String getUserName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The trello board containing the Slush Pile.
|
||||||
|
*/
|
||||||
|
String getBoardName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The email address to send submission attachments to.
|
||||||
|
*
|
||||||
|
* <p>e.g. the kindle address</p>
|
||||||
|
*/
|
||||||
|
String getSender();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The email address to send emails from.
|
||||||
|
*
|
||||||
|
* <p>If sending to Kindle, then ensure this address is listed as a valid sender.</p>
|
||||||
|
*/
|
||||||
|
String getReader();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of the Webhook to register with services.
|
||||||
|
*/
|
||||||
|
String getWebhook();
|
||||||
|
|
||||||
|
}
|
38
src/main/java/net/kemitix/trello/TrelloProducers.java
Normal file
38
src/main/java/net/kemitix/trello/TrelloProducers.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package net.kemitix.trello;
|
||||||
|
|
||||||
|
import com.julienvey.trello.Trello;
|
||||||
|
import com.julienvey.trello.TrelloHttpClient;
|
||||||
|
import com.julienvey.trello.domain.Member;
|
||||||
|
import com.julienvey.trello.impl.http.JDKTrelloHttpClient;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
import javax.enterprise.inject.Produces;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class TrelloProducers {
|
||||||
|
|
||||||
|
@Produces
|
||||||
|
@ApplicationScoped
|
||||||
|
TrelloHttpClient trelloHttpClient() {
|
||||||
|
return new JDKTrelloHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Produces
|
||||||
|
@ApplicationScoped
|
||||||
|
TrelloClient trello(
|
||||||
|
TrelloConfig config,
|
||||||
|
TrelloHttpClient httpClient
|
||||||
|
) {
|
||||||
|
return new KemitixTrelloClient(
|
||||||
|
config.getTrelloKey(),
|
||||||
|
config.getTrelloSecret(),
|
||||||
|
httpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Produces
|
||||||
|
@ApplicationScoped
|
||||||
|
Member member(Trello trello, TrelloConfig trelloConfig) {
|
||||||
|
return trello.getMemberInformation(trelloConfig.getUserName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
0
src/main/resources/META-INF/beans.xml
Normal file
0
src/main/resources/META-INF/beans.xml
Normal file
Loading…
Reference in a new issue