dependencies
| (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)) | |||||||||