-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathparcel.rb
More file actions
125 lines (101 loc) · 3.44 KB
/
Copy pathparcel.rb
File metadata and controls
125 lines (101 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
module Plugins
class Parcel < Base
# maps Parcel status codes to I18n keys "renders.parcel.status.{status_key}"
# (fall back to 'renders.parcel.status.unknown')
STATUS_KEYS = {
0 => 'delivered',
1 => 'frozen',
2 => 'in_transit',
3 => 'expecting_pickup',
4 => 'out_for_delivery',
5 => 'not_found',
6 => 'failed_delivery_attempt',
7 => 'delivery_exception',
8 => 'information_received'
}.freeze
def locals
result = fetch_deliveries
skip_display = skip_if_empty? && result[:error].nil? && result[:deliveries].empty?
{
deliveries: result[:deliveries].map { delivery_item(it) },
error: result[:error],
filter_mode: filter_mode.humanize,
skip_display:,
style:
}
end
private
def delivery_item(delivery)
{
title: delivery['description'],
status_key: status_key(delivery['status_code']),
latest: latest_event(delivery['events']),
delivery_by: delivery_by(delivery),
days: delivery_days(delivery)
}
end
def style = settings['style'] || 'detailed'
def api_key = settings['api_key']
def filter_mode = settings['filter_mode']
def skip_if_empty? = settings['empty_state'] == 'skip'
def headers = { 'api-key' => api_key, 'user-agent' => 'TRMNL Server' }
def query = { 'filter_mode' => filter_mode }
def url = 'https://api.parcel.app/external/deliveries/'
def cache_key = "parcel_#{api_key}"
def fetch_deliveries
# API docs: https://parcelapp.net/help/api.html
# "The rate limit is 20 requests per hour."
Rails.cache.fetch(cache_key, expires_in: 5.minutes) do
response = HTTParty.get(url, headers:, query:)
if response.success?
data = JSON.parse(response.body) # content-type is wrong (text/html), so we need to explicitly parse the body
if data['success']
{ deliveries: data['deliveries'], error: nil }
elsif data['error_message'].present?
{ deliveries: [], error: data['error_message'] }
else
{ deliveries: [], error: t('renders.parcel.errors.api') }
end
else
{ deliveries: [], error: t('renders.parcel.errors.http', code: response.code) }
end
end
rescue StandardError
{ deliveries: [], error: t('renders.parcel.errors.internal') }
end
def status_key(status_code)
STATUS_KEYS.fetch(status_code, 'unknown')
end
def user_today
user.datetime_now.to_date
end
def delivery_days(delivery)
return unless delivery['date_expected'].present?
date_expected = DateTime.parse(delivery['date_expected']).to_date
days = (date_expected - user_today).to_i
days >= 0 ? days : nil
rescue Date::Error
nil
end
def latest_event(events)
return nil if events.blank?
events.first['event']
end
def delivery_by(delivery)
delivery_days = delivery_days(delivery)
return unless delivery_days
date_expected = DateTime.parse(delivery['date_expected']).to_date
if delivery_days >= 7
l(date_expected, format: :short) # far in the future
elsif delivery_days == 1
t('renders.parcel.tomorrow') # tomorrow
elsif delivery_days.zero?
t('renders.parcel.today') # today
else
l(date_expected, format: '%A') # day of week
end
rescue Date::Error
nil
end
end
end