mirror of
https://github.com/Findus23/RadioStats.git
synced 2024-09-09 04:23:47 +02:00
major overhaul
- use new ORF API - better structured fetchers - easier channel metadata
This commit is contained in:
parent
654962735d
commit
d286059289
17 changed files with 373 additions and 588 deletions
366
channelInfo.py
366
channelInfo.py
|
@ -1,238 +1,134 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class ChannelData:
|
||||
shortname: str
|
||||
stationname: str
|
||||
has_data: bool
|
||||
primary_color: str
|
||||
secondary_color: str
|
||||
|
||||
|
||||
channels = {
|
||||
"oe1": {
|
||||
"shortname": "oe1",
|
||||
"streamurl": "//oe1shoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/oe1.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/oe1infos.html",
|
||||
"aticon": "./images/oe1-aticon.png",
|
||||
"statncss": "./css/oe1.css",
|
||||
"stationname": "Radio Österreich 1",
|
||||
"cHasData": False,
|
||||
"cPrimaryColor": "#b11a1a",
|
||||
"cSecondaryColor": "#ffffff",
|
||||
"cStationName": "Radio Ö1"
|
||||
"oe1": ChannelData(
|
||||
shortname="oe1",
|
||||
stationname="Radio Ö1",
|
||||
has_data=True,
|
||||
primary_color="#b11a1a",
|
||||
secondary_color="#ffffff"
|
||||
),
|
||||
"oe3": ChannelData(
|
||||
shortname="oe3",
|
||||
has_data=True,
|
||||
primary_color="#002350",
|
||||
secondary_color="#E10032",
|
||||
stationname="Hitradio Ö3"
|
||||
|
||||
},
|
||||
"oe3": {
|
||||
"shortname": "oe3",
|
||||
"streamurl": "//oe3shoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "http://ms01.oe3.fm/oe3metafiles/RMX/RMWEB.PHP?Res=200&Format=json&callback=onair&Type=long",
|
||||
"curProgram": "http://ms01.oe3.fm/oe3metafiles/ModAK/ShowInfo.php?ImgRes=HD&InfoType=Full&Format=json&callback=sendung",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/oe3infos.html",
|
||||
"aticon": "./images/oe3-aticon.png",
|
||||
"statncss": "./css/oe3b.css",
|
||||
"chcolor": "#f04040",
|
||||
"stationname": "hitradio Ö3",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#002350",
|
||||
"cSecondaryColor": "#E10032",
|
||||
"cStationName": "Hitradio Ö3"
|
||||
|
||||
},
|
||||
"fm4": {
|
||||
"shortname": "fm4",
|
||||
"streamurl": "//fm4shoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/fm4.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=Wochen-Plan-Fm4.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/fm4infos.html",
|
||||
"aticon": "./images/fm4-aticon.png",
|
||||
"statncss": "./css/fm4b.css",
|
||||
"stationname": "Radio FM4",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#FFE500",
|
||||
"cSecondaryColor": "#000000",
|
||||
},
|
||||
"bgl": {
|
||||
"shortname": "bgl",
|
||||
"streamurl": "//oe2bshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/bgl.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-bgl.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/bglinfos.html",
|
||||
"aticon": "./images/bgl-aticon.png",
|
||||
"anicon": "./images/bgl-aticon-128.png",
|
||||
"statncss": "./css/bgl.css",
|
||||
"stationname": "Radio Burgenland",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#ffa60f",
|
||||
"cSecondaryColor": "#d32824"
|
||||
},
|
||||
"ktn": {
|
||||
"shortname": "ktn",
|
||||
"streamurl": "//oe2kshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/ktn.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-ktn.xml",
|
||||
"leftbuttonstring": "Tracklist",
|
||||
"midbuttonstring": "",
|
||||
"infodata": "./infos/ktninfos.html",
|
||||
"aticon": "./images/ktn-aticon.png",
|
||||
"statncss": "./css/ktn.css",
|
||||
"stationname": "Radio Kärnten",
|
||||
"cHasData": False,
|
||||
"cPrimaryColor": "#bc1716",
|
||||
"cSecondaryColor": "#ffcd00"
|
||||
},
|
||||
"noe": {
|
||||
"shortname": "noe",
|
||||
"streamurl": "//oe2nshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/noe.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-noe.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/noeinfos.html",
|
||||
"aticon": "./images/noe-aticon.png",
|
||||
"statncss": "./css/noe.css",
|
||||
"stationname": "Radio Niederösterreich",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#002777",
|
||||
"cSecondaryColor": "#ffcd00"
|
||||
},
|
||||
"ooe": {
|
||||
"shortname": "ooe",
|
||||
"streamurl": "//oe2oshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/ooe.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-ooe.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "",
|
||||
"infodata": "./infos/ooeinfos.html",
|
||||
"aticon": "./images/ooe-aticon.png",
|
||||
"statncss": "./css/ooe.css",
|
||||
"stationname": "Radio Oberösterreich",
|
||||
"deskstream": "http://orfradio.liwest.at/liveHQ.m3u",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#bc1716",
|
||||
"cSecondaryColor": "#ffffff"
|
||||
},
|
||||
"sbg": {
|
||||
"shortname": "sbg",
|
||||
"streamurl": "//oe2sshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/sbg.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-sbg.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "",
|
||||
"infodata": "./infos/sbginfos.html",
|
||||
"aticon": "./images/sbg-aticon.png",
|
||||
"splash": "./images/sbg-splash.png",
|
||||
"statncss": "./css/sbg.css",
|
||||
"stationname": "Radio Salzburg",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#bc1716",
|
||||
"cSecondaryColor": "#ffffff"
|
||||
},
|
||||
"stm": {
|
||||
"shortname": "stm",
|
||||
"streamurl": "//oe2stshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/stmk.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-stm.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/stminfos.html",
|
||||
"aticon": "./images/stm-aticon.png",
|
||||
"statncss": "./css/stm.css",
|
||||
"stationname": "Radio Steiermark",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#006843",
|
||||
"cSecondaryColor": "#ffffff"
|
||||
},
|
||||
"tir": {
|
||||
"shortname": "tir",
|
||||
"streamurl": "//oe2tshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/tir.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-tir.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/tirinfos.html",
|
||||
"aticon": "./images/tir-aticon.png",
|
||||
"statncss": "./css/tir.css",
|
||||
"stationname": "Radio Tirol",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#bc1716",
|
||||
"cSecondaryColor": "#ffffff"
|
||||
},
|
||||
"vbg": {
|
||||
"shortname": "vbg",
|
||||
"streamurl": "//oe2vshoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/vbg.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-vbg.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/vbginfos.html",
|
||||
"aticon": "./images/vbg-aticon.png",
|
||||
"statncss": "./css/vbg.css",
|
||||
"stationname": "Radio Vorarlberg",
|
||||
"cHasData": False,
|
||||
"cPrimaryColor": "#bc1716",
|
||||
"cSecondaryColor": "#ffffff"
|
||||
},
|
||||
"wie": {
|
||||
"shortname": "wie",
|
||||
"streamurl": "//oe2w2shoutcast.sf.apa.at/;",
|
||||
"strmtype": "audio/mpeg",
|
||||
"tracklist": "//hop.orf.at/img-trackservice/wien.js",
|
||||
"curProgram": "https://tube.orf.at/broadcastSchedule/currentBroadcast.jsonp?scheme=sendungsplan-wie.xml",
|
||||
"leftbuttonstring": "Hitlist",
|
||||
"midbuttonstring": "Podcasts",
|
||||
"infodata": "./infos/wieinfos.html",
|
||||
"aticon": "./images/wie-aticon.png",
|
||||
"splash": "./images/wie-splash.png",
|
||||
"statncss": "./css/wie.css",
|
||||
"stationname": "Radio Wien",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#ee7e01",
|
||||
"cSecondaryColor": "#552382"
|
||||
},
|
||||
"kht": {
|
||||
"shortname": "kht",
|
||||
"stationname": "Kronehit",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#000000",
|
||||
"cSecondaryColor": "#b89c4f"
|
||||
},
|
||||
"886": {
|
||||
"shortname": "886",
|
||||
"stationname": "Radio 88.6",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#123e6b",
|
||||
"cSecondaryColor": "#ffe116"
|
||||
},
|
||||
"ara": {
|
||||
"shortname": "ara",
|
||||
"stationname": "Radio Arabella",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#003e88",
|
||||
"cSecondaryColor": "#e6007e"
|
||||
},
|
||||
"eng": {
|
||||
"shortname": "eng",
|
||||
"stationname": "Engergy Wien/Nö/Bgld",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "#000000",
|
||||
"cSecondaryColor": "#E2001A"
|
||||
},
|
||||
"all": {
|
||||
"shortname": "all",
|
||||
"stationname": "Alle",
|
||||
"cHasData": True,
|
||||
"cPrimaryColor": "black",
|
||||
"cSecondaryColor": "white"
|
||||
}
|
||||
),
|
||||
"fm4": ChannelData(
|
||||
shortname="fm4",
|
||||
stationname="Radio FM4",
|
||||
has_data=True,
|
||||
primary_color="#FFE500",
|
||||
secondary_color="#000000",
|
||||
),
|
||||
"bgl": ChannelData(
|
||||
shortname="bgl",
|
||||
stationname="Radio Burgenland",
|
||||
has_data=True,
|
||||
primary_color="#ffa60f",
|
||||
secondary_color="#d32824"
|
||||
),
|
||||
"ktn": ChannelData(
|
||||
shortname="ktn",
|
||||
stationname="Radio Kärnten",
|
||||
has_data=True,
|
||||
primary_color="#bc1716",
|
||||
secondary_color="#ffcd00"
|
||||
),
|
||||
"noe": ChannelData(
|
||||
shortname="noe",
|
||||
stationname="Radio Niederösterreich",
|
||||
has_data=True,
|
||||
primary_color="#002777",
|
||||
secondary_color="#ffcd00"
|
||||
),
|
||||
"ooe": ChannelData(
|
||||
shortname="ooe",
|
||||
stationname="Radio Oberösterreich",
|
||||
has_data=True,
|
||||
primary_color="#bc1716",
|
||||
secondary_color="#ffffff"
|
||||
),
|
||||
"sbg": ChannelData(
|
||||
shortname="sbg",
|
||||
stationname="Radio Salzburg",
|
||||
has_data=True,
|
||||
primary_color="#bc1716",
|
||||
secondary_color="#ffffff"
|
||||
),
|
||||
"stm": ChannelData(
|
||||
shortname="stm",
|
||||
stationname="Radio Steiermark",
|
||||
has_data=True,
|
||||
primary_color="#006843",
|
||||
secondary_color="#ffffff"
|
||||
),
|
||||
"tir": ChannelData(
|
||||
shortname="tir",
|
||||
stationname="Radio Tirol",
|
||||
has_data=True,
|
||||
primary_color="#bc1716",
|
||||
secondary_color="#ffffff"
|
||||
),
|
||||
"vbg": ChannelData(
|
||||
shortname="vbg",
|
||||
stationname="Radio Vorarlberg",
|
||||
has_data=True,
|
||||
primary_color="#bc1716",
|
||||
secondary_color="#ffffff"
|
||||
),
|
||||
"wie": ChannelData(
|
||||
shortname="wie",
|
||||
stationname="Radio Wien",
|
||||
has_data=True,
|
||||
primary_color="#ee7e01",
|
||||
secondary_color="#552382"
|
||||
),
|
||||
"kht": ChannelData(
|
||||
shortname="kht",
|
||||
stationname="Kronehit",
|
||||
has_data=True,
|
||||
primary_color="#000000",
|
||||
secondary_color="#b89c4f"
|
||||
),
|
||||
"886": ChannelData(
|
||||
shortname="886",
|
||||
stationname="Radio 88.6",
|
||||
has_data=True,
|
||||
primary_color="#123e6b",
|
||||
secondary_color="#ffe116"
|
||||
),
|
||||
"ara": ChannelData(
|
||||
shortname="ara",
|
||||
stationname="Radio Arabella",
|
||||
has_data=True,
|
||||
primary_color="#003e88",
|
||||
secondary_color="#e6007e"
|
||||
),
|
||||
"eng": ChannelData(
|
||||
shortname="eng",
|
||||
stationname="Engergy Wien/Nö/Bgld",
|
||||
has_data=True,
|
||||
primary_color="#000000",
|
||||
secondary_color="#E2001A"
|
||||
),
|
||||
"all": ChannelData(
|
||||
shortname="all",
|
||||
stationname="Alle",
|
||||
has_data=True,
|
||||
primary_color="black",
|
||||
secondary_color="white"
|
||||
),
|
||||
}
|
||||
|
|
12
create.py
12
create.py
|
@ -7,12 +7,6 @@ for i in [Channel, Song, Play]:
|
|||
i.create_table()
|
||||
|
||||
for id, channel in channelInfo.channels.items():
|
||||
if "streamurl" in channel:
|
||||
streamurl = "https:" + channel["streamurl"].replace(";", "")
|
||||
else:
|
||||
streamurl = None
|
||||
if "cStationName" in channel:
|
||||
channel["stationname"] = channel["cStationName"]
|
||||
Channel.create(shortname=channel["shortname"], streamurl=streamurl,
|
||||
stationname=channel["stationname"], has_data=channel["cHasData"],
|
||||
primary_color=channel["cPrimaryColor"], secondary_color=channel["cSecondaryColor"])
|
||||
print("create", channel.stationname)
|
||||
Channel.create(shortname=channel.shortname, stationname=channel.stationname, has_data=channel.has_data,
|
||||
primary_color=channel.primary_color, secondary_color=channel.secondary_color)
|
||||
|
|
16
fetch.py
16
fetch.py
|
@ -1,17 +1,15 @@
|
|||
from datetime import timedelta
|
||||
|
||||
import sentry_sdk
|
||||
from peewee import DoesNotExist, IntegrityError
|
||||
|
||||
import config
|
||||
from models import *
|
||||
from parser import kronehit, aas, orf, ara
|
||||
from parser import KroneHitFetcher, AchtundachzigsechsFetcher, ArabellaFetcher, OrfFetcher
|
||||
|
||||
if config.sentryDSN:
|
||||
client = sentry_sdk.init(dsn=config.sentryDSN)
|
||||
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; RadioStats/1.0;)',
|
||||
}
|
||||
|
||||
|
||||
def detect_show(artist, title):
|
||||
return "Ö3" in artist or "LiveStream" in title or "Radio Tirol" in title \
|
||||
|
@ -49,17 +47,17 @@ def add_entry(time, artist, title):
|
|||
for channel in Channel.select():
|
||||
if channel.has_data:
|
||||
if channel.shortname == "kht":
|
||||
pars = kronehit
|
||||
pars = KroneHitFetcher()
|
||||
elif channel.shortname == "886":
|
||||
pars = aas
|
||||
pars = AchtundachzigsechsFetcher()
|
||||
elif channel.shortname == "ara":
|
||||
pars = ara
|
||||
pars = ArabellaFetcher()
|
||||
elif channel.shortname == "eng":
|
||||
continue
|
||||
elif channel.shortname == "all":
|
||||
continue
|
||||
else:
|
||||
pars = orf
|
||||
pars = OrfFetcher()
|
||||
|
||||
for time, artist, title in pars.get(channel):
|
||||
add_entry(time, artist, title)
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
from peewee import *
|
||||
from peewee import CharField, BooleanField, DateTimeField, ForeignKeyField
|
||||
|
||||
from basemodel import BaseModel
|
||||
|
||||
|
||||
class Channel(BaseModel):
|
||||
shortname = CharField(unique=True, max_length=5)
|
||||
streamurl = CharField(null=True)
|
||||
stationname = CharField()
|
||||
has_data = BooleanField()
|
||||
primary_color = CharField(max_length=7)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
from . import aas
|
||||
from . import ara
|
||||
from . import kronehit
|
||||
from . import orf
|
||||
from .base import BaseFetcher
|
||||
from .aas import AchtundachzigsechsFetcher
|
||||
from .ara import ArabellaFetcher
|
||||
from .eng import EnergyFetcher
|
||||
from .kronehit import KroneHitFetcher
|
||||
from .orf import OrfFetcher
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
from utils import *
|
||||
from sentry_sdk import capture_exception
|
||||
|
||||
from parser import BaseFetcher
|
||||
from utils import *
|
||||
|
||||
URL = "https://meta.radio886.at/886/0"
|
||||
|
||||
|
||||
def get(channel):
|
||||
data = fetch(URL, True)
|
||||
if "data" not in data:
|
||||
capture_exception(Exception("886 didn't return any data."))
|
||||
return []
|
||||
for track in fetch(URL, True)["data"]:
|
||||
artist = track["name"]
|
||||
title = track["title"]
|
||||
try:
|
||||
time = time_to_date(string_to_time(track["scheduled_time"]))
|
||||
yield time, artist, title
|
||||
except ValueError as e: # in case time is 24:02:31 or similar
|
||||
print(e)
|
||||
class AchtundachzigsechsFetcher(BaseFetcher):
|
||||
def get(self, channel):
|
||||
data = fetch(URL, True)
|
||||
if "data" not in data:
|
||||
capture_exception(Exception("886 didn't return any data."))
|
||||
return []
|
||||
for track in fetch(URL, True)["data"]:
|
||||
artist = track["name"]
|
||||
title = track["title"]
|
||||
try:
|
||||
time = time_to_date(string_to_time(track["scheduled_time"]))
|
||||
yield time, artist, title
|
||||
except ValueError as e: # in case time is 24:02:31 or similar
|
||||
print(e)
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
from parser import BaseFetcher
|
||||
from utils import *
|
||||
|
||||
URL = "http://www.arabella.at/live-feed/ajax.php?station=zenon-rp-wien"
|
||||
|
||||
|
||||
def get(channel):
|
||||
response=fetch(URL, True)
|
||||
if response:
|
||||
for track in response["songs"]:
|
||||
artist = track["artist"]
|
||||
title = track["title"]
|
||||
dt = track["start_date_time"]
|
||||
time = datetime(year=int(dt["year"]), month=int(dt["month"]), day=int(dt["day"]),
|
||||
hour=int(dt["hours"]), minute=int(dt["minutes"]), second=int(dt["seconds"]))
|
||||
yield time, artist, title
|
||||
class ArabellaFetcher(BaseFetcher):
|
||||
def get(self, channel):
|
||||
response = fetch(URL, True)
|
||||
if response:
|
||||
for track in response["songs"]:
|
||||
artist = track["artist"]
|
||||
title = track["title"]
|
||||
dt = track["start_date_time"]
|
||||
time = datetime(year=int(dt["year"]), month=int(dt["month"]), day=int(dt["day"]),
|
||||
hour=int(dt["hours"]), minute=int(dt["minutes"]), second=int(dt["seconds"]))
|
||||
yield time, artist, title
|
||||
|
|
11
parser/base.py
Normal file
11
parser/base.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime
|
||||
from typing import Tuple, Iterable
|
||||
|
||||
from models import Channel
|
||||
|
||||
|
||||
class BaseFetcher(ABC):
|
||||
@abstractmethod
|
||||
def get(self, channel: Channel) -> Iterable[Tuple[datetime, str, str]]:
|
||||
pass
|
|
@ -1,19 +1,22 @@
|
|||
from bs4 import BeautifulSoup
|
||||
|
||||
from parser import BaseFetcher
|
||||
from utils import *
|
||||
|
||||
|
||||
def get(channel):
|
||||
url = "http://www.energy.at/extern/tifo/?station=vie&hour={hour}&min={min}&date={date}&submit=1"
|
||||
now = datetime.now() - timedelta(minutes=30)
|
||||
url = url.format(hour=now.hour, min=now.minute, date=now.strftime("%d.%m.%Y"))
|
||||
soup = BeautifulSoup(fetch(url, False), 'html.parser')
|
||||
print(url)
|
||||
for item in soup.findAll("div", "item"):
|
||||
artist = item.find("p", "interpret").get_text()
|
||||
title = item.find("p", "title").get_text()
|
||||
timestring = item.find("span", "time").get_text()
|
||||
datestring = item.find("span", "date").get_text()
|
||||
time = local_to_utc(datetime.strptime(datestring + " " + timestring, '%d.%m.%Y %H:%M'))
|
||||
yield time, artist, title
|
||||
exit()
|
||||
class EnergyFetcher(BaseFetcher):
|
||||
disabled = True
|
||||
|
||||
def get(self, channel):
|
||||
url = "http://www.energy.at/extern/tifo/?station=vie&hour={hour}&min={min}&date={date}&submit=1"
|
||||
now = datetime.now() - timedelta(minutes=30)
|
||||
url = url.format(hour=now.hour, min=now.minute, date=now.strftime("%d.%m.%Y"))
|
||||
soup = BeautifulSoup(fetch(url, False), 'html.parser')
|
||||
print(url)
|
||||
for item in soup.findAll("div", "item"):
|
||||
artist = item.find("p", "interpret").get_text()
|
||||
title = item.find("p", "title").get_text()
|
||||
timestring = item.find("span", "time").get_text()
|
||||
datestring = item.find("span", "date").get_text()
|
||||
time = local_to_utc(datetime.strptime(datestring + " " + timestring, '%d.%m.%Y %H:%M'))
|
||||
yield time, artist, title
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
from parser import BaseFetcher
|
||||
from utils import *
|
||||
|
||||
URL = "https://www.kronehit.at/alles-ueber-kronehit/hitsuche/?format=json&channel=1"
|
||||
|
||||
|
||||
def get(channel):
|
||||
for track in fetch(URL, True)["items"]:
|
||||
artist = track["ArtistName"]
|
||||
title = track["TrackName"]
|
||||
time = time_to_date(string_to_time(track["PlayTime"],seconds=False))
|
||||
yield time, artist, title
|
||||
class KroneHitFetcher(BaseFetcher):
|
||||
def get(self, channel):
|
||||
for track in fetch(URL, True)["items"]:
|
||||
artist = track["ArtistName"]
|
||||
title = track["TrackName"]
|
||||
time = time_to_date(string_to_time(track["PlayTime"], seconds=False))
|
||||
yield time, artist, title
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
from parser import BaseFetcher
|
||||
from utils import *
|
||||
|
||||
|
||||
def get(channel):
|
||||
r = careful_fetch(channel.streamurl + "played.html?type=json")
|
||||
print(r.text)
|
||||
for song in r.json():
|
||||
time = datetime.fromtimestamp(song["playedat"])
|
||||
|
||||
if " - " in song["title"]:
|
||||
# for whatever crazy reason only half of the channels are the other way round
|
||||
if channel.shortname in ["oe3", "fm4", "noe", "wie", "stm"]:
|
||||
artist, title = song["title"].split(" - ")[:2]
|
||||
else:
|
||||
title, artist = song["title"].split(" - ")[:2]
|
||||
else:
|
||||
artist = ""
|
||||
title = song["title"]
|
||||
if channel.shortname == "fm4" and "|" in title:
|
||||
title = title.split("|")[0]
|
||||
|
||||
yield (time, artist, title)
|
||||
class OrfFetcher(BaseFetcher):
|
||||
def get(self, channel):
|
||||
r = careful_fetch(f"https://audioapi.orf.at/{channel.shortname}/json/4.0/live")
|
||||
r.raise_for_status()
|
||||
for song in r.json()[0]["items"]:
|
||||
time = datetime.fromtimestamp(song["start"] / 1000)
|
||||
try:
|
||||
artist = song["interpreter"]
|
||||
title = song["title"]
|
||||
except KeyError:
|
||||
print("not a song")
|
||||
continue
|
||||
yield (time, artist, title)
|
||||
|
|
227
poetry.lock
generated
227
poetry.lock
generated
|
@ -1,63 +1,63 @@
|
|||
[[package]]
|
||||
category = "main"
|
||||
description = "Screen-scraping library"
|
||||
name = "beautifulsoup4"
|
||||
version = "4.9.2"
|
||||
description = "Screen-scraping library"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "4.9.0"
|
||||
|
||||
[package.dependencies]
|
||||
soupsieve = [">1.2", "<2.0"]
|
||||
soupsieve = {version = ">1.2", markers = "python_version >= \"3.0\""}
|
||||
|
||||
[package.extras]
|
||||
html5lib = ["html5lib"]
|
||||
lxml = ["lxml"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Fast, simple object-to-object and broadcast signaling"
|
||||
name = "blinker"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "1.4"
|
||||
description = "Fast, simple object-to-object and broadcast signaling"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
name = "certifi"
|
||||
version = "2020.6.20"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "2020.4.5.1"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Universal encoding detector for Python 2 and 3"
|
||||
name = "chardet"
|
||||
version = "3.0.4"
|
||||
description = "Universal encoding detector for Python 2 and 3"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "3.0.4"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Composable command line interface toolkit"
|
||||
name = "click"
|
||||
version = "7.1.2"
|
||||
description = "Composable command line interface toolkit"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "7.1.1"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "A simple framework for building complex web applications."
|
||||
name = "flask"
|
||||
version = "1.1.2"
|
||||
description = "A simple framework for building complex web applications."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "1.1.2"
|
||||
|
||||
[package.dependencies]
|
||||
Jinja2 = ">=2.10.1"
|
||||
Werkzeug = ">=0.15"
|
||||
click = ">=5.1"
|
||||
itsdangerous = ">=0.24"
|
||||
Jinja2 = ">=2.10.1"
|
||||
Werkzeug = ">=0.15"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
|
||||
|
@ -65,26 +65,23 @@ docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-
|
|||
dotenv = ["python-dotenv"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Adds caching support to your Flask application"
|
||||
name = "flask-caching"
|
||||
version = "1.9.0"
|
||||
description = "Adds caching support to your Flask application"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "1.8.0"
|
||||
|
||||
[package.dependencies]
|
||||
Flask = "*"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "WSGI HTTP Server for UNIX"
|
||||
name = "gunicorn"
|
||||
version = "20.0.4"
|
||||
description = "WSGI HTTP Server for UNIX"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.4"
|
||||
version = "20.0.4"
|
||||
|
||||
[package.dependencies]
|
||||
setuptools = ">=3.0"
|
||||
|
||||
[package.extras]
|
||||
eventlet = ["eventlet (>=0.9.7)"]
|
||||
|
@ -93,28 +90,28 @@ setproctitle = ["setproctitle"]
|
|||
tornado = ["tornado (>=0.2)"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
name = "idna"
|
||||
version = "2.10"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "2.9"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Various helpers to pass data to untrusted environments and back."
|
||||
name = "itsdangerous"
|
||||
version = "1.1.0"
|
||||
description = "Various helpers to pass data to untrusted environments and back."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "1.1.0"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "A very fast and expressive template engine."
|
||||
name = "jinja2"
|
||||
version = "2.11.2"
|
||||
description = "A very fast and expressive template engine."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "2.11.2"
|
||||
|
||||
[package.dependencies]
|
||||
MarkupSafe = ">=0.23"
|
||||
|
@ -123,58 +120,59 @@ MarkupSafe = ">=0.23"
|
|||
i18n = ["Babel (>=0.8)"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Safely add untrusted strings to HTML/XML markup."
|
||||
name = "markupsafe"
|
||||
version = "1.1.1"
|
||||
description = "Safely add untrusted strings to HTML/XML markup."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
|
||||
version = "1.1.1"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "a little orm"
|
||||
name = "peewee"
|
||||
version = "3.13.3"
|
||||
description = "a little orm"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "3.13.3"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Pure Python MySQL Driver"
|
||||
name = "pymysql"
|
||||
version = "0.10.1"
|
||||
description = "Pure Python MySQL Driver"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.9.3"
|
||||
|
||||
[package.extras]
|
||||
ed25519 = ["PyNaCl (>=1.4.0)"]
|
||||
rsa = ["cryptography"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
name = "pytz"
|
||||
version = "2020.1"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "2019.3"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Python client for Redis key-value store"
|
||||
name = "redis"
|
||||
version = "3.5.3"
|
||||
description = "Python client for Redis key-value store"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "3.4.1"
|
||||
|
||||
[package.extras]
|
||||
hiredis = ["hiredis (>=0.1.3)"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Python HTTP for Humans."
|
||||
name = "requests"
|
||||
version = "2.24.0"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "2.23.0"
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
|
@ -187,62 +185,58 @@ security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"]
|
|||
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Python client for Sentry (https://getsentry.com)"
|
||||
name = "sentry-sdk"
|
||||
version = "0.17.8"
|
||||
description = "Python client for Sentry (https://sentry.io)"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.14.3"
|
||||
|
||||
[package.dependencies]
|
||||
blinker = {version = ">=1.1", optional = true, markers = "extra == \"flask\""}
|
||||
certifi = "*"
|
||||
flask = {version = ">=0.11", optional = true, markers = "extra == \"flask\""}
|
||||
urllib3 = ">=1.10.0"
|
||||
|
||||
[package.dependencies.blinker]
|
||||
optional = true
|
||||
version = ">=1.1"
|
||||
|
||||
[package.dependencies.flask]
|
||||
optional = true
|
||||
version = ">=0.11"
|
||||
|
||||
[package.extras]
|
||||
aiohttp = ["aiohttp (>=3.5)"]
|
||||
beam = ["beam (>=2.12)"]
|
||||
beam = ["apache-beam (>=2.12)"]
|
||||
bottle = ["bottle (>=0.12.13)"]
|
||||
celery = ["celery (>=3)"]
|
||||
chalice = ["chalice (>=1.16.0)"]
|
||||
django = ["django (>=1.8)"]
|
||||
falcon = ["falcon (>=1.4)"]
|
||||
flask = ["flask (>=0.11)", "blinker (>=1.1)"]
|
||||
pure_eval = ["pure-eval", "executing", "asttokens"]
|
||||
pyspark = ["pyspark (>=2.4.4)"]
|
||||
rq = ["0.6"]
|
||||
rq = ["rq (>=0.6)"]
|
||||
sanic = ["sanic (>=0.8)"]
|
||||
sqlalchemy = ["sqlalchemy (>=1.2)"]
|
||||
tornado = ["tornado (>=5)"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
name = "six"
|
||||
version = "1.15.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
version = "1.14.0"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "A modern CSS selector implementation for Beautiful Soup."
|
||||
name = "soupsieve"
|
||||
version = "2.0.1"
|
||||
description = "A modern CSS selector implementation for Beautiful Soup."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "1.9.5"
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "A light weight Python library for the Spotify Web API"
|
||||
name = "spotipy"
|
||||
version = "2.16.0"
|
||||
description = "A light weight Python library for the Spotify Web API"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "2.11.2"
|
||||
|
||||
[package.dependencies]
|
||||
requests = ">=2.20.0"
|
||||
|
@ -253,69 +247,70 @@ doc = ["Sphinx (>=1.5.2)"]
|
|||
test = ["mock (2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
name = "urllib3"
|
||||
version = "1.22"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "1.22"
|
||||
|
||||
[package.extras]
|
||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
||||
socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "The comprehensive WSGI web application library."
|
||||
name = "werkzeug"
|
||||
version = "1.0.1"
|
||||
description = "The comprehensive WSGI web application library."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
version = "1.0.1"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"]
|
||||
watchdog = ["watchdog"]
|
||||
|
||||
[metadata]
|
||||
content-hash = "a8ff226072ae85c4c5c564886f4e0a019157c31acd922ccc0c1c0bf8fc03a9ed"
|
||||
lock-version = "1.1"
|
||||
python-versions = ">=3.7"
|
||||
content-hash = "d32e930d2994b6dcc97a0679843cbed9b5345b63a953e4ce98c935d281679b50"
|
||||
|
||||
[metadata.files]
|
||||
beautifulsoup4 = [
|
||||
{file = "beautifulsoup4-4.9.0-py2-none-any.whl", hash = "sha256:a4bbe77fd30670455c5296242967a123ec28c37e9702a8a81bd2f20a4baf0368"},
|
||||
{file = "beautifulsoup4-4.9.0-py3-none-any.whl", hash = "sha256:d4e96ac9b0c3a6d3f0caae2e4124e6055c5dcafde8e2f831ff194c104f0775a0"},
|
||||
{file = "beautifulsoup4-4.9.0.tar.gz", hash = "sha256:594ca51a10d2b3443cbac41214e12dbb2a1cd57e1a7344659849e2e20ba6a8d8"},
|
||||
{file = "beautifulsoup4-4.9.2-py2-none-any.whl", hash = "sha256:645d833a828722357038299b7f6879940c11dddd95b900fe5387c258b72bb883"},
|
||||
{file = "beautifulsoup4-4.9.2-py3-none-any.whl", hash = "sha256:5dfe44f8fddc89ac5453f02659d3ab1668f2c0d9684839f0785037e8c6d9ac8d"},
|
||||
{file = "beautifulsoup4-4.9.2.tar.gz", hash = "sha256:1edf5e39f3a5bc6e38b235b369128416c7239b34f692acccececb040233032a1"},
|
||||
]
|
||||
blinker = [
|
||||
{file = "blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2020.4.5.1-py2.py3-none-any.whl", hash = "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304"},
|
||||
{file = "certifi-2020.4.5.1.tar.gz", hash = "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"},
|
||||
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
|
||||
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
|
||||
]
|
||||
chardet = [
|
||||
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
|
||||
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
|
||||
]
|
||||
click = [
|
||||
{file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"},
|
||||
{file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"},
|
||||
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
|
||||
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
|
||||
]
|
||||
flask = [
|
||||
{file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"},
|
||||
{file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"},
|
||||
]
|
||||
flask-caching = [
|
||||
{file = "Flask-Caching-1.8.0.tar.gz", hash = "sha256:3d0bd13c448c1640334131ed4163a12aff7df2155e73860f07fc9e5e75de7126"},
|
||||
{file = "Flask_Caching-1.8.0-py2.py3-none-any.whl", hash = "sha256:54b6140bb7b9f3e63d009ff08b03bacd84eefb1af1d30af06b4a6bc3c16fa3b2"},
|
||||
{file = "Flask-Caching-1.9.0.tar.gz", hash = "sha256:a0356ad868b1d8ec2d0e675a6fe891c41303128f8904d5d79e180d8b3f952aff"},
|
||||
{file = "Flask_Caching-1.9.0-py2.py3-none-any.whl", hash = "sha256:e6ef2e2af84e13c4fd32c1839c1943a42f11b6b0fbcfdd6bf46547ea5482dbfe"},
|
||||
]
|
||||
gunicorn = [
|
||||
{file = "gunicorn-20.0.4-py2.py3-none-any.whl", hash = "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"},
|
||||
{file = "gunicorn-20.0.4.tar.gz", hash = "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626"},
|
||||
]
|
||||
idna = [
|
||||
{file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"},
|
||||
{file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"},
|
||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"},
|
||||
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"},
|
||||
]
|
||||
itsdangerous = [
|
||||
{file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"},
|
||||
|
@ -364,37 +359,37 @@ peewee = [
|
|||
{file = "peewee-3.13.3.tar.gz", hash = "sha256:1269a9736865512bd4056298003aab190957afe07d2616cf22eaf56cb6398369"},
|
||||
]
|
||||
pymysql = [
|
||||
{file = "PyMySQL-0.9.3-py2.py3-none-any.whl", hash = "sha256:3943fbbbc1e902f41daf7f9165519f140c4451c179380677e6a848587042561a"},
|
||||
{file = "PyMySQL-0.9.3.tar.gz", hash = "sha256:d8c059dcd81dedb85a9f034d5e22dcb4442c0b201908bede99e306d65ea7c8e7"},
|
||||
{file = "PyMySQL-0.10.1-py2.py3-none-any.whl", hash = "sha256:44f47128dda8676e021c8d2dbb49a82be9e4ab158b9f03e897152a3a287c69ea"},
|
||||
{file = "PyMySQL-0.10.1.tar.gz", hash = "sha256:263040d2779a3b84930f7ac9da5132be0fefcd6f453a885756656103f8ee1fdd"},
|
||||
]
|
||||
pytz = [
|
||||
{file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"},
|
||||
{file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"},
|
||||
{file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"},
|
||||
{file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"},
|
||||
]
|
||||
redis = [
|
||||
{file = "redis-3.4.1-py2.py3-none-any.whl", hash = "sha256:b205cffd05ebfd0a468db74f0eedbff8df1a7bfc47521516ade4692991bb0833"},
|
||||
{file = "redis-3.4.1.tar.gz", hash = "sha256:0dcfb335921b88a850d461dc255ff4708294943322bd55de6cfd68972490ca1f"},
|
||||
{file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"},
|
||||
{file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"},
|
||||
{file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"},
|
||||
{file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"},
|
||||
{file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"},
|
||||
]
|
||||
sentry-sdk = [
|
||||
{file = "sentry-sdk-0.14.3.tar.gz", hash = "sha256:bb90a4e19c7233a580715fc986cc44be2c48fc10b31e71580a2037e1c94b6950"},
|
||||
{file = "sentry_sdk-0.14.3-py2.py3-none-any.whl", hash = "sha256:23808d571d2461a4ce3784ec12bbee5bdb8c026c143fe79d36cef8a6d653e71f"},
|
||||
{file = "sentry-sdk-0.17.8.tar.gz", hash = "sha256:e159f7c919d19ae86e5a4ff370fccc45149fab461fbeb93fb5a735a0b33a9cb1"},
|
||||
{file = "sentry_sdk-0.17.8-py2.py3-none-any.whl", hash = "sha256:c9c0fa1412bad87104c4eee8dd36c7bbf60b0d92ae917ab519094779b22e6d9a"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"},
|
||||
{file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"},
|
||||
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
|
||||
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
|
||||
]
|
||||
soupsieve = [
|
||||
{file = "soupsieve-1.9.5-py2.py3-none-any.whl", hash = "sha256:bdb0d917b03a1369ce964056fc195cfdff8819c40de04695a80bc813c3cfa1f5"},
|
||||
{file = "soupsieve-1.9.5.tar.gz", hash = "sha256:e2c1c5dee4a1c36bcb790e0fabd5492d874b8ebd4617622c4f6a731701060dda"},
|
||||
{file = "soupsieve-2.0.1-py3-none-any.whl", hash = "sha256:1634eea42ab371d3d346309b93df7870a88610f0725d47528be902a0d95ecc55"},
|
||||
{file = "soupsieve-2.0.1.tar.gz", hash = "sha256:a59dc181727e95d25f781f0eb4fd1825ff45590ec8ff49eadfd7f1a537cc0232"},
|
||||
]
|
||||
spotipy = [
|
||||
{file = "spotipy-2.11.2-py2-none-any.whl", hash = "sha256:a90dbadeb899763a6789dabbf9a57ec8874f1e72c38161669661c0714654acaf"},
|
||||
{file = "spotipy-2.11.2-py3-none-any.whl", hash = "sha256:293a070de156345359620e17945a379762488b0e00f01a25530ab7af1abea4ab"},
|
||||
{file = "spotipy-2.11.2.tar.gz", hash = "sha256:9d5ca9f600bbceb6c86d66e819e2a1446db819cfca349a2f55c3fdda11b606af"},
|
||||
{file = "spotipy-2.16.0-py2-none-any.whl", hash = "sha256:800330badc1b953417dace1532a586220d35b2240eb2e538e883e19e6bf1b53d"},
|
||||
{file = "spotipy-2.16.0-py3-none-any.whl", hash = "sha256:9d07b8948c30d8a338805440797263749ccad07c22009f9b3112aa2bcb2ebcea"},
|
||||
{file = "spotipy-2.16.0.tar.gz", hash = "sha256:315eadd1248053ed336b4d3adbf2e3c32895fdbb0cfcd170542c848c8fd45649"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.22-py2.py3-none-any.whl", hash = "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b"},
|
||||
|
|
|
@ -9,12 +9,12 @@ python = ">=3.7"
|
|||
requests = "^2.22.0"
|
||||
Flask = "^1.1.1"
|
||||
Flask-Caching = "^1.8.0"
|
||||
sentry-sdk = {extras = ["flask"], version = "^0.14.1"}
|
||||
sentry-sdk = {extras = ["flask"], version = "^0.17.1"}
|
||||
spotipy = "^2.4.4"
|
||||
peewee = "^3.13.1"
|
||||
beautifulsoup4 = "^4.8.2"
|
||||
PyMySQL = "^0.9.3"
|
||||
pytz = "^2019.3"
|
||||
PyMySQL = "^0.10.0"
|
||||
pytz = "^2020.1"
|
||||
gunicorn = "^20.0.4"
|
||||
redis = "^3.3.11"
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import calendar
|
|||
from datetime import datetime, timedelta
|
||||
|
||||
from flask import jsonify, request
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
from playhouse.shortcuts import model_to_dict, fn, SQL
|
||||
|
||||
from app import app, cache
|
||||
from models import *
|
||||
|
|
12
update_channels.py
Normal file
12
update_channels.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
import channelInfo
|
||||
from models import Channel
|
||||
|
||||
for id, channel in channelInfo.channels.items():
|
||||
print("update", channel.stationname)
|
||||
|
||||
db_chan = Channel.get(shortname=channel.shortname)
|
||||
db_chan.stationname = channel.stationname
|
||||
db_chan.has_data = channel.has_data
|
||||
db_chan.primary_color = channel.primary_color
|
||||
db_chan.secondary_color = channel.secondary_color
|
||||
db_chan.save()
|
27
utils.py
27
utils.py
|
@ -1,16 +1,18 @@
|
|||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, time
|
||||
from time import sleep
|
||||
|
||||
import pytz
|
||||
import requests
|
||||
from requests import Response
|
||||
|
||||
headers = {
|
||||
s = requests.Session()
|
||||
s.headers.update({
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; RadioStats/1.0;)',
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
def careful_fetch(url):
|
||||
def careful_fetch(url) -> Response:
|
||||
"""
|
||||
:rtype: requests.models.Response
|
||||
"""
|
||||
|
@ -19,7 +21,7 @@ def careful_fetch(url):
|
|||
tries = 0
|
||||
while result is None:
|
||||
try:
|
||||
req = requests.get(url, headers=headers)
|
||||
req = s.get(url)
|
||||
if "Invalid resource" in req.text:
|
||||
raise requests.exceptions.ConnectionError
|
||||
return req
|
||||
|
@ -33,11 +35,7 @@ def careful_fetch(url):
|
|||
pass
|
||||
|
||||
|
||||
def string_to_time(timestring, seconds=True):
|
||||
"""
|
||||
|
||||
:rtype: datetime.time
|
||||
"""
|
||||
def string_to_time(timestring, seconds=True) -> time:
|
||||
if seconds:
|
||||
format = "%H:%M:%S"
|
||||
else:
|
||||
|
@ -45,12 +43,7 @@ def string_to_time(timestring, seconds=True):
|
|||
return datetime.strptime(timestring, format).time()
|
||||
|
||||
|
||||
def time_to_date(time):
|
||||
"""
|
||||
|
||||
:rtype: datetime.datetime
|
||||
:type time: datetime.time
|
||||
"""
|
||||
def time_to_date(time: time) -> datetime:
|
||||
time_hour = time.hour
|
||||
day = datetime.now()
|
||||
current_hour = day.hour
|
||||
|
@ -69,7 +62,7 @@ def local_to_utc(date):
|
|||
|
||||
|
||||
def fetch(url, json=False):
|
||||
req = requests.get(url, headers=headers)
|
||||
req = s.get(url)
|
||||
if req.status_code != 200:
|
||||
print("URL failed to fetch: {status} {url}".format(status=req.status_code, url=url), file=sys.stderr)
|
||||
return False
|
||||
|
|
137
web/yarn.lock
137
web/yarn.lock
|
@ -2927,7 +2927,7 @@ debug@=3.1.0:
|
|||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
|
||||
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||
|
@ -3016,11 +3016,6 @@ deep-equal@^1.0.1:
|
|||
object-keys "^1.1.1"
|
||||
regexp.prototype.flags "^1.2.0"
|
||||
|
||||
deep-extend@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
||||
|
||||
deep-is@~0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
|
@ -3109,11 +3104,6 @@ detect-file@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
||||
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
|
||||
|
||||
detect-libc@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
|
||||
detect-node@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
||||
|
@ -4122,13 +4112,6 @@ fs-extra@^8.1.0:
|
|||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-minipass@^1.2.5:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
|
||||
integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
|
||||
dependencies:
|
||||
minipass "^2.6.0"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
|
@ -4737,7 +4720,7 @@ https-proxy-agent@^5.0.0:
|
|||
agent-base "6"
|
||||
debug "4"
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
|
@ -4761,13 +4744,6 @@ iferr@^0.1.5:
|
|||
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
|
||||
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
|
||||
|
||||
ignore-walk@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
|
||||
integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==
|
||||
dependencies:
|
||||
minimatch "^3.0.4"
|
||||
|
||||
ignore@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||
|
@ -4960,7 +4936,7 @@ inherits@2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
|
||||
ini@^1.3.4, ini@^1.3.5:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
|
||||
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
|
||||
|
@ -6013,14 +5989,6 @@ minipass-pipeline@^1.2.2:
|
|||
dependencies:
|
||||
minipass "^3.0.0"
|
||||
|
||||
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
||||
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minipass@^3.0.0, minipass@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
|
||||
|
@ -6028,13 +5996,6 @@ minipass@^3.0.0, minipass@^3.1.1:
|
|||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^1.2.1:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
|
||||
integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
|
||||
dependencies:
|
||||
minipass "^2.9.0"
|
||||
|
||||
mississippi@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
|
||||
|
@ -6159,15 +6120,6 @@ natural-compare@^1.4.0:
|
|||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
needle@^2.2.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.1.tgz#14af48732463d7475696f937626b1b993247a56a"
|
||||
integrity sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g==
|
||||
dependencies:
|
||||
debug "^3.2.6"
|
||||
iconv-lite "^0.4.4"
|
||||
sax "^1.2.4"
|
||||
|
||||
negotiator@0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
|
@ -6247,22 +6199,6 @@ node-libs-browser@^2.2.1:
|
|||
util "^0.11.0"
|
||||
vm-browserify "^1.0.1"
|
||||