Commits

Guido Draheim committed 019bae0

program userscript no.1

  • Participants
  • Parent commits 21c07f3

Comments (0)

Files changed (7)

src/dvbcronrecording/core.py

             page = m.group(1)
             if page and page.startswith("channel"): return False
             if page and page.startswith("file"): return False
+            if page and page.startswith("programguide"): return False
             req.args['page'] = page 
             return True
         return False

src/dvbcronrecording/dvbcronrecording.de.po

 msgid "channelname"
 msgstr "Senderkennung"
 
+msgid "program guide"
+msgstr "Programmzeitschrift"
+
 msgid "recorder list"
 msgstr "Recorder-Liste"
 

src/dvbcronrecording/htdocs/js/dvbcronrecording_tvspielfilm.user.js

+// ==UserScript== 
+// @name          DvbCronRecording TvSpielfilm
+// @description   Save entries on the program guide to the recording list
+// @namespace     http://bitbucket.org/2011/dvbcronrecording
+// @source        http://SERVER/recording/programguide
+// @version       0.1.1.0
+// @creator       Guido Draheim <guidod-2011-@gmx.de>
+// @license       http://creativecommons.org/licenses/by-nc-sa/2.0/de/
+// @include       http://www.tvspielfilm.de/sendung/*
+// @include       http://tvspielfilm.de/sendung/*
+// @include       http://www.tvspielfilm.de/tv-programm/sendung/*
+// @include       http://tvspielfilm.de/tv-programm/sendung/*
+              http://www.tvspielfilm.de/tv-programm/sendung/lets-dance,107029138385.html
+// @require       http://SERVER/chrome/common/js/jquery.js
+// ==/UserScript==
+
+var _url = "http://SERVER/recording/programguide/tvspielfilm";
+
+function url_data(data) {
+	var text = "";
+	for (var elem in data) {
+		if (text == "") text += "?"; else text += "&";
+		text += encodeURIComponent(elem) + "=" + encodeURIComponent(data[elem]);
+	}
+	return text;
+}
+
+function parentsUntil(node, selector) {
+	var N = $(node);
+	if (N && $(N).is(selector)) return N; else N = $(N).parent();
+	if (N && $(N).is(selector)) return N; else N = $(N).parent();
+	if (N && $(N).is(selector)) return N; else N = $(N).parent();
+	if (N && $(N).is(selector)) return N; else N = $(N).parent();
+	if (N && $(N).is(selector)) return N; else N = $(N).parent();
+	if (N && $(N).is(selector)) return N; else N = $(N).parent();
+	return node;
+}
+
+function save_error(response) {
+	GM_log("ERROR "+response.statusText);
+    $("#dvbcronrecording").css("border", "2px solid red")
+    var value = $(".message", response.responseText).text();
+    $("#dvbcronrecording").text("?"+response.statusText+" | "+value);
+}
+
+function save_success(response) {
+	GM_log("STORED "+response.statusText);
+    $("#dvbcronrecording").css("border", "1px solid green");
+    var value = $(".message", response.responseText).text();
+    if (value.match("OOPS")) $("#dvbcronrecording").css("border", "1px solid red");
+    $("#dvbcronrecording").text("!"+response.statusText+" | "+value);
+}
+
+
+function save_send(date, time, channel, title) {
+    var data = { op: "insert",
+    		date: date,
+    		time: time,
+    		channel: channel,
+    		title: title };
+    GM_log("SEND "+url_data(data));
+    GM_xmlhttpRequest({
+    	method: "GET", url : _url + url_data(data),
+    	headers: { 
+    		"Accept" : "text/html,text/xml" },
+    	onload: save_success, onerror: save_error }); 
+}
+
+
+function clicked_save(event) {
+	var target = event.target;
+	var film_info = parentsUntil(target, ".film-info");
+	var film_items = $("li", film_info);
+	var date = $(film_items.get(0)).text();
+	var time = $(film_items.get(1)).text();
+	var channel = $(film_items.get(2)).text();
+	var title = $($("h1").get(0)).text();
+	// alert("DATE:"+date+" TIME:"+time+" CHANNEL:"+channel+" TITLE:"+title);
+	save_send(date, time, channel, title);
+}
+
+function register()
+{
+	GM_log("register dvbcronrecording")
+	film_info = $(".film-info");
+	if (film_info.length == 1) {
+		var mark = $("ul", film_info);
+		if (mark.length != 1) {
+			alert("mark = " + mark.length);
+		}
+		var div = $(document.createElement("li")).attr("id","dvbcronrecording").css("color", "red").css("font-weight", "bold");
+		div.text("SAVE");
+		div.click(clicked_save);
+		div.appendTo(mark);
+	}
+}
+
+$(window).load(register);
+GM_log("ready dvbcronrecording");
+

src/dvbcronrecording/programguide.py

+# -*- coding: utf-8 -*-
+import pkg
+import re
+import os.path
+import sys
+import datetime
+
+from trac.core import Component, implements
+# from trac.db import *
+#from trac.wiki import wiki_to_html, wiki_to_oneliner
+from trac.web.chrome import add_stylesheet, add_script
+#from trac.util import Markup, format_datetime
+
+from trac.web import IRequestHandler
+from trac.perm import IPermissionRequestor
+from trac.web.chrome import  ITemplateProvider # INavigationContributor,
+from trac.util.presentation import Paginator
+from translate import Translate #@UnresolvedImport
+
+from dvbcronrecording.db.session import db_cnx, commit
+from dvbcronrecording.db.schema import RecordingList #@UnresolvedImport
+from dvbcronrecording.db.schema import RecordingChanges #@UnresolvedImport
+
+def intnull(value, default = None):
+    if value is None: return default
+    try: return int(value)
+    except Exception: return default
+def lookup(lists, entry, default = None):
+    if entry is None: return default
+    idx = intnull(entry)
+    if idx is None or idx >= len(lists): return default
+    return lists[idx]
+def ustr(text):
+    if type(text) is unicode: return text
+    if type(text) is str: return unicode(text)
+    return unicode(str(text))
+
+PACKAGE = u'dvbcronrecording'
+NAV = 'recordings'
+URL = 'recording'
+SUBURL = 'programguide'
+
+LIST_APPEND = 'DVBREC_LIST_APPEND'
+
+"""
+  here we are.
+"""
+class DvbCronRecordingProgramguidePlugin(Component):
+
+    #
+    # Public methods
+    #
+
+    implements(IPermissionRequestor, ITemplateProvider,  IRequestHandler)
+
+    # IPermissionRequestor methods
+
+    """
+      Returns list of permitions privided by this plugin.
+    """
+    def get_permission_actions(self):
+        return [ LIST_APPEND ]
+
+    # ITemplateProvider methods
+
+    """
+      Returns additional path where stylesheets are placed.
+    """
+    def get_htdocs_dirs(self):
+        return [(PACKAGE, pkg.resource_filename(__name__, 'htdocs'))]
+
+    """
+      Returns additional path where templates are placed.
+    """
+    def get_templates_dirs(self):
+        return [pkg.resource_filename(__name__, 'templates')]
+
+    # IRequestHandler methods
+
+    """
+      Determines if request should be handled by this plugin.
+    """
+    def match_request(self, req):
+        m = re.match(r"/%s/%ss?(?:/(.*))?$" % (URL, SUBURL), req.path_info)
+        if m:
+            page = m.group(1)
+            req.args['page'] = page 
+            return True
+        return False
+
+    """
+      Handles display and download requests on this plugin.
+    """
+    def process_request(self, req):
+        req.perm.assert_permission(LIST_APPEND)
+        # ------------------------------------------------
+        translate = Translate(PACKAGE, req.locale)
+        userscripts_dir = self.get_scripts_dir()
+
+        page = req.args['page']
+        message = "[%s]" % page
+
+        if page and page.startswith("install/"):
+            name = page[len("install/"):]
+            filepath = os.path.join(userscripts_dir, name)
+            if os.path.exists(filepath):
+                try:
+                    f = open(filepath)
+                    text = f.read()
+                    f.close()
+                    text = text.replace("http://SERVER", ustr(req.base_url).encode("utf-8"))
+                    req.send_header("Content-Disposition:", 'inline; filename="%s"' % name)
+                    req.send(text, "application/octet-stream")
+                    return
+                except Exception, e:
+                    # req.send_error(sys.exc_info(), status=500, env=self.env, data = { "page" : page})
+                    # return
+                    message = "OOPS %s" % (e,)
+            else:
+                message = translate("userscript not found:")
+                message += " %s" % name
+        elif page and page.startswith("tvspielfilm"):
+            # decode the strings from the remote page
+            date = req.args["date"]
+            time = req.args["time"]
+            channel = req.args["channel"]
+            title = req.args["title"]
+            on_date = re.compile(r"\w\w\s+(\d+)[.](\d+)[.]\s*")
+            on_time = re.compile(r"(\d+:\d+)\s+-\s+(\d+:\d+)")
+            newdate = None
+            newtime = None
+            endtime = None
+            m = on_date.match(date)
+            if m:
+                day = m.group(1)
+                month = m.group(2)
+                current = datetime.datetime.now()
+                year = current.year
+                if int(month) < current.month:
+                    year += 1  
+                newdate = datetime.datetime(year, int(month), int(day))
+            m = on_time.match(time)
+            if m:
+                newtime = m.group(1)
+                endtime = m.group(2)
+            channel = self.map_channel(channel)
+            message = self.save(req, newdate, newtime, endtime, channel, title, page)
+
+        userscripts = []
+        for filename in os.listdir(userscripts_dir):
+            if filename.endswith(".user.js"):
+                userscripts += [ filename ]
+
+        add_stylesheet(req, 'common/css/wiki.css')
+        add_stylesheet(req, PACKAGE+'/css/dvbcronrecording.css')
+        add_script(req, 'common/js/trac.js')
+        add_script(req, 'common/js/wikitoolbar.js')
+
+        # passing variables to template
+        data = {}
+        data['message'] = message
+        data['title'] = translate('Userscript List')
+        data['scripts_url'] = self.get_scripts_url("")
+        data['install_url'] = self.get_install_url("")
+        data["_pagenum"] = req.args.get("_pagenum", "0")
+        data["_pagesize"] = req.args.get("_pagesize", "10")
+        data['datalist'] = Paginator(userscripts, int(data["_pagenum"]), int(data["_pagesize"]))
+        data['author'] = req.authname or ""
+        data['_'] = translate
+
+        return ('programguidescripts.html', data, None)
+
+    def get_scripts_dir(self):
+        htdocsdir = self.get_htdocs_dirs()[0][1]
+        return os.path.join(str(htdocsdir), "js")
+    def get_install_url(self, name):
+        return "%s/%s/install/%s" % (URL, SUBURL, name)
+    def get_scripts_url(self, name):
+        return ("/chrome/"+PACKAGE+"/js/"+name)
+
+    def save(self, req, newdate, newtime, endtime, channel, title, source):
+        onlydate = newdate.strftime("%d.%m.")
+        weekday = newdate.weekday()
+        session = db_cnx(self.env)
+        q = session.query(RecordingList).filter_by(title = title, onlydate = onlydate)
+        existing = q.count()
+        if existing > 0:
+            return "EXISTS"
+        item = RecordingList()
+        item.channelname = channel
+        item.newtime = newtime
+        item.endtime = endtime
+        item.extratime = 9
+        item.weekday = weekday
+        item.onlydate = onlydate
+        item.status = "ok"
+        item.priority = "3"
+        item.title = title
+        session.add(item)
+        datespec = "[%s-%s%s]" % (item.newtime, 
+                                item.endtime, 
+                                item.onlydate 
+                               ) 
+        changed = "new recording on %s %s %s (from %s)" % (item.channelname,
+                                                 datespec,
+                                                 item.title,
+                                                 source)
+        session.add(RecordingChanges(tablename="RecordingList",
+                                  username=req.authname,
+                                  modified=datetime.datetime.now(),
+                                  changed=changed))
+        session.flush()
+        return u"OK %s" % item.id
+    def map_channel(self, channel):
+        """ FIXME: hardcoded """
+        if channel in ["Das Erste"]:
+            return "1ard"
+        if channel in ["ZDF"]:
+            return "2zdf"
+        if channel in [ "RTL" ]:
+            return "rtl"
+        if channel in [ "SAT.1" ]:
+            return "sat1"
+        if channel in [ "ProSieben" ]:
+            return "pro7"
+        if channel in [ "kabel eins" ]:
+            return "kabel1"
+        if channel in [ "RTL II" ]:
+            return "rtl2"
+        if channel in [ "VOX" ]:
+            return "vox"
+        if channel in [ "ARTE" ]:
+            return "arte"
+        if channel in [ "TELE 5" ]:
+            return "tele5"
+        return channel

src/dvbcronrecording/templates/channelsconf_nav.html

         <li><a href="${href.recording('channelsconf/list/radio')}">${_('radio channels')}</a></li>
         <li><a href="${href.recording('channelsconf/list')}">${_('channel.conf show')}</a></li>
         <li>&nbsp;<a href="${href.recording('channeltuning/list')}">${_('tuning list')}</a></li>
+        <li><a href="${href.recording('programguide')}">${_('program guide')}</a></li>
   </ul>
   

src/dvbcronrecording/templates/programguidescripts.html

+<!DOCTYPE html
+    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:py="http://genshi.edgewall.org/"
+      xmlns:xi="http://www.w3.org/2001/XInclude">
+  <xi:include href="layout.html" />
+  <xi:include href="macros.html" />
+<head><title>${title}</title></head>
+<body>
+<div id="ctxtnav" class="nav">
+</div>
+  <xi:include href="channels_nav.html" />
+  <xi:include href="recording_nav.html" />
+
+<div id="content">
+<h2>${title}</h2>
+ 
+<py:if test="message">
+  <div class="error">
+    ${message}
+  </div>
+</py:if>
+
+<table>
+<tr>
+<th>Original</th>
+<th>Installation</th>
+</tr>
+<tr py:for="item in datalist">
+  <td><a href="${href(scripts_url)+'/'+item}">${item}</a></td>
+  <td><a href="${href(install_url)+'/'+item}">${item}</a></td>
+</tr>
+</table>
+  <xi:include href="paginator_datalist.html" />
+</div>
+
+</body>
+</html>
     'DvbCronRecording.channelsconf = dvbcronrecording.channelsconf',
     'DvbCronRecording.files = dvbcronrecording.files',
     'DvbCronRecording.tuning = dvbcronrecording.tuning',
+    'DvbCronRecording.programguide = dvbcronrecording.programguide',
   ]},
   keywords = 'dvb trac recorder',
   author = 'Guido Draheim',