mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Update Arret sur images
This commit is contained in:
parent
b9394ff3af
commit
ebcfa3dd17
@ -1,55 +1,196 @@
|
|||||||
from __future__ import unicode_literals
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
|
||||||
__license__ = 'WTFPL'
|
import json
|
||||||
__author__ = '2013, François D. <franek at chicour.net>'
|
from datetime import datetime
|
||||||
__description__ = 'Get some fresh news from Arrêt sur images'
|
|
||||||
|
import mechanize
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
from calibre import browser
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
|
||||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
class ArretSurImages(BasicNewsRecipe):
|
||||||
|
title = 'Arrêt sur Images'
|
||||||
|
description = 'Site français d\'analyse des médias'
|
||||||
class Asi(BasicNewsRecipe):
|
|
||||||
|
|
||||||
title = 'Arrêt sur images'
|
|
||||||
__author__ = 'François D. (aka franek)'
|
|
||||||
description = 'Global news in french from news site "Arrêt sur images"'
|
|
||||||
|
|
||||||
oldest_article = 7.0
|
|
||||||
language = 'fr'
|
language = 'fr'
|
||||||
|
encoding = 'utf-8'
|
||||||
needs_subscription = True
|
needs_subscription = True
|
||||||
|
oldest_article = 7
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
|
|
||||||
simultaneous_downloads = 1
|
|
||||||
timefmt = '[%a, %d %b %Y %I:%M +0200]'
|
|
||||||
cover_url = 'http://www.arretsurimages.net/images/header/menu/menu_1.png'
|
|
||||||
|
|
||||||
use_embedded_content = False
|
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
remove_javascript = True
|
remove_javascript = True
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
('vite dit et gratuit', 'http://www.arretsurimages.net/vite-dit.rss'),
|
('Arrêt sur images', 'https://api.arretsurimages.net/api/public/rss/all-content')
|
||||||
('Toutes les chroniques', 'http://www.arretsurimages.net/chroniques.rss'),
|
|
||||||
('Contenus et dossiers', 'http://www.arretsurimages.net/dossiers.rss'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
conversion_options = {'smarten_punctuation': True}
|
def default_cover(self, cover_file):
|
||||||
|
"""
|
||||||
|
Crée une couverture personnalisée avec le logo ASI
|
||||||
|
"""
|
||||||
|
from qt.core import QColor, QFont, QImage, QPainter, QPen, QRect, Qt
|
||||||
|
|
||||||
remove_tags = [dict(id='vite-titre'), dict(id='header'), dict(id='wrap-connexion'), dict(id='col_right'),
|
from calibre.gui2 import ensure_app, load_builtin_fonts, pixmap_to_data
|
||||||
dict(name='div', attrs={'class': 'bloc-chroniqueur-2'}), dict(id='footercontainer')]
|
try:
|
||||||
|
ensure_app()
|
||||||
|
load_builtin_fonts()
|
||||||
|
|
||||||
def print_version(self, url):
|
today = datetime.now(ZoneInfo('Europe/Paris'))
|
||||||
return url.replace('contenu.php', 'contenu-imprimable.php')
|
wkd = today.weekday()
|
||||||
|
french_weekday = {0:'Lundi',1:'Mardi',2:'Mercredi',3:'Jeudi',4:'Vendredi',5:'Samedi',6:'Dimanche'}
|
||||||
|
french_month = {1:'janvier', 2:'février', 3:'mars', 4:'avril', 5:'mai', 6:'juin',
|
||||||
|
7:'juillet', 8:'août', 9:'septembre', 10:'octobre', 11:'novembre', 12:'décembre'}
|
||||||
|
|
||||||
|
weekday = french_weekday[wkd]
|
||||||
|
month = french_month[today.month]
|
||||||
|
date_str = f"{weekday} {today.day} {month} {today.year}"
|
||||||
|
edition = today.strftime('Édition de %Hh')
|
||||||
|
|
||||||
|
img = QImage(1400, 1920, QImage.Format_RGB888)
|
||||||
|
img.fill(QColor('white'))
|
||||||
|
|
||||||
|
# Dessiner la bordure rouge
|
||||||
|
border_painter = QPainter(img)
|
||||||
|
border_pen = QPen(QColor('red'))
|
||||||
|
border_pen.setWidth(120) # Épaisseur de la bordure
|
||||||
|
border_painter.setPen(border_pen)
|
||||||
|
border_painter.drawRect(10, 10, img.width()-20, img.height()-20) # Marge de 10 pixels
|
||||||
|
border_painter.end()
|
||||||
|
|
||||||
|
logo_url = 'https://www.arretsurimages.net/assets/img/front/logo-asi-grand.png'
|
||||||
|
logo_data = browser().open(logo_url).read()
|
||||||
|
logo = QImage()
|
||||||
|
logo.loadFromData(logo_data)
|
||||||
|
|
||||||
|
logo_width = 800
|
||||||
|
scaled_logo = logo.scaledToWidth(logo_width, Qt.SmoothTransformation)
|
||||||
|
|
||||||
|
x = (img.width() - scaled_logo.width()) // 2
|
||||||
|
y = (img.height() - scaled_logo.height()) // 2 - 100
|
||||||
|
|
||||||
|
p = QPainter(img)
|
||||||
|
p.drawImage(x, y, scaled_logo)
|
||||||
|
p.end()
|
||||||
|
|
||||||
|
p = QPainter(img)
|
||||||
|
p.setPen(QPen(QColor('black')))
|
||||||
|
|
||||||
|
font = QFont('Liberation Sans', 36)
|
||||||
|
p.setFont(font)
|
||||||
|
|
||||||
|
r = QRect(0, y + scaled_logo.height() + 50, img.width(), 100)
|
||||||
|
p.drawText(r, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter, date_str)
|
||||||
|
|
||||||
|
font.setItalic(True)
|
||||||
|
font.setPointSize(32)
|
||||||
|
p.setFont(font)
|
||||||
|
|
||||||
|
r = QRect(0, y + scaled_logo.height() + 150, img.width(), 100)
|
||||||
|
p.drawText(r, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter, edition)
|
||||||
|
|
||||||
|
p.end()
|
||||||
|
|
||||||
|
img_data = pixmap_to_data(img)
|
||||||
|
cover_file.write(img_data)
|
||||||
|
cover_file.flush()
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Erreur lors de la création de la couverture: {e}')
|
||||||
|
return False
|
||||||
|
|
||||||
def get_browser(self):
|
def get_browser(self):
|
||||||
# Need to use robust HTML parser
|
br = BasicNewsRecipe.get_browser(self)
|
||||||
br = BasicNewsRecipe.get_browser(self, use_robust_parser=True)
|
if self.username and self.password:
|
||||||
if self.username is not None and self.password is not None:
|
auth_data = {
|
||||||
br.open('http://www.arretsurimages.net/index.php')
|
'client_id': '1_1e3dazertyukilygfos7ldzertyuof7pfd',
|
||||||
br.select_form(nr=0)
|
'client_secret': '2r8yd4a8un0fn45d93acfr3efrgthzdheifhrehihidg4dk5kds7ds23',
|
||||||
br.form.set_all_readonly(False)
|
'username': self.username,
|
||||||
br['redir'] = 'forum/login.php'
|
'password': self.password,
|
||||||
br['username'] = self.username
|
'grant_type': 'password'
|
||||||
br['password'] = self.password
|
}
|
||||||
br.submit()
|
request = mechanize.Request(
|
||||||
|
'https://api.arretsurimages.net/oauth/v2/token',
|
||||||
|
data=json.dumps(auth_data).encode('utf-8'),
|
||||||
|
headers={'Content-Type': 'application/json', 'Accept': 'application/json'}
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
response = br.open(request)
|
||||||
|
auth_response = json.loads(response.read().decode('utf-8'))
|
||||||
|
if 'access_token' in auth_response:
|
||||||
|
br.addheaders += [('Authorization', f'Bearer {auth_response["access_token"]}')]
|
||||||
|
print('Authentification réussie')
|
||||||
|
else:
|
||||||
|
print('Échec de l\'authentification - Vérifiez vos identifiants')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Erreur lors de l\'authentification: {str(e)}')
|
||||||
return br
|
return br
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
url = article.get('link', article.get('guid'))
|
||||||
|
if url:
|
||||||
|
return url.replace('www.arretsurimages.net/', 'api.arretsurimages.net/api/public/contents/')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def preprocess_raw_html(self, raw_html, url):
|
||||||
|
try:
|
||||||
|
article_data = json.loads(raw_html)
|
||||||
|
authors = ', '.join([a.get('name', '') for a in article_data.get('authors', [])])
|
||||||
|
cover_html = ''
|
||||||
|
if article_data.get('cover') and article_data['cover'].get('formats', {}).get('article_header'):
|
||||||
|
cover_slug = article_data['cover']['slug']
|
||||||
|
cover_url = f'https://api.arretsurimages.net/api/public/media/{cover_slug}/action/show?format=article_header'
|
||||||
|
cover_html = f'<img src="{cover_url}" alt="{article_data.get("title", "")}">'
|
||||||
|
return f'''
|
||||||
|
<html>
|
||||||
|
<head><title>{article_data.get('title', 'Article sans titre')}</title></head>
|
||||||
|
<body>
|
||||||
|
<article>
|
||||||
|
<h1>{article_data.get('title', 'Article sans titre')}</h1>
|
||||||
|
<div class="article-meta">
|
||||||
|
<p>Par {authors or "Auteur inconnu"}</p>
|
||||||
|
</div>
|
||||||
|
{cover_html}
|
||||||
|
<div class="article-content">
|
||||||
|
<p><strong>{article_data.get('lead', '')}</strong></p>
|
||||||
|
{article_data.get('content', '')}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Erreur preprocessing HTML: {str(e)}')
|
||||||
|
return raw_html
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
try:
|
||||||
|
for tag in soup.find_all(['asi-html', 'asi-image', 'asi-video']):
|
||||||
|
if tag.name == 'asi-html' and tag.get('data-html'):
|
||||||
|
tag.replace_with(soup.new_tag('div', attrs={'class': 'asi-content'}).append(tag['data-html']))
|
||||||
|
elif tag.name == 'asi-image':
|
||||||
|
img_data = tag.get('data-image', {})
|
||||||
|
if img_data:
|
||||||
|
try:
|
||||||
|
img_data = json.loads(img_data)
|
||||||
|
if img_data.get('slug'):
|
||||||
|
img_url = f'https://api.arretsurimages.net/api/public/media/{img_data["slug"]}/action/show?format=article_body'
|
||||||
|
img_tag = soup.new_tag('img', src=img_url)
|
||||||
|
if img_data.get('caption'):
|
||||||
|
caption_div = soup.new_tag('div', attrs={'class': 'image-caption'})
|
||||||
|
caption_div.string = img_data['caption']
|
||||||
|
tag.replace_with(img_tag)
|
||||||
|
img_tag.insert_after(caption_div)
|
||||||
|
else:
|
||||||
|
tag.replace_with(img_tag)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Erreur processing image: {str(e)}')
|
||||||
|
tag.decompose()
|
||||||
|
else:
|
||||||
|
tag.decompose()
|
||||||
|
return soup
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Erreur preprocessing HTML: {str(e)}')
|
||||||
|
return soup
|
||||||
|
Loading…
x
Reference in New Issue
Block a user