@@ -25,9 +25,14 @@ module Agents |
||
| 25 | 25 |
|
| 26 | 26 |
"instructions": {
|
| 27 | 27 |
"message": "Today's conditions look like {{conditions}} with a high temperature of {{high.celsius}} degrees Celsius.",
|
| 28 |
- "subject": "{{data}}"
|
|
| 28 |
+ "subject": "{{data}}",
|
|
| 29 |
+ "created_at": "{{created_at}}"
|
|
| 29 | 30 |
} |
| 30 | 31 |
|
| 32 |
+ Names here like `conditions`, `high` and `data` refer to the corresponding values in the Event hash. |
|
| 33 |
+ |
|
| 34 |
+ The special key `created_at` refers to the timestamp of the Event, which can be reformatted by the `date` filter, like `{{created_at | date:"at %I:%M %p" }}`.
|
|
| 35 |
+ |
|
| 31 | 36 |
The upstream agent of each received event is accessible via the key `agent`, which has the following attributes: #{''.tap { |s| s << AgentDrop.instance_methods(false).map { |m| "`#{m}`" }.join(', ') }}.
|
| 32 | 37 |
|
| 33 | 38 |
Have a look at the [Wiki](https://github.com/cantino/huginn/wiki/Formatting-Events-using-Liquid) to learn more about liquid templating. |
@@ -68,8 +73,6 @@ module Agents |
||
| 68 | 73 |
|
| 69 | 74 |
If you want to retain original contents of events and only add new keys, then set `mode` to `merge`, otherwise set it to `clean`. |
| 70 | 75 |
|
| 71 |
- By default, the output event will have a `created_at` field added as well, reflecting the original Event creation time. You can skip this output by setting `skip_created_at` to `true`. |
|
| 72 |
- |
|
| 73 | 76 |
To CGI escape output (for example when creating a link), use the Liquid `uri_escape` filter, like so: |
| 74 | 77 |
|
| 75 | 78 |
{
|
@@ -82,7 +85,7 @@ module Agents |
||
| 82 | 85 |
after_save :clear_matchers |
| 83 | 86 |
|
| 84 | 87 |
def validate_options |
| 85 |
- errors.add(:base, "instructions, mode, and skip_created_at all need to be present.") unless options['instructions'].present? && options['mode'].present? && options['skip_created_at'].present? |
|
| 88 |
+ errors.add(:base, "instructions and mode need to be present.") unless options['instructions'].present? && options['mode'].present? |
|
| 86 | 89 |
|
| 87 | 90 |
validate_matchers |
| 88 | 91 |
end |
@@ -92,11 +95,11 @@ module Agents |
||
| 92 | 95 |
'instructions' => {
|
| 93 | 96 |
'message' => "You received a text {{text}} from {{fields.from}}",
|
| 94 | 97 |
'agent' => "{{agent.type}}",
|
| 95 |
- 'some_other_field' => "Looks like the weather is going to be {{fields.weather}}"
|
|
| 98 |
+ 'some_other_field' => "Looks like the weather is going to be {{fields.weather}}",
|
|
| 99 |
+ 'created_at' => "{{created_at}}"
|
|
| 96 | 100 |
}, |
| 97 | 101 |
'matchers' => [], |
| 98 | 102 |
'mode' => "clean", |
| 99 |
- 'skip_created_at' => "false" |
|
| 100 | 103 |
} |
| 101 | 104 |
end |
| 102 | 105 |
|
@@ -110,7 +113,6 @@ module Agents |
||
| 110 | 113 |
opts = interpolated(event.to_liquid(payload)) |
| 111 | 114 |
formatted_event = opts['mode'].to_s == "merge" ? event.payload.dup : {}
|
| 112 | 115 |
formatted_event.merge! opts['instructions'] |
| 113 |
- formatted_event['created_at'] = event.created_at unless opts['skip_created_at'].to_s == "true" |
|
| 114 | 116 |
create_event :payload => formatted_event |
| 115 | 117 |
end |
| 116 | 118 |
end |
@@ -56,6 +56,8 @@ class EventDrop |
||
| 56 | 56 |
case key |
| 57 | 57 |
when 'agent' |
| 58 | 58 |
@object.agent |
| 59 |
+ when 'created_at' |
|
| 60 |
+ @object.created_at |
|
| 59 | 61 |
end |
| 60 | 62 |
end |
| 61 | 63 |
end |
@@ -0,0 +1,21 @@ |
||
| 1 |
+class ConvertEfaSkipCreatedAt < ActiveRecord::Migration |
|
| 2 |
+ def up |
|
| 3 |
+ Agent.where(type: 'Agents::EventFormattingAgent').each do |agent| |
|
| 4 |
+ agent.options_will_change! |
|
| 5 |
+ unless agent.options.delete('skip_created_at').to_s == 'true'
|
|
| 6 |
+ agent.options['instructions'] = {
|
|
| 7 |
+ 'created_at' => '{{created_at}}'
|
|
| 8 |
+ }.update(agent.options['instructions'] || {})
|
|
| 9 |
+ end |
|
| 10 |
+ agent.save! |
|
| 11 |
+ end |
|
| 12 |
+ end |
|
| 13 |
+ |
|
| 14 |
+ def down |
|
| 15 |
+ Agent.where(type: 'Agents::EventFormattingAgent').each do |agent| |
|
| 16 |
+ agent.options_will_change! |
|
| 17 |
+ agent.options['skip_created_at'] = (agent.options['instructions'] || {})['created_at'] == '{{created_at}}'
|
|
| 18 |
+ agent.save! |
|
| 19 |
+ end |
|
| 20 |
+ end |
|
| 21 |
+end |
@@ -9,6 +9,8 @@ describe Agents::EventFormattingAgent do |
||
| 9 | 9 |
:message => "Received {{content.text}} from {{content.name}} .",
|
| 10 | 10 |
:subject => "Weather looks like {{conditions}} according to the forecast at {{pretty_date.time}}",
|
| 11 | 11 |
:agent => "{{agent.type}}",
|
| 12 |
+ :created_at => "{{created_at}}",
|
|
| 13 |
+ :created_at_iso => "{{created_at | date:'%FT%T%:z'}}",
|
|
| 12 | 14 |
}, |
| 13 | 15 |
:mode => "clean", |
| 14 | 16 |
:matchers => [ |
@@ -18,7 +20,6 @@ describe Agents::EventFormattingAgent do |
||
| 18 | 20 |
:to => "pretty_date", |
| 19 | 21 |
}, |
| 20 | 22 |
], |
| 21 |
- :skip_created_at => "false" |
|
| 22 | 23 |
} |
| 23 | 24 |
} |
| 24 | 25 |
@checker = Agents::EventFormattingAgent.new(@valid_params) |
@@ -53,18 +54,12 @@ describe Agents::EventFormattingAgent do |
||
| 53 | 54 |
Event.last.payload[:content].should_not == nil |
| 54 | 55 |
end |
| 55 | 56 |
|
| 56 |
- it "should accept skip_created_at" do |
|
| 57 |
- @checker.receive([@event]) |
|
| 58 |
- Event.last.payload[:created_at].should_not == nil |
|
| 59 |
- @checker.options[:skip_created_at] = "true" |
|
| 60 |
- @checker.receive([@event]) |
|
| 61 |
- Event.last.payload[:created_at].should == nil |
|
| 62 |
- end |
|
| 63 |
- |
|
| 64 | 57 |
it "should handle Liquid templating in instructions" do |
| 65 | 58 |
@checker.receive([@event]) |
| 66 | 59 |
Event.last.payload[:message].should == "Received Some Lorem Ipsum from somevalue ." |
| 67 | 60 |
Event.last.payload[:agent].should == "WeatherAgent" |
| 61 |
+ Event.last.payload[:created_at].should == @event.created_at.to_s |
|
| 62 |
+ Event.last.payload[:created_at_iso].should == @event.created_at.iso8601 |
|
| 68 | 63 |
end |
| 69 | 64 |
|
| 70 | 65 |
it "should handle matchers and Liquid templating in instructions" do |
@@ -144,10 +139,5 @@ describe Agents::EventFormattingAgent do |
||
| 144 | 139 |
@checker.options[:mode] = "" |
| 145 | 140 |
@checker.should_not be_valid |
| 146 | 141 |
end |
| 147 |
- |
|
| 148 |
- it "should validate presence of skip_created_at" do |
|
| 149 |
- @checker.options[:skip_created_at] = "" |
|
| 150 |
- @checker.should_not be_valid |
|
| 151 |
- end |
|
| 152 | 142 |
end |
| 153 | 143 |
end |
@@ -85,6 +85,7 @@ describe EventDrop do |
||
| 85 | 85 |
before do |
| 86 | 86 |
@event = Event.new |
| 87 | 87 |
@event.agent = agents(:jane_weather_agent) |
| 88 |
+ @event.created_at = Time.at(1400000000) |
|
| 88 | 89 |
@event.payload = {
|
| 89 | 90 |
'title' => 'some title', |
| 90 | 91 |
'url' => 'http://some.site.example.org/', |
@@ -111,4 +112,9 @@ describe EventDrop do |
||
| 111 | 112 |
t = '{{agent.name}}'
|
| 112 | 113 |
interpolate(t, @event).should eq('SF Weather')
|
| 113 | 114 |
end |
| 115 |
+ |
|
| 116 |
+ it 'should have created_at' do |
|
| 117 |
+ t = '{{created_at | date:"%FT%T%z" }}'
|
|
| 118 |
+ interpolate(t, @event).should eq('2014-05-13T09:53:20-0700')
|
|
| 119 |
+ end |
|
| 114 | 120 |
end |