Telegram-bot replies to messages from specific user in group chat (aiogram) - telegram-bot

I want my bot to reply to a certain person in chat every time he writes (in fact every 2 hrs, like regular cuddling)
e.g.
User1: Good morning everyone
User2: Good morning
Bot: (reply to User2): Have a nice day!
Now i can send messages to group from bot
#dp.message_handler(commands="HAD")
async def cmd_dice(message: types.Message):
await message.bot.send_message($here chat_id$, text="Have a nice day!")
I don't understand how I can reply to user messages if he doesn't address the bot. Is this possible?
Thanks in advance for your help!

To get all the messages in the bot group, you need to turn off Privacy mode. Open the #botfather. Send the /mybots command. Select the bot.
bot_settings --> allow_groups --> turn_groups_of
Use the magic_filter
...
from magic_filter import F
...
...
#dp.message_handler(F.from_user.id.in_({42, 1000, 123123})) # 42, 1000, 123123 users id
async def message_sender(message: types.Message):
await message.answer(text="Have a nice day!")
...

Related

How can I send report on stop locust (as lib mode)

I want to send out report: example how many percent failures to group telegram on stop locust
It is for total request, it is not in method on_stop for each user instance
Thanks,
Use the test_stop event as documented here: https://docs.locust.io/en/stable/extending-locust.html
Specifically, if you wanted to print your fail ratio you would do:
#events.test_stop.add_listener
def on_test_stop(environment, **kwargs):
print(environment.runner.stats.total.fail_ratio)
Another example is here: https://github.com/locustio/locust/blob/master/examples/test_data_management.py

how to send random local notification message in react-native?

I have an app that needs to send out notification/s everyday with random messages to user depending on how many notification they want (up to 5 notifs per day) and between what time they want (for example notifications will fire only between 6:00am - 9:00am everyday).
To elaborate I'm building a functionality with an idea to send out random inspirational messages that I'm pulling from a hardcoded array variable or json file.
Currently I'm using this package: https://github.com/zo0r/react-native-push-notification to create local notification.
I tried the idea of setting a function that returns a string for the message parameter of localNotificationSchedule, but when I do this, instead of using a regular string, it's not showing the notification.
PushNotification.localNotificationSchedule({
id : '1',
userInfo : { id: userId },
message : () => {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5); //trying to return random string every time notification fires.
},
date : moment(Date.now()).add(2, 'seconds').toDate(),
repeatType : 'day',
});
I considered using other approach such as react-native headless JS but it's for android only.
Also considered using https://www.npmjs.com/package/react-native-background-fetch. But I have a complex interval for notifications. For example, the user might set the notification to run from 6:00am - 6:30am everyday and set to fire 5 notifications. In this interval, notifications will run every 6 mins.
But react-native-background-fetch' minimal interval is only 15 minutes.
I know that this can be done by using a push notification instead, but with that, user will need a connection in order for them to receive a notification, which is not ideal for this case.
Iv'e seen this from an Ios app so I know this is possible to achieve.
As per the dev, you can try calling PushNotification.localNotificationSchedule multiple times.
What I've done is this:
const messages = [{text:'',time:0}...];
messages.map(message=>{
PushNotification.localNotificationSchedule({
//... You can use all the options from localNotifications
channelId: "my-channel",
message: message.text, // (required)
date: new Date(Date.now() + (60 + message.time) * 1000), // in 60 secs
});
})
to show a message from the messages array separated by 5 seconds.

Can a telegram bot block a specific user?

I have a telegram bot that for any received message runs a program in the server and sends its result back. But there is a problem! If a user sends too many messages to my bot(spamming), it will make server so busy!
Is there any way to block the people whom send more than 5 messages in a second and don't receive their messages anymore? (using telegram api!!)
Firstly I have to say that Telegram Bot API does not have such a capability itself, Therefore you will need to implement it on your own and all you need to do is:
Count the number of the messages that a user sends within a second which won't be so easy without having a database. But if you have a database with a table called Black_List and save all the messages with their sent-time in another table, you'll be able to count the number of messages sent via one specific ChatID in a pre-defined time period(In your case; 1 second) and check if the count is bigger than 5 or not, if the answer was YES you can insert that ChatID to the Black_List table.
Every time the bot receives a message it must run a database query to see that the sender's chatID exists in the Black_List table or not. If it exists it should continue its own job and ignore the message(Or even it can send an alert to the user saying: "You're blocked." which I think can be time consuming).
Note that as I know the current telegram bot API doesn't have the feature to stop receiving messages but as I mentioned above you can ignore the messages from spammers.
In order to save time, You should avoid making a database connection
every time the bot receives an update(message), instead you can load
the ChatIDs that exist in the Black_List to a DataSet and update the
DataSet right after the insertion of a new spammer ChatID to the
Black_List table. This way the number of the queries will reduce
noticeably.
I have achieved it by this mean:
# Using the ttlcache to set a time-limited dict. you can adjust the ttl.
ttl_cache = cachetools.TTLCache(maxsize=128, ttl=60)
def check_user_msg_frequency(message):
print(ttl_cache)
msg_cnt = ttl_cache[message.from_user.id]
if msg_cnt > 3:
now = datetime.now()
until = now + timedelta(seconds=60*10)
bot.restrict_chat_member(message.chat.id, message.from_user.id, until_date=until)
def set_user_msg_frequency(message):
if not ttl_cache.get(message.from_user.id):
ttl_cache[message.from_user.id] = 1
else:
ttl_cache[message.from_user.id] += 1
With these to functions above, you can record how many messages sent by any user in the period. If a user's messages sent more than expected, he would be restricted.
Then, every handler you called should call these two functions:
#bot.message_handler(commands=['start', 'help'])
def handle_start_help(message):
set_user_msg_frequency(message)
check_user_msg_frequency(message)
I'm using pyTelegramBotAPI this module to handle.
I know I'm late to the party, but here is another simple solution that doesn't use a Db:
Create a ConversationState class to attach to each telegram Id when they start to chat with the bot
Then add a LastMessage DateTime variable to the ConversationState class
Now every time you receive a message check if enought time has passed from the LasteMessage DateTime, if not enought time has passed answer with a warning message.
You can also implement a timer that deletes the conversation state class if you are worried about performance.

How to sync for the emails which are received after a particular email.

I am working on an application which download Yahoo account emails in the order of down to top using Yahoo Mail API's.
Application sync logic works like below
Lets say Inbox consists of 1000 emails.
1) Initially fetching 100 emails message ID's by using "ListMessages" with parameters startMid = 0 and numMid=100.
2) Processing chunk emails .
3) Now requesting for the next chunk emails by giving the startMid = 100 and numMid=100.
The above logic works fine if user is not deleting any emails during syncing.
Is there any way to retrieve next chunk emails based on the message ID (string unique value) rather than message number.
What is the logic for syncing the emails from the last processed message?
PS:I can not rely on message number (since message number is not meant for unique identifier of a message).
I was looking for the same thing and found "How to get only emails which are arrived from the Client last sync." (http://developer.yahoo.com/forum/Yahoo-Mail-Web-Services-API/How-to-get-only-emails-which/1320329478746-16f18e6a-aadd-40c3-b259-e095ce80a1e6) where some guy reply "This feature is not available right now but we do plan to support this in future." date: 3 Nov 2011 11:24 AM
I think you can query mailTables (with YQL) or ListMessage (Api) and get the complete list of messages id (without any info) eg: SELECT * FROM ymail.messages WHERE numInfo="0"
And then "count" the position of the last message you got and then, get mail from that number. Eg: SELECT * FROM ymail.messages WHERE startMid="3" and numMid="100"
What do you think?
Greetings from Argentina
PS: sorry about my horrible english

Twitter stream api with agents in F#

From Don Syme blog (http://blogs.msdn.com/b/dsyme/archive/2010/01/10/async-and-parallel-design-patterns-in-f-reporting-progress-with-events-plus-twitter-sample.aspx) I tried to implement a twitter stream listener. My goal is to follow the guidance of the twitter api documentation which says "that tweets should often be saved or queued before processing when building a high-reliability system".
So my code needs to have two components:
A queue that piles up and processes each status/tweet json
Something to read the twitter stream that dumps to the queue the tweet in json strings
I choose the following:
An agent to which I post each tweet, that decodes the json, and dumps it to database
A simple http webrequest
I also would like to dump into a text file any error from inserting in the database. ( I will probably switch to a supervisor agent for all the errors).
Two problems:
is my strategy here any good ? If I understand correctly, the agent behaves like a smart queue and processes its messages asynchronously ( if it has 10 guys on its queue it will process a bunch of them at time, instead of waiting for the 1 st one to finish then the 2nd etc...), correct ?
According to Don Syme's post everything before the while is Isolated so the StreamWriter and the database dump are Isolated. But because I need this, I never close my database connection... ?
The code looks something like:
let dumpToDatabase databaseName =
//opens databse connection
fun tweet -> inserts tweet in database
type Agent<'T> = MailboxProcessor<'T>
let agentDump =
Agent.Start(fun (inbox: MailboxProcessor<string>) ->
async{
use w2 = new StreamWriter(#"\Errors.txt")
let dumpError =fun (error:string) -> w2.WriteLine( error )
let dumpTweet = dumpToDatabase "stream"
while true do
let! msg = inbox.Receive()
try
let tw = decode msg
dumpTweet tw
with
| :? MySql.Data.MySqlClient.MySqlException as ex ->
dumpError (msg+ex.ToString() )
| _ as ex -> ()
}
)
let filter_url = "http://stream.twitter.com/1/statuses/filter.json"
let parameters = "track=RT&"
let stream_url = filter_url
let stream = twitterStream MyCredentials stream_url parameters
while true do
agentDump.Post(stream.ReadLine())
Thanks a lot !
Edit of code with processor agent:
let dumpToDatabase (tweets:tweet list)=
bulk insert of tweets in database
let agentProcessor =
Agent.Start(fun (inbox: MailboxProcessor<string list>) ->
async{
while true do
let! msg = inbox.Receive()
try
msg
|> List.map(decode)
|> dumpToDatabase
with
| _ as ex -> Console.WriteLine("Processor "+ex.ToString()))
}
)
let agentDump =
Agent.Start(fun (inbox: MailboxProcessor<string>) ->
let rec loop messageList count = async{
try
let! newMsg = inbox.Receive()
let newMsgList = newMsg::messageList
if count = 10 then
agentProcessor.Post( newMsgList )
return! loop [] 0
else
return! loop newMsgList (count+1)
with
| _ as ex -> Console.WriteLine("Dump "+ex.ToString())
}
loop [] 0)
let filter_url = "http://stream.twitter.com/1/statuses/filter.json"
let parameters = "track=RT&"
let stream_url = filter_url
let stream = twitterStream MyCredentials stream_url parameters
while true do
agentDump.Post(stream.ReadLine())
I think that the best way to describe agent is that it is is a running process that keeps some state and can communicate with other agents (or web pages or database). When writing agent-based application, you can often use multiple agents that send messages to each other.
I think that the idea to create an agent that reads tweets from the web and stores them in a database is a good choice (though you could also keep the tweets in memory as the state of the agent).
I wouldn't keep the database connection open all the time - MSSQL (and MySQL likely too) implements connection pooling, so it will not close the connection automatically when you release it. This means that it is safer and similarly efficient to reopen the connection each time you need to write data to the database.
Unless you expect to receive a large number of error messages, I would probably do the same for file stream as well (when writing, you can open it, so that new content is added to the end).
The way queue of F# agents work is that it processes messages one by one (in your example, you're waiting for a message using inbox.Receive(). When the queue contains multiple messages, you'll get them one by one (in a loop).
If you wanted to process multiple messages at once, you could write an agent that waits for, say, 10 messages and then sends them as a list to another agent (which would then perform bulk-processing).
You can also specify timeout parameter to the Receive method, so you could wait for at most 10 messages as long as they all arrive within one second - this way, you can quite elegantly implement bulk processing that doesn't hold messages for a long time.