Threaded Web COMP

Accessing Facebooks Graph API

  • go to [url]https://developers.facebook.com/[/url] and click the “Add a new App” from the “My Apps” dropdown.
    step1.png
  • fill out the application details and click “Create App ID”
  • go to “Settings>Basic” and note the “App ID” as well as “App Secret”
  • click on “Tools & Support” and then click on the “Graph API Explorer”
  • choose your app from the Application drop down
    step4.png
  • copy the “Access Token”
  • on the Web COMP select OAuth2 on the “Authentication Type” parameter and fill in the previously collected App Id, App Secret and Token
    step6.png
  • refer to the Graph API on how to retrieve information from the Facebook Graph

get your own feed

  • set the Web COMP “Request Type” parameter to “Get”
  • enter graph.facebook.com/v2.7/me/feed into the “URL” parameter
  • pulse the “Go” parameter
  • replacing “me” with a user id will return that users feed

Just wonderful Markus, can’t thank you enough. This is really making TD much more valuable for commercial projects that need custom social media displays.

It seems to have trouble with the json decoded callbacks provided. Won’t start thread, intermittent.

Can you give me instructions on how to duplicate?

When I enter your code into the callbacks dat :
import json
def receive(data):
msg = data.get(‘msg’,None)
if msg:
decoded = json.loads(msg.decode())
for k in decoded.keys():
print(‘key:’,k,‘value:’,decoded[k])
return

I get very intermittent functionality. I’ll try to dig up a toe when I get the time

I am getting this error, and don’t really understand why…
any idea?

{‘status’: ‘Thread Started’}
python >>>
{‘status’: ‘##start post request’}
python >>>
{‘code’: 401, ‘encoding’: ‘ISO-8859-1’}
python >>>
{‘msg’: b’\n\n\nError 401 Unauthorized‘}
python >>>
{‘msg’: b’‘}
python >>>
{‘msg’: b’‘}
python >>>
{‘msg’: b’

HTTP ERROR: 401

‘}
python >>>
{‘msg’: b"

Problem accessing ‘/1.1/statuses/filter.json’. Reason:"}
python >>>
{‘msg’: b’

    Unauthorized
‘}
python >>>
{‘msg’: b’‘}
python >>>
{‘msg’: b’'}
python >>>
{‘status’: ‘##end of message’}
python >>>

Hi gionniz.

what is it that you are trying to do?
You get a default “Unauthorized” response from the server indicating that your credentials are not correct//

Cheers
Markus

The question came up how to post images to Twitter.
I changed the Send method a bit to allow for specifying the url for each Send you are doing - this is especially useful when having to respond to events received from a server. Please download the latest WebComp zip from the first post.
First you will need to read in the file, then upload the file and finally post a status update with the id which twitter returns after successfully having received your image.

Here is a little guide:
1. Follow the Steps here: to create your Twitter Application and get all necessary OAuth info.

2.The Imagedata needs to be base64 encoded before it can be send to Twitter:

import base64

# save out a TOP
file = op('noise1').save('noise1.jpg')

# open the saved out file in binary format and read it into a variable
imgFile = open(file, 'r+b')
imgData = imgFile.read()

# encode as base64 and convert into a string
b64Data = base64.b64encode(imgData)
dataString = b64Data.decode()

# create a data dictionary you want to send to twitter
dataDict = {}
dataDict['media_data'] = dataString
dataDict['Name'] = 'An Image from TouchDesigner'

# send the data to Twitter
op('web1').Send(data=dataDict, url='https://upload.twitter.com/1.1/media/upload.json')

3. Now we wait for an response from Twitter and post an status update with the img id.
For this we need to create a script in the web1_callbacks DAT:

import json
def receive(data):
	# see if the data contains a message part
	msg = data.get('msg',None)
	if msg:
		# the returned message will be binary so lets decode this and convert the json into a dict
		msg = msg.decode()
		answerDict = json.loads(msg)

		# see if we can retrieve a media_id
		image = answerDict.get('media_id',None)
		if image:
			# create a data dictionary which contains the status update text and the uploaded media id
			dataDict = {}
			dataDict['media_ids'] = image
			dataDict['status'] = 'Testing Image Upload from TouchDesigner099'
			# send it to twitter
			op('web1').Send(data=dataDict, url='https://api.twitter.com/1.1/statuses/update.json')
		else:
			print(answerDict)
	else:
		print(data)
	return

Be advised that there is a limit on how much you can upload. So don;t run these scripts every frame. Also keep your Twitter applications OAuth keys and secret save!!!

Sorry for the newb question, anyone able give me a pointer on how to get the twitter stream python data that is successfully going into textport to a text DAT?

Something I can use to then select just the message and eventually send it to a text TOP?

Bit stuck on this one.

Thanks in advance

The supplied callbacks are creating a python dictionary of all keys/values and printing them to the console. You simply need to find which keys you would like to use and assign their value to whatever operators you would like. I would suggest reading through how to parse python dictionaries/lists.

Below is a simple callback eample that assigns the user’s screen name and tweet to Text TOPs…

import json def receive(data): msg = data.get('msg',None) if msg: decoded = json.loads(msg.decode()) for k in decoded.keys(): if k == 'user': print(decoded[k]['screen_name']) op('text1').par.text = '@' + decoded[k]['screen_name'] if k == 'text': print(decoded[k]) op('text2').par.text = decoded[k] print('-------------------------') return

Hi everyone! Thanks for putting together this COMP - this has helped open up a world of possibilities for connecting projects to web sources.

I’m working on an interactive projection activation, and we’re trying to build a very simple trigger to start playback on movie files, activated by a Twitter feed. We have a third party app that will write the tweets on a @“testAccount” we’ve set up with the appropriate developer API’s, we have our app key/secret/OAuth token/secret in place in the COMP, and we’ve entered the Twitter account in table4 (where @nasa appears in the original). We even beat some initial 401 Unauthorized issues. It seems like everything should be working, but…

After entering our @“testAccount” in table4, switching web1 to Active, and pulsing Go, we get our code 200 back, but then the script seems to hang with no feedback. Pulsing Stop or switching Active to Off (on web1) does not break the loop, and requires a full restart of TD to regain control of Textport.

python >>> {'status': 'Thread Started'} python >>> {'status': '##start post request'} python >>> {'code': 200, 'encoding': None} python >>>

Followed by an indefinite hold (10min+ tested)

This only seems to specifically be a problem with our “fresh” Twitter account we created specifically for this activation. Testing @nasa yields no problems - the following Textport comes from only changing our tracked Twitter handle in table4 from @“testAccount” to @nasa (stop initiated by pulsing Stop in web1).

python >>> {'status': 'Thread Started'} python >>> {'status': '##start post request'} python >>> {'code': 200, 'encoding': None} python >>> {'msg': b'{"created_at":"Tue Feb 21 18:58:41 +0000 2017","id":834115142975705095,"id_str":"834115142975705095","text":"Nasa announces major press conference on a \'discovery beyond our solar system\' https:\\/\\/t.co\\/HWG2qPOdXy","source":"\\u003ca href=\\"http:\\/\\/twitter.com\\" rel=\\"nofollow\\"\\u003eTwitter Web Client\\u003c\\/a\\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":3012613095,"id_str":"3012613095","name":"Barfield Educational","screen_name":"BarfieldEd","location":"Batley and surrounding areas","url":"http:\\/\\/www.barfieldeducational.co.uk\\/","description":"Providing STEM sessions in schools and social enterprise for disadvantaged children and senior citizens","protected":false,"verified":false,"followers_count":51,"friends_count":147,"listed_count":16,"favourites_count":25,"statuses_count":1243,"created_at":"Mon Feb 02 17:51:27 +0000 2015","utc_o python >>> {'status': 'Execution Interrupted, waiting for new commnad'} python >>> {'status': '##end of message'} python >>>

Some other accounts seem to work just fine - we’ve tried with @cubs and @Yankees (accounts selected arbitrarily), which both worked with no issues (maybe an extra second or two of latency on @Yankees?).

However, we had a similar-but-different issue when we tried to access @AppleSupport - there is roughly a ~20 second latency between Activating/pulsing Go web1 and receiving tweets. Similarly with sending pulses/Offs, Textport holds for 15-20 seconds before returning the Execution Interrupted. Maybe there’s a connection?

We’ve recreated this issue identically on both a laptop running Windows 10 and a desktop running Windows 7 SP1. We’re using 099 Commercial, but also have access to 088.

So. With all this in mind - what could we be possibly doing wrong here? Is our testTwitter account not configured properly? Yet that’s where we got our OAuth tokens etc from. Any suggestions or insight?

Thanks in advance!

I just tried getting tweets from one single account and made following changes:

The Request Type parameter was set to “GET”
The url to fetch my accounts tweets was set to “https://userstream.twitter.com/1.1/user.json

I disconnected the table4 from the input as I don’t want to filter for certain messages.

And it works well for me - but this only let’s me see my own accounts tweets or tweets mentioning my account.

For the behavior you describe, did you change the URL?

Cheers
Markus

HELP

requests seems to not be running on OSX? Will try at the office on a mac…

Cheers
Markus

I’m getting similar errors trying to run this on a Mac so would be great to hear of a solution.

Is this COMP still being developed?

Great idea but looks broken

testing in v2018.20100
THREAAD CONFLICT
TouchDesigner objects cannot be referenced from separate threads

Working on spec for an oauth2 TD client so keen to hear how people tackling auth nowadays.

Hey,

just looked at the webCOMP as we are including now all the necessary libraries into TouchDesigner. A problem was probably that I was passing in a lot of parameters as myOp.par.Mypar which now causes an Thread error as it’s passing in the parameter objects instead of parameter values. Until a fixed version is published with a new release of TouchDesigner, you can change the extension DAT called Web inside webCOMP to reference all parameters as for example

owner.par.Username.eval()

instead of just

owner.par.Username

Best
Markus

1 Like

Im looking for some method to use all of the realtime tweets that contain specified keyword as triggers to post my tweets. My automated tweets should contain a picture, rendered from TD and mentioning the account that have just tweeted the keyword.
By now I can post tweets with pictures from TD, but cant fully understand how the realtime stream is structured. Do all the tweets really make it to the stream on which the track function operates? Or they are somehow indexed and only high ranked can be tracked? When i track for the default “nasa” keyword from the we comp I get a lot of tweets coming in, I can extract their text and user names its all good. And any time I would post anything with “nasa” I would track my own post among others. But if i try to put replace my own keyword, like just some combination of letters to see if it will track my post with this letters combination - it wouldnt work. Thats why I thought twitter somehow indexes all realtime posts and track operates only on some higher ranked tweets. Is that the case?

Hi guys,
with the new authentication system of instagram and facebook is it possible to use this .tox ?
I can’t use it (with oAuth1-2 and token…)
No problem for Twitter.
Thanks !

Markus, thanks for that. I got dreaded “TouchDesigner objects cannot be referenced from separate threads.” error while using Asyncio library for posting web requests. I was referencing to a DAT cell in a script and didn’t realize, that unlike in expressions, I had to add “.val” at the and of cell address.