Commit 2c14d369 authored by Gottfried Gaisbauer's avatar Gottfried Gaisbauer
Browse files

implemented manual inserting of a ScheduleEntry. Manual radio control is not...

implemented manual inserting of a ScheduleEntry. Manual radio control is not far away. Found a - at least for me - hard to track bug coming from sqlalchemy session. not fixed
parent 8d508cb9
This diff is collapsed.
......@@ -20,10 +20,6 @@ class Guru:
try:
parser = ArgumentParser()
# commands
parser.add_argument("-fnp", "--fetch-new-programmes", action="store_true", dest="fetch_new_programme",
default=False, help="Fetch new programmes from calendarurl in comba.ini")
# options
parser.add_argument("-sep", "--stop-execution-time", action="store_true", dest="stoptime", default=False,
help="Prints the execution time at the end of the skript")
......@@ -52,12 +48,14 @@ class Guru:
# help="Add new source to LiquidSoap mixer [Experimental]")
# playlist manipulation
parser.add_argument("-fnp", "--fetch-new-programmes", action="store_true", dest="fetch_new_programme",
default=False, help="Fetch new programmes from calendarurl in comba.ini")
parser.add_argument("-spe", "--swap-playlist-entries", action="store", dest="swap_playlist_entries", default=0, metavar=("FROM", "TO"), nargs=2,
help="Swaps two Playlistentries")
parser.add_argument("-dpe", "--delete-playlist-entry", action="store", dest="delete_playlist_entry", default=0, metavar="INDEX",
help="Delete Playlistentry at INDEX")
parser.add_argument("-ape", "--add-playlist-entry", action="store", dest="add_playlist_entry", default=0, metavar=("INDEX", "FROMTIME", "SOURCE"), nargs=3,
help="Add a new Playlistentry at a given index", type=valid_playlist_entry)
parser.add_argument("-ipe", "--insert-playlist-entry", action="store", dest="insert_playlist_entry", default=0, metavar=("FROMTIME", "SOURCE"), nargs=2,
help="Add a new Playlistentry at a given index") # , type=valid_playlist_entry)
parser.add_argument("-pmq", "--print-message-queue", action="store_true", dest="print_message_queue", default=False,
help="Prints message queue")
......@@ -122,17 +120,18 @@ class Guru:
def valid_playlist_entry(argument):
import datetime
from datetime import datetime
import argparse
try:
index = int(argument[0])
fromtime = datetime.strptime(argument[1], "%Y-%m-%d")
source = argument[2]
return index, fromtime, source
except:
msg = "Not a valid date: '{0}'.".format(argument[0])
raise argparse.ArgumentTypeError(msg)
raise
# # ## ## ## ## ## # #
......
......@@ -148,7 +148,10 @@ class AuraCalendarService(threading.Thread):
return
def store_schedule(self, schedule):
schedule_db = Schedule.query.filter(Schedule.schedule_id == schedule['schedule_id']).first()
from libraries.database.database import db
#schedule_db = Schedule.query.filter(Schedule.schedule_id == schedule['schedule_id']).first()
schedule_db = db.session.query(Schedule).filter(Schedule.schedule_id == schedule['schedule_id']).first()
# schedule_db = Schedule.get_by_id(schedule['schedule_id'])
if not schedule_db:
print("no schedule with given schedule id in database => create new")
......
......@@ -11,92 +11,52 @@ from libraries.database.database import db
class Model:
def store(self, commit=False):
curr_db_sessions = db.session.object_session(self)
print("WARNING: Source of the BAND-AID problem! Multiple sessions, where when something is deleted a transaction is pending")
if curr_db_sessions is None:
db.session.add(self)
if commit:
db.session.commit()
else:
curr_db_sessions.add(self)
obj_session = db.session.object_session(self)
if obj_session is not None:
obj_session.add(self)
if commit:
curr_db_sessions.commit()
obj_session.commit()
db.session.add(self)
if commit:
db.session.commit()
def delete(self, commit=False):
curr_db_sessions = db.session.object_session(self)
curr_db_sessions.delete(self)
obj_session = db.session.object_session(self)
if commit:
curr_db_sessions.commit()
if obj_session is not None:
obj_session.delete(self)
if commit:
obj_session.commit()
@staticmethod
def commit():
db.session.commit()
db.session.delete(self)
if commit:
db.session.commit()
def _asdict(self):
return self.__dict__
@staticmethod
def recreate_db():
def recreate_db(systemexit = False):
manualschedule = Schedule()
manualschedule.schedule_id = 0
print("Recreating Database...")
db.drop_all()
print("all dropped. creating...")
db.create_all()
print("inserting manual scheduling possibility")
db.session.add(manualschedule)
print("all created. commiting...")
db.session.commit()
print("Database recreated!")
# sys.exit(0)
# ------------------------------------------------------------------------------------------ #
class ScheduleModel(Model):
def get_length(self):
sec1 = int(datetime.datetime.strptime(self.start[0:16].replace(" ", "T"), "%Y-%m-%dT%H:%M").strftime("%s"))
sec2 = int(datetime.datetime.strptime(self.end[0:16].replace(" ", "T"), "%Y-%m-%dT%H:%M").strftime("%s"))
len = sec2 - sec1
return len
# ------------------------------------------------------------------------------------------ #
class ScheduleEntryModel(Model):
# ------------------------------------------------------------------------------------------ #
@staticmethod
def upcoming(datefrom=datetime.datetime.now()):
upcomingtracks = ScheduleEntry.query.filter(ScheduleEntry.start > datefrom).all()
return upcomingtracks
# ------------------------------------------------------------------------------------------ #
@staticmethod
def select_all():
# when deleting all entries, and fetching new programmes, the entries are stored and commited in the code.
# but sqlalchemy thinks somehow it is not commit and returns an empty set
print("WARNING: This commit before SELECT is a BAND-AID. There is a transaction pending and not commited")
db.session.commit()
# fetching all
all_entries = ScheduleEntry.query.filter().all()
cnt = 0
for entry in all_entries:
entry.programme_index = cnt
entry.entry_start_unix = time.mktime(entry.entry_start.timetuple())
entry.entry_end_unix = time.mktime(entry.entry_end.timetuple())
cnt = cnt + 1
return all_entries
@staticmethod
def select_one(playlist_id, entry_num):
return ScheduleEntry.query.filter(ScheduleEntry.playlist_id == playlist_id, ScheduleEntry.entry_num == entry_num).first()
def __str__(self):
return "ScheduleEntry starts @ " + ScheduleEntry.entry_start + " and ends @ " + ScheduleEntry.entry_end + " and plays " + ScheduleEntry.source
if systemexit:
sys.exit(0)
# ------------------------------------------------------------------------------------------ #
class Schedule(db.Model, ScheduleModel):
class Schedule(db.Model, Model):
"""
One specific Schedule for a show on a timeslot
"""
......@@ -104,8 +64,8 @@ class Schedule(db.Model, ScheduleModel):
schedule_id = Column(Integer, primary_key=True, autoincrement=False)
show_id = Column(Integer)
schedule_start = Column(DateTime, nullable=False)
schedule_end = Column(DateTime, nullable=False)
schedule_start = Column(DateTime) # can be null due to manual entries
schedule_end = Column(DateTime) # can be null due to manual entries
show_name = Column(String(256))
show_hosts = Column(String(256))
rtr_category = Column(String(256))
......@@ -123,6 +83,12 @@ class Schedule(db.Model, ScheduleModel):
show_fallback_id = Column(Integer)
station_fallback_id = Column(Integer)
def get_length(self):
sec1 = int(datetime.datetime.strptime(self.start[0:16].replace(" ", "T"), "%Y-%m-%dT%H:%M").strftime("%s"))
sec2 = int(datetime.datetime.strptime(self.end[0:16].replace(" ", "T"), "%Y-%m-%dT%H:%M").strftime("%s"))
len = sec2 - sec1
return len
@property
def serialize(self):
"""Return object data in easily serializeable format"""
......@@ -141,7 +107,7 @@ class Schedule(db.Model, ScheduleModel):
# ------------------------------------------------------------------------------------------ #
class ScheduleEntry(db.Model, ScheduleEntryModel):
class ScheduleEntry(db.Model, Model):
"""
One schedule can have multiple entries
"""
......@@ -151,7 +117,7 @@ class ScheduleEntry(db.Model, ScheduleEntryModel):
entry_num = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
schedule_id = Column(Integer, ForeignKey("schedule.schedule_id"))
entry_start = Column(DateTime, nullable=False)
entry_end = Column(DateTime, nullable=False)
entry_end = Column(DateTime)
source = Column(String(256))
artist = Column(String(256))
track = Column(String(256))
......@@ -165,6 +131,79 @@ class ScheduleEntry(db.Model, ScheduleEntryModel):
entry_end_unix = 0
programme_index = -1
# ------------------------------------------------------------------------------------------ #
@staticmethod
def select_all():
# when deleting all entries, and fetching new programmes, the entries are stored and commited in the code.
# but sqlalchemy thinks somehow it is not commit and returns an empty set
print("WARNING: broadcasts.py This commit before SELECT is a BAND-AID & UGLY-HACK. Why the hell is there a transaction pending and not commited?")
db.session.commit()
# fetching all
# all_entries = ScheduleEntry.query.filter().all()
all_entries = db.session.query(ScheduleEntry).filter().all()
# BAND-AID debug output. The model and db session are different. crap
print("SELECT ALL ScheduleEntry.q.session == db.session?")
print(ScheduleEntry.query.session == db.session)
print("SELECT ALL ScheduleEntry.q.s.conn == db.s.conn?")
print(ScheduleEntry.query.session.connection() == db.session.connection())
cnt = 0
for entry in all_entries:
entry.programme_index = cnt
entry.entry_start_unix = time.mktime(entry.entry_start.timetuple())
if entry.entry_end is not None:
entry.entry_end_unix = time.mktime(entry.entry_end.timetuple())
cnt = cnt + 1
return all_entries
@staticmethod
def select_next_manual_entry_num():
from sqlalchemy import func
# damn BAND-AID
db.session.commit()
#subqry = db.session.query(func.max(ScheduleEntry.entry_num)).filter(ScheduleEntry.schedule_id = 0)
#qry = db.session.query(Data).filter(Data.user_id == user_id, Data.counter == subqry)
max_manual_entry_num = db.session.query(func.max(ScheduleEntry.entry_num)).filter(ScheduleEntry.schedule_id == 0).first()
print(max_manual_entry_num)
if max_manual_entry_num[0] is None:
return 0
else:
return int(max_manual_entry_num[0])+1
# print("returning", res)
# return res
# ------------------------------------------------------------------------------------------ #
@staticmethod
def upcoming(datefrom=datetime.datetime.now()):
# damn BAND-AID
db.session.commit()
upcomingtracks = db.session.query(ScheduleEntry).filter(ScheduleEntry.start > datefrom).all()
#upcomingtracks = ScheduleEntry.query.filter(ScheduleEntry.start > datefrom).all()
return upcomingtracks
# ------------------------------------------------------------------------------------------ #
@staticmethod
def select_one(playlist_id, entry_num):
# damn BAND-AID
db.session.commit()
one = db.session.query(ScheduleEntry).filter(ScheduleEntry.playlist_id == playlist_id, ScheduleEntry.entry_num == entry_num).first()
return one
# ------------------------------------------------------------------------------------------ #
def __str__(self):
return "ScheduleEntry starts @ " + ScheduleEntry.entry_start + " and ends @ " + ScheduleEntry.entry_end + " and plays " + ScheduleEntry.source
# def __init__(self, playlist_id, entry_num, schedule_id, entry_start, entry_end, source, artist, track, albumname, genre, tracknum, cdnum, year):
# self.playlist_id = playlist_id
......@@ -219,4 +258,4 @@ class ScheduleEntry(db.Model, ScheduleEntryModel):
#Model.recreate_db()
#Model.recreate_db(True)
......@@ -2,7 +2,7 @@ from sqlalchemy.ext.declarative import declarative_base
from libraries.base.config import ConfigReader
from flask_sqlalchemy import SQLAlchemy
from flask_babel import Babel, get_locale
from flask_babel import Babel
from flask import Flask
Base = declarative_base()
......@@ -23,7 +23,8 @@ app = Flask(__name__, template_folder=install_dir+'/modules/web/templates')
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://"+db_user+":"+db_pass+"@"+db_host+"/"+db_name+"?charset=utf8"
app.config['BABEL_DEFAULT_LOCALE'] = 'de'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
#app.debug = True
print("init db")
db = SQLAlchemy(app)
babel = Babel(app)
\ No newline at end of file
......@@ -3,10 +3,11 @@ from enum import Enum
class Channels(Enum):
STANDARD = "aura"
MAIN = "main"
# MAIN = "main"
IP_REPLY = "init_player_reply"
FNP_REPLY = "fetch_new_programme_reply"
GAP_REPLY = "get_act_programme_reply"
PMQ_REPLY = "print_message_queue_reply"
MPE_REPLY = "move_playlist_entry_reply"
DPE_REPLY = "delete_playlist_entry_reply"
\ No newline at end of file
DPE_REPLY = "delete_playlist_entry_reply"
IPE_REPLY = "insert_playlist_entry_reply"
\ No newline at end of file
......@@ -145,6 +145,11 @@ class ServerRedisAdapter(threading.Thread, RedisMessenger):
print("entry to del: ", entrynum)
self.execute(Channels.DPE_REPLY.value, self.scheduler.delete_playlist_entry, entrynum)
elif item["data"].find("insert_playlist_entry") >= 0:
extracted = item["data"].split()[1:3]
param = {"fromtime": extracted[0], "source": extracted[1]}
self.execute(Channels.IPE_REPLY.value, self.scheduler.insert_playlist_entry, param)
else:
raise RedisConnectionException("ServerRedisAdapter Cannot understand command: " + item["data"])
......
......@@ -20,7 +20,7 @@ class RedisMessenger():
"""
Constructor
"""
self.channel = Channels.MAIN
self.channel = Channels.STANDARD
self.section = ''
self.rstore = RedisStateStore()
self.errnr = '00'
......
__author__ = 'michel'
# -*- coding: utf-8 -*-
from datetime import timedelta
#from libraries.database.broadcasts import Timeslot
from libraries.database.combadb import BroadcastEvent
"""
Model - handles events
"""
class ModelBroadcastEventOverrides(object):
# ------------------------------------------------------------------------------------------ #
@staticmethod
def upcoming(datefrom, freq):
dateto = (datefrom + timedelta(seconds=freq))
#upcomingtracks = BroadcastEvent.query.filter(BroadcastEvent.start > datefrom, BroadcastEvent.start >= dateto).all()
# print(type(BroadcastEvent))
# print(BroadcastEvent)
# print(type(BroadcastEvent.start))
# print(BroadcastEvent.start)
# print(type(datefrom))
# print(datefrom)
# print(type(dateto))
# print(dateto)
# print((BroadcastEvent.start > datefrom))
# print((BroadcastEvent.start <= dateto))
return None #upcomingtracks
......@@ -53,7 +53,6 @@ import threading
from libraries.base.schedulerconfig import AuraSchedulerConfig
from modules.communication.redis.messenger import RedisMessenger
from libraries.base.calendar import AuraCalendarService
from modules.scheduling.models import ModelBroadcastEventOverrides
from libraries.database.broadcasts import ScheduleEntry, Model
from libraries.exceptions.auraexceptions import NoProgrammeLoadedException
......@@ -93,12 +92,15 @@ class AuraScheduler():
debug = False
active_entry = None
def __init__(self, config): #, liquidsoap_client):
def __init__(self, config):
"""
Constructor
@type config: string
@param config: Pfad zur aura.ini
@type config: ConfigReader
@param config: read aura.ini
"""
# Model.recreate_db(True)
self.auraconfig = config
self.debug = config.get("debug")
......@@ -389,6 +391,22 @@ class AuraScheduler():
return self.get_act_programme_as_string()
# ------------------------------------------------------------------------------------------ #
def insert_playlist_entry(self, fromtime_source):
fromtime = fromtime_source["fromtime"]
source = fromtime_source["source"]
entry = ScheduleEntry()
entry.entry_start = fromtime
entry.source = source
entry.playlist_id = 0
entry.schedule_id = 0
entry.entry_num = ScheduleEntry.select_next_manual_entry_num()
entry.store()
self.load_programme_from_db()
return self.get_act_programme_as_string()
# ------------------------------------------------------------------------------------------ #
def __load_config__(self):
......
......@@ -53,9 +53,8 @@ class Padavan:
elif self.args.delete_playlist_entry:
self.delete_playlist_entry(self.args.delete_playlist_entry)
# elif self.args.add_playlist_entry:
# print("moving pl en")
# self.add_playlist_entry(self.args.move_playlist_entry[0], self.args.move_playlist_entry[1])
elif self.args.insert_playlist_entry:
self.insert_playlist_entry(self.args.insert_playlist_entry[0], self.args.insert_playlist_entry[1]) #, self.args.insert_playlist_entry[2])
elif self.args.print_message_queue:
self.print_message_queue()
......@@ -116,15 +115,13 @@ class Padavan:
self.print_programme(actprogramme)
def print_programme(self, programme):
# idx = 0
for entry in programme:
self.stringreply += "idx: " + str(entry["programme_index"]) + \
" --- schedule id #" + str(entry["schedule_id"]) + \
" and entrynumber #" + str(entry["entry_num"]) + \
" starting @ " + entry["entry_start"] + \
" ending @ " + entry["entry_end"] + \
" is playing " + entry["source"] + "\n"
# idx = idx + 1
# " ending @ " + entry["entry_end"] + \
def init_player(self):
self.stringreply = self.send_and_wait_redis("aura", "init_player", Channels.IP_REPLY)
......@@ -143,8 +140,10 @@ class Padavan:
actprogramme = simplejson.loads(json_reply)
self.print_programme(actprogramme)
def add_playlist_entry(self, from_index, to_index):
return ""
def insert_playlist_entry(self, fromtime, source):
json_reply = self.send_and_wait_redis("aura", "insert_playlist_entry " + fromtime + " " + source, Channels.IPE_REPLY)
actprogramme = simplejson.loads(json_reply)
self.print_programme(actprogramme)
def print_message_queue(self):
self.stringreply = self.send_and_wait_redis("aura", "print_message_queue", Channels.PMQ_REPLY)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment