-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ecal.js
186 lines (154 loc) · 6.2 KB
/
ecal.js
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//ECal Plugin for HomeRemote
//Coming events from ICS calendar file
//Developed by Vpow 2022
plugin.Name = "ECal";
plugin.OnChangeRequest = onChangeRequest;
plugin.OnConnect = onConnect;
plugin.OnDisconnect = onDisconnect;
plugin.OnPoll = onPoll;
plugin.OnSynchronizeDevices = onSynchronizeDevices;
plugin.PollingInterval = 43000000; //this is milliseconds, around 12h
plugin.DefaultSettings = {"URL": ""};
var http = new HTTPClient();
function onChangeRequest(device, attribute, value) {
}
function onConnect() {
}
function onDisconnect() {
}
function zeroPad(num, places) {
var zero = places - num.toString().length + 1;
return Array(+(zero > 0 && zero)).join("0") + num;
}
function onPoll() {
try {
var response = http.get(plugin.Settings["URL"], {responseType : "text"});
} catch(err) {
//other than status 200 responses end up here, since HR treats them as exceptions
console.log(err.message);
return;
}
if(typeof response != "undefined") { //200 response received
//create timestamp for current date
var dateObj = new Date();
var newdate = dateObj.getUTCFullYear() + zeroPad(dateObj.getUTCMonth() + 1, 2) + zeroPad(dateObj.getUTCDate(), 2);
var str = response.data;
var startIndex, endIndex, index, events = [];
var sdate, edate, ssum, sdes;
//simple check that it is actually calendar file
startIndex = str.indexOf("BEGIN:VCALENDAR");
if(startIndex == -1) {
return;
}
while((index = str.indexOf("BEGIN:VEVENT", startIndex)) > -1) { //find start of an event
var ii;
//find end of an event, if not found the file is not good
ii = str.indexOf("END:VEVENT", index);
if(ii != -1) {
endIndex = ii;
}
else {
return;
}
//find startdate within event
ii = str.indexOf("DTSTART", index);
if( (ii != -1) && (ii < endIndex) ) {
ii = str.indexOf(":", ii); //skip possible optional parameters
sdate = str.substr(ii+1,8);
}
else { //if start time missing go to next event
startIndex = endIndex;
continue;
}
//find enddate within event
ii = str.indexOf("DTEND", index);
if( (ii != -1) && (ii < endIndex) ) {
ii = str.indexOf(":", ii);
edate = str.substr(ii+1,8); //enddate timestamp
}
else { //if end time missing just use starttime
edate = sdate;
}
//find summary within event
ii = str.indexOf("SUMMARY", index);
if( (ii != -1) && (ii < endIndex) ) {
ii = str.indexOf(":", ii);
ssum = ii+1;
}
else { //if summary is missing then do not add event
startIndex = endIndex;
continue;
}
//find description within event
ii = str.indexOf("DESCRIPTION", index);
if( (ii != -1) && (ii < endIndex) ) {
ii = str.indexOf(":", ii);
sdes = ii+1;
}
else { //if description is missing
sdes = -1;
}
//add event if all ok
if( (sdate >= newdate) || ((sdate < newdate) && (edate >= newdate)) ) { //either event is in the future, or has started and event end is the future (multiday event)
let event = {};
event.date = sdate;
event.year = parseInt(sdate.substr(0,4));
event.month = parseInt(sdate.substr(4,2));
event.day = parseInt(sdate.substr(6,2));
event.summary = str.substring(ssum, str.indexOf("\r\n", ssum));
//unfold description
var unfold = 1;
ii = sdes;
while(unfold) {
ii = str.indexOf("\r\n", ii) + 2; //find end of CRLF
if(str.charAt(ii) != " ") { //CRLF+space is line separator, just CRLF is end of description
unfold = 0;
}
}
//remove line separators and escapes
var s = str.substring(sdes, ii);
while(s.indexOf("\r\n ") > -1) {
s = s.replace("\r\n ","");
}
while(s.indexOf("\\") > -1) {
s = s.replace("\\","");
}
//word wrap around 60 chars
s = s.replace(/(?![^\n]{1,60}$)([^\n]{1,60})\s/g, '$1\n');
event.description = s;
events.push(event);
}
startIndex = endIndex;
}
//sort events based on date
events.sort(function(a, b){return a.date - b.date});
var device = plugin.Devices[1];
//update events
for(var i=0; (i<events.length) && (i<10); i++) {
device['event'+(i+1)] = events[i].day + "." + events[i].month + ". " + events[i].summary;
}
var elist;
elist = "[";
for(var i=0; (i<events.length) && (i<500); i++) { //limit to 500 in any case
elist = elist + "{" + "event:\"" + events[i].day + "." + events[i].month + ". " + events[i].summary + "\"},";
}
elist = elist.slice(0,-1) + "]";
device.eventlist = elist;
elist = "[";
for(var i=0; (i<events.length) && (i<500); i++) { //limit to 500 in any case
elist = elist + "{" + "event:\"" + events[i].day + "." + events[i].month + ". " + events[i].summary + "\\n" + events[i].description + "\"},";
}
elist = elist.slice(0,-1) + "]";
device.longlist = elist;
}
}
function onSynchronizeDevices() {
var cal1 = new Device();
cal1.Id = "1";
cal1.DisplayName = "Event Calender 1";
cal1.Capabilities = [];
cal1.Attributes = [
"eventlist", "longlist", "event1", "event2", "event3" ,"event4", "event5", "event6", "event7", "event8", "event9", "event10"
];
plugin.Devices[cal1.Id] = cal1;
}