From 1c11ab72addad213d4f5a4e3e546d0e6e2334cde Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 16:28:58 +0330 Subject: [PATCH 01/77] fresh product changes --- say/api/need_api.py | 10 ++++++++-- say/crawler/__init__.py | 22 ++++++++++++---------- say/models/need_model.py | 4 ++-- say/tasks/update_needs.py | 4 ++-- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index 0c9ffeb4..83fefc25 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -334,7 +334,10 @@ def patch(self, need_id): need.link = new_link session.flush() - update_need.delay(need.id, force=True) + if "Protein" in self.name_translations.en | "Dairy" in self.name_translations.en: + update_need.delay(need.id, True) + else: + update_need.delay(need.id, False) if 'affiliateLinkUrl' in request.form.keys(): need.affiliateLinkUrl = request.form['affiliateLinkUrl'] @@ -691,8 +694,11 @@ def post(self): if new_need.link: from say.tasks import update_need + if "Protein" in name_translations.en | "Dairy" in name_translations.en: + update_need.delay(new_need.id, True) + else: + update_need.delay(new_need.id, False) - update_need.delay(new_need.id) return new_need diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 0840c386..25fa7626 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -115,24 +115,26 @@ def __init__(self, url): except IndexError: self.dkp = None - def get_data(self, force=False): + def get_data(self, fresh, force=False): if self.dkp is None: return - - url = self.API_URL_NOT_FRESH % self.dkp - if force: - r = requests.get(url) - else: - r = request_with_cache(url) + - if r.status_code != 200: - # fresh products have different api + # fresh products have different api + if fresh: + url = self.API_URL_NOT_FRESH % self.dkp + if force: + r = requests.get(url) + else: + r = request_with_cache(url) + if r.status_code != 200: + return + else: url = self.API_URL_FRESH % self.dkp if force: r = requests.get(url) else: r = request_with_cache(url) - if r.status_code != 200: return diff --git a/say/models/need_model.py b/say/models/need_model.py index 88b6a04b..c469339a 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -442,12 +442,12 @@ def current_participants(self): paid=past_participation.paid, ) - def update(self, force=False): + def update(self, fresh, force=False): from say.crawler import Crawler from say.crawler import DigikalaCrawler if 'digikala' in self.link: - data = DigikalaCrawler(self.link).get_data(force=force) + data = DigikalaCrawler(self.link).get_data(fresh, force=force) else: data = Crawler(self.link).get_data(force=force) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 03eb8ea8..fb7dc229 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -36,12 +36,12 @@ def update_needs(self): retry_kwargs={'max_retries': 1}, queue='slow', ) -def update_need(self, need_id, force=False): +def update_need(self, need_id, fresh, force=False): from say.models.need_model import Need sleep(5) need = self.session.query(Need).get(need_id) - data = need.update(force=force) + data = need.update(fresh, force=force) safe_commit(self.session) return data From 728c79c08cee2c61549fd47a73eb268dd7369177 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 16:32:47 +0330 Subject: [PATCH 02/77] fresh product changes --- say/crawler/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 25fa7626..7dfb733c 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -118,10 +118,9 @@ def __init__(self, url): def get_data(self, fresh, force=False): if self.dkp is None: return - # fresh products have different api - if fresh: + if fresh == False: url = self.API_URL_NOT_FRESH % self.dkp if force: r = requests.get(url) From ba1f1ed393eea1ae88f1eece52da1bf739fc0e09 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 17:30:38 +0330 Subject: [PATCH 03/77] fresh product changes --- say/api/need_api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index 83fefc25..e138f0bb 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -334,9 +334,11 @@ def patch(self, need_id): need.link = new_link session.flush() - if "Protein" in self.name_translations.en | "Dairy" in self.name_translations.en: + if "Protein" in need.name_translations['en'] | "Dairy" in need.name_translations['en']: + print("Fresh Products") update_need.delay(need.id, True) else: + print("Not Fresh Products") update_need.delay(need.id, False) if 'affiliateLinkUrl' in request.form.keys(): From cd80f172d68811575d860dee3e901cc3ccd1862e Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 18:01:09 +0330 Subject: [PATCH 04/77] fresh product changes --- say/api/need_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index e138f0bb..d2c0ec2d 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -696,7 +696,7 @@ def post(self): if new_need.link: from say.tasks import update_need - if "Protein" in name_translations.en | "Dairy" in name_translations.en: + if "Protein" in name_translations['en'] | "Dairy" in name_translations['en']: update_need.delay(new_need.id, True) else: update_need.delay(new_need.id, False) From f2eba4c68b08d290ab916d2ee6365693ec7bc119 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 18:11:33 +0330 Subject: [PATCH 05/77] fresh product changes --- say/api/need_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index d2c0ec2d..42062088 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -334,7 +334,7 @@ def patch(self, need_id): need.link = new_link session.flush() - if "Protein" in need.name_translations['en'] | "Dairy" in need.name_translations['en']: + if "Protein" in need.name_translations['en'] or "Dairy" in need.name_translations['en']: print("Fresh Products") update_need.delay(need.id, True) else: @@ -696,7 +696,7 @@ def post(self): if new_need.link: from say.tasks import update_need - if "Protein" in name_translations['en'] | "Dairy" in name_translations['en']: + if "Protein" in name_translations['en'] or "Dairy" in name_translations['en']: update_need.delay(new_need.id, True) else: update_need.delay(new_need.id, False) From 4e55efff7ef40d72de02480da8d18448a89a06be Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 18:32:34 +0330 Subject: [PATCH 06/77] celeray task --- say/tasks/update_needs.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index fb7dc229..e8d4f7a0 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -23,7 +23,12 @@ def update_needs(self): t = [] for need in needs: t.append(need.id) - update_need.delay(need.id) + if "Protein" in need.name_translations['en'] or "Dairy" in need.name_translations['en']: + print("Fresh Products") + update_need.delay(need.id, True) + else: + print("Not Fresh Products") + update_need.delay(need.id, False) return t From 069178fc8f8ad18aa961a16fffefaf16a5341c8e Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 18:49:12 +0330 Subject: [PATCH 07/77] celeray task --- say/tasks/update_needs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index e8d4f7a0..06b2a48c 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -13,7 +13,7 @@ def update_needs(self): needs = self.session.query(Need).filter( Need.type == 1, or_( - Need.status < 4, + # Need.status < 4, since digikala fresh api was not implemented many done needs could be missing tile Need.title.is_(None), ), Need.isDeleted.is_(False), From ed79626531ab01ec012df53909687300a19b153d Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 18:49:48 +0330 Subject: [PATCH 08/77] celeray task --- say/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/celery.py b/say/celery.py index 20e5330e..ecf50689 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=30, hour='0,4,8,12,16,20'), + 'schedule': crontab(minute=30, hour='0,4,8,12,16,19'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', From 1706c345f286c38d7dfe6cbc34db5faee75c2292 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 18:59:08 +0330 Subject: [PATCH 09/77] celeray task --- say/tasks/update_needs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 06b2a48c..e8d4f7a0 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -13,7 +13,7 @@ def update_needs(self): needs = self.session.query(Need).filter( Need.type == 1, or_( - # Need.status < 4, since digikala fresh api was not implemented many done needs could be missing tile + Need.status < 4, Need.title.is_(None), ), Need.isDeleted.is_(False), From d1705a360ed33d8b1bb281e9d91804670e308439 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 19:25:04 +0330 Subject: [PATCH 10/77] celeray task --- say/api/need_api.py | 13 +++---------- say/celery.py | 2 +- say/tasks/update_needs.py | 16 +++++++++------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index 42062088..71ea8aec 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -334,12 +334,8 @@ def patch(self, need_id): need.link = new_link session.flush() - if "Protein" in need.name_translations['en'] or "Dairy" in need.name_translations['en']: - print("Fresh Products") - update_need.delay(need.id, True) - else: - print("Not Fresh Products") - update_need.delay(need.id, False) + update_need.delay(need.id) + if 'affiliateLinkUrl' in request.form.keys(): need.affiliateLinkUrl = request.form['affiliateLinkUrl'] @@ -696,10 +692,7 @@ def post(self): if new_need.link: from say.tasks import update_need - if "Protein" in name_translations['en'] or "Dairy" in name_translations['en']: - update_need.delay(new_need.id, True) - else: - update_need.delay(new_need.id, False) + update_need.delay(new_need.id) return new_need diff --git a/say/celery.py b/say/celery.py index ecf50689..590c2f8b 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=30, hour='0,4,8,12,16,19'), + 'schedule': crontab(minute=00, hour='0,4,8,12,16,20'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index e8d4f7a0..5a832061 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -23,12 +23,7 @@ def update_needs(self): t = [] for need in needs: t.append(need.id) - if "Protein" in need.name_translations['en'] or "Dairy" in need.name_translations['en']: - print("Fresh Products") - update_need.delay(need.id, True) - else: - print("Not Fresh Products") - update_need.delay(need.id, False) + update_need.delay(need.id) return t @@ -41,11 +36,18 @@ def update_needs(self): retry_kwargs={'max_retries': 1}, queue='slow', ) -def update_need(self, need_id, fresh, force=False): +def update_need(self, need_id, force=False): from say.models.need_model import Need sleep(5) need = self.session.query(Need).get(need_id) + if "fresh" in need.link: + fresh= True + print("Fresh Product: ", need.id) + else: + fresh= False + print("Not Fresh Product: ", need.id) + data = need.update(fresh, force=force) safe_commit(self.session) From 54f8a715a910d269851bb471508c673e7de158dc Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 19:30:24 +0330 Subject: [PATCH 11/77] celeray task --- say/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/celery.py b/say/celery.py index 590c2f8b..1f0ef62c 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=00, hour='0,4,8,12,16,20'), + 'schedule': crontab(minute=15, hour='0,4,8,12,16,20'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', From a03ad60217c56beaab8887ebb3311f043aa4a055 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 19:53:32 +0330 Subject: [PATCH 12/77] celeray task --- say/api/need_api.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index 71ea8aec..ffd7fb28 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -329,13 +329,12 @@ def patch(self, need_id): if 'link' in request.form.keys(): new_link = request.form['link'] - if new_link != need.link: - from say.tasks import update_need + from say.tasks import update_need - need.link = new_link - session.flush() - update_need.delay(need.id) - + need.link = new_link + session.flush() + update_need.delay(need.id) + if 'affiliateLinkUrl' in request.form.keys(): need.affiliateLinkUrl = request.form['affiliateLinkUrl'] From 8f0d8125bd8d2d683fe7192e9db1339dc7a51d54 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 20:04:52 +0330 Subject: [PATCH 13/77] celeray task --- say/crawler/__init__.py | 17 +++++++---------- say/models/need_model.py | 4 ++-- say/tasks/update_needs.py | 11 ++--------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 7dfb733c..6d783454 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -115,20 +115,17 @@ def __init__(self, url): except IndexError: self.dkp = None - def get_data(self, fresh, force=False): + def get_data(self, force=False): if self.dkp is None: return - # fresh products have different api - if fresh == False: - url = self.API_URL_NOT_FRESH % self.dkp - if force: - r = requests.get(url) - else: - r = request_with_cache(url) - if r.status_code != 200: - return + # fresh products have different api / Digikala redirect to new link for fresh product + url = self.API_URL_NOT_FRESH % self.dkp + if force: + r = requests.get(url) else: + r = request_with_cache(url) + if r.status_code != 200: url = self.API_URL_FRESH % self.dkp if force: r = requests.get(url) diff --git a/say/models/need_model.py b/say/models/need_model.py index c469339a..88b6a04b 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -442,12 +442,12 @@ def current_participants(self): paid=past_participation.paid, ) - def update(self, fresh, force=False): + def update(self, force=False): from say.crawler import Crawler from say.crawler import DigikalaCrawler if 'digikala' in self.link: - data = DigikalaCrawler(self.link).get_data(fresh, force=force) + data = DigikalaCrawler(self.link).get_data(force=force) else: data = Crawler(self.link).get_data(force=force) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 5a832061..06817c21 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -40,15 +40,8 @@ def update_need(self, need_id, force=False): from say.models.need_model import Need sleep(5) - need = self.session.query(Need).get(need_id) - if "fresh" in need.link: - fresh= True - print("Fresh Product: ", need.id) - else: - fresh= False - print("Not Fresh Product: ", need.id) - - data = need.update(fresh, force=force) + need = self.session.query(Need).get(need_id) + data = need.update(force=force) safe_commit(self.session) return data From 1840d49046fb92d2073839c4910450f1909e3236 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 20:45:54 +0330 Subject: [PATCH 14/77] celeray task --- say/crawler/__init__.py | 20 ++++++++++++-------- say/models/need_model.py | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 6d783454..eec5cedf 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -115,7 +115,7 @@ def __init__(self, url): except IndexError: self.dkp = None - def get_data(self, force=False): + def get_data(self, need_id, force=False): if self.dkp is None: return @@ -126,13 +126,17 @@ def get_data(self, force=False): else: r = request_with_cache(url) if r.status_code != 200: - url = self.API_URL_FRESH % self.dkp - if force: - r = requests.get(url) - else: - r = request_with_cache(url) - if r.status_code != 200: - return + if r.status_code == 302 and "fresh" in r["redirect_url"]["uri"]: + print("Checking if fresh product...") + url = self.API_URL_FRESH % self.dkp + if force: + r = requests.get(url) + else: + r = request_with_cache(url) + if r.status_code != 200: + print("Could not call the digikala api", need_id ) + return + print(url) data = r.json()['data'] diff --git a/say/models/need_model.py b/say/models/need_model.py index 88b6a04b..fe3b62c1 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -447,7 +447,7 @@ def update(self, force=False): from say.crawler import DigikalaCrawler if 'digikala' in self.link: - data = DigikalaCrawler(self.link).get_data(force=force) + data = DigikalaCrawler(self.link).get_data(self.id, force=force) else: data = Crawler(self.link).get_data(force=force) From 6cc3a8b93e741036b8fd7852c829666a31f00c17 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 20:59:13 +0330 Subject: [PATCH 15/77] celeray task --- say/crawler/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index eec5cedf..a92c4690 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -126,6 +126,7 @@ def get_data(self, need_id, force=False): else: r = request_with_cache(url) if r.status_code != 200: + print(r) if r.status_code == 302 and "fresh" in r["redirect_url"]["uri"]: print("Checking if fresh product...") url = self.API_URL_FRESH % self.dkp From 560895a06b6713239989e7d9001e4bbb033a9fc4 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 21:30:34 +0330 Subject: [PATCH 16/77] celeray task --- say/api/need_api.py | 2 +- say/models/need_model.py | 4 ++-- say/tasks/update_needs.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index ffd7fb28..144c354e 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -330,7 +330,7 @@ def patch(self, need_id): if 'link' in request.form.keys(): new_link = request.form['link'] from say.tasks import update_need - + print("updating link...") need.link = new_link session.flush() update_need.delay(need.id) diff --git a/say/models/need_model.py b/say/models/need_model.py index fe3b62c1..a6d4ee83 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -442,12 +442,12 @@ def current_participants(self): paid=past_participation.paid, ) - def update(self, force=False): + def update(self,need_id, force=False): from say.crawler import Crawler from say.crawler import DigikalaCrawler if 'digikala' in self.link: - data = DigikalaCrawler(self.link).get_data(self.id, force=force) + data = DigikalaCrawler(self.link).get_data(need_id, force=force) else: data = Crawler(self.link).get_data(force=force) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 06817c21..3e41dc6b 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -41,7 +41,7 @@ def update_need(self, need_id, force=False): sleep(5) need = self.session.query(Need).get(need_id) - data = need.update(force=force) + data = need.update(need_id, force=force) safe_commit(self.session) return data From 6367f737c96578fd6aa57909a2d6f679bf440f29 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 22:56:29 +0330 Subject: [PATCH 17/77] celeray task --- say/crawler/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index a92c4690..dcc0c33a 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -125,18 +125,20 @@ def get_data(self, need_id, force=False): r = requests.get(url) else: r = request_with_cache(url) - if r.status_code != 200: + if r.status != 200: print(r) - if r.status_code == 302 and "fresh" in r["redirect_url"]["uri"]: + if r.status == 302 and "fresh" in r["redirect_url"]["uri"]: print("Checking if fresh product...") url = self.API_URL_FRESH % self.dkp if force: r = requests.get(url) else: r = request_with_cache(url) - if r.status_code != 200: + if r.status != 200: print("Could not call the digikala api", need_id ) return + else: + return print(url) data = r.json()['data'] From 39da9e25bf073f73c716e423ea29c15da0bea005 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 23:07:52 +0330 Subject: [PATCH 18/77] celeray task --- say/crawler/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index dcc0c33a..d7a38425 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -125,16 +125,16 @@ def get_data(self, need_id, force=False): r = requests.get(url) else: r = request_with_cache(url) - if r.status != 200: + if r.status_code != 200: print(r) - if r.status == 302 and "fresh" in r["redirect_url"]["uri"]: + if r.status_code == 302: print("Checking if fresh product...") url = self.API_URL_FRESH % self.dkp if force: r = requests.get(url) else: r = request_with_cache(url) - if r.status != 200: + if r.status_code != 200: print("Could not call the digikala api", need_id ) return else: From b7ed25aeb9d73b785b0101460e3e49c5ec4f43b8 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 23:40:53 +0330 Subject: [PATCH 19/77] celeray task --- say/crawler/__init__.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index d7a38425..204ed871 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -119,29 +119,29 @@ def get_data(self, need_id, force=False): if self.dkp is None: return - # fresh products have different api / Digikala redirect to new link for fresh product url = self.API_URL_NOT_FRESH % self.dkp if force: r = requests.get(url) else: r = request_with_cache(url) if r.status_code != 200: - print(r) - if r.status_code == 302: - print("Checking if fresh product...") - url = self.API_URL_FRESH % self.dkp - if force: - r = requests.get(url) - else: - r = request_with_cache(url) - if r.status_code != 200: - print("Could not call the digikala api", need_id ) - return + return + + # fresh products have different api / Digikala redirect to new link for fresh product + # Typical respond: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} + result = r.json + if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: + url = self.API_URL_FRESH % self.dkp + if force: + r = requests.get(url) else: + r = request_with_cache(url) + if r.status_code != 200: return - print(url) + else: + return - data = r.json()['data'] + data = result['data'] if data['product'].get('is_inactive'): return dict(cost='unavailable', img=None, title=None) From 2438de0c2e8134dd421069e70b0c279114e7be5a Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 15 Sep 2024 23:57:34 +0330 Subject: [PATCH 20/77] celeray task --- say/crawler/__init__.py | 3 ++- say/models/need_model.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 204ed871..96c54918 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -130,7 +130,8 @@ def get_data(self, need_id, force=False): # fresh products have different api / Digikala redirect to new link for fresh product # Typical respond: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} result = r.json - if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: + print(result) + if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: url = self.API_URL_FRESH % self.dkp if force: r = requests.get(url) diff --git a/say/models/need_model.py b/say/models/need_model.py index a6d4ee83..8298910f 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -447,6 +447,7 @@ def update(self,need_id, force=False): from say.crawler import DigikalaCrawler if 'digikala' in self.link: + print("updating via crawler.....") data = DigikalaCrawler(self.link).get_data(need_id, force=force) else: data = Crawler(self.link).get_data(force=force) From 83617e62bf60ffc56890cfc0b6a28d391b17550e Mon Sep 17 00:00:00 2001 From: ehsang Date: Mon, 16 Sep 2024 00:14:57 +0330 Subject: [PATCH 21/77] celeray task --- say/crawler/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 96c54918..6532fb56 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -139,8 +139,7 @@ def get_data(self, need_id, force=False): r = request_with_cache(url) if r.status_code != 200: return - else: - return + data = result['data'] From 4fdeef6b5003e1978f1688d055861fca370c4969 Mon Sep 17 00:00:00 2001 From: ehsang Date: Mon, 16 Sep 2024 00:15:57 +0330 Subject: [PATCH 22/77] celeray task --- say/crawler/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 6532fb56..aa06e50c 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -129,7 +129,7 @@ def get_data(self, need_id, force=False): # fresh products have different api / Digikala redirect to new link for fresh product # Typical respond: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} - result = r.json + result = r.json() print(result) if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: url = self.API_URL_FRESH % self.dkp From e8ae8bae061326199cd11b93d8cfe481193cd552 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 21 Sep 2024 18:06:34 +0330 Subject: [PATCH 23/77] fresh product changes --- say/crawler/__init__.py | 5 +- ...\330\255.\330\252\330\263\330\256\330\257" | 454 ++++++++++++++++++ 2 files changed, 456 insertions(+), 3 deletions(-) create mode 100644 "\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index aa06e50c..95dc077b 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -128,9 +128,8 @@ def get_data(self, need_id, force=False): return # fresh products have different api / Digikala redirect to new link for fresh product - # Typical respond: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} + # Typical response: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} result = r.json() - print(result) if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: url = self.API_URL_FRESH % self.dkp if force: @@ -139,7 +138,7 @@ def get_data(self, need_id, force=False): r = request_with_cache(url) if r.status_code != 200: return - + result = r.json() data = result['data'] diff --git "a/\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" "b/\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" new file mode 100644 index 00000000..1efeca71 --- /dev/null +++ "b/\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" @@ -0,0 +1,454 @@ +{ + "status": 200, + "data": { + "product": { + "id": 792148, + "title_fa": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "title_en": "Mahya Protein Chicken Barbecue Drumstick - 0.9 Kg", + "url": { + "uri": "/product/dkp-792148/جوجه-کباب-ران-مرغ-مهیا-پروتئین-09-کیلوگرم" + }, + "status": "out_of_stock", + "has_quick_view": false, + "data_layer": { + "brand": "مهیا پروتئین", + "category": "[FF,گوشت مرغ]", + "metric6": 2173, + "dimension2": 0, + "dimension6": 0, + "dimension7": "none", + "dimension9": 4.3, + "dimension11": 0, + "dimension20": "out_of_stock", + "item_category2": "مواد پروتئینی و تخم مرغ", + "item_category3": "", + "item_category4": "", + "item_category5": "" + }, + "product_type": "product", + "digiplus": { + "services": [ + "۴ ارسال رایگان ماهانه + ۲ ارسال رایگان بیشتر، ویژه سوپرمارکت", + "پشتیبانی اختصاصی" + ], + "services_summary": [ + "ارسال رایگان" + ], + "is_jet_eligible": false, + "cash_back": 0, + "is_general_location_jet_eligible": false + }, + "images": { + "main": { + "url": [ + "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/quality,q_90" + ], + "webp_url": [ + "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/format,webp/quality,q_90" + ] + }, + "list": [ + { + "url": [ + "https://dkstatics-public.digikala.com/digikala-products/1f85d2dab3ceb24b47d37cd1b6d4f21a09058417_1675085790.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/quality,q_90" + ], + "webp_url": [ + "https://dkstatics-public.digikala.com/digikala-products/1f85d2dab3ceb24b47d37cd1b6d4f21a09058417_1675085790.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/format,webp/quality,q_90" + ] + } + ] + }, + "rating": { + "rate": 84.03037275655775, + "count": 2173 + }, + "properties": { + "is_fast_shipping": false, + "is_ship_by_seller": false, + "free_shipping_badge": false, + "is_multi_warehouse": false, + "is_fake": false, + "has_gift": false, + "min_price_in_last_month": 1746000, + "is_non_inventory": false, + "is_ad": false, + "is_jet_eligible": false, + "is_medical_supplement": false, + "has_printed_price": true + }, + "has_true_to_size": false, + "category": { + "id": 84, + "title_fa": "گوشت مرغ", + "title_en": "Chicken", + "code": "chicken", + "return_reason_alert": "به دلیل ماهیت و شرایط ویژه نگهداری و ارسال این گروه کالایی، درخواست مرجوع کردن آن با دلیل «انصراف از خرید» قابل تایید نیست." + }, + "brand": { + "id": 8897, + "code": "mahya-protein", + "title_fa": "مهیا پروتئین", + "title_en": "Mahya Protein", + "url": { + "uri": "/brand/mahya-protein/" + }, + "visibility": true, + "logo": { + "url": [ + "https://dkstatics-public.digikala.com/digikala-brands/477ab48bb7261595c02cb0f4c504837e464f00d0_1663485028.jpg?x-oss-process=image/resize,m_lfit,h_120,w_120/quality,q_80" + ] + }, + "is_premium": false, + "is_miscellaneous": false, + "is_name_similar": false + }, + "pros_and_cons": [], + "suggestion": { + "count": 600, + "percentage": 85 + }, + "questions_count": 3, + "comments_count": 775, + "breadcrumb": [ + { + "title": "سوپرمارکت", + "url": { + "uri": "/" + } + }, + { + "title": "مواد پروتئینی و تخم مرغ", + "url": { + "uri": "/search/category-protein-foods/" + } + }, + { + "title": "گوشت مرغ", + "url": { + "uri": "/search/category-chicken/" + } + }, + { + "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "url": { + "uri": "/product/dkp-792148/%D8%AC%D9%88%D8%AC%D9%87-%DA%A9%D8%A8%D8%A7%D8%A8-%D8%B1%D8%A7%D9%86-%D9%85%D8%B1%D8%BA-%D9%85%D9%87%DB%8C%D8%A7-%D9%BE%D8%B1%D9%88%D8%AA%D8%A6%DB%8C%D9%86-09-%DA%A9%DB%8C%D9%84%D9%88%DA%AF%D8%B1%D9%85" + } + } + ], + "specifications": [ + { + "title": "مشخصات", + "attributes": [ + { + "title": "وزن بسته‌بندی", + "values": [ + "0.9 گرم" + ] + }, + { + "title": "ابعاد بسته‌بندی", + "values": [ + "22 × 17 × 4 سانتی‌متر" + ] + }, + { + "title": "شماره پروانه بهداشت", + "values": [ + "IVC913961227824900 " + ] + }, + { + "title": "طعم", + "values": [ + "ساده " + ] + }, + { + "title": "سایر توضیحات", + "values": [ + "مناسب برای مصارف خانوار\r\nعرضه شده در ظرف با جنس پلی پروپیلن " + ] + } + ] + } + ], + "expert_reviews": { + "description": "", + "short_review": "", + "technical_properties": [] + }, + "meta": { + "brand_category_url": { + "uri": "/search/category-chicken/mahya-protein/" + } + }, + "last_comments": [ + { + "id": 65689093, + "body": "یه کم بو گرفته بود", + "created_at": "27 شهریور 1403", + "rate": 4, + "reactions": { + "likes": 0, + "dislikes": 0 + }, + "recommendation_status": "recommended", + "is_buyer": true, + "user_name": "سید زهیر مرتضوی", + "is_anonymous": false + }, + { + "id": 65625902, + "title": "", + "body": "تازه و خوب", + "created_at": "25 شهریور 1403", + "rate": 5, + "reactions": { + "likes": 0, + "dislikes": 0 + }, + "recommendation_status": "recommended", + "is_buyer": true, + "user_name": "سمانه قاسمی", + "is_anonymous": false + }, + { + "id": 65564545, + "title": "", + "body": "تازه بود ولی خودتون هم باید پاکش کنین چون کمی غضروف داره", + "created_at": "23 شهریور 1403", + "rate": 3, + "reactions": { + "likes": 0, + "dislikes": 0 + }, + "recommendation_status": "recommended", + "is_buyer": true, + "user_name": "فریبا صفاری فر", + "is_anonymous": false + }, + { + "id": 65368906, + "body": "خوب", + "created_at": "16 شهریور 1403", + "rate": 5, + "reactions": { + "likes": 0, + "dislikes": 0 + }, + "recommendation_status": "recommended", + "is_buyer": true, + "user_name": "کاربر دیجی‌کالا", + "is_anonymous": true + } + ], + "last_questions": [ + { + "id": 4985418, + "status": "accepted", + "text": "سلام علامت Aمثبت مفهومش چیست؟", + "answer_count": 5, + "sender": "مصطفی صنایعیان", + "created_at": "15 اردیبهشت 1402" + }, + { + "id": 3553714, + "status": "accepted", + "text": "سینه مرغ بسته ای ۹۵ تومن یا کیلویی ۹۵ تومن؟؟", + "answer_count": 6, + "sender": "ملیکا شهبازی", + "created_at": "22 خرداد 1401" + }, + { + "id": 3358273, + "status": "accepted", + "text": "استخوان دارد؟\n", + "answer_count": 7, + "sender": "نسرین صفاوردی", + "created_at": "7 اردیبهشت 1401" + } + ], + "digify_touchpoint": "" + }, + "data_layer": { + "event": "eec.productDetail", + "ecommerce": { + "detail": { + "actionField": { + "list": "category-گوشت مرغ" + }, + "products": [ + { + "brand": "مهیا پروتئین", + "category": "[FF,گوشت مرغ]", + "metric6": 2173, + "dimension2": 0, + "dimension6": 0, + "dimension7": "none", + "dimension9": 4.3, + "dimension11": 0, + "dimension20": "out_of_stock", + "item_category2": "مواد پروتئینی و تخم مرغ", + "item_category3": "", + "item_category4": "", + "item_category5": "", + "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "id": 792148, + "metric8": 0, + "dimension3": "marketplace", + "dimension15": 0, + "metric15": 0, + "metric11": 775, + "metric12": 600 + } + ] + } + } + }, + "seo": { + "title": "قیمت و خرید جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا", + "twitter_card": { + "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "image": "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_350,w_350/quality,q_60", + "price": 0, + "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا" + }, + "open_graph": { + "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "url": "https://www.digikala.com/product/dkp-792148/جوجه-کباب-ران-مرغ-مهیا-پروتئین-09-کیلوگرم", + "image": "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_350,w_350/quality,q_60", + "availability": "out of stock", + "type": "product", + "site": "دیجی‌کالا", + "price": 0 + }, + "header": { + "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا", + "canonical_url": "https://www.digikala.com/fresh/product/dkp-792148/%D8%AC%D9%88%D8%AC%D9%87-%DA%A9%D8%A8%D8%A7%D8%A8-%D8%B1%D8%A7%D9%86-%D9%85%D8%B1%D8%BA-%D9%85%D9%87%DB%8C%D8%A7-%D9%BE%D8%B1%D9%88%D8%AA%D8%A6%DB%8C%D9%86-09-%DA%A9%DB%8C%D9%84%D9%88%DA%AF%D8%B1%D9%85" + }, + "markup_schema": [ + { + "@type": "Product", + "@context": "https://www.schema.org", + "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", + "alternateName": "Mahya Protein Chicken Barbecue Drumstick - 0.9 Kg", + "images": [ + "https://dkstatics-public.digikala.com/digikala-products/1f85d2dab3ceb24b47d37cd1b6d4f21a09058417_1675085790.jpg?x-oss-process=image/resize,h_1600/quality,q_80" + ], + "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا", + "mpn": 792148, + "sku": 792148, + "category": "https://www.digikala.com/search/category-chicken/", + "brand": { + "@type": "Brand", + "name": "مهیا پروتئین", + "url": "https://www.digikala.com/brand/mahya-protein/", + "@id": "https://www.digikala.com/brand/mahya-protein/#brand" + }, + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": 4.2, + "reviewCount": 2179 + }, + "offers": { + "@type": "Offer", + "priceCurrency": "IRR", + "price": 1850000, + "itemCondition": "https://schema.org/NewCondition", + "availability": "https://schema.org/InStock" + }, + "review": { + "@type": "Review", + "reviewRating": { + "@type": "Rating", + "bestRating": 5, + "ratingValue": 4 + }, + "author": { + "@type": "Person", + "name": "سید زهیر مرتضوی" + }, + "datePublished": "2024-09-17", + "reviewBody": "یه کم بو گرفته بود", + "name": "" + } + }, + [ + { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + "itemListElement": [ + { + "@type": "ListItem", + "position": 1, + "name": "سوپرمارکت", + "item": { + "@type": "Corporation", + "@id": "//#corporation" + } + }, + { + "@type": "ListItem", + "position": 2, + "name": "مواد پروتئینی و تخم مرغ", + "item": "https://www.digikala.com/freshmain/protein-foods/" + }, + { + "@type": "ListItem", + "position": 3, + "name": "گوشت مرغ", + "item": "https://www.digikala.com/freshsearch/category-chicken/" + }, + { + "@type": "ListItem", + "position": 4, + "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم" + } + ] + }, + { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + "itemListElement": [ + { + "@type": "ListItem", + "position": 1, + "name": "مهیا پروتئین", + "item": { + "@type": "Brand", + "@id": "https://www.digikala.com/brand/mahya-protein/#brand" + } + }, + { + "@type": "ListItem", + "position": 2, + "name": "گوشت مرغ مهیا پروتئین", + "item": "https://www.digikala.com/search/category-chicken/mahya-protein/" + }, + { + "@type": "ListItem", + "position": 3, + "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم" + } + ] + } + ] + ] + }, + "promotion_banner": { + "dkjet_promotion": { + "mobile_banner": "https://dkstatics-public.digikala.com/digikala-static/e532944f277b28a38b3cfbf5f70e02f678145da5_1722682800.jpg", + "desktop_banner": "https://dkstatics-public.digikala.com/digikala-static/b37b8af7fc36e9bf8e673fc09a29dfebebb7634b_1722682228.jpg", + "url": "https://www.digikalajet.com/?utm_source=digikala&utm_medium=pdp&utm_campaign=Paid" + } + }, + "bigdata_tracker_data": { + "page_name": "product", + "page_info": { + "product_id": 792148 + } + } + } +} \ No newline at end of file From 1bf56ccee7e7b1f26dab13c808790564559da094 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 21 Sep 2024 18:38:18 +0330 Subject: [PATCH 24/77] fresh product changes --- say/celery.py | 2 +- say/crawler/__init__.py | 4 +- ...\330\255.\330\252\330\263\330\256\330\257" | 454 ------------------ 3 files changed, 3 insertions(+), 457 deletions(-) delete mode 100644 "\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" diff --git a/say/celery.py b/say/celery.py index 1f0ef62c..fbe562b2 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=15, hour='0,4,8,12,16,20'), + 'schedule': crontab(minute=15, hour='0,4,8,12,15,20'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 95dc077b..136d647f 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -115,7 +115,7 @@ def __init__(self, url): except IndexError: self.dkp = None - def get_data(self, need_id, force=False): + def get_data(self, force=False): if self.dkp is None: return @@ -126,10 +126,10 @@ def get_data(self, need_id, force=False): r = request_with_cache(url) if r.status_code != 200: return + result = r.json() # fresh products have different api / Digikala redirect to new link for fresh product # Typical response: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} - result = r.json() if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: url = self.API_URL_FRESH % self.dkp if force: diff --git "a/\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" "b/\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" deleted file mode 100644 index 1efeca71..00000000 --- "a/\331\201\330\253\331\276\330\255.\330\252\330\263\330\256\330\257" +++ /dev/null @@ -1,454 +0,0 @@ -{ - "status": 200, - "data": { - "product": { - "id": 792148, - "title_fa": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "title_en": "Mahya Protein Chicken Barbecue Drumstick - 0.9 Kg", - "url": { - "uri": "/product/dkp-792148/جوجه-کباب-ران-مرغ-مهیا-پروتئین-09-کیلوگرم" - }, - "status": "out_of_stock", - "has_quick_view": false, - "data_layer": { - "brand": "مهیا پروتئین", - "category": "[FF,گوشت مرغ]", - "metric6": 2173, - "dimension2": 0, - "dimension6": 0, - "dimension7": "none", - "dimension9": 4.3, - "dimension11": 0, - "dimension20": "out_of_stock", - "item_category2": "مواد پروتئینی و تخم مرغ", - "item_category3": "", - "item_category4": "", - "item_category5": "" - }, - "product_type": "product", - "digiplus": { - "services": [ - "۴ ارسال رایگان ماهانه + ۲ ارسال رایگان بیشتر، ویژه سوپرمارکت", - "پشتیبانی اختصاصی" - ], - "services_summary": [ - "ارسال رایگان" - ], - "is_jet_eligible": false, - "cash_back": 0, - "is_general_location_jet_eligible": false - }, - "images": { - "main": { - "url": [ - "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/quality,q_90" - ], - "webp_url": [ - "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/format,webp/quality,q_90" - ] - }, - "list": [ - { - "url": [ - "https://dkstatics-public.digikala.com/digikala-products/1f85d2dab3ceb24b47d37cd1b6d4f21a09058417_1675085790.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/quality,q_90" - ], - "webp_url": [ - "https://dkstatics-public.digikala.com/digikala-products/1f85d2dab3ceb24b47d37cd1b6d4f21a09058417_1675085790.jpg?x-oss-process=image/resize,m_lfit,h_800,w_800/format,webp/quality,q_90" - ] - } - ] - }, - "rating": { - "rate": 84.03037275655775, - "count": 2173 - }, - "properties": { - "is_fast_shipping": false, - "is_ship_by_seller": false, - "free_shipping_badge": false, - "is_multi_warehouse": false, - "is_fake": false, - "has_gift": false, - "min_price_in_last_month": 1746000, - "is_non_inventory": false, - "is_ad": false, - "is_jet_eligible": false, - "is_medical_supplement": false, - "has_printed_price": true - }, - "has_true_to_size": false, - "category": { - "id": 84, - "title_fa": "گوشت مرغ", - "title_en": "Chicken", - "code": "chicken", - "return_reason_alert": "به دلیل ماهیت و شرایط ویژه نگهداری و ارسال این گروه کالایی، درخواست مرجوع کردن آن با دلیل «انصراف از خرید» قابل تایید نیست." - }, - "brand": { - "id": 8897, - "code": "mahya-protein", - "title_fa": "مهیا پروتئین", - "title_en": "Mahya Protein", - "url": { - "uri": "/brand/mahya-protein/" - }, - "visibility": true, - "logo": { - "url": [ - "https://dkstatics-public.digikala.com/digikala-brands/477ab48bb7261595c02cb0f4c504837e464f00d0_1663485028.jpg?x-oss-process=image/resize,m_lfit,h_120,w_120/quality,q_80" - ] - }, - "is_premium": false, - "is_miscellaneous": false, - "is_name_similar": false - }, - "pros_and_cons": [], - "suggestion": { - "count": 600, - "percentage": 85 - }, - "questions_count": 3, - "comments_count": 775, - "breadcrumb": [ - { - "title": "سوپرمارکت", - "url": { - "uri": "/" - } - }, - { - "title": "مواد پروتئینی و تخم مرغ", - "url": { - "uri": "/search/category-protein-foods/" - } - }, - { - "title": "گوشت مرغ", - "url": { - "uri": "/search/category-chicken/" - } - }, - { - "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "url": { - "uri": "/product/dkp-792148/%D8%AC%D9%88%D8%AC%D9%87-%DA%A9%D8%A8%D8%A7%D8%A8-%D8%B1%D8%A7%D9%86-%D9%85%D8%B1%D8%BA-%D9%85%D9%87%DB%8C%D8%A7-%D9%BE%D8%B1%D9%88%D8%AA%D8%A6%DB%8C%D9%86-09-%DA%A9%DB%8C%D9%84%D9%88%DA%AF%D8%B1%D9%85" - } - } - ], - "specifications": [ - { - "title": "مشخصات", - "attributes": [ - { - "title": "وزن بسته‌بندی", - "values": [ - "0.9 گرم" - ] - }, - { - "title": "ابعاد بسته‌بندی", - "values": [ - "22 × 17 × 4 سانتی‌متر" - ] - }, - { - "title": "شماره پروانه بهداشت", - "values": [ - "IVC913961227824900 " - ] - }, - { - "title": "طعم", - "values": [ - "ساده " - ] - }, - { - "title": "سایر توضیحات", - "values": [ - "مناسب برای مصارف خانوار\r\nعرضه شده در ظرف با جنس پلی پروپیلن " - ] - } - ] - } - ], - "expert_reviews": { - "description": "", - "short_review": "", - "technical_properties": [] - }, - "meta": { - "brand_category_url": { - "uri": "/search/category-chicken/mahya-protein/" - } - }, - "last_comments": [ - { - "id": 65689093, - "body": "یه کم بو گرفته بود", - "created_at": "27 شهریور 1403", - "rate": 4, - "reactions": { - "likes": 0, - "dislikes": 0 - }, - "recommendation_status": "recommended", - "is_buyer": true, - "user_name": "سید زهیر مرتضوی", - "is_anonymous": false - }, - { - "id": 65625902, - "title": "", - "body": "تازه و خوب", - "created_at": "25 شهریور 1403", - "rate": 5, - "reactions": { - "likes": 0, - "dislikes": 0 - }, - "recommendation_status": "recommended", - "is_buyer": true, - "user_name": "سمانه قاسمی", - "is_anonymous": false - }, - { - "id": 65564545, - "title": "", - "body": "تازه بود ولی خودتون هم باید پاکش کنین چون کمی غضروف داره", - "created_at": "23 شهریور 1403", - "rate": 3, - "reactions": { - "likes": 0, - "dislikes": 0 - }, - "recommendation_status": "recommended", - "is_buyer": true, - "user_name": "فریبا صفاری فر", - "is_anonymous": false - }, - { - "id": 65368906, - "body": "خوب", - "created_at": "16 شهریور 1403", - "rate": 5, - "reactions": { - "likes": 0, - "dislikes": 0 - }, - "recommendation_status": "recommended", - "is_buyer": true, - "user_name": "کاربر دیجی‌کالا", - "is_anonymous": true - } - ], - "last_questions": [ - { - "id": 4985418, - "status": "accepted", - "text": "سلام علامت Aمثبت مفهومش چیست؟", - "answer_count": 5, - "sender": "مصطفی صنایعیان", - "created_at": "15 اردیبهشت 1402" - }, - { - "id": 3553714, - "status": "accepted", - "text": "سینه مرغ بسته ای ۹۵ تومن یا کیلویی ۹۵ تومن؟؟", - "answer_count": 6, - "sender": "ملیکا شهبازی", - "created_at": "22 خرداد 1401" - }, - { - "id": 3358273, - "status": "accepted", - "text": "استخوان دارد؟\n", - "answer_count": 7, - "sender": "نسرین صفاوردی", - "created_at": "7 اردیبهشت 1401" - } - ], - "digify_touchpoint": "" - }, - "data_layer": { - "event": "eec.productDetail", - "ecommerce": { - "detail": { - "actionField": { - "list": "category-گوشت مرغ" - }, - "products": [ - { - "brand": "مهیا پروتئین", - "category": "[FF,گوشت مرغ]", - "metric6": 2173, - "dimension2": 0, - "dimension6": 0, - "dimension7": "none", - "dimension9": 4.3, - "dimension11": 0, - "dimension20": "out_of_stock", - "item_category2": "مواد پروتئینی و تخم مرغ", - "item_category3": "", - "item_category4": "", - "item_category5": "", - "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "id": 792148, - "metric8": 0, - "dimension3": "marketplace", - "dimension15": 0, - "metric15": 0, - "metric11": 775, - "metric12": 600 - } - ] - } - } - }, - "seo": { - "title": "قیمت و خرید جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا", - "twitter_card": { - "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "image": "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_350,w_350/quality,q_60", - "price": 0, - "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا" - }, - "open_graph": { - "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "url": "https://www.digikala.com/product/dkp-792148/جوجه-کباب-ران-مرغ-مهیا-پروتئین-09-کیلوگرم", - "image": "https://dkstatics-public.digikala.com/digikala-products/3d70b4ef3f0647dc67a7ae086755afdd21b9ff2b_1675085791.jpg?x-oss-process=image/resize,m_lfit,h_350,w_350/quality,q_60", - "availability": "out of stock", - "type": "product", - "site": "دیجی‌کالا", - "price": 0 - }, - "header": { - "title": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا", - "canonical_url": "https://www.digikala.com/fresh/product/dkp-792148/%D8%AC%D9%88%D8%AC%D9%87-%DA%A9%D8%A8%D8%A7%D8%A8-%D8%B1%D8%A7%D9%86-%D9%85%D8%B1%D8%BA-%D9%85%D9%87%DB%8C%D8%A7-%D9%BE%D8%B1%D9%88%D8%AA%D8%A6%DB%8C%D9%86-09-%DA%A9%DB%8C%D9%84%D9%88%DA%AF%D8%B1%D9%85" - }, - "markup_schema": [ - { - "@type": "Product", - "@context": "https://www.schema.org", - "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم", - "alternateName": "Mahya Protein Chicken Barbecue Drumstick - 0.9 Kg", - "images": [ - "https://dkstatics-public.digikala.com/digikala-products/1f85d2dab3ceb24b47d37cd1b6d4f21a09058417_1675085790.jpg?x-oss-process=image/resize,h_1600/quality,q_80" - ], - "description": "خرید اینترنتی جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم به همراه مقایسه، بررسی مشخصات و لیست قیمت امروز در فروشگاه اینترنتی دیجی‌کالا", - "mpn": 792148, - "sku": 792148, - "category": "https://www.digikala.com/search/category-chicken/", - "brand": { - "@type": "Brand", - "name": "مهیا پروتئین", - "url": "https://www.digikala.com/brand/mahya-protein/", - "@id": "https://www.digikala.com/brand/mahya-protein/#brand" - }, - "aggregateRating": { - "@type": "AggregateRating", - "ratingValue": 4.2, - "reviewCount": 2179 - }, - "offers": { - "@type": "Offer", - "priceCurrency": "IRR", - "price": 1850000, - "itemCondition": "https://schema.org/NewCondition", - "availability": "https://schema.org/InStock" - }, - "review": { - "@type": "Review", - "reviewRating": { - "@type": "Rating", - "bestRating": 5, - "ratingValue": 4 - }, - "author": { - "@type": "Person", - "name": "سید زهیر مرتضوی" - }, - "datePublished": "2024-09-17", - "reviewBody": "یه کم بو گرفته بود", - "name": "" - } - }, - [ - { - "@context": "https://schema.org", - "@type": "BreadcrumbList", - "itemListElement": [ - { - "@type": "ListItem", - "position": 1, - "name": "سوپرمارکت", - "item": { - "@type": "Corporation", - "@id": "//#corporation" - } - }, - { - "@type": "ListItem", - "position": 2, - "name": "مواد پروتئینی و تخم مرغ", - "item": "https://www.digikala.com/freshmain/protein-foods/" - }, - { - "@type": "ListItem", - "position": 3, - "name": "گوشت مرغ", - "item": "https://www.digikala.com/freshsearch/category-chicken/" - }, - { - "@type": "ListItem", - "position": 4, - "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم" - } - ] - }, - { - "@context": "https://schema.org", - "@type": "BreadcrumbList", - "itemListElement": [ - { - "@type": "ListItem", - "position": 1, - "name": "مهیا پروتئین", - "item": { - "@type": "Brand", - "@id": "https://www.digikala.com/brand/mahya-protein/#brand" - } - }, - { - "@type": "ListItem", - "position": 2, - "name": "گوشت مرغ مهیا پروتئین", - "item": "https://www.digikala.com/search/category-chicken/mahya-protein/" - }, - { - "@type": "ListItem", - "position": 3, - "name": "جوجه کباب ران مرغ مهیا پروتئین - 0.9 کیلوگرم" - } - ] - } - ] - ] - }, - "promotion_banner": { - "dkjet_promotion": { - "mobile_banner": "https://dkstatics-public.digikala.com/digikala-static/e532944f277b28a38b3cfbf5f70e02f678145da5_1722682800.jpg", - "desktop_banner": "https://dkstatics-public.digikala.com/digikala-static/b37b8af7fc36e9bf8e673fc09a29dfebebb7634b_1722682228.jpg", - "url": "https://www.digikalajet.com/?utm_source=digikala&utm_medium=pdp&utm_campaign=Paid" - } - }, - "bigdata_tracker_data": { - "page_name": "product", - "page_info": { - "product_id": 792148 - } - } - } -} \ No newline at end of file From 6de0dd6b08fcb314743bcd3e6a71c3d7ff08963c Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 21 Sep 2024 18:56:01 +0330 Subject: [PATCH 25/77] fresh product changes --- say/celery.py | 2 +- say/models/need_model.py | 4 ++-- say/tasks/update_needs.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/say/celery.py b/say/celery.py index fbe562b2..55cb6821 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=15, hour='0,4,8,12,15,20'), + 'schedule': crontab(minute=30, hour='0,4,8,12,15,20'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', diff --git a/say/models/need_model.py b/say/models/need_model.py index 8298910f..fd0117c5 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -442,13 +442,13 @@ def current_participants(self): paid=past_participation.paid, ) - def update(self,need_id, force=False): + def update(self, force=False): from say.crawler import Crawler from say.crawler import DigikalaCrawler if 'digikala' in self.link: print("updating via crawler.....") - data = DigikalaCrawler(self.link).get_data(need_id, force=force) + data = DigikalaCrawler(self.link).get_data(force=force) else: data = Crawler(self.link).get_data(force=force) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 3e41dc6b..06817c21 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -41,7 +41,7 @@ def update_need(self, need_id, force=False): sleep(5) need = self.session.query(Need).get(need_id) - data = need.update(need_id, force=force) + data = need.update(force=force) safe_commit(self.session) return data From a3e10212608169cd5fb923025777b77ffc1ec8cb Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 21 Sep 2024 19:01:44 +0330 Subject: [PATCH 26/77] fresh product changes --- say/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/celery.py b/say/celery.py index 55cb6821..626ae8df 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=30, hour='0,4,8,12,15,20'), + 'schedule': crontab(minute=45, hour='0,4,8,12,15,20'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', From c9285b3ed3ec94b13cbf4bdf54f4bf9596a370fe Mon Sep 17 00:00:00 2001 From: ehsang Date: Wed, 25 Sep 2024 16:35:58 +0330 Subject: [PATCH 27/77] celery rest --- say/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/celery.py b/say/celery.py index 626ae8df..20e5330e 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=45, hour='0,4,8,12,15,20'), + 'schedule': crontab(minute=30, hour='0,4,8,12,16,20'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', From c1089259233383a7f69b451a110ea44c05b90b6a Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 1 Dec 2024 22:32:52 +0330 Subject: [PATCH 28/77] tasks bug fix --- say/crawler/__init__.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 136d647f..8b74c070 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -116,6 +116,8 @@ def __init__(self, url): self.dkp = None def get_data(self, force=False): + result = None + if self.dkp is None: return @@ -124,10 +126,8 @@ def get_data(self, force=False): r = requests.get(url) else: r = request_with_cache(url) - if r.status_code != 200: - return result = r.json() - + # fresh products have different api / Digikala redirect to new link for fresh product # Typical response: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: @@ -136,10 +136,11 @@ def get_data(self, force=False): r = requests.get(url) else: r = request_with_cache(url) - if r.status_code != 200: - return result = r.json() + + if r.status_code != 200: + return data = result['data'] if data['product'].get('is_inactive'): From c9a68fe8c5301aa8398eb2845197b2c990257efe Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 1 Dec 2024 22:32:55 +0330 Subject: [PATCH 29/77] tasks bug fix --- say/crawler/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 8b74c070..c95834c0 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -130,7 +130,7 @@ def get_data(self, force=False): # fresh products have different api / Digikala redirect to new link for fresh product # Typical response: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} - if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: + if result and result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: url = self.API_URL_FRESH % self.dkp if force: r = requests.get(url) From 4cd96cee333247972174a56d52f094d13d54fb5b Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 1 Dec 2024 22:46:21 +0330 Subject: [PATCH 30/77] tasks bug fix --- say/crawler/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index c95834c0..e5d82fec 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -126,7 +126,9 @@ def get_data(self, force=False): r = requests.get(url) else: r = request_with_cache(url) - result = r.json() + + if r.status_code == 200: + result = r.json() # fresh products have different api / Digikala redirect to new link for fresh product # Typical response: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} From 24d88d3ed8d1e4a67b914012bb9b0c2a3d63447d Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 1 Dec 2024 23:05:16 +0330 Subject: [PATCH 31/77] tasks bug fix --- say/crawler/__init__.py | 5 ++++- say/models/need_model.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index e5d82fec..ee5558a7 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -126,7 +126,7 @@ def get_data(self, force=False): r = requests.get(url) else: r = request_with_cache(url) - + if r.status_code == 200: result = r.json() @@ -140,6 +140,9 @@ def get_data(self, force=False): r = request_with_cache(url) result = r.json() + print("url and result:") + print(url) + print(result) if r.status_code != 200: return diff --git a/say/models/need_model.py b/say/models/need_model.py index fd0117c5..ce604eac 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -449,6 +449,7 @@ def update(self, force=False): if 'digikala' in self.link: print("updating via crawler.....") data = DigikalaCrawler(self.link).get_data(force=force) + print("Done updating.") else: data = Crawler(self.link).get_data(force=force) From 307d35c1927dcad30c8d42062914349bf6834288 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 1 Dec 2024 23:24:07 +0330 Subject: [PATCH 32/77] tasks bug fix --- say/crawler/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index ee5558a7..bb83a4d5 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -127,12 +127,16 @@ def get_data(self, force=False): else: r = request_with_cache(url) - if r.status_code == 200: + if r.status == 200 or r.status == 302: result = r.json() + else: + print("Cold not update!") + return + # fresh products have different api / Digikala redirect to new link for fresh product # Typical response: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} - if result and result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: + if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: url = self.API_URL_FRESH % self.dkp if force: r = requests.get(url) From 24a552331372c3c0e1e05e23c1739833c9f40bbe Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 1 Dec 2024 23:34:11 +0330 Subject: [PATCH 33/77] tasks bug fix --- say/crawler/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index bb83a4d5..7b4a1c33 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -127,7 +127,7 @@ def get_data(self, force=False): else: r = request_with_cache(url) - if r.status == 200 or r.status == 302: + if r.status_code == 200 or r.status_code == 302: result = r.json() else: print("Cold not update!") From 3b5ac0d17d9fa373dfdf7e29f211e4f70c496528 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sun, 1 Dec 2024 23:47:49 +0330 Subject: [PATCH 34/77] tasks bug fix --- say/crawler/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 7b4a1c33..0508735e 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -127,9 +127,10 @@ def get_data(self, force=False): else: r = request_with_cache(url) - if r.status_code == 200 or r.status_code == 302: + if r.status_code == 200: result = r.json() else: + print(url) print("Cold not update!") return From a9bfa43195c0949128a07e2ba4fe1b7fb4f78285 Mon Sep 17 00:00:00 2001 From: ehsang Date: Mon, 2 Dec 2024 00:03:44 +0330 Subject: [PATCH 35/77] tasks bug fix --- say/crawler/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 0508735e..b758e940 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -130,6 +130,7 @@ def get_data(self, force=False): if r.status_code == 200: result = r.json() else: + print(r) print(url) print("Cold not update!") return From e54d53c6c7846857c76f7fa0a38633b15a5c6fd3 Mon Sep 17 00:00:00 2001 From: ehsang Date: Mon, 2 Dec 2024 00:29:15 +0330 Subject: [PATCH 36/77] tasks bug fix --- say/tasks/update_needs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 06817c21..1b521326 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -1,6 +1,6 @@ from time import sleep -from sqlalchemy import or_ +from sqlalchemy import or_, and_ from say.celery import celery from say.orm import safe_commit @@ -12,7 +12,7 @@ def update_needs(self): needs = self.session.query(Need).filter( Need.type == 1, - or_( + and_( Need.status < 4, Need.title.is_(None), ), @@ -39,7 +39,7 @@ def update_needs(self): def update_need(self, need_id, force=False): from say.models.need_model import Need - sleep(5) + sleep(10) need = self.session.query(Need).get(need_id) data = need.update(force=force) safe_commit(self.session) From f10c7e9e664ce3c6f0b7c0528fd446d52584a7c8 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 17:39:55 +0330 Subject: [PATCH 37/77] retialer 403 fix --- requirements.txt | 3 +- say/crawler/__init__.py | 78 ++++++++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/requirements.txt b/requirements.txt index a4e8fe74..c4aa2d33 100644 --- a/requirements.txt +++ b/requirements.txt @@ -38,4 +38,5 @@ SQLAlchemy-Utils~=0.38.2 ujson~=5.2.0 web3~=5.13.1 Werkzeug~=1.0.1 -markupsafe==2.0.1 \ No newline at end of file +markupsafe==2.0.1 +wget==3.2 diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index b758e940..ede6f44d 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -2,7 +2,8 @@ import html import re from typing import NamedTuple - +import subprocess +import json import requests from cachetools import TTLCache from cachetools import cached @@ -115,53 +116,66 @@ def __init__(self, url): except IndexError: self.dkp = None - def get_data(self, force=False): + + def call_api(self, url): + try: + # Run the wget command and capture the output + result = subprocess.run(['wget', '-qO-', url], capture_output=True, text=True, check=True) + return result.stdout + except subprocess.CalledProcessError as e: + return f"An error occurred: {e}" + + def parse_result(self, api_response): + try: + # Parse the JSON response + json_response = json.loads(api_response) + return json_response + except json.JSONDecodeError as e: + return f"An error occurred while parsing JSON: {e}" + + def get_data(self): result = None + parsed_result = None if self.dkp is None: return url = self.API_URL_NOT_FRESH % self.dkp - if force: - r = requests.get(url) - else: - r = request_with_cache(url) + api_response = self.call_api(url) + parsed_result = self.parse_result(api_response) + + print(parsed_result) + if int(parsed_result["status"]) == 200: + parsed_result = self.parse_result(api_response) + elif parsed_result["status"] == 302 and "fresh" in parsed_result["redirect_url"]["uri"]: + url = self.API_URL_FRESH % self.dkp + api_response = self.call_api(url) + parsed_result = self.parse_result(api_response) + if parsed_result["status"] != 200: + print("Cold not update!") + return + else: + parsed_result = self.parse_result(api_response) - if r.status_code == 200: - result = r.json() else: - print(r) - print(url) print("Cold not update!") + print(url) return + result = parsed_result["data"] - # fresh products have different api / Digikala redirect to new link for fresh product - # Typical response: {'status': 302, 'redirect_url': {'base': None, 'uri': '/fresh/product/dkp-10269403/'}} - if result["status"] == 302 and "fresh" in result["redirect_url"]["uri"]: - url = self.API_URL_FRESH % self.dkp - if force: - r = requests.get(url) - else: - r = request_with_cache(url) - result = r.json() - - print("url and result:") - print(url) - print(result) - if r.status_code != 200: - return - data = result['data'] - - if data['product'].get('is_inactive'): + if result['product'].get('is_inactive'): return dict(cost='unavailable', img=None, title=None) - title = data['product']['title_fa'] - if data['product']['status'] == 'marketable': - cost = int(data['product']['default_variant']['price']['rrp_price']) // 10 + title = result['product']['title_fa'] + if result['product']['status'] == 'marketable': + cost = int(result['product']['default_variant']['price']['rrp_price']) // 10 else: cost = 'unavailable' - img = data['product']['images']['main']['url'][0] + img = result['product']['images']['main']['url'][0] return dict(cost=cost, img=img, title=title) + + + From 4a8d51c9b0e2c204c4acd2a3779f58c5473c1067 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 17:58:05 +0330 Subject: [PATCH 38/77] retialer 403 fix --- say/crawler/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index ede6f44d..d05af4b1 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -133,7 +133,7 @@ def parse_result(self, api_response): except json.JSONDecodeError as e: return f"An error occurred while parsing JSON: {e}" - def get_data(self): + def get_data(self, force=False): result = None parsed_result = None From 97a4701361f535a2a6da08c8f172969cc9a3f45d Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 18:02:59 +0330 Subject: [PATCH 39/77] retialer 403 fix --- say/tasks/update_needs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 1b521326..85143ff5 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -12,7 +12,7 @@ def update_needs(self): needs = self.session.query(Need).filter( Need.type == 1, - and_( + or_( Need.status < 4, Need.title.is_(None), ), From 3aa71f8e1b70d56ae2d2bbba9ea409dde0676c2e Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 18:31:52 +0330 Subject: [PATCH 40/77] retialer 403 fix --- say/crawler/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index d05af4b1..cd13e802 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -120,7 +120,9 @@ def __init__(self, url): def call_api(self, url): try: # Run the wget command and capture the output + print("result") result = subprocess.run(['wget', '-qO-', url], capture_output=True, text=True, check=True) + print(result) return result.stdout except subprocess.CalledProcessError as e: return f"An error occurred: {e}" From 91fddfebeaeb0567c07507437e3cc117231d9a73 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 18:43:00 +0330 Subject: [PATCH 41/77] retialer 403 fix --- say/crawler/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index cd13e802..12e49674 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -120,9 +120,7 @@ def __init__(self, url): def call_api(self, url): try: # Run the wget command and capture the output - print("result") result = subprocess.run(['wget', '-qO-', url], capture_output=True, text=True, check=True) - print(result) return result.stdout except subprocess.CalledProcessError as e: return f"An error occurred: {e}" @@ -135,7 +133,7 @@ def parse_result(self, api_response): except json.JSONDecodeError as e: return f"An error occurred while parsing JSON: {e}" - def get_data(self, force=False): + def get_data(self, force): result = None parsed_result = None @@ -143,6 +141,8 @@ def get_data(self, force=False): return url = self.API_URL_NOT_FRESH % self.dkp + print("url:") + print(url) api_response = self.call_api(url) parsed_result = self.parse_result(api_response) From 3891f56863b7fab7247a4b5da02df7e046551ed7 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 19:22:11 +0330 Subject: [PATCH 42/77] retialer 403 fix --- requirements.txt | 3 ++- say/crawler/__init__.py | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/requirements.txt b/requirements.txt index c4aa2d33..e8876ae1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,4 +39,5 @@ ujson~=5.2.0 web3~=5.13.1 Werkzeug~=1.0.1 markupsafe==2.0.1 -wget==3.2 +urllib3==2.2.3 + diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index 12e49674..c923f152 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -2,7 +2,7 @@ import html import re from typing import NamedTuple -import subprocess +import urllib.request import json import requests from cachetools import TTLCache @@ -119,16 +119,17 @@ def __init__(self, url): def call_api(self, url): try: - # Run the wget command and capture the output - result = subprocess.run(['wget', '-qO-', url], capture_output=True, text=True, check=True) - return result.stdout - except subprocess.CalledProcessError as e: - return f"An error occurred: {e}" + with urllib.request.urlopen(url) as response: + status_code = response.getcode() + content = response.read().decode('utf-8') + return status_code, content + except urllib.error.URLError as e: + return None, f"An error occurred: {e}" def parse_result(self, api_response): try: # Parse the JSON response - json_response = json.loads(api_response) + json_response = json.loads(api_response[1]) return json_response except json.JSONDecodeError as e: return f"An error occurred while parsing JSON: {e}" @@ -154,13 +155,13 @@ def get_data(self, force): api_response = self.call_api(url) parsed_result = self.parse_result(api_response) if parsed_result["status"] != 200: - print("Cold not update!") + print("Could not update!") return else: parsed_result = self.parse_result(api_response) else: - print("Cold not update!") + print("Could not update!") print(url) return From f9fcb072651077e0325c2fd706536cb0b1ee812c Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 19:33:29 +0330 Subject: [PATCH 43/77] retialer 403 fix --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e8876ae1..66cd418a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,5 +39,5 @@ ujson~=5.2.0 web3~=5.13.1 Werkzeug~=1.0.1 markupsafe==2.0.1 -urllib3==2.2.3 +urllib3 From 314137d1628f201fe7098e07a1a66a170e24d7bf Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 19:46:25 +0330 Subject: [PATCH 44/77] retialer 403 fix --- say/crawler/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/say/crawler/__init__.py b/say/crawler/__init__.py index c923f152..25e9152c 100644 --- a/say/crawler/__init__.py +++ b/say/crawler/__init__.py @@ -142,12 +142,9 @@ def get_data(self, force): return url = self.API_URL_NOT_FRESH % self.dkp - print("url:") - print(url) api_response = self.call_api(url) parsed_result = self.parse_result(api_response) - print(parsed_result) if int(parsed_result["status"]) == 200: parsed_result = self.parse_result(api_response) elif parsed_result["status"] == 302 and "fresh" in parsed_result["redirect_url"]["uri"]: From 18e8927c2158e689227d8266ea7f3ae7dc1416d9 Mon Sep 17 00:00:00 2001 From: ehsang Date: Sat, 7 Dec 2024 20:51:20 +0330 Subject: [PATCH 45/77] retialer 403 fix --- say/celery.py | 2 +- say/tasks/update_needs.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/say/celery.py b/say/celery.py index 20e5330e..c61df57c 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=30, hour='0,4,8,12,16,20'), + 'schedule': crontab(minute=30, hour='6,12,16,20'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 85143ff5..763d7eb9 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -21,8 +21,11 @@ def update_needs(self): ) t = [] + + print(f"Total needs to be updated: {len(needs)}") for need in needs: t.append(need.id) + print(f"updating need: {need.id}") update_need.delay(need.id) return t From fc30bdca68ff0a373ea80cb5843664583905eeef Mon Sep 17 00:00:00 2001 From: ehsang Date: Mon, 3 Mar 2025 15:01:47 +0330 Subject: [PATCH 46/77] Update actions/cache to v4 --- .github/workflows/pipeline.yml | 2 +- say/tasks/update_needs.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml index e8def1ee..9eedbdf9 100644 --- a/.github/workflows/pipeline.yml +++ b/.github/workflows/pipeline.yml @@ -67,7 +67,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Cache Docker layers - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 763d7eb9..20b432b4 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -21,11 +21,12 @@ def update_needs(self): ) t = [] - + counter = 0 print(f"Total needs to be updated: {len(needs)}") for need in needs: + counter+=1 t.append(need.id) - print(f"updating need: {need.id}") + print(f"{counter}/{len(needs)}-> updating need: {need.id}") update_need.delay(need.id) return t From 5d2316a3f4f46ff8f74be13ff9683eddfbb49dc5 Mon Sep 17 00:00:00 2001 From: G Date: Thu, 17 Jul 2025 18:45:28 +0330 Subject: [PATCH 47/77] just a re-run --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 307037b5..e71b7ed4 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ #### Run Server + ```bash ./scripts/up.sh ``` From e29e7d44c4c0460899364c581640e031ca766623 Mon Sep 17 00:00:00 2001 From: G Date: Sun, 3 Aug 2025 16:21:29 +0330 Subject: [PATCH 48/77] fetching need erroro --- say/models/need_model.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/say/models/need_model.py b/say/models/need_model.py index ce604eac..51aef33d 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -314,6 +314,9 @@ def type_name(cls): @hybrid_property def status_description(self): locale = get_locale() + print('checking...') + print(self.id) + print(self.type_name) raw_status = NeedStatuses.get(self.status, self.type_name, locale) need_name = self.clean_title if self.type == 1 else self.name From 2ce7048005d96f908a77f2af2a0ff3c3fdd2ebab Mon Sep 17 00:00:00 2001 From: G Date: Sun, 3 Aug 2025 16:54:06 +0330 Subject: [PATCH 49/77] fixed - fetching need error --- say/models/need_model.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/say/models/need_model.py b/say/models/need_model.py index 51aef33d..ce604eac 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -314,9 +314,6 @@ def type_name(cls): @hybrid_property def status_description(self): locale = get_locale() - print('checking...') - print(self.id) - print(self.type_name) raw_status = NeedStatuses.get(self.status, self.type_name, locale) need_name = self.clean_title if self.type == 1 else self.name From 4351d2657cfda83793388cb813e382a48156497b Mon Sep 17 00:00:00 2001 From: G Date: Mon, 4 Aug 2025 16:47:23 +0330 Subject: [PATCH 50/77] minor fixes --- say/api/child_api.py | 2 +- say/models/social_worker_model.py | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/say/api/child_api.py b/say/api/child_api.py index b1f5a23f..f41a6d48 100644 --- a/say/api/child_api.py +++ b/say/api/child_api.py @@ -928,7 +928,7 @@ def patch(self, child_id): if family: family.isDeleted = True - child.social_worker.currentChildCount -= 1 + child.social_worker.current_child_count -= 1 child.ngo.currentChildrenCount -= 1 safe_commit(session) diff --git a/say/models/social_worker_model.py b/say/models/social_worker_model.py index 81fed409..1ccd28fb 100644 --- a/say/models/social_worker_model.py +++ b/say/models/social_worker_model.py @@ -203,18 +203,20 @@ def validate_password(self, password): def send_password(self, password): from say.authorization import create_sw_access_token from say.tasks import send_embeded_subject_email - - send_embeded_subject_email.delay( - to=self.email, - html=render_template_i18n( - 'social_worker_password.html', - social_worker=self, - surname=surname(self.gender), - password=password, - token=create_sw_access_token(self), - locale=self.locale, - ), - ) + try: + send_embeded_subject_email.delay( + to=self.email, + html=render_template_i18n( + 'social_worker_password.html', + social_worker=self, + surname=surname(self.gender), + password=password, + token=create_sw_access_token(self), + locale=self.locale, + ), + ) + except Exception as e: + self.retry(exc=e, countdown=60) @staticmethod def generate_password(): From 91e79f86bce9f5ef39b38bb2cbf5cfc1fc636457 Mon Sep 17 00:00:00 2001 From: G Date: Mon, 4 Aug 2025 18:54:37 +0330 Subject: [PATCH 51/77] mail timeout --- say/tasks/send_email.py | 1 + 1 file changed, 1 insertion(+) diff --git a/say/tasks/send_email.py b/say/tasks/send_email.py index 1b9a2846..78c52ce5 100644 --- a/say/tasks/send_email.py +++ b/say/tasks/send_email.py @@ -21,6 +21,7 @@ def get_subject_from_html(html): retry_backoff=True, retry_backoff_max=600, retry_kwargs={'max_retries': 80}, + soft_time_limit=60 ) def send_email(subject, to, html, cc=[], bcc=[]): if isinstance(to, str): From 4164971e1db9b0c0106bca7cbfe21ef4487a1fa0 Mon Sep 17 00:00:00 2001 From: G Date: Mon, 4 Aug 2025 21:47:52 +0330 Subject: [PATCH 52/77] some log print for tasks --- say/api/need_api.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index 144c354e..b88bcdd4 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -296,8 +296,11 @@ def patch(self, need_id): return need_dict if 'cost' in request.form.keys(): + print("updating cost...") new_cost = int(request.form['cost'].replace(',', '')) - + print(f"Id: {need.id}") + print(f"oldCost: {need._cost}") + print(f"newCOst: {new_cost}") if ( ( sw_role in [SOCIAL_WORKER, COORDINATOR, NGO_SUPERVISOR] From b8c0232ab102c89cc334b7e8b224757fdbed729a Mon Sep 17 00:00:00 2001 From: G Date: Tue, 5 Aug 2025 01:02:35 +0330 Subject: [PATCH 53/77] need task fixes --- say/tasks/update_needs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/say/tasks/update_needs.py b/say/tasks/update_needs.py index 20b432b4..9ed7053b 100644 --- a/say/tasks/update_needs.py +++ b/say/tasks/update_needs.py @@ -22,11 +22,11 @@ def update_needs(self): t = [] counter = 0 - print(f"Total needs to be updated: {len(needs)}") + print(f"Total needs to be updated: {needs.count()}") for need in needs: counter+=1 t.append(need.id) - print(f"{counter}/{len(needs)}-> updating need: {need.id}") + print(f"{counter}/{needs.count()}-> updating need: {need.id}") update_need.delay(need.id) return t From 135ec22a3d5e17b795afc52955bb8851a1a90afb Mon Sep 17 00:00:00 2001 From: G Date: Tue, 5 Aug 2025 01:09:20 +0330 Subject: [PATCH 54/77] need task fixes --- say/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/celery.py b/say/celery.py index c61df57c..a29d9cde 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=30, hour='6,12,16,20'), + 'schedule': crontab(minute=0, hour='12,21'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', From 459b8ae2bdbce97d6bef171ca653628c3ebb9a33 Mon Sep 17 00:00:00 2001 From: G Date: Tue, 5 Aug 2025 01:13:40 +0330 Subject: [PATCH 55/77] need task time changes --- say/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/say/celery.py b/say/celery.py index a29d9cde..58db7e55 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=0, hour='12,21'), + 'schedule': crontab(minute=0, hour='8,22'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', From 37b80d1390fec8b888b09d6178cc896c00ad9be0 Mon Sep 17 00:00:00 2001 From: G Date: Tue, 5 Aug 2025 02:00:37 +0330 Subject: [PATCH 56/77] need task minor changes --- say/api/need_api.py | 3 --- say/celery.py | 2 +- say/config.py | 2 +- say/models/need_model.py | 5 ++++- say/tasks/send_email.py | 1 - 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/say/api/need_api.py b/say/api/need_api.py index b88bcdd4..6d79626d 100644 --- a/say/api/need_api.py +++ b/say/api/need_api.py @@ -298,9 +298,6 @@ def patch(self, need_id): if 'cost' in request.form.keys(): print("updating cost...") new_cost = int(request.form['cost'].replace(',', '')) - print(f"Id: {need.id}") - print(f"oldCost: {need._cost}") - print(f"newCOst: {new_cost}") if ( ( sw_role in [SOCIAL_WORKER, COORDINATOR, NGO_SUPERVISOR] diff --git a/say/celery.py b/say/celery.py index 58db7e55..395fac32 100644 --- a/say/celery.py +++ b/say/celery.py @@ -23,7 +23,7 @@ }, 'update-needs': { 'task': 'say.tasks.update_needs.update_needs', - 'schedule': crontab(minute=0, hour='8,22'), + 'schedule': crontab(minute=30, hour='6'), }, 'report_to_family': { 'task': 'say.tasks.report_to_family.report_to_families', diff --git a/say/config.py b/say/config.py index 42d1d5bd..b4ca8327 100644 --- a/say/config.py +++ b/say/config.py @@ -73,7 +73,7 @@ class Config(object): # Celery BROKER = "redis" - task_soft_time_limit = 60 + task_soft_time_limit = 120 task_acks_late = True worker_prefetch_multiplier = 1 diff --git a/say/models/need_model.py b/say/models/need_model.py index ce604eac..1209c105 100644 --- a/say/models/need_model.py +++ b/say/models/need_model.py @@ -454,12 +454,15 @@ def update(self, force=False): data = Crawler(self.link).get_data(force=force) if data is None: + print(f"Could not get data for: {self.id}") return img = data['img'] title = data['title'] cost = data['cost'] - + print(f"Id: {self.id}") + print(f"fetched title: {title}") + print(f"fetched cost: {cost}") if img: self.img = img diff --git a/say/tasks/send_email.py b/say/tasks/send_email.py index 78c52ce5..1b9a2846 100644 --- a/say/tasks/send_email.py +++ b/say/tasks/send_email.py @@ -21,7 +21,6 @@ def get_subject_from_html(html): retry_backoff=True, retry_backoff_max=600, retry_kwargs={'max_retries': 80}, - soft_time_limit=60 ) def send_email(subject, to, html, cc=[], bcc=[]): if isinstance(to, str): From ec58e8b07feea78f689a2ee653b34de5dd004393 Mon Sep 17 00:00:00 2001 From: G Date: Tue, 5 Aug 2025 19:32:02 +0330 Subject: [PATCH 57/77] pre-need filtering --- say/api/preneed_api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/say/api/preneed_api.py b/say/api/preneed_api.py index 3457b3c3..2a9608c8 100644 --- a/say/api/preneed_api.py +++ b/say/api/preneed_api.py @@ -30,6 +30,7 @@ def get(self): ).filter( Need.child_id == DEFAULT_CHILD_ID, Need.isDeleted.is_(False), + ~Need.imageUrl.ilike('%wrong path%') # Case-insensitive ) return PreneedSummarySchema.from_query_list(preneeds) From 5bf8b71da96e28d76417ff4d2350802292f2e9b6 Mon Sep 17 00:00:00 2001 From: G Date: Wed, 6 Aug 2025 17:29:22 +0330 Subject: [PATCH 58/77] revising automated emails --- say/static/images/github.png | Bin 0 -> 23802 bytes say/templates/fa/base.html | 513 +++++++++++------- say/templates/fa/cart_successful_payment.html | 356 ++++++------ say/templates/fa/social_worker_password.html | 344 +++++++++++- say/templates/fa/status_update_to_family.html | 7 +- say/templates/fa/successful_payment.html | 360 ++++++------ say/templates/fa/unsuccessful_payment.html | 77 ++- 7 files changed, 1043 insertions(+), 614 deletions(-) create mode 100644 say/static/images/github.png diff --git a/say/static/images/github.png b/say/static/images/github.png new file mode 100644 index 0000000000000000000000000000000000000000..402191e09edaf5619244f4cbbe449d69c949dbf5 GIT binary patch literal 23802 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 literal 0 HcmV?d00001 diff --git a/say/templates/fa/base.html b/say/templates/fa/base.html index 3a4dc352..0fe1b0f5 100644 --- a/say/templates/fa/base.html +++ b/say/templates/fa/base.html @@ -1,39 +1,305 @@ - - - - - - - - {% block title %}{% endblock %} - - + + {% block title %}{% endblock %} + + + + - -
+
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ SAY DAO +
+
+
+
+ + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ مستندات +
+
+ + + + + +
+ + + + +
+ دپلیکیشن +
+
+ + + + + +
+ + + + +
+ وبسایت +
+
+
+
+
+
+ +
- -
+ +
- {% block img %}{% endblock %} + "> + {% block img %}{% endblock %} - -

- {% block tcontent %}{% endblock %} -

+ "> + {% block tcontent %}{% endblock %} +

- -

- {% block mcontent %}{% endblock %} -

+ "> + {% block mcontent %}{% endblock %} +

- -

- ما به شما گوش می‌دهیم، با ما تماس بگیرید. -

- - -
- - - -
-
- - - - - -
-

+ ما به شما گوش می‌دهیم، با ما تماس بگیرید. +

+

- تلفن : ۰ ۲ ۱ - ۲ ۲ ۳ ۴ ۷ ۸ ۱ ۴ -

-
+ "> + info@saydao.org

- - +
+ + + \ No newline at end of file diff --git a/say/templates/fa/cart_successful_payment.html b/say/templates/fa/cart_successful_payment.html index 4332dca1..3ba6781d 100644 --- a/say/templates/fa/cart_successful_payment.html +++ b/say/templates/fa/cart_successful_payment.html @@ -1,180 +1,184 @@ - - تراکنش موفق - - - - - - - - - - - -