Filme nach Zeit X automatisch als ungesehen markieren

  • Erste Erkenntnis....

    json.load ist was anderes als json.loads ;)

    Das eine liest von einer Datei und das andere von einem String. Das muss man erstmal wissen ;)

  • @PvD

    Vielleicht kannst du hier schon mal unterstützen ;)

    Das funktioniert soweit und durch die Anpassung des Datums (habe ich halt in dem Fall mal hart eingetragen) bekomme ich in einem Dialog auch nur einen einzigen Film aus meiner Dateibank angezeigt.

    Soweit so gut....führe ich das Script aber nun ein 2. Mal aus, dann bekomme ich eine Notification angezeigt welche mir sagt, dass ich das Logfile anschauen soll. Da steht dann:

    https://paste.kodi.tv/osotugazax

    Und das verstehe ich gerade nicht, warum das nur beim 2. Durchlauf der Fall ist.

    Starte ich Kodi neu, dann läuft das einwandfrei wieder für 1 Mal durch. Es klingt für mich irgendwie so, als gäbe es ein Problem mit einer der Variablen, dass die nicht aufgerufen werden können. Ich verstehe halt nur nicht warum.

    Danke im Voraus.

  • @PvD (sorry, wenn ich dich so oft pinge....)

    Ich habe noch ein wenig geforscht und ein paar Logmessages ins Kodi Log gehauen. Mir fällt auf, dass o. g. Fehler nur dann auftritt, wenn

    • ich das script ein 2. Mal ausführe
    • das Script wieder an eine Stelle kommt wo der Eintrag in der DB ein "lastplayed"-value hat.

    Der Hase liegt also tatsächlich irgendwo in Zeile 38 im Pfeffer

    Und ich verstehe es tatsächlich immer noch nicht. Ich schreibe einen String in last_p und lasse den in Zeile 38 in ein Datumsformat wandeln. Warum klappt das beim ersten Mal und warum ist es beim 2. Mail ein "NoneType"?

  • datetime.datetime.strptime() unter Python ist mehr oder weniger kaputt. Es liegt nicht - wie man evtl. vermutet - an der Variablen last_p, sondern (unter ganz bestimmnten Laufzeitbedingungen) am datetime-Modul.

    Das führt Dich dahin (auch mit einer Lösung): https://stackoverflow.com/questions/4039…e-in-python-3-4
    Bugreport: https://bugs.python.org/issue27400

    Selbst Google ist nicht davor gefeit. Das oauth-Modul besitzt das gleich Issue, weswegen es bei uns im Repo ein gefixtes oauth gibt. Trotz Bugreport ist sich Google aber zu fein, das in Ihren APIs zu fixen. Pech gehabt.

    Lange Rede kurzer Sinn, versuche mal anstelle von:


    Code
    last_date = datetime.datetime.strptime(last_p, "%Y-%m-%d %H:%M:%S")

    Quellcode

    Python
    try:
        res = datetime.datetime.strptime(last_p, "%Y-%m-%d %H:%M:%S")
    except TypeError:
        res = datetime.datetime(*(time.strptime(last_p, "%Y-%m-%d %H:%M:%S")[0:6]))

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • Nicht vergessen, dass man time dann natürlich auch noch importieren muss.

    Nachdem der Fehler jetzt gelöst ist (das Problem kannte ich noch gar nicht), würde ich ein paar Verbesserungen am Code vorschlagen:


    Statt import datetime würde ich direkt from datetime import datetime importieren. Dann wird weniger importiert, was das Ganze minimal schneller machen sollte und man spart sich etwas Schreibarbeit, weil man z.B. in Zeile 10 statt datetime.datetime.now() jetzt datetime.now() nutzen kann. Wenn man sehr schreibfaul ist (wie ich), kann man auch from datetime import datetime as dt machen und dann dt.now() nutzen.


    Bei der for-Schleife würde ich so was versuchen:

    Python
    for movie in data['result']['movies']:
        last_p = movie['lastplayed']
        #...

    Dann brauchst du auch die Variable total gar nicht.


    In Zeile 36 würde ich dann gleich 2 Änderungen machen:
    Du überprüfst hier nur, ob last_p ein leerer String ist, oder nicht. Um den Code robuster zu machen, könntest du noch andere Fälle abdecken, indem du einfach nur if last_p: nutzt. Ein leerer String wird nämlich als False interpretiert, genau so wie eine 0 oder None. Alles andere wird als True gewertet (evtl. gibt es noch eine Ausnahme, die mir gerade nicht einfällt).
    Und es ist weniger Schreibarbeit [ag]

    Insgesamt hast du in den letzten Zeilen ziemlich viel Einrückung. So etwas mache ich gerne etwas flacher, indem ich die Logik bei Conditions umdrehe. Also statt

    Python
    if last_p:
        # format string to date
        last_date = datetime.datetime.strptime(last_p, "%Y-%m-%d %H:%M:%S")
        #...

    Würde ich schreiben

    Python
    if not last_p:
        continue
    
    
    # format string to date
    last_date = datetime.datetime.strptime(last_p, "%Y-%m-%d %H:%M:%S")
    #...

    continue bedeutet, dass die for-Schleife mit dem nächsten Element weiter machen soll. Alles darunter wird also nicht mehr ausgeführt, sondern erst wieder mit dem nächsten i bzw. movie


    In Zeile 42 vergleichst du zwei Daten, indem du beide in einen String umwandelst. Das kann schnell zu Fehlern führen. Ich würde lieber if lastp_plus_year < now: machen. Für deine Tests müsstest du now dann eben erzeugen wie bei last_date, also mit strptime von datetime oder time.


    Zu guter Letzt die Variable ans:
    Die wird mit jedem Schritt der for-Schleife wieder überschrieben und enthält am Ende nur den label-Wert des letzten Films. Ich vermute du willst eher eine Liste, d.h. vor die Schleife (Z. 25) kommt ans = list() und in Zeile 43 dann ans.append(str(label))

    Vermutlich musst du aus ans dann in Zeile 46 wieder einen String machen, da weiß ich nicht wie xbmcgui.Dialog().ok() mit einer Liste umgehen würde.

  • Vermutlich musst du aus ans dann in Zeile 46 wieder einen String machen, da weiß ich nicht wie xbmcgui.Dialog().ok() mit einer Liste umgehen würde.

    Ja, das wusste ich sogar schon ;). Aber vielen Dank


    Statt import datetime würde ich direkt from datetime import datetime importieren.

    Das hatte ich schon probiert. Ich konnte dann aber [tt]strptime[/tt| nicht verwenden, wenn ich richtig liege. Das muss ich mir aber nochmal anschauen.

    Vielen Dank für die Hinweise. Ich werds heute Abend umsetzen ;)

  • So...das meiste ist umgesetzt und funktioniert auch schon. Jetzt muss ich noch ein wenig kreativ beim Icon werden und vielleicht baue ich noch ein Setting für die Tage ein.

    Falls jemand noch ne Idee hat, was man noch implementieren könnte, dann bin ich für Vorschläge offen. Werd's dann nachher noch in mein Git pushen

    @PvD @Steevee2 vielen Dank für eure Hilfe. [ay]

  • Habe zwar keinen Anwendungsfall hierfür, aber warum nur Tage bei den Settings anbieten?
    Macht doch drei Variablen rein Tage, Monate und Jahre. So kann dann wirklich jeder nach seinem Geschmack auswählen wann etwas als ungesehen markiert werden soll.

    NAS: Gehäuse: Jonsbo G3, Mainboard: MSI B460M PRO, CPU: Intel Pentium G6400, OS: OMV 6

    Client: NVIDIA Shield Pro 2019

  • Muss ich mir anschauen. Wenn ich nicht ganz falsch liege, dann bietet mir "Timedelta" (was offensichtlich für das hinzufügen von Tagen verantwortlich ist) die Einheit "Tage" als Maximum an.

    Vielleicht kann ich ein anderes Modul verwenden.

    Was ich noch mit einbauen werde, sind Episoden.

  • timedelta berechnet auch Zeitdifferenzen in die Vergangenheit, also nicht nur in die Zukunft.

    Python
    from datetime import datetime, timedelta
    
    
    dtnow = datetime.now()
    one_year_back = dtnow - timedelta(days=365)
    five_years_back = dtnow - 5 * timedelta(days=365) # Punktrechnung geht vor Strichrechnung

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

    Einmal editiert, zuletzt von PvD (29. Januar 2022 um 09:00) aus folgendem Grund: Quellcode berichtigt.

  • Ja, das ist klar. Ich kann eine Berechnung machen. Die kann ich entweder im Script machen oder es dem User überlassen, welchen Wert er da eintragen möchte und das als Setting verfügbar machen.

    Ich kann dem User aber keine Möglichkeit geben eine bestimmte Anzahl an Monaten zu definieren, da ich nur Tage berechnen kann und jeder Monat unterschiedliche Anzahl an Tagen hat. Ich könnte einen Monatsdurchschnitt berechnen: 365 / 12, was dann 30,4166666667 Tage wären und so könnte ich dann einen Montag berechen:


    Code
    monat = dtnow + 30,4166666667 * timedelta(days=1)

    (Ich glaube die Klammern bei dtnow() sind nicht korrekt....zumindest wirft es mit einen Fehler, wenn ich dein Script oben kopiere und ausführe ;) ohne die Klammern klappt es)

    Das finde ich aber ziemlich ungenau.

    Und ja...das ich "timedelta" zusätzlich importieren muss, habe ich auch schon gemerkt ;). Daher habe ich auch einfach "datetime" komplett importiert.

    Weiter ist das Problem, welches ich habe (weswegen ich es vielleicht so umständlich geschrieben habe), dass ich verschiedene Typen bekomme:

    in deinem Beispiel oben ist "dtnow" ein Typ <class 'datetime.datetime'> und gibt mir bei einer Ausgabe auch Millisekunden mit, die ich zum Vergleich nicht brauche/möchte. Also muss ich die einmal wandeln (mit strftime). Nach der Wandlung ist es dann aber ein Typ "str".

    Aus dem JSON bekomme ich einen Typ "str"...um damit Berechnungen via "timedelta" machen zu können muss ich den String erst wieder zurück zu einem Typ "<class 'datetime.datetime'>" machen (via "strptime")

    Ich werde auf jeden Fall mal den import anpassen....datetime und timedelta von datetime schein tatsächlich ausreichend zu sein

    In der Zeile 42 kann ich mit wahrscheinlich einen "str" im Vergleich sparen, da kodi_time schon ein "str" ist (entweder weil ich es so rein schreibe bzw. durch die Wandlung mit "strftime"). In jedem Fall muss es auf beiden Seiten ein String sein, damit ich es vergleichen kann. So zumindest mein Verständnis bisher ;)

  • In jedem Fall muss es auf beiden Seiten ein String sein, damit ich es vergleichen kann. So zumindest mein Verständnis bisher

    Nein. Datetime-Objekte kann man direkt vergleichen. Ein Stringvergleich kann gehörig in die Hose gehen, z.B. ergibt print('01.12.2020' < '30.11.2020') True, was aber bezogen auf das Datum nicht stimmt. Der Stringvergleich vergleicht zeichenweise von Anfang beginnend beide Zeichenketten und da ist '0' schonmal kleiner als '3'. Ein direkter Vergleich der Datetimeobjekte macht das richtig (dazu sind sie ja da).


    Python
    from datetime import datetime
    dez = datetime.strptime('01.12.2020', '%d.%m.%Y')
    nov = datetime.strptime('30.11.2020', '%d.%m.%Y')
    print(dez < nov)
    
    
    ==> False

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • Ok...ist es dann beim Vergleich egal ob es Millisekunden hat oder nicht? Denn dann würde ich nur den JSON Wert zu einem datetime-Objekt wandeln und könnte so dann diese Werte miteinander vergleichen.

    Vom JSON bekomme ich halt nur "YYYY-mm-dd HH:MM:SS" als String

  • Denn dann würde ich nur den JSON Wert zu einem datetime-Objekt wandeln und könnte so dann diese Werte miteinander vergleichen.

    Das ist der richtige Weg. Das JSON-Format würe ich als Konstante nach den Imports definieren, dann hast Du weniger Schreibkram: JSON_TIME_FMT = '%Y-%m-%d %H:%M:%S', bei der Umwandlung in datetime einfach nur (Zeile 38): last_date = datetime.datetime.strptime(last_p, JSON_TIME_FMT)

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • Ich habe mal noch den Formatkram oben geändert. Es ist noch früh und mein Hirn arbeitet noch mechanisch...

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • Es geht um den Stringvergleich ansich und nicht um die deutsche Schreibweise eines Datums.

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • Bei der chinesischen auch nicht und selbst bei der amerikanischen mit '2020/01/12' oder '2020/12/01' kann man sich nicht sicher sein.

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!