-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathemby_channel_update.py
More file actions
108 lines (91 loc) · 4.1 KB
/
Copy pathemby_channel_update.py
File metadata and controls
108 lines (91 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
"""
Emby Channel Guide Mapper - uses LiveTv/Channels endpoint directly
"""
import urllib.request
import urllib.parse
import json
import getpass
EMBY_HOST = "YOUR_EMBY_IP:8096"
PROVIDER_NJ = "1c0742ba56084f7896d8ea10892a1a7a" # Emby Guide Data NJ
PROVIDER_XML = "ae840e03099c4d6595b8e1d5cec92b64" # XmlTV / Threadfin
TOKEN = None
def get_headers():
return {
"X-Emby-Authorization": f'MediaBrowser Client="Mapper", Device="Python", DeviceId="mapper-001", Version="1.0", Token="{TOKEN}"',
"Content-Type": "application/json",
}
def login(username, password):
global TOKEN
url = f"{EMBY_HOST}/emby/Users/AuthenticateByName"
payload = json.dumps({"Username": username, "Pw": password}).encode()
headers = {
"X-Emby-Authorization": 'MediaBrowser Client="Mapper", Device="Python", DeviceId="mapper-001", Version="1.0"',
"Content-Type": "application/json",
}
req = urllib.request.Request(url, data=payload, method="POST", headers=headers)
with urllib.request.urlopen(req, timeout=15) as r:
data = json.loads(r.read())
TOKEN = data["AccessToken"]
print(f"Logged in as: {data['User']['Name']}")
def api_get(path):
url = f"{EMBY_HOST}{path}"
req = urllib.request.Request(url, headers=get_headers())
with urllib.request.urlopen(req, timeout=15) as r:
return json.loads(r.read())
def api_post(path, data=None, method="POST"):
url = f"{EMBY_HOST}{path}"
body = json.dumps(data).encode() if data else b""
req = urllib.request.Request(url, data=body, method=method, headers=get_headers())
try:
with urllib.request.urlopen(req, timeout=15) as r:
try:
return r.status, json.loads(r.read())
except:
return r.status, {}
except urllib.error.HTTPError as e:
try:
return e.code, json.loads(e.read())
except:
return e.code, {}
def main():
username = input("Emby username: ").strip()
password = getpass.getpass("Emby password: ")
login(username, password)
# Get all live TV channels
print("\nFetching live TV channels...")
result = api_get("/emby/LiveTv/Channels?Limit=200&Fields=ChannelInfo,ExternalEtag")
channels = result.get("Items", [])
print(f"Found {len(channels)} channels")
# Get XmlTV provider channels (Threadfin) - these have numeric IDs matching channel numbers
print("Fetching XmlTV provider channels...")
xml_opts = api_get(f"/emby/LiveTv/ChannelMappingOptions?ProviderId={PROVIDER_XML}")
xml_channels = {pc.get("Name", "").split(" ", 1)[-1].strip().lower(): pc
for pc in xml_opts.get("ProviderChannels", [])}
xml_by_id = {pc.get("Id"): pc for pc in xml_opts.get("ProviderChannels", [])}
# Get NJ guide provider channels
print("Fetching Emby Guide Data channels...")
nj_opts = api_get(f"/emby/LiveTv/ChannelMappingOptions?ProviderId={PROVIDER_NJ}")
nj_channels = {pc.get("Name", "").lower(): pc
for pc in nj_opts.get("ProviderChannels", [])}
print(f"\nXmlTV channels available: {len(xml_channels)}")
print(f"NJ Guide channels available: {len(nj_channels)}")
# Print first few from each to understand naming
print("\nFirst 5 XmlTV provider channels:")
for pc in xml_opts.get("ProviderChannels", [])[:5]:
print(f" {pc.get('Name')} | Id: {pc.get('Id')}")
print("\nFirst 5 NJ Guide provider channels:")
for pc in nj_opts.get("ProviderChannels", [])[:5]:
print(f" {pc.get('Name')} | Id: {pc.get('Id')}")
print("\nFirst 5 Live TV channels:")
for ch in channels[:5]:
print(f" {ch.get('Name')} | Id: {ch.get('Id')} | ExternalId: {ch.get('ExternalId')} | Number: {ch.get('Number')}")
# Try to fetch a single channel's full detail to see all fields
if channels:
ch = channels[0]
print(f"\nFull detail for channel '{ch.get('Name')}':")
detail = api_get(f"/emby/LiveTv/Channels/{ch.get('Id')}")
for k, v in detail.items():
if v is not None and v != "" and v != []:
print(f" {k}: {v}")
if __name__ == "__main__":
main()