I am trying to stream market live data from a stock broker (Zerodha) via their websockets sdk, to my frontend.
I am able to log the live data in my python console, but I am not able to stream it to the frontend.
I am new to the socket programming, so please kindly excuse.
Below is the python snippet.
import json
from flask import Flask, render_template, request, redirect, session
import threading
import time
from kiteconnect import KiteTicker #WebSocket client for connecting to Kite Connect's streaming quotes service.
import logging
###
from flask_socketio import SocketIO, emit
###
app = Flask(__name__)
##
socketio = SocketIO(app, async_mode= 'threading')
##
app.config['DEBUG'] = False
ticker = None
#app.route('/streamData')
def streamData():
'''
to start stream we first have to
1.) initiliase a WS connection - done
2.) Subscribe/register the symbols - done
3.) Check on new ticks - done
4.) To do: kill the ws after x time
'''
global ticker
accessToken = getAccessToken()
ticker = KiteTicker("api key here", accessToken)#1
# Assign the callbacks.
ticker.on_connect = onConnectLocal
ticker.on_close = onDisconnectLocal
ticker.on_error = onErrorLocal
ticker.on_ticks = onNewTicksLocal#3
logging.info('Ticker: Going to connect..')
ticker.connect(threaded=True)
time.sleep(5)
symbols = ['stock', 'names', 'given', 'here']
tokens = []
kite = getKite()
fetchInstruments(kite)
for symbol in symbols:
isd = getInstrumentDataBySymbol(symbol)
token = isd['instrument_token']
logging.info('registerSymbol: %s token = %s', symbol, token)
tokens.append(token)
logging.info('Subscribing tokens %s', tokens)
ticker.subscribe(tokens)#2
print(tokens)
return render_template('stream.html', async_mode='threading') # here is where I want to stream the data
def onConnectLocal(ws, response):
logging.info('Ticker connection successful.')
def onDisconnectLocal(ws, code, reason):
logging.error('Ticker got disconnected. code = %d, reason = %s', code, reason)
def onErrorLocal(ws, code, reason):
logging.error('Ticker errored out. code = %d, reason = %s', code, reason)
##socketio.on('my_broadcast_event', namespace='/test')
def onNewTicksLocal(ws, ticks):#3 # this the method which streams data from the broker's websocket
for tick in ticks:
isd = getInstrumentDataByToken(tick['instrument_token'])
symbol = isd['tradingsymbol']
logging.info('Tick: %s CMP = %f', symbol, tick['last_price']) #this prints to the python console with no problem
socketio.emit('my_response',{'data': tick}, broadcast=True)# this makes the problem
app.run('localhost', 8080)
stream.html (frontend)
<script src="//code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
namespace = 'http://localhost:8080/streamData';
var socket = io(namespace);
socket.on('connect', function() {
socket.emit('my_event', {data: 'connected to the SocketServer...'});
});
socket.on('my_response', function(msg, cb) {
$('#log').append('<br>' + $('<div/>').text('logs #' + msg.count + ': ' + msg.data).html());
if (cb)
cb();
});
$('form#emit').submit(function(event) {
socket.emit('my_event', {data: $('#emit_data').val()});
return false;
});
$('form#broadcast').submit(function(event) {
socket.emit('my_broadcast_event', {data: $('#broadcast_data').val()});
return false;
});
$('form#disconnect').submit(function(event) {
socket.emit('disconnect_request');
return false;
});
socket.on('my_response', function(data){
console.log(data.msg)
socket.emit('my_response', {data: data.msg});
});
});
</script>
The error i get always is :-
TypeError: onNewTicksLocal() missing 1 required positional argument: 'ticks'
But as you can see above I have supplied this(I get this error when I click on the broadcast button).
Please let me know where I am going wrong (I feel, but not certain, I could be going wrong with the callbacks).
edit :- updated the html code & port number in python
Related
When I try to send image from flutter to flask, flask shows error 400.
I have no idea where is an error in my flutter code. Flutter function gets file(image in my case) as Uint8List. Then, I cast it as List, and trying to send with multipart.
Here is the code from flask and flutter.
Flask:
#auth.post('update/avatar')
#jwt_required()
def update_avatar():
current_user = get_jwt_identity()
save_folder = 'images/users/'
file = request.files.get('file', None)
file.filename = str(current_user) +".jpeg"
filename = secure_filename(file.filename)
file.save(os.path.join(save_folder, filename))
Flutter:
Future<String> uploadAvatar(Uint8List file, int userId) async {
var url = ApiConstants.baseUrlAuth + ApiConstants.updateAvatar + userId.toString();
String? access = await storage.storage.read(key: 'access');
if(access == null){
return '';
}
http.MultipartRequest request = http.MultipartRequest('POST', Uri.parse(url));
List<int> _selectedFile = file;
request.headers.addAll({'Authorization': access, "Content-type": "multipart/form-data"});
request.files.add(http.MultipartFile.fromBytes('file', _selectedFile, contentType: MediaType('file', 'jpeg'),));
http.StreamedResponse response = await request.send();
final responseStr = await response.stream.bytesToString();
Map data = json.decode(responseStr);
if (response.statusCode == 401 && data.containsKey("msg") && data['msg'] == "Token has expired!"){
String res = auths.refreshToken() as String;
if(res == "success"){
res = uploadImagePost(file, userId) as String;
}
return res;
} else if(response.statusCode == 201){
return data['photo_url'];
}
return '';
}
}
According to http Error 400 (Bad Request) the error is because request was somehow corrupted on the way.
check this Mozilla docs for more information about the main error.
If I go into my firebase console and setup a campaign my end devices receive the notification just fine, but for messages to specific devices using the device's registration token, sent from django/python, I get no notification on my mobile devices.
Not sure if this matters but my app is still in development, it is not in production, so if this matters please let me know.
My frontend is flutter, here is the flutter code I am using to get the registration token and send it to the backend:
Future<StreamedResponse> AddProductPut(context, pk, name, quantity, cost, selling, XFile? chosenImage) async {
String id_token = await FirebaseAuth.instance.currentUser!.getIdToken();
late String? fcm_token;
await FirebaseMessaging.instance.getToken().then((token) async {
fcm_token = token!;
}).catchError((e) {
print(e);
});
print(fcm_token);
var url = backend + "/pm/createproduct/" + pk.toString() + "/";
var request = http.MultipartRequest('PUT', Uri.parse(url));
print("FCM TOKEN");
print(fcm_token);
request.headers["Authorization"] = "Token " + id_token;
request.fields["name"] = name;
request.fields["quantity"] = quantity.toString();
request.fields["cost_price"] = cost.toString();
request.fields["selling_price"] = selling.toString();
request.fields["barcode"] = "11111";
request.fields["token"] = fcm_token!;
request.files.add(
await http.MultipartFile.fromPath(
'image',
chosenImage!.path
)
);
return await request.send();
}
Here is the python code in my django serializer to send the notification message:
registration_token = self.context['request'].data["token"],
print(registration_token[0])
print(type(registration_token[0]))
# See documentation on defining a message payload.
message = Message(
notification=Notification(
title='New Product Added',
body='A new product called ' + validated_data['name'] + ' has been added to your account.',
),
token=registration_token[0]
)
# Send a message to the device corresponding to the provided
# registration token.
response = send(message)
print(response)
I am not getting any errors in my django/python console when sending this message, and response prints something like this:
projects/<project name>/messages/16641.......0329
My registration token is something like this:
cmLYCAbL0EsJrxppKzXvhF:APA..............qdt5ySYLbkQC_bpqwL6RdCwSzK_tX8iclp-e0QZB................lgw9g2eFNzfXpn2C4U................UnMphyWa6L9d-wUg
Not sure what the problem is, but I am receiving FCM messages on Apple and Android now...
registration_token = subuser.fcm
print(registration_token)
message = Message(
notification=Notification('Added As A Sub-User', f'A user with the phone {instance.userprofile.phone} has added you to their account as a sub user.'),
token=registration_token
)
and my flutter code that updates the database with the user's fcm registration token...
FirebaseMessaging.instance.getToken().then((token) async {
print(token);
String id_token = await FirebaseAuth.instance.currentUser!.getIdToken();
String uid = await FirebaseAuth.instance.currentUser!.uid;
final result = await http.put(
Uri.parse(backend + "/pm/setfcm/" + uid + "/"),
headers: {
"Content-Type": "application/json",
"Authorization": "Token " + id_token
},
body: jsonEncode({
"fcm": token,
})
);
}).catchError((e) {
print(e);
});
FirebaseMessaging.instance.onTokenRefresh.listen((newToken) async {
print(newToken);
String id_token = await FirebaseAuth.instance.currentUser!.getIdToken();
String uid = await FirebaseAuth.instance.currentUser!.uid;
final result = await http.put(
Uri.parse(backend + "/pm/setfcm/" + uid + "/"),
headers: {
"Content-Type": "application/json",
"Authorization": "Token " + id_token
},
body: jsonEncode({
"fcm": newToken,
})
);
});
response = send(message)
print(response)
I have an app with which I can write data to my database but cannot read data from the database. I'd like to be able to send data from the database to my app whenever I want which I think is done by the get and post http methods in flask. Should this be done with the same script or separate scripts? If separate scripts, how should I go about writing them? If not I am not sure what to add to my swift and python files.
The code I am working with uses flask and mysql-connector to make database connections, any help modifying to read data from the database would be greatly appreciated:
app.py
from flask import Flask
from flask import make_response
from flask import request
import mysql.connector
#opens database connectionto "events" database
try:
mydb = mysql.connector.connect(host="localhost", user="root", passwd="Proteus^5", database = "events")
print("Connection OK")
except e:
print("Connection failed: ", e)
#prepare a cursor object using cursor() method
mycursor = mydb.cursor()
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def register():
event_id = request.form['a']
poi = request.form['b']
address = request.form['c']
start_time = request.form['d']
end_time = request.form['e']
sql = "INSERT INTO events (event_id, poi, address, start_time, end_time) VALUES (%s, %s, %s, %s, %s)"
val = (event_id, poi, address, start_time, end_time)
try:
# Execute the SQL command
mycursor.execute(sql, val)
# Commit your changes in the database
mydb.commit()
mydb.close()
except e:
# Rollback in case there is any error
print("Error: ", e)
mydb.rollback()
return make_response("Success!", 200)
print("DB is closed")
swift file that sends data to database on a button press:
import Foundation
import SwiftUI
struct CreateEventButton: View {
#State private var isPresentedEvent = false
#State private var eventid: Int = 3
#State private var eventName: String = ""
#State private var eventDescription: String = ""
#State private var selectedStartTime = Date()
#State private var selectedEndTime = Date()
#Binding var annotationSelected: Bool
func send(_ sender: Any) {
let request = NSMutableURLRequest(url: NSURL(string: "http://localhost:5000/")! as
URL)
request.httpMethod = "POST"
let postString = "a=\(self.eventid)&b=\(self.eventName)&c=\.
(self.eventDescription)&d=\.
(self.selectedStartTime)&e=\(self.selectedEndTime)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(String(describing: error))")
return
}
print("response = \(String(describing: response))")
let responseString = NSString(data: data!, encoding:
String.Encoding.utf8.rawValue)
print("responseString = \(String(describing: responseString))")
}
task.resume()
self.eventName = ""
self.eventDescription = ""
self.selectedStartTime = Date()
self.selectedEndTime = Date()
}
var body: some View {
Button(action: {
self.isPresentedEvent.toggle() //trigger modal presentation
}, label: {
Text("Create Event").font(.system(size: 18))
}).padding(EdgeInsets(top: 8, leading: 6, bottom: 8, trailing: 6
.sheet(isPresented: $isPresentedEvent, content:{
VStack{
TextField("Event Name", text: self.$eventName).padding()
TextField("Event Description", text: self.$eventDescription).padding()
Form {
DatePicker("When your event starts: ", selection:
self.$selectedStartTime,
in: Date()...)
}
Form {
DatePicker("When your event ends: ", selection: self.$selectedEndTime,
in:
Date()...)
}
HStack{
Button(action: {
self.isPresentedEvent.toggle()
self.annotationSelected = false
self.eventid += 1
print("Start: \(self.selectedStartTime)")
print("End: \(self.selectedEndTime)")
self.send((Any).self)
}, label: {
Text("Create Event")
})
Button(action: {
self.isPresentedEvent.toggle()
}, label: {
Text("Cancel")
})
}
Text("Create Event Button (Non Functional)").padding()
}
} )
}
}
I do not know anything about swifts but I have worked with flask.
A simple and typical way for retrieving data from database is to define an API for
that. In this API you query the database (e.g. Select * From user Where user_id = ...) and then serialize the results (convert retrieved data from database in a form that is proper for sending to the client application. e.g. create a dictionary/json object) and send the response to the client.
an API example in flask
#app.route('.../get_user', methods=['GET'])
def get_user_api:
# query database
data = { 'username': username,
'level: level,
...
}
return data, 200
I have an API made on Flask that has several endpoints. I am trying to use data from these end points to display a chart on my front end that shows the data to the user.
The following are my exact requirements:
Implement one or more types of charts that can be used to effectively visualize data supplied from the API endpoints. Users should be able to pick different metrics to visualize and compare with others.
My Flask API:
import os
from flask import Flask, jsonify, session, request
import sqlalchemy
import time
from functools import wraps
# web app
app = Flask(__name__)
app.secret_key = 'super_secure_key_that_should_be_in_.env'
# database engine
engine = sqlalchemy.create_engine(os.getenv('SQL_URI'))
def rate_limit(**limit_kwargs):
def decorator(function):
#wraps(function)
def wrapper(*args, **kwargs):
limit = limit_kwargs['limit'] if 'limit' in limit_kwargs else 5
seconds = limit_kwargs['window'] if 'window' in limit_kwargs else 60
session_key = 'rate_limit_' + str(request.url_rule)
if session_key not in session:
session[session_key] = []
window: list = session[session_key]
if len(window) < limit:
window.append(int(time.time()))
session[session_key] = window
return function(*args, **kwargs)
if time.time() - window[0] < seconds:
return jsonify(error='Rate limit exceeded'), 429
window.pop(0)
window.append(int(time.time()))
session[session_key] = window
return function(*args, **kwargs)
return wrapper
return decorator
#app.route('/')
#rate_limit()
def index():
return 'Welcome 😎'
#app.route('/events/hourly')
#rate_limit(limit=3, window=20)
def events_hourly():
return queryHelper('''
SELECT date, hour, events
FROM public.hourly_events
ORDER BY date, hour
LIMIT 168;
''')
#app.route('/events/daily')
#rate_limit(limit=2)
def events_daily():
return queryHelper('''
SELECT date, SUM(events) AS events
FROM public.hourly_events
GROUP BY date
ORDER BY date
LIMIT 7;
''')
#app.route('/stats/hourly')
#rate_limit(limit=3, window=20)
def stats_hourly():
return queryHelper('''
SELECT date, hour, impressions, clicks, revenue
FROM public.hourly_stats
ORDER BY date, hour
LIMIT 168;
''')
#app.route('/stats/daily')
#rate_limit(limit=2)
def stats_daily():
return queryHelper('''
SELECT date,
SUM(impressions) AS impressions,
SUM(clicks) AS clicks,
SUM(revenue) AS revenue
FROM public.hourly_stats
GROUP BY date
ORDER BY date
LIMIT 7;
''')
#app.route('/poi')
#rate_limit(limit=3)
def poi():
return queryHelper('''
SELECT *
FROM public.poi;
''')
def queryHelper(query):
with engine.connect() as conn:
result = conn.execute(query).fetchall()
return jsonify([dict(row.items()) for row in result])
My React App.js:
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import DailyEvents from "./Components/DailyEvents";
class App extends Component {
render() {
return (
<div className="App">
<header className= "App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title"> Welcome to React</h1>
</header>
<DailyEvents />
</div>
);
}
}
export default App;
My Components/DailyEvents.js:
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
state = {
dates: []
}
componentDidMount() {
axios.get('api_url_or_localhost/events/daily')
.then(res => res.json())
.then((data) => {
this.setState({ dates: data })
})
.catch(console.log)
}
}
export default App;
I keep getting a TypeError that instance.render is not a function.
What I am trying to do is use my Flask API endpoints to visualize the data on the front-end.
try using axios :
https://alligator.io/react/axios-react/
it should look like this :
axios.get('put the query address')
.then(response => {
process your response
})
Can / Should you make changes to the Flask API, or is that code part of the requirements? Because I'm pretty sure you won't be able to return those Date objects straight from the DB without serializing them first.
I suggest you use Postman (or just a browser, for get requests) to test the routes locally and basically have a look at the data first.
React can use Axios or fetch to get this data and visualize it.
import React, { Component } from 'react'
class App extends Component {
state = {
dates: []
}
componentDidMount() {
fetch('api_url_or_localhost/events/daily'))
.then(res => res.json())
.then((data) => {
this.setState({ dates: data })
})
.catch(console.log)
}
...
}
see this https://pusher.com/tutorials/consume-restful-api-react for more details
I'm just wondering if there is any way to write a python script to check to see if a twitch.tv stream is live?
I'm not sure why my app engine tag was removed, but this would be using app engine.
Since all answers are actually outdated as of 2020-05-02, i'll give it a shot. You now are required to register a developer application (I believe), and now you must use an endpoint that requires a user-id instead of a username (as they can change).
See https://dev.twitch.tv/docs/v5/reference/users
and https://dev.twitch.tv/docs/v5/reference/streams
First you'll need to Register an application
From that you'll need to get your Client-ID.
The one in this example is not a real
TWITCH_STREAM_API_ENDPOINT_V5 = "https://api.twitch.tv/kraken/streams/{}"
API_HEADERS = {
'Client-ID' : 'tqanfnani3tygk9a9esl8conhnaz6wj',
'Accept' : 'application/vnd.twitchtv.v5+json',
}
reqSession = requests.Session()
def checkUser(userID): #returns true if online, false if not
url = TWITCH_STREAM_API_ENDPOINT_V5.format(userID)
try:
req = reqSession.get(url, headers=API_HEADERS)
jsondata = req.json()
if 'stream' in jsondata:
if jsondata['stream'] is not None: #stream is online
return True
else:
return False
except Exception as e:
print("Error checking user: ", e)
return False
I hated having to go through the process of making an api key and all those things just to check if a channel was live, so i tried to find a workaround:
As of june 2021 if you send a http get request to a url like https://www.twitch.tv/CHANNEL_NAME, in the response there will be a "isLiveBroadcast": true if the stream is live, and if the stream is not live, there will be nothing like that.
So i wrote this code as an example in nodejs:
const fetch = require('node-fetch');
const channelName = '39daph';
async function main(){
let a = await fetch(`https://www.twitch.tv/${channelName}`);
if( (await a.text()).includes('isLiveBroadcast') )
console.log(`${channelName} is live`);
else
console.log(`${channelName} is not live`);
}
main();
here is also an example in python:
import requests
channelName = '39daph'
contents = requests.get('https://www.twitch.tv/' +channelName).content.decode('utf-8')
if 'isLiveBroadcast' in contents:
print(channelName + ' is live')
else:
print(channelName + ' is not live')
It looks like Twitch provides an API (documentation here) that provides a way to get that info. A very simple example of getting the feed would be:
import urllib2
url = 'http://api.justin.tv/api/stream/list.json?channel=FollowGrubby'
contents = urllib2.urlopen(url)
print contents.read()
This will dump all of the info, which you can then parse with a JSON library (XML looks to be available too). Looks like the value returns empty if the stream isn't live (haven't tested this much at all, nor have I read anything :) ). Hope this helps!
RocketDonkey's fine answer seems to be outdated by now, so I'm posting an updated answer for people like me who stumble across this SO-question with google.
You can check the status of the user EXAMPLEUSER by parsing
https://api.twitch.tv/kraken/streams/EXAMPLEUSER
The entry "stream":null will tell you that the user if offline, if that user exists.
Here is a small Python script which you can use on the commandline that will print 0 for user online, 1 for user offline and 2 for user not found.
#!/usr/bin/env python3
# checks whether a twitch.tv userstream is live
import argparse
from urllib.request import urlopen
from urllib.error import URLError
import json
def parse_args():
""" parses commandline, returns args namespace object """
desc = ('Check online status of twitch.tv user.\n'
'Exit prints are 0: online, 1: offline, 2: not found, 3: error.')
parser = argparse.ArgumentParser(description = desc,
formatter_class = argparse.RawTextHelpFormatter)
parser.add_argument('USER', nargs = 1, help = 'twitch.tv username')
args = parser.parse_args()
return args
def check_user(user):
""" returns 0: online, 1: offline, 2: not found, 3: error """
url = 'https://api.twitch.tv/kraken/streams/' + user
try:
info = json.loads(urlopen(url, timeout = 15).read().decode('utf-8'))
if info['stream'] == None:
status = 1
else:
status = 0
except URLError as e:
if e.reason == 'Not Found' or e.reason == 'Unprocessable Entity':
status = 2
else:
status = 3
return status
# main
try:
user = parse_args().USER[0]
print(check_user(user))
except KeyboardInterrupt:
pass
Here is a more up to date answer using the latest version of the Twitch API (helix). (kraken is deprecated and you shouldn't use GQL since it's not documented for third party use).
It works but you should store the token and reuse the token rather than generate a new token every time you run the script.
import requests
client_id = ''
client_secret = ''
streamer_name = ''
body = {
'client_id': client_id,
'client_secret': client_secret,
"grant_type": 'client_credentials'
}
r = requests.post('https://id.twitch.tv/oauth2/token', body)
#data output
keys = r.json();
print(keys)
headers = {
'Client-ID': client_id,
'Authorization': 'Bearer ' + keys['access_token']
}
print(headers)
stream = requests.get('https://api.twitch.tv/helix/streams?user_login=' + streamer_name, headers=headers)
stream_data = stream.json();
print(stream_data);
if len(stream_data['data']) == 1:
print(streamer_name + ' is live: ' + stream_data['data'][0]['title'] + ' playing ' + stream_data['data'][0]['game_name']);
else:
print(streamer_name + ' is not live');
📚 Explanation
Now, the Twitch API v5 is deprecated. The helix API is in place, where an OAuth Authorization Bearer AND client-id is needed. This is pretty annoying, so I went on a search for a viable workaround, and found one.
🌎 GraphQL
When inspecting Twitch's network requests, while not being logged in, I found out the anonymous API relies on GraphQL. GraphQL is a query language for APIs.
query {
user(login: "USERNAME") {
stream {
id
}
}
}
In the graphql query above, we are querying a user by their login name. If they are streaming, the stream's id will be given. If not, None will be returned.
🐍 The Final Code
The finished python code, in a function, is below. The client-id is taken from Twitch's website. Twitch uses the client-id to fetch information for anonymous users. It will always work, without the need of getting your own client-id.
import requests
# ...
def checkIfUserIsStreaming(username):
url = "https://gql.twitch.tv/gql"
query = "query {\n user(login: \""+username+"\") {\n stream {\n id\n }\n }\n}"
return True if requests.request("POST", url, json={"query": query, "variables": {}}, headers={"client-id": "kimne78kx3ncx6brgo4mv6wki5h1ko"}).json()["data"]["user"]["stream"] else False
I've created a website where you can play with Twitch's GraphQL API. Refer to the GraphQL Docs for help on GraphQL syntax! There's also Twitch GraphQL API documentation on my playground.
Use the twitch api with your client_id as a parameter, then parse the json:
https://api.twitch.tv/kraken/streams/massansc?client_id=XXXXXXX
Twitch Client Id is explained here: https://dev.twitch.tv/docs#client-id,
you need to register a developer application: https://www.twitch.tv/kraken/oauth2/clients/new
Example:
import requests
import json
def is_live_stream(streamer_name, client_id):
twitch_api_stream_url = "https://api.twitch.tv/kraken/streams/" \
+ streamer_name + "?client_id=" + client_id
streamer_html = requests.get(twitch_api_stream_url)
streamer = json.loads(streamer_html.content)
return streamer["stream"] is not None
I'll try to shoot my shot, just in case someone still needs an answer to this, so here it goes
import requests
import time
from twitchAPI.twitch import Twitch
client_id = ""
client_secret = ""
twitch = Twitch(client_id, client_secret)
twitch.authenticate_app([])
TWITCH_STREAM_API_ENDPOINT_V5 = "https://api.twitch.tv/kraken/streams/{}"
API_HEADERS = {
'Client-ID' : client_id,
'Accept' : 'application/vnd.twitchtv.v5+json',
}
def checkUser(user): #returns true if online, false if not
userid = twitch.get_users(logins=[user])['data'][0]['id']
url = TWITCH_STREAM_API_ENDPOINT_V5.format(userid)
try:
req = requests.Session().get(url, headers=API_HEADERS)
jsondata = req.json()
if 'stream' in jsondata:
if jsondata['stream'] is not None:
return True
else:
return False
except Exception as e:
print("Error checking user: ", e)
return False
print(checkUser('michaelreeves'))
https://dev.twitch.tv/docs/api/reference#get-streams
import requests
# ================================================================
# your twitch client id
client_id = ''
# your twitch secret
client_secret = ''
# twitch username you want to check if it is streaming online
twitch_user = ''
# ================================================================
#getting auth token
url = 'https://id.twitch.tv/oauth2/token'
params = {
'client_id':client_id,
'client_secret':client_secret,
'grant_type':'client_credentials'}
req = requests.post(url=url,params=params)
token = req.json()['access_token']
print(f'{token=}')
# ================================================================
#getting user data (user id for example)
url = f'https://api.twitch.tv/helix/users?login={twitch_user}'
headers = {
'Authorization':f'Bearer {token}',
'Client-Id':f'{client_id}'}
req = requests.get(url=url,headers=headers)
userdata = req.json()
userid = userdata['data'][0]['id']
print(f'{userid=}')
# ================================================================
#getting stream info (by user id for example)
url = f'https://api.twitch.tv/helix/streams?user_id={userid}'
headers = {
'Authorization':f'Bearer {token}',
'Client-Id':f'{client_id}'}
req = requests.get(url=url,headers=headers)
streaminfo = req.json()
print(f'{streaminfo=}')
# ================================================================
This solution doesn't require registering an application
import requests
HEADERS = { 'client-id' : 'kimne78kx3ncx6brgo4mv6wki5h1ko' }
GQL_QUERY = """
query($login: String) {
user(login: $login) {
stream {
id
}
}
}
"""
def isLive(username):
QUERY = {
'query': GQL_QUERY,
'variables': {
'login': username
}
}
response = requests.post('https://gql.twitch.tv/gql',
json=QUERY, headers=HEADERS)
dict_response = response.json()
return True if dict_response['data']['user']['stream'] is not None else False
if __name__ == '__main__':
USERS = ['forsen', 'offineandy', 'dyrus']
for user in USERS:
IS_LIVE = isLive(user)
print(f'User {user} live: {IS_LIVE}')
Yes.
You can use Twitch API call https://api.twitch.tv/kraken/streams/YOUR_CHANNEL_NAME and parse result to check if it's live.
The below function returns a streamID if the channel is live, else returns -1.
import urllib2, json, sys
TwitchChannel = 'A_Channel_Name'
def IsTwitchLive(): # return the stream Id is streaming else returns -1
url = str('https://api.twitch.tv/kraken/streams/'+TwitchChannel)
streamID = -1
respose = urllib2.urlopen(url)
html = respose.read()
data = json.loads(html)
try:
streamID = data['stream']['_id']
except:
streamID = -1
return int(streamID)