db.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. from pymongo import MongoClient, errors, DESCENDING, ASCENDING
  2. from bson.objectid import ObjectId
  3. import datetime
  4. import re
  5. import news
  6. import pytz
  7. class db():
  8. DB = "alexis"
  9. def __init__(self):
  10. self.client = MongoClient('localhost', 27017)
  11. self.c_sources = self.client[self.DB]["sources"]
  12. self.c_articles = self.client[self.DB]["articles"]
  13. def change_timezone(self, el):
  14. gmt = pytz.timezone("America/Buenos_Aires") # FIXME
  15. est = pytz.timezone('US/Eastern')
  16. fmt = '%Y-%m-%d %H:%M:%S %Z%z'
  17. el["scrap_date"] = gmt.localize(el["scrap_date"])
  18. el["scrap_date"] = el["scrap_date"].astimezone(est)
  19. el["scrap_date"] = el["scrap_date"].strftime(fmt)
  20. return el
  21. def jsonable(self, el):
  22. if el is None or "_id" not in el:
  23. return el
  24. el["_id"] = str(el["_id"])
  25. return el
  26. def filter_articles(self, filter, limit=80):
  27. db_filter = {}
  28. db_filter["matches"] = True
  29. db_filter["deleted"] = False
  30. db_filter["scrap_date"] = {}
  31. if "maxdate" in filter and len(filter["maxdate"]) > 7:
  32. db_filter["scrap_date"]["$lt"] = datetime.datetime.strptime(
  33. filter["maxdate"], "%Y-%m-%d")
  34. if "mindate" in filter and len(filter["mindate"]) > 7:
  35. db_filter["scrap_date"]["$gt"] = datetime.datetime.strptime(
  36. filter["mindate"], "%Y-%m-%d")
  37. if db_filter["scrap_date"] == {}:
  38. del db_filter["scrap_date"]
  39. if "title" in filter and filter["title"] != "":
  40. filter["title"] = filter["title"].replace(
  41. "(", "\(").replace(")", "\)")
  42. db_filter["title"] = {"$regex": ".*%s.*" %
  43. filter["title"], "$options": 'i'}
  44. if "site" in filter and filter["site"] != "":
  45. filter["site"] = filter["site"].replace(
  46. "(", "\(").replace(")", "\)")
  47. db_filter["source_name"] = {
  48. "$regex": ".*%s.*" % filter["site"], "$options": 'i'}
  49. # db_filter["$or"]=[
  50. # {"source_name": {"$regex":".*%s.*"%filter["site"], "$options": 'i'}},
  51. # {"url": {"$regex":".*%s.*"%filter["site"], "$options": 'i' }}
  52. # ]
  53. if "minweight" not in filter or not filter["minweight"].isdigit():
  54. filter["minweight"] = 1
  55. if "category" not in filter or filter["category"] == "-1":
  56. filter["category"] = -1
  57. if int(filter["category"]) >= 0:
  58. db_filter["category"] = int(filter["category"])
  59. # pass
  60. db_filter["weight"] = {"$gt": int(filter["minweight"])}
  61. if "keyword" in filter and len(filter["keyword"]) > 0:
  62. db_filter["kw"] = {"$all": filter["keyword"]}
  63. # db_filter["kw.0"]={"$exists":False}
  64. pageNumber = 0
  65. if "page" in filter:
  66. pageNumber = filter["page"]
  67. # print(db_filter)
  68. res = self.c_articles.find(db_filter, {"html": 0, "text": 0})
  69. if res is not None:
  70. toSkip = (((pageNumber - 1) * limit) if pageNumber > 0 else 0)
  71. q = res.skip(toSkip).sort("scrap_date", DESCENDING).limit(limit)
  72. count = q.count()
  73. else:
  74. q = []
  75. count = 0
  76. return {'articles': [self.jsonable(self.change_timezone(p)) for p in q],
  77. 'count': count}
  78. def article(self, id):
  79. ret = self.c_articles.find_one({"_id": ObjectId(id)})
  80. return self.jsonable(ret)
  81. def delete_article(self, artid):
  82. return self.c_articles.update({"_id": ObjectId(artid)}, {"$set": {"deleted": True}})
  83. def undelete_article(self, artid):
  84. return self.c_articles.update({"_id": ObjectId(artid)}, {"$set": {"deleted": False}})
  85. def sources(self, id=None):
  86. if id is None:
  87. return [self.jsonable(p) for p in self.c_sources.find()]
  88. ret = self.c_sources.find_one({"_id": ObjectId(id)})
  89. return self.jsonable(ret)
  90. def rss_sources(self):
  91. return [p for p in self.c_sources.find({"rss": 1})]
  92. def insert_article(self, o):
  93. try:
  94. self.c_articles.insert_one(o)
  95. return True
  96. except errors.DuplicateKeyError:
  97. print("Dup")
  98. return False
  99. def purge_error(self):
  100. self.c_articles.remove({'error': True})
  101. def article_exists(self, url):
  102. ret = self.c_articles.find_one({'lowerurl': url.lower()})
  103. if ret is None:
  104. return False
  105. return True
  106. def lower_arr(self, arr):
  107. return [a.lower() for a in arr]
  108. def to_regex(self, arr): # "ACH" | "PAYMENT" | "EBAY"
  109. return [re.compile('\\b' + w.lower() + '\\b') for w in arr]
  110. def get_keywords_list(self):
  111. kw = self.client[self.DB]["keywords"]
  112. return [k["keyword"] for k in kw.find({})]
  113. def get_keywords(self, category):
  114. kw = self.client[self.DB]["keywords"] # FIXME, split on "|" or regex
  115. ret = [{"weight": k["weight"],
  116. "kw": k["keyword"],
  117. "pattern": self.to_regex(k["keyword"].split("|"))} for k in kw.find({})] # FIXME, categories
  118. return ret
  119. def add_source(self, url, rss, selector, name, category):
  120. self.c_sources.insert({"link": url,
  121. "rss": rss,
  122. "selector": selector,
  123. "name": name,
  124. "category": category})
  125. def reparse_articles(self, articles, kw):
  126. for a in articles:
  127. # print(a)
  128. art = self.c_articles.find_one({"url": a["url"]})
  129. res = news.match_keywords(kw, art["text"])
  130. #(matches,w_sum,matching)
  131. # if(res["matches"]):
  132. print(res)
  133. self.c_articles.update({"_id": ObjectId(a["_id"])}, {"$set": res})
  134. #matches, kw, weight