How to run the task in cloud task once a day? - python

Basically I have this Python code to insert a task in the queue and post the message in the http request, this is working fine, but the task runs and disappears, and I wanted it to run every day at a specific time, and I don't know how to do this logic.
data = {
"message":"oi"
}
project = key["project_id"]
queue = 'my-queue'
location = 'location'
url = 'https://....'
payload = data
in_seconds = 180
task_name = 'test_task'
deadline = 900
# Construct the fully qualified queue name.
parent = client.queue_path(project, location, queue)
# Construct the request http body.
task = {
"http_request": { # Specify the type of request.
"http_method": tasks_v2.HttpMethod.POST,
"url": "https:my_cloud-function_htppRequest"
}
}
if payload is not None:
if isinstance(payload, dict):
# Convert dict to JSON string
payload = json.dumps(payload)
# specify http content-type to application/json
task["http_request"]["headers"] = {"Authorization":"bearer", "Content-type":"application/json"}
# The API expects a payload of type bytes.
converted_payload = payload.encode()
# Add the payload to the request.
task["http_request"]["body"] = converted_payload
if in_seconds is not None:
# Convert "seconds from now" into an rfc3339 datetime string.
d = datetime.datetime.utcnow() + datetime.timedelta(seconds=in_seconds)
# Create Timestamp protobuf.
timestamp = timestamp_pb2.Timestamp()
timestamp.FromDatetime(d)
# Add the timestamp to the tasks.
task["schedule_time"] = timestamp
if task_name is not None:
# Add the name to tasks.
task["name"] = client.task_path(project, location, queue, task_name)
if deadline is not None:
# Add dispatch deadline for requests sent to the worker.
duration = duration_pb2.Duration()
duration.FromSeconds(deadline)
task["dispatch_deadline"] = duration
# Use the client to build and send the task.
response = client.create_task(request={"parent": parent, "task": task})
print("Created task {}".format(response.name))

Related

How can i run a config file multiple times with a different parameter each time in Python?

I'm working on the Twitter API to find the follower list for each user I have in my db. To do this, I have a script with the following parameters:
mongodb_tweets:
url: mongodb://localhost:27017/
database: hatemap
collection: p
mongodb_users:
url: mongodb://localhost:27017/
database: hatemap
collection: p1
twitter:
configuration:
barer_token: AAAAAAAAAAAAAAAAAAAAAAPtPgEAAAAAoVlZ4I0szkcu4dL%2Bhqif%2F%2BF45Oo%3DJbvSo773bskLu1GexDv9Dq1HjuSjfSwfxgLdDXEdlPO5mKyE6G
end_point: https://api.twitter.com/2/users/id/following
What I want to do is change the endpoint every time, more precisely the id within the endpoint which corresponds to the id of the user for which I want to find the list of followers.
For example in my db I have users with id "1", "2", "3", I want to change the endpoint within the same execution with all these different ids.
What I want to do is make multiple requests for each endpoint. In the sense that initially I have the following default endpoint: https://api.twitter.com/2/users/id/following, then I modify the endpoint with the replace command like so:
def __connect_to_endpoint(self, retried=False) -> dict:
"""
This method sends the request to twitter and return the response.
The possibles status codes in the twitter response are:
- 200: ok,in this case the response is a valid response;
- 429: rate limit exceeded, this means that either more requests were sent per second than allowed or more requests were sent in 15min than allowed. so in this case this method waits 1 second and tries to send the request again, if twitter still replies with a 429 code, it retrieves from the reply the time when the limit will reset and wait for that time to resubmit the request;
- others: in this case the method raises an exception
:param retried: a parameter that indicate if it is the first retry after an error or not, defaults to False
:type retried: bool, optional
:raise Exception: when twitter response with not 200 or 429 status code.
:return: dict that contains the response from twitter
:rtype: dict
"""
prova = "https://api.twitter.com/2/users/id/following"
to_search = self.mongodb_tweets.get_users_id()
saved = self.mongodb_users.get_users()
to_search = [usr for usr in to_search if usr not in saved]
#self.log.info("LOADED {} USERS ID TO SEARCH".format(len(to_search)))
for id in to_search:
print(id)
self.__twitter_end_point = prova.replace("id", id)
#print(self.__twitter_end_point)
response = requests.request("GET", self.__twitter_end_point, headers=self.__headers, params=self.__query)
if response.status_code == 200:
self.log.info("RECEIVED VALID RESPONSE")
json_response = response.json()
if "errors" in json_response:
self.log.warning("RECEIVED VALID RESPONSE WITH ERRORS")
ids = []
for i in json_response["errors"]:
ids.append(i["value"])
self.log.warning("IMPOSSIBLE TO RETRIEVE THE FOLLOWING USERS:{}".format(ids))
return json_response
if response.status_code == 429 and not retried:
self.log.debug("RETRY")
time.sleep(1)
return self.__connect_to_endpoint(retried=True)
elif response.status_code == 429 and retried:
self.log.info("RATE LIMITS REACHED: WAITING")
now = time.time()
now_date = datetime.fromtimestamp(now, timezone.utc)
reset = float(response.headers.get("x-rate-limit-reset"))
reset_date = datetime.fromtimestamp(reset, timezone.utc)
sec_to_reset = (reset_date - now_date).total_seconds()
for i in tqdm(range(0, math.floor(sec_to_reset) + 1), desc="WAITING FOR (in sec)", leave=True, position=0):
time.sleep(1)
return self.__connect_to_endpoint(retried=True)
else:
self.log.critical("GET BAD RESPONSE FROM TWITTER: {}: {}".format(response.status_code, response.text))
raise Exception(response.status_code, response.text)
This piece of code is the method that allows me to connect to the endpoint. As you can see in the first lines I use the replace command to change the endpoint with the different ids of the users that are present in the database for which I want to find the followers.
However, this leads me to find only the followers for the last id but not for all.

difficulty setting up consumer test pact python

Im trying to set up a consumer test with Pact, but Im struggling. If someone could help me where Im going wrong it would be appreciated.
The file I am trying to test is as follows:
import requests
from orders_service.exceptions import (
APIIntegrationError,
InvalidActionError
)
class OrderItem:
def __init__(self, id, product, quantity, size):
self.id = id
self.product = product
self.quantity = quantity
self.size = size
def dict(self):
return {
'product': self.product,
'size': self.size,
'quantity': self.quantity
}
class Order:
def __init__(self, id, created, items, status, schedule_id=None,
delivery_id=None, order_=None):
self._order = order_
self._id = id
self._created = created
self.items = [OrderItem(**item) for item in items]
self.status = status
self.schedule_id = schedule_id
self.delivery_id = delivery_id
#property
def id(self):
return self._id or self._order.id
#property
def created(self):
return self._created or self._order.created
#property
def status(self):
return self._status or self._order.status
def cancel(self):
if self.status == 'progress':
response = requests.get(
f'http://localhost:3001/kitchen/schedule/{self.schedule_id}/cancel',
data={'order': self.items}
)
if response.status_code == 200:
return
raise APIIntegrationError(
f'Could not cancel order with id {self.id}'
)
if self.status == 'delivery':
raise InvalidActionError(f'Cannot cancel order with id {self.id}')
def pay(self):
response = requests.post(
'http://localhost:3001/payments', data={'order_id': self.id}
)
if response.status_code == 200:
return
raise APIIntegrationError(
f'Could not process payment for order with id {self.id}'
)
def schedule(self):
response = requests.post(
'http://localhost:3000/kitchen/schedule',
data={'order': [item.dict() for item in self.items]}
)
if response.status_code == 201:
return response.json()['id']
raise APIIntegrationError(
f'Could not schedule order with id {self.id}'
)
def dict(self):
return {
'id': self.id,
'order': [item.dict() for item in self.items],
'status': self.status,
'created': self.created,
}
The consumer test I just can't get it to stage where it is publishing the contract. There are 2 areas Im not too familiar with firstly the python fixture. Im really unsure what needs to go here or how to do that and lastly the "consumer.cancel()" at the very bottom of the test.
Some help getting me set up and one the way would be greatly appreciated. Here is what I wrote for the test:
import atexit
from datetime import datetime
import logging
import os
from uuid import UUID
import requests
import pytest
import subprocess
from pact import Consumer, Like, Provider, Term, Format
from orders_service.orders import Order, OrderItem
log = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
# If publishing the Pact(s), they will be submitted to the Pact Broker here.
# For the purposes of this example, the broker is started up as a fixture defined
# in conftest.py. For normal usage this would be self-hosted or using Pactflow.
PACT_BROKER_URL = "https://xxx.pactflow.io/"
PACT_BROKER_USERNAME = xxx
PACT_BROKER_PASSWORD = xxx
# Define where to run the mock server, for the consumer to connect to. These
# are the defaults so may be omitted
PACT_MOCK_HOST = "localhost"
PACT_MOCK_PORT = 1234
# Where to output the JSON Pact files created by any tests
PACT_DIR = os.path.dirname(os.path.realpath(__file__))
#pytest.fixture
def consumer() -> Order.cancel:
# return Order.cancel("http://{host}:{port}".format(host=PACT_MOCK_HOST, "port=PACT_MOCK_PORT))
order = [OrderItem(**{"id":1, "product":"coffee", "size":"big", "quantity":2})]
payload = Order(id=UUID, created=datetime.now, items=order, status="progress")
return Order.cancel(payload)
#pytest.fixture(scope="session")
def pact(request):
"""Setup a Pact Consumer, which provides the Provider mock service. This
will generate and optionally publish Pacts to the Pact Broker"""
# When publishing a Pact to the Pact Broker, a version number of the Consumer
# is required, to be able to construct the compatability matrix between the
# Consumer versions and Provider versions
# version = request.config.getoption("--publish-pact")
# publish = True if version else False
pact = Consumer("UserServiceClient", version=1).has_pact_with(
Provider("UserService"),
host_name=PACT_MOCK_HOST,
port=PACT_MOCK_PORT,
pact_dir=PACT_DIR,
publish_to_broker=True,
broker_base_url=PACT_BROKER_URL,
broker_username=PACT_BROKER_USERNAME,
broker_password=PACT_BROKER_PASSWORD,
)
pact.start_service()
# Make sure the Pact mocked provider is stopped when we finish, otherwise
# port 1234 may become blocked
atexit.register(pact.stop_service)
yield pact
# This will stop the Pact mock server, and if publish is True, submit Pacts
# to the Pact Broker
pact.stop_service()
# Given we have cleanly stopped the service, we do not want to re-submit the
# Pacts to the Pact Broker again atexit, since the Broker may no longer be
# available if it has been started using the --run-broker option, as it will
# have been torn down at that point
pact.publish_to_broker = False
def test_cancel_scheduled_order(pact, consumer):
expected = \
{
"id": "1e54e244-d0ab-46ed-a88a-b9e6037655ef",
"order": [
{
"product": "coffee",
"quantity": 1,
"size": "small"
}
],
"scheduled": "Wed, 22 Jun 2022 09:21:26 GMT",
"status": "cancelled"
}
(pact
.given('A scheduled order exists and it is not cancelled already')
.upon_receiving('a request for cancellation')
.with_request('get', f'http://localhost:3001/kitchen/schedule/{Like(12343)}/cancel')
.will_respond_with(200, body=Like(expected)))
with pact:
payload = Order(UUID, datetime.now, {"product":"coffee", "size":"large", "quantity":1}, "progress")
print(payload)
response = consumer.cancel(payload)
assert response['status'] == "cancelled"
pact.verify()
Also I originally had(adapted from the example in pact):
# return Order.cancel("http://{host}:{port}".format(host=PACT_MOCK_HOST, "port=PACT_MOCK_PORT))
but i'm not sure how that works
Thanks for helping me
There are a couple of issues here:
.with_request('get', f'http://localhost:3001/kitchen/schedule/{Like(12343)}/cancel')
The Like matcher is a function that returns an object. Adding this within a string is likely to cause issues when it is stringified
You don't need to put the protocol and host portion here - just the path e.g.:
.with_request(method='GET', path='/kitchen/schedule/bc72e917-4af1-4e39-b897-1eda6d006b18/cancel', headers={'Content-Type': 'application/json'} ...)
If you want to use a matcher on the path, it needs to be on the string as a whole e.g. Regex('/kitchen/schedule/([0-9]+)/cancel') (this is not a real regex, but hopefully you get the idea).
I can’t see in this code where it calls the actual mock service. I’ve removed the commented items for readability:
(pact
.given('A scheduled order exists and it is not cancelled already')
.upon_receiving('a request for cancellation')
.with_request(method='GET', path='/kitchen/schedule/bc72e917-4af1-4e39-b897-1eda6d006b18/cancel', headers={'Content-Type': 'application/json'},)
.will_respond_with(200, body=Like(expected)))
with pact:
# this needs to be sending a request to
# http://localhost:1234/kitchen/schedule/bc72e917-4af1-4e39-b897-1eda6d006b18/cancel
response = consumer.cancel()
pact.verify()
The definition of the function you are calling doesn't make any HTTP request to the pact mock service, it just returns a canned response.
#pytest.fixture
def consumer() -> Order.cancel:
# return Order.cancel("http://{host}:{port}".format(host=PACT_MOCK_HOST, "port=PACT_MOCK_PORT))
order = [OrderItem(**{"id":1, "product":"coffee", "size":"big", "quantity":2})]
payload = Order(id=UUID, created=datetime.now, items=order, status="progress")
return Order.cancel(payload)
For a Pact test to pass, you need to demonstrate your code actually calls the correct HTTP endpoints with the right data, and that your code can handle it.

Extracting data from Pinterest using gRPC, Python

I want to grab all chats of my Pinterest account
I have a Proto Service:
syntax = "proto3";
service Pinterest{
rpc GetConversations (request_chat_info) returns (chat_response);
}
message request_chat_info{
string conversation_id = 1;
string csrftoken = 2;
string _b = 3;
string _pinterest_sess = 4;
}
message chat_response{
string type = 1;
string id = 2;
string text = 3;
}
message chat_response_array{
repeated chat_response messages = 1;
}
and this is my Pinterest Servicer:
# GRPC Service
class PinterestService(pb2_grpc.PinterestServicer):
def GetConversations(self, request, context):
conversation_id = request.conversation_id
csrftoken = request.csrftoken
_b = request._b
_pinterest_sess = request._pinterest_sess
chats = _exec(
get_chat,
{"conversation_id": conversation_id, "csrftoken": csrftoken, "_b": _b, "_pinterest_sess": _pinterest_sess}
)
return pb2.chat_response_array(messages=chats)
and main Program is something like this:
# ENDPOINTS
CHAT_API = "https://www.pinterest.com/resource/ConversationMessagesResource/get/"
# Execute Fucntion
def _exec(func, params):
return func(**params)
# Make Requests here
def _get(url:str, cookies:Dict = None, headers:Dict = None) -> requests.Response:
response = requests.request("GET", url=url, cookies=cookies, headers=headers)
response.raise_for_status()
return response
# Chat Parser Function
def _chat_parser(chat_dict: Dict) -> Dict:
return {
"type": chat_dict.get("type", ""),
"id": chat_dict.get("id", ""),
"text": chat_dict.get("text", ""),
}
# Function to handle GRPC
def get_chat(conversation_id:str, csrftoken:str, _b:str, _pinterest_sess:str) -> Dict:
options = {"page_size":25,"conversation_id":conversation_id,"no_fetch_context_on_resource":False}
_cookies = {"csrftoken":csrftoken, "_b":_b, "_pinterest_sess":_pinterest_sess}
query = {"data": json.dumps({"options":options})}
encoded_query = urlencode(query).replace("+", "%20")
url = "{}?{}".format(CHAT_API, encoded_query)
msg_counter = 0
while True:
try:
return _chat_parser(_get(url, _cookies).json()["resource_response"]["data"][msg_counter])
except IndexError:
break
finally:
msg_counter += 1
I need to get all CHAT and I Don't know how to do that!
The Response JSON in Pinterest is exactly Like this:
["resource_response"]["data"][0]
["resource_response"]["data"][1]
["resource_response"]["data"][2]
["resource_response"]["data"][...]
Based on Messages Count the last number change from 0 to any number
I don't know how to handle that!
does the fault in my proto or what?
should I use stream in proto, if yes, bidirectional stream or for Client, Server...
Thank you for Helping me.
I found the answer
it must be server stream and use for loop and yield

Push Notification not working with push notification time

When I am using push notification in python then I am not able to sent push notification time as per required
Example : 1m or 60m etc
I am using https://github.com/olucurious/PyFCM this in application.
Please give me example how to send push notification time as per required
registration_id = request.POST['registration_id']
message_title = request.POST['message_title']
message_body = request.POST['message_body']
result = push_service.notify_single_device(registration_id=registration_id, message_title=message_title, message_body=message_body)
Where we need to sent push notification type for this application When I am setting time then getting so many problems and example not exit in whole example.
Full Example:
def index(request):
if (request.POST['type'] == 'android'):
push_service = FCMNotification(api_key="abc.pem")
registration_id = request.POST['registration_id']
message_title = request.POST['message_title']
message_body = request.POST['message_body']
result = push_service.notify_single_device(registration_id=registration_id, message_title=message_title, message_body=message_body)
print result
return HttpResponse("Hello Testing, world. You're at the tesing index.")
else:
apns = APNs(use_sandbox=True, cert_file='abc.pem', enhanced=True)
token_hex = request.POST['registration_id']
messageTitle = request.POST['message_title']
dict = {'title': request.POST['message_title'], 'body': request.POST['message_body']}
payload = Payload(alert=dict, sound="default", badge=1)
apns.gateway_server.send_notification(token_hex, payload)
frame = Frame()
identifier = 1
expiry = time.time()+3600
priority = 10
frame.add_item(request.POST['registration_id'], payload, identifier, expiry, priority)
return HttpResponse("Hello Testing, world. You're at the tesing index second")

Is There Any Way To Check if a Twitch Stream Is Live Using Python?

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)

Categories

Resources