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