Using commands (/) in inline mode for a Telegram bot - python

I use python-telegram-bot wrapper.
For a command that is called upon using '/' I have the following method:
def advice(update, context):
with open ("advice.txt", "rt") as file_advice:
line=file_advice.readlines()
advice_message=random.choice(line)
context.bot.send_message(chat_id=update.effective_chat.id, text=advice_message)
advice_handler = CommandHandler('advice', advice)
dispatcher.add_handler(advice_handler)
I want this method to be called in inline mode when '/advice' is typed and there should be no output in all other cases.
I'm familiar with examples from the wrapper developers, where they show the following code:
def inline_caps(update, context):
query = update.inline_query.query
if not query:
return
results = list()
results.append(
InlineQueryResultArticle(
id=query.upper(),
title='Caps',
input_message_content=InputTextMessageContent(query.upper())
)
)
context.bot.answer_inline_query(update.inline_query.id, results)
inline_caps_handler = InlineQueryHandler(inline_caps)
dispatcher.add_handler(inline_caps_handler)
I tried to swap query.upper() with advice(update, context) but there are different errors about unknown type so feels like I don't know what I'm doing.

It won't work like that because InputTextMessageContent() requieres a string at least and your function doesn't return a string. In that case I would rewrite the advice function so you can reuse it in your command handler and your inline handler.
import random
from uuid import uuid4
def getAdvice():
with open ("advice.txt", "rt") as file_advice:
line=file_advice.readlines()
advice_message=random.choice(line)
return advice_message
def advice(update, context):
advice_message=getAdvice()
context.bot.send_message(chat_id=update.effective_chat.id, text=advice_message)
def inlinequery(update, context):
query = update.inline_query.query
results = [
InlineQueryResultArticle(
id=uuid4(),
title="/advice",
input_message_content=InputTextMessageContent(
getAdvice()))
]
update.inline_query.answer(results)
advice_handler = CommandHandler('advice', advice)
dispatcher.add_handler(advice_handler)
inlinequery_handler = InlineQueryHandler(inlinequery)
dispatcher.add_handler(inlinequery_handler)

Related

Python `beanie` mongo ODM: Bulk update with upsert=True

I am using beanie==1.10.1
I want to perform bulk operation with updating multiple documents with upsert=True. I expect following code to insert full document if find query didn't give results.
I was using this as a reference: https://github.com/roman-right/beanie/blob/main/tests/odm/documents/test_bulk_write.py
Here is full code:
import beanie
import asyncio
import random
from beanie import BulkWriter
from beanie.odm.operators.update.general import Set
from motor.motor_asyncio import AsyncIOMotorClient
class TestDoc(beanie.Document):
a: str
b: int
async def init_mongo():
mongo_client = AsyncIOMotorClient("mongodb://127.0.0.1:27017")
await beanie.init_beanie(
database=mongo_client.db_name, document_models=[TestDoc]
)
async def run_test():
await init_mongo()
docs = [TestDoc(a=f"id_{i}", b=random.randint(1, 100)) for i in range(10)]
async with BulkWriter() as bulk_writer:
for doc in docs:
await TestDoc \
.find_one({TestDoc.a: doc.a}, bulk_writer=bulk_writer) \
.upsert(Set({TestDoc.b: doc.b}), on_insert=doc, bulk_writer=bulk_writer)
# .update_one(Set(doc), bulk_writer=bulk_writer, upsert=True)
read_docs = await TestDoc.find().to_list()
print(f"read_docs: {read_docs}")
if __name__ == '__main__':
pool = asyncio.get_event_loop()
pool.run_until_complete(run_test())
After executing no documents are inserted into db. Not with .upsert() nor with .update_one() method. What is correct way to achieve that logic?
With pymongo such operation would be written like so (and it works):
def write_reviews(self, docs: List[TestDoc]):
operations = []
for doc in docs:
doc_dict = to_dict(doc)
update_operation = pymongo.UpdateOne(
{"a": doc.a}, {"$set": doc_dict}, upsert=True
)
operations.append(update_operation)
result = self.test_collection.bulk_write(operations)
PS: Cannot create beanie tag here. Can someone create it for me?
This is old, and you probably figured it out but since its the first result in a google search for me I thought I would answer.
The current way you use bulk_writer is just wrapping the options and then committing them.
from beanie.odm.operators.update.general import Set
async def run_test():
await init_mongo()
docs = [TestDoc(a=f"id_{i}", b=random.randint(1, 100)) for i in range(10)]
async with BulkWriter() as bulk_writer:
for doc in docs:
await TestDoc \
.find_one({TestDoc.a: doc.a}) \
.upsert(Set({TestDoc.b: doc.b}), on_insert=doc)
bulk_writer.commit()
read_docs = await TestDoc.find().to_list()
print(f"read_docs: {read_docs}")
Original Test in Beanie Test Suite

Python async call to regular function

I am trying to run async function that will call to a regular function.
Tried this:
import asyncio
from okta.client import Client as OktaClient
def startFunc(metadataURL,appID):
print("This is the",metadataURL, appID)
config = {
'orgUrl': 'https://example.com',
'token': 'myToken'}
okta_client = OktaClient(config)
async def skipFunc():
apps, resp, err = await okta_client.list_applications()
for app in apps:
appsList = (app.label,app.id)
for app.label in appsList:
if app.label == 'John':
strApp = str(app)
appJson = ast.literal_eval(strApp)
metadataURL = (appJson['links']['metadata']['href'])
appID = (appJson['id'])
startFunc(metadataURL,appID) ## Trying to call this function
loop = asyncio.get_event_loop()
loop.run_until_complete(skipFunc())
I do not receive the output, It looks like the function startFunc() didn't execute and I am not getting any error.
Hope you can help me.

Is there a way to combine 2 decorators in python with or condition?

I am using RTMclient to get slack message data. Here the type of message is 'message' which only gives us the data of parent thread. But I want the message data of replies.
On research I found it is 'message_replied' type. I want to include either message or message_replied in decorator.
Pfb a sample code.
#slack.RTMClient.run_on(event='message')
def respond(**payload):
data = payload['data']
web_client = payload['web_client']
rtm_client = payload['rtm_client']
user_id = data.get("user")
text = data.get("text")
Here I want to use #slack.RTMClient.run_on(event='message_replied') also but with 'or' condition
Looking at the source code for slack.RTMClient.run_on(), you should be able to "stack" the decorators like so:
#slack.RTMClient.run_on(event='message')
#slack.RTMClient.run_on(event='message_replied')
def respond(**payload):
data = payload['data']
web_client = payload['web_client']
rtm_client = payload['rtm_client']
user_id = data.get("user")
Have you tried this?

Creating interpreter with python and want to read from file instead of shell commands

I'm making an interpreter with python (following a tutorial) and want to read from a file instead of writing into shell (tutorial only shows how to input to shell).
I've tried using def load_file(filename) but it's probably not that easy to change the code and it doesn't work
Main run function, tried adding :
def open_file(filename):
data = open(filename, "r").read()
return data
def run(fn, text):
data = open_file(argv[0])
....
Current function that works using shell:
def run(fn, text):
# Generate tokens
lexer = Lexer(fn, text)
tokens, error = lexer.make_tokens()
if error: return None, error
# Generate AST
parser = Parser(tokens)
ast = parser.parse()
if ast.error: return None, ast.error
# Run program
interpreter = Interpreter()
context = Context('<program>')
context.symbol_table = global_symbol_table
result = interpreter.visit(ast.node, context)
return result.value, result.error
Shell.py:
import litas
while True:
text = input('litas > ')
result, error = litas.run('<stdin>', text)
if error: print(error.as_string())
elif result: print(result)

OpenSubtitle API, returning blank data with status 200

(A same question is available in Stackoverflow. But that didn't help me because it used other function)
API Documentation
Hello, I am trying to implement Opensubtitle API with Python. I prefer trying to search subtitle file with hash, because it's accurate.
As I have never used xmlrpc before and quite new to using APIs, I had to study to make it work. But I am stuck at the final point. My program is returning Status 200 (OK), but the 'data' array is blank. I think, I am doing something wrong with the paramater passing thing. The code is here:
from xmlrpclib import ServerProxy
import hashCheck, os
server = 'http://api.opensubtitles.org/xml-rpc'
class MainEngine(object):
def __init__(self, language="None"):
self.rpc = ServerProxy(server, allow_none=True)
user_agent = 'OSTestUserAgentTemp'
self.Start()
def getToken(self):
self.logindata = self.rpc.LogIn(None, None, "en", "OSTestUserAgentTemp")
self.Token = self.logindata["token"]
return self.Token
def subSearch(self, path):
self.hash = hashCheck.hash(self.path)
token = self.getToken()
self.param = [
token, # token
[
'eng', # sublanguageid
self.hash, #hash
os.path.getsize(path), # byte size
]
]
Obj = self.rpc.SearchSubtitles(token, self.param)
print Obj
def Start(self):
# print server
self.path = "E:\Movies\English\Captain Phillips\Captain Phillips.mp4"
self.subSearch(self.path)
def main():
MainEngine()
if __name__ == '__main__':
main()

Categories

Resources