Initial commit.

This commit is contained in:
Erik C. Thauvin 2017-05-17 00:41:35 -07:00
commit 2ee3568e40
25 changed files with 882 additions and 0 deletions

5
.gitattributes vendored Normal file
View file

@ -0,0 +1,5 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# batch files are specific to windows and always crlf
*.bat eol=crlf

29
.gitignore vendored Normal file
View file

@ -0,0 +1,29 @@
**/.idea/dictionaries
**/.idea/gradle.xml
**/.idea/libraries
**/.idea/tasks.xml
**/.idea/workspace.xml
*.sublime-*
*.iws
.classpath
.DS_Store
.gradle
.kobalt
.nb-gradle
.project
.settings
/bin
/build
/deploy
/dist
/gen
/gradle.properties
/local.properties
/out
/proguard-project.txt
/project.properties
/target
/test-output
ehthumbs.db
kobaltBuild
Thumbs.db

View file

@ -0,0 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="&amp;#36;file.fileName&#10;&#10;Copyright (c) &amp;#36;today.year, Erik C. Thauvin (erik@thauvin.net)&#10;All rights reserved.&#10;&#10;Redistribution and use in source and binary forms, with or without&#10;modification, are permitted provided that the following conditions are met:&#10;&#10; Redistributions of source code must retain the above copyright notice, this&#10; list of conditions and the following disclaimer.&#10;&#10; Redistributions in binary form must reproduce the above copyright notice,&#10; this list of conditions and the following disclaimer in the documentation&#10; and/or other materials provided with the distribution.&#10;&#10; Neither the name of this project nor the names of its contributors may be&#10; used to endorse or promote products derived from this software without&#10; specific prior written permission.&#10;&#10;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;&#10;AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE&#10;IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE&#10;DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE&#10;FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL&#10;DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR&#10;SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER&#10;CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,&#10;OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE&#10;OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." />
<option name="myName" value="Erik's Copyright Notice" />
</copyright>
</component>

15
.idea/copyright/profiles_settings.xml generated Normal file
View file

@ -0,0 +1,15 @@
<component name="CopyrightManager">
<settings>
<module2copyright>
<element module="Source" copyright="Erik's Copyright Notice" />
</module2copyright>
<LanguageOptions name="JAVA">
<option name="fileTypeOverride" value="3" />
<option name="addBlankAfter" value="false" />
</LanguageOptions>
<LanguageOptions name="Kotlin">
<option name="fileTypeOverride" value="3" />
<option name="addBlankAfter" value="false" />
</LanguageOptions>
</settings>
</component>

6
.idea/encodings.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

View file

@ -0,0 +1,53 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<option name="myLocal" value="true" />
<inspection_tool class="FieldMayBeFinal" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="created" />
</inspection_tool>
<inspection_tool class="LocalCanBeFinal" enabled="true" level="WARNING" enabled_by_default="true">
<option name="REPORT_VARIABLES" value="true" />
<option name="REPORT_PARAMETERS" value="false" />
<option name="REPORT_CATCH_PARAMETERS" value="false" />
</inspection_tool>
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
</inspection_tool>
<inspection_tool class="UnnecessarySemicolon" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
<option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" />
<option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" />
<option name="SUGGEST_PRIVATE_FOR_INNERS" value="false" />
</inspection_tool>
</profile>
</component>

19
.idea/kobalt.xml generated Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KobaltSettings">
<option name="linkedExternalProjectsSettings">
<KobaltProjectSettings>
<option name="autoDownloadKobalt" value="true" />
<option name="downloadSources" value="false" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="kobaltHome" value="$USER_HOME$/.kobalt/wrapper/dist/kobalt-1.0.86" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="profiles" value="" />
</KobaltProjectSettings>
</option>
</component>
</project>

4
.idea/misc.xml generated Normal file
View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8.x" project-jdk-type="JavaSDK" />
</project>

9
.idea/modules.xml generated Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/kobalt/Build.kt.iml" filepath="$PROJECT_DIR$/kobalt/Build.kt.iml" />
<module fileurl="file://$PROJECT_DIR$/pinboard-poster.iml" filepath="$PROJECT_DIR$/pinboard-poster.iml" />
</modules>
</component>
</project>

3
.idea/scopes/Source.xml generated Normal file
View file

@ -0,0 +1,3 @@
<component name="DependencyValidationManager">
<scope name="Source" pattern="file[pinboard-poster]:src/main/java//*.java||file[pinboard-poster]:src/main/kotlin//*.kt" />
</component>

124
.idea/uiDesigner.xml generated Normal file
View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

19
.travis.yml Normal file
View file

@ -0,0 +1,19 @@
language: java
jdk:
- oraclejdk8
before_install:
- chmod +x kobaltw
install: true
cache:
directories:
- $HOME/.m2
- $HOME/.kobalt
before_cache:
- rm -rf .kobalt/*
script: ./kobaltw clean assemble

113
README.md Normal file
View file

@ -0,0 +1,113 @@
# [Pinboard](https://pinboard.in) Poster for Kotlin/Java
[![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](http://opensource.org/licenses/BSD-3-Clause) [![Build Status](https://travis-ci.org/ethauvin/pinboard-poster.svg?branch=master)](https://travis-ci.org/ethauvin/pinboard-poster) [![Dependency Status](https://www.versioneye.com/user/projects/58ff729f6ac171425cd00acf/badge.svg?style=flat-square)](https://www.versioneye.com/user/projects/58ff729f6ac171425cd00acf) [![Download](https://api.bintray.com/packages/ethauvin/maven/pinboard-poster/images/download.svg) ](https://bintray.com/ethauvin/maven/pinboard-poster/_latestVersion)
A small Kotlin/Java library for posting to [Pinboard](https://pinboard.in).
## Examples
### Kotlin
```kotlin
val poster = PinboardPoster("user:TOKEN")
poster.addPin("http://www.example.com/foo", "This is a test")
poster.deletePin("http:///www.example.com/bar")
```
### Java
```java
final PinboardPoster poster = new PinBboardPoster("user:TOKEN");
poster.addPin("http://www.example.com/foo", "This is a test");
poster.deletePin("http:///www.example.com/bar");
```
Your API authentication token is available on the [Pinboard settings page](https://pinboard.in/settings/password).
## Usage with Maven, Gradle and Kobalt
### Maven
To install and run from Maven, configure an artifact as follows:
```xml
<dependency>
<groupId>net.thauvin.erik</groupId>
<artifactId>pinboard-poster</artifactId>
<version>0.9.0</version>
</dependency>
```
### Gradle
To install and run from Gradle, add the following to the build.gradle file:
```gradle
dependencies {
compileOnly 'net.thauvin.erik:pinboard-poster:0.9.0'
}
```
### Kobalt
To install and run from Kobalt, add the following to the Build.kt file:
```gradle
dependencies {
compile("net.thauvin.erik:pinboard-poster:0.9.0")
}
```
## Adding
The `addPin` function support all of the [Pinboard API parameters](https://pinboard.in/api/#posts_add):
```kotlin
poster.addPin(url = "http://www.example.com",
description = "This is the title.",
extended = "This is the extended description.",
tags = "tag1 tag2 tag3",
dt = "2010-12-11T19:48:02Z",
replace = true,
shared = true,
toRead = false)
```
`url` and `description` are required.
It returns `true` if the bookmark was added successfully, `false` otherwise.
## Deleting
The `deletePin` function support all of the [Pinboard API parameters](https://pinboard.in/api/#posts_delete):
```kotlin
poster.deletePin(url = "http://www.example.com/")
```
It returns `true` if the bookmark was deleted successfully, `false` otherwise.
## Logging
The library used [`java.util.logging`](https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html) to log errors. Logging can be configured as follows:
```kotlin
with(poster.logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
}
```
or using a property file.
## API End Point
The API end point is automatically configured to `https://api.pinboard.in/v1/`. Since Pinboard uses the `del.ico.us` API, the library could potentially be used with another compatible service. To configure the API end point, use:
```kotlin
poster.apiEndPoint = "https://www.example.com/v1"
```

24
kobalt/Build.kt.iml Normal file
View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="Build.kt" external.linked.project.path="$MODULE_DIR$/.." external.root.project.path="$MODULE_DIR$/.." external.system.id="KOBALT" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/out/classes" />
<output-test url="file://$MODULE_DIR$/out/test-classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library name="Kobalt: com.beust.kobalt:kobalt:jar:1.0.86">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/wrapper/dist/kobalt-1.0.86/kobalt/wrapper/kobalt-1.0.86.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.kobalt/wrapper/dist/kobalt-1.0.86/kobalt/wrapper/kobalt-1.0.86-sources.jar!/" />
</SOURCES>
</library>
</orderEntry>
</component>
</module>

90
kobalt/src/Build.kt Normal file
View file

@ -0,0 +1,90 @@
import com.beust.kobalt.glob
import com.beust.kobalt.plugin.application.application
import com.beust.kobalt.plugin.packaging.assemble
import com.beust.kobalt.plugin.packaging.install
import com.beust.kobalt.plugin.publish.autoGitTag
import com.beust.kobalt.plugin.publish.bintray
import com.beust.kobalt.project
import org.apache.maven.model.Developer
import org.apache.maven.model.License
import org.apache.maven.model.Model
import org.apache.maven.model.Scm
import java.io.FileInputStream
import java.util.*
val p = project {
name = "pinboard-poster"
group = "net.thauvin.erik"
artifactId = name
version = "0.9.0"
val localProperties = Properties().apply { FileInputStream("local.properties").use { fis -> load(fis) } }
val apiToken = localProperties.getProperty("pinboard-api-token", "")
pom = Model().apply {
description = project.description
url = "https://github.com/ethauvin/pinboard-poster"
licenses = listOf(License().apply {
name = "BSD 3-Clause"
url = "https://opensource.org/licenses/BSD-3-Clause"
})
scm = Scm().apply {
url = "https://github.com/ethauvin/pinboard-poster"
connection = "https://github.com/ethauvin/pinboard-poster.git"
developerConnection = "git@github.com:ethauvin/pinboard-poster.git"
}
developers = listOf(Developer().apply {
id = "ethauvin"
name = "Erik C. Thauvin"
email = "erik@thauvin.net"
})
}
dependencies {
compile("org.jetbrains.kotlin:kotlin-stdlib:1.1.2-3")
compile("com.squareup.okhttp3:okhttp:3.8.0")
}
dependenciesTest {
compile("org.testng:testng:6.11")
compile("org.jetbrains.kotlin:kotlin-test:1.1.2-3")
}
assemble {
jar { }
mavenJars { }
}
application {
mainClass = "net.thauvin.erik.pinboard.PinboardPosterKt"
args(apiToken)
}
application {
taskName = "runJava"
mainClass = "net.thauvin.erik.pinboard.JavaExample"
args(apiToken)
}
install {
target = "deploy"
include(from("kobaltBuild/libs"), to(target), glob("**/*"))
collect(compileDependencies).forEach {
copy(from(it.file.absolutePath), to(target))
}
}
autoGitTag {
enabled = true
//push = false
message = "Version $version"
}
bintray {
publish = true
description = "Release version $version"
issueTrackerUrl = "https://github.com/ethauvin/pinboard-poster/issues"
vcsTag = version
sign = true
}
}

Binary file not shown.

View file

@ -0,0 +1 @@
kobalt.version=1.0.86

2
kobaltw Normal file
View file

@ -0,0 +1,2 @@
#!/usr/bin/env sh
java -jar "`dirname "$0"`/kobalt/wrapper/kobalt-wrapper.jar" $*

4
kobaltw.bat Normal file
View file

@ -0,0 +1,4 @@
@echo off
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
java -jar "%DIRNAME%/kobalt/wrapper/kobalt-wrapper.jar" %*

BIN
lib/kotlin-reflect.jar Normal file

Binary file not shown.

Binary file not shown.

BIN
lib/kotlin-runtime.jar Normal file

Binary file not shown.

106
pinboard-poster.iml Normal file
View file

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="pinboard-poster" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="KOBALT" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/kobaltBuild/classes" />
<output-test url="file://$MODULE_DIR$/kobaltBuild/test-classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/kobaltBuild" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library name="Kobalt: org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.2-3">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/org/jetbrains/kotlin/kotlin-stdlib/1.1.2-3/kotlin-stdlib-1.1.2-3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="Kobalt: org.jetbrains:annotations:jar:13.0">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/org/jetbrains/annotations/13.0/annotations-13.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="Kobalt: org.jetbrains.kotlin:kotlin-stdlib:jar:1.1.2-3">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/org/jetbrains/kotlin/kotlin-stdlib/1.1.2-3/kotlin-stdlib-1.1.2-3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="Kobalt: org.yaml:snakeyaml:jar:1.17">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/org/yaml/snakeyaml/1.17/snakeyaml-1.17.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="Kobalt: com.beust:jcommander:jar:1.64">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/com/beust/jcommander/1.64/jcommander-1.64.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="Kobalt: com.squareup.okio:okio:jar:1.13.0">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/com/squareup/okio/okio/1.13.0/okio-1.13.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="Kobalt: org.jetbrains:annotations:jar:13.0">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/org/jetbrains/annotations/13.0/annotations-13.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="Kobalt: org.jetbrains.kotlin:kotlin-test:jar:1.1.2-3">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/org/jetbrains/kotlin/kotlin-test/1.1.2-3/kotlin-test-1.1.2-3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="Kobalt: org.testng:testng:jar:6.11">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/org/testng/testng/6.11/testng-6.11.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module-library">
<library name="Kobalt: com.squareup.okhttp3:okhttp:jar:3.8.0">
<CLASSES>
<root url="jar://$USER_HOME$/.kobalt/cache/com/squareup/okhttp3/okhttp/3.8.0/okhttp-3.8.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

View file

@ -0,0 +1,47 @@
/*
* JavaExample.java
*
* Copyright (c) 2017, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.pinboard;
public class JavaExample {
public static void main(String[] args) {
final String url = "http://www.example.com/pinboard";
final PinboardPoster poster = new PinboardPoster(args[0]);
if (poster.addPin(url, "Testing", "Extended test", "test koltin")) {
System.out.println("Added: " + url);
}
if (poster.deletePin(url)) {
System.out.println("Deleted: " + url);
}
}
}

View file

@ -0,0 +1,203 @@
/*
* PinboardPoster.kt
*
* Copyright (c) 2017, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.pinboard
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import java.net.URL
import java.util.logging.ConsoleHandler
import java.util.logging.Level
import java.util.logging.Logger
object Constants {
const val API_ENDPOINT = "https://api.pinboard.in/v1/"
const val AUTH_TOKEN = "auth_token"
const val DONE = "done"
}
open class PinboardPoster(val apiToken: String) {
var apiEndPoint: String = Constants.API_ENDPOINT
val logger: Logger by lazy { Logger.getLogger(PinboardPoster::class.java.simpleName) }
private val client by lazy { OkHttpClient() }
@JvmOverloads
fun addPin(url: String,
description: String,
extended: String = "",
tags: String = "",
dt: String = "",
replace: Boolean = true,
shared: Boolean = true,
toRead: Boolean = false): Boolean {
if (validate()) {
if (!validateUrl(url)) {
logger.log(Level.SEVERE, "Please specify a valid URL to pin.")
} else if (description.isBlank()) {
logger.log(Level.SEVERE, "Please specify a valid description.")
} else {
val apiUrl = HttpUrl.parse(cleanEndPoint("posts/add"))
if (apiUrl != null) {
val httpUrl = apiUrl.newBuilder().apply {
addQueryParameter("url", url)
addQueryParameter("description", description)
if (extended.isNotBlank()) {
addQueryParameter("extended", extended)
}
if (tags.isNotBlank()) {
addQueryParameter("tags", tags)
}
if (dt.isNotBlank()) {
addQueryParameter("dt", dt)
}
if (!replace) {
addQueryParameter("replace", "no")
}
if (!shared) {
addQueryParameter("shared", "no")
}
if (toRead) {
addQueryParameter("toread", "yes")
}
addQueryParameter(Constants.AUTH_TOKEN, apiToken)
}.build()
val request = Request.Builder().url(httpUrl).build()
val result = client.newCall(request).execute()
logger.log(Level.FINE, "HTTP Result: ${result.code()}")
val response = result.body()?.string()
if (response != null && response.contains(Constants.DONE)) {
logger.log(Level.FINE, "HTTP Response:\n$response")
return true
}
} else {
logger.log(Level.SEVERE, "Invalid API end point: $apiEndPoint")
}
}
}
return false
}
fun deletePin(url: String): Boolean {
if (validate()) {
if (!validateUrl(url)) {
logger.log(Level.SEVERE, "Please specify a valid URL to delete.")
} else {
val apiUrl = HttpUrl.parse(cleanEndPoint("posts/delete"))
if (apiUrl != null) {
val httpUrl = apiUrl.newBuilder().apply {
addQueryParameter("url", url)
addQueryParameter(Constants.AUTH_TOKEN, apiToken)
}.build()
val request = Request.Builder().url(httpUrl).build()
val result = client.newCall(request).execute()
logger.log(Level.FINE, "HTTP Result: ${result.code()}")
val response = result.body()?.string()
if (response != null && response.contains(Constants.DONE)) {
logger.log(Level.FINE, "HTTP Response:\n$response")
return true
}
} else {
logger.log(Level.SEVERE, "Invalid API end point: $apiEndPoint")
}
}
}
return false
}
private fun validateUrl(url: String): Boolean {
if (url.isBlank()) {
return false
}
try {
URL(url)
} catch(e: Exception) {
logger.log(Level.FINE, "Invalid URL: $url", e)
return false
}
return true
}
private fun validate(): Boolean {
if (apiToken.isBlank() && !apiToken.contains(':')) {
logger.log(Level.SEVERE, "Please specify a valid API token. (eg. user:TOKEN)")
return false
} else if (!validateUrl(apiEndPoint)) {
logger.log(Level.SEVERE, "Please specify a valid API end point. (eg. ${Constants.API_ENDPOINT})")
return false
}
return true
}
private fun cleanEndPoint(method: String): String {
if (apiEndPoint.endsWith('/')) {
return "$apiEndPoint$method"
} else {
return "$apiEndPoint/$method"
}
}
}
fun main(args: Array<String>) {
if (args.size == 1) {
val url = "http://www.example.com/pinboard"
val poster = PinboardPoster(args[0])
with(poster.logger) {
addHandler(ConsoleHandler().apply { level = Level.FINE })
level = Level.FINE
}
if (poster.addPin(url, "Testing", "Extended test", "test koltin")) {
println("Added: $url")
}
if (poster.deletePin(url)) {
println("Deleted: $url")
}
} else {
println("Please specify a valid API token. (eg. user:TOKEN)")
}
}