Compare commits
57 Commits
v0.1
...
fix/modern
Author | SHA1 | Date |
---|---|---|
Cadey Ratio | a98f5fcd3a | |
Cadey Ratio | 0a2daa0140 | |
Cadey Ratio | b0dc06c75a | |
Christine Dodrill | 0575283f5c | |
Christine Dodrill | 5e6f321c9c | |
Christine Dodrill | bb55555bdd | |
Christine Dodrill | a0fd4d1588 | |
Christine Dodrill | 95cb346e20 | |
Christine Dodrill | b0bd424056 | |
Christine Dodrill | d7a5ccb2cb | |
Christine Dodrill | b4ec8adf9c | |
Christine Dodrill | 8e92e1097e | |
Christine Dodrill | f4bf5ebe0b | |
Christine Dodrill | e47a4da840 | |
Christine Dodrill | 3e27f55a76 | |
Christine Dodrill | 895f8011a7 | |
Christine Dodrill | 5472c5c969 | |
Christine Dodrill | 6b7b1c78d1 | |
Christine Dodrill | 77ba95c811 | |
Christine Dodrill | 92def355ff | |
Christine Dodrill | af1521874d | |
Christine Dodrill | d668137e95 | |
Christine Dodrill | 2982eb2bd5 | |
Christine Dodrill | 375278bc12 | |
Christine Dodrill | c050b65bbf | |
Christine Dodrill | 882b5b1551 | |
Christine Dodrill | 791b7d59a0 | |
Christine Dodrill | 50a6d7b5f6 | |
Christine Dodrill | dc24fa6b48 | |
Christine Dodrill | 5d3a94bffa | |
Christine Dodrill | a0688e4b55 | |
Christine Dodrill | 6aa9ec5b18 | |
Justin Kaufman | 8dfbfd2f2b | |
Christine Dodrill | 0b3e015482 | |
Christine Dodrill | 50c2cbed2c | |
Justin Kaufman | 20cad274e6 | |
Christine Dodrill | 956d57a9dd | |
Christine Dodrill | 34682afd1e | |
Christine Dodrill | e2fd239e37 | |
Christine Dodrill | 0cc73a2e95 | |
Christine Dodrill | 045f69d53a | |
Christine Dodrill | b5d36da2b6 | |
Christine Dodrill | 24ef6f4c69 | |
Christine Dodrill | 67c484ee19 | |
Christine Dodrill | d80166a420 | |
Christine Dodrill | 813e1164c1 | |
Christine Dodrill | 9489789334 | |
Christine Dodrill | c7af9e9bb2 | |
Christine Dodrill | 577de316ac | |
Christine Dodrill | 3ce8c3b833 | |
Christine Dodrill | 97dbe29bca | |
Christine Dodrill | d75622b505 | |
Christine Dodrill | e62d6877ad | |
Christine Dodrill | 651e0f6065 | |
Christine Dodrill | a3ea1ed922 | |
Christine Dodrill | 162052d17b | |
Christine Dodrill | 71489f4f33 |
|
@ -1 +1,2 @@
|
||||||
static/* linguist-vendored
|
public/static/* linguist-vendored
|
||||||
|
client/* linguist-vendored
|
||||||
|
|
|
@ -59,3 +59,5 @@ docs/_build/
|
||||||
# PyBuilder
|
# PyBuilder
|
||||||
target/
|
target/
|
||||||
|
|
||||||
|
ponyapi
|
||||||
|
nimcache
|
||||||
|
|
17
Dockerfile
17
Dockerfile
|
@ -1,14 +1,17 @@
|
||||||
FROM python:2.7.10
|
FROM coopernurse/docker-nim
|
||||||
|
|
||||||
RUN adduser --disabled-password --gecos '' r
|
RUN apk update && apk add bash
|
||||||
ADD ./requirements.txt /app/requirements.txt
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
RUN pip install -r ./requirements.txt
|
EXPOSE 5000
|
||||||
|
RUN adduser -D -g '' r
|
||||||
|
RUN chmod a+x /opt/Nim/bin/nim
|
||||||
|
|
||||||
ADD . /app
|
ADD . /app
|
||||||
|
|
||||||
EXPOSE 5000
|
WORKDIR /app
|
||||||
|
RUN nimble update &&\
|
||||||
|
yes | nimble install &&\
|
||||||
|
nim c -d:release --deadCodeElim:on ponyapi
|
||||||
|
|
||||||
USER r
|
USER r
|
||||||
CMD gunicorn ponyapi:app --log-file=- -b 0.0.0.0:5000 -w 4
|
CMD ./ponyapi
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
build:
|
||||||
|
nim c --deadcodeElim:on --hints:off ponyapi
|
||||||
|
|
||||||
|
run: build
|
||||||
|
./ponyapi
|
49
README.md
49
README.md
|
@ -35,15 +35,19 @@ Clients
|
||||||
- [Go](https://godoc.org/github.com/Xe/PonyAPI/client/go)
|
- [Go](https://godoc.org/github.com/Xe/PonyAPI/client/go)
|
||||||
- [Nim](https://github.com/Xe/PonyAPI/blob/master/client/nim/ponyapi.nim) [Docs](http://ponyapi.apps.xeserv.us/static/nim.html)
|
- [Nim](https://github.com/Xe/PonyAPI/blob/master/client/nim/ponyapi.nim) [Docs](http://ponyapi.apps.xeserv.us/static/nim.html)
|
||||||
- [Python](https://github.com/Xe/PonyAPI/blob/master/client/python/ponyapi.py)
|
- [Python](https://github.com/Xe/PonyAPI/blob/master/client/python/ponyapi.py)
|
||||||
|
- [Java](https://github.com/Xe/PonyAPI/tree/master/client/java)
|
||||||
|
|
||||||
Routes
|
Routes
|
||||||
------
|
------
|
||||||
|
|
||||||
The canonical route base for PonyAPI is http://ponyapi.apps.xeserv.us. Example
|
The canonical route base for PonyAPI is `https://ponyapi.apps.xeserv.us`. This
|
||||||
usage:
|
now supports HTTP/2.0 using [Caddy](https://caddyserver.com) and SSL using
|
||||||
|
[Let's Encrypt](https://letsencrypt.org/). If you get SSL errors, please be
|
||||||
|
sure your system certificate lists are up to date.
|
||||||
|
Example usage:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ curl http://ponyapi.apps.xeserv.us/season/1/episode/1
|
$ curl https://ponyapi.apps.xeserv.us/season/1/episode/1
|
||||||
{
|
{
|
||||||
"episode": {
|
"episode": {
|
||||||
"air_date": 1286735400,
|
"air_date": 1286735400,
|
||||||
|
@ -55,6 +59,31 @@ $ curl http://ponyapi.apps.xeserv.us/season/1/episode/1
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Bare Replies
|
||||||
|
------------
|
||||||
|
|
||||||
|
As of [882b5b1](https://github.com/Xe/PonyAPI/commit/882b5b155157d3a3c9e329fffcf7ff3fdf64d4ee),
|
||||||
|
PonyAPI will accept an `X-API-Options` header that when set to `bare` will
|
||||||
|
return the API replies without the `episode` or `episodes` header.
|
||||||
|
Functionality is otherwise unchanged, however an error will still be shown if
|
||||||
|
something goes wrong, and that will parse differently. This API will return
|
||||||
|
`200` if and **only** if everything went to plan.
|
||||||
|
|
||||||
|
An example:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ curl --header "X-API-Options: bare" https://ponyapi.apps.xeserv.us/last_aired
|
||||||
|
{
|
||||||
|
"name": "Do Princesses Dream of Magic Sheep?",
|
||||||
|
"air_date": 1436628600,
|
||||||
|
"season": 5,
|
||||||
|
"episode": 13,
|
||||||
|
"is_movie": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This will also be triggered if you set the query parameter `options` to `bare`.
|
||||||
|
|
||||||
### `/all`
|
### `/all`
|
||||||
|
|
||||||
Returns all information about all episodes. This returns an array of Episode
|
Returns all information about all episodes. This returns an array of Episode
|
||||||
|
@ -64,13 +93,18 @@ objects as defined above.
|
||||||
|
|
||||||
Returns the episode of My Little Pony: Friendship is Magic that will air next.
|
Returns the episode of My Little Pony: Friendship is Magic that will air next.
|
||||||
|
|
||||||
|
### `/last_aired`
|
||||||
|
|
||||||
|
Returns the episode of My Little Pony: Friendship is Magic that most recently
|
||||||
|
aired.
|
||||||
|
|
||||||
### `/season/<number>`
|
### `/season/<number>`
|
||||||
|
|
||||||
Returns all information about episodes in the given season number or a `404`
|
Returns all information about episodes in the given season number or a `404`
|
||||||
reply if no episodes could be found. To get all information about the movies
|
reply if no episodes could be found. To get all information about the movies
|
||||||
shown, set the season as `99`.
|
shown, set the season as `99`.
|
||||||
|
|
||||||
### `/season/<number>/episode/<number`
|
### `/season/<number>/episode/<number>`
|
||||||
|
|
||||||
Returns all information about the episode with the given season and episode
|
Returns all information about the episode with the given season and episode
|
||||||
number. If the episode cannot be found, this will return a `404`.
|
number. If the episode cannot be found, this will return a `404`.
|
||||||
|
@ -85,3 +119,10 @@ This must be given a query paramater `q` containing the text to search for. Not
|
||||||
including this will return a `406` reply. This will search the list of episode
|
including this will return a `406` reply. This will search the list of episode
|
||||||
records for any episodes whose names match the given search terms. This is
|
records for any episodes whose names match the given search terms. This is
|
||||||
case-insensitive. If no episodes can be found, this will return a `404` reply.
|
case-insensitive. If no episodes can be found, this will return a `404` reply.
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
------------
|
||||||
|
|
||||||
|
Contributions will be judged by their technical merit. No politics on project forums.
|
||||||
|
|
||||||
|
All code is licensed under the MIT license.
|
||||||
|
|
|
@ -9,15 +9,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
endpoint = "http://ponyapi.apps.xeserv.us"
|
endpoint = "https://ponyapi.apps.xeserv.us"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getJson(fragment string) (data []byte, err error) {
|
func getJson(fragment string) (data []byte, err error) {
|
||||||
resp, err := http.Get(endpoint + fragment)
|
c := &http.Client{}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", endpoint+fragment, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//req.Header.Add("X-API-Options", "bare")
|
||||||
|
|
||||||
|
resp, err := c.Do(req)
|
||||||
|
|
||||||
data, err = ioutil.ReadAll(resp.Body)
|
data, err = ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -61,6 +67,12 @@ func Newest() (*Episode, error) {
|
||||||
return getEpisode("/newest")
|
return getEpisode("/newest")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LastAired returns information on the most recently aried episode
|
||||||
|
// or an error.
|
||||||
|
func LastAired() (*Episode, error) {
|
||||||
|
return getEpisode("/last_aired")
|
||||||
|
}
|
||||||
|
|
||||||
// Random returns information on a random episode.
|
// Random returns information on a random episode.
|
||||||
func Random() (*Episode, error) {
|
func Random() (*Episode, error) {
|
||||||
return getEpisode("/random")
|
return getEpisode("/random")
|
||||||
|
|
|
@ -4,6 +4,15 @@ import "testing"
|
||||||
|
|
||||||
func TestNewestEpisode(t *testing.T) {
|
func TestNewestEpisode(t *testing.T) {
|
||||||
ep, err := Newest()
|
ep, err := Newest()
|
||||||
|
if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("%#v", ep)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLastAiredEpisode(t *testing.T) {
|
||||||
|
ep, err := LastAired()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
set -x
|
|
||||||
|
|
||||||
go test -v .
|
go test .
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
.gradle
|
|
@ -0,0 +1,62 @@
|
||||||
|
PonyAPI Java Client
|
||||||
|
===================
|
||||||
|
|
||||||
|
A Java client for accessing PonyAPI. Requires Java 8.
|
||||||
|
|
||||||
|
Example Usage
|
||||||
|
-------------
|
||||||
|
|
||||||
|
```java
|
||||||
|
package us.xeserv.examples;
|
||||||
|
|
||||||
|
import us.xeserv.ponyapi.Episode;
|
||||||
|
import us.xeserv.ponyapi.PonyApiClient;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PonyApiExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
// Initialize a client with a custom API host
|
||||||
|
PonyApiClient client = new PonyApiClient("some.fqdn.here"); // defaults to port 80
|
||||||
|
client = new PonyApiClient("some.fqdn.here", 8080); // with a custom port number
|
||||||
|
// Initialize a client using http://ponyapi.apps.xeserv.us/ as the API host
|
||||||
|
client = new PonyApiClient();
|
||||||
|
|
||||||
|
// Get a list of all the episodes
|
||||||
|
List<Episode> allEpisodes = client.all();
|
||||||
|
|
||||||
|
// Get the newest episode
|
||||||
|
Episode newestEpisode = client.newest();
|
||||||
|
|
||||||
|
// Get information about an episode
|
||||||
|
String name = newestEpisode.name;
|
||||||
|
Instant airDate = newestEpisode.airDate;
|
||||||
|
int seasonNumber = newestEpisode.season;
|
||||||
|
int episodeNumber = newestEpisode.episode;
|
||||||
|
boolean isMovie = newestEpisode.isMovie;
|
||||||
|
|
||||||
|
// Get all episodes in a season
|
||||||
|
List<Episode> season = client.getSeason(1);
|
||||||
|
|
||||||
|
// Get all movies
|
||||||
|
List<Episode> movies = client.getMovies();
|
||||||
|
|
||||||
|
// Get a specific episode by season and episode number
|
||||||
|
Episode specificEpisode = client.getEpisode(1, 13);
|
||||||
|
|
||||||
|
// Get a specific movie by movie number
|
||||||
|
Episode specificMovie = client.getMovie(1);
|
||||||
|
|
||||||
|
// Get a random movie or movie number
|
||||||
|
Episode random = client.random();
|
||||||
|
|
||||||
|
// Get a list of all episodes and movies matching a query
|
||||||
|
List<Episode> queryResults = client.search("Owl's Well"); // returns Owl's Well That Ends Well
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,19 @@
|
||||||
|
group 'us.xeserv'
|
||||||
|
version '1.0'
|
||||||
|
|
||||||
|
apply plugin: 'java'
|
||||||
|
|
||||||
|
sourceCompatibility = 1.8
|
||||||
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "com.google.code.gson:gson:+"
|
||||||
|
compile "org.apache.httpcomponents:httpclient:+"
|
||||||
|
compile "org.apache.httpcomponents:fluent-hc:+"
|
||||||
|
compile "com.google.guava:guava:+"
|
||||||
|
testCompile "junit:junit:+"
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
||||||
|
#Tue Aug 18 15:13:15 CDT 2015
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip
|
|
@ -0,0 +1,164 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn ( ) {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die ( ) {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >&-
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >&-
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||||
|
function splitJvmOpts() {
|
||||||
|
JVM_OPTS=("$@")
|
||||||
|
}
|
||||||
|
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||||
|
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
|
@ -0,0 +1,84 @@
|
||||||
|
package us.xeserv.ponyapi;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code Episode} class represents My Little Pony episode or movie information returned by PonyAPI.
|
||||||
|
* <p>
|
||||||
|
* Episodes are immutable; they represent data returned from the API and cannot be changed after they are created.
|
||||||
|
* <p>
|
||||||
|
* Movie data stored in an {@code Episode} object are referred to by the season number 99. Their episode number refers
|
||||||
|
* to the order of their release starting with 1.
|
||||||
|
*
|
||||||
|
* @author Justin Kaufman
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class Episode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the episode or movie.
|
||||||
|
*/
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The season of the episode, or 99 if it is a movie.
|
||||||
|
*/
|
||||||
|
public final int season;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The episode or movie number.
|
||||||
|
*/
|
||||||
|
public final int episode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The air date.
|
||||||
|
*/
|
||||||
|
public final Instant airDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if this episode represents a movie, false otherwise.
|
||||||
|
*/
|
||||||
|
public final boolean isMovie;
|
||||||
|
|
||||||
|
protected Episode(String name, int season, int episode, long airDate, boolean isMovie) {
|
||||||
|
this.name = name;
|
||||||
|
this.season = season;
|
||||||
|
this.episode = episode;
|
||||||
|
this.airDate = Instant.ofEpochSecond(airDate);
|
||||||
|
this.isMovie = isMovie;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Episode rhs = (Episode) obj;
|
||||||
|
return Objects.equals(name, rhs.name)
|
||||||
|
&& Objects.equals(season, rhs.season)
|
||||||
|
&& Objects.equals(episode, rhs.episode)
|
||||||
|
&& Objects.equals(airDate, rhs.airDate)
|
||||||
|
&& Objects.equals(isMovie, rhs.isMovie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, season, episode, airDate, isMovie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "{\n"
|
||||||
|
+ "\t\"name\": \"" + name + "\",\n"
|
||||||
|
+ "\t\"air_date\": " + airDate.getEpochSecond() + ",\n"
|
||||||
|
+ "\t\"season\": " + season + ",\n"
|
||||||
|
+ "\t\"episode\": " + episode + ",\n"
|
||||||
|
+ "\t\"is_movie\": " + isMovie + "\n"
|
||||||
|
+ "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package us.xeserv.ponyapi;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.gson.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class JsonDecoder {
|
||||||
|
|
||||||
|
private static final Gson gson;
|
||||||
|
static {
|
||||||
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
|
gsonBuilder.registerTypeAdapter(Episode.class, (JsonDeserializer<Episode>) (json, typeOfT, context) -> {
|
||||||
|
JsonObject jsonObject = json.getAsJsonObject();
|
||||||
|
return new Episode(
|
||||||
|
jsonObject.get("name").getAsString(),
|
||||||
|
jsonObject.get("season").getAsInt(),
|
||||||
|
jsonObject.get("episode").getAsInt(),
|
||||||
|
jsonObject.get("air_date").getAsLong(),
|
||||||
|
jsonObject.get("is_movie").getAsBoolean()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
gson = gsonBuilder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Episode fromJson(String json) {
|
||||||
|
if (Strings.isNullOrEmpty(json)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
JsonObject wrapper = (JsonObject) new JsonParser().parse(json);
|
||||||
|
JsonObject payload = wrapper.get("episode").getAsJsonObject();
|
||||||
|
return gson.fromJson(payload, Episode.class);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// TODO: Logging for parse errors or passing a general parse exception
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static List<Episode> listFromJson(String json) {
|
||||||
|
if (Strings.isNullOrEmpty(json)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<Episode> list = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
JsonObject wrapper = (JsonObject) new JsonParser().parse(json);
|
||||||
|
JsonArray payload = wrapper.get("episodes").getAsJsonArray();
|
||||||
|
for (JsonElement episode : payload) {
|
||||||
|
list.add(gson.fromJson(episode, Episode.class));
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// TODO: Logging for parse errors or passing a general parse exception
|
||||||
|
}
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,170 @@
|
||||||
|
package us.xeserv.ponyapi;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.fluent.Request;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code PonyApiClient} class provides an interface between Java code that uses this library and PonyAPI.
|
||||||
|
* <p>
|
||||||
|
* This client is able to retrieve information about the show My Little Pony: Friendship is Magic.
|
||||||
|
*
|
||||||
|
* @author Justin Kaufman
|
||||||
|
* @since 1.0
|
||||||
|
*/
|
||||||
|
public class PonyApiClient {
|
||||||
|
|
||||||
|
private final String host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default constructor initializes a client instance that uses http://ponyapi.apps.xeserv.us/ as the API source.
|
||||||
|
*/
|
||||||
|
public PonyApiClient() {
|
||||||
|
this("ponyapi.apps.xeserv.us");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a FQDN and port running the PonyAPI service on a specified port.
|
||||||
|
* @param host a FQDN running the PonyAPI service
|
||||||
|
* @param port the port the PonyAPI service is running on
|
||||||
|
*/
|
||||||
|
public PonyApiClient(String host, int port) {
|
||||||
|
this.host = host + ":" + port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a FQDN running the PonyAPI service on port 80.
|
||||||
|
* @param host a FQDN running the PonyAPI service
|
||||||
|
*/
|
||||||
|
public PonyApiClient(String host) {
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all episodes and movies.
|
||||||
|
* @return a list of all episodes and movies
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public List<Episode> all() throws IOException {
|
||||||
|
return JsonDecoder.listFromJson(asJson(get("/all")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the newest episode or movie aired.
|
||||||
|
* @return the newest episode or movie aired
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public Episode newest() throws IOException {
|
||||||
|
return JsonDecoder.fromJson(asJson(get("/newest")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the episode or movie that most recently aired.
|
||||||
|
* @return the episode or movie that most recently aired
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public Episode lastAired() throws IOException {
|
||||||
|
return JsonDecoder.fromJson(asJson(get("/last_aired")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all information about episodes in a given season number.
|
||||||
|
* @param season the season number
|
||||||
|
* @return all information about episodes in a given season number
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public List<Episode> getSeason(int season) throws IOException {
|
||||||
|
HttpResponse response = get("/season/" + season);
|
||||||
|
if (statusCode(response) == 404) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JsonDecoder.listFromJson(asJson(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all information about movies.
|
||||||
|
* @return all information about movies
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public List<Episode> getMovies() throws IOException {
|
||||||
|
return JsonDecoder.listFromJson(asJson(get("/season/99")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all information about the episode with the given season and episode number.
|
||||||
|
* @param season the season number
|
||||||
|
* @param episode the episode number
|
||||||
|
* @return all information about the episode with the given season and episode number
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public Episode getEpisode(int season, int episode) throws IOException {
|
||||||
|
HttpResponse response = get("/season/" + season + "/episode/" + episode);
|
||||||
|
if (statusCode(response) == 404) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JsonDecoder.fromJson(asJson(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all information about the movie with the given movie number.
|
||||||
|
* @param movie the movie number
|
||||||
|
* @return all information about the movie with the given movie number
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public Episode getMovie(int movie) throws IOException {
|
||||||
|
HttpResponse response = get("/season/99/episode/" + movie);
|
||||||
|
if (statusCode(response) == 404) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JsonDecoder.fromJson(asJson(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random episode or movie from the record.
|
||||||
|
* @return a random episode or movie from the record
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
*/
|
||||||
|
public Episode random() throws IOException {
|
||||||
|
String json = asJson(get("/random"));
|
||||||
|
return JsonDecoder.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of episodes which contain the query in its name.
|
||||||
|
* @param query a case-independent, non-empty {@code String}
|
||||||
|
* @return a list of episodes which contain the query in its name
|
||||||
|
* @throws IOException if there is an error accessing the service
|
||||||
|
* @throws IllegalArgumentException if the query is null or empty
|
||||||
|
*/
|
||||||
|
public List<Episode> search(String query) throws IOException {
|
||||||
|
if (Strings.isNullOrEmpty(query)) {
|
||||||
|
throw new IllegalArgumentException("A search query is required.");
|
||||||
|
}
|
||||||
|
HttpResponse response = get("/search?q=" + URLEncoder.encode(query, "UTF-8"));
|
||||||
|
if (statusCode(response) == 404) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JsonDecoder.listFromJson(asJson(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpResponse get(String path) throws IOException {
|
||||||
|
return Request.Get("https://" + host + path)
|
||||||
|
.userAgent("PonyApi Java Client 1.0")
|
||||||
|
.execute()
|
||||||
|
.returnResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String asJson(HttpResponse response) throws IOException {
|
||||||
|
return EntityUtils.toString(response.getEntity());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int statusCode(HttpResponse response) throws IOException {
|
||||||
|
return response.getStatusLine().getStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
package us.xeserv.ponyapi;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
public class JsonDecoderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void malformedInputTest() {
|
||||||
|
assertNull(JsonDecoder.fromJson(null));
|
||||||
|
assertNull(JsonDecoder.fromJson(""));
|
||||||
|
assertNull(JsonDecoder.fromJson("{ \"error\": { \"msg\": \"some error\", \"code\": 404 }"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void episodeTest() {
|
||||||
|
String json = "{\n"
|
||||||
|
+ "\t\"episode\":\n"
|
||||||
|
+ "\t{\n"
|
||||||
|
+ "\t\t\"name\": \"Friendship is Magic Part 1\",\n"
|
||||||
|
+ "\t\t\"air_date\": 1286735400,\n"
|
||||||
|
+ "\t\t\"season\": 1,\n"
|
||||||
|
+ "\t\t\"episode\": 1,\n"
|
||||||
|
+ "\t\t\"is_movie\": false\n"
|
||||||
|
+ "\t}\n"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
Episode episode = JsonDecoder.fromJson(json);
|
||||||
|
assertEquals("Friendship is Magic Part 1", episode.name);
|
||||||
|
assertEquals(Instant.ofEpochSecond(1286735400), episode.airDate);
|
||||||
|
assertEquals(1, episode.season);
|
||||||
|
assertEquals(1, episode.episode);
|
||||||
|
assertEquals(false, episode.isMovie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void movieTest() {
|
||||||
|
String json = "{\n"
|
||||||
|
+ "\t\"episode\":\n"
|
||||||
|
+ "\t{\n"
|
||||||
|
+ "\t\t\"name\": \"Equestria Girls\",\n"
|
||||||
|
+ "\t\t\"air_date\": 1371340800,\n"
|
||||||
|
+ "\t\t\"season\": 99,\n"
|
||||||
|
+ "\t\t\"episode\": 1,\n"
|
||||||
|
+ "\t\t\"is_movie\": true\n"
|
||||||
|
+ "\t}\n"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
Episode episode = JsonDecoder.fromJson(json);
|
||||||
|
assertEquals("Equestria Girls", episode.name);
|
||||||
|
assertEquals(Instant.ofEpochSecond(1371340800), episode.airDate);
|
||||||
|
assertEquals(99, episode.season);
|
||||||
|
assertEquals(1, episode.episode);
|
||||||
|
assertEquals(true, episode.isMovie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multipleMalformedInputTest() {
|
||||||
|
assertNull(JsonDecoder.listFromJson(null));
|
||||||
|
assertNull(JsonDecoder.listFromJson(""));
|
||||||
|
assertNull(JsonDecoder.listFromJson("{ \"error\": { \"msg\": \"some error\", \"code\": 404 }"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multipleTest() {
|
||||||
|
String json = "{\n"
|
||||||
|
+ "\t\"episodes\": [\n"
|
||||||
|
+ "\t\t{\n"
|
||||||
|
+ "\t\t\t\"name\": \"Friendship is Magic Part 1\",\n"
|
||||||
|
+ "\t\t\t\"air_date\": 1286735400,\n"
|
||||||
|
+ "\t\t\t\"season\": 1,\n"
|
||||||
|
+ "\t\t\t\"episode\": 1,\n"
|
||||||
|
+ "\t\t\t\"is_movie\": false\n"
|
||||||
|
+ "\t\t},\n"
|
||||||
|
+ "\t\t{\n"
|
||||||
|
+ "\t\t\t\"name\": \"Equestria Girls\",\n"
|
||||||
|
+ "\t\t\t\"air_date\": 1371340800,\n"
|
||||||
|
+ "\t\t\t\"season\": 99,\n"
|
||||||
|
+ "\t\t\t\"episode\": 1,\n"
|
||||||
|
+ "\t\t\t\"is_movie\": true\n"
|
||||||
|
+ "\t\t}\n"
|
||||||
|
+ "\t]\n"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
List<Episode> episodes = JsonDecoder.listFromJson(json);
|
||||||
|
assertNotNull(episodes);
|
||||||
|
assertEquals(2, episodes.size());
|
||||||
|
|
||||||
|
Episode episode1 = episodes.get(0);
|
||||||
|
assertEquals("Friendship is Magic Part 1", episode1.name);
|
||||||
|
assertEquals(Instant.ofEpochSecond(1286735400), episode1.airDate);
|
||||||
|
assertEquals(1, episode1.season);
|
||||||
|
assertEquals(1, episode1.episode);
|
||||||
|
assertEquals(false, episode1.isMovie);
|
||||||
|
|
||||||
|
Episode episode2 = episodes.get(1);
|
||||||
|
assertEquals("Equestria Girls", episode2.name);
|
||||||
|
assertEquals(Instant.ofEpochSecond(1371340800), episode2.airDate);
|
||||||
|
assertEquals(99, episode2.season);
|
||||||
|
assertEquals(1, episode2.episode);
|
||||||
|
assertEquals(true, episode2.isMovie);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
package us.xeserv.ponyapi;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PonyApiClientTest {
|
||||||
|
|
||||||
|
private PonyApiClient client = new PonyApiClient();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void allTest() throws Exception {
|
||||||
|
List<Episode> list = client.all();
|
||||||
|
assertFalse(list.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void newestTest() throws IOException {
|
||||||
|
Episode episode = client.newest();
|
||||||
|
assertNotNull(episode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void lastAiredTest() throws IOException {
|
||||||
|
Episode episode = client.lastAired();
|
||||||
|
assertNotNull(episode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getSeasonTest() throws IOException {
|
||||||
|
List<Episode> list = client.getSeason(98);
|
||||||
|
assertNull(list);
|
||||||
|
list = client.getSeason(1);
|
||||||
|
assertEquals(26, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMoviesTest() throws IOException {
|
||||||
|
List<Episode> list = client.getMovies();
|
||||||
|
assertFalse(list.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getEpisodeTest() throws IOException {
|
||||||
|
Episode episode = client.getEpisode(98, 1);
|
||||||
|
assertNull(episode);
|
||||||
|
episode = client.getEpisode(1, 1);
|
||||||
|
assertEquals("Friendship is Magic Part 1", episode.name);
|
||||||
|
assertEquals(Instant.ofEpochSecond(1286735400), episode.airDate);
|
||||||
|
assertEquals(1, episode.season);
|
||||||
|
assertEquals(1, episode.episode);
|
||||||
|
assertFalse(episode.isMovie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getMovieTest() throws IOException {
|
||||||
|
Episode movie = client.getMovie(98);
|
||||||
|
assertNull(movie);
|
||||||
|
movie = client.getMovie(1);
|
||||||
|
assertEquals("Equestria Girls", movie.name);
|
||||||
|
assertEquals(Instant.ofEpochSecond(1371340800), movie.airDate);
|
||||||
|
assertEquals(99, movie.season);
|
||||||
|
assertEquals(1, movie.episode);
|
||||||
|
assertTrue(movie.isMovie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void randomTest() throws IOException {
|
||||||
|
Episode episode = client.random();
|
||||||
|
assertNotNull(episode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void searchTest() throws IOException {
|
||||||
|
List<Episode> episodes = client.search("No Results");
|
||||||
|
assertNull(episodes);
|
||||||
|
episodes = client.search("Owl's Well");
|
||||||
|
assertEquals(1, episodes.size());
|
||||||
|
Episode episode = episodes.get(0);
|
||||||
|
assertEquals("Owl's Well That Ends Well", episode.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
./gradlew test
|
|
@ -14,7 +14,7 @@ type
|
||||||
is_movie*: bool ## does this record represent a movie?
|
is_movie*: bool ## does this record represent a movie?
|
||||||
|
|
||||||
const
|
const
|
||||||
API_ENDPOINT: string = "http://ponyapi.apps.xeserv.us"
|
API_ENDPOINT: string = "https://ponyapi.apps.xeserv.us"
|
||||||
|
|
||||||
proc getJson(endpoint: string): json.JsonNode =
|
proc getJson(endpoint: string): json.JsonNode =
|
||||||
## get the HTTP body for the API base endpoint catted with the specific endpoint
|
## get the HTTP body for the API base endpoint catted with the specific endpoint
|
||||||
|
@ -44,6 +44,10 @@ proc newest*(): Episode =
|
||||||
## returns information on the newest episode of My Little Pony: Friendship is Magic.
|
## returns information on the newest episode of My Little Pony: Friendship is Magic.
|
||||||
getJson("/newest")["episode"].newEpisodeFromNode
|
getJson("/newest")["episode"].newEpisodeFromNode
|
||||||
|
|
||||||
|
proc last_aired*(): Episode =
|
||||||
|
## returns information on the most recently aired episode of My Little Pony: Friendship is Magic.
|
||||||
|
getJson("/last_aired")["episode"].newEpisodeFromNode
|
||||||
|
|
||||||
proc random*(): Episode =
|
proc random*(): Episode =
|
||||||
## returns information on a random episode.
|
## returns information on a random episode.
|
||||||
getJson("/random")["episode"].newEpisodeFromNode
|
getJson("/random")["episode"].newEpisodeFromNode
|
||||||
|
@ -72,10 +76,18 @@ when isMainModule:
|
||||||
suite "ponyapi tests":
|
suite "ponyapi tests":
|
||||||
var ep: Episode
|
var ep: Episode
|
||||||
|
|
||||||
test "Newest episode lookup":
|
test "newest episode lookup":
|
||||||
try:
|
try:
|
||||||
ep = newest()
|
ep = newest()
|
||||||
|
|
||||||
|
except:
|
||||||
|
echo getCurrentExceptionMsg()
|
||||||
|
#fail
|
||||||
|
|
||||||
|
test "last aired episode lookup":
|
||||||
|
try:
|
||||||
|
ep = last_aired()
|
||||||
|
|
||||||
except:
|
except:
|
||||||
echo getCurrentExceptionMsg()
|
echo getCurrentExceptionMsg()
|
||||||
fail
|
fail
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
set -x
|
|
||||||
|
|
||||||
nim c -r ponyapi
|
nim c -d:ssl --hints:off -r ponyapi
|
||||||
|
|
|
@ -28,7 +28,7 @@ Available methods:
|
||||||
search(query) -> return all episodes that have query in the title
|
search(query) -> return all episodes that have query in the title
|
||||||
"""
|
"""
|
||||||
|
|
||||||
API_ENDPOINT = "http://ponyapi.apps.xeserv.us"
|
API_ENDPOINT = "https://ponyapi.apps.xeserv.us"
|
||||||
|
|
||||||
# _base_get :: Text -> Maybe [Text] -> (Maybe [Text] -> IO (Either Episode [Episode]))
|
# _base_get :: Text -> Maybe [Text] -> (Maybe [Text] -> IO (Either Episode [Episode]))
|
||||||
# _base_get takes a text, a splatted list of texts and returns a function such that
|
# _base_get takes a text, a splatted list of texts and returns a function such that
|
||||||
|
@ -66,6 +66,9 @@ all_episodes = _base_get("/all")
|
||||||
# newest :: IO Episode
|
# newest :: IO Episode
|
||||||
newest = _base_get("/newest")
|
newest = _base_get("/newest")
|
||||||
|
|
||||||
|
# last_aired :: IO Episode
|
||||||
|
last_aired = _base_get("/last_aired")
|
||||||
|
|
||||||
# random :: IO Episode
|
# random :: IO Episode
|
||||||
random = _base_get("/random")
|
random = _base_get("/random")
|
||||||
|
|
||||||
|
@ -85,9 +88,9 @@ def search(query):
|
||||||
|
|
||||||
return r.json()["episodes"]
|
return r.json()["episodes"]
|
||||||
|
|
||||||
# last_aired :: IO Episode
|
# last_aired_old :: IO Episode
|
||||||
# TODO: Does not know how to wrap around seasons, fix this
|
# TODO: Does not know how to wrap around seasons, fix this
|
||||||
def last_aired():
|
def last_aired_old():
|
||||||
new = newest()
|
new = newest()
|
||||||
|
|
||||||
if new[u"air_date"] > int(time.time()):
|
if new[u"air_date"] > int(time.time()):
|
||||||
|
|
|
@ -3,7 +3,10 @@ import unittest
|
||||||
|
|
||||||
class TestPonyAPI(unittest.TestCase):
|
class TestPonyAPI(unittest.TestCase):
|
||||||
def test_newest(self):
|
def test_newest(self):
|
||||||
ponyapi.newest()
|
try:
|
||||||
|
ponyapi.newest()
|
||||||
|
except:
|
||||||
|
print "probably on hiatus"
|
||||||
|
|
||||||
def test_all_episodes(self):
|
def test_all_episodes(self):
|
||||||
assert len(ponyapi.all_episodes()) > 0
|
assert len(ponyapi.all_episodes()) > 0
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
set -x
|
|
||||||
|
|
||||||
python ./test.py
|
python ./test.py
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
set -x
|
|
||||||
|
|
||||||
for client in *
|
for client in *
|
||||||
do
|
do
|
||||||
if [ -d "$client" ]
|
if [ -d "$client" ]
|
||||||
then
|
then
|
||||||
(cd "$client" && ./test.sh)
|
time (cd "$client" && ./test.sh)
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
type
|
||||||
|
Episode* = object of RootObj
|
||||||
|
## An episode of My Little Pony: Friendship is Magic
|
||||||
|
name*: string ## Episode name
|
||||||
|
air_date*: int ## Air date in unix time
|
||||||
|
season*: int ## season number of the episode
|
||||||
|
episode*: int ## the episode number in the season
|
||||||
|
is_movie*: bool ## does this record represent a movie?
|
||||||
|
|
||||||
|
proc `%`*(ep: Episode): JsonNode =
|
||||||
|
## Convert an Episode record to a JsonNode
|
||||||
|
%*
|
||||||
|
{
|
||||||
|
"name": ep.name,
|
||||||
|
"air_date": ep.air_date,
|
||||||
|
"season": ep.season,
|
||||||
|
"episode": ep.episode,
|
||||||
|
"is_movie": ep.is_movie,
|
||||||
|
}
|
||||||
|
|
||||||
|
proc `%`*(eps: seq[Episode]): JsonNode =
|
||||||
|
## Convert a sequence of episodes to a JsonNode
|
||||||
|
result = newJArray()
|
||||||
|
|
||||||
|
for ep in eps:
|
||||||
|
add result, %ep
|
||||||
|
|
||||||
|
proc newEpisodeFromNode*(data: json.JsonNode): Episode =
|
||||||
|
## Convert a json node into an episode object
|
||||||
|
Episode(name: data["name"].getStr,
|
||||||
|
air_date: data["air_date"].getNum.int,
|
||||||
|
season: data["season"].getNum.int,
|
||||||
|
episode: data["episode"].getNum.int,
|
||||||
|
is_movie: data["is_movie"].getBVal)
|
||||||
|
|
||||||
|
proc newEpisodeListFromNode*(data: json.JsonNode): seq[Episode] =
|
||||||
|
## Convert a json array into a sequence of episode objects
|
||||||
|
var ret: seq[Episode]
|
||||||
|
for item in data.items():
|
||||||
|
ret = ret & item.newEpisodeFromNode
|
||||||
|
|
||||||
|
return ret
|
19
fim.list
19
fim.list
|
@ -104,6 +104,23 @@ FIM 1436023800 5 12 Amending Fences
|
||||||
FIM 1436628600 5 13 Do Princesses Dream of Magic Sheep?
|
FIM 1436628600 5 13 Do Princesses Dream of Magic Sheep?
|
||||||
FIM 1442071800 5 14 Canterlot Boutique
|
FIM 1442071800 5 14 Canterlot Boutique
|
||||||
FIM 1442676600 5 15 Rarity Investigates!
|
FIM 1442676600 5 15 Rarity Investigates!
|
||||||
|
FIM 1443281400 5 16 Made in Manehattan
|
||||||
|
FIM 1443886200 5 17 Brotherhooves Social
|
||||||
|
FIM 1444491000 5 18 Crusaders of the Lost Mark
|
||||||
|
FIM 1445095800 5 19 The One Where Pinkie Pie Knows
|
||||||
|
FIM 1445700600 5 20 Hearthbreakers
|
||||||
|
FIM 1446305400 5 21 Scare Master
|
||||||
|
FIM 1446913800 5 22 What About Discord
|
||||||
|
FIM 1447518600 5 23 The Hooffields and McColts
|
||||||
|
FIM 1448123400 5 24 The Mane Attraction
|
||||||
|
FIM 1448726400 5 25 The Cutie Re-Mark Part 1
|
||||||
|
FIM 1448728200 5 26 The Cutie Re-Mark Part 2
|
||||||
|
FIM 1459004400 6 1 The Crystalling Part 1
|
||||||
|
FIM 1459006200 6 2 The Crystalling Part 2
|
||||||
|
FIM 1459611000 6 3 The Gift of the Maud Pie
|
||||||
|
FIM 1460215800 6 4 On Your Marks
|
||||||
|
FIM 1460820600 6 5 Gauntlet of Fire
|
||||||
|
FIM 1462030200 6 6 No Second Prances
|
||||||
FIM 1371340800 99 1 Equestria Girls
|
FIM 1371340800 99 1 Equestria Girls
|
||||||
FIM 1411862400 99 2 Equestria Girls - Rainbow Rocks
|
FIM 1411862400 99 2 Equestria Girls - Rainbow Rocks
|
||||||
FIM 1443277800 99 3 Equestria Girls - Friendship Games
|
FIM 1443321000 99 3 Equestria Girls - Friendship Games
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
import asyncdispatch
|
||||||
|
import episode
|
||||||
|
import future
|
||||||
|
import jester
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import stats
|
||||||
|
import strutils
|
||||||
|
import times
|
||||||
|
|
||||||
|
var
|
||||||
|
episodes: seq[Episode]
|
||||||
|
|
||||||
|
for line in lines "./fim.list":
|
||||||
|
var
|
||||||
|
ep: Episode
|
||||||
|
splitLine = line.split " "
|
||||||
|
timestr = splitLine[1]
|
||||||
|
seasonstr = splitLine[2]
|
||||||
|
episodestr = splitLine[3]
|
||||||
|
is_movie = seasonstr == "99"
|
||||||
|
name = splitLine[4 .. ^1].join " "
|
||||||
|
|
||||||
|
ep = Episode(name: name,
|
||||||
|
air_date: timestr.parseInt,
|
||||||
|
season: seasonstr.parseInt,
|
||||||
|
episode: episodestr.parseInt,
|
||||||
|
is_movie: is_movie)
|
||||||
|
|
||||||
|
episodes = episodes & ep
|
||||||
|
|
||||||
|
proc `%%`(ep: Episode): JsonNode =
|
||||||
|
## Pack an episode for PonyAPI clients.
|
||||||
|
%*
|
||||||
|
{
|
||||||
|
"episode": ep,
|
||||||
|
}
|
||||||
|
|
||||||
|
proc `%%`(eps: seq[Episode]): JsonNode =
|
||||||
|
## Pack a sequence of episodes to a JsonNode for PonyAPI clients.
|
||||||
|
%*
|
||||||
|
{
|
||||||
|
"episodes": eps,
|
||||||
|
}
|
||||||
|
|
||||||
|
proc `%%`(why: string): JsonNode =
|
||||||
|
## Make an error object
|
||||||
|
%*
|
||||||
|
{
|
||||||
|
"error": why
|
||||||
|
}
|
||||||
|
|
||||||
|
proc `%`(why: string): JsonNode =
|
||||||
|
%%why
|
||||||
|
|
||||||
|
template httpReply(code, body: expr): expr =
|
||||||
|
## Make things a lot simpler for replies, etc.
|
||||||
|
if request.headers.getOrDefault("X-API-Options") == "bare" or @"options" == "bare":
|
||||||
|
# New "bare" reply format, easier to scrape, etc.
|
||||||
|
resp code, myHeaders, pretty(%body, 4)
|
||||||
|
else:
|
||||||
|
resp code, myHeaders, pretty(%%body, 4)
|
||||||
|
|
||||||
|
let myHeaders = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-Powered-By": "Nim and Jester",
|
||||||
|
"X-Git-Hash": getEnv("GIT_REV"),
|
||||||
|
"X-Server-Epoch": $ getTime().toSeconds().int,
|
||||||
|
}
|
||||||
|
|
||||||
|
settings:
|
||||||
|
port = 5000.Port
|
||||||
|
bindAddr = "0.0.0.0"
|
||||||
|
|
||||||
|
routes:
|
||||||
|
get "/":
|
||||||
|
"http://github.com/Xe/PonyAPI".uri.redirect
|
||||||
|
|
||||||
|
get "/all":
|
||||||
|
stats.all.success.inc
|
||||||
|
httpReply Http200, episodes
|
||||||
|
|
||||||
|
get "/newest":
|
||||||
|
var
|
||||||
|
now = getTime()
|
||||||
|
ep: Episode
|
||||||
|
|
||||||
|
for episode in episodes:
|
||||||
|
var then = times.fromSeconds(episode.air_date)
|
||||||
|
|
||||||
|
if now < then:
|
||||||
|
ep = episode
|
||||||
|
break
|
||||||
|
|
||||||
|
if ep.season == 0:
|
||||||
|
stats.newest.fails.inc
|
||||||
|
halt Http404, "No new episode found, hiatus?"
|
||||||
|
|
||||||
|
stats.newest.success.inc
|
||||||
|
httpReply Http200, ep
|
||||||
|
|
||||||
|
get "/random":
|
||||||
|
stats.newest.success.inc
|
||||||
|
httpReply Http200, episodes.randomChoice()
|
||||||
|
|
||||||
|
get "/last_aired":
|
||||||
|
var
|
||||||
|
#now = getTime()
|
||||||
|
ep: Episode
|
||||||
|
|
||||||
|
for epid, episode in pairs[Episode](episodes):
|
||||||
|
# XXX HACK PLEASE FIX
|
||||||
|
if episode.season == 5 and episode.episode == 26:
|
||||||
|
ep = episode
|
||||||
|
|
||||||
|
stats.lastAired.success.inc
|
||||||
|
httpReply Http200, ep
|
||||||
|
|
||||||
|
get "/season/@snumber":
|
||||||
|
var
|
||||||
|
season: int = @"snumber".parseInt
|
||||||
|
eps: seq[Episode] = lc[x | (x <- episodes, x.season == season), Episode]
|
||||||
|
|
||||||
|
if eps.len == 0:
|
||||||
|
stats.seasonLookup.fails.inc
|
||||||
|
httpReply Http404, "No episodes found"
|
||||||
|
else:
|
||||||
|
stats.seasonLookup.success.inc
|
||||||
|
httpReply Http200, eps
|
||||||
|
|
||||||
|
get "/season/@snumber/episode/@epnumber":
|
||||||
|
var
|
||||||
|
season: int = @"snumber".parseInt
|
||||||
|
enumber: int = @"epnumber".parseInt
|
||||||
|
ep: Episode
|
||||||
|
|
||||||
|
for episode in episodes:
|
||||||
|
if episode.season == season:
|
||||||
|
if episode.episode == enumber:
|
||||||
|
ep = episode
|
||||||
|
|
||||||
|
if @"format" == "irccmd":
|
||||||
|
let
|
||||||
|
irccmd = "/cs episode del $1 $2\n/cs episode add $1 $2 $3 $4" % [$ep.season, $ep.episode, $ep.air_date, ep.name]
|
||||||
|
echo irccmd
|
||||||
|
|
||||||
|
if ep.air_date == 0:
|
||||||
|
stats.episodeLookup.fails.inc
|
||||||
|
httpReply Http404, "Not found"
|
||||||
|
else:
|
||||||
|
stats.episodeLookup.success.inc
|
||||||
|
httpReply Http200, ep
|
||||||
|
|
||||||
|
get "/search":
|
||||||
|
var
|
||||||
|
query = @"q".toLower
|
||||||
|
|
||||||
|
if query == "":
|
||||||
|
stats.search.fails.inc
|
||||||
|
halt Http406, myHeaders, pretty(%%"Need to specify a query", 4)
|
||||||
|
|
||||||
|
var
|
||||||
|
eps: seq[Episode] =
|
||||||
|
lc[x | (x <- episodes, x.name.toLower.contains query), Episode]
|
||||||
|
|
||||||
|
if eps.len == 0:
|
||||||
|
stats.search.fails.inc
|
||||||
|
httpReply Http404, "No episodes found"
|
||||||
|
else:
|
||||||
|
stats.search.success.inc
|
||||||
|
httpReply Http200, eps
|
||||||
|
|
||||||
|
get "/_stats":
|
||||||
|
resp Http200, myHeaders, pretty(%*
|
||||||
|
[
|
||||||
|
stats.all,
|
||||||
|
stats.newest,
|
||||||
|
stats.random,
|
||||||
|
stats.lastAired,
|
||||||
|
stats.seasonLookup,
|
||||||
|
stats.episodeLookup,
|
||||||
|
stats.search,
|
||||||
|
], 4)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
runForever()
|
||||||
|
else:
|
||||||
|
quit "This should not be called outside of being the main module"
|
|
@ -1,10 +1,11 @@
|
||||||
[Package]
|
# Package
|
||||||
name = "ponyapi"
|
|
||||||
version = "0.1.0"
|
|
||||||
author = "Christine Dodrill <xena@yolo-swag.com>"
|
|
||||||
description = "PonyAPI client https://github.com/Xe/PonyAPI"
|
|
||||||
license = "MIT"
|
|
||||||
srcDir = "client/nim"
|
|
||||||
|
|
||||||
[Deps]
|
version = "0.2.0"
|
||||||
Requires: "nim >= 0.10.0"
|
author = "Cadey Dodrill"
|
||||||
|
description = "PonyAPI server https://github.com/Xe/PonyAPI"
|
||||||
|
license = "MIT"
|
||||||
|
bin = @["ponyapi"]
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 0.13.0", "jester#head", "random#head", "sam#head", "jsmn#head"
|
||||||
|
|
105
ponyapi.py
105
ponyapi.py
|
@ -1,105 +0,0 @@
|
||||||
import datetime
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
|
|
||||||
from flask import Flask, abort, jsonify, request, redirect
|
|
||||||
|
|
||||||
# An Episode is constructed as such:
|
|
||||||
# data Episode = Episode
|
|
||||||
# { name :: String
|
|
||||||
# , air_date :: Int
|
|
||||||
# , season :: Int
|
|
||||||
# , episode :: Int
|
|
||||||
# , is_movie :: Bool
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# Any instance of season 99 should be interpreted as a movie.
|
|
||||||
episodes = []
|
|
||||||
|
|
||||||
# First, open the input file and read in episodes
|
|
||||||
with open("./fim.list", "r") as f:
|
|
||||||
for line in f:
|
|
||||||
airdate, s, e, name = line.split(' ', 4)[1:]
|
|
||||||
|
|
||||||
episode = {
|
|
||||||
"name": name[:-1],
|
|
||||||
"air_date": int(airdate),
|
|
||||||
"season": int(s),
|
|
||||||
"episode": int(e),
|
|
||||||
"is_movie": s == "99"
|
|
||||||
}
|
|
||||||
|
|
||||||
episodes.append(episode)
|
|
||||||
|
|
||||||
# Now, initialize Flask
|
|
||||||
app = Flask(__name__)
|
|
||||||
|
|
||||||
@app.route("/")
|
|
||||||
def hello():
|
|
||||||
return redirect("https://github.com/Xe/PonyAPI#ponyapi", code=302)
|
|
||||||
|
|
||||||
@app.route("/all")
|
|
||||||
def all_episodes():
|
|
||||||
return jsonify(episodes=episodes)
|
|
||||||
|
|
||||||
@app.route("/newest")
|
|
||||||
def newest_episode():
|
|
||||||
now = datetime.datetime(2006, 1, 4)
|
|
||||||
now = now.now()
|
|
||||||
|
|
||||||
for episode in episodes:
|
|
||||||
if now.fromtimestamp(episode["air_date"]) > now:
|
|
||||||
return jsonify(episode=episode)
|
|
||||||
|
|
||||||
abort(500)
|
|
||||||
|
|
||||||
@app.route("/season/<number>")
|
|
||||||
def season(number):
|
|
||||||
retEpisodes = []
|
|
||||||
|
|
||||||
for episode in episodes:
|
|
||||||
if str(episode["season"]) == number:
|
|
||||||
retEpisodes.append(episode)
|
|
||||||
|
|
||||||
try:
|
|
||||||
assert len(retEpisodes) > 0
|
|
||||||
except:
|
|
||||||
abort(404)
|
|
||||||
|
|
||||||
return jsonify(episodes=retEpisodes)
|
|
||||||
|
|
||||||
@app.route("/season/<snumber>/episode/<epnumber>")
|
|
||||||
def show_episode(snumber, epnumber):
|
|
||||||
for episode in episodes:
|
|
||||||
if str(episode["season"]) == snumber and str(episode["episode"]) == epnumber:
|
|
||||||
return jsonify(episode=episode)
|
|
||||||
|
|
||||||
abort(404)
|
|
||||||
|
|
||||||
@app.route("/random")
|
|
||||||
def show_random_ep():
|
|
||||||
return jsonify(episode=random.choice(episodes))
|
|
||||||
|
|
||||||
@app.route("/search")
|
|
||||||
def search():
|
|
||||||
retEpisodes = []
|
|
||||||
term = request.args.get("q", "").lower()
|
|
||||||
|
|
||||||
try:
|
|
||||||
assert term != ""
|
|
||||||
except:
|
|
||||||
abort(406)
|
|
||||||
|
|
||||||
for episode in episodes:
|
|
||||||
if term in episode["name"].lower():
|
|
||||||
retEpisodes.append(episode)
|
|
||||||
|
|
||||||
try:
|
|
||||||
assert len(retEpisodes) > 0
|
|
||||||
except:
|
|
||||||
abort(404)
|
|
||||||
|
|
||||||
return jsonify(episodes=retEpisodes)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run(host="0.0.0.0", debug=True)
|
|
|
@ -489,7 +489,7 @@ pre {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-width: calc(100% - 19.5px);
|
min-width: calc(100% - 19.5px);
|
||||||
padding: 9.5px;
|
padding: 9.5px;
|
||||||
margin: 0 10px 0px 10px;
|
margin: 0.25em 10px 0.25em 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
white-space: pre !important;
|
white-space: pre !important;
|
||||||
|
@ -892,6 +892,10 @@ div.align-right {
|
||||||
|
|
||||||
/* div.align-center * { */
|
/* div.align-center * { */
|
||||||
/* text-align: left } */
|
/* text-align: left } */
|
||||||
|
|
||||||
|
ul.simple > li {
|
||||||
|
margin-bottom: 0.5em }
|
||||||
|
|
||||||
ol.simple, ul.simple {
|
ol.simple, ul.simple {
|
||||||
margin-bottom: 1em; }
|
margin-bottom: 1em; }
|
||||||
|
|
||||||
|
@ -1160,11 +1164,11 @@ dt pre > span.Operator ~ span.Identifier, dt pre > span.Operator ~ span.Operator
|
||||||
<ul class="simple simple-toc-section">
|
<ul class="simple simple-toc-section">
|
||||||
<li><a class="reference" href="#Episode"
|
<li><a class="reference" href="#Episode"
|
||||||
title="Episode = object of RootObj
|
title="Episode = object of RootObj
|
||||||
name*: string ## Episode name
|
name*: string ## Episode name
|
||||||
air_date*: int ## Air date in unix time
|
air_date*: int ## Air date in unix time
|
||||||
season*: int ## season number of the episode
|
season*: int ## season number of the episode
|
||||||
episode*: int ## the episode number in the season
|
episode*: int ## the episode number in the season
|
||||||
is_movie*: bool ## does this record represent a movie?"><wbr />Episode</a></li>
|
is_movie*: bool ## does this record represent a movie?"><wbr />Episode</a></li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1173,6 +1177,8 @@ dt pre > span.Operator ~ span.Identifier, dt pre > span.Operator ~ span.Operator
|
||||||
<ul class="simple simple-toc-section">
|
<ul class="simple simple-toc-section">
|
||||||
<li><a class="reference" href="#newest,"
|
<li><a class="reference" href="#newest,"
|
||||||
title="newest(): Episode"><wbr />newest</a></li>
|
title="newest(): Episode"><wbr />newest</a></li>
|
||||||
|
<li><a class="reference" href="#last_aired,"
|
||||||
|
title="last_aired(): Episode"><wbr />last_<wbr />aired</a></li>
|
||||||
<li><a class="reference" href="#random,"
|
<li><a class="reference" href="#random,"
|
||||||
title="random(): Episode"><wbr />random</a></li>
|
title="random(): Episode"><wbr />random</a></li>
|
||||||
<li><a class="reference" href="#get_episode,int,int"
|
<li><a class="reference" href="#get_episode,int,int"
|
||||||
|
@ -1201,11 +1207,11 @@ dt pre > span.Operator ~ span.Identifier, dt pre > span.Operator ~ span.Operator
|
||||||
<h1><a class="toc-backref" href="#7">Types</a></h1>
|
<h1><a class="toc-backref" href="#7">Types</a></h1>
|
||||||
<dl class="item">
|
<dl class="item">
|
||||||
<dt id="Episode"><a name="Episode"></a><pre><span class="Identifier">Episode</span> <span class="Other">=</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">RootObj</span>
|
<dt id="Episode"><a name="Episode"></a><pre><span class="Identifier">Episode</span> <span class="Other">=</span> <span class="Keyword">object</span> <span class="Keyword">of</span> <span class="Identifier">RootObj</span>
|
||||||
<span class="Identifier">name</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">string</span> <span class="Comment">## Episode name</span>
|
<span class="Identifier">name</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">string</span> <span class="Comment">## Episode name</span>
|
||||||
<span class="Identifier">air_date</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">int</span> <span class="Comment">## Air date in unix time</span>
|
<span class="Identifier">air_date</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">int</span> <span class="Comment">## Air date in unix time</span>
|
||||||
<span class="Identifier">season</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">int</span> <span class="Comment">## season number of the episode</span>
|
<span class="Identifier">season</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">int</span> <span class="Comment">## season number of the episode</span>
|
||||||
<span class="Identifier">episode</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">int</span> <span class="Comment">## the episode number in the season</span>
|
<span class="Identifier">episode</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">int</span> <span class="Comment">## the episode number in the season</span>
|
||||||
<span class="Identifier">is_movie</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">bool</span> <span class="Comment">## does this record represent a movie?</span>
|
<span class="Identifier">is_movie</span><span class="Operator">*</span><span class="Other">:</span> <span class="Identifier">bool</span> <span class="Comment">## does this record represent a movie?</span>
|
||||||
</pre></dt>
|
</pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
An episode of My Little Pony: Friendship is Magic
|
An episode of My Little Pony: Friendship is Magic
|
||||||
|
@ -1216,45 +1222,53 @@ An episode of My Little Pony: Friendship is Magic
|
||||||
<div class="section" id="12">
|
<div class="section" id="12">
|
||||||
<h1><a class="toc-backref" href="#12">Procs</a></h1>
|
<h1><a class="toc-backref" href="#12">Procs</a></h1>
|
||||||
<dl class="item">
|
<dl class="item">
|
||||||
<dt id="newest"><a name="newest,"></a><pre><span class="Keyword">proc</span> <span class="Identifier">newest</span><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">Episode</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span> <span class="Identifier">HttpRequestError</span><span class="Other">,</span>
|
<dt id="newest"><a name="newest,"></a><pre><span class="Keyword">proc</span> <span class="Identifier">newest</span><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">Episode</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span> <span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span>
|
||||||
<span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span>
|
<span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
||||||
<span class="Identifier">Exception</span><span class="Other">,</span> <span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span>
|
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span>
|
||||||
<span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
<span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
returns information on the newest episode of My Little Pony: Friendship is Magic.
|
returns information on the newest episode of My Little Pony: Friendship is Magic.
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="random"><a name="random,"></a><pre><span class="Keyword">proc</span> <span class="Identifier">random</span><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">Episode</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span> <span class="Identifier">HttpRequestError</span><span class="Other">,</span>
|
<dt id="last_aired"><a name="last_aired,"></a><pre><span class="Keyword">proc</span> <span class="Identifier">last_aired</span><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">Episode</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span> <span class="Identifier">HttpRequestError</span><span class="Other">,</span>
|
||||||
<span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span>
|
<span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span>
|
||||||
<span class="Identifier">Exception</span><span class="Other">,</span> <span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span>
|
<span class="Identifier">Exception</span><span class="Other">,</span> <span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span>
|
||||||
<span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
<span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
||||||
|
<dd>
|
||||||
|
returns information on the most recently aired episode of My Little Pony: Friendship is Magic.
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt id="random"><a name="random,"></a><pre><span class="Keyword">proc</span> <span class="Identifier">random</span><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">Episode</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span> <span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span>
|
||||||
|
<span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
||||||
|
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span>
|
||||||
|
<span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
returns information on a random episode.
|
returns information on a random episode.
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="get_episode"><a name="get_episode,int,int"></a><pre><span class="Keyword">proc</span> <span class="Identifier">get_episode</span><span class="Other">(</span><span class="Identifier">season</span><span class="Other">,</span> <span class="Identifier">episode</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">Episode</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span>
|
<dt id="get_episode"><a name="get_episode,int,int"></a><pre><span class="Keyword">proc</span> <span class="Identifier">get_episode</span><span class="Other">(</span><span class="Identifier">season</span><span class="Other">,</span> <span class="Identifier">episode</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">Episode</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span>
|
||||||
<span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
<span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
||||||
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
return an arbitrary episode by season, episode pair.
|
return an arbitrary episode by season, episode pair.
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="all_episodes"><a name="all_episodes,"></a><pre><span class="Keyword">proc</span> <span class="Identifier">all_episodes</span><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">seq</span><span class="Other">[</span><span class="Identifier">Episode</span><span class="Other">]</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span>
|
<dt id="all_episodes"><a name="all_episodes,"></a><pre><span class="Keyword">proc</span> <span class="Identifier">all_episodes</span><span class="Other">(</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">seq</span><span class="Other">[</span><span class="Identifier">Episode</span><span class="Other">]</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span> <span class="Identifier">HttpRequestError</span><span class="Other">,</span>
|
||||||
<span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
<span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span> <span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span>
|
||||||
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
<span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
return all information on all episodes.
|
return all information on all episodes.
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="get_season"><a name="get_season,int"></a><pre><span class="Keyword">proc</span> <span class="Identifier">get_season</span><span class="Other">(</span><span class="Identifier">season</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">seq</span><span class="Other">[</span><span class="Identifier">Episode</span><span class="Other">]</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span>
|
<dt id="get_season"><a name="get_season,int"></a><pre><span class="Keyword">proc</span> <span class="Identifier">get_season</span><span class="Other">(</span><span class="Identifier">season</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">seq</span><span class="Other">[</span><span class="Identifier">Episode</span><span class="Other">]</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span>
|
||||||
<span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
<span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
||||||
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
return all information on a single season.
|
return all information on a single season.
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt id="search"><a name="search,string"></a><pre><span class="Keyword">proc</span> <span class="Identifier">search</span><span class="Other">(</span><span class="Identifier">term</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">seq</span><span class="Other">[</span><span class="Identifier">Episode</span><span class="Other">]</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span>
|
<dt id="search"><a name="search,string"></a><pre><span class="Keyword">proc</span> <span class="Identifier">search</span><span class="Other">(</span><span class="Identifier">term</span><span class="Other">:</span> <span class="Identifier">string</span><span class="Other">)</span><span class="Other">:</span> <span class="Identifier">seq</span><span class="Other">[</span><span class="Identifier">Episode</span><span class="Other">]</span> <span class="Other">{.</span><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ValueError</span><span class="Other">,</span> <span class="Identifier">OSError</span><span class="Other">,</span>
|
||||||
<span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
<span class="Identifier">HttpRequestError</span><span class="Other">,</span> <span class="Identifier">OverflowError</span><span class="Other">,</span> <span class="Identifier">TimeoutError</span><span class="Other">,</span> <span class="Identifier">ProtocolError</span><span class="Other">,</span> <span class="Identifier">Exception</span><span class="Other">,</span>
|
||||||
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
<span class="Identifier">JsonParsingError</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Identifier">ReadIOEffect</span><span class="Other">,</span> <span class="Identifier">WriteIOEffect</span><span class="Other">,</span> <span class="Identifier">TimeEffect</span><span class="Other">]</span><span class="Other">.}</span></pre></dt>
|
||||||
<dd>
|
<dd>
|
||||||
searches for episodes by the given query term.
|
searches for episodes by the given query term.
|
||||||
|
@ -1270,7 +1284,7 @@ searches for episodes by the given query term.
|
||||||
<div class="twelve-columns footer">
|
<div class="twelve-columns footer">
|
||||||
<span class="nim-sprite"></span>
|
<span class="nim-sprite"></span>
|
||||||
<br>
|
<br>
|
||||||
<small>Made with Nim. Generated: 2015-08-12 17:29:43 UTC</small>
|
<small>Made with Nim. Generated: 2015-08-17 15:01:16 UTC</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -1,8 +0,0 @@
|
||||||
Flask==0.10.1
|
|
||||||
Jinja2==2.8
|
|
||||||
MarkupSafe==0.23
|
|
||||||
Werkzeug==0.10.4
|
|
||||||
argparse==1.2.1
|
|
||||||
gunicorn==19.3.0
|
|
||||||
itsdangerous==0.24
|
|
||||||
wsgiref==0.1.2
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
ponyapi.apps.xeserv.us {
|
||||||
|
log syslog
|
||||||
|
|
||||||
|
proxy / http://127.0.0.1:6452 {
|
||||||
|
proxy_header Host {host}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
[Unit]
|
||||||
|
Description=PonyAPI Server listening on port 6452
|
||||||
|
Requires=docker.service
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStartPre=-/usr/bin/docker pull xena/ponyapi
|
||||||
|
ExecStartPre=-/usr/bin/docker rm -f ponyapi
|
||||||
|
ExecStart=/usr/bin/docker run -p 6452:5000 --name ponyapi xena/ponyapi
|
||||||
|
ExecStop=/usr/bin/docker rm -f ponyapi
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=network.target
|
|
@ -0,0 +1,25 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
type
|
||||||
|
Bucket* = object of RootObj
|
||||||
|
## A collection of stats
|
||||||
|
name*: string
|
||||||
|
fails*: int
|
||||||
|
success*: int
|
||||||
|
|
||||||
|
proc `%`*(b: Bucket): JsonNode =
|
||||||
|
%*
|
||||||
|
{
|
||||||
|
"name": b.name,
|
||||||
|
"fails": b.fails,
|
||||||
|
"success": b.success,
|
||||||
|
}
|
||||||
|
|
||||||
|
var
|
||||||
|
all* = Bucket(name: "all")
|
||||||
|
newest* = Bucket(name: "newest")
|
||||||
|
random* = Bucket(name: "random")
|
||||||
|
lastAired* = Bucket(name: "lastAired")
|
||||||
|
seasonLookup* = Bucket(name: "seasonLookup")
|
||||||
|
episodeLookup* = Bucket(name: "episodeLookup")
|
||||||
|
search* = Bucket(name: "search")
|
Loading…
Reference in New Issue