Closed matthuisman closed 6 days ago
Hi, Would it be feasible for supporters to share the 9now addon URL with Tivimate? I'm ok using Kodi, but the wife approval factor of now using 2 apps to watch TV is quite low!
getting tivimate to get a url from kodi isnt really possible. youd need to create your own HTTP app somewhere on the network somewhere to fetch and return the url Someone did that on https://github.com/matthuisman/slyguy.addons/issues/825
Ah ok thanks anyhow, I'm only a homelabber running truenas scale, some VM's and Docker Desktop, coding is out of my reach.
Perhaps automation requests are being sent to frequently, and too predictably. Maybe implement it do be done randomly, perhaps once every few hours, then once between 30 and 45 minutes in between.
I suspect it's simply seeing multiple ips using the same token. I've heard users using a dontbugme login creds having that account suspended too.
On Sun, 4 Aug 2024, 16:29 paul19920801, @.***> wrote:
Perhaps automation requests are being sent to frequently, and too predictably. Maybe implement it do be done randomly, perhaps once every few hours, then once between 30 and 45 minutes in between.
— Reply to this email directly, view it on GitHub https://github.com/matthuisman/i.mjh.nz/issues/116#issuecomment-2267299884, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPQAKLO5GAWGZ22TKOYMSTZPWU4HAVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRXGI4TSOBYGQ . You are receiving this because you authored the thread.Message ID: @.***>
I've managed to successfully extract a tokenized url for each channel manually from 9now.com.au, and the streams still work after 48 hours. Tested in VLC, Chrome browser and Tivimate. They also work with and without VPN so at least 2 IPs. I don't want to share them incase more than 2 IPs triggers an account suspension.
Requires the M3U Sniffer extension for Chrome. Navigate to each channel on 9now and grab the url that begins with either of the two syntaxes below:
https://csm-e-nineau1-eb.bln1.yospace.com/csm/extlive/nnaprd01,prod-simulcast-....
https://9now-livestreams-fhd-t.akamaized.net/t/prod/simulcast/......
It's a bloody big url with over 1500 characters. But they work so far.
That's the exact same as we used to use. They will get blocked when you have as many users using it.
On Sun, 4 Aug 2024, 17:50 oismacca, @.***> wrote:
I've managed to successfully extract a tokenized url for each channel manually from 9now.com.au, and the streams still work after 48 hours. Tested in VLC, Chrome browser and Tivimate. They also work with and without VPN so at least 2 IPs. I don't want to share them incase more than 2 IPs triggers an account suspension.
Requires the M3U Sniffer https://chromewebstore.google.com/detail/m3u8-sniffer-tv-find-and/akkncdpkjlfanomlnpmmolafofpnpjgn extension for Chrome. Navigate to each channel on 9now and grab the url that begins with either of the two syntaxes below:
https://csm-e-nineau1-eb.bln1.yospace.com/csm/extlive/nnaprd01,prod-simulcast-.. ..
https://9now-livestreams-fhd-t.akamaized.net/t/prod/simulcast/......
It's a bloody big url with over 1500 characters. But they work so far.
— Reply to this email directly, view it on GitHub https://github.com/matthuisman/i.mjh.nz/issues/116#issuecomment-2267354311, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPQAKK2MD2YG5QV2AUT2BLZPW6MBAVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRXGM2TIMZRGE . You are receiving this because you authored the thread.Message ID: @.***>
Do you know if these urls eventually expire? I'm surprised I'm getting 48+ hours out of them so far.
What would it require to import the tokenized urls into nextpvr?
I'm thinking along the lines of an app/webserver which automatically do it - this would require each user to use their own token, which should automatically get generated, then the url that's exported from the app is what one would import into nextpvr.
This is what my server does. It uses a constant url that redirects to latest streams. There code floating around that's copied the auth etc from my plugin. It just gets the url and then 302 redirect to the latest.
There is even my kodi.proxy which can run my addon's outside of Kodi to get the links etc. ppl use that with tvheadend.
It's still not an easy solution. But if anyone has a server running, not too hard to setup your own redirect service using your own auth
On Sun, 4 Aug 2024, 18:42 paul19920801, @.***> wrote:
What would it require to import the tokenized urls into nextpvr?
I'm thinking along the lines of an app/webserver which automatically do it
- this would require each user to use their own token, which should automatically get generated, then the url that's exported from the app is what one would import into nextpvr.
— Reply to this email directly, view it on GitHub https://github.com/matthuisman/i.mjh.nz/issues/116#issuecomment-2267370841, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPQAKPMFTQQM3FUNMIDVILZPXENFAVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRXGM3TAOBUGE . You are receiving this because you authored the thread.Message ID: @.***>
If anybody gets said redirect server working as a docker container that would be brilliant!
I hope there is a fix. wife is on my case.
But if anyone has a server running, not too hard to setup your own redirect service using your own auth
I've been trying to work out how they generate the token. I get tokenized urls for the SBS streams which is an easy php redirect that calls an api via curl with the right auth headers. The results in a json with the stream url. But it looks like 9now uses some on-the-fly base64 stuff across multiple js scripts to generate the token instead of an api call. It's like they're hiding the token other than in the url? Bit above my head I think, my skills go as far as php/curl/java.
everything you need is in my slyguy 9now plugin or that other code above
Just want to share these flask apps that have been tested on Ubuntu 24.04 server. All codes here are based entirely on Matt's 9now addon so all credits go to him.
flask app to activate device and acquire private refresh_token:
` from flask import Flask, render_template_string, jsonify, redirect, url_for import time import json import os import requests from urllib.parse import urlencode from requests.exceptions import RequestException, Timeout, ConnectionError import threading
app = Flask(name)
HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36', } AUTH_URL = 'https://login.nine.com.au/api/device{}' REFRESH_TOKEN_PATH = 'your_local_path/refresh_token.json' ACTIVATION_URL = 'https://login.nine.com.au/device?client_id=9now-web'
device_code_data = None device_code_lock = threading.Lock()
class API: def init(self): self.session = requests.Session() self.session.headers.update(HEADERS)
def _make_request(self, method, url, **kwargs):
max_retries = 3
for attempt in range(max_retries):
try:
response = method(url, **kwargs, timeout=60)
response.raise_for_status()
return response
except (Timeout, ConnectionError) as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt) # Exponential backoff
except RequestException as e:
raise
def device_code(self):
params = {
'client_id': '9nowdevice',
}
response = self._make_request(self.session.post, AUTH_URL.format('/code'), params=params, data={})
return response.json()
def device_login(self, auth_code, device_code):
params = {
'auth_code': auth_code,
'device_code': device_code,
'client_id': '9nowdevice',
'response_types': 'id_token',
}
response = self._make_request(self.session.get, AUTH_URL.format('/token'), params=params)
data = response.json()
if 'accessToken' not in data:
return False
# Store the refresh token in the session cookies
self.session.cookies.set('refresh_token', data['refresh_token'])
return True
api = API()
def get_new_device_code(): global device_code_data with device_code_lock: try: device_code_data = api.device_code() print("\nNew Device Code Information:") print(f"Your device code is: {device_code_data['auth_code']}") print(f"Please visit: {ACTIVATION_URL}") print("Enter the device code on that page to activate your device.") except RequestException as e: print(f"Error getting device code: {str(e)}") device_code_data = None
@app.route('/') def index(): get_new_device_code() # Always get a new device code when the page is loaded if device_code_data is None: return "Error getting device code. Please refresh the page to try again.", 500
html = """
<!DOCTYPE html>
<html>
<head>
<title>9Now Device Activation</title>
<script>
function checkStatus() {
fetch('/check_status', {
method: 'POST',
headers: {
'User-Agent': '{{ user_agent }}'
}
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
document.getElementById('status').innerHTML = `
Device activated! Refresh token saved.<br>
Token: ${data.refresh_token}<br>
Saved to: ${data.token_path}<br>
<a href="/">Click here to activate another device</a>
`;
} else if (data.status === 'pending') {
setTimeout(checkStatus, 5000);
} else if (data.status === 'reset') {
window.location.reload();
} else {
document.getElementById('status').innerHTML = 'Error: ' + data.message + ' <a href="/">Click here to try again</a>';
}
})
.catch(error => {
console.error('Error:', error);
setTimeout(checkStatus, 5000);
});
}
</script>
</head>
<body onload="checkStatus()">
<h1>9Now Device Activation</h1>
<p>Your device code is: <strong>{{ device_code }}</strong></p>
<p>Please follow these steps:</p>
<ol>
<li>Visit <a href="{{ activation_url }}" target="_blank">{{ activation_url }}</a> to activate your device.</li>
<li>If you're not already logged in, you'll be asked to log in to your 9Now account.</li>
<li>After logging in (if necessary), enter the code above on that page.</li>
</ol>
<p id="status">Waiting for activation...</p>
</body>
</html>
"""
return render_template_string(html,
device_code=device_code_data['auth_code'],
activation_url=ACTIVATION_URL,
user_agent=HEADERS['User-Agent'])
@app.route('/check_status', methods=['POST']) def check_status(): global device_code_data if device_code_data is None: return jsonify({"status": "reset", "message": "Device code not initialized"})
try:
if api.device_login(device_code_data['auth_code'], device_code_data['device_code']):
refresh_token = api.session.cookies.get('refresh_token')
if refresh_token:
save_refresh_token(refresh_token)
print("Device activated! Refresh token saved.")
return jsonify({
"status": "success",
"message": "Device activated and refresh token saved.",
"refresh_token": refresh_token,
"token_path": REFRESH_TOKEN_PATH
})
else:
return jsonify({"status": "error", "message": "Refresh token not found in cookies."})
else:
return jsonify({"status": "pending", "message": "Waiting for device activation."})
except RequestException as e:
if '422' in str(e):
print("Received 422 error. Device code may be expired or invalid.")
return jsonify({"status": "reset", "message": "Device code expired or invalid. Please refresh the page."})
return jsonify({"status": "error", "message": f"Network error: {str(e)}"})
def save_refresh_token(refresh_token): save_path = os.path.dirname(REFRESH_TOKEN_PATH) if not os.path.exists(save_path): os.makedirs(save_path)
with open(REFRESH_TOKEN_PATH, 'w') as f:
json.dump({'refresh_token': refresh_token}, f)
print(f"Refresh token saved to {REFRESH_TOKEN_PATH}")
if name == 'main': print("Starting 9Now Device Activation server...") print("Please open a web browser and navigate to http://localhost:9000") print(f"Using User-Agent: {HEADERS['User-Agent']}")
app.run(host='0.0.0.0', port=9000)
`
flask app to get Channel 9 NSW live stream:
` import os import json import time import requests from flask import Flask, Response, redirect from urllib.parse import urlencode, parse_qsl import threading import sys from datetime import datetime
HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36', } AUTH_URL = 'https://login.nine.com.au/api/device{}' LIVESTREAM_URL = 'https://api.9now.com.au/ctv/livestreams'
REFRESH_TOKEN_PATH = '/your_local_path/refresh_token.json' CACHE_FILE_PATH = '/your_local_path/channel9_url_cache.json' DEAD_SCRIPT_PATH = '/your_local_path/dead_channel_script.txt'
class Settings: REGION = 'nsw' CHANNEL_REFERENCE = 'live-ch9-syd-ssai' # Reference for Channel 9 Sydney MAX_RETRIES = 5 INITIAL_RETRY_DELAY = 1 # seconds
settings = Settings()
def get_refresh_token(): with open(REFRESH_TOKEN_PATH, 'r') as f: data = json.load(f) return data.get('refresh_token')
def print_with_timestamp(message): print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - {message}")
class API: def init(self): self.session = requests.Session() self.session.verify = True self.session.headers.update(HEADERS) self._access_token = None self._token_expires = 0 self.retry_count = 0 self.url_cache = {} self.is_initial_fetch = True
def _refresh_token(self, force=False):
if not force and self._token_expires > time.time():
return True
refresh_token = get_refresh_token()
params = {
'refresh_token': refresh_token,
'client_id': '9nowdevice',
'response_types': 'id_token',
}
refresh_url = AUTH_URL.format('/refresh-token')
full_url = f"{refresh_url}?{urlencode(params)}"
print_with_timestamp(f"Refreshing Access token: {full_url}")
try:
response = self.session.post(refresh_url, params=params, timeout=30)
response.raise_for_status()
data = response.json()
if 'error' in data:
raise Exception(data['error'])
self._access_token = data['accessToken']
self._token_expires = int(time.time()) + data['expiresIn'] - 30
self.session.headers.update({'Authorization': f'Bearer {self._access_token}'})
print_with_timestamp(f"Access token refreshed successfully. Expires at: {time.ctime(self._token_expires)}")
self.retry_count = 0
return True
except requests.exceptions.RequestException as e:
print_with_timestamp(f"Error refreshing token: {str(e)}")
self.handle_retry()
return False
def handle_retry(self):
self.retry_count += 1
if self.retry_count >= settings.MAX_RETRIES:
print_with_timestamp(f"Max retries ({settings.MAX_RETRIES}) reached. Exiting...")
self.exit_gracefully()
else:
retry_delay = settings.INITIAL_RETRY_DELAY * (2 ** (self.retry_count - 1))
print_with_timestamp(f"Retry {self.retry_count}/{settings.MAX_RETRIES}. Waiting for {retry_delay} seconds before next attempt.")
time.sleep(retry_delay)
def exit_gracefully(self):
with open(DEAD_SCRIPT_PATH, 'w') as f:
f.write(os.path.abspath(__file__))
print_with_timestamp(f"Written to {DEAD_SCRIPT_PATH}. Exiting...")
sys.exit(1)
def channels(self, region='nsw'):
self._refresh_token()
params = {
'device': 'web',
'streamParams': 'web,chrome,windows',
'region': region,
'offset': 0,
}
try:
response = self.session.get(LIVESTREAM_URL, params=params, timeout=60)
response.raise_for_status()
data = response.json()
self.retry_count = 0 # Reset retry count on successful request
return data['data']['getLivestream']
except requests.RequestException as e:
print_with_timestamp(f"Error fetching channels: {str(e)}")
self.handle_retry()
return None
def get_channel9_url(self):
current_time = time.time()
if 'url' in self.url_cache and current_time < self.url_cache['expiry']:
return self.url_cache['url']
if not self._refresh_token():
print_with_timestamp("Failed to refresh token")
return None
try:
data = self.channels(region=settings.REGION)
if data:
for row in data['channels']:
if row['referenceId'] == settings.CHANNEL_REFERENCE:
url = row['stream']['url']
if '?' in url:
url = url.split('?')[0] + '?' + urlencode(parse_qsl(url.split('?')[1]))
self.url_cache = {
'url': url,
'expiry': self._token_expires
}
with open(CACHE_FILE_PATH, 'w') as f:
json.dump(self.url_cache, f)
if self.is_initial_fetch:
print_with_timestamp("Successfully acquired initial URL:")
print(url)
print_with_timestamp(f"Next refresh in {self.format_next_refresh()}")
self.is_initial_fetch = False
else:
print_with_timestamp("Successfully updated URL upon expiry:")
print(url)
print_with_timestamp(f"Next refresh in {self.format_next_refresh()}")
return url
print_with_timestamp("Channel not found in API response.")
return None
else:
print_with_timestamp("No data returned from channels()")
return None
except Exception as e:
print_with_timestamp(f"Error fetching Channel 9 URL: {str(e)}")
return None
def format_next_refresh(self):
sleep_time = max(self._token_expires - time.time(), 60)
hours, remainder = divmod(sleep_time, 3600)
minutes, _ = divmod(remainder, 60)
next_refresh_time = time.localtime(self._token_expires)
return f"{int(hours)} hrs {int(minutes):02d} mins at {time.strftime('%Y-%m-%d %H:%M:%S', next_refresh_time)}"
def initialize_api(): global api api = API() max_attempts = 10 for attempt in range(max_attempts): print_with_timestamp(f"Attempt {attempt + 1}/{max_attempts} to initialize API and fetch initial URL") url = api.get_channel9_url() if url: return True else: print_with_timestamp(f"Failed to acquire initial URL on attempt {attempt + 1}") time.sleep(5) # Wait 5 seconds before retrying
print_with_timestamp(f"Failed to acquire initial URL after {max_attempts} attempts")
return False
def update_url_periodically(): while True: try: url = api.get_channel9_url() if not url: print_with_timestamp("Failed to update URL") time.sleep(max(api._token_expires - time.time(), 60)) except Exception as e: print_with_timestamp(f"Error in periodic update: {str(e)}") time.sleep(60)
app = Flask(name)
@app.route('/9') def get_channel9_live(): url = api.get_channel9_url() if url: print_with_timestamp("Serving cached URL") return redirect(url) else: return Response("Unable to fetch Channel 9 URL", status=500, mimetype='text/plain')
if name == 'main': if initialize_api():
threading.Thread(target=update_url_periodically, daemon=True).start()
# Start the Flask app in production mode with threading
print_with_timestamp("Starting Flask app")
app.run(host='0.0.0.0', port=9001, threaded=True)
else:
print_with_timestamp("Failed to initialize API. Exiting...")
sys.exit(1)
`
I've managed to successfully extract a tokenized url for each channel manually from 9now.com.au, and the streams still work after 48 hours. Tested in VLC, Chrome browser and Tivimate. They also work with and without VPN so at least 2 IPs. I don't want to share them incase more than 2 IPs triggers an account suspension.
Requires the M3U Sniffer extension for Chrome. Navigate to each channel on 9now and grab the url that begins with either of the two syntaxes below:
https://csm-e-nineau1-eb.bln1.yospace.com/csm/extlive/nnaprd01,prod-simulcast-....
https://9now-livestreams-fhd-t.akamaized.net/t/prod/simulcast/......
It's a bloody big url with over 1500 characters. But they work so far.
I have managed to use the sniffer and play on VLC and Chrome , how do you play this in Tivimate ?
Try matching the User-Agent setting in Tivimate (either under Settings > General or Settings > Playlists > [playlist name]) with the user agent in the URL.
On Tue, 6 Aug 2024, 4:24 pm LGSAM59, @.***> wrote:
I've managed to successfully extract a tokenized url for each channel manually from 9now.com.au, and the streams still work after 48 hours. Tested in VLC, Chrome browser and Tivimate. They also work with and without VPN so at least 2 IPs. I don't want to share them incase more than 2 IPs triggers an account suspension.
Requires the M3U Sniffer https://chromewebstore.google.com/detail/m3u8-sniffer-tv-find-and/akkncdpkjlfanomlnpmmolafofpnpjgn extension for Chrome. Navigate to each channel on 9now and grab the url that begins with either of the two syntaxes below:
https://csm-e-nineau1-eb.bln1.yospace.com/csm/extlive/nnaprd01,prod-simulcast-.. ..
https://9now-livestreams-fhd-t.akamaized.net/t/prod/simulcast/......
It's a bloody big url with over 1500 characters. But they work so far.
I have managed to use the sniffer and play on VLC and Chrome , how do you play this in Tivimate ?
— Reply to this email directly, view it on GitHub https://github.com/matthuisman/i.mjh.nz/issues/116#issuecomment-2270679157, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADRL4OBBJRVDXLEYCJXNAILZQCB3RAVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZQGY3TSMJVG4 . You are receiving this because you commented.Message ID: <matthuisman/i. @.***>
This is a very good extension for Chrome/Edge.
https://chromewebstore.google.com/detail/videoplayer-mpdm3u8m3uepg/opmeopcambhfimffbomjgemehjkbbmji
It autoplays and is capable of decrypting WV encrypted videos on the fly if WV keys are provided.
Try matching the User-Agent setting in Tivimate (either under Settings > General or Settings > Playlists > [playlist name]) with the user agent in the URL. … On Tue, 6 Aug 2024, 4:24 pm LGSAM59, @.> wrote: I've managed to successfully extract a tokenized url for each channel manually from 9now.com.au, and the streams still work after 48 hours. Tested in VLC, Chrome browser and Tivimate. They also work with and without VPN so at least 2 IPs. I don't want to share them incase more than 2 IPs triggers an account suspension. Requires the M3U Sniffer https://chromewebstore.google.com/detail/m3u8-sniffer-tv-find-and/akkncdpkjlfanomlnpmmolafofpnpjgn extension for Chrome. Navigate to each channel on 9now and grab the url that begins with either of the two syntaxes below: https://csm-e-nineau1-eb.bln1.yospace.com/csm/extlive/nnaprd01,prod-simulcast-.. .. https://9now-livestreams-fhd-t.akamaized.net/t/prod/simulcast/...... It's a bloody big url with over 1500 characters. But they work so far. I have managed to use the sniffer and play on VLC and Chrome , how do you play this in Tivimate ? — Reply to this email directly, view it on GitHub <#116 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADRL4OBBJRVDXLEYCJXNAILZQCB3RAVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZQGY3TSMJVG4 . You are receiving this because you commented.Message ID: <matthuisman/i. @.>
Thanks , ended up being a poor copy and paste on my part . Now I just need to find a way to link it to a guide and hope it stays live
Thanks , ended up being a poor copy and paste on my part . Now I just need to find a way to link it to a guide and hope it stays live
If you keep the IDs the same as Matt's, you can just use his EPG. No reason why it wouldn't work (unless they have been removed from the EPG).
Edit: Probably should have elaborated. Add those links to a new m3u playlist and make sure you keep the IDs the same as Matt's. Then it should work using his EPG.
I'm at the same position, used the sniffer to get a working url, self hosted YOURLS to get a nice short url, but now can't add it to Tivimate without a matching epg? Matt's is still live, but of course the ID's now do not match.
Update:
I already pipe Xteve to all my Tivimate instances, I will see if I can manually write a m3u file using my links, but with matts ID's.
I got the EPG working nicely, unfortunately the links do not work in Tivimate, even though they are fine in Chrome?
Could someone please post the useragent for Tivimate, pretty sure I have messed it up
I use the Kodi format of Matt's with the pipe, but I have not tested if it is even needed as the M3U has the useragent in it. This is mine
https://9now-livestreams-fhd-t.akamaized.net/VeryLongURLWithLotsInIt|user-agent=Mozilla/5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit/537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome/98.0.4758.102%20Safari/537.36&seekable=0&referer=%20
That's the way. For tivimate just slap on the |user-agent= and profit :)
On Fri, 9 Aug 2024, 18:42 The James, @.***> wrote:
I use the Kodi format of Matt's with the pipe, but I have not tested if it is even needed as the M3U has the useragent in it. This is mine
https://9now-livestreams-fhd-t.akamaized.net/VeryLongURLWithLotsInIt|user-agent=Mozilla/5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit/537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome/98.0.4758.102%20Safari/537.36&seekable=0&referer=%20 https://9now-livestreams-fhd-t.akamaized.net/VeryLongURLWithLotsInIt%7Cuser-agent=Mozilla/5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit/537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome/98.0.4758.102%20Safari/537.36&seekable=0&referer=%20
— Reply to this email directly, view it on GitHub https://github.com/matthuisman/i.mjh.nz/issues/116#issuecomment-2277252552, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPQAKJFTMLPUE76GUE63XTZQRQEXAVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZXGI2TENJVGI . You are receiving this because you authored the thread.Message ID: @.***>
Mine works in Chrome and my media player, tivimate gives me a 302 error.
[link removed]
302 isnt an error. 302 = redirect tivimate needs to follow that redirect
Looks like your URL shortener is mundging it. I am anything but an expert, but if I was you and you are worrying about long URLs, why don't you just make a playlist with a short name and host that. It makes no difference how long the URLs inside that list are. So make a playlist called 9.m3u8 and add all 5 Nine networks channels in that. It will even be shorter than your 'shortened' URL. eg cannardy.com/9.m3u8
Ah ok, that's precisely what i had done, I have a m3u file called channels 9, it contains all five long url's. Tivimate use a short url from Xteve.
I posted the short one for convenience. Though i was testing from it too. I will go add the |useragent to the end of the long urls and test properly thanks.
ahhhhh frustrating, I'm watching the olympics live in Chrome, working fine, then, as soon as I add the pipe on the end thats it, 400 bad request error.
[link removed]
@matthuisman not sure if you know the answer, but figure it might be worth asking. The links contain 2 parameters 'st' and 'exp' which contain timestamps, 'st' looks like start and 'exp' looks like expiry and is exactly 48 hours 'st'. Any chance you happen to know if I can just populate those on a nightly job to keep the links active as I'm sure the token id doesn't change?
ahhhhh frustrating, I'm watching the olympics live in Chrome, working fine, then, as soon as I add the pipe on the end thats it, 400 bad request error.
I know you are just testing, but if you are, why not ignore Chrome and see if it works on TiVi mate? I wouldn't be phased about Chrome as it will already add your useragent. If you still have issues with the pipe, drop the pipe and just add the user agent through TiVi ,ate playlist options?
@trevor68 no. only kodi + tivimate understand the pipe. Itll only work directly into them.... Why overcomplicate everything copy the url from chrome. Add on the |user-agent=.... on the end, put it in a m3u8 file and point tivimate to that file. Done
@jamesgallagher not that easy. there will be a checksum in the url. you can confirm this by attempting to change them If generate checksum over query params doesnt = the checksum on their end then denied
another good call, the media player on W11 plays this link fine, no sound, but I suspect thats a codec issue, as it never did have sound. Have added them all to the m3u file and wandering off to test tivimate now, wish me luck.
if anyone thinks "ill create a short static url that redirects to the long url and share it with everyone" Well done - you've just thought of the i.mjh.nz service :)
The account you used to create the url will most likely suspended and the stream stop working. So, keep your own links just for yourself and they should keep working :)
Totally get it matt, small problem is my links work fine in everything except tivimate, the intended recipient!
[M3U Removed]
why do your links contain: chrome-extension://akkncdpkjlfanomlnpmmolafofpnpjgn/player/player.html?site=https://links.cannardy.com/admin/#
Tivimate wont understand that at all....
For you and everyone else, your playlist should be as simple as
#EXTM3U
#EXTINF:-1 tvg-id="mjh-channel-9-nsw",Channel 9
https://csm-e-nineau1-eb.bln1.yospace.com/csm/ext..............|user-agent=Mozilla/5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit/537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome/98.0.4758.102%20Safari/537.36
#EXTINF:-1 tvg-id="mjh-gem-nsw",9 Gem
https://csm-e-nineau1-eb.bln1.yospace.com/csm/ext..............|user-agent=Mozilla/5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit/537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome/98.0.4758.102%20Safari/537.36
Ah ok, they are the links that the m3u sniffer gave me, I'll try again later.
All sorted, just sharing the M3U via SMB now. Worth noting things get interesting if you have 3 instances of Tivimate.
Once another instance uses the link, they all stop working. You then need to force stop them all, then the first one to grab the link works, otherwise 403 errors for all.
Haha , I just spent an hour or so trying to setup , kept getting 403 errors on Tivimate , I then realized I still had the stream running on my laptop . All good now
What would it require to import the tokenized urls into nextpvr?
I'm thinking along the lines of an app/webserver which automatically do it - this would require each user to use their own token, which should automatically get generated, then the url that's exported from the app is what one would import into nextpvr.
@paul19920801 I'm going to try to fix myu NextPVR over the weekend, but essentially, my plan is to simply post the link into an Extra. I already have extras for Channel 7 and Channel 9 so I can use Streamlink rather than ffmpeg, which seems to work better, so, it's simply a case of replacing Matt's links with the direct link.
It's also easy to test with streamlink, you just need to paster the link into the streamlink command-line and channel 9 should pop up on the screen. If this works, then NextPVR is golden.
There are a bunch of instructions on the NextPVR forums on how to set up extras is you haven't done this before.
Hey - question for the experts... I'm successfully using the tokenized urls from m3u sniffer. Thank you to the folks that figured that out! My VPS is in Sydney and I'm directed to the Sydney streams. Looking at the URL there's a "simulcast-syd-ch9-hls" that I thought I might just switch to "bri" for the Brisbane streams but no luck. By chance anyone know how/if I can get streams for the other regions? Thanks!
My kodi plugin has the code you can use to request different regions
On Sat, 10 Aug 2024, 15:15 keehan-git, @.***> wrote:
Hey - question for the experts... I'm successfully using the tokenized urls from m3u sniffer. Thank you to the folks that figured that out! My VPS is in Sydney and I'm directed to the Sydney streams. Looking at the URL there's a "simulcast-syd-ch9-hls" that I thought I might just switch to "bri" for the Brisbane streams but no luck. By chance anyone know how/if I can get streams for the other regions? Thanks!
— Reply to this email directly, view it on GitHub https://github.com/matthuisman/i.mjh.nz/issues/116#issuecomment-2278957381, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPQAKJ36DNHJUP5ZOIEVJLZQWAVXAVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZYHE2TOMZYGE . You are receiving this because you were mentioned.Message ID: @.***>
What's the latest on getting Nine channels back in NextPVR? I wish that NextPVR had the ability to FTA but encrypted channels using either cleartype or Widevine - they can be played back with FFplay with appropriate keys - should be fairly easy to pipe the output in FFplay, to ffmpeg, and then onto NextPVR, but some things are more complicated than they appear - but if encrypted links were supported, it would make my life, so much easier...
The 9 channels are not encrypted. The issue is their tokens. Once things cool down, I'll try get a docker container up for a redirect service that can just hook into my kodi plugins (without Kodi) so no need to duplicate all the python
On Sun, 11 Aug 2024, 11:25 paul19920801, @.***> wrote:
What's the latest on getting Nine channels back in NextPVR? I wish that NextPVR had the ability to FTA but encrypted channels using either cleartype or Widevine - they can be played back with FFplay with appropriate keys - should be fairly easy to pipe the output in FFplay, to ffmpeg, and then onto NextPVR, but some things are more complicated than they appear - but if encrypted links were supported, it would make my life, so much easier...
— Reply to this email directly, view it on GitHub https://github.com/matthuisman/i.mjh.nz/issues/116#issuecomment-2282311358, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABPQAKIUFP2VXM7KHSRM2O3ZQ2OP3AVCNFSM6AAAAABL3YHZCGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEOBSGMYTCMZVHA . You are receiving this because you were mentioned.Message ID: @.***>
What's the latest on getting Nine channels back in NextPVR? I wish that NextPVR had the ability to FTA but encrypted channels using either cleartype or Widevine - they can be played back with FFplay with appropriate keys - should be fairly easy to pipe the output in FFplay, to ffmpeg, and then onto NextPVR, but some things are more complicated than they appear - but if encrypted links were supported, it would make my life, so much easier...
In theory it all works fine with an extra. I got myself a link using 9now.com.au and M3U sniffer, then I ran streamlink with the link and it worked perfectly and popped up VLC to play channel 9. The problem comes when I add it to the extra XML. When I try to rescan the channel, I'm getting a syntax error on the ampersand (&) in the link. I tried quoting it and dereferencing with a backslash, but it doesn't help. I'm going to post something to the NextPVR forums to see if they can help, otherwise I need some way to alias and forward the link so I can type in some short form link in the NextPVR extra and have it forward to the long link with all the special characters (pretty much exactly what Matt's service does). I don't know if there is any way to "alias" links without an HTML server, but if there is, can someone post how to do it.
If I work it out, I'll post.
Does anyone know the likelihood this being permanent with 9? The app is very slow on TV, and the kodi addon while better it still takes a while to switch channels. I was hoping its just for the olympics and possibly paralympics. Seems to slow their app down even, it always just switched perfectly. Always prefer using an iptv client and these lists were amazing.
All shall be revealed soon I guess, with the olympics finished now.
someone said the old urls are back working
Can someone see if this plays: https://9now-livestreams-v2.akamaized.net/prod/simulcast/adl/ch9/hls/r1/index.m3u8
Doesn't work for me using VLC. I get a 403.
-- logger module started -- main: Running vlc with the default interface. Use 'cvlc' to use vlc without interface. main: playlist is empty access error: HTTP 403 error http error: local stream 1 error: Cancellation (0x8) access error: HTTP 403 error http error: local stream 1 error: Cancellation (0x8) -- logger module stopped --
Currently the 9 streams are down.
Around the start of olympics they removed the old linear streams that were used We needed to switch to streams that require a TOKEN These tokens need to be generated by a 9now user account.
Added automation to do this, however the user accounts keep getting suspended. Maybe they are detected as bots? or maybe its human's doing it? Or, could be automation if a token is used by multiple different IPs then kill the account.
Anyway - to get new user accounts - it takes a bit of time to create them and then get the refresh token required to create access tokens that then are used to get the streams.
Im currently a bit "sick of the back and forth" so not jumping to try to keep fixing it.
For now, I'd recommend using the 9now Kodi addon which generates the token for just your instance (not shared).
Another option is to spin up a server to generate the tokens and then points other IPTV players at that server. There is abit about that on this ticket: https://github.com/matthuisman/slyguy.addons/issues/825