PyFacebook Infinite Session - python

I am trying to set a cron task to read updates for a Facebook application. I have prompted the user to grant Offline Access permissions and i have store the session_key in the db.
I am crearing a new Facebook object and besides api and secret key I also use the session_key (previously stored in db) and the fb uid. When i am trying to create the auth token or do a API call i get a Error 104: Incorrect signature
Any ideas, experience, hints ?

I just wrote a blog entry about my search for something similar - need to write a Python cron script. Here's what I came up with:
#!/usr/bin/python
import os, sys, optparse, time, json
import facebook
##
USER_SESSION_FILE = os.path.expanduser('fb-user.session')
APP_KEY_FILE = os.path.expanduser('fb-app.keys')
##
def main():
app_keys = open(APP_KEY_FILE).readlines()
fb_api = facebook.Facebook(api_key=app_keys[0].strip(), secret_key=app_keys[1].strip())
opts, args = parse_options()
if args == ['init']:
init(fb_api)
return
session = json.load(open(USER_SESSION_FILE))
fb_api.uid = session['uid']
fb_api.secret = session['secret']
fb_api.session_key = session['session_key']
fb_api.stream.publish(message="test from PyFacebook")
def init(fb_api):
fb_api.auth.createToken()
sys.stdout.write('Opening web page to add application (press ENTER when done)...')
sys.stdout.flush()
fb_api.login()
raw_input()
sys.stdout.write('Asking for offline access now...')
sys.stdout.flush()
fb_api.request_extended_permission('offline_access')
raw_input()
sys.stdout.write('And, finally, asking for permission to publish')
sys.stdout.flush()
fb_api.request_extended_permission('publish_stream')
raw_input()
fb_api.auth.getSession()
if fb_api.session_key_expires != 0:
print """We were granted a temporary key; please wait a minute and run `%s init` again.""" % (sys.argv[0],)
else:
if not os.path.exists(USER_SESSION_FILE):
# Only set restrictive permissions when creating the file
# ourselves.
open(USER_SESSION_FILE, 'w').close()
os.chmod(USER_SESSION_FILE, 0600)
json.dump({
'uid': fb_api.uid,
'secret': fb_api.secret,
'session_key': fb_api.session_key,
},
open(USER_SESSION_FILE, 'w'),
sort_keys=True,
indent=4)
def parse_options():
p = optparse.OptionParser()
return p.parse_args()
if __name__ == '__main__':
sys.exit(main())

I faced the same problem where the error displayed was:
"facebook.FacebookError: Error 104: Incorrect signature"
Just reset your APP Secret_key and make corresponding change in the code and that sgould fix the problem.
Cheers!

I've never used PyFacebook. Or tried to resume sessions in this manner. But I'd imagine just storing session_key and uid is not enough. There are other params too, and a signature param that's calculated based on all the fb_* params. So you might need to store all of them.
But even so, they might only work for 20-30 minutes if you're unlucky.

Related

python aiosmtpd server with basic authentication

Im trying to create an aiosmtpd server to process emails received.
It works great without authentication, yet i simply cannot figure out how to setup the authentication.
I have gone through the documents and searched for examples on this.
a sample of how im currently using it:
from aiosmtpd.controller import Controller
class CustomHandler:
async def handle_DATA(self, server, session, envelope):
peer = session.peer
mail_from = envelope.mail_from
rcpt_tos = envelope.rcpt_tos
data = envelope.content # type: bytes
# Process message data...
print('peer:' + str(peer))
print('mail_from:' + str(mail_from))
print('rcpt_tos:' + str(rcpt_tos))
print('data:' + str(data))
return '250 OK'
if __name__ == '__main__':
handler = CustomHandler()
controller = Controller(handler, hostname='192.168.8.125', port=10025)
# Run the event loop in a separate thread.
controller.start()
# Wait for the user to press Return.
input('SMTP server running. Press Return to stop server and exit.')
controller.stop()```
which is the basic method from the documentation.
could someone please provide me with an example as to how to do simple authentication?
Alright, since you're using version 1.3.0, you can follow the documentation for Authentication.
A quick way to start is to create an "authenticator function" (can be a method in your handler class, can be standalone) that follows the Authenticator Callback guidelines.
A simple example:
from aiosmtpd.smtp import AuthResult, LoginPassword
auth_db = {
b"user1": b"password1",
b"user2": b"password2",
b"user3": b"password3",
}
# Name can actually be anything
def authenticator_func(server, session, envelope, mechanism, auth_data):
# For this simple example, we'll ignore other parameters
assert isinstance(auth_data, LoginPassword)
username = auth_data.login
password = auth_data.password
# If we're using a set containing tuples of (username, password),
# we can simply use `auth_data in auth_set`.
# Or you can get fancy and use a full-fledged database to perform
# a query :-)
if auth_db.get(username) == password:
return AuthResult(success=True)
else:
return AuthResult(success=False, handled=False)
Then you're creating the controller, create it like so:
controller = Controller(
handler,
hostname='192.168.8.125',
port=10025,
authenticator=authenticator_func, # i.e., the name of your authenticator function
auth_required=True, # Depending on your needs
)

List subscriptions for a given Azure account

I'm trying to list the subscriptions in an Azure account using azure-python-sdk.
I have followed this link in documentation.
https://learn.microsoft.com/en-us/python/api/azure-mgmt-subscription/azure.mgmt.subscription.operations.subscriptionsoperations?view=azure-python#list-custom-headers-none--raw-false----operation-config-
from azure.mgmt.subscription import SubscriptionClient
from msrestazure.azure_active_directory import UserPassCredentials
credentials = UserPassCredentials(username='xxxx', password='xxxx')
sub_client = SubscriptionClient(credentials)
subs = [sub.as_dict() for sub in sub_client.subscriptions.list()]
print(subs)
It is supposed to return a list of subscriptions.
However, I see only empty list returned every time I try the above code.
Can anybody help?
Try this code,
def list_subscriptions():
try:
sub_client = get_client_from_cli_profile(SubscriptionClient)
except CLIError:
logger.info("Not logged in, running az login")
_run_az_cli_login()
sub_client = get_client_from_cli_profile(SubscriptionClient)
return [["Subscription_name", "Subscription ID"]] + [
[sub.display_name, sub.subscription_id]
for sub in sub_client.subscriptions.list()
]
You can find the handy tool from here
If the list is empty and you get not exception, it's likely your credentials are correct (no exception), but your user doesn't have access to subscriptions (no permissions)
In the Azure portal, in the subscription panel you have a button "Access control (IAM)" to define what users are allowed to a given subscription.
https://learn.microsoft.com/azure/role-based-access-control/role-assignments-portal
https://learn.microsoft.com/azure/role-based-access-control/rbac-and-directory-admin-roles
(I work at MS in the SDK team)
I think I solved the issue using Azure CLI. Yet, I still wonder why it didn't work as supposed using azure-python-sdk.
Here is the code:
import subprocess
import json
subscriptions = json.loads(subprocess.check_output('az account list', shell=True).decode('utf-8'))
print(subscriptions)
Thank you for your responses.
I have a similar problem, so I have used AzureCliCredential and it simply worked.
The code is this:
def subscription_list():
credential = AzureCliCredential()
subscription_client = SubscriptionClient(credential)
sub_list = subscription_client.subscriptions.list()
column_width = 40
print("Subscription ID".ljust(column_width) + "Display name")
print("-" * (column_width * 2))
for group in list(sub_list):
print(f'{group.subscription_id:<{column_width}}{group.display_name}')
Before trying this code, you have to log to Azure through the command line in your dev environment.

GCP/Py: determine when compute engine instance is actually ready to be used (not "RUNNING")

I am messing with the example code Google provides and I am looking to determine when an instance is ready to do work. They have an operation 'DONE' status and they have an instance 'RUNNING' status, but there is still a delay until I can actually use the instance. What is the best way to wait for this without waiting for a set time period (because that is a waste for time if the instance is ready sooner)?
I modified their wait_for_operation function so it uses isUp:
# [START wait_for_operation]
def wait_for_operation(compute, project, zone, operation):
print('Waiting for operation to finish...')
while True:
result = compute.zoneOperations().get(
project=project,
zone=zone,
operation=operation).execute()
if result['status'] == 'DONE':
print("done.")
print("result:")
print(result)
if 'error' in result:
raise Exception(result['error'])
print("before ex")
instStatus = compute.instances().get(
project=project,
zone=zone,
instance='inst-test1').execute()
print("after ex")
if instStatus['status'] == 'RUNNING':
if isUp("10.xxx.xx.xx"):
print("instStatus = ")
print(instStatus)
return result
else:
print("wasn't replying to ping")
time.sleep(1)
# [END wait_for_operation]
def isUp(hostname):
giveFeedback = False
if platform.system() == "Windows":
response = os.system("ping "+hostname+" -n 1")
else:
response = os.system("ping -c 1 " + hostname)
isUpBool = False
if response == 0:
if giveFeedback:
print( hostname + 'is up!')
isUpBool = True
else:
if giveFeedback:
print( hostname + 'is down!')
return isUpBool
See Matthew's answer for original isUp code: Pinging servers in Python
Most of the other code originated here:
https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/compute/api/create_instance.py
GCP status link:
https://cloud.google.com/compute/docs/instances/checking-instance-status
My code works, but is there a better way using instance status or something and avoiding the entire isUp/ping stuff? Seems like my method is a needless workaround.
Obviously I am using Python and this is just messing around code with needless prints etc.
I have a Windows 7 workstation and I don't want to have to require admin rights and a Linux instance.
Edit 1: "by ready to do work", I mean I can send commands to it and it will respond.
Hi I would suggest you to use global operations.
https://cloud.google.com/compute/docs/reference/rest/beta/globalOperations/get
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
service = discovery.build('compute', 'beta', credentials=credentials)
# Project ID for this request.
project = 'my-project' # TODO: Update placeholder value.
# Name of the Operations resource to return.
operation = 'my-operation' # TODO: Update placeholder value.
request = service.globalOperations().get(project=project, operation=operation)
response = request.execute()
# TODO: Change code below to process the `response` dict:
pprint(response)
One approach I have used is having a startup script create a field in the instance metadata. You can then check the instance status using your code about and see if the new metadata has been added. You can then avoid pinging the server. An added benefit is if there is not an external ip for the instance, this method still works.
instStatus = compute.instances().get(
project=project,
zone=zone,
instance='inst-test1').execute()

How do I return the Instagram Realtime subscription challenge?

I'm trying to subscribe to a tag. It appears that the callback URL is being called correctly with a hub.challenge and hub.mode, and I figured out how to access the challenge using self.request.get('hub.challenge'). I thought I was just supposed to echo the challenge, but that doesn't appear to work since I receive the following errors in the GAE logs:
InstagramAPIError: (400) APISubscriptionError-Challenge verification failed. Sent "647bf6dbed31465093ee970577ce1b72", received "
647bf6dbed31465093ee970577ce1b72
".
Here is the full handler:
class InstagramHandler(BaseHandler):
def get(self):
def process_tag_update(update):
update = update
mode = self.request.get('hub.mode')
challenge = self.request.get('hub.challenge')
verify_token = self.request.get('hub.verify_token')
if challenge:
template_values = {'challenge':challenge}
path = os.path.join(os.path.dirname(__file__), '../templates/instagram.html')
html = template.render(path, template_values)
self.response.out.write(html)
else:
reactor = subscriptions.SubscriptionsReactor()
reactor.register_callback(subscriptions.SubscriptionType.TAG, process_tag_update)
x_hub_signature = self.request.headers.get('X-Hub-Signature')
raw_response = self.request.data
try:
reactor.process('INSTAGRAM_SECRET', raw_response, x_hub_signature)
except subscriptions.SubscriptionVerifyError:
logging.error('Instagram signature mismatch')
So returning it as a string worked. I should have payed closer attention to the error message, but it took a helpful person on the Python IRC to point out the extra line breaks in the message. Once I put the template files on one line, it seemed to work. I can now confirm that my app is authorized via Instagram's list subscription URL.

Python: Upload a photo to photobucket

Can a Python script upload a photo to photo bucket and then retrieve the URL for it? Is so how?
I found a script at this link: http://www.democraticunderground.com/discuss/duboard.php?az=view_all&address=240x677
But I just found that confusing.
many thanks,
Phil
Yes, you can. Photobucket has a well-documented API, and someone wrote a wrapper around it.
Download the it and put it into your Python path, then download httplib2 (you can use easy_install or pip for this one).
Then, you have to request a key for the Photobucket API.
If you did everything right, you can write your script now. The Python wrapper is great, but is not documented at all which makes it very difficult to use it. I spent hours on understanding it (compare the question and response time here). As example, the script even has form/multipart support, but I had to read the code to find out how to use it. I had to prefix the filename with a #.
This library is a great example how you should NOT document your code!
I finally got it working, enjoy the script: (it even has oAuth handling!)
import pbapi
import webbrowser
import cPickle
import os
import re
import sys
from xml.etree import ElementTree
__author__ = "leoluk"
###############################################
## CONFIGURATION ##
###############################################
# File in which the oAuth token will be stored
TOKEN_FILE = "token.txt"
IMAGE_PATH = r"D:\Eigene Dateien\Bilder\SC\foo.png"
IMAGE_RECORD = {
"type": 'image',
"uploadfile": '#'+IMAGE_PATH,
"title": "My title", # <---
"description": "My description", # <---
}
ALBUM_NAME = None # default album if None
API_KEY = "149[..]"
API_SECRET = "528[...]"
###############################################
## SCRIPT ##
###############################################
api = pbapi.PbApi(API_KEY, API_SECRET)
api.pb_request.connection.cache = None
# Test if service online
api.reset().ping().post()
result = api.reset().ping().post().response_string
ET = ElementTree.fromstring(result)
if ET.find('status').text != 'OK':
sys.stderr.write("error: Ping failed \n"+result)
sys.exit(-1)
try:
# If there is already a saved oAuth token, no need for a new one
api.username, api.pb_request.oauth_token = cPickle.load(open(TOKEN_FILE))
except (ValueError, KeyError, IOError, TypeError):
# If error, there's no valid oAuth token
# Getting request token
api.reset().login().request().post().load_token_from_response()
# Requesting user permission (you have to login with your account)
webbrowser.open_new_tab(api.login_url)
raw_input("Press Enter when you finished access permission. ")
#Getting oAuth token
api.reset().login().access().post().load_token_from_response()
# This is needed for getting the right subdomain
infos = api.reset().album(api.username).url().get().response_string
ET = ElementTree.fromstring(infos)
if ET.find('status').text != 'OK':
# Remove the invalid oAuth
os.remove(TOKEN_FILE)
# This happend is user deletes the oAuth permission online
sys.stderr.write("error: Permission deleted. Please re-run.")
sys.exit(-1)
# Fresh values for username and subdomain
api.username = ET.find('content/username').text
api.set_subdomain(ET.find('content/subdomain/api').text)
# Default album name
if not ALBUM_NAME:
ALBUM_NAME = api.username
# Debug :-)
print "User: %s" % api.username
# Save the new, valid oAuth token
cPickle.dump((api.username, api.oauth_token), open(TOKEN_FILE, 'w'))
# Posting the image
result = (api.reset().album(ALBUM_NAME).
upload(IMAGE_RECORD).post().response_string)
ET = ElementTree.fromstring(result)
if ET.find('status').text != 'OK':
sys.stderr.write("error: File upload failed \n"+result)
sys.exit(-1)
# Now, as an example what you could do now, open the image in the browser
webbrowser.open_new_tab(ET.find('content/browseurl').text)
Use the python API by Ron White that was written to do just this

Categories

Resources