Using telethon with a django application - django

I want to watch updates on telegram messages in an django application and interact with django orm.
I found telethon library, it works with user api which is what I want.
Below code simply works on its own.
from telethon import TelegramClient
from telethon import events
api_id = 231232131
api_hash = '32131232312312312edwq'
client = TelegramClient('anon', api_id, api_hash)
#client.on(events.NewMessage)
async def my_event_handler(event):
if 'hello' in event.raw_text:
await event.reply('hi!')
client.start()
But telethon requires phone message verification and it needs to work in a seperate thread.
I couldn't find a way to put this code in a django application. And when django starts, I dont know how to bypass phone verification.
It should always work in an seperate loop and interact with django orm. Which is very confusing for me.

You can simply use django-telethon and use the API endpoints for signing bot and user session.
run the following command to start the server:
python manage.py runserver
run the following command to start telegram client:
python manage.py runtelegram
go to admin panel and telegram app section. create a new app. get data from the your Telegram account.
request code from telegram:
import requests
import json
url = "127.0.0.1:8000/telegram/send-code-request/"
payload = json.dumps({
"phone_number": "+12345678901",
"client_session_name": "name of the client session"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
send this request for sign in:
import requests
import json
url = "127.0.0.1:8000/telegram/login-user-request/"
payload = json.dumps({
"phone_number": "+12345678901",
"client_session_name": "name of the client session",
"code": "1234",
"password": "1234"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)

It's not the answer I wanted initially.
But, I think this is better approach.
Instead of trying to put all of this in django application. It's better to run it seperately and let django application communicate this with rest framework.

Related

Flask Facebook Login using Oauthlib - redirect problem

I would like to implement Facebook login using Flask.
Here is the function which is called to request service from Facebook
#users_view.route('/facebook/')
def facebook():
credentials = current_app.config['OAUTH_CREDENTIALS']['facebook']
f_client = WebApplicationClient(credentials['id'])
authorization_endpoint = 'https://www.facebook.com/dialog/oauth'
request_uri = f_client.prepare_request_uri(
authorization_endpoint,
redirect_uri=request.base_url + "/auth",
scope=["email"],
auth_type = "reauthenticate",
)
print("REQUEST: {}".format(request_uri))
return redirect(request_uri)
#users_view.route("/facebook/auth")
def facebook_callback():
credentials = current_app.config['OAUTH_CREDENTIALS']['facebook']
f_client = WebApplicationClient(credentials['id'])
token_endpoint = 'https://graph.facebook.com/oauth/access_token'
code = request.args.get("code")
token_url, headers, body = f_client.prepare_token_request(
token_endpoint,
authorization_response=request.url,
redirect_url=request.base_url,
code=code
)
print("ALL: url:{} headers:{} url:{} ".format(token_url, headers, body))
Which forwards me to this URL:
https://www.facebook.com/dialog/oauth?response_type=code&client_id=5453357158093262&redirect_uri=https%3A%2F%2F127.0.0.1%3A5000%2Fuser%2Ffacebook%2F%2Fauth&scope=email&auth_type=reauthenticate&ret=login&fbapp_pres=0&logger_id=1cc03c7d-9a19-43ba-978c-4ed8cb7aa559&tp=unspecified&cbt=1663931173196&ext=1663941992&hash=AeaYsntT-4HEQj4ZtfI
That throws the following Error:
In my Facebook developers account, I have following redirect URL configuration:
Kindly, advice how can I fix this issue.
Facebook API is expecting the requester to use HTTPS as you've set in your Facebook Developer Account.
Probably you are running your flask app using HTTP protocol (not HTTPS) while on your Facebook Developer account you did white-list only HTTPS, but since you didn't specify HTTP it will be rejected.
A) You cannot allow HTTP(without S) from Facebook Panel because Oauth2 need HTTPS.
Try:
B) Install pyOpenSSL
pip3 install pyOpenSSL
Create ssl_my_app.py and run with ssl_context:
from flaskr import create_app
from flask import current_app, g
import sqlite3 # if using databases
app = create_app()
with app.app_context():
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
with current_app.open_resource('schema.sql') as f:
g.db.executescript(f.read().decode('utf-8'))
app.run(ssl_context='adhoc')
run the app using ssl_my_app.py:
python3 ssl_my_app.py
This will run the app using HTTPS (self-signed certificate).
So when you call Facebook API your application's request will be in the white-list.

Flask: Request works on browser but not on Postman

I'm creating a simple Flask app. My problem is that when I try to do a request from Postman, I alway get a 501 Not Implemented.
However, if I do the request directly from my browser, I got a successful response.
My code is:
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Logs(Resource):
def get(self):
return {'hello': 'world'}
api.add_resource(Logs, '/logs')
if __name__ == '__main__':
app.run(debug=True, load_dotenv=True)
I'm not sure what is causing Postman to not being able to communicate with the app.
I'm sure I'm sending a GET request from Postman.
I'm attaching my Postman request configuration as an image.
Did you make sure you put your request type to GET and not to POST on Postman? The error usually means that the server doesn't know the request type and maybe expects a POST request but a post request hasn't been implemented in the Resource in your flask endpoint.

How to make a request to local URL as part of automated tests?

I'm writing an automated test in Django to check that a webhook is working on the application. The test sends a bunch of JSON to the webhook and will check that the call has been logged in the database. The problem I'm hitting however is that the test calls the http://localhost URL and the data is thus saved in my local dev database and not in the temporary database created by the test. So I now have no way to check the call has been received.
Whats the right solution for this?
from django.test import TestCase
import requests
from monzo.models import Transaction, RequestLog
class WebhookChecks(TestCase):
fixtures = ['db.json', ]
def test_simple_expense(self):
my_json = '{"type": "transaction.created", REMOVED FOR SECURITY }'
url = 'http://localhost/some_url/webhook/'
headers = {'Content-Type': 'application/json'}
r = requests.post(url, data=my_json, headers=headers)
if not "200" in str(r):
print("Something didn't work out. Error: "+str(r))
self.assertTrue("200" in str(r))
Use Djangos Client with which you can perform requests in your tests.
Example:
from django.test import Client
c = Client()
c.get('/some_url/..')
Another way is to use Djangos LiveServerTestCase.
You can use self.live_server_url instead of directly writing http://localhost.
This testcase sets up a live server which listens to localhost.

unable to make a successful call from android using retrofit with csrf token

I'm new to django and got struck with csrf tokens. I'm making a post request from android using retrofit to my django server which is using csrf protection. I had obtained the csrf token by making a get request first and then I'm passing this csrftoken from the body of POST request. However, my server is showing 'CSRF cookie not set' error. The server is responding well to the calls from POSTMAN but when I make calls from android, I get this error. I think there is some simple thing I'm missing, but I'm not able to figure it out.
Session based authorization is usually used in web-apps. In case of android apps which are backed by API.
So rather than you can do Token Based Authorization using rest_framework in Django.
In your settings.py
INSTALLED_APPS = [
...
'rest_framework',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
}
Now migrate the migrations to the database.
python manage.py migrate
Run this command to generate token for the specific user.
python manage.py drf_create_token <username>
Now add this line to urls.py.
from rest_framework.authtoken.views import obtain_auth_token
urlpatterns = [
#Some other urls.
path('api-token-auth/', obtain_auth_token, name='api_token_auth'),
]
Using this you can obtain token for any user by using its username & password by just passing them in request body.
So this will be our protected api. Add this class based view in your views.py
from rest_framework.permissions import IsAuthenticated,AllowAny # <-- Here
from rest_framework.views import APIView
from rest_framework.response import Response
class DemoData(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request):
content = {'data': 'Hello, World!'}
return Response(content)
Now pass a header with the api name as 'Authorization' & value be like something 'Token 5a2b846d267f68be68185944935d1367c885f360'
This is how we implement Token Authentication/Authorization in Django.
For more info, click here to see official documentation.

Running django admin command via curl or request.post

I have a special Django admin action called "run_test".
I would like to start that action from a Jenkins job on some items.
Something like this was my idea
import json
import requests
url = "http://localhost:8000/admin/app/model/"
item = { "user": "jenkins",
"password": "password",
"action": "run_test",
"index": 0
}
headers = {"Content-Type":"application/json","Accept": "application/json"}
resp = requests.post(url,data=json.dumps(item),headers=headers)
print(resp)
403 is the answer I got as a response.
Is there a way to run Django admin command with curl or request.post?
How can I include a queryset?
Note: manage.py command is not an option
This requires a bit of stateful shell scripting -- login to admin area, obtain a magic cookie and then shoot your custom requests with the magic cookie included. Details in this answer.