Flask socketio multiple connections - python

I am trying to create a FB-chat like application. I have already started with the bare minimum of flask socketio implementation. So far, I already understand that client and server side communicate through a common handler. My current implementation is a free for all chat. for brevity i just show the handlers:
Client side:
socket.on('message', function(msg) {
$("#messages").append('<li>'+msg+'</li>');
console.log('Received message');
});
Server side:
#socketio.on('message')
def handleMessage(msg):
print('Message: ' + msg)
send(msg, broadcast=True)
Question:
How do I pass in arguments so I could have different chat ids

I guess what you want to do is some chat rooms. Good news! Flask-SocketIO is now natively dealing with rooms.
You can import the modules like this :
from flask_socketio import SocketIO, emit, join_room, leave_room,
close_room, rooms, disconnect
For joining a room, it looks like this :
#socketio.on('join', namespace='/test')
def join(message):
join_room(message['room'])
session['receive_count'] = session.get('receive_count', 0) + 1
emit('my_response',
{'data': 'In rooms: ' + ', '.join(rooms()),
'count': session['receive_count']})
You can find a complete example of code in the Miguel's Github page :)

Hi sorry for previous answer.
You can get cookies from sid. If you save chat id into cookies. you can identify user id easily.
this is my namespace code.
import socketio
import imp
import json
from datetime import datetime, timedelta
gameDBModule = imp.load_compiled("ChatDatabase", "./game_chat/chat_database.pyc")
apiModule = imp.load_compiled("TotoAPI", "./game_api/__init__.pyc")
class GameChat(socketio.Namespace):
def init(self):
self.lastDataIndex = 0
self.api = apiModule.TotoAPI()
def on_join(self, sid, message):
self.db = gameDBModule.ChatDatabase()
sessid = self.getUserId(sid)
try:
info = json.loads(self.api.userinfo(sessid))
userID = str(info[4])
except Exception as e:
userID = None
self.emit('join', {'history': self.db.get_chathistory(), 'channel': message, 'moderator': False, 'user_id': userID}, room=sid)
def on_connect(self, sid, environ):
self.emit('connect', {'data': 'Connected', 'count': 0}, room=sid)
print('GameChat Connected')
def on_say(self, sid, message, environ):
sessid =self.getUserId(sid)
try:
info = json.loads(self.api.userinfo(sessid))
userID = str(info[4])
except Exception as e:
userID = None
if userID !=None:
userID = None
#Save into History
now = self.get_current_time(9)
self.lastDataIndex = self.lastDataIndex + 1
item = {
'dataIndex': self.lastDataIndex,
'bot': False,
'date': now,
'message': message,
'role': 'user',
'type': 'say',
'user_id': userID
}
self.emit('msg', item)
item['date'] = self.get_current_time(0)
self.db.insert_chatting(item)
def on_disconnect(self, sid):
print('GameChat disconnected')
def getUserId(self, sid):
try:
#Get UserID from Cookies
cookies = str(self.server.environ[sid]['HTTP_COOKIE']).split(';')
id = None
for item in (cookies):
name=str(item).split('=')[0].strip()
value=str(item).split('=')[1].strip()
if name.__eq__('ci_session'):
id = value
return id
except Exception as e:
return None
def get_current_time(self, diff):
i = datetime.now() - timedelta(hours = diff)
return i.isoformat()[:-3]+"Z"
this is the code using above name space
async_mode = 'eventlet'
import eventlet
import eventlet.wsgi
from flask import Flask, render_template, Response, request, make_response
import socketio
import imp
gameChatModule = imp.load_compiled("GameChat", "./game_chat/__init__.pyc")
apiModule = imp.load_compiled("TotoAPI", "./game_api/__init__.pyc")
sio = socketio.Server(logger=False, async_mode=async_mode)
app = Flask(__name__)
app.wsgi_app = socketio.Middleware(sio, app.wsgi_app)
app.config['SECRET_KEY'] = 'secret!'
api = apiModule.TotoAPI()
ns = gameChatModule.GameChat("/")
ns.init()
if __name__ == '__main__':
sio.register_namespace(ns)
eventlet.wsgi.server(eventlet.listen(('', 8880)), app)
I have implemented it in python 2.7 You seem use python 3. but you can implement my code.

Related

Can't implement braintree subscription on Flask

I have this app
import braintree
from flask import Flask, render_template, send_from_directory, request
try:
from ConfigParser import SafeConfigParser
except ImportError:
from configparser import SafeConfigParser
app = Flask(__name__)
parser = SafeConfigParser()
parser.read('secrets.ini')
MERCHANTID = parser.get('braintree', 'MERCHANTID')
PUBLICKEY = parser.get('braintree', 'PUBLICKEY')
PRIVATEKEY = parser.get('braintree', 'PRIVATEKEY')
braintree.Configuration.configure(braintree.Environment.Sandbox,
merchant_id=MERCHANTID,
public_key=PUBLICKEY,
private_key=PRIVATEKEY)
#app.route("/")
def index():
# Generate client token for the dropin ui
client_token = braintree.ClientToken.generate({})
return render_template('index.html', token=client_token)
#app.route("/proc", methods=['GET', 'POST'])
def proc():
# result = braintree.Transaction.sale({
# "amount": request.form["amount"],
# "payment_method_nonce": request.form["payment_method_nonce"]
# })
# print(result)
result = braintree.Customer.create({
"credit_card": {
"number": "4111111111111111",
"expiration_date": "12/16"
}
})
result = braintree.Subscription.create({
"payment_method_token": result.customer.credit_cards[0].token,
"plan_id": "upwork_sub"
})
return render_template('proc.html', result=result, request=request.form)
if __name__ == "__main__":
app.run(host='0.0.0.0')
The one time charge(the code that is commented) works fine.
The problem is when I want to charge with subscription I have to hard create the Client and then auto charge with subscription.
How I can make it without hard coding the clients info

Error: Timestamp for this request is outside of revcWindow

I'm trying to send a request to the binance servers which require an api-key and a signature but the console is saying that the timestamp is outside of the revcWindow
I've looked up the problem and found that I need sync my computer's time to the Binance's. I'm not quite sure how to do that though (pretty newbie in Python)
def test(self):
self.url += self.url_list['test']
params = {'symbol': 'BTCETH', "timestamp": 0, "side": "BUY", "type": "LIMIT", "quantity": 0.0005, "recvWindow": 500 }
data = parammanger.encode_params(params)
data += "&signature=" + self.hash(data)
headers = {'X-MBX-APIKEY': self.a_key}
print(data)
r_body = {'signature': self.hash(data)}
r = requests.post(self.url, data, headers=headers)
print(r.request.headers)
print(r.json())
def hash(self, data):
return hashmanager.create_hash(self.s_key.encode("utf-8"), data.encode("utf-8"))
{'code': -1021, 'msg': 'Timestamp for this request is outside of the recvWindow.'}
The syncing has to do more with you SO that with Python.
Those guys here: have some solutions enter link description here
This one seems to be bulletproof (so far)
import time
from binance.client import Client
class Binance:
def __init__(self, public_key = '', secret_key = '', sync = False):
self.time_offset = 0
self.b = Client(public_key, secret_key)
if sync:
self.time_offset = self._get_time_offset()
def _get_time_offset(self):
res = self.b.get_server_time()
return res['serverTime'] - int(time.time() * 1000)
def synced(self, fn_name, **args):
args['timestamp'] = int(time.time() - self.time_offset)
return getattr(self.b, fn_name)(**args)
#I then instantiate it and call my private account functions with synced
binance = Binance(public_key = 'my_pub_key', secret_key = 'my_secret_key', sync=True)
binance.synced('order_market_buy', symbol='BNBBTC', quantity=10)
Edit:
I found an easier solution here, and the other one does not seems to be so bulletproof: enter link description here
from binance.client import Client
client = Client('api_key', 'api_secret')
import time
import win32api
gt = client.get_server_time()
tt=time.gmtime(int((gt["serverTime"])/1000))
win32api.SetSystemTime(tt[0],tt[1],0,tt[2],tt[3],tt[4],tt[5],0)

How can I pass to graphql more than one record using Orientdb and Flask?

I has the following code, i try to build and microservice that allow me get specific fields in my application, am beginning with orientdb and graphql:
from flask import Flask, request
import graphene
import json
import pyorient
app = Flask(__name__)
class Person(graphene.ObjectType):
name = graphene.String()
middle_name = graphene.String()
last_name = graphene.String()
class Query(graphene.ObjectType):
person = graphene.Field(Person, id=graphene.Argument(graphene.Int))
persons = graphene.Field(Person)
def resolve_person(self, info, id):
with open('orientdb_config.json') as config_file:
orient_config = json.load(config_file)
try:
client = pyorient.OrientDB(orient_config["host"], orient_config["port"])
session_id = client.connect(orient_config["user"], orient_config["password"])
client.db_open(orient_config["database"], orient_config["user"], orient_config["password"])
if client is not None:
query = "SELECT * FROM Person WHERE #rid = #12: %(id)s" % {'id': id}
data = client.query(query)
print(data[0])
return data[0]
else:
return None
except Exception as e:
return None
def resolve_persons(self, info):
with open('orientdb_config.json') as config_file:
orient_config = json.load(config_file)
try:
client = pyorient.OrientDB(orient_config["host"], orient_config["port"])
session_id = client.connect(orient_config["user"], orient_config["password"])
client.db_open(orient_config["database"], orient_config["user"], orient_config["password"])
if client is not None:
query = "SELECT * FROM Person"
data = client.query(query)
result = []
for d in data:
result.append(d)
return result
else:
return None
except Exception as e:
return None
schema = graphene.Schema(query=Query)
#app.route("/", methods=['POST'])
def main():
data = json.loads(request.data)
return json.dumps(schema.execute(data['query']).data)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5002, debug=True)
Everything seems to work when I request a Person using its id, but when I try to obtain all the people, graphql responds with a null value, I verify the result of the query and the value is there.
In your GraphQL definition, you should have
persons = graphene.List(lambda: Person)

Python keeps KeyError: 'message' when fetch data from Messenger Callback - Python/flask

I've tried to build a simple bot on Messenger that echoing back whenever we send a message to it.
The message is sent successfully so far but in the log, it keeps displaying error:
message_id = data['entry'][0]['messaging'][0]['message']['mid']
KeyError: 'message'
I have no idea why it happen, this is the logic operations:
import requests
import traceback
from flask import request
from ...config.default import VERIFY_TOKEN, ACCESS_TOKEN
ROOT_URL = "https://graph.facebook.com/v2.6/me/messages?access_token="
def reply(user_id, page_id, msg):
data = {
"sender": {"id": page_id},
"recipient": {"id": user_id},
"message": {"text": msg}
}
requests.post(ROOT_URL + ACCESS_TOKEN, json=data)
def verification_handler():
if request.args['hub.verify_token'] == VERIFY_TOKEN:
return request.args['hub.challenge'], 200
return "Invalid verification token"
def handle_incoming_messages(data):
try:
# Get all data from Messenger callback - Text
recipient_id = data['entry'][0]['messaging'][0]['recipient']['id']
sender_id = data['entry'][0]['messaging'][0]['sender']['id']
timestamp = data['entry'][0]['messaging'][0]['timestamp']
message_id = data['entry'][0]['messaging'][0]['message']['mid']
text = data['entry'][0]['messaging'][0]['message']['text']
reply(sender_id, recipient_id, text)
except KeyError:
print(traceback.format_exc())
return ''
this is the routes:
from flask import Blueprint, request
from .ops import verification_handler, handle_incoming_messages
mod = Blueprint('messenger', __name__)
# Route: /messenger/
#mod.route('/', methods=['GET'])
def verify():
"""Facebook will GET request to this endpoint for verification."""
return verification_handler()
# Route: /messenger/
#mod.route('/', methods=['POST'])
def handle():
data = request.json
handle_incoming_messages(data)
return ''
# Route: /messenger/hello
#mod.route('/hello')
def hello():
return 'hello there'
I don't have enough reputation to leave a comment so I have to post this here.
From the Python Wiki
Python raises a KeyError whenever a dict() object is requested (using the format a = adict[key]) and the key is not in the dictionary.
Are you sure the key 'message' exists?
I do this to extract the info
if keys_exist(event, ['body']):
event_entry=json.loads(event['body'])
if ((len(event_entry['entry'])>0) & (keys_exist(event_entry['entry'][0],['messaging'])) ):
messaging_event = event_entry['entry'][0]['messaging'][0]
if (keys_exist(messaging_event,['message'])):
msg_txt = messaging_event['message']['text']
sender_id = messaging_event['sender']['id']

Where to mock to test a Django view that calls a service?

This is Django 1.6.8, Python 2.7, and the mock library.
I have a view that calls a remote service using suds for sales tax information (this is a simplified version):
def sales_tax(self, bundle_slug):
bundle = get_object_or_404(Bundle, slug=bundle_slug,
active=True)
cloud = TaxCloud(TAXCLOUD_API_ID, TAXCLOUD_API_KEY)
origin = Address('origin address')
destination = Address('customer address')
cart_item = CartItem(bundle.sku, TAXCLOUD_TIC_ONLINE_GAMES,
bundle.price, 1)
try:
rate_info = cloud.get_rate(origin, destination,
[cart_item],
str(customer.id))
sales_tax = Decimal(rate_info['sales_tax'])
response = {'salesTax': locale.currency(sales_tax),
'total': locale.currency(bundle.price + sales_tax)}
except TaxCloudException as tce:
response = {
'error': str(tce)
}
Here's relevant code from the TaxCloud class:
from suds.client import Client
from suds import WebFault
class TaxCloud(object):
def __init__(self, api_login_id, api_key):
self.api_login_id = api_login_id
self.api_key = api_key
self.soap_url = 'https://api.taxcloud.net/1.0/TaxCloud.asmx'
self.wsdl_url = 'https://api.taxcloud.net/1.0/?wsdl'
self.client = Client(url=self.wsdl_url, location=self.soap_url, faults=False)
def get_rate(self, billing_address, origin_address, raw_cart_items, customer_id):
address = self.convert_to_address(billing_address)
origin = self.convert_to_address(origin_address)
cart_items = self.convert_to_cart_list(raw_cart_items)
response = self.client.service.Lookup(self.api_login_id,
self.api_key, customer_id,
self.cart_id(customer_id), cart_items,
address, origin, True, None)
if( response[1].ResponseType == 'Error' ):
raise TaxCloudException(response[1].Messages[0][0].Message)
return {
'sales_tax': str(response[1].CartItemsResponse[0][0].TaxAmount),
'cart_id': response[1].CartID
}
In my test for the view, I don't want to call the remote service. Using this example of a mocked client, I built out a dumb mock class (my ClientMock matches exactly the example in that answer):
class TaxCloudServiceClientMock(ClientMock):
"""
Mock object that implements remote side services.
"""
def Lookup(cls, api_id, api, customer_id, cart_id, cart_items,
address, origin, flag, setting):
"""
Stub for remote service.
"""
return """(200, (LookupRsp){
ResponseType = "OK"
Messages = ""
CartID = "82cabf35faf66d8b197c7040a9f7382b3f61573fc043d73717"
CartItemsResponse =
(ArrayOfCartItemResponse){
CartItemResponse[] =
(CartItemResponse){
CartItemIndex = 1
TaxAmount = 0.10875
},
}
})"""
In my test, I'm trying to #patch the Client used in the TaxCloud class:
#patch('sales.TaxCloud.Client', new=TaxCloudServiceClientMock)
def test_can_retrieve_sales_tax(self):
from django.core.urlresolvers import reverse
tax_url = reverse('sales_tax', kwargs={'bundle_slug': self.bundle.slug})
self.client.login(username=self.user.username, password='testpassword')
response = self.client.get(tax_url, {'address1': '1234 Blah St',
'city': 'Some City',
'state': 'OH',
'zipcode': '12345',
'country': 'US'},
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
self.assertEqual(response.status_code, 200)
The remote call is still being made, however. Based on the "Where to mock" documentation, I'm correctly targeting sales.TaxCloud.Client instead of suds.client.Client.
What could be causing the patch to be ignored/bypassed?

Categories

Resources