Testing how long a user has been in a list - python

I'm using a bot for twitch and it tracks the time the user has spent in the channel. !time You have spent 10 seconds in the stream. However when multiple users use this command !time it doesn't have a seperate 'count' for each user. Ex:
Rustie: !time
Bot: Rustie, you have 20 seconds in the stream.
~1 minute later~
John: !time
Bot: John, you have 1 minute 20 seconds in the stream.
My current code:
usersForTime = []
if "time" in message:
if user in usersForTime:
endTime = time.time() # I already made startTime in the !start command (which starts the time tracker in the first place)
ellapsed = (endTime - startTime)
sendMessage(s, user + ", you have " + "%.2f" % round(ellapsed, 2) + " seconds in the stream.")
else:
sendMessage(s ,"You need to start tracking your time with the !start command.")

You'll want to store startTime associated with a specific user, something like
userStart = {}
if user in usersForTime:
...
ellapsed = (endTime - userStart[user])
which uses a dictionary to look up the individual's startTime.
To store it originally (in !start):
userStart[user] = time.time()

Related

How can I improve what I already have?

I have created a windows internet speed test, I'd like to improve it and make the code more presentable as well as better define my functions.
When the computer reaches initialise, due to the variable being in another function, it cannot call it. How can I rectify this as I have various variables being called in different functions.
Feel free to use this speedtester as well, I will be working on developing a useful phone app to run the code as well.
The code prints the current date and time, searches for the connected SSID, initialises the speedtest module, scans for servers, selects the best server, initiates ping test, then download speed test, then upload speed test, followed by printing the results on screen and writing it to a simple txt file for viewing later.
Each function shows its run time using the time module and lastly total execution time with date and time also.
It works perfectly without the functions, and on android without find_ssid(): but I keep running into the trouble of localised variables.
import speedtest
from datetime import datetime
import subprocess
import re
import time
def main():
def date():
dt_now = datetime.now()
dtn = dt_now.strftime("%a %d-%m-%Y, %H:%M:%S%p")
return dtn
print(date())
def find_ssid():
stt = time.time()
cdop = subprocess.run(["netsh", "WLAN", "show", "interfaces"], capture_output=True).stdout.decode()
ssid = (re.findall("SSID : (.*)\r", cdop))
for char in ssid:
ssid = f"Network Name: {char} \n"
sid = time.time() - stt
print(f'SSID found in: {sid:.2f}s')
print(ssid)
find_ssid()
def initialise():
print("Initialising network speed test... ")
st = speedtest.Speedtest()
print("Network speed test active.")
sta = time.time() - stt
print(f'Speed test activation time: {sta - sid:.2f}s')
def scan_servers():
print("Scanning for available servers...")
st.get_servers()
print("Found available servers.")
sft = time.time() - stt
print(f'Servers found in: {sft - sta:.2f}s')
def best_server():
print("Choosing best server...")
bserv = st.get_best_server()
print(f"Best server is: {bserv['sponsor']} - {bserv['host']} located in {bserv['name']}, {bserv['country']}")
bst = time.time() - stt
print(f'Best server found in: {bst - sft:.2f}s')
def ping_test():
print("Ping testing...")
p = st.results.ping
ph = f"Ping: {p:.2f}ms"
print("Ping test complete.")
ptt = time.time() - stt
print(f'Ping test completed in: {ptt - bst:.2f}s')
def download_speed_test():
print("Download speed testing...")
ds = st.download()
dsh = f"Download speed: {ds / 1024 / 1024:.2f}mb/s"
print("Download speed test complete.")
dst = time.time() - stt
print(f'Download speed test completed in: {dst - ptt:.2f}s')
def upload_speed_test():
print("Upload speed testing...")
us = st.upload()
ust = time.time() - stt
ush = f"Upload speed: {us / 1024 / 1024:.2f}mb/s \n"
print("Upload speed test complete. \n")
print(f'Upload speed test completed in: {ust - dst:.2f}s')
def result():
print("Speed test results are: \n")
print(ssid)
print(ph)
print(dsh)
print(ush)
ttn = datetime.now()
fdt = ttn.strftime("%a %d-%m-%Y, %H:%M:%S%p")
tt = time.time() - stt
print(f"Start Time: {dtn}")
print(f"Finish Time: {fdt}")
print(f'Total execution time: {tt:.2f}s')
results = [ssid, ph, dsh, ush, dtn]
txt = "Speedtest Results.txt"
with open(txt, 'a') as f:
f.write("\n")
f.write("\n".join(results))
f.write("\n")
f.close()
main()
You can run this on, one line i believe by
ssid = (re.findall("SSID : (.*)\r", cdop))
for char in ssid:
ssid = f"Network Name: {char} \n/
Which should make it quicker, have a look at list comprehension

discord.py Trying to store time in a db and check if 12 hours passed

I'm trying to check when 12 hours has passed since a user has voted and when I try to run the function through a while True loop, It doesn't run my bot.
def check_votes():
now = datetime.datetime.now()
voted_users = votedb.votes.find({"voted": "true"})
for user in voted_users:
vote_time = user.get("vote_time")
elapsed_time = now - vote_time
if elapsed_time > datetime.timedelta(hours=12):
votedb.votes.update_one({"user_id": user.get("user_id")}, {"$set": {"voted": "false"}})
while not client.is_closed():
while True:
check_votes()
time.sleep(3600)
This is making my bot not run and I'm trying to make it check when if it's been 12 hours since the vote_time which is set as "vote_time": datetime.datetime.now()

How do make an event activate on a specific Unix timestamp. in discord.py?

I am making a bot that has an announcement at a different time on each weekday. I want to go about the process of making this by having 5 discord task loops that send the announcement on their respective days. They will activate on their respective Unix timestamps and then will reactivate on the the timestamp is refreshed for the next week.
How do I make a an #client.event that activates on a Unix timestamp?
import discord
from discord.ext import commands, tasks
import random
import datetime
client = commands.Bot(command_prefix='.')
orig = datetime.datetime.fromtimestamp(1425917335)
new = orig + datetime.timedelta(days=90)
target_channel_id = 123456789
list_warning = ["T minus... 5 minutes... until detonation.", "Teacher is waiting. Get your ass back in 5 minutes.", "300 seconds unt-, 299 seconds unt-, 298 seconds unt-...",
"Chow down boys, lunch ends in 5 minutes.", "Looks like you've got some schoolin' to do."]
list_time = [1, 10]
#loops the 5 minute warning for lunch to end
#tasks.loop(seconds=)
async def called_once_a_day():
message_channel = client.get_channel(target_channel_id)
print(f"Got channel {message_channel}")
await message_channel.send(random.choice(list_warning))
org = orig + datetime.timedelta(days=7)
#called_once_a_day.before_loop
async def before():
await client.wait_until_ready()
print("Finished waiting")
called_once_a_day.start()
client.run("")
I would consider a more naive solution. Simply loop frequently and check if you at lunch time, if so send the lunch message. I tend to use arrow because I find it easy to use... you could implement with other libraries
tuesday_lunch_time = arrow.get("1230","HHmm")
#loop every minute so we are within a minute of lunch time.. you could change this to loop more often
#tasks.loop(minutes=1)
async def called_once_a_day():
now = arrow.now()
if now.weekday()== 1: #is today tuesday, don't ask me why tuesday is 1
if tuesday_lunch_time.shift(minutes=2).time() > now.time > tuesday_lunch_time.time(): ###this checks if you are within two minutes after lunch time, you could change this if you want to say have it be early, because of our loop it should be within a minute but I picked two minutes to be safe
message_channel = client.get_channel(target_channel_id)
print(f"Got channel {message_channel}")
await message_channel.send(random.choice(list_warning))
#to get out of the conditional above, so you don't send multiple times
await asyncio.sleep(720)

How to automate control of Wemo light switch based on iPhone GPS

I'm writing a program to toggle the lights at my house based on my iPhone's GPS coordinates. Below is what I have so far. However, I feel like there must be a better way to do this. Is there a way to get GPS data without pinging my phone every five minutes?
So far I've tried the following with no joy:
Using Shortcuts and Scriptable I tried to write some JavaScript that would trigger when I got close to home. However, I could not figure out how to use await require('wemo-client') using scriptablify. I kept getting an error, "ReferenceError: Can't find variable: require".
IFTTT does not have a variable timed trigger so the lights won't turn off after 15 minutes. Also, I plan on adding a motion sensor trigger that is unsupported.
Pythonista is $10. Yes, I am that cheap.
Apple HomeKit does not support the model I'm using, Wemo Smart Light Switch F7C030.
The code below works, but I hate that I have to ping my phone every five minutes. I'd rather save battery life by firing this code once or twice a day, as needed.
Any suggestions would be greatly appreciated.
Code:
import sys
import time
import datetime
import os
from pyicloud import PyiCloudService
import pywemo
APPLE_ID = os.getenv('APPLE_ID') # Apple ID username
APPLE_ID_PASSWORD = os.getenv('APPLE_ID_PASSWORD') # Apple ID password
API = PyiCloudService(APPLE_ID, APPLE_ID_PASSWORD)
IPHONE = API.devices[1]
LOCATION = IPHONE.location()
FIVE = 300 # 5 * 60 seconds
FIFTEEN = 900 # 15 * 60 seconds
ONEMILE = 0.01449275362318840579710144927536 # one mile is 1/69 degrees lat or long
HOMELAT = # my home's latitude
HOMELONG = # my home's longitude
WEMOS = pywemo.discover_devices()
LEN_WEMOS = range(len(WEMOS))
# Two factor authentication to retrieve iPhone data
if API.requires_2fa:
import click
print("Two-step authentication required. Your trusted devices are:")
DEVICES = API.devices
for i, device in enumerate(DEVICES):
print(" %s: %s" % (i, device.get('deviceName', "SMS to %s" % device.get('phoneNumber'))))
DEF_DEVICE = click.prompt('Which device would you like to use?', default=0)
DEVICE = DEVICES[DEF_DEVICE]
if not API.send_verification_code(DEVICE):
print("Failed to send verification code")
sys.exit(1)
CODE = click.prompt('Please enter validation code')
if not API.validate_verification_code(DEVICE, CODE):
print("Failed to verify verification code")
sys.exit(1)
# Turn off the lights when I leave
def leavehome():
timenow = datetime.datetime.now()
print("Left home on {}".format(timenow.strftime("%B %d, %Y at %H:%M:%S")))
for wemo in LEN_WEMOS:
WEMOS[wemo].off()
# Turn on the lights for 15 minutes when I get home
def arrivehome():
timenow = datetime.datetime.now()
print("Arrived home on {}".format(timenow.strftime("%B %d, %Y at %H:%M:%S")))
# Loop through all Wemo devices
for wemo in LEN_WEMOS:
WEMOS[wemo].on()
time.sleep(FIFTEEN)
for wemo in LEN_WEMOS:
WEMOS[wemo].off()
# Automatically turn off the lights after 15 minutes - save electricity
def timeoff():
time.sleep(FIFTEEN)
for wemo in LEN_WEMOS:
WEMOS[wemo].off()
# Ping my phone for GPS data
def pingphone(prev):
mylat = LOCATION["latitude"]
mylong = LOCATION["longitude"]
logic(prev, mylat, mylong)
time.sleep(FIVE)
# Perform logic to determine if I'm home, out, arriving, or leaving
def logic(prev, lat, long):
inrange = (HOMELAT+ONEMILE >= lat >= HOMELAT-ONEMILE and HOMELONG+ONEMILE >= long >= HOMELONG-ONEMILE)
current = bool(inrange)
previous = prev
if current and not previous:
arrivehome()
elif previous and not current:
leavehome()
else:
timeoff()
pingphone(current)
# Run the script
pingphone(False)

GPIOZERO Measure time of inactive/active state of digital input

I have a dust sensor, and I have to measure a sum of inactive time in 30 seconds cycles.
For DigitalInputDevice gpiozero provides cool functionality, I mean two properties, and two callbacks:
properties - active_time (return float if pin is active or None) and inactive_time
(return float if pin is inactive or None),
callbacks - when_activated and when_deactivated
I thought that inside those callbacks I would have access to the digit input in the previous state, which would allow me to grab active time when pin change state to inactive, and inactive time when pin change state to active, but I was wrong.
So my question is: There is any possibility in this library to grab a whole active time when pin turns to inactive and vice versa?
Thank you!
Clarification: what I want is described in the image below
image of chart my sensor docs: https://botland.com.pl/index.php?controller=attachment&id_attachment=1565
I do it now in this way:
from gpiozero import DigitalInputDevice
from datetime import timedelta
import time
sensor_one_micrometer = DigitalInputDevice(20)
while True:
active_time = 0
inactive_time = 0
sensor_one_micrometer.wait_for_active()
while active_time + inactive_time < 30:
watch_start = time.time()
sensor_one_micrometer.wait_for_inactive()
active_time += time.time() - watch_start
watch_start = time.time()
sensor_one_micrometer.wait_for_active()
inactive_time += time.time() - watch_start
percent = inactive_time/(active_time+inactive_time)
print("Active Time: ", active_time)
print("Inactive Time: ", inactive_time)
print(
inactive_time/(active_time+inactive_time)
)

Categories