Merge pull request #540 from status-im/feature/#445

!faucet command (#445)
This commit is contained in:
Roman Volosovskyi 2016-12-09 13:03:41 +02:00 committed by GitHub
commit 379669ada0
12 changed files with 215 additions and 17 deletions

2
.gitignore vendored
View File

@ -2,6 +2,8 @@
# #
.DS_Store .DS_Store
.projectile .projectile
.cljs_rhino_repl/
.#*
# Xcode # Xcode
# #

View File

@ -13,8 +13,10 @@ I18n.translations = {
password_placeholder2: 'Please re-enter password to confirm', password_placeholder2: 'Please re-enter password to confirm',
password_error: 'Password should be not less then 6 symbols.', password_error: 'Password should be not less then 6 symbols.',
password_error1: 'Password confirmation doesn\'t match password.', password_error1: 'Password confirmation doesn\'t match password.',
password_validation_title: 'Password' password_validation_title: 'Password',
faucet_incorrect_title: 'Incorrect faucet',
faucet_incorrect_description: 'Please, select a one from the list'
}, },
ru: { ru: {
phone_title: 'Отправить номер телефона', phone_title: 'Отправить номер телефона',
@ -1594,7 +1596,6 @@ status.command({
handler: jsHandler handler: jsHandler
}); });
var phones = [ // TODO this is supposed to be regionalised var phones = [ // TODO this is supposed to be regionalised
{ {
number: "89171111111", number: "89171111111",
@ -1719,6 +1720,111 @@ var phoneConfig = {
status.response(phoneConfig); status.response(phoneConfig);
status.command(phoneConfig); status.command(phoneConfig);
var faucets = [
{
name: "Ethereum Robsten Faucet",
url: "http://faucet.ropsten.be:3001"
},
{
name: "Status Testnet Faucet",
url: "http://46.101.129.137:3001",
},
{
name: "Zerogox Faucet",
url: "https://zerogox.com/ethereum/wei_faucet"
}
];
function faucetSuggestions(params) {
var suggestions = faucets.map(function(entry) {
return status.components.touchable(
{onPress: [status.events.SET_VALUE, entry.url]},
status.components.view(
suggestionContainerStyle,
[status.components.view(
suggestionSubContainerStyle,
[
status.components.text(
{style: valueStyle},
entry.name
),
status.components.text(
{style: descriptionStyle},
entry.url
)
]
)]
)
);
});
var view = status.components.scrollView(
suggestionsContainerStyle(faucets.length),
suggestions
);
return {markup: view};
}
status.command({
name: "faucet",
title: "Faucet",
description: "Get some ETH",
color: "#7099e6",
registeredOnly: true,
params: [{
name: "url",
type: status.types.TEXT,
suggestions: faucetSuggestions,
placeholder: "Faucet URL"
}],
preview: function (params) {
return status.components.text(
{},
params.url
);
},
validator: function (params, context) {
var f = faucets.map(function (entry) {
return entry.url;
});
if (f.indexOf(params.url) == -1) {
var error = status.components.validationMessage(
I18n.t('faucet_incorrect_title'),
I18n.t('faucet_incorrect_description')
);
return {errors: [error]};
}
}
});
function browseSuggestions(params) {
if (params.url && params.url !== "undefined" && params.url != "") {
var url = params.url;
if (!/^[a-zA-Z-_]+:/.test(url)) {
url = 'http://' + url;
}
return {webViewUrl: url};
}
}
status.command({
name: "browse",
color: "#ffa500",
hidden: true,
fullscreen: true,
suggestionsTrigger: 'on-send',
params: [{
name: "url",
suggestions: browseSuggestions,
type: status.types.TEXT
}]
});
// status.command({ // status.command({
// name: "help", // name: "help",
@ -1822,4 +1928,4 @@ status.registerFunction("message-suggestions", function(params, context) {
status.registerFunction("message-handler", function(params, context) { status.registerFunction("message-handler", function(params, context) {
return jsHandler({code: params.message}, context); return jsHandler({code: params.message}, context);
}); });

View File

@ -26,6 +26,7 @@ Command.prototype.create = function (com) {
this.description = com.description; this.description = com.description;
this.handler = com.handler; this.handler = com.handler;
this["has-handler"] = com.handler != null; this["has-handler"] = com.handler != null;
this["registered-only"] = com.registeredOnly;
this.validator = com.validator; this.validator = com.validator;
this.color = com.color; this.color = com.color;
this.icon = com.icon; this.icon = com.icon;

View File

@ -34,6 +34,7 @@
status-im.chat.handlers.unviewed-messages status-im.chat.handlers.unviewed-messages
status-im.chat.handlers.send-message status-im.chat.handlers.send-message
status-im.chat.handlers.receive-message status-im.chat.handlers.receive-message
status-im.chat.handlers.faucet
[cljs.core.async :as a] [cljs.core.async :as a]
status-im.chat.handlers.webview-bridge status-im.chat.handlers.webview-bridge
status-im.chat.handlers.wallet-chat status-im.chat.handlers.wallet-chat
@ -584,6 +585,10 @@
(fn [{:keys [current-chat-id] :as db} [_ url]] (fn [{:keys [current-chat-id] :as db} [_ url]]
(assoc-in db [:web-view-url current-chat-id] url))) (assoc-in db [:web-view-url current-chat-id] url)))
(register-handler :set-web-view-extra-js
(fn [{:keys [current-chat-id] :as db} [_ extra-js]]
(assoc-in db [:web-view-extra-js current-chat-id] extra-js)))
(register-handler :set-soft-input-mode (register-handler :set-soft-input-mode
(after (after
(fn [{:keys [current-chat-id]} [_ mode chat-id]] (fn [{:keys [current-chat-id]} [_ mode chat-id]]

View File

@ -18,12 +18,16 @@
:confirmation-code :confirmation-code
(fn [params id] (fn [params id]
(dispatch [:sign-up-confirm (params "code") id]))}) (dispatch [:sign-up-confirm (params "code") id]))
:faucet
(fn [params id]
(dispatch [:open-faucet (params "url") id]))})
(def commands-names (set (keys console-commands))) (def commands-names (set (keys console-commands)))
(def commands-with-delivery-status (def commands-with-delivery-status
(disj commands-names :password)) (disj commands-names :password :faucet))
(register-handler :invoke-console-command-handler! (register-handler :invoke-console-command-handler!
(u/side-effect! (u/side-effect!

View File

@ -0,0 +1,65 @@
(ns status-im.chat.handlers.faucet
(:require [re-frame.core :refer [dispatch]]
[status-im.utils.handlers :refer [register-handler] :as u]
[status-im.utils.utils :refer [http-get]]
[status-im.utils.random :as random]
[status-im.constants :refer [console-chat-id
text-content-type]]
[status-im.i18n :refer [label]]
[taoensso.timbre :as log]
[goog.string :as gstring]
goog.string.format))
(def faucets
[{:name "http://faucet.ropsten.be:3001"
:type :api
:api-url "http://faucet.ropsten.be:3001/donate/0x%s"}
{:name "http://46.101.129.137:3001"
:type :api
:api-url "http://46.101.129.137:3001/donate/0x%s"}
{:name "https://zerogox.com/ethereum/wei_faucet"
:type :prefill
:prefill-js "document.getElementById('edit-ethereum-address').value='%s';"}])
(defn faucet-by-name [faucet-name]
(->> faucets
(filter #(= (:name %) faucet-name))
(first)))
(defn received-message [content]
(dispatch [:received-message
{:message-id (random/id)
:content content
:content-type text-content-type
:outgoing false
:chat-id console-chat-id
:from console-chat-id
:to "me"}]))
(defmulti open-faucet (fn [_ _ {:keys [type]}] type))
(defmethod open-faucet :api
[faucet-name current-address {:keys [api-url]}]
(let [api-url (gstring/format api-url current-address)]
(http-get api-url
#(received-message (label :t/faucet-success))
#(received-message (label :t/faucet-error)))))
(defmethod open-faucet :prefill
[faucet-name current-address {:keys [prefill-js]}]
(let [prefill-js (gstring/format prefill-js current-address)
web-view-js (gstring/format
"document.addEventListener('DOMContentLoaded', function(){ %s };"
prefill-js)]
(dispatch [:set-chat-command :browse])
(dispatch [:fill-chat-command-content faucet-name])
(dispatch [:set-web-view-extra-js web-view-js])
(js/setTimeout #(dispatch [:send-command!]) 500)))
(register-handler
:open-faucet
(u/side-effect!
(fn [{:keys [accounts current-account-id]} [_ faucet-name _]]
(if-let [faucet (faucet-by-name faucet-name)]
(let [current-address (get-in accounts [current-account-id :address])]
(open-faucet faucet-name current-address faucet))))))

View File

@ -260,6 +260,11 @@
(let [chat-id (subscribe [:get-current-chat-id])] (let [chat-id (subscribe [:get-current-chat-id])]
(reaction (get-in @db [:web-view-url @chat-id]))))) (reaction (get-in @db [:web-view-url @chat-id])))))
(register-sub :web-view-extra-js
(fn [db]
(let [chat-id (subscribe [:get-current-chat-id])]
(reaction (get-in @db [:web-view-extra-js @chat-id])))))
(register-sub :animate? (register-sub :animate?
(fn [db] (fn [db]
(let [chat-id (subscribe [:get-current-chat-id])] (let [chat-id (subscribe [:get-current-chat-id])]

View File

@ -129,7 +129,8 @@
[text (label :t/web-view-error)]])) [text (label :t/web-view-error)]]))
(defview suggestions-web-view [] (defview suggestions-web-view []
[url [:web-view-url]] [url [:web-view-url]
extra-js [:web-view-extra-js]]
(when url (when url
[webview-bridge [webview-bridge
{:ref #(dispatch [:set-webview-bridge %]) {:ref #(dispatch [:set-webview-bridge %])
@ -137,7 +138,7 @@
:source {:uri url} :source {:uri url}
:render-error web-view-error :render-error web-view-error
:java-script-enabled true :java-script-enabled true
:injected-java-script js-res/webview-js :injected-java-script (str js-res/webview-js extra-js)
:bounces false :bounces false
:on-navigation-state-change on-navigation-change}])) :on-navigation-state-change on-navigation-change}]))

View File

@ -1,5 +1,6 @@
(ns status-im.chat.views.suggestions (ns status-im.chat.views.suggestions
(:require-macros [status-im.utils.views :refer [defview]]) (:require-macros [status-im.utils.views :refer [defview]]
[clojure.string :as str])
(:require [re-frame.core :refer [subscribe dispatch]] (:require [re-frame.core :refer [subscribe dispatch]]
[status-im.components.react :refer [view [status-im.components.react :refer [view
scroll-view scroll-view
@ -77,7 +78,7 @@
^{:key [chat-id message-id]} ^{:key [chat-id message-id]}
[request-item request])) [request-item request]))
[title (label :t/suggestions-commands)] [title (label :t/suggestions-commands)]
(for [suggestion suggestions] (for [suggestion (remove #(nil? (:title (second %))) suggestions)]
^{:key (first suggestion)} ^{:key (first suggestion)}
[suggestion-list-item suggestion])]]) [suggestion-list-item suggestion])]])

View File

@ -16,7 +16,7 @@
(let [hiccup (generate-hiccup markup)] (let [hiccup (generate-hiccup markup)]
(assoc-in db [:rendered-commands chat-id message-id] hiccup))) (assoc-in db [:rendered-commands chat-id message-id] hiccup)))
(defn command-hadler! (defn command-handler!
[_ [chat-id [_ [chat-id
{:keys [staged-command] :as parameters} {:keys [staged-command] :as parameters}
{:keys [result error]}]] {:keys [result error]}]]
@ -46,7 +46,7 @@
(let [{:keys [markup webViewUrl]} (:returned result) (let [{:keys [markup webViewUrl]} (:returned result)
hiccup (generate-hiccup markup)] hiccup (generate-hiccup markup)]
(-> db (-> db
(assoc-in [:suggestions chat-id] (generate-hiccup markup)) (assoc-in [:suggestions chat-id] hiccup)
(assoc-in [:web-view-url chat-id] webViewUrl) (assoc-in [:web-view-url chat-id] webViewUrl)
(assoc-in [:has-suggestions? chat-id] (or hiccup webViewUrl))))) (assoc-in [:has-suggestions? chat-id] (or hiccup webViewUrl)))))
@ -83,7 +83,7 @@
(reg-handler :command-handler! (reg-handler :command-handler!
(after (print-error-message! "Error on command handling")) (after (print-error-message! "Error on command handling"))
(u/side-effect! command-hadler!)) (u/side-effect! command-handler!))
(reg-handler :suggestions-handler (reg-handler :suggestions-handler
[(after #(dispatch [:animate-show-response])) [(after #(dispatch [:animate-show-response]))
@ -103,4 +103,4 @@
(reg-handler :set-local-storage (reg-handler :set-local-storage
(fn [{:keys [current-chat-id] :as db} [{:keys [data] :as event}]] (fn [{:keys [current-chat-id] :as db} [{:keys [data] :as event}]]
(log/debug "Got event: " event) (log/debug "Got event: " event)
(assoc-in db [:local-storage current-chat-id] data))) (assoc-in db [:local-storage current-chat-id] data)))

View File

@ -10,7 +10,8 @@
[status-im.constants :refer [console-chat-id wallet-chat-id]] [status-im.constants :refer [console-chat-id wallet-chat-id]]
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.utils.homoglyph :as h] [status-im.utils.homoglyph :as h]
[status-im.utils.js-resources :as js-res])) [status-im.utils.js-resources :as js-res]
[clojure.string :as str]))
(def commands-js "commands.js") (def commands-js "commands.js")
@ -79,8 +80,11 @@
(map (fn [[k v]] [k (assoc v :type as)])) (map (fn [[k v]] [k (assoc v :type as)]))
(into {}))) (into {})))
(defn filter-forbidden-names [id commands] (defn filter-forbidden-names [account id commands]
(->> commands (->> commands
(remove (fn [[_ {:keys [registered-only]}]]
(and (not (:address account))
registered-only)))
(remove (fn [[n]] (remove (fn [[n]]
(and (and
(not (= console-chat-id id)) (not (= console-chat-id id))
@ -89,8 +93,9 @@
(defn add-commands (defn add-commands
[db [id _ {:keys [commands responses autorun]}]] [db [id _ {:keys [commands responses autorun]}]]
(let [commands' (filter-forbidden-names id commands) (let [account @(subscribe [:get-current-account])
responses' (filter-forbidden-names id responses)] commands' (filter-forbidden-names account id commands)
responses' (filter-forbidden-names account id responses)]
(-> db (-> db
(assoc-in [id :commands] (mark-as :command commands')) (assoc-in [id :commands] (mark-as :command commands'))
(assoc-in [id :responses] (mark-as :response responses')) (assoc-in [id :responses] (mark-as :response responses'))

View File

@ -31,6 +31,8 @@
:no-messages "No messages" :no-messages "No messages"
:suggestions-requests "Requests" :suggestions-requests "Requests"
:suggestions-commands "Commands" :suggestions-commands "Commands"
:faucet-success "Faucet request has been received"
:faucet-error "Faucet request error"
;sync ;sync
:sync-in-progress "Syncing..." :sync-in-progress "Syncing..."
@ -162,6 +164,7 @@
:command-text-browse "Browsing webpage: {{webpage}}" :command-text-browse "Browsing webpage: {{webpage}}"
:command-text-send "Transaction: {{amount}} ETH" :command-text-send "Transaction: {{amount}} ETH"
:command-text-help "Help" :command-text-help "Help"
:command-text-faucet "Faucet: {{url}}"
;new-group ;new-group
:group-chat-name "Chat name" :group-chat-name "Chat name"