#!/usr/bin/env python3 from argparse import ArgumentParser import datetime as dt import bs4 import os from config import conf from models import Song, AirCast, DoesNotExist from utils import http_get import webapp # ---------------------------------------------------------------------- # Get song informations last_ten_url = 'https://radiobalises.com/Play-list/last10.html' def get_last_ten(): response = http_get(last_ten_url) soup = bs4.BeautifulSoup(response.content, 'html5lib') dates = soup.select('p.rldj-cell span.post-date') for elem in dates: song_dt = dt.datetime.fromisoformat(elem.text) artist, title = [x.strip() for x in elem.previous.previous.split(' - ', 1)] song, _ = Song.get_or_create(artist=artist, title=title) # get_or_create does not play nice with the unique constraint on the date # so we use a simple try/except instead try: aircast = AirCast.get(date=song_dt, song=song) except DoesNotExist: aircast = AirCast.create(date=song_dt, song=song) line_template = '{:<10} | {:<25} {:<40}' print(line_template.format(str(song_dt), artist, title)) # ---------------------------------------------------------------------- # Search song def search_songs_between(start_dt, end_dt): query = AirCast\ .select()\ .order_by(AirCast.date)\ .where(AirCast.date.between(start_dt, end_dt)) return [x for x in query] def search_song(day, hour): # query must be a datetime # we search the songs withing the hour specified start_dt = dt.datetime.combine(day, dt.time(hour=hour)) delta = dt.timedelta(hours=1) return search_songs_between(start_dt, start_dt + delta) def print_aircast(x): line_template = '{:<10} | {:<25} {:<40}' print(line_template.format(str(x.date), x.song.artist, x.song.title)) # ---------------------------------------------------------------------- # Argument parsing # use a decorator to simplify argparse usage, as suggested by # https://mike.depalatis.net/blog/simplifying-argparse.html cli = ArgumentParser(description='Balises') subparsers = cli.add_subparsers(dest="subcommand") def subcommand(args=[], parent=subparsers): def decorator(func): parser = parent.add_parser(func.__name__, description=func.__doc__) for arg in args: parser.add_argument(*arg[0], **arg[1]) parser.set_defaults(func=func) return decorator def argument(*name_or_flags, **kwargs): return ([*name_or_flags], kwargs) @subcommand([argument('day', help='Day of the song'), argument('hour', help='Hour the song was played')]) def search(args): results = search_song(dt.datetime.fromisoformat(args.day), int(args.hour)) for res in results: print_aircast(res) @subcommand() def update(args): get_last_ten() @subcommand() def serve(args): webapp.run(host=conf['server'].get('host', 'localhost'), port=conf['server'].getint('port', 9980), debug=conf['server'].getboolean('debug', False), reloader=conf['server'].getboolean('reloader', False)) # ---------------------------------------------------------------------- # Main def main(): args = cli.parse_args() if args.subcommand is None: cli.print_help() else: args.func(args) if __name__ == '__main__': main()