How to use ChosenInlineResultHandler in python telegram bot to handle the send query result? - callback

Here is my code.
def start(update, context):
buttons = [InlineKeyboardButton("Invite User", switch_inline_query="test")]
update.message.reply_text("Please choose: ", reply_markup=InlineKeyboardMarkup(buttons))
def button(update, context):
query = update.callback_query
print(query)
def main():
updater = Updater(token, use_context=True)
updater.dispatcher.add_handler(ChosenInlineResultHandler(button))
And I set the bot inline feedback 100%, but in that case I can not send the message to the selected chat.
I'd like to send the button with the switch inline query, but I can not.
Here is my new code:
import logging
import os
from unittest import result
from telegram import ReplyKeyboardMarkup, InlineQueryResultArticle, KeyboardButton, InlineKeyboardButton, InlineKeyboardMarkup, WebAppInfo, Update, LoginUrl
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, ContextTypes, CallbackQueryHandler, ChosenInlineResultHandler, InlineQueryHandler
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
invite_state = False
def start(update, context):
"""Send a message when the command /start is issued."""
buttons = [
[InlineKeyboardButton(
text="Random Image",
switch_inline_query="test"
),
InlineKeyboardButton(
"Random Person",
callback_data="2"
)],
]
update.message.reply_text("Please choose:", reply_markup=InlineKeyboardMarkup(buttons))
def button (update, context):
query = update.inline_query.query
results = [
InlineQueryResultArticle(
id=str(uuid4()),
title="Caps",
input_message_content=InputTextMessageContent(query.upper()),
)
]
update.inline_query.answer(results)
def main(receiver_id):
updater = Updater(os.environ['TELEGRAM_BOT_TOKEN'] , use_context=True)
updater.bot.send_message(chat_id=receiver_id, text="welcome")
dp = updater.dispatcher
dp.add_handler(CommandHandler("start", start))
dp.add_handler(InlineQueryHandler(button))
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
But I got error message "Can not find chat" in button function.

I totally solved this problem by using InlineQueryHandler.
So I send the answer with InlineQueryResultArticle and reply_markup with InlineButtons.
Here is the code.
def button (update, context):
query = update.inline_query.query
buttons = [[InlineKeyboardButton("Invitation", login_url=LoginUrl(url=websiteUrl))]]
results = [
InlineQueryResultArticle(
id=str("123456787654321"),
title="Send invitation",
input_message_content=InputTextMessageContent(query),
reply_markup=InlineKeyboardMarkup(buttons)
)
]
update.inline_query.answer(results)
Updater.dispatcher.add_handler(InlineQueryHandler(button))

Related

Why does kivy keep freezing when using python sockets?

I'm working on a basic client-server desktop app project using kivy & sockets & threading.
The client & server work on it's own, however when I try to integrate it with kivy, python & kivy don't want to respond & yet no definitive error pops up.
Could i have some ideas as to how to fix this?
This is the code that freezes when i run it, if i take away the import server_sock it works as a general gui and doesnt freeze.
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
import server_sock
import sys
kivy.require("2.1.0") #latest version
class ConnectPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text="IP:"))
self.ip = TextInput(multiline=False)
self.add_widget(self.ip)
self.add_widget(Label(text="PORT:"))
self.port = TextInput(multiline=False)
self.add_widget(self.port)
self.add_widget(Label(text="USERNAME:"))
self.user = TextInput(multiline=False)
self.add_widget(self.user)
self.join = Button(text="Join")
self.join.bind(on_press=self.join_button)
self.add_widget(Label())
self.add_widget(self.join)
def join_button(self, instance):
port = self.port.text
ip = self.ip.text
user = self.user.text
info = f"Attempting to join {ip}:{port} as {user}"
chat_app.info_page.update_info(info)
chat_app.screen_manager.current = "Info"
Clock.shedule_once(self.connect,1)
def connect(self, _):
port = int(self.port.text)
ip = self.ip.text
user = self.user.text
try:
server_sock.connect(ip, port)
chat_app.create_chat_page()
chat_app.screen_manager.current = "Chat"
except:
show_error(message="not gonna happen")
class InfoPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.message = Label(halign="center", valign="middle", font_size="30")
self.message.bind(width=self.update_text_width)
self.add_widget(self.message)
def update_info(self,message):
self.message.text = message
def update_text_width(self, *_):
self.message.text_size = (self.message.width*0.9, None)
class ChatPage(GridLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.cols = 1
self.add_widget(Label(text="Hey at least it works till now"))
class ChatApp(App):
def build(self):
self.screen_manager = ScreenManager()
self.connect_page = ConnectPage()
screen = Screen(name="Connect")
screen.add_widget(self.connect_page)
self.screen_manager.add_widget(screen)
self.info_page = InfoPage()
screen= Screen(name="Info")
screen.add_widget(self.info_page)
self.screen_manager.add_widget(screen)
return self.screen_manager
def create_chat_page(self):
self.chat_page = ChatPage()
screen = Screen(name="Chat")
screen.add_widget(self.chat_page)
self.screen_manager.add_widget(screen)
def show_error(message):
chat_app.info_page.update_info(message)
chat_app.screen_manager.current = "Info"
Clock.shedule_once(sys.exit, 10)
if __name__ == "__main__":
chat_app =ChatApp()
chat_app.run()
This is the server_sock file
import socket
import threading
import socket
HOST = '127.0.0.1'
PORT = 55555
server = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM
)
try:
server.bind((HOST, PORT))
except:
print(f'unable to bind to {HOST} and {PORT}')
server.listen()
print(f"Listening for connections on {HOST}: {PORT}")
clients = []
nicknames = []
def broadcast(message):
for client in clients:
client.send(message)
def message_recv(client):
while True:
try:
message = client.recv(2048)
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
nickname = nicknames[index]
broadcast(f'{nickname} left the chat'.encode('ascii'))
nicknames.remove(nickname)
break
def recieve():
while True:
client, address = server.accept()
print(f"Connected with {str(address)}")
client.send("SOMETHING".encode('ascii'))
nickname = client.recv(2048).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f"Nickname of the client is {nickname}")
broadcast(f"{nickname} joined the chat".encode('ascii'))
client.send("Connected to the server".encode('ascii'))
thread = threading.Thread(target=message_recv, args=(client,))
thread.start()
print("Server is listening")
recieve()

How to Fix unident does not match for any outer indentation level

i have tried to make a desktop assistant as voice recognizer and do as i say
but i get this error every time i try to run that: unindent does not match with any outer indentation level. can someone please help me!
it is somehow copied from YouTube video
gtts import gTTS
import speech_recognition as sr
import os
import webbrowser
import smtplib
def talktome(audio):
print(audio)
tts = gTTS(text=audio, lang='eng')
tts.save('audio.mp3')
os.system('mpg123 audio.mp3')
def myCommand():
r = sr.Recognizer()
with sr.Microphone() as source:
print('hello')
r.pause_threshold = 1
r.adjust_for_ambient_noise(source, duration = 1)
audio = r.listen(source)
try:
command = r.recognize_google(audio)
print('you said: ' + command + '/n')
except sr.UnknownValueError:
assistant(myCommand())
return command
def assistant(command):
if 'open reddit python' in command:
chrome_pathchrome_path = '/Program Files (x86)/google/Chrome/Application/chrome.exe'
webbrowser.get(chrome_path).open(url)
if 'what\'s up' in command:
talkToMe('i am a bit busy')
if 'email' in command:
talkToMe('who is the recipient?')
recipient = myCommand()
if 'john' in recipient:
talkToMe('what should i say?')
content - myCommand()
mail = smtplib.SMTP('smtp.gmail.com', 587)
mail.ehlo()
mail.starttls()
mail.login('username', 'password')
mail.sendmail('persion name', 'email address#whatever.com'. content)
mail.close()
talkToMe('email sent')
talkToMe('i am ready for your sound')
while true: assistant(myCommand())

my Tornado chat is losing messages

i am losing messages in my tornado chat and i do not known how to detect when the message wasn't sent and to send the message again
there is any way to detect when the conexion get lost? and when the conexión restart send the message
this is my code
def get(self):
try:
json.dumps(MessageMixin.cache)
except KeyError:
raise tornado.web.HTTPError(404)
class MessageMixin(object):
waiters = {}
cache = {}
cache_size = 200
def wait_for_messages(self,cursor=None):
t = self.section_slug
waiters = self.waiters.setdefault(t, [])
result_future = Future()
waiters.append(result_future)
return result_future
def cancel_wait(self, future):
t = self.section_slug
waiters = self.waiters.setdefault(t, [])
waiters.remove(future)
# Set an empty result to unblock any coroutines waiting.
future.set_result([])
def new_messages(self, message):
t = self.section_slug
#cache = self.cache.setdefault(t, [])
#print t
#print self.waiters.setdefault(t, [])
waiters = self.waiters.setdefault(t, [])
for future in waiters:
try:
if message is not None:
future.set_result(message)
except Exception:
logging.error("Error in waiter callback", exc_info=True)
waiters = []
#self.cache.extend(message)
#if len(self.cache) > self.cache_size:
#self.cache = self.cache[-self.cache_size:]
class MessageNewHandler(MainHandler, MessageMixin):
def post(self, section_slug):
self.section_slug = section_slug
post = self.get_argument("html")
idThread = self.get_argument("idThread")
isOpPost = self.get_argument("isOpPost")
arg_not = self.get_argument("arg")
type_not = self.get_argument("type")
redirect_to = self.get_argument("next", None)
message= {"posts": [post],"idThread": idThread,"isOpPost": isOpPost,
"type": type_not,"arg_not": arg_not}
if redirect_to:
self.redirect(redirect_to)
else:
self.write(post)
self.new_messages(message)
class MessageUpdatesHandler(MainHandler, MessageMixin):
#gen.coroutine
def post(self, section_slug):
self.section_slug = section_slug
try:
self.future = self.wait_for_messages(cursor=self.get_argument("cursor", None))
data = yield self.future
if self.request.connection.stream.closed():
return
self.write(data)
except Exception:
raise tornado.web.HTTPError(404)
def on_connection_close(self):
self.cancel_wait(self.future)
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/api/1\.0/stream/(\w+)", MessageUpdatesHandler),
(r"/api/1\.0/streamp/(\w+)", MessageNewHandler)
]
tornado.web.Application.__init__(self, handlers)
def main():
tornado.options.parse_command_line()
app = Application()
port = int(os.environ.get("PORT", 5000))
app.listen(port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
In the original chatdemo, this is what the cursor parameter to wait_for_messages is for: the browser tells you the last message it got, so you can send it every message since then. You need to buffer messages and potentially re-send them in wait_for_messages. The code you've quoted here will only send messages to those clients that are connected at the time the message came in (and remember that in long-polling, sending a message puts the client out of the "waiting" state for the duration of the network round-trip, so even when things are working normally clients will constantly enter and leave the waiting state)

Momoko, Jinja2 and Tornado

there is something fundamentally wrong with my code. These are my
tornado handlers with basic authentication and jinja2 as template
engine. The following works without the momoko db parts.
class BaseHandler(tornado.web.RequestHandler):
#property
def db(self):
return self.application.db
def get_current_user(self):
return self.get_secure_cookie("user")
class TemplateHandler(BaseHandler):
"""Request handler for writing HTML templates."""
def render(self, template_name, **kwargs):
"""Renders a Jinja2 template."""
kwargs['options'] = options.as_dict()
template = templates.environment.get_template(template_name)
html = template.render(kwargs)
self.write(html)
class AuthLoginHandler(TemplateHandler):
def get(self):
try:
errormessage = self.get_argument("error")
except:
errormessage = ""
self.render("login.html", errormessage = errormessage)
def check_permission(self, password, username):
if username == "admin" and password == "admin":
return True
return False
def post(self):
username = self.get_argument("username", "")
password = self.get_argument("password", "")
auth = self.check_permission(password, username)
if auth:
self.set_current_user(username)
self.redirect(self.get_argument("next", u"/"))
else:
error_msg = u"?error=" + tornado.escape.url_escape("Login incorrect")
self.redirect(u"/auth/login/" + error_msg)
def set_current_user(self, user):
if user:
self.set_secure_cookie("user", tornado.escape.json_encode(user))
else:
self.clear_cookie("user")
class AuthLogoutHandler(TemplateHandler):
def get(self):
self.clear_cookie("user")
self.redirect(self.get_argument("next", "/"))
class MainHandler(TemplateHandler):
#gen.engine
def get(self):
username = tornado.escape.xhtml_escape(self.current_user)
try:
cursor = yield momoko.Op(self.db.execute, 'SELECT * FROM products;')
except Exception as error:
self.write(str(error))
res = 'Query results: '+''.join(str(cursor.fetchall()))
self.render("index.html", username = username, cip = self.request.remote_ip, res = res)
For the logged in client, this code should execute a basic query and then print the result to the defined location ( {{ res }} ) within the jinja template. When I try to start the server, I get this:
line 22, in render
kwargs['options'] = options.as_dict()
AttributeError: 'module' object has no attribute 'as_dict'
We'll need to see your "import" statements to know what's wrong for certain. I suspect you have:
from tornado import options
But you need:
from tornado.options import options

Push notification from python to iPhone, how to debug?

How do one debug the connection from a provider to Apple push notification server?
I'm using a library called PyAPNs (github repo) and have the code below:
from apns import APNs, Payload
print "start"
apns = APNs(use_sandbox=True, cert_file='apns-prod.pem', key_file='apns-prod.pem')
# Send a notification
token_hex = '*******'
payload = Payload(alert="Hello World!", sound="default", badge=1)
apns.gateway_server.send_notification(token_hex, payload)
# Get feedback messages
for (token_hex, fail_time) in apns.feedback_server.items():
print token_hex
print fail_time
print "end"
The application is registered to receive RemoteNotification an everything looks okey under notification settings in the iPhone. But not notifications shows up.
My questions here how can I debug this. When running the script I don't get any errors and the apns.feedback_server.items is empty. I've tried to print the buffer from the feedback serve, but nothing.
Is there a way to see what's happening in the SSL socket? Or get some response from apples servers?
..fredrik
EDIT
I solved the problem. The issues was with the token_hex. I used the identifier number from the xcode organizer and not the token generated when registering the application.
USE THIS CODE:
#!/usr/bin/python2.7
import socket
import ssl
import json
import struct
import argparse
APNS_HOST = ( 'gateway.sandbox.push.apple.com', 2195 )
class Payload:
PAYLOAD = '{"aps":{${MESSAGE}${BADGE}${SOUND}}}'
def __init__(self):
pass
def set_message(self, msg):
if msg is None:
self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '')
else:
self.PAYLOAD = self.PAYLOAD.replace('${MESSAGE}', '"alert":"%s",' % msg)
def set_badge(self, num):
if num is None:
self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '')
else:
self.PAYLOAD = self.PAYLOAD.replace('${BADGE}', '"badge":%s,' % num)
def set_sound(self, sound):
if sound is None:
self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '')
else:
self.PAYLOAD = self.PAYLOAD.replace('${SOUND}', '"sound":"%s",' % sound)
def toString(self):
return (self.PAYLOAD.replace('${MESSAGE}','').replace('${BADGE}','').replace('${SOUND}',''))
def connectAPNS(host, cert):
ssl_sock = ssl.wrap_socket( socket.socket( socket.AF_INET, socket.SOCK_STREAM ), certfile = cert )
ssl_sock.connect( APNS_HOST )
return ssl_sock
def sendNotification(sslSock, device, message, badge, sound):
payload = Payload()
payload.set_message(message)
payload.set_badge(badge)
payload.set_sound(sound)
payloadAsStr = payload.toString()
format = '!BH32sH%ds' % len(payloadAsStr)
binaryDeviceToken = device.replace(' ','').decode('hex')
binaryNotification = struct.pack( format, 0, 32, binaryDeviceToken, len(payloadAsStr), payloadAsStr )
print ("sending payload: ["+payloadAsStr+"] as binary to device: ["+device+"]")
sslSock.write(binaryNotification)
def printUsageAndExit():
print("msg2ios - Version 0.1\nmsg2IOS.py -d <device> -m <message> -s[plays sound] -b <badgeint> -c <certBundlePath>")
exit(1)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--device')
parser.add_argument('-m', '--message')
parser.add_argument('-s', '--sound')
parser.add_argument('-b', '--badge')
parser.add_argument('-c', '--cert')
args = parser.parse_args()
if (args.device is None) or ((args.message is None) and (args.sound is None) and (args.badge is None)) or (args.cert is None):
printUsageAndExit()
sslSock = connectAPNS(APNS_HOST, args.cert)
sendNotification(sslSock, args.device, args.message, args.badge, args.sound)
sslSock.close()