Discord Pypresence crashing custom application after pressing connect button - python

This is how the application looks like: [1]: https://i.stack.imgur.com/HUaix.png
[2]: https://i.stack.imgur.com/CYWdS.png
The second [2] image shows how the application should look after pressing the "Connect" button. However, after pressing the button it looks the same (image [1]), although the Discord rich presence starts running.
def rpcstart():
os.system('start-rpc-script.py')
global rpc_on
if rpc_on:
connectbutton.config(image=rpcconnectedimage, state='disabled')
disconnectbutton.config(image=rpcdisconnectimage, state='normal')
else:
connectbutton.config(image=rpcconnectimage)
menubar.entryconfig(1,label="Status: Connected")
This is the part of my script that starts the Discord rich presence. There are no errors or anything similar. It just makes the application unresponsive. Is there any fix for that? Here's the pypresence script that I use:
from pypresence import Presence
import time
start = int(time.time())
client_id = "XXXXXX"
RPC = Presence(client_id)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "DEMO.",
large_image = "logo_rpc_v2",
large_text = "demo.exe is running!",
small_image = "green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [{"label": "example.net ", "url": "https://example.net/"},
{"label": "example.net", "url": "https://example.net"}]
)
time.sleep(60)

Try running your RPC code in a separate thread
from threading import Thread
def _rpc_connect(client_id): # this will be your 'target' function, run in its own thread
start = int(time.time())
RPC = Presence(client_id)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "DEMO.",
large_image = "logo_rpc_v2",
large_text = "demo.exe is running!",
small_image = "green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [
{"label": "example.net ", "url": "https://example.net/"},
{"label": "example.net", "url": "https://example.net"}
],
)
time.sleep(60)
def run_rpc(client_id)
t_rpc = Threading(
target=_rpc_connect,
args=(client_id,),
daemon=True,
)
t_rpc.start() # start the thread
To run the RPC thread, call the run_rpc function as usual
run_rpc(client_id='XXXXXX')

Related

Pypresence not closing connection

This is the code I'm using to turn the pypresence on:
from pypresence import Presence
import time
start = int(time.time())
client_id = "XXXXXXXXXXXXXXXX"
RPC = Presence(client_id, pipe=0, loop=None, handler=None)
RPC.connect()
while True:
RPC.update(
details = "▬▬▬▬▬▬▬▬▬▬",
state = "All Systems Operational.",
large_image = "xxx_logo_rpc_v2",
large_text = "exe is running!",
small_image = "xx_green_circle_rpc_v2",
small_text = "Online",
start = start,
buttons = [{"label": "🌐XX 🌐", "url": "https://xx/"}, {"label": "xxxx", "url": "https://xxxx8"}]
)
time.sleep(60)
This is the code I'm trying to use to turn it off:
from pypresence import Presence
import os
client_id = "XXXXXXXXXXXXXX"
RPC = Presence(client_id, pipe=0, loop=None, handler=None)
RPC.clear(pid=os.getpid())
RPC.close()
The problem is that it shows me this error:
File "C:\Users\Foxii\AppData\Local\Programs\Python\Python310\lib\site- packages\pypresence\baseclient.py",
line 96, in send_data assert self.sock_writer is not None, "You must connect your client before sending events!" AssertionError: You must connect your client before sending events!
Well, the client seems to be connected when I run it with my custom Tkinter GUI but when I try to run the code to close it, it shows me that error.

Is there a way to get "text" or "fg_color" value from custom Tkinter button widget?

I have a customtkinter (CTk) button widget that, when pressed, sends an encoded message to a client depending on the button's "text" value; in this case, if the button's text is "Off", it sends the message "On" and vice versa to the client.
import tkinter as tk
import traceback
import customtkinter as cust
import socket
from threading import Thread
from tkinter import messagebox
class GUI2(cust.CTk): #second window; not the root
def __init__(self):
super().__init__()
self.PORT = 5000
self.SERVER = socket.gethostbyname(socket.gethostname())
self.ADDRESS = (self.SERVER, self.PORT)
self.FORMAT = "utf-8"
self.clients = [] #list to store all client connections
self.server = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
self.server.bind(self.ADDRESS)
self.master2 = cust.CTkToplevel()
self.ecdpower = cust.CTkButton(self.master2, text = "Off", fg_color = "Black", text_color = "White", hover_color = "Silver", command = lambda: Thread(target = self.startstream).start())
self.ecdpower.grid(row = 0, column = 0) #button to send message to client connections
self.thread = Thread(target = self.startChat)
self.thread.start() #starts function to accept client connections
def startChat(self): #function to accept client connections
self.server.listen(30)
try:
while True:
self.conn, self.addr = self.server.accept()
self.clients.append(self.conn) #stores all client connections
except:
pass
def startstream(self):
try:
if not self.clients: #checks if list is empty
messagebox.showerror("No Connections!", "No clients connected to host!")
else:
for x in self.clients:
if self.ecdpower["text"] == "Off": #ecdpower button widget acts like a "power button"
self.ecdpower.configure(text = "On", fg_color = "Green")
x.send(("On").encode(self.FORMAT))
else:
self.ecdpower.configure(text = "Off", fg_color = "Red")
x.send(("Off").encode(self.FORMAT))
except:
print (traceback.format_exc())
Error is as follows:
Traceback (most recent call last):
File "f:\project\mainmenu.py", line 390, in startstream
File "F:\Program Files (x86)\Python\lib\tkinter\__init__.py", line 1681, in cget
return self.tk.call(self._w, 'cget', '-' + key)
_tkinter.TclError: unknown option "-text"
I have also tried if self.ecdpower.cget("text") == "Off: and tried other values like fg_color; both result in the same error. When I removed the if condition, the message sending works correctly so the only problem is how to verify the button "text" value.
Any help to fix this or possible other alternatives is greatly appreciated.
Per #jasonharper's comment above, CTkButton is
not actually a Tkinter Button at all (it's made from a Frame containing a Canvas and a Label), so the normal Tkinter attribute-getting functions don't apply.
Instead of using self.ecdpower["text"] or self.ecdpower.cget("text"): I should use
self.ecdpower.text
to get the CTKbutton's text value.
The same can be applied with fg_color; use self.ecdpower.fg_color to get the value.

Netmiko / Python Threading for multiple send_command on the same devices ( network device )

Goal is to send multiple ping via a Cisco device ( L2 ) to populate the arp table.
Script is done and working but ultra slow since I need to ping 254 address and more depending if /24 or /23 etc...
Where I am confuse, I have test some threading with some basic scripts to understand how it works and everything works by using a function and call it and so far so good.
My Problem is that I don't want to create 200+ ssh connections if I use a function for the whole code.
I would like to use the threading only on the send_command part from netmiko.
My Code :
from netmiko import ConnectHandler
from pprint import pprint
from time import perf_counter
from threading import Thread
mng_ip = input("please enter the subnet to be scan: ")
cisco_Router = {
"device_type": "cisco_ios",
"host": mng_ip,
"username": "XXXX",
"password": "XXXX",
"fast_cli": False,
"secret": "XXXX"}
print(mng_ip)
subnet1 = mng_ip.split(".")[0]
subnet2 = mng_ip.split(".")[1]
subnet3 = mng_ip.split(".")[2]
#subnet4 = mng_ip.split(".")[3]
active_list = []
start_time = perf_counter()
for x in range(1,254):
ip = (subnet1+"."+subnet2+"."+subnet3+"."+str(x))
print ("Pinging:",ip)
with ConnectHandler(**cisco_Router) as net_connect:
net_connect.enable()
result = net_connect.send_command(f"ping {ip} ",delay_factor=2) # <----- this is the part i would like to perform the threading
print(result)
if "0/5" in result:
print("FAILED")
else:
print("ACTIVE")
active_list.append(ip)
net_connect.disconnect()
print("Done")
pprint(active_list)
end_time = perf_counter()
print(f'It took {end_time- start_time: 0.2f} second(s) to complete.')
not sure if it is possible and how it could be done,
Thank you in advance,

How to show images in window in PySimpleGUI?

I'm working on PySimpleGUI and I want to show images in the Window of PySimpleGUi. Basically, first I'm converting my sentence into characters and now I want to simply show an image of that character in the window and speak which is the character.
Below is my code:
from tkinter.constants import TRUE
import PySimpleGUI as sg
from PySimpleGUI.PySimpleGUI import Window
import pyttsx3
import time
import _thread
first_coloumn = [
[sg.LBox([], size=(20,10), key='-FILESLB-')],
[sg.Input(visible=False, enable_events=True, key='-IN-'), sg.FilesBrowse()],
[sg.Text('Enter what you wanna teach : ')],
[sg.Input(key='-inp-')],
[sg.Button('Reads'),sg.Button('Pause'),sg.Button('Slow'),sg.Button('Fast'),sg.Button('Stop'),sg.Button('Repeat'),sg.Button('Exit')]
]
image_viewer_coloumn = [
[sg.Text("Image Viewer")],
[sg.Image(key='-IMAGE-')],
]
layout = [
[
sg.Column(first_coloumn),
sg.VSeparator(),
sg.Column(image_viewer_coloumn),
]
]
window = sg.Window("Narrator",layout)
engine = pyttsx3.init()
words = []
chars = []
a = 0.5
stop = False
def splits(sentence):
return list(sentence)
def speak(a):
global stop
for i in range (len(chars)):
if stop:
break
elif chars[i]=='A' or chars[i]=='a':
filepath = "D:\Office-Work\Chars\A.png"
window['-IMAGE-'].update(filepath=filepath)
engine.say(chars[i])
time.sleep(a)
engine.runAndWait()
while TRUE:
event,values = window.read()
if event == 'Reads':
out = values['-inp-']
if out:
chars = splits(out)
stop = False
_thread.start_new_thread(speak, (a,))
and I'm getting the following error:
update() got an unexpected keyword argument 'filepath'
File "C:\Users\Kashi\OneDrive\Desktop\PySimpleGUI\a.py", line 45, in speak
window['-IMAGE-'].update(filepath=filepath)
sg.Image defined as
def __init__(self, source=None, filename=None, data=None, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, key=None, k=None, tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, enable_events=False, metadata=None):
You can find there's no option for filepath, another issue is not to update GUI when not in main thread.
...
elif chars[i]=='A' or chars[i]=='a':
filepath = "D:\Office-Work\Chars\A.png"
"""
window['-IMAGE-'].update(filepath=filepath) # unexpected keyword argument 'filepath'
window['-IMAGE-'].update(filename=filepath) # correct keyword, but not update GUI here
"""
window.write_event_value("Update Image", filepath) # Generate an event when not in main thread.
...
while TRUE:
event,values = window.read()
...
if event == "Update Image":
window['-IMAGE-'].update(filename=filepath)
...
Should not update GUI in other thread function speak.

How to add dividers to rumps menu

I have made a python script which creates a MacOS Status bar item which displays youtube statistics.
I want to add dividers to the drop down menu when you click the text but I am unable to do this. (Image of what I mean under the text). I have found many examples but all of them only work with an __init__ function in the class. If I try adding an __init__ function to the class I get an error saying AttributeError: 'Sub_Counter' object has no attribute '_menu'. Why is this happening and how can it be fixed?
Code I added to the __init_ function
self.menu = [
"About",
"No Icon",
None,
"Detailed Statistics:",
None,
"Quit",
]
Normal Code without the __init__ function
import rumps
import time
import sys
import os
from sty import fg
from googleapiclient.discovery import build
key = open(os.path.join(sys.path[0], './key.txt')).read().strip()
service = build('youtube', 'v3', developerKey=key)
subs = service.channels().list(
part='statistics',
id='UCERizKQbgpBXOck0R6t_--Q'
).execute()['items'][0]['statistics']['subscriberCount']
timers = ["1 secs","5 secs","10 secs","15 secs","20 secs","25 secs","30 secs","35 secs","45 secs","50 secs","1 Min"]
EXEC_TIMER = 60
class Sub_Counter(rumps.App):
#rumps.timer(EXEC_TIMER)
def pull_data(self, _):
self.sub_menu = timers
subs = service.channels().list(
part='statistics',
id='UCERizKQbgpBXOck0R6t_--Q'
).execute()['items'][0]['statistics']['subscriberCount']
a = (str(subs))
self.icon = "logo.png"
self.title = "Subscribers: " + str(a)
self.notification = str(a) + " Subscribers"
#rumps.clicked("About")
def about(self, _=):
rumps.notification("Youtube Subscriber Count", "Made by Roxiun using Python & rumps", "Shows Youtube Subscriber counts")
#rumps.clicked("No Icon")
def noicon(self, sender):
sender.state = not sender.state
self.icon = None
#rumps.clicked("Detailed Statistics")
def Detailed_Statistics(self, _):
rumps.notification("You have:", self.notification , "Veiws Comming Soon")
if __name__ == "__main__":
Sub_Counter("Loading...").run() #debug=True
Image of what I want to do [circled in red - (Yes it is the line)]
Thanks in advance!
Fixed by doing
app = Sub_Counter("Loading...")
app.menu[
"About",
"No Icon",
None,
"Detailed Statistics:",
None,
"Quit",
]
app.run()
You can add a separator by doing:
self.menu.add(rumps.separator)
Link to source code.

Categories