14 socials integration #34
@@ -2,6 +2,8 @@
|
|||||||
# Infatti scegliamo l'immagine ufficiale di uv che ha già tutto configurato
|
# Infatti scegliamo l'immagine ufficiale di uv che ha già tutto configurato
|
||||||
FROM ghcr.io/astral-sh/uv:python3.12-alpine
|
FROM ghcr.io/astral-sh/uv:python3.12-alpine
|
||||||
|
|
||||||
|
RUN apk add --update npm
|
||||||
|
RUN npm install -g rettiwt-api
|
||||||
# Dopo aver definito la workdir mi trovo già in essa
|
# Dopo aver definito la workdir mi trovo già in essa
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ dependencies = [
|
|||||||
|
|
||||||
|
|
|||||||
# API di social media
|
# API di social media
|
||||||
"praw", # Reddit
|
"praw", # Reddit
|
||||||
"docker", # Necessario per usare Rettiwt per X
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
|
|||||||
@@ -43,97 +43,60 @@ class ChanWrapper(SocialWrapper):
|
|||||||
if 'sticky' in thread:
|
if 'sticky' in thread:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
# print(thread)
|
|
||||||
# Otteniamo la data
|
|
||||||
time: str = thread['now']
|
time: str = thread['now']
|
||||||
# Otteniamo dalla data il mese (primi 2 caratteri)
|
|
||||||
month: str = time[:2]
|
month: str = time[:2]
|
||||||
# Otteniamo dalla data il giorno (caratteri 4 e 5)
|
|
||||||
day: str = time[4:6]
|
day: str = time[4:6]
|
||||||
# Otteniamo dalla data l'anno (caratteri 7 e 8)
|
|
||||||
year: str = time[7:9]
|
year: str = time[7:9]
|
||||||
# Ricreiamo la data completa come dd/mm/yy
|
|
||||||
time: str = day + '/' + month + '/' + year
|
time: str = day + '/' + month + '/' + year
|
||||||
|
|
||||||
# Otteniamo il nome dell'utente
|
|
||||||
name: str = thread['name']
|
name: str = thread['name']
|
||||||
# Proviamo a recuperare il titolo
|
|
||||||
try:
|
try:
|
||||||
# Otteniamo il titolo del thread contenuto nella key "sub"
|
|
||||||
title: str = thread['sub']
|
title: str = thread['sub']
|
||||||
# Ripuliamo la stringa
|
|
||||||
# Decodifichiamo caratteri ed entità HTML
|
|
||||||
html_entities = html.unescape(title)
|
html_entities = html.unescape(title)
|
||||||
# Rimuoviamo caratteri HTML
|
|
||||||
soup = BeautifulSoup(html_entities, 'html.parser')
|
soup = BeautifulSoup(html_entities, 'html.parser')
|
||||||
title = soup.get_text(separator=" ")
|
title = soup.get_text(separator=" ")
|
||||||
# Rimuoviamo backlash e doppi slash
|
|
||||||
title = re.sub(r"[\\/]+", "/", title)
|
title = re.sub(r"[\\/]+", "/", title)
|
||||||
# Rimuoviamo spazi in piú
|
|
||||||
title = re.sub(r"\s+", " ", title).strip()
|
title = re.sub(r"\s+", " ", title).strip()
|
||||||
# Aggiungiamo il nome dell'utente al titolo
|
|
||||||
title = name + " posted: " + title
|
title = name + " posted: " + title
|
||||||
except:
|
except:
|
||||||
title: str = name + " posted"
|
title: str = name + " posted"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Otteniamo il commento del thread contenuto nella key "com"
|
|
||||||
thread_description: str = thread['com']
|
thread_description: str = thread['com']
|
||||||
# Ripuliamo la stringa
|
|
||||||
# Decodifichiamo caratteri ed entità HTML
|
|
||||||
html_entities = html.unescape(thread_description)
|
html_entities = html.unescape(thread_description)
|
||||||
# Rimuoviamo caratteri HTML
|
|
||||||
soup = BeautifulSoup(html_entities, 'html.parser')
|
soup = BeautifulSoup(html_entities, 'html.parser')
|
||||||
thread_description = soup.get_text(separator=" ")
|
thread_description = soup.get_text(separator=" ")
|
||||||
# Rimuoviamo backlash e doppi slash
|
|
||||||
thread_description = re.sub(r"[\\/]+", "/", thread_description)
|
thread_description = re.sub(r"[\\/]+", "/", thread_description)
|
||||||
# Rimuoviamo spazi in piú
|
|
||||||
thread_description = re.sub(r"\s+", " ", thread_description).strip()
|
thread_description = re.sub(r"\s+", " ", thread_description).strip()
|
||||||
except:
|
except:
|
||||||
thread_description = None
|
thread_description = None
|
||||||
# Creiamo la lista delle risposte al thread
|
|
||||||
try:
|
try:
|
||||||
response_list: list[dict] = thread['last_replies']
|
response_list: list[dict] = thread['last_replies']
|
||||||
except:
|
except:
|
||||||
response_list: list[dict] = []
|
response_list: list[dict] = []
|
||||||
# Creiamo la lista che conterrà i commenti
|
|
||||||
comments_list: list[SocialComment] = []
|
comments_list: list[SocialComment] = []
|
||||||
|
|
||||||
# Otteniamo i primi 5 commenti
|
# Otteniamo i primi 5 commenti
|
||||||
i = 0
|
i = 0
|
||||||
for response in response_list:
|
for response in response_list:
|
||||||
# Otteniamo la data
|
|
||||||
time: str = response['now']
|
time: str = response['now']
|
||||||
# print(time)
|
|
||||||
# Otteniamo dalla data il mese (primi 2 caratteri)
|
|
||||||
month: str = time[:2]
|
month: str = time[:2]
|
||||||
# Otteniamo dalla data il giorno (caratteri 4 e 5)
|
|
||||||
day: str = time[3:5]
|
day: str = time[3:5]
|
||||||
# Otteniamo dalla data l'anno (caratteri 7 e 8)
|
|
||||||
year: str = time[6:8]
|
year: str = time[6:8]
|
||||||
# Ricreiamo la data completa come dd/mm/yy
|
|
||||||
time: str = day + '/' + month + '/' + year
|
time: str = day + '/' + month + '/' + year
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Otteniamo il commento della risposta contenuto nella key "com"
|
|
||||||
comment_description: str = response['com']
|
comment_description: str = response['com']
|
||||||
# Ripuliamo la stringa
|
|
||||||
# Decodifichiamo caratteri ed entità HTML
|
|
||||||
html_entities = html.unescape(comment_description)
|
html_entities = html.unescape(comment_description)
|
||||||
# Rimuoviamo caratteri HTML
|
|
||||||
soup = BeautifulSoup(html_entities, 'html.parser')
|
soup = BeautifulSoup(html_entities, 'html.parser')
|
||||||
comment_description = soup.get_text(separator=" ")
|
comment_description = soup.get_text(separator=" ")
|
||||||
# Rimuoviamo backlash e doppi slash
|
|
||||||
comment_description = re.sub(r"[\\/]+", "/", comment_description)
|
comment_description = re.sub(r"[\\/]+", "/", comment_description)
|
||||||
# Rimuoviamo spazi in piú
|
|
||||||
comment_description = re.sub(r"\s+", " ", comment_description).strip()
|
comment_description = re.sub(r"\s+", " ", comment_description).strip()
|
||||||
except:
|
except:
|
||||||
comment_description = None
|
comment_description = None
|
||||||
# Se la descrizione del commento non esiste, passiamo al commento successivo
|
|
||||||
if comment_description is None:
|
if comment_description is None:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
# Creiamo il SocialComment
|
|
||||||
social_comment: SocialComment = SocialComment(
|
social_comment: SocialComment = SocialComment(
|
||||||
time=time,
|
time=time,
|
||||||
description=comment_description
|
description=comment_description
|
||||||
@@ -145,7 +108,6 @@ class ChanWrapper(SocialWrapper):
|
|||||||
if thread_description is None:
|
if thread_description is None:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
# Creiamo il SocialPost
|
|
||||||
social_post: SocialPost = SocialPost(
|
social_post: SocialPost = SocialPost(
|
||||||
time=time,
|
time=time,
|
||||||
title=title,
|
title=title,
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ https://www.npmjs.com/package/rettiwt-api
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import docker
|
|
||||||
import json
|
import json
|
||||||
from .base import SocialWrapper, SocialPost, SocialComment
|
from .base import SocialWrapper, SocialPost
|
||||||
|
from shutil import which
|
||||||
|
import subprocess
|
||||||
class XWrapper(SocialWrapper):
|
class XWrapper(SocialWrapper):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
'''
|
'''
|
||||||
@@ -26,10 +27,13 @@ class XWrapper(SocialWrapper):
|
|||||||
]
|
]
|
||||||
self.api_key = os.getenv("X_API_KEY")
|
self.api_key = os.getenv("X_API_KEY")
|
||||||
assert self.api_key, "X_API_KEY environment variable not set"
|
assert self.api_key, "X_API_KEY environment variable not set"
|
||||||
|
'''
|
||||||
# Connection to the docker deamon
|
# Connection to the docker deamon
|
||||||
self.client = docker.from_env()
|
self.client = docker.from_env()
|
||||||
# Connect with the relative container
|
# Connect with the relative container
|
||||||
self.container = self.client.containers.get("node_rettiwt")
|
self.container = self.client.containers.get("node_rettiwt")
|
||||||
|
'''
|
||||||
|
assert which('rettiwt') is not None, "Command `rettiwt` not installed"
|
||||||
self.social_posts: list[SocialPost] = []
|
self.social_posts: list[SocialPost] = []
|
||||||
def get_top_crypto_posts(self, limit = 5) -> list[SocialPost]: #-> list[SocialPost]:
|
def get_top_crypto_posts(self, limit = 5) -> list[SocialPost]: #-> list[SocialPost]:
|
||||||
'''
|
'''
|
||||||
@@ -38,7 +42,8 @@ class XWrapper(SocialWrapper):
|
|||||||
social_posts: list[SocialPost] = []
|
social_posts: list[SocialPost] = []
|
||||||
for user in self.users:
|
for user in self.users:
|
||||||
# This currently doesn't work as intended since it returns the posts in random order
|
# This currently doesn't work as intended since it returns the posts in random order
|
||||||
tweets = self.container.exec_run("rettiwt -k" + self.api_key + " tweet search -f " + str(user), tty=True)
|
# tweets = self.container.exec_run("rettiwt -k" + self.api_key + " tweet search -f " + str(user), tty=True)
|
||||||
|
tweets = subprocess.run("rettiwt -k" + self.api_key + " tweet search -f " + str(user))
|
||||||
tweets = tweets.output.decode()
|
tweets = tweets.output.decode()
|
||||||
tweets = json.loads(tweets)
|
tweets = json.loads(tweets)
|
||||||
tweets: list[dict] = tweets['list']
|
tweets: list[dict] = tweets['list']
|
||||||
|
|||||||
39
uv.lock
generated
39
uv.lock
generated
@@ -377,6 +377,17 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/40/cd/ef820662e0d87f46b829bba7e2324c7978e0153692bbd2f08f7746049708/ddgs-9.6.0-py3-none-any.whl", hash = "sha256:24120f1b672fd3a28309db029e7038eb3054381730aea7a08d51bb909dd55520", size = 41558, upload-time = "2025-09-17T13:27:08.99Z" },
|
{ url = "https://files.pythonhosted.org/packages/40/cd/ef820662e0d87f46b829bba7e2324c7978e0153692bbd2f08f7746049708/ddgs-9.6.0-py3-none-any.whl", hash = "sha256:24120f1b672fd3a28309db029e7038eb3054381730aea7a08d51bb909dd55520", size = 41558, upload-time = "2025-09-17T13:27:08.99Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deepseek"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "requests" },
|
||||||
|
]
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/7b/bede06edf1a25a6ab06553b15f6abf8e912848dfa5f68514720d3e388550/deepseek-1.0.0-py3-none-any.whl", hash = "sha256:ee4175bfcb7ac1154369dbd86a4d8bc1809f6fa20e3e7baa362544567197cb3f", size = 4542, upload-time = "2025-01-03T08:06:23.887Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "distro"
|
name = "distro"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
@@ -395,20 +406,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },
|
{ url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "docker"
|
|
||||||
version = "7.1.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
|
||||||
{ name = "requests" },
|
|
||||||
{ name = "urllib3" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/91/9b/4a2ea29aeba62471211598dac5d96825bb49348fa07e906ea930394a83ce/docker-7.1.0.tar.gz", hash = "sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c", size = 117834, upload-time = "2024-05-23T11:13:57.216Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e3/26/57c6fb270950d476074c087527a558ccb6f4436657314bfb6cdf484114c4/docker-7.1.0-py3-none-any.whl", hash = "sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0", size = 147774, upload-time = "2024-05-23T11:13:55.01Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "docstring-parser"
|
name = "docstring-parser"
|
||||||
version = "0.17.0"
|
version = "0.17.0"
|
||||||
@@ -1360,16 +1357,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
|
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pywin32"
|
|
||||||
version = "311"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyyaml"
|
name = "pyyaml"
|
||||||
version = "6.0.3"
|
version = "6.0.3"
|
||||||
@@ -1677,7 +1664,7 @@ dependencies = [
|
|||||||
{ name = "agno" },
|
{ name = "agno" },
|
||||||
{ name = "coinbase-advanced-py" },
|
{ name = "coinbase-advanced-py" },
|
||||||
{ name = "ddgs" },
|
{ name = "ddgs" },
|
||||||
{ name = "docker" },
|
{ name = "deepseek" },
|
||||||
{ name = "dotenv" },
|
{ name = "dotenv" },
|
||||||
{ name = "gnews" },
|
{ name = "gnews" },
|
||||||
{ name = "google-genai" },
|
{ name = "google-genai" },
|
||||||
@@ -1696,7 +1683,7 @@ requires-dist = [
|
|||||||
{ name = "agno" },
|
{ name = "agno" },
|
||||||
{ name = "coinbase-advanced-py" },
|
{ name = "coinbase-advanced-py" },
|
||||||
{ name = "ddgs" },
|
{ name = "ddgs" },
|
||||||
{ name = "docker" },
|
{ name = "deepseek" },
|
||||||
{ name = "dotenv" },
|
{ name = "dotenv" },
|
||||||
{ name = "gnews" },
|
{ name = "gnews" },
|
||||||
{ name = "google-genai" },
|
{ name = "google-genai" },
|
||||||
|
|||||||
Reference in New Issue
Block a user
Come per il file x.py, è meglio usare direttamente il comando della CMD