forked from platypush/platypush
89 lines
2.4 KiB
Python
89 lines
2.4 KiB
Python
import copy
|
|
import json
|
|
import re
|
|
import requests
|
|
import time
|
|
|
|
from frozendict import frozendict
|
|
from threading import Thread
|
|
|
|
from platypush.message.response import Response
|
|
|
|
class HttpRequest(Thread):
|
|
poll_seconds = 60
|
|
timeout = 5
|
|
bus = None
|
|
last_call_timestamp = None
|
|
|
|
|
|
class HttpRequestArguments(object):
|
|
def __init__(self, url, method='get', *args, **kwargs):
|
|
self.method = method.lower()
|
|
self.url = url
|
|
self.args = args
|
|
self.kwargs = kwargs
|
|
|
|
|
|
def __init__(self, args, poll_seconds=None, timeout=None, bus=None, **kwargs):
|
|
super().__init__()
|
|
|
|
self.poll_seconds = poll_seconds or self.poll_seconds
|
|
self.timeout = timeout or self.timeout
|
|
self.bus = bus or self.bus
|
|
|
|
if isinstance(args, self.HttpRequestArguments):
|
|
self.args = args
|
|
elif isinstance(args, dict):
|
|
self.args = self.HttpRequestArguments(**args)
|
|
else:
|
|
raise RuntimeError('{} is neither a dictionary nor an HttpRequest')
|
|
|
|
|
|
def execute(self):
|
|
self.last_call_timestamp = time.time()
|
|
|
|
method = getattr(requests, self.args.method.lower())
|
|
response = method(self.args.url, *self.args.args, **self.args.kwargs)
|
|
response.raise_for_status()
|
|
return response
|
|
|
|
|
|
class JsonHttpRequest(HttpRequest):
|
|
def __init__(self, path=None, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.path = path
|
|
self.seen_entries = set()
|
|
|
|
|
|
def execute(self):
|
|
is_first_call = self.last_call_timestamp is None
|
|
response = super().execute().json()
|
|
new_entries = []
|
|
|
|
if self.path:
|
|
m = re.match('\$\{\s*(.*)\s*\}', self.path)
|
|
response = eval(m.group(1))
|
|
|
|
for entry in response:
|
|
flattened_entry = deep_freeze(entry)
|
|
if flattened_entry not in self.seen_entries:
|
|
new_entries.append(entry)
|
|
self.seen_entries.add(flattened_entry)
|
|
|
|
return new_entries
|
|
|
|
|
|
def deep_freeze(x):
|
|
if isinstance(x, str) or not hasattr(x, "__len__") :
|
|
return x
|
|
if hasattr(x, "keys") and hasattr(x, "values") :
|
|
return frozendict({deep_freeze(k) : deep_freeze(v) for k,v in x.items()})
|
|
if hasattr(x, "__getitem__") :
|
|
return tuple(map(deep_freeze, x))
|
|
|
|
return frozenset(map(deep_freeze,x))
|
|
|
|
|
|
# vim:sw=4:ts=4:et:
|
|
|