Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'code-agent' of https://github.com/umarsheikh/huginn int…

…o umarsheikh-code-agent
  • Loading branch information...
commit 42c70af52a62f84920c276f5466e80ad322dbf49 2 parents a7935d1 + e86e052
@cantino authored
Showing with 116 additions and 0 deletions.
  1. +2 −0  Gemfile
  2. +6 −0 Gemfile.lock
  3. +108 −0 app/models/agents/code_agent.rb
View
2  Gemfile
@@ -37,6 +37,8 @@ gem 'twitter-stream', '>=0.1.16'
gem 'em-http-request'
gem 'weibo_2'
+gem 'therubyracer'
+
platforms :ruby_18 do
gem 'system_timer'
gem 'fastercsv'
View
6 Gemfile.lock
@@ -124,6 +124,7 @@ GEM
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kramdown (1.1.0)
+ libv8 (3.16.14.3)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
@@ -174,6 +175,7 @@ GEM
rake (10.1.0)
rdoc (3.12.2)
json (~> 1.4)
+ ref (1.0.5)
rest-client (1.6.7)
mime-types (>= 1.16)
rr (1.1.2)
@@ -224,6 +226,9 @@ GEM
system_timer (1.2.4)
term-ansicolor (1.2.2)
tins (~> 0.8)
+ therubyracer (0.12.0)
+ libv8 (~> 3.16.14.0)
+ ref
thor (0.18.1)
tilt (1.4.1)
tins (0.13.1)
@@ -300,6 +305,7 @@ DEPENDENCIES
select2-rails
shoulda-matchers
system_timer
+ therubyracer
twilio-ruby
twitter
twitter-stream (>= 0.1.16)
View
108 app/models/agents/code_agent.rb
@@ -0,0 +1,108 @@
+require 'date'
+require 'cgi'
+module Agents
+ class CodeAgent < Agent
+ #cannot_receive_events!
+ #cannot_be_scheduled!
+ description <<-MD
+ Here is an agent that gives you the ability to specify your own code. We have already provided you
+ a javascript object that has read and write access to this agent's memory, and read access to events, options and the attributes of the agent.
+ We also provide you with a method to create events on the server.
+ You will be provided with an instance of the Agent object in javascript, with access to the above data.
+ You can create events based on your own logic.
+ Specifically, you have the following class, lets say, present is a string "js_code".
+
+ function Agent(e, o, agent){
+ this.events = JSON.parse(e);
+ this.options = JSON.parse(o);
+ this.agent = JSON.parse(agent);
+ }
+ Agent.prototype.check = function(){
+ // Implement me
+ }
+ Agent.prototype.receive = function(){
+ // Implement me
+ }
+ You need to provide the code for the Agent::check and Agent::receive function. You code will override any methods already present in the Agent if it has to, and you can use other methods as well with access to the agent properties. You need to at least provide the implementation of Agent.prototype.check and Agent.prototype.receive so that it can be called periodically, or it can execute when an event happens.
+
+ We will yield control to your implementation in the following way:
+
+ context.eval(js_code); //this is the code that declares the class Agent, and provides a global create_event method.
+ context.eval("a = new Agent(events, options, agent)")
+ context.eval(options['code'])
+ If you agent fires periodically {
+ context.eval("a.check();")
+ } else if your agent responds when an event happens {
+ context.eval("a.receive();")
+ }
+
+ If your agent responds to events it receive, you need to implement the receive() method, and if you agent fires periodically, you need to implement check(). If your agent does both, please implement both!
+
+ MD
+ def example_js
+ <<-H
+ function Agent(e, o, agent){
+ this.events = JSON.parse(e);
+ this.options = JSON.parse(o);
+ this.agent = JSON.parse(agent);
+ }
+ Agent.prototype.memory = function(key,value){
+ if (typeof(key) != "undefined" && typeof(value) != "undefined") {
+ var mem = JSON.parse(access_memory(JSON.stringify(key), JSON.stringify(value)));
+ return JSON.stringify(mem);
+ } else {
+ var mem = JSON.parse(access_memory());
+ return JSON.stringify(mem);
+ }
+ }
+ Agent.prototype.check = function(){
+ }
+ Agent.prototype.receive = function(){
+ }
+ H
+ end
+
+ def working?
+ return false if recent_error_logs?
+ if options['expected_update_period_in_days'].present?
+ return false unless event_created_within?(options['expected_update_period_in_days'])
+ end
+ if options['expected_receive_period_in_days'].present?
+ return false unless last_receive_at && last_receive_at > options['expected_receive_period_in_days'].to_i.days.ago
+ end
+ true
+ end
+
+ def execute_js(incoming_events, js_function = "check")
+ js_function = (js_function == "check" ? "check" : "receive")
+ context = V8::Context.new
+ context.eval(example_js)
+ context["create_event"] = lambda {|x,y| puts x; puts y; create_event payload: JSON.parse(y)}
+ context["access_memory"] = lambda {|a, x, y| x && y ? (memory[x] = y; memory.to_json) : memory.to_json }
+
+ context.eval(options['code']) # should override the run function.
+ a, e, o = [self.attributes.to_json, incoming_events.to_json, self.options.to_json]
+ string = "a = new Agent('#{e}','#{o}','#{a}');"
+ context.eval(string)
+ runner = "a.#{js_function}();"
+ context.eval(runner)
+ end
+
+ def check
+ execute_js("")
+ end
+
+ def receive(incoming_events)
+ execute_js(incoming_events)
+ end
+
+ def default_options
+ js_code = "Agent.prototype.check = function(){ var pd = JSON.stringify({memory: this.memory(), events: this.events, options: this.options});create_event(pd); };Agent.prototype.receive = function(){ var pd = JSON.stringify({memory: this.memory(), events: this.events, options: this.options});create_event(pd); }"
+ {
+ "code" => js_code,
+ 'expected_receive_period_in_days' => "2",
+ 'expected_update_period_in_days' => "2"
+ }
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.