forked from wbt5/real-url
-
Notifications
You must be signed in to change notification settings - Fork 42
/
twitch.py
93 lines (79 loc) · 3.11 KB
/
twitch.py
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
# -*- coding: utf-8 -*-
# @Time: 2021/5/2 16:20
# @Project: real-url
# @Author: wbt5
# @Blog: https://wbt5.com
import json
import re
from urllib.parse import urlencode
# twitch 直播需要科学上网
import requests
class Twitch:
def __init__(self, rid):
# rid = channel_name
self.rid = rid
with requests.Session() as self.s:
pass
def get_client_id(self):
try:
res = self.s.get(f'https://www.twitch.tv/{self.rid}').text
client_id = re.search(r'"Client-ID":"(.*?)"', res).group(1)
return client_id
except requests.exceptions.ConnectionError:
raise Exception('ConnectionError')
def get_sig_token(self):
data = {
"operationName": "PlaybackAccessToken_Template",
"query": "query PlaybackAccessToken_Template($login: String!, $isLive: Boolean!, $vodID: ID!, "
"$isVod: Boolean!, $playerType: String!) { streamPlaybackAccessToken(channelName: $login, "
"params: {platform: \"web\", playerBackend: \"mediaplayer\", playerType: $playerType}) @include("
"if: $isLive) { value signature __typename } videoPlaybackAccessToken(id: $vodID, "
"params: {platform: \"web\", playerBackend: \"mediaplayer\", playerType: $playerType}) @include("
"if: $isVod) { value signature __typename }}",
"variables": {
"isLive": True,
"login": self.rid,
"isVod": False,
"vodID": "",
"playerType": "site"
}
}
headers = {
'Client-ID': self.get_client_id(),
'Referer': 'https://www.twitch.tv/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/90.0.4430.93 Safari/537.36',
}
res = self.s.post('https://gql.twitch.tv/gql', headers=headers, data=json.dumps(data)).json()
try:
token, signature, _ = res['data']['streamPlaybackAccessToken'].values()
except AttributeError:
raise Exception("Channel does not exist")
return signature, token
def get_real_url(self):
signature, token = self.get_sig_token()
params = {
'allow_source': 'true',
'dt': 2,
'fast_bread': 'true',
'player_backend': 'mediaplayer',
'playlist_include_framerate': 'true',
'reassignments_supported': 'true',
'sig': signature,
'supported_codecs': 'vp09,avc1',
'token': token,
'cdm': 'wv',
'player_version': '1.4.0',
}
url = f'https://usher.ttvnw.net/api/channel/hls/{self.rid}.m3u8?{urlencode(params)}'
return url
def get_real_url(rid):
try:
tw = Twitch(rid)
return tw.get_real_url()
except Exception as e:
print('Exception:', e)
return False
if __name__ == '__main__':
r = input('请输入 twitch 房间名:\n')
print(get_real_url(r))