gengo-clj

0.1.0-SNAPSHOT


Gengo API for Clojure

dependencies

org.clojure/clojure
1.6.0
org.clojure/data.json
0.1.2
clj-http
0.3.5



(this space intentionally left almost blank)
 
(ns gengoclj.auth
  (:import
   (java.util Calendar)
   (javax.crypto Mac)
   (javax.crypto.spec SecretKeySpec)
   (java.math BigInteger)))
(defn- current-timestamp []
  (let [cal (Calendar/getInstance)
        current-time-millis (long (/ (long (.getTimeInMillis cal)) 1000))]
    (String/valueOf current-time-millis)))
(defn- get-hash-str [data-bytes]
  (apply str
	  (map #(.substring
           (Integer/toString (+ (bit-and % 0xff) 0x100) 16) 1) data-bytes)))

Calculate HMAC signature for given data.

(defn- hmac
  [#^String key #^String data]
  (let [hmac-sha1 "HmacSHA1"
        signing-key (SecretKeySpec. (.getBytes key "iso-8859-1") hmac-sha1)
        mac (doto (Mac/getInstance hmac-sha1) (.init signing-key))]
    (get-hash-str (.doFinal mac (.getBytes data "iso-8859-1")))))

Creates map of required data for gengo authentication

(defn- add-auth-params
  [key secret request]
  (let [ts (current-timestamp)]
    (assoc request
      :query (merge
               (request :query)
               {:ts ts
                :api_sig (hmac secret ts)
                :api_key key}))))
(defn- add-data-param [request]
  (assoc-in request [:query :data] (request :body)))
(defn authenticated-request [key secret request]
  (add-auth-params key secret (add-data-param request)))
 
(ns gengoclj.gengo
  (:require
   [clj-http.client :as http]
   [gengoclj.auth :as auth])
  (:use [clojure.data.json :only [json-str read-json]]
        [clojure.string :only [join]]))
(def client-version 0.1)
(def user-agent (format "Gengo Clojure library; Version %f" client-version))
(def gengo-live-base "https://api.gengo.com/v2/")
(def gengo-sandbox-base "http://api.sandbox.gengo.com/v2/")
(def ^{:dynamic true} *gengo-key* nil)
(def ^{:dynamic true} *gengo-secret* nil)
(def ^{:dynamic true} *sandbox?* true)
(defmacro with-gengo [[key secret sandbox?] & body]
  `(binding [*gengo-key* ~key *gengo-secret* ~secret *sandbox?* ~sandbox?]
     ~@body))
(defstruct request :method :path :query :body)
(defstruct job :slug :body_src :lc_src :lc_tgt :tier)
(defn- uri [path]
  (if *sandbox?*
    (str gengo-sandbox-base path)
    (str gengo-live-base path)))
(defn- make-uri [request]
  (uri (request :path)))
(defn- parameter-string [params]
  (join "&"
        (map (fn [[key val]] (str (name key) "=" (str val)))
             (sort-by #(name (key %)) java.lang.String/CASE_INSENSITIVE_ORDER params))))
(defn- make-post-request [request]
  {:body (parameter-string
           (merge
             (:query
               (auth/authenticated-request *gengo-key* *gengo-secret* request))
               (assoc {} :data (json-str (request :body)))))
    :query-params nil
    :headers {"Content-Type" "application/x-www-form-urlencoded"
              "User-Agent" user-agent
              "Accept" "application/json"}})
(defn- make-put-request [request]
  {:body (parameter-string
           (merge
             (:query
               (auth/authenticated-request *gengo-key* *gengo-secret* request))
               (assoc {} :data (json-str (request :body)))))
    :query-params nil
    :headers {"Content-Type" "text/plain"
              "User-Agent" user-agent
              "Accept" "application/json"}})
(defn- do-get! [request]
  (read-json (:body (http/get (make-uri request)
              {:body (request :body)
               :query-params (:query (auth/authenticated-request *gengo-key* *gengo-secret* request))
               :headers {"Content-Type" "application/json"
                         "User-Agent" user-agent
                         "Accept" "application/json"}}))))
(defn- do-post! [request]
  (let [request-body (make-post-request request)]
    (read-json (:body (http/post (make-uri request)
            request-body)))))
(defn- do-put! [request]
  (let [request-body (make-put-request request)]
    (read-json (:body (http/put (make-uri request)
              request-body)))))
(defn- do-delete! [request]
  (read-json (:body (http/delete (make-uri request)
               {:body (request :body)
                :query-params (:query (auth/authenticated-request *gengo-key* *gengo-secret* request))
                :headers {"Content-Type" 
                          "User-Agent" user-agent
                          "Accept" "application/json"}}))))

Get account statistics

(defn get-account-stats
  []
  (let [request (struct request "GET" "account/stats" nil nil)]
    (do-get! request)))

Get account balance

(defn get-account-balance
  []
  (let [request (struct request "GET" "account/balance" nil nil)]
    (do-get! request)))

Get preferred translators in array by langs and tier

(defn get-account-preferred-translators
  []
  (let [request (struct request "GET" "account/preferred_translators" nil nil)]
    (do-get! request)))

Submit multiple jobs for translation

(defn post-translation-jobs
  [jobs as-group?]
  (let [request (struct request "POST" "translate/jobs" nil {:jobs jobs :as_group (if as-group? "1" "0")})]
    (do-post! request)))

Request revisions for a job

(defn revise-translation-job
  [job-id comments]
  (let [request (struct request "PUT" (format "translate/job/%d" job-id) nil {:action "revise" :comment comments})]
    (do-put! request)))

Approve a translation

(defn approve-translation-job
  [job-id rating translator-comments gengo-comments is-public?]
  (let [request (struct request "PUT" (format "translate/job/%d" job-id) nil
                        (merge {:action "approve" :public (if is-public? "1" "0")}
                          (if (nil? rating) {} {:rating rating})
                          (if (nil? translator-comments) {} {:commentsForTranslator translator-comments})
                          (if (nil? gengo-comments) {} {:commentsForGengo gengo-comments})))]
    (do-put! request)))

Reject a translation

(defn reject-translation-job
  [job-id reason comments captcha requeue?]
  (let [request (struct request "PUT" (format "translate/job/%d" job-id) nil
                  {:action "reject" :reason reason :comment comments :captcha captcha :follow_up (if requeue? "requeue" "cancel")})]
    (do-put! request)))

Get a translation job

(defn get-translation-job
  [job-id]
  (let [request (struct request "GET" (format "translate/job/%d" job-id) nil nil)]
    (do-get! request)))

Get all or slected translation jobs

(defn get-translation-jobs
  [& [job-ids]]
  (let [request (struct request "GET" (if job-ids (str "translate/jobs/" (join "," job-ids)) "translate/jobs/") nil nil)]
    (do-get! request)))

Post a comment for a translation job

(defn post-translation-job-comment
  [job-id comments]
  (let [request (struct request "POST" (format "translate/job/%d/comment" job-id) nil {:body comments})]
    (do-post! request)))

Get comments for a translation job

(defn get-translation-job-comments
  [job-id]
  (let [request (struct request "GET" (format "translate/job/%d/comments" job-id) nil nil)]
    (do-get! request)))

Get feedback for a translation job

(defn get-translation-job-feedback
  [job-id]
  (let [request (struct request "GET" (format "translate/job/%d/feedback" job-id) nil nil)]
    (do-get! request)))

Get revisions for a translation job

(defn get-translation-job-revisions
  [job-id]
  (let [request (struct request "GET" (format "translate/job/%d/revisions" job-id) nil nil)]
    (do-get! request)))

Get a specific revision for a translation job

(defn get-translation-job-revision
  [job-id revision-id]
  (let [request (struct request "GET" (format "translate/job/%d/revisions/%d/" job-id revision-id) nil nil)]
    (do-get! request)))

Cancel a translation job. It can only be deleted if it has not been started by a translator

(defn delete-translation-job
  [job-id]
  (let [request (struct request "DELETE" (format "translate/job/%d" job-id) nil nil)]
    (do-delete! request)))

Get a list of supported languages and their language codes

(defn get-service-languages
  []
  (let [request (struct request "GET" "translate/service/languages" nil nil)]
    (do-get! request)))

Get a list of supported language pairs, tiers, and credit prices

(defn get-service-language-pairs
  [&[source-lang-code]]
  (let [request (struct request "GET" "translate/service/language_pairs" (if source-lang-code {:lc_src source-lang-code} nil) nil)]
    (do-get! request)))

Get a quote for translation jobs.

(defn determine-translation-cost
  [jobs]
  (let [request (struct request "POST" "translate/service/quote" nil {:jobs jobs})]
    (do-post! request)))

Get translation jobs which were previously submitted together by their order id

(defn get-order-jobs
  [order-id]
  (let [request (struct request "GET" (format "translate/order/%d" order-id) nil nil)]
    (do-get! request)))
 
(ns gengoclj.examples.account
  (:require [gengoclj.gengo :as gengo]))

get account balance

(with-gengo ["key" "secret" true]
  (get-account-balance))

get account preferred translators

(with-gengo ["key" "secret" true]
  (get-account-preferred-translators))

get account stats

(with-gengo ["key" "secret" true]
  (get-account-stats))
 
(ns gengoclj.examples.jobs
  (:require [gengoclj.gengo :as gengo]))

delete a translation job

(with-gengo ["key" "secret" true]
  (delete-translation-job 12345))

get a translation job

(with-gengo ["key" "secret" true]
  (get-translation-job 12345))

get a translation job's comments

(with-gengo ["key" "secret" true]
  (get-translation-job-comments 12345))

get a translation job's feedback

(with-gengo ["key" "secret" true]
  (get-translation-job-feedback 12345))

get a translation job's revisions

(with-gengo ["key" "secret" true]
  (get-translation-job-revisions 12345))

get a specific translation job's revision

(with-gengo ["key" "secret" true]
  (get-translation-job-revision 12345 6))

get multiple translation jobs

(with-gengo ["key" "secret" true]
  (get-translation-jobs (list 1 2 3 4 5)))

get all translation jobs

(with-gengo ["key" "secret" true]
  (get-translation-jobs))

post a comment on a translation job

(with-gengo ["key" "secret" true]
  (post-translation-job-comment 12345 "This is a comment."))

post new translation jobs

(with-gengo ["key" "secret" true]
  (let [job1 (struct job "slug1" "content1" "en" "es" "standard")
        job2 (struct job "slug2" "content2" "en" "es" "standard")]
    (post-translation-jobs (list job1 job2) true)))

approve a translation job params - job-id rating (integer 1-5) translator-comments gengo-comments is-public?

(with-gengo ["key" "secret" true]
  (approve-translation-job 12345 4 "Something for the translator" "Something for gengo" true))

reject a translation job params - job-id reason (0: Quality 1: Incomplete 2: Other) comments captcha requeue?

(with-gengo ["key" "secret" true]
  (reject-translation-job 12345 0 "Some comment" "captcha text" true))

revise a translation job params - job-id comments

(with-gengo ["key" "secret" true]
  (revise-translation-job 12345 "Please fix this and that"))
 
(ns gengoclj.examples.order
  (:require [gengoclj.gengo :as gengo]))

get group of jobs submitted together by their order id

(with-gengo ["key" "secret" true]
  (get-order-jobs 12345))
 
(ns gengoclj.examples.service
  (:require [gengoclj.gengo :as gengo]))

get all service language pairs

(with-gengo ["key" "secret" true]
  (get-service-language-pairs))

get specific service language pairs by source language

(with-gengo ["key" "secret" true]
  (get-service-language-pairs "en"))

get service languages

(with-gengo ["key" "secret" true]
  (get-service-languages))