14 socials integration #34
@@ -42,6 +42,15 @@ CRYPTOPANIC_API_KEY=
|
||||
REDDIT_API_CLIENT_ID=
|
||||
REDDIT_API_CLIENT_SECRET=
|
||||
|
||||
# Per ottenere questa API è necessario seguire i seguenti passaggi:
|
||||
# - Installare l'estensione su chrome X Auth Helper
|
||||
# - Dargli il permesso di girare in incognito
|
||||
# - Andare in incognito ed entrare sul proprio account X
|
||||
# - Aprire l'estensione e fare "get key"
|
||||
# - Chiudere chrome
|
||||
# Dovrebbe funzionare per 5 anni o finchè non si si fa il log out, in ogni caso si può ricreare
|
||||
X_API_KEY=
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Configurazioni per API di messaggistica
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# Utilizziamo Debian slim invece di Alpine per migliore compatibilità
|
||||
FROM debian:bookworm-slim
|
||||
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Installiamo le dipendenze di sistema
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl npm && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
RUN npm install -g rettiwt-api
|
||||
|
||||
# Installiamo uv
|
||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def unified_timestamp(timestamp_ms: int | None = None, timestamp_s: int | None = None) -> str:
|
||||
"""
|
||||
Transform the timestamp from milliseconds or seconds to a unified string format.
|
||||
The resulting string is a formatted string 'YYYY-MM-DD HH:MM'.
|
||||
Args:
|
||||
timestamp_ms: Timestamp in milliseconds.
|
||||
timestamp_s: Timestamp in seconds.
|
||||
Raises:
|
||||
ValueError: If neither timestamp_ms nor timestamp_s is provided.
|
||||
"""
|
||||
if timestamp_ms is not None:
|
||||
timestamp = timestamp_ms // 1000
|
||||
elif timestamp_s is not None:
|
||||
timestamp = timestamp_s
|
||||
else:
|
||||
raise ValueError("Either timestamp_ms or timestamp_s must be provided")
|
||||
assert timestamp > 0, "Invalid timestamp data received"
|
||||
|
||||
return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M')
|
||||
@@ -1,6 +1,6 @@
|
||||
import statistics
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
from app.api.core import unified_timestamp
|
||||
|
||||
|
||||
class ProductInfo(BaseModel):
|
||||
@@ -64,24 +64,8 @@ class Price(BaseModel):
|
||||
"""Timestamp in format YYYY-MM-DD HH:MM"""
|
||||
|
||||
def set_timestamp(self, timestamp_ms: int | None = None, timestamp_s: int | None = None) -> None:
|
||||
"""
|
||||
Sets the timestamp from milliseconds or seconds.
|
||||
The timestamp is saved as a formatted string 'YYYY-MM-DD HH:MM'.
|
||||
Args:
|
||||
timestamp_ms: Timestamp in milliseconds.
|
||||
timestamp_s: Timestamp in seconds.
|
||||
Raises:
|
||||
ValueError: If neither timestamp_ms nor timestamp_s is provided.
|
||||
"""
|
||||
if timestamp_ms is not None:
|
||||
timestamp = timestamp_ms // 1000
|
||||
elif timestamp_s is not None:
|
||||
timestamp = timestamp_s
|
||||
else:
|
||||
raise ValueError("Either timestamp_ms or timestamp_s must be provided")
|
||||
assert timestamp > 0, "Invalid timestamp data received"
|
||||
|
||||
self.timestamp = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M')
|
||||
""" Use the unified_timestamp function to set the timestamp."""
|
||||
self.timestamp = unified_timestamp(timestamp_ms, timestamp_s)
|
||||
|
||||
@staticmethod
|
||||
def aggregate(prices: dict[str, list['Price']]) -> list['Price']:
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
from pydantic import BaseModel
|
||||
from app.api.core import unified_timestamp
|
||||
|
||||
|
||||
|
||||
MAX_COMMENTS = 5
|
||||
|
||||
class SocialPost(BaseModel):
|
||||
"""
|
||||
Represents a social media post with time, title, description, and comments.
|
||||
@@ -10,6 +14,10 @@ class SocialPost(BaseModel):
|
||||
description: str = ""
|
||||
comments: list["SocialComment"] = []
|
||||
|
||||
def set_timestamp(self, timestamp_ms: int | None = None, timestamp_s: int | None = None) -> None:
|
||||
""" Use the unified_timestamp function to set the time."""
|
||||
self.time = unified_timestamp(timestamp_ms, timestamp_s)
|
||||
|
||||
class SocialComment(BaseModel):
|
||||
"""
|
||||
Represents a comment on a social media post.
|
||||
@@ -17,6 +25,10 @@ class SocialComment(BaseModel):
|
||||
time: str = ""
|
||||
description: str = ""
|
||||
|
||||
def set_timestamp(self, timestamp_ms: int | None = None, timestamp_s: int | None = None) -> None:
|
||||
""" Use the unified_timestamp function to set the time."""
|
||||
self.time = unified_timestamp(timestamp_ms, timestamp_s)
|
||||
|
||||
|
||||
class SocialWrapper:
|
||||
"""
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from app.api.social.reddit import RedditWrapper
|
||||
from app.api.social.x import XWrapper
|
||||
from app.api.social.chan import ChanWrapper
|
||||
|
||||
__all__ = ["RedditWrapper"]
|
||||
__all__ = ["RedditWrapper", "XWrapper", "ChanWrapper"]
|
||||
|
||||
89
src/app/api/social/chan.py
Normal file
@@ -0,0 +1,89 @@
|
||||
|
|
||||
'''
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
per evitare il try usa per evitare il try usa ```thread.get('sub', '')``` così non da errore e restituisce solo vuoto se non cè
|
||||
Usiamo le API di 4chan per ottenere un catalogo di threads dalla board /biz/
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
'''
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
import re
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
import html
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
import requests
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
from bs4 import BeautifulSoup
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
from datetime import datetime
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
from app.api.core.social import *
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
class ChanWrapper(SocialWrapper):
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
def __init__(self):
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
super().__init__()
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
def __time_str(self, timestamp: str) -> int:
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
"""Converte una stringa da MM/GG/AA(DAY)HH:MM:SS di 4chan a millisecondi"""
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
time = datetime.strptime(timestamp, "%m/%d/%y(%a)%H:%M:%S")
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
return int(time.timestamp() * 1000)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
def __unformat_html_str(self, html_element: str) -> str:
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
"""Pulisce il commento rimuovendo HTML e formattazioni inutili"""
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
if not html_element: return ""
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
html_entities = html.unescape(html_element)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
soup = BeautifulSoup(html_entities, 'html.parser')
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
html_element = soup.get_text(separator=" ")
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
html_element = re.sub(r"[\\/]+", "/", html_element)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
html_element = re.sub(r"\s+", " ", html_element).strip()
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
return html_element
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
def get_top_crypto_posts(self, limit: int = 5) -> list[SocialPost]:
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
url = 'https://a.4cdn.org/biz/catalog.json'
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
response = requests.get(url)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
assert response.status_code == 200, f"Error in 4chan API request [{response.status_code}] {response.text}"
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
social_posts: list[SocialPost] = []
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# Questa lista contiene un dizionario per ogni pagina della board di questo tipo {"page": page_number, "threads": [{thread_data}]}
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
for page in response.json():
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
for thread in page['threads']:
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# ci indica se il thread è stato fissato o meno, se non è presente vuol dire che non è stato fissato, i thread sticky possono essere ignorati
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
if 'sticky' in thread:
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
continue
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# la data di creazione del thread tipo "MM/GG/AA(day)hh:mm:ss", ci interessa solo MM/GG/AA
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
time = self.__time_str(thread.get('now', ''))
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# il nome dell'utente
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
name: str = thread.get('name', 'Anonymous')
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# il nome del thread, può contenere anche elementi di formattazione html che saranno da ignorare, potrebbe non essere presente
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
title = self.__unformat_html_str(thread.get('sub', ''))
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
title = f"{name} posted: {title}"
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# il commento del thread, può contenere anche elementi di formattazione html che saranno da ignorare
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
thread_description = self.__unformat_html_str(thread.get('com', ''))
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
if not thread_description:
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
continue
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# una lista di dizionari conteneti le risposte al thread principale, sono strutturate similarmente al thread
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
response_list = thread.get('last_replies', [])
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
comments_list: list[SocialComment] = []
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
for i, response in enumerate(response_list):
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
if i >= MAX_COMMENTS: break
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# la data di creazione della risposta tipo "MM/GG/AA(day)hh:mm:ss", ci interessa solo MM/GG/AA
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
time = self.__time_str(response['now'])
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
# il commento della risposta, può contenere anche elementi di formattazione html che saranno da ignorare
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
comment = self.__unformat_html_str(response.get('com', ''))
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
if not comment:
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
continue
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
social_comment = SocialComment(description=comment)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
social_comment.set_timestamp(timestamp_ms=time)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
comments_list.append(social_comment)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
social_post: SocialPost = SocialPost(
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
title=title,
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
description=thread_description,
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
comments=comments_list
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
social_post.set_timestamp(timestamp_ms=time)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
social_posts.append(social_post)
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
return social_posts[:limit]
|
||||
|
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
|
||||
@@ -1,10 +1,9 @@
|
||||
import os
|
||||
from praw import Reddit # type: ignore
|
||||
from praw.models import Submission # type: ignore
|
||||
from app.api.core.social import SocialWrapper, SocialPost, SocialComment
|
||||
from app.api.core.social import *
|
||||
|
||||
|
||||
MAX_COMMENTS = 5
|
||||
# metterne altri se necessario.
|
||||
# fonti: https://lkiconsulting.io/marketing/best-crypto-subreddits/
|
||||
SUBREDDITS = [
|
||||
@@ -24,13 +23,13 @@ SUBREDDITS = [
|
||||
|
||||
def extract_post(post: Submission) -> SocialPost:
|
||||
social = SocialPost()
|
||||
social.time = str(post.created)
|
||||
social.set_timestamp(timestamp_ms=post.created)
|
||||
social.title = post.title
|
||||
social.description = post.selftext
|
||||
|
||||
for top_comment in post.comments:
|
||||
comment = SocialComment()
|
||||
comment.time = str(top_comment.created)
|
||||
comment.set_timestamp(timestamp_ms=top_comment.created)
|
||||
comment.description = top_comment.body
|
||||
social.comments.append(comment)
|
||||
|
||||
|
||||
46
src/app/api/social/x.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
|
Direi che è meglio non usare docker direttamente per questa implementazione... Qualcosa tipo questo, formattato meglio e controlato se funziona: Direi che è meglio non usare docker direttamente per questa implementazione...
Preferirei che controllassi se il comando `rettiwt` è presente nel sistema, e se non lo è dare un errore.
Qualcosa tipo questo, formattato meglio e controlato se funziona:
```python
from shutil import which
assert which('rettiwt') is not None, "Command `rettiwt` not installed"
```
|
||||
import json
|
||||
import subprocess
|
||||
from shutil import which
|
||||
from app.api.core.social import SocialWrapper, SocialPost
|
||||
|
||||
|
||||
# This is the list of users that can be interesting
|
||||
# To get the ID of a new user is necessary to search it on X, copy the url and insert it in a service like "https://get-id-x.foundtt.com/en/"
|
||||
X_USERS = [
|
||||
'watcherguru',
|
||||
'Cointelegraph',
|
||||
'BTC_Archive',
|
||||
'elonmusk'
|
||||
]
|
||||
|
||||
class XWrapper(SocialWrapper):
|
||||
def __init__(self):
|
||||
'''
|
||||
This wrapper uses the rettiwt API to get data from X in order to avoid the rate limits of the free X API,
|
||||
even if improbable this could lead to a ban so do not use the personal account,
|
||||
In order to work it is necessary to install the rettiwt cli tool, for more information visit the official documentation at https://www.npmjs.com/package/rettiwt-api
|
||||
'''
|
||||
|
||||
self.api_key = os.getenv("X_API_KEY")
|
||||
assert self.api_key, "X_API_KEY environment variable not set"
|
||||
assert which('rettiwt') is not None, "Command `rettiwt` not installed"
|
||||
|
||||
|
||||
def get_top_crypto_posts(self, limit:int = 5) -> list[SocialPost]:
|
||||
social_posts: list[SocialPost] = []
|
||||
|
||||
for user in X_USERS:
|
||||
process = subprocess.run(f"rettiwt -k {self.api_key} tweet search -f {str(user)}", capture_output=True)
|
||||
results = process.stdout.decode()
|
||||
json_result = json.loads(results)
|
||||
|
||||
tweets = json_result['list']
|
||||
for tweet in tweets[:limit]:
|
||||
social_post = SocialPost()
|
||||
social_post.time = tweet['createdAt']
|
||||
social_post.title = str(user) + " tweeted: "
|
||||
social_post.description = tweet['fullText']
|
||||
social_posts.append(social_post)
|
||||
|
||||
return social_posts
|
||||
@@ -1,7 +1,7 @@
|
||||
from agno.tools import Toolkit
|
||||
from app.api.wrapper_handler import WrapperHandler
|
||||
from app.api.core.social import SocialPost, SocialWrapper
|
||||
from app.api.social import RedditWrapper
|
||||
from app.api.social import *
|
||||
|
||||
|
||||
class SocialAPIsTool(SocialWrapper, Toolkit):
|
||||
@@ -23,7 +23,7 @@ class SocialAPIsTool(SocialWrapper, Toolkit):
|
||||
- RedditWrapper.
|
||||
"""
|
||||
|
||||
wrappers: list[type[SocialWrapper]] = [RedditWrapper]
|
||||
wrappers: list[type[SocialWrapper]] = [RedditWrapper, XWrapper, ChanWrapper]
|
||||
self.handler = WrapperHandler.build_wrappers(wrappers)
|
||||
|
||||
Toolkit.__init__( # type: ignore
|
||||
|
||||
22
tests/api/test_social_4chan.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import re
|
||||
import pytest
|
||||
from app.api.social.chan import ChanWrapper
|
||||
|
||||
@pytest.mark.social
|
||||
@pytest.mark.api
|
||||
class TestChanWrapper:
|
||||
def test_initialization(self):
|
||||
wrapper = ChanWrapper()
|
||||
assert wrapper is not None
|
||||
|
||||
def test_get_top_crypto_posts(self):
|
||||
wrapper = ChanWrapper()
|
||||
posts = wrapper.get_top_crypto_posts(limit=2)
|
||||
assert isinstance(posts, list)
|
||||
assert len(posts) == 2
|
||||
for post in posts:
|
||||
assert post.title != ""
|
||||
assert post.time != ""
|
||||
assert re.match(r'\d{4}-\d{2}-\d{2}', post.time)
|
||||
assert isinstance(post.comments, list)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import re
|
||||
import pytest
|
||||
from app.api.social.reddit import MAX_COMMENTS, RedditWrapper
|
||||
|
||||
@@ -18,6 +19,8 @@ class TestRedditWrapper:
|
||||
assert len(posts) == 2
|
||||
for post in posts:
|
||||
assert post.title != ""
|
||||
assert re.match(r'\d{4}-\d{2}-\d{2}', post.time)
|
||||
|
||||
assert isinstance(post.comments, list)
|
||||
assert len(post.comments) <= MAX_COMMENTS
|
||||
for comment in post.comments:
|
||||
22
tests/api/test_social_x_api.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import os
|
||||
import re
|
||||
import pytest
|
||||
from app.api.social.x import XWrapper
|
||||
|
||||
@pytest.mark.social
|
||||
@pytest.mark.api
|
||||
@pytest.mark.skipif(not os.getenv("X_API_KEY"), reason="X_API_KEY not set in environment variables")
|
||||
class TestXWrapper:
|
||||
def test_initialization(self):
|
||||
wrapper = XWrapper()
|
||||
assert wrapper is not None
|
||||
|
||||
def test_get_top_crypto_posts(self):
|
||||
wrapper = XWrapper()
|
||||
posts = wrapper.get_top_crypto_posts(limit=2)
|
||||
assert isinstance(posts, list)
|
||||
assert len(posts) == 2
|
||||
for post in posts:
|
||||
assert post.title != ""
|
||||
assert re.match(r'\d{4}-\d{2}-\d{2}', post.time)
|
||||
assert isinstance(post.comments, list)
|
||||
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore
Pulire il file che ha troppi commenti, in modo da rendere il codice più leggibile
Rimuovere inoltre la quantità di try non necessaria, dato che se l'API ha dei problemi non voglio che mi restituisca un oggetto vuoto, ma voglio l'errore