source: feed2telegram/trunk/feed2telegram.py@ 4

Last change on this file since 4 was 4, checked in by cheese, 7 years ago

#1 commit prototype

File size: 4.4 KB
Line 
1#-*- coding: utf-8 -*-
2import json
3import os
4import sys
5import threading
6import traceback
7import urlparse
8
9import feedparser
10import requests
11
12class Telegram:
13 class API:
14 URL = 'https://api.telegram.org/bot<token>/<method>'
15
16 def __init__(self, token, method, http_method='POST'):
17 self.token = token
18 self.method = method
19 self.http_method = http_method.upper()
20 self.param = {}
21
22 def setParam(self, **kwargs):
23 self.param.update(kwargs)
24 return self
25
26 @property
27 def url(self):
28 ret = Telegram.API.URL.replace('<token>', self.token).replace('<method>', self.method)
29 return ret
30
31 @property
32 def header(self):
33 header = {
34 'accept': 'application/x-www-form-urlencoded',
35 'agent': ('Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
36 'AppleWebKit/537.36 (KHTML, like Gecko) '
37 'Chrome/59.0.3071.115 Safari/537.36'),
38 }
39 return header
40
41 def __init__(self, token):
42 self.token = token
43 self.chatId = self.getUpdates(limit=1)['result'][0]['message']['chat']['id']
44
45 def request(self, api):
46 if api.http_method == 'GET':
47 req = requests.get(api.url, headers=api.header, params=api.param)
48 else:# if api.http_method == 'POST':
49 req = requests.get(api.url, headers=api.header, data=api.param)
50
51 response = req.json()
52
53 if not response['ok']:
54 raise Exception(response['description'])
55
56 return response
57
58 def getUpdates(self, limit=None):
59 api = Telegram.API(token=self.token, method='getUpdates', http_method='GET')
60
61 if limit:
62 api.setParam(limit=limit)
63
64 return self.request(api)
65
66 def sendMessage(self, text):
67 api = Telegram.API(token=self.token, method='sendMessage').setParam(chat_id=self.chatId, text=text)
68 return self.request(api)
69
70class Feed:
71 def __init__(self, url):
72 self.url = url
73 self.etag = None
74 self.modified = None
75 self.feed = None
76
77 self.save_dir = '.changes'
78
79 if os.path.isfile(self.filepath):
80 self.load()
81
82 @property
83 def filepath(self):
84 domain = urlparse.urlparse(self.url).netloc
85 return os.path.join(self.save_dir, domain)
86
87 def save(self):
88 data = {
89 'url': self.url,
90 'etag': self.etag,
91 'modified': self.modified
92 }
93 jsonstr = json.dumps(data, indent=2)
94
95 if not os.path.isdir(self.save_dir):
96 os.makedirs(self.save_dir)
97
98 with open(self.filepath, 'w') as f:
99 f.write(jsonstr)
100
101 def load(self):
102 with open(self.filepath, 'r') as f:
103 jsonobj = json.load(f)
104
105 self.etag = jsonobj['etag']
106 self.modified = jsonobj['modified']
107
108 def get(self):
109 self.feed = feedparser.parse(self.url, etag=self.etag, modified=self.modified)
110
111 self.etag = self.feed.etag
112 self.modified = self.feed.modified
113
114 return self.feed
115
116class Feed2Telegram:
117 def __init__(self,
118 feed_url, # required
119 telegram_token, # required
120 callback_get_iterator, # required, method returns iterable object from dictionary parsed by feedparser, prototype: def get_iterator(feed)
121 callback_get_message, # required, method returns a message to send with an object of iterable object , prototype: def get_data(obj)
122 check_interval=60*60,
123 send_error=True,
124 continue_on_error=False,
125 threaded=False):
126 self.url = feed_url
127 self.feed = Feed(self.url)
128
129 self.token = telegram_token
130 self.telegram = Telegram(self.token)
131
132 self.get_iterator = callback_get_iterator
133 self.get_message = callback_get_message
134
135 self.send_error = send_error
136 self.continue_on_error = continue_on_error
137
138 self.thread = None
139 if threaded:
140 self.thread = threading.Thread(target=self.run)
141
142 self.stop_event = threading.Event()
143
144 def run(self):
145 while not self.stop_event.is_set():
146 try:
147 feed = self.feed.get()
148
149 for obj in self.get_iterator(feed):
150 if self.stop_event.is_set():
151 break
152
153 message = self.get_message(obj)
154 self.telegram.sendMessage(message)
155
156 else:
157 self.feed.save()
158
159 except:
160 if self.send_error:
161 e = traceback.format_exc()
162 sys.stderr.write(e)
163 self.telegram.sendMessage(e)
164
165 if not self.continue_on_error:
166 raise
167
168 finally:
169 if not self.stop_event.is_set() and self.continue_on_error:
170 self.stop_event.wait(60 * 60)
171
172 def start(self):
173 self.stop_event.clear()
174
175 if self.thread:
176 self.thread.run()
177 else:
178 self.run()
179
180 def join(self, timeout=None):
181 if self.thread:
182 self.thread.join(timeout)
183
184 def stop(self):
185 self.stop_event.set()
186
Note: See TracBrowser for help on using the repository browser.