Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-casttube for openSUSE:Factory
checked in at 2022-01-15 20:05:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-casttube (Old)
and /work/SRC/openSUSE:Factory/.python-casttube.new.1892 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-casttube"
Sat Jan 15 20:05:16 2022 rev:2 rq:946642 version:0.2.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-casttube/python-casttube.changes
2019-01-03 18:08:40.628031147 +0100
+++
/work/SRC/openSUSE:Factory/.python-casttube.new.1892/python-casttube.changes
2022-01-15 20:05:28.433771828 +0100
@@ -1,0 +2,7 @@
+Sat Jan 15 15:29:36 UTC 2022 - Dirk M??ller <[email protected]>
+
+- update to 0.2.1:
+ * You can now set a starting time for a video
+ * Session data and queued videos info
+
+-------------------------------------------------------------------
Old:
----
LICENSE
casttube-0.2.0.tar.gz
New:
----
casttube-0.2.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-casttube.spec ++++++
--- /var/tmp/diff_new_pack.GsEuzQ/_old 2022-01-15 20:05:28.861772162 +0100
+++ /var/tmp/diff_new_pack.GsEuzQ/_new 2022-01-15 20:05:28.865772165 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-casttube
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2022 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,14 +18,13 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-casttube
-Version: 0.2.0
+Version: 0.2.1
Release: 0
Summary: YouTube chromecast api
License: MIT
Group: Development/Languages/Python
-Url: http://github.com/ur1katz/casttube
+URL: http://github.com/ur1katz/casttube
Source:
https://files.pythonhosted.org/packages/source/c/casttube/casttube-%{version}.tar.gz
-Source1:
https://raw.githubusercontent.com/ur1katz/casttube/master/LICENSE
BuildRequires: %{python_module setuptools}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
@@ -38,7 +37,6 @@
%prep
%setup -q -n casttube-%{version}
-cp %{SOURCE1} .
%build
%python_build
@@ -46,6 +44,7 @@
%install
%python_install
%python_expand %fdupes %{buildroot}%{$python_sitelib}
+rm -v %{buildroot}%{_prefix}/LICENSE
%files %{python_files}
%doc README.md
++++++ casttube-0.2.0.tar.gz -> casttube-0.2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/casttube-0.2.0/LICENSE new/casttube-0.2.1/LICENSE
--- old/casttube-0.2.0/LICENSE 1970-01-01 01:00:00.000000000 +0100
+++ new/casttube-0.2.1/LICENSE 2018-06-01 09:23:27.000000000 +0200
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Uri Katz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/casttube-0.2.0/PKG-INFO new/casttube-0.2.1/PKG-INFO
--- old/casttube-0.2.0/PKG-INFO 2018-09-21 07:48:58.000000000 +0200
+++ new/casttube-0.2.1/PKG-INFO 2020-04-08 14:46:03.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: casttube
-Version: 0.2.0
+Version: 0.2.1
Summary: YouTube chromecast api
Home-page: http://github.com/ur1katz/casttube
Author: Uri Katz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/casttube-0.2.0/casttube/YouTubeSession.py
new/casttube-0.2.1/casttube/YouTubeSession.py
--- old/casttube-0.2.0/casttube/YouTubeSession.py 2018-06-16
09:47:44.000000000 +0200
+++ new/casttube-0.2.1/casttube/YouTubeSession.py 2020-04-08
14:30:51.000000000 +0200
@@ -1,15 +1,19 @@
import re
+import json
+from html.parser import HTMLParser
import requests
YOUTUBE_BASE_URL = "https://www.youtube.com/"
BIND_URL = YOUTUBE_BASE_URL + "api/lounge/bc/bind"
LOUNGE_TOKEN_URL = YOUTUBE_BASE_URL +
"api/lounge/pairing/get_lounge_token_batch"
+QUEUE_AJAX_URL = YOUTUBE_BASE_URL + "watch_queue_ajax"
HEADERS = {"Origin": YOUTUBE_BASE_URL, "Content-Type":
"application/x-www-form-urlencoded"}
LOUNGE_ID_HEADER = "X-YouTube-LoungeId-Token"
REQ_PREFIX = "req{req_id}"
+WATCH_QUEUE_ITEM_CLASS = 'yt-uix-scroller-scroll-unit watch-queue-item'
GSESSION_ID_REGEX = '"S","(.*?)"]'
SID_REGEX = '"c","(.*?)",\"'
@@ -26,18 +30,35 @@
ACTION_REMOVE = "removeVideo"
ACTION_INSERT = "insertVideo"
ACTION_ADD = "addVideo"
-
+ACTION_GET_QUEUE_ITEMS = "action_get_watch_queue_items"
GSESSIONID = "gsessionid"
+LOUNGEIDTOKEN = "loungeIdToken"
CVER = "CVER"
+TYPE = "TYPE"
RID = "RID"
SID = "SID"
VER = "VER"
+AID = "AID"
+CI = "CI"
BIND_DATA = {"device": "REMOTE_CONTROL", "id": "aaaaaaaaaaaaaaaaaaaaaaaaaa",
"name": "Python",
"mdx-version": 3, "pairing_type": "cast", "app":
"android-phone-13.14.55"}
+class QueueHTMLParser(HTMLParser):
+ def __init__(self):
+ self.queue_items = []
+ super().__init__()
+
+ def handle_starttag(self, tag, attrs):
+ if tag == "li":
+ attributes = dict((x, y) for x, y in attrs)
+ if 'class' in attributes.keys():
+ if attributes['class'] == WATCH_QUEUE_ITEM_CLASS:
+ self.queue_items.append(attributes)
+
+
class YouTubeSession(object):
""" The main logic to interact with YouTube cast api."""
@@ -57,15 +78,16 @@
else:
return False
- def play_video(self, video_id, list_id=""):
+ def play_video(self, video_id, list_id="", start_time="0"):
"""
Play video(video_id) now. This ignores the current play queue order.
- :param list_id: list id for playing playlist
...youtube.com/watch?v=VIDEO_ID&list=LIST_ID
:param video_id: YouTube video id(http://youtube.com/watch?v=video_id)
+ :param list_id: list id for playing playlist
...youtube.com/watch?v=VIDEO_ID&list=LIST_ID
+ :param start_time: starting time of the video in seconds
"""
# We always want to start a new session here to ensure an empty queue.
self._start_session()
- self._initialize_queue(video_id, list_id)
+ self._initialize_queue(video_id, list_id, start_time)
def add_to_queue(self, video_id):
"""
@@ -91,6 +113,49 @@
def clear_playlist(self):
self._queue_action('', ACTION_CLEAR)
+ def get_session_data(self):
+ """
+ Get data about the current active session using an xmlhttp request.
+ :return: List of session attributes
+ """
+ url_params = {LOUNGEIDTOKEN: self._lounge_token, VER: 8, "v": 2, RID:
"rpc", SID: self._sid,
+ GSESSIONID: self._gsession_id, TYPE: "xmlhttp", "t": 1,
AID: 5, CI: 1}
+ url_params.update(BIND_DATA)
+ response = self._do_post(BIND_URL, headers={LOUNGE_ID_HEADER:
self._lounge_token},
+ session_request=True, params=url_params)
+ response_text = response.text
+ response_text = response_text.replace("\n", "")
+ response_list = json.loads(response_text[response_text.find("["):])
+ response_list = [v for k, v in response_list]
+ return response_list
+
+ def get_queue_playlist_id(self):
+ """
+ Get the current queue playlist id.
+ :return: queue playlist id or None
+ """
+ session_data = self.get_session_data()
+ for v in session_data:
+ if v[0] == "nowPlaying":
+ if v[1]["listId"]:
+ return v[1]["listId"]
+ return None
+
+ def get_queue_videos(self):
+ """
+ Get the video id, video title and uploader username for videos
currently in the queue.
+ :return: index, video id, title, username or {} if no active playlist
id is found for the session
+ """
+ queue_playlist_id = self.get_queue_playlist_id()
+ if not queue_playlist_id:
+ return {}
+ url_params = {ACTION_GET_QUEUE_ITEMS: 1, "list": queue_playlist_id}
+ response = self._do_post(QUEUE_AJAX_URL, headers={LOUNGE_ID_HEADER:
self._lounge_token},
+ session_request=False, params=url_params)
+ parser = QueueHTMLParser()
+ parser.feed(response.json()['html'])
+ return parser.queue_items
+
def _start_session(self):
self._get_lounge_id()
self._bind()
@@ -126,13 +191,13 @@
self._sid = sid.group(1)
self._gsession_id = gsessionid.group(1)
- def _initialize_queue(self, video_id, list_id=""):
+ def _initialize_queue(self, video_id, list_id="", start_time="0"):
"""
Initialize a queue with a video and start playing that video.
"""
request_data = {LIST_ID: list_id,
ACTION: ACTION_SET_PLAYLIST,
- CURRENT_TIME: "0",
+ CURRENT_TIME: start_time,
CURRENT_INDEX: -1,
AUDIO_ONLY: "false",
VIDEO_ID: video_id,
@@ -172,7 +237,7 @@
req_count = REQ_PREFIX.format(req_id=self._req_count)
return {req_count + k if k.startswith("_") else k: v for k, v in
param_dict.items()}
- def _do_post(self, url, data, params=None, headers=None,
session_request=False):
+ def _do_post(self, url, data=None, params=None, headers=None,
session_request=False):
"""
Calls requests.post with custom headers,
increments RID(request id) on every post.
@@ -190,7 +255,6 @@
else:
headers = HEADERS
response = requests.post(url, headers=headers, data=data,
params=params)
-
# 404 resets the sid, session counters
# 400 in session probably means bad sid
# If user did a bad request (eg. remove an non-existing video from
queue) bind restores the session.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/casttube-0.2.0/casttube.egg-info/PKG-INFO
new/casttube-0.2.1/casttube.egg-info/PKG-INFO
--- old/casttube-0.2.0/casttube.egg-info/PKG-INFO 2018-09-21
07:48:58.000000000 +0200
+++ new/casttube-0.2.1/casttube.egg-info/PKG-INFO 2020-04-08
14:46:03.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: casttube
-Version: 0.2.0
+Version: 0.2.1
Summary: YouTube chromecast api
Home-page: http://github.com/ur1katz/casttube
Author: Uri Katz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/casttube-0.2.0/casttube.egg-info/SOURCES.txt
new/casttube-0.2.1/casttube.egg-info/SOURCES.txt
--- old/casttube-0.2.0/casttube.egg-info/SOURCES.txt 2018-09-21
07:48:58.000000000 +0200
+++ new/casttube-0.2.1/casttube.egg-info/SOURCES.txt 2020-04-08
14:46:03.000000000 +0200
@@ -1,3 +1,4 @@
+LICENSE
README.md
setup.cfg
setup.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/casttube-0.2.0/setup.py new/casttube-0.2.1/setup.py
--- old/casttube-0.2.0/setup.py 2018-09-21 07:34:25.000000000 +0200
+++ new/casttube-0.2.1/setup.py 2020-04-08 14:40:53.000000000 +0200
@@ -4,7 +4,7 @@
long_description = fh.read()
setup(name='casttube',
- version='0.2.0',
+ version='0.2.1',
description='YouTube chromecast api',
long_description=long_description,
long_description_content_type="text/markdown",
@@ -12,6 +12,7 @@
author='Uri Katz',
author_email='[email protected]',
license='MIT',
+ data_files = [("", ["LICENSE"])],
packages=['casttube'],
zip_safe=False,
keywords = ['youtube', 'chromecast', 'youtube-api'],