Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
c2c5bd1396 | |||
9c40b58301 | |||
cd7495a4d9 | |||
de9398ef84 | |||
7a98a0ac84 | |||
298fa75a60 | |||
667a43263d | |||
5d5fc16609 | |||
9c28e99676 | |||
c7f37b164e | |||
a0ed6908cb | |||
9c4d01eba2 | |||
2f0ce4ded4 | |||
249a3c51de | |||
10368df6f9 | |||
47c5c3380f | |||
c9eb733014 | |||
56b35e358e | |||
0ff1f73039 | |||
0214112d7b | |||
4900c4649a | |||
3476872925 | |||
4cfef10989 | |||
354f392c26 | |||
68b5f05928 | |||
d782762e32 | |||
857ce38b57 | |||
7384c85567 | |||
18458d059f | |||
0564ba6f75 | |||
f8291526d2 | |||
8d7911f20c |
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
||||
[submodule "pyfbx"]
|
||||
path = pyfbx
|
||||
url = https://djib.fr/djib/pyfbx.git
|
||||
url = https://framagit.org/djib/pyfbx.git
|
||||
|
@ -7,6 +7,7 @@ import argparse
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
import socket
|
||||
@ -33,15 +34,17 @@ class Movie:
|
||||
self.date = 0
|
||||
self.start_time = 0
|
||||
self.end_time = 0
|
||||
self.year = ''
|
||||
|
||||
def __str__(self):
|
||||
return '{}: {} - {} ({})\n TMDB: {} - {}\n @ {}\n {}'.format(
|
||||
return '{}: {} - {} ({})\n TMDB: {} - {} - {}\n @ {}\n {}'.format(
|
||||
'Today' if self.day == '' else self.day,
|
||||
self.title,
|
||||
self.genre,
|
||||
self.channel,
|
||||
self.rating,
|
||||
self.original_title,
|
||||
self.year,
|
||||
self.url,
|
||||
self.overview
|
||||
)
|
||||
@ -56,15 +59,14 @@ class Movie:
|
||||
|
||||
|
||||
class TVGuideScraper:
|
||||
TV_GUIDE_URL = 'https://www.programme-television.org/{}?bouquet=free'
|
||||
TV_GUIDE_URL = 'https://programme-tv.nouvelobs.com/programme-free/categorie-film/{}/'
|
||||
|
||||
def findAllMovies():
|
||||
movies = []
|
||||
days = deque(['lundi', 'mardi', 'mercredi',
|
||||
'jeudi', 'vendredi', 'samedi', 'dimanche'])
|
||||
offset = datetime.datetime.today().weekday()
|
||||
days.rotate(-1-offset)
|
||||
days.appendleft('')
|
||||
days.rotate(-offset)
|
||||
date = datetime.date.today()
|
||||
for day in days:
|
||||
movies += TVGuideScraper._getMovies(day, date)
|
||||
@ -74,44 +76,45 @@ class TVGuideScraper:
|
||||
|
||||
@staticmethod
|
||||
def _getMovies(day='', date=datetime.date.today()):
|
||||
logging.info('Connecting to {}'.format(TVGuideScraper.TV_GUIDE_URL))
|
||||
r = requests.get(TVGuideScraper.TV_GUIDE_URL.format(day))
|
||||
url = TVGuideScraper.TV_GUIDE_URL.format(day)
|
||||
logging.info('Connecting to {}'.format(url))
|
||||
r = requests.get(url)
|
||||
r.raise_for_status()
|
||||
html = BeautifulSoup(r.text, 'html.parser')
|
||||
movies = []
|
||||
for channel in html.select('.bloc_cnt'):
|
||||
if len(channel.select('em')):
|
||||
for movietag in channel.find_all(TVGuideScraper._tag_is_film):
|
||||
for channel in html.select('.tab_grille'):
|
||||
for movietag in channel.select('.cat-film'):
|
||||
try:
|
||||
movie = Movie()
|
||||
movie.title = \
|
||||
movietag.select('.texte_titre a')[0]['title']
|
||||
movie.genre = movietag.select('.texte_cat a')[0].string
|
||||
movie.channel = channel.select('em')[0]\
|
||||
.string.replace('Programme ', '')
|
||||
movie.title = movietag.select('a.titre')[0].string
|
||||
movie.genre = 'Film' # Genre is not available
|
||||
movie.channel = channel.select('.logo_chaine_g img')[0]\
|
||||
['alt'].replace('Programme ','')
|
||||
movie.day = day.title()
|
||||
movie.date = datetime.date.strftime(date, '%Y-%m-%d')
|
||||
movie.start_time = datetime.datetime.strptime(
|
||||
'{} {}'.format(
|
||||
movie.date,
|
||||
movietag.select('.horaire')[0].string
|
||||
movietag.select('span.t16')[0].string
|
||||
),
|
||||
'%Y-%m-%d %H:%M'
|
||||
'%Y-%m-%d %H.%M'
|
||||
)
|
||||
duration = TVGuideScraper._parse_duration(
|
||||
movietag.select('.texte_cat')[0]
|
||||
.contents[1].strip(' \n\t()')
|
||||
re.search(r'\((.*) mn\)',movietag.text).group(1)
|
||||
)
|
||||
movie.end_time = movie.start_time + duration
|
||||
|
||||
logging.debug('Found movie: {0!r}'.format(movie))
|
||||
movies.append(movie)
|
||||
except:
|
||||
logging.warning('Error parsing movie from tag: {0!r}'.format(movietag))
|
||||
|
||||
return movies
|
||||
|
||||
@staticmethod
|
||||
def _tag_is_film(tag):
|
||||
def _tag_is_movie(tag):
|
||||
"""
|
||||
Helper to check if a tag is a film
|
||||
Helper to check if a tag is a movie
|
||||
"""
|
||||
return (
|
||||
tag.has_attr('data-nature')
|
||||
@ -121,18 +124,12 @@ class TVGuideScraper:
|
||||
|
||||
@staticmethod
|
||||
def _parse_duration(text):
|
||||
match = re.match(r"((?P<hours>\d+)h)?(?P<minutes>\d+)mn", text)
|
||||
if not match:
|
||||
error = "Could not parse duration '{}'".format(text)
|
||||
logging.error(error)
|
||||
raise ValueError(error)
|
||||
hours = int(match.group('hours')) if match.group('hours') else 0
|
||||
minutes = int(match.group('minutes'))
|
||||
return datetime.timedelta(hours=hours, minutes=minutes)
|
||||
minutes = int(text)
|
||||
return datetime.timedelta(minutes=minutes)
|
||||
|
||||
|
||||
class FreeboxMoviePlanner:
|
||||
def __init__(self, movies):
|
||||
def __init__(self, movies, excluded_channels=[], excluded_directory=[]):
|
||||
logging.debug('Opening config file: config.json')
|
||||
with open('config.json') as config_file:
|
||||
self.config = json.load(config_file)
|
||||
@ -140,18 +137,21 @@ class FreeboxMoviePlanner:
|
||||
self.createAuthenticationToken()
|
||||
tmdbsimple.API_KEY = self.config['tmdb-api']
|
||||
self.movies = movies
|
||||
self.excluded_directory = excluded_directory
|
||||
|
||||
logging.info('Opening Freebox session')
|
||||
self.freebox = Fbx(nomdns=True)
|
||||
self.freebox = Fbx()
|
||||
self.freebox.mksession(
|
||||
app_id='FreeboxMoviePlanner',
|
||||
token=self.config['freebox-session-token']
|
||||
)
|
||||
self.getListOfAvailableChannels()
|
||||
self.getListOfAvailableChannels(excluded_channels)
|
||||
self.excludeUnavailableChannels()
|
||||
self.excludeTelevisionFilm()
|
||||
self.excludeTelevisionMovie()
|
||||
self.findMoviesOnTMDB()
|
||||
self.excludeBadRatings()
|
||||
for directory in self.excluded_directory:
|
||||
self.excludeLocalMovies(directory)
|
||||
self.askForUserSelection()
|
||||
self.excludeNotSelected()
|
||||
self.programMovies()
|
||||
@ -159,7 +159,7 @@ class FreeboxMoviePlanner:
|
||||
|
||||
def createAuthenticationToken(self):
|
||||
logging.info('Creating authentication token')
|
||||
self.freebox = Fbx(nomdns=True)
|
||||
self.freebox = Fbx()
|
||||
hostname = socket.gethostname()
|
||||
print("You don't seem to have an authentication token.")
|
||||
print("I will now atempt to create one.")
|
||||
@ -178,12 +178,17 @@ class FreeboxMoviePlanner:
|
||||
result += '>'
|
||||
return result
|
||||
|
||||
def getListOfAvailableChannels(self):
|
||||
def getListOfAvailableChannels(self, excluded_channels):
|
||||
logging.info('Getting the list of available channels')
|
||||
self.channels = {}
|
||||
for channel in self.freebox.Tv.Getting_the_list_of_channels().values():
|
||||
if channel['available']:
|
||||
self.channels[channel['name']] = channel['uuid']
|
||||
if channel['name'] in excluded_channels:
|
||||
logging.debug(
|
||||
"Excluding '{}'".format(channel['name'])
|
||||
)
|
||||
else:
|
||||
self.channels[channel['name'].lower()] = channel['uuid']
|
||||
else:
|
||||
logging.debug("Dropping '{}'".format(channel['name']))
|
||||
logging.debug('Got the following channels: {}'.format(self.channels))
|
||||
@ -217,6 +222,19 @@ class FreeboxMoviePlanner:
|
||||
float(movie.rating) >= self.config['minimum-rating']
|
||||
movie.url = 'https://www.themoviedb.org/movie/{}?language={}' \
|
||||
.format(movie.tmdb_id, self.config['tmdb-language'])
|
||||
try:
|
||||
movie.year = datetime.datetime.strptime(
|
||||
tmdb_details['release_date'], '%Y-%m-%d'
|
||||
).year
|
||||
except (ValueError, KeyError):
|
||||
logging.warning(
|
||||
"No release date for '{!r}'".format(movie)
|
||||
)
|
||||
pass
|
||||
else:
|
||||
logging.warning(
|
||||
"'{!r}' not found on TMDB!".format(movie)
|
||||
)
|
||||
|
||||
def _findMovieOnTMDB(self, movie):
|
||||
logging.info("Searching for '{}' on TMDB".format(movie))
|
||||
@ -228,7 +246,7 @@ class FreeboxMoviePlanner:
|
||||
))
|
||||
return search.results[0]
|
||||
else:
|
||||
logging.warning("'{}' not found on TMDB!".format(movie))
|
||||
logging.info("'{}' not found!".format(movie))
|
||||
return []
|
||||
|
||||
def excludeBadRatings(self):
|
||||
@ -242,15 +260,25 @@ class FreeboxMoviePlanner:
|
||||
logging.info('Dropping movies on unavailable channels: {}'.format(
|
||||
[m for m in self.movies if m.channel not in self.channels]
|
||||
))
|
||||
self.movies = [m for m in self.movies if m.channel in self.channels]
|
||||
self.movies = [m for m in self.movies if m.channel.lower() in self.channels]
|
||||
logging.debug('Kept {}'.format(self.movies))
|
||||
|
||||
def excludeTelevisionFilm(self):
|
||||
logging.info('Dropping television films')
|
||||
def excludeTelevisionMovie(self):
|
||||
logging.info('Dropping television movies')
|
||||
self.movies = [
|
||||
m for m in self.movies if not m.genre.startswith("Téléfilm")
|
||||
]
|
||||
|
||||
def excludeLocalMovies(self, directory):
|
||||
(_, _, filenames) = next(os.walk(directory))
|
||||
clean = lambda t: re.sub(r"( :|\?)", "", t)
|
||||
logging.warning('Dropping movies already recorded: {}'.format(
|
||||
[m for m in self.movies if clean(m.title)+'.m2ts' in filenames]
|
||||
))
|
||||
self.movies = [
|
||||
m for m in self.movies if clean(m.title)+'.m2ts' not in filenames
|
||||
]
|
||||
|
||||
def excludeNotSelected(self):
|
||||
self.movies = [m for m in self.movies if m.user_selected]
|
||||
|
||||
@ -270,19 +298,21 @@ class FreeboxMoviePlanner:
|
||||
|
||||
def checkForConflicts(self):
|
||||
programmed_movies = self.freebox.Pvr.Getting_the_list_of_precords()
|
||||
conflicting_movies = [m for m in programmed_movies if m['conflict']]
|
||||
if conflicting_movies:
|
||||
print(
|
||||
"\n"
|
||||
"!!!!!!!!!\n"
|
||||
"!Warning!\n"
|
||||
"!!!!!!!!!\n"
|
||||
"Conflicting records detected, please "
|
||||
"check your Freebox interface"
|
||||
)
|
||||
logging.info("Conflicting records detected '{}'".format(
|
||||
conflicting_movies
|
||||
))
|
||||
if programmed_movies:
|
||||
conflicting_movies = [m for m in programmed_movies if m['conflict']]
|
||||
if conflicting_movies:
|
||||
print(
|
||||
"\n"
|
||||
"!!!!!!!!!\n"
|
||||
"!Warning!\n"
|
||||
"!!!!!!!!!\n"
|
||||
"Conflicting records detected, please "
|
||||
"check your Freebox interface\n"
|
||||
"http://192.168.1.254/#Fbx.os.app.pvr.app"
|
||||
)
|
||||
logging.info("Conflicting records detected '{}'".format(
|
||||
conflicting_movies
|
||||
))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@ -298,11 +328,45 @@ if __name__ == '__main__':
|
||||
action='store_true',
|
||||
help='Search movies for current day only instead of a full week'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-l', '--log',
|
||||
action='store_true',
|
||||
help='Display more log messages'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-b', '--debug',
|
||||
action='store_true',
|
||||
help='Display even more log messages'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-e', '--exclude',
|
||||
action='append',
|
||||
default=[],
|
||||
help='Exclude the following Channel'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-x', '--exclude-directory',
|
||||
action='append',
|
||||
default=[],
|
||||
help='''Do not display movies available in the following directory.
|
||||
This will prevent you from recording the same movie multiple
|
||||
times.'''
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
print("Working the magic, please wait…")
|
||||
if args.debug:
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
elif args.log:
|
||||
logging.getLogger().setLevel(logging.INFO)
|
||||
if args.day:
|
||||
movies = TVGuideScraper._getMovies()
|
||||
else:
|
||||
movies = TVGuideScraper.findAllMovies()
|
||||
fmp = FreeboxMoviePlanner(movies)
|
||||
|
||||
fmp = FreeboxMoviePlanner(
|
||||
movies,
|
||||
excluded_channels=args.exclude,
|
||||
excluded_directory=args.exclude_directory
|
||||
)
|
||||
input("Press Enter to continue...")
|
||||
|
4
Pipfile
4
Pipfile
@ -5,11 +5,11 @@ name = "pypi"
|
||||
|
||||
[packages]
|
||||
requests = "*"
|
||||
beautifulsoup4 = "*"
|
||||
tmdbsimple = "*"
|
||||
zeroconf = "*"
|
||||
bs4 = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.7"
|
||||
python_version = "3.9"
|
||||
|
76
Pipfile.lock
generated
76
Pipfile.lock
generated
@ -1,11 +1,11 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "b03fc445dafa601842507fc39fc83f3041132934f9ceb06ca0d037b361421c02"
|
||||
"sha256": "90b0ce807d75e401aca384343417ee0c7ba3250bb05b846bd886d476cf56d1b1"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.7"
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
@ -18,77 +18,87 @@
|
||||
"default": {
|
||||
"beautifulsoup4": {
|
||||
"hashes": [
|
||||
"sha256:5279c36b4b2ec2cb4298d723791467e3000e5384a43ea0cdf5d45207c7e97169",
|
||||
"sha256:6135db2ba678168c07950f9a16c4031822c6f4aec75a65e0a97bc5ca09789931",
|
||||
"sha256:dcdef580e18a76d54002088602eba453eec38ebbcafafeaabd8cab12b6155d57"
|
||||
"sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35",
|
||||
"sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25",
|
||||
"sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"
|
||||
],
|
||||
"version": "==4.9.3"
|
||||
},
|
||||
"bs4": {
|
||||
"hashes": [
|
||||
"sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.8.1"
|
||||
"version": "==0.0.1"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50",
|
||||
"sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"
|
||||
"sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
|
||||
"sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
|
||||
],
|
||||
"version": "==2019.9.11"
|
||||
"version": "==2021.5.30"
|
||||
},
|
||||
"chardet": {
|
||||
"charset-normalizer": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
"sha256:88fce3fa5b1a84fdcb3f603d889f723d1dd89b26059d0123ca435570e848d5e1",
|
||||
"sha256:c46c3ace2d744cfbdebceaa3c19ae691f53ae621b39fd7570f59d14fb7f2fd12"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==2.0.3"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||
"sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
|
||||
"sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
|
||||
],
|
||||
"version": "==2.8"
|
||||
"markers": "python_version >= '3'",
|
||||
"version": "==3.2"
|
||||
},
|
||||
"ifaddr": {
|
||||
"hashes": [
|
||||
"sha256:c19c64882a7ad51a394451dabcbbed72e98b5625ec1e79789924d5ea3e3ecb93"
|
||||
"sha256:1f9e8a6ca6f16db5a37d3356f07b6e52344f6f9f7e806d618537731669eb1a94",
|
||||
"sha256:d1f603952f0a71c9ab4e705754511e4e03b02565bc4cec7188ad6415ff534cd3"
|
||||
],
|
||||
"version": "==0.1.6"
|
||||
"version": "==0.1.7"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
|
||||
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
|
||||
"sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
|
||||
"sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.22.0"
|
||||
"version": "==2.26.0"
|
||||
},
|
||||
"soupsieve": {
|
||||
"hashes": [
|
||||
"sha256:605f89ad5fdbfefe30cdc293303665eff2d188865d4dbe4eb510bba1edfbfce3",
|
||||
"sha256:b91d676b330a0ebd5b21719cb6e9b57c57d433671f65b9c28dd3461d9a1ed0b6"
|
||||
"sha256:052774848f448cf19c7e959adf5566904d525f33a3f8b6ba6f6f8f26ec7de0cc",
|
||||
"sha256:c2c1c2d44f158cdbddab7824a9af8c4f83c76b1e23e049479aa432feb6c4c23b"
|
||||
],
|
||||
"version": "==1.9.4"
|
||||
"markers": "python_version >= '3.0'",
|
||||
"version": "==2.2.1"
|
||||
},
|
||||
"tmdbsimple": {
|
||||
"hashes": [
|
||||
"sha256:3383780ae40fbc2b5197feb06496f81f3a5c0ff3336a2a971a51e638fb10c895",
|
||||
"sha256:cd8c5bc3599e803f1f908339b3d010e138722d147f10ed410b3205c72db0c00c"
|
||||
"sha256:2f6f4b762e07e71e222b3200e3b83c4fce8ff61892402a60be925f79d49ab7fd",
|
||||
"sha256:c882112396634bc8d42689fdf347e4a230f6897e5c423fd4d3ab1411dcb4b98f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.2.0"
|
||||
"version": "==2.8.0"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398",
|
||||
"sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86"
|
||||
"sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4",
|
||||
"sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
|
||||
],
|
||||
"version": "==1.25.6"
|
||||
"version": "==1.26.6"
|
||||
},
|
||||
"zeroconf": {
|
||||
"hashes": [
|
||||
"sha256:21d02538ff52fc572e1d785c692b97b8d4374623cb95d593cc06ab92bd5aaf61",
|
||||
"sha256:e0c333b967c48f8b2e5cc94a1d4d28893023fb06dfd797ee384a94cdd1d0eef5"
|
||||
"sha256:5b91d4d93c225f60dbb37915f63c2d1b445b7b39ba17f8da42f51c373d866af4",
|
||||
"sha256:75e6616401f6d4a51f522f558b5d8a329da1407adc3e876134a4533e29acd279"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.23.0"
|
||||
"version": "==0.32.1"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
|
41
Readme.md
41
Readme.md
@ -12,7 +12,7 @@ d'enregistrements avec votre *Freebox*.
|
||||
|
||||
Concrètement, l'outil effectue les opérations suivantes :
|
||||
|
||||
* Récupérer les film de la semaine à partir du [planning *Télé 7 Jours*](https://www.programme-television.org/?bouquet=free)
|
||||
* Récupérer les film de la semaine à partir du [planning *NouvelObs*](https://programme-tv.nouvelobs.com/programme-free/categorie-film/)
|
||||
* Retirer les chaînes auxquelles vous n'avez pas accès
|
||||
* Trouver les notes des films sur [*TMDb*](https://www.themoviedb.org/) (*The Movie Database*)
|
||||
* Exclure les films en dessous d'une certaine note (paramétrable)
|
||||
@ -20,15 +20,18 @@ Concrètement, l'outil effectue les opérations suivantes :
|
||||
* Planifier les enregistrements sur votre *Freebox*.
|
||||
* Vous prévenir si des conflits sont identifiés pour que vous les résolviez depuis l'interface de votre *Freebox*.
|
||||
|
||||

|
||||

|
||||
|
||||
Installation
|
||||
---
|
||||
### À partir de l'exécutable
|
||||
[Téléchargez](https://djib.fr/djib/FreeboxMoviePlanner/releases) le fichier qui correspond à votre système d'exploitation (Linux ou Windows) dans le répertoire `dist` ainsi que le fichier `config.template.json`.
|
||||
~~[Téléchargez](https://git.djib.fr/djib/FreeboxMoviePlanner/releases) le fichier qui correspond à votre système d'exploitation (Linux ou Windows).
|
||||
Extrayez ensuite ce fichier à l'emplacement de votre choix.~~
|
||||
|
||||
L’exécutable n’est plus valable car il utilisait une ancienne version du site de Télé 7 Jours. Si une nouvelle version vous intéresse, n’hésitez pas à [le demander dans un ticket](https://git.djib.fr/djib/FreeboxMoviePlanner/issues).
|
||||
|
||||
### À partir des sources
|
||||
Pour utiliser **FreeboxMoviePlanner** à partir des sources, il vous faut Python, ainsi que les 3 packages suivants (à installer par exemple avec `pip install [nom du packet]` :
|
||||
Pour utiliser **FreeboxMoviePlanner** à partir des sources, il vous faut Python, ainsi que les 3 packages suivants (à installer par exemple avec `pip install [nom du packet]`) :
|
||||
|
||||
* `beautifulsoup4`
|
||||
* `tmdbsimple`
|
||||
@ -36,14 +39,14 @@ Pour utiliser **FreeboxMoviePlanner** à partir des sources, il vous faut Python
|
||||
|
||||
Il vous faut ensuite récupérer le code du projet, le plus simple étant en clonant le dépôt git.
|
||||
```bash
|
||||
git clone --recurse-submodules https://djib.fr/djib/FreeboxMoviePlanner.git
|
||||
git clone --recurse-submodules https://git.djib.fr/djib/FreeboxMoviePlanner.git
|
||||
```
|
||||
|
||||
Configuration
|
||||
---
|
||||
Ensuite, il vous faut créer un fichier de conf `config.json`. Vous pouvez tout simplement renommer le fichier `config.template.json`.
|
||||
|
||||
Dans ce fichier vous devrez renseigner une clef API TMDb. Pour cela vous aurez besoin d'ouvrir un compte sur leur site et de [demander une clef API](https://www.themoviedb.org/settings/api).
|
||||
Dans ce fichier vous devrez renseigner une clef API TMDb. Pour cela vous aurez besoin d'[ouvrir un compte](https://www.themoviedb.org/account/signup) sur leur site et de [demander une clef API](https://www.themoviedb.org/settings/api).
|
||||
|
||||
Le fichier de config vous permet aussi de configurer la marge avant et après chaque enregistrement, ou la note en dessous de laquelle les films ne s'afficheront pas.
|
||||
|
||||
@ -51,5 +54,27 @@ Exécution
|
||||
---
|
||||
L'outil devrait vous afficher rapidement le petit texte `Working the magic, please wait…` puis, après environ une minute (ou plus si votre réseau est lent), le détail des films.
|
||||
|
||||
À la première exécution, l'outil vous demandera aussi d'autoriser le script sur votre Freebox (*Please go to your Freebox and accept the authentication.*)
|
||||
À ce moment, l'affichage de votre boîtier *Freebox* vous demandera alors de valider cette demande d'authentification. Vous devez donc physiquement valider l'accès à partir de votre box (sur la V6, il s'agit de presser la flèche de droite).
|
||||
À la première exécution, l'outil vous demandera aussi d'autoriser le script sur votre Freebox (`Please go to your Freebox and accept the authentication.`)
|
||||
À ce moment, l'affichage de votre boîtier *Freebox* vous demandera de valider cette demande d'authentification. Vous devez donc physiquement valider l'accès à partir de votre box (sur la V6, il s'agit de presser la flèche de droite).
|
||||
|
||||
Notez que les films de *Canal+* s'afficheront par défaut. La *Freebox* indique que la chaîne est disponible, probablement car elle est parfois visible en clair. Vous pouvez forcer son exclusion avec le paramètre `-e Canal+`.
|
||||
|
||||
Enjoy!
|
||||
|
||||
Documentation
|
||||
---
|
||||
```shell
|
||||
usage: FreeboxMoviePlanner.py [-h] [-d] [-l] [-e EXCLUDE] [-x EXCLUDE_DIRECTORY]
|
||||
|
||||
Schedule movie recordings on your Freebox
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-d, --day Search movies for current day only instead of a full week
|
||||
-l, --log Display more log messages
|
||||
-b, --debug Display even more log messages
|
||||
-e EXCLUDE, --exclude EXCLUDE
|
||||
Exclude the following Channel
|
||||
-x EXCLUDE_DIRECTORY, --exclude-directory EXCLUDE_DIRECTORY
|
||||
Do not display movies available in the following directory. This will prevent you from recording the same movie multiple times.
|
||||
```
|
||||
|
2
pyfbx
2
pyfbx
Submodule pyfbx updated: 69ae89806d...5cbc535286
Reference in New Issue
Block a user