Skip to content

Commit f4108af

Browse files
committed
⚙️feat: add Conversation Cleanup
1 parent 59d6246 commit f4108af

File tree

8 files changed

+198
-182
lines changed

8 files changed

+198
-182
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fastapi dev main.py
4343

4444
| Feature | Description | Status |
4545
| ---------------------- | -------------------------------------------------------- | -------------------- |
46-
| Conversation Cleanup | Auto-delete conversations after x months of inactivity | ⚒️ Under Refactoring |
46+
| Conversation Cleanup | Auto-delete conversations after x months of inactivity | ✅ Done |
4747
| Ad Refresh | Automatic refreshing of listings | ⚒️ Under Refactoring |
4848
| Sales Analytics | Export transactions, generate graphs & statistics | 📝 To Be Done |
4949
| Annual Reports | Yearly compatible reporting system | 📝 To Be Done |

backend/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from fastapi.middleware.cors import CORSMiddleware
22
from fastapi import FastAPI
33
from config.settings import ALLOW_ORIGINS, DEBUG_MODE
4-
from routers import ads_management, auth, follow_mass
4+
from routers import ads_management, auth, follow_mass, accounting
55
from config.models import lifespan
66

77

@@ -12,6 +12,7 @@
1212
app.include_router(ads_management.router)
1313
app.include_router(auth.router)
1414
app.include_router(follow_mass.router)
15+
app.include_router(accounting.router)
1516

1617

1718
app.add_middleware(

backend/routers/accounting.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import datetime
2+
import re
3+
from fastapi import HTTPException, APIRouter, Depends
4+
from pydantic import BaseModel
5+
from sqlmodel import Session, select
6+
from constants import API_URL
7+
from utils import execute_request, get_vinted_headers
8+
from config.models import User, get_session
9+
from fastapi import APIRouter, Depends
10+
11+
router = APIRouter(
12+
prefix="/accounting",
13+
)
14+
15+
16+
class CleanConversations(BaseModel):
17+
monthsToKeep: int
18+
19+
20+
@router.post("/clean-conversations")
21+
async def clean_conversations(
22+
clean_conversations: CleanConversations,
23+
session: Session = Depends(get_session),
24+
headers: dict = Depends(get_vinted_headers),
25+
):
26+
page = 1
27+
nb_conversations_deleted = 0
28+
29+
response = execute_request(
30+
"GET", f"{API_URL}inbox?page={page}?per_page=20", headers, session=session
31+
)
32+
33+
total_pages = response.json()["pagination"]["total_pages"]
34+
35+
while page < total_pages:
36+
response = execute_request(
37+
"GET", f"{API_URL}inbox?page={page}?per_page=20", headers, session=session
38+
)
39+
40+
for conversation in response.json()["conversations"]:
41+
if (datetime.datetime.now() - datetime.datetime.strptime(conversation["updated_at"].split("+")[0], "%Y-%m-%dT%H:%M:%S")).days > clean_conversations.monthsToKeep * 30:
42+
nb_conversations_deleted += 1
43+
if not conversation["is_deletion_restricted"]:
44+
execute_request(
45+
"DELETE",
46+
f"{API_URL}conversations/{conversation['id']}",
47+
headers,
48+
session=session,
49+
)
50+
51+
page += 1
52+
53+
return {
54+
"message": "Conversations cleaned",
55+
"nnConversationsDeleted": nb_conversations_deleted,
56+
}

backend/routers/ads_management.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ async def refresh_ads(
113113
while True:
114114
user = session.exec(select(User).where(User.id == 1)).first()
115115
url = f"{API_URL}wardrobe/{user.userId}/items?page={page}&per_page=20&order=revelance"
116-
response = execute_request("get", url, headers)
116+
response = execute_request("GET", url, headers)
117117

118118
if response.status_code != 200:
119119
break
@@ -193,7 +193,7 @@ async def delete_sold_items(
193193
while True:
194194
user = session.exec(select(User).where(User.id == 1)).first()
195195
url = f"{API_URL}wardrobe/{user.userId}/items?page={page}&per_page=20&order=revelance"
196-
response = execute_request("get", url, headers)
196+
response = execute_request("GET", url, headers)
197197
nb_items_deleted = 0
198198

199199
if response.status_code != 200:
@@ -236,7 +236,7 @@ async def delete_all_ads(
236236
while True:
237237
user = session.exec(select(User).where(User.id == 1)).first()
238238
url = f"{API_URL}wardrobe/{user.userId}/items?page={page}&per_page=20&order=revelance"
239-
response = execute_request("get", url, headers)
239+
response = execute_request("GET", url, headers)
240240
nb_items_deleted = 0
241241

242242
if response.status_code != 200:

backend/routers/follow_mass.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ async def backup_followed_users(
6464
def toggle_follow(user_id: int, headers: dict) -> int:
6565
url = f"{API_URL}followed_users/toggle"
6666
data = {"user_id": user_id}
67-
response = execute_request("post", url, headers, data)
67+
response = execute_request("POST", url, headers, data)
6868
print(
6969
f"[RESULT] user_id: {user_id} CODE: {response.status_code} | REASON: {response.reason} | text: {response.text}"
7070
)

backend/utils.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,19 @@ def execute_request(
5959
i = 0
6060

6161
while i < MAX_RETRIES:
62-
if method == "get":
62+
if method == "GET":
6363
response = requests.get(url, headers=headers)
64-
elif method == "post":
64+
elif method == "POST":
6565
response = requests.post(url, headers=headers, json=data)
66-
elif method == "put":
67-
response = requests.put(url, headers=headers, json=data)
68-
elif method == "delete":
66+
elif method == "PATCH":
67+
response = requests.patch(url, headers=headers, json=data)
68+
elif method == "DELETE":
6969
response = requests.delete(url, headers=headers, json=data)
7070

7171
if response.status_code != 200:
7272
refresh_access_token(headers, session)
7373

74-
headers = get_vinted_headers()
74+
headers = get_vinted_headers(session)
7575
print(
7676
f"Status code: {response.status_code}",
7777
f"Reason: {response.reason}",
@@ -89,10 +89,14 @@ def execute_request(
8989

9090

9191
def refresh_access_token(headers: dict, session: Session):
92-
response = execute_request(
93-
"post", f"https://www.vinted.fr/web/api/auth/refresh", headers
92+
response = requests.post(
93+
f"https://www.vinted.fr/web/api/auth/refresh", headers=headers
9494
)
95-
print("Token vient d'être rafraîchi", response.json()["access_token"][:-5])
95+
if response.status_code != 200:
96+
raise HTTPException(
97+
status_code=401,
98+
detail="Refresh token refused by Vinted server. Please update your token.",
99+
)
96100
auth = session.exec(select(User).order_by(User.id.desc())).first()
97101
auth.vinted_access_token = response.json()["access_token"]
98102
session.add(auth)

0 commit comments

Comments
 (0)