golestan_reporter.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import requests
  2. import configparser
  3. import cherrypy
  4. import re
  5. import lmdb
  6. import pickle
  7. import smtplib
  8. import ssl
  9. import threading
  10. import chevron
  11. from email.mime.multipart import MIMEMultipart
  12. from email.mime.text import MIMEText
  13. from bs4 import BeautifulSoup
  14. from logger import Logger
  15. from main import siged_in, auth
  16. T = 'GR'
  17. class GolestanReporter(threading.Thread):
  18. def __init__(self, env:lmdb.Environment, users_db, config: configparser.SectionProxy, logger:Logger, templates):
  19. super.__init__()
  20. self.templates = templates
  21. self.cfg = config
  22. self.env = env
  23. self.usersDB = users_db
  24. self.l = logger
  25. self.last_news = None
  26. self.__locker=threading.Lock()
  27. last_news_file_dir = self.cfg.get('last_news_file', 'last news.dat')
  28. with open(last_news_file_dir, 'rb') as lnfile:
  29. self.last_news = pickle.load(lnfile)
  30. self.check_thread:threading.Timer = None
  31. def get_user_data(self, user, key = None):
  32. self.l.d(f'getting user({user}) info',T)
  33. try:
  34. with self.env.begin(self.usersDB) as txn:
  35. data = txn.get(user.enconde())
  36. user_info = pickle.loads(data)
  37. if key:
  38. return user_info[key]
  39. return user_info
  40. except Exception as e:
  41. self.l.e('error on getting user info',T)
  42. self.l.d(f'{type(e)}: {e}',T)
  43. def check_and_mail(self, timer=0):
  44. n = self.get_last_news()
  45. if n is not None and n != self.last_news:
  46. # TADA! new news!
  47. self.l.i('new news. prepairing to send emails...')
  48. context = ssl.create_default_context()
  49. # Try to log in to server and send email
  50. try:
  51. server = smtplib.SMTP(
  52. self.cfg['smtp_server'], int(self.cfg['smtp_port']))
  53. server.ehlo() # Can be omitted
  54. server.starttls(context=context) # Secure the connection
  55. server.ehlo() # Can be omitted
  56. server.login(
  57. self.cfg['sender_email'], self.cfg['email_password'])
  58. msg = MIMEMultipart('alternative')
  59. msg['From'] = self.cfg.get(
  60. 'sender_name', 'Golestan reporter')
  61. msg['Subject'] = n['title']
  62. msg.attach(MIMEText(n['body'], 'html'))
  63. with self.usersDB.begin() as txn:
  64. for user, info in txn.cursor:
  65. info = pickle.loads(info)
  66. if info.email != '' and not info['golestan_reporter.mute']:
  67. self.l.d(f"sending mail to user({info['uni_code']}): {info['email']}", T)
  68. msg['To'] = info['email']
  69. server.sendmail(
  70. self.cfg['sender_email'], msg['To'], msg.as_string())
  71. except Exception as e:
  72. self.l.e('cannot do check & mail',T)
  73. self.l.d(f'{type(e)}: {e}, n: {n}',T)
  74. finally:
  75. server.quit()
  76. self.check_thread = threading.Timer(
  77. timer, self.check_and_mail, (timer,))
  78. def run(self):
  79. self.check_and_mail(self.cfg.getint('check_interval', 100))
  80. self.__locker.acquire()
  81. def join(self):
  82. self.__locker.acquire()
  83. self.__locker.release()
  84. def stop(self):
  85. self.l.i('thread is stoping...',T)
  86. try:
  87. self.check_thread.cancel()
  88. self.check_thread.join()
  89. except:
  90. pass
  91. finally:
  92. self.__locker.release()
  93. class GolestanReporterRoot:
  94. def __init__(self, env:lmdb.Environment, users_db, config: configparser.SectionProxy, logger:Logger):
  95. self.cfg = config
  96. self.env = env
  97. self.usersDB = users_db
  98. self.l = logger
  99. self.mountpoint = '/cp/services/golestan_reporter'
  100. @cherrypy.tools.auth('all')
  101. def index(self):
  102. pass
  103. def do(self, q):
  104. """do an action"""
  105. pass