-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.py
137 lines (98 loc) · 2.82 KB
/
run.py
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
import os
import time
import html
import json
import asyncio
import aiohttp
from hashlib import md5
import redis
from aiotg import Bot
from bs4 import BeautifulSoup
# redis
db = redis.StrictRedis(
host=os.getenv('REDIS_HOST'),
port=os.getenv('REDIS_PORT'),
password=os.getenv('REDIS_PASS'),
decode_responses=True
)
assert db.ping()
REDIS_KEY = os.getenv('REDIS_KEY')
# telegram
bot = Bot(api_token=os.environ['TELEGRAM_TOKEN'])
canal = bot.channel(os.environ['BOT_CHANNEL'])
# config
with open('config.json') as f:
config = json.load(f)
async def enviar(avisos=[]):
if not avisos:
return
print(f"enviando {len(avisos)} avisos...")
lineas = []
for aviso in avisos:
texto = aviso.text.strip()
if aviso.a:
link = aviso.a['href']
texto = "{texto} (<a href='{link}'>link</a>)".format(
link=html.escape(link),
texto=html.escape(texto)
)
lineas.append(f"🏠 {texto}")
texto = "\n".join(lineas)
print(texto)
await canal.send_text(texto, parse_mode="HTML")
async def f5(session, url):
print(f"f5 - {url}")
avisos = []
nuevos = set()
visitados = db.zrange(REDIS_KEY, 0, -1)
async with session.get(url) as r:
content = await r.text()
dom = BeautifulSoup(content, 'html.parser')
selector = config.get('selector')
keywords = config.get('keywords')
for aviso in dom.select(selector):
txt = aviso.text.lower()
key = md5(txt.encode('utf8')).hexdigest()
if key in visitados:
continue
if not keywords or any(kw in txt for kw in keywords):
avisos.append(aviso)
nuevos.add(key)
if nuevos:
ts = time.time()
db.zadd(REDIS_KEY, **{key: ts for key in nuevos})
return avisos
async def run():
async def task(session, url):
avisos = await f5(session, url)
await enviar(avisos)
async with aiohttp.ClientSession() as session:
await asyncio.gather(*[
task(session, url)
for url in config.get('urls', [])
])
def handler(event, ctx):
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
def sync(event, ctx):
loop = asyncio.get_event_loop()
loop.run_until_complete(f5())
def clean(event, ctx):
return db.zremrangebyrank(REDIS_KEY, 0, -1000)
def delete(event, ctx):
return db.delete(REDIS_KEY)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
async def cron():
errors = 0
while errors < 5:
try:
await run()
errors = 0
except Exception as e:
print(e)
errors += 1
finally:
await asyncio.sleep(60 * 60)
loop.run_until_complete(cron())
loop.close()