ads fetch machanism change - #15
Conversation
PR Summary by QodoUpdate Divar ad fetch to new postlist search API + scheduled GitHub Actions run
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1. Unstable token file churn
|
| # get new tokens list (single page - newest ads sorted by date) | ||
| tokens_list = get_tokens_page() | ||
| # remove repeated tokens | ||
| tokens_list = list(filter(lambda t: t not in tokens, tokens_list)) | ||
| tokens = list(set(tokens_list + tokens)) | ||
| asyncio.run(process_data(tokens_list)) | ||
|
|
||
| # save new tokens | ||
| save_tokns(tokens) |
There was a problem hiding this comment.
1. Unstable token file churn 🐞 Bug ☼ Reliability
tokens is rebuilt via set() and then saved, which produces nondeterministic ordering and can change tokens.json even when no new ads exist. Because the workflow commits/pushes tokens.json, this can create unnecessary commits and increase the chance of push conflicts.
Agent Prompt
## Issue description
`tokens = list(set(...))` produces nondeterministic ordering, causing `tokens.json` to change unpredictably and be re-committed even when token contents are unchanged.
## Issue Context
The scheduled workflow commits/pushes `tokens.json`, so ordering churn translates directly into repo churn and higher likelihood of push conflicts.
## Fix Focus Areas
- main.py[219-227]
- .github/workflows/run-bot.yml[35-41]
## Suggested fix
- Replace the `set()` merge with an order-preserving de-duplication (e.g., `list(dict.fromkeys(tokens_list + tokens))`), and/or sort tokens before saving.
- Optionally, only write/commit when the *content* actually changes (compare loaded tokens vs new tokens before writing).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| # New search parameters (replace the old SEARCH_CONDITIONS URL-path string) | ||
| SEARCH_CITY_ID = os.environ.get("SEARCH_CITY_ID", "897") # e.g. "897" for Golestan province | ||
| SEARCH_CATEGORY = os.environ.get("SEARCH_CATEGORY", "real-estate") | ||
|
|
There was a problem hiding this comment.
3. Env/docs mismatch persists 🐞 Bug ⚙ Maintainability
The code switches search configuration to SEARCH_CITY_ID/SEARCH_CATEGORY and no longer uses SEARCH_CONDITIONS, but README and .env.sample still instruct users to set SEARCH_CONDITIONS. The workflow also checks SEARCH_CONDITIONS in a debug step that doesn’t receive that env var, so it reports an empty value regardless of the secret configured for the run step.
Agent Prompt
## Issue description
Docs and workflow still reference `SEARCH_CONDITIONS` even though the code now uses `SEARCH_CITY_ID`/`SEARCH_CATEGORY`.
## Issue Context
This is likely to confuse operators and make debugging harder (the debug step checks a variable that isn't exported for that step).
## Fix Focus Areas
- main.py[18-21]
- README.md[29-44]
- .env.sample[1-5]
- .github/workflows/run-bot.yml[22-33]
## Suggested fix
- Update README and `.env.sample` to describe the new configuration variables.
- Update the workflow to remove `SEARCH_CONDITIONS` entirely (or pass the relevant env vars to the debug step and validate those instead).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| def get_data(): | ||
| body = build_search_body() | ||
| response = requests.post(URL, headers=REQUEST_HEADERS, json=body) | ||
| print( | ||
| "{} - Got response: {}".format( | ||
| datetime.datetime.now(), response.status_code | ||
| ) | ||
| ) | ||
| response.raise_for_status() | ||
| return response.json() | ||
|
|
||
|
|
||
| def get_ads_list(data): | ||
| return data["web_widgets"]["post_list"] | ||
| # New API returns posts directly under "widget_list" | ||
| return data.get("widget_list", []) | ||
|
|
||
|
|
||
| def fetch_ad_data(token: str) -> AD: | ||
| # send request | ||
| data = requests.get(f"https://api.divar.ir/v8/posts-v2/web/{token}").json() | ||
| images = [] | ||
| # check post exists | ||
| if not "sections" in data: | ||
| if "sections" not in data: | ||
| return None |
There was a problem hiding this comment.
4. Http calls lack timeouts 🐞 Bug ☼ Reliability
get_data() and fetch_ad_data() make requests calls without any timeout, so a stalled connection can hang the workflow run. fetch_ad_data() also parses .json() without checking HTTP status, so non-2xx responses can raise exceptions and abort the run before saving updated tokens.
Agent Prompt
## Issue description
Network requests to Divar have no timeouts, and `fetch_ad_data()` parses JSON without validating response status.
## Issue Context
On GitHub Actions, a hung request can waste runner time and prevent state persistence; transient API errors can crash the script mid-run.
## Fix Focus Areas
- main.py[81-90]
- main.py[98-104]
## Suggested fix
- Add explicit `timeout=` to all `requests` calls (e.g., `timeout=(5, 20)`).
- In `fetch_ad_data()`, store the response, call `raise_for_status()`, and handle `requests.RequestException`/`ValueError` (JSON decode) by returning `None` (or logging and skipping that token).
- Optionally use a shared `requests.Session()` for connection reuse.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
what happens while nothing received Signed-off-by: aliaslani <a77aslani@gmail.com>
pull before push Signed-off-by: aliaslani <a77aslani@gmail.com>
Signed-off-by: aliaslani <a77aslani@gmail.com>
Signed-off-by: aliaslani <a77aslani@gmail.com>
Signed-off-by: aliaslani <a77aslani@gmail.com>
Signed-off-by: aliaslani <a77aslani@gmail.com>
Signed-off-by: aliaslani <a77aslani@gmail.com>
divar had multiple changes in the way it gets/posts ads , so i applied changes to main.py and some other field.
its not completely verified, please double check it and tell me if something is wrong.