decently working!
This commit is contained in:
parent
383cad8808
commit
3c6876420f
114
addtoDB-backup.py
Normal file
114
addtoDB-backup.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding:utf-8 -*-
|
||||||
|
|
||||||
|
#this script takes a file as an option and adds that file scuttlebutt
|
||||||
|
# originally from ebb, modified for custodisco
|
||||||
|
|
||||||
|
import optparse
|
||||||
|
import traceback
|
||||||
|
import os, sys
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
#get options and arguments
|
||||||
|
p = optparse.OptionParser()
|
||||||
|
p.add_option('--file', '-f', action='store', dest='file', help='this needs to be a file path')
|
||||||
|
|
||||||
|
options, arguments = p.parse_args()
|
||||||
|
|
||||||
|
if options.file:
|
||||||
|
pathToImage=options.file
|
||||||
|
else:
|
||||||
|
print("you need to provide a file path")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def addToSSB(pathToImage,description,mintOrGive):
|
||||||
|
|
||||||
|
# mint
|
||||||
|
if mintOrGive == 1:
|
||||||
|
try:
|
||||||
|
result = subprocess.Popen('./ssb-post.sh mint "' + description + '" ' + pathToImage, shell=True, stdout=subprocess.PIPE, )
|
||||||
|
except:
|
||||||
|
print('traceback.format_exc():\n%s' % traceback.format_exc())
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# else give
|
||||||
|
elif mintOrGive == 2:
|
||||||
|
try:
|
||||||
|
result = subprocess.Popen('./ssb-post.sh give "' + pathToImage + '" ' + description, shell=True, stdout=subprocess.PIPE, )
|
||||||
|
except:
|
||||||
|
print('traceback.format_exc():\n%s' % traceback.format_exc())
|
||||||
|
exit()
|
||||||
|
|
||||||
|
# get the ssb json from the bash command we just ran
|
||||||
|
newssb = result.stdout.read().decode() # decode bytes to string
|
||||||
|
print(newssb)
|
||||||
|
|
||||||
|
# CHECK that newssb is _anything_ if ssb-server isn't running that may show as garbage that will crash the program
|
||||||
|
if len(newssb) == 0:
|
||||||
|
print("String is empty")
|
||||||
|
|
||||||
|
#convert string to object
|
||||||
|
# Make sure it's valid JSON before loading
|
||||||
|
try:
|
||||||
|
json_object = json.loads(newssb)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print("Invalid JSON")
|
||||||
|
return "offline" # Return the blouch
|
||||||
|
|
||||||
|
# get the key for the post we just made
|
||||||
|
key = json_object["key"]
|
||||||
|
print (key)
|
||||||
|
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def get_message_content(message_id):
|
||||||
|
try:
|
||||||
|
print(f"Executing command: ./ssb-post.sh get_message_content {message_id}")
|
||||||
|
result = subprocess.run(['./ssb-post.sh', 'get_message_content', message_id],
|
||||||
|
capture_output=True, text=True, check=True)
|
||||||
|
|
||||||
|
print(f"Command output:\n{result.stdout}")
|
||||||
|
|
||||||
|
# Split the output into lines
|
||||||
|
lines = result.stdout.split('\n')
|
||||||
|
|
||||||
|
# Extract the image path
|
||||||
|
image_path = None
|
||||||
|
for line in lines:
|
||||||
|
if line.startswith("IMAGE_PATH:"):
|
||||||
|
image_path = line.split(":", 1)[1].strip()
|
||||||
|
break
|
||||||
|
|
||||||
|
# Find the start of the JSON content
|
||||||
|
json_start = next(i for i, line in enumerate(lines) if line.strip().startswith("{"))
|
||||||
|
|
||||||
|
# Join the JSON lines and parse
|
||||||
|
json_content = "\n".join(lines[json_start:])
|
||||||
|
message_content = json.loads(json_content)
|
||||||
|
|
||||||
|
print(f"Parsed message content: {message_content}")
|
||||||
|
print(f"Image path: {image_path}")
|
||||||
|
|
||||||
|
return message_content, image_path
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error: subprocess.CalledProcessError - {e}")
|
||||||
|
print(f"Debug: stdout = {e.stdout}")
|
||||||
|
print(f"Debug: stderr = {e.stderr}")
|
||||||
|
return None, None
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
print(f"Error: json.JSONDecodeError - {e}")
|
||||||
|
print(f"Debug: stdout = {result.stdout}")
|
||||||
|
return None, None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error: Unexpected exception - {e}")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
31
addtoDB.py
31
addtoDB.py
@ -85,29 +85,46 @@ def get_message_content(message_id):
|
|||||||
image_path = line.split(":", 1)[1].strip()
|
image_path = line.split(":", 1)[1].strip()
|
||||||
break
|
break
|
||||||
|
|
||||||
# Find the start of the JSON content
|
# Find the start and end of the main message content
|
||||||
json_start = next(i for i, line in enumerate(lines) if line.strip().startswith("{"))
|
json_start = next(i for i, line in enumerate(lines) if line.strip().startswith("{"))
|
||||||
|
replies_start = next(i for i, line in enumerate(lines) if line.strip() == "REPLIES_START")
|
||||||
|
|
||||||
# Join the JSON lines and parse
|
# Join the JSON lines for the main message and parse
|
||||||
json_content = "\n".join(lines[json_start:])
|
json_content = "\n".join(lines[json_start:replies_start])
|
||||||
message_content = json.loads(json_content)
|
message_content = json.loads(json_content)
|
||||||
|
|
||||||
|
# Parse replies
|
||||||
|
replies = []
|
||||||
|
reply_json = ""
|
||||||
|
for line in lines[replies_start+1:]:
|
||||||
|
if line.strip() == "REPLIES_END":
|
||||||
|
break
|
||||||
|
if line.strip() == "{":
|
||||||
|
reply_json = "{"
|
||||||
|
elif line.strip() == "}":
|
||||||
|
reply_json += "}"
|
||||||
|
replies.append(json.loads(reply_json))
|
||||||
|
reply_json = ""
|
||||||
|
else:
|
||||||
|
reply_json += line
|
||||||
|
|
||||||
print(f"Parsed message content: {message_content}")
|
print(f"Parsed message content: {message_content}")
|
||||||
print(f"Image path: {image_path}")
|
print(f"Image path: {image_path}")
|
||||||
|
print(f"Number of replies: {len(replies)}")
|
||||||
|
|
||||||
return message_content, image_path
|
return message_content, image_path, replies
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print(f"Error: subprocess.CalledProcessError - {e}")
|
print(f"Error: subprocess.CalledProcessError - {e}")
|
||||||
print(f"Debug: stdout = {e.stdout}")
|
print(f"Debug: stdout = {e.stdout}")
|
||||||
print(f"Debug: stderr = {e.stderr}")
|
print(f"Debug: stderr = {e.stderr}")
|
||||||
return None, None
|
return None, None, None
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
print(f"Error: json.JSONDecodeError - {e}")
|
print(f"Error: json.JSONDecodeError - {e}")
|
||||||
print(f"Debug: stdout = {result.stdout}")
|
print(f"Debug: stdout = {result.stdout}")
|
||||||
return None, None
|
return None, None, None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error: Unexpected exception - {e}")
|
print(f"Error: Unexpected exception - {e}")
|
||||||
return None, None
|
return None, None, None
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
341
kiosk.py
341
kiosk.py
@ -152,30 +152,71 @@ class Screen1(tk.Frame):
|
|||||||
label.pack(pady=90)
|
label.pack(pady=90)
|
||||||
|
|
||||||
tk.Button(self, text="Yes, and I already have an account", command=lambda: master.switch_frame(Screen2), height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
tk.Button(self, text="Yes, and I already have an account", command=lambda: master.switch_frame(Screen2), height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
||||||
tk.Button(self, text="Yes, but I need to create an account now", command=lambda: master.switch_frame(Screen7), height=3, width=50, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
# tk.Button(self, text="Yes, but I need to create an account now", command=lambda: master.switch_frame(Screen7), height=3, width=50, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
||||||
tk.Button(self, text="No thanks", command=lambda: master.switch_frame(Screen3), height=3, width=50, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
tk.Button(self, text="No thanks", command=lambda: master.switch_frame(Screen3), height=3, width=50, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualScrolledFrame(ttk.Frame):
|
||||||
|
def __init__(self, parent, *args, **kw):
|
||||||
|
ttk.Frame.__init__(self, parent, *args, **kw)
|
||||||
|
|
||||||
|
# Create a canvas object and a vertical scrollbar for scrolling it
|
||||||
|
self.vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL)
|
||||||
|
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, bg='#bcfef9')
|
||||||
|
self.vscrollbar.config(command=self.canvas.yview)
|
||||||
|
|
||||||
|
# Reset the view
|
||||||
|
self.canvas.xview_moveto(0)
|
||||||
|
self.canvas.yview_moveto(0)
|
||||||
|
|
||||||
|
# Create a frame inside the canvas which will be scrolled with it
|
||||||
|
self.interior = tk.Frame(self.canvas, bg='#bcfef9')
|
||||||
|
self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=tk.NW)
|
||||||
|
|
||||||
|
# Pack the widgets
|
||||||
|
self.vscrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||||
|
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
# Bind events to the Canvas
|
||||||
|
self.canvas.bind('<Configure>', self._configure_canvas)
|
||||||
|
self.interior.bind('<Configure>', self._configure_interior)
|
||||||
|
|
||||||
|
def _configure_interior(self, event):
|
||||||
|
# Update the scrollbars to match the size of the inner frame
|
||||||
|
size = (self.interior.winfo_reqwidth(), self.interior.winfo_reqheight())
|
||||||
|
self.canvas.config(scrollregion="0 0 %s %s" % size)
|
||||||
|
if self.interior.winfo_reqwidth() != self.canvas.winfo_width():
|
||||||
|
# Update the canvas's width to fit the inner frame
|
||||||
|
self.canvas.config(width=self.interior.winfo_reqwidth())
|
||||||
|
|
||||||
|
def _configure_canvas(self, event):
|
||||||
|
if self.interior.winfo_reqwidth() != self.canvas.winfo_width():
|
||||||
|
# Update the inner frame's width to fill the canvas
|
||||||
|
self.canvas.itemconfigure(self.interior_id, width=self.canvas.winfo_width())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# find yourself in list of ssb users
|
# find yourself in list of ssb users
|
||||||
class Screen2(tk.Frame):
|
class Screen2(tk.Frame):
|
||||||
selected_user = None # This is the global variable to store selected user
|
|
||||||
|
|
||||||
def __init__(self, master):
|
def __init__(self, master):
|
||||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||||
self.selected_label = None # This is the global variable to store selected label
|
self.selected_label = None
|
||||||
|
self.filtered_users = []
|
||||||
|
|
||||||
# Create a new frame at the top for the label and text box
|
# Create a new frame at the top for the label and text box
|
||||||
self.top_frame = tk.Frame(self, bg='#bcfef9')
|
self.top_frame = tk.Frame(self, bg='#bcfef9')
|
||||||
self.top_frame.pack(side="top", fill="x", pady=60)
|
self.top_frame.pack(side="top", fill="x", pady=(60, 10))
|
||||||
|
|
||||||
# Add a label with text wrapping
|
# Add a label with text wrapping
|
||||||
self.label = tk.Label(self.top_frame,
|
self.label = tk.Label(self.top_frame,
|
||||||
text="Start typing your public key to find yourself in the list then click on your key to select it.",
|
text="Start typing your public key or alias to find yourself in the list then click on your key to select it.",
|
||||||
font=GlobalVars.TEXT_FONT,
|
font=GlobalVars.TEXT_FONT,
|
||||||
wraplength=800, # Adjust this value as needed
|
wraplength=800,
|
||||||
bg='#bcfef9')
|
bg='#bcfef9')
|
||||||
self.label.pack(side="top", pady=(0, 20)) # Add some padding below the label
|
self.label.pack(side="top", pady=(0, 10))
|
||||||
|
|
||||||
# Add text box to the top frame
|
# Add text box to the top frame
|
||||||
self.entry = tk.Entry(self.top_frame, font=GlobalVars.TEXT_FONT)
|
self.entry = tk.Entry(self.top_frame, font=GlobalVars.TEXT_FONT)
|
||||||
@ -186,92 +227,143 @@ class Screen2(tk.Frame):
|
|||||||
self.entry.focus_set()
|
self.entry.focus_set()
|
||||||
|
|
||||||
# Create container for user list
|
# Create container for user list
|
||||||
self.container = ttk.Frame(self, height=500) # Define a height here
|
self.container = tk.Frame(self, bg='#bcfef9')
|
||||||
self.container.pack(fill='both', expand=True, padx=20, pady=20)
|
self.container.pack(fill='both', expand=True, padx=20, pady=10)
|
||||||
|
|
||||||
# Initialize users list from users.json
|
# Create a canvas for the user list
|
||||||
|
self.canvas = tk.Canvas(self.container, bg='#bcfef9')
|
||||||
|
self.scrollbar = ttk.Scrollbar(self.container, orient="vertical", command=self.canvas.yview)
|
||||||
|
self.scrollable_frame = tk.Frame(self.canvas, bg='#bcfef9')
|
||||||
|
|
||||||
|
self.scrollable_frame.bind(
|
||||||
|
"<Configure>",
|
||||||
|
lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all"))
|
||||||
|
)
|
||||||
|
|
||||||
|
self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
|
||||||
|
self.canvas.configure(yscrollcommand=self.scrollbar.set)
|
||||||
|
|
||||||
|
self.canvas.pack(side="left", fill="both", expand=True)
|
||||||
|
self.scrollbar.pack(side="right", fill="y")
|
||||||
|
|
||||||
|
# Configure the scrollbar style to make it larger
|
||||||
|
style = ttk.Style()
|
||||||
|
style.configure("Vertical.TScrollbar", arrowsize=48, width=48)
|
||||||
|
|
||||||
|
# Create a frame for action buttons at the bottom
|
||||||
|
self.button_frame = tk.Frame(self, bg='#bcfef9')
|
||||||
|
self.button_frame.pack(side="bottom", fill="x", pady=10)
|
||||||
|
|
||||||
|
# The 'Refresh List' button
|
||||||
|
self.refresh_button = tk.Button(self.button_frame, text="Refresh List", command=self.refresh_users,
|
||||||
|
height=2, width=20, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||||
|
self.refresh_button.pack(side="left", padx=(20, 10))
|
||||||
|
|
||||||
|
# The 'Done' button to navigate to next screen
|
||||||
|
self.done_button = tk.Button(self.button_frame, text="Done", command=lambda: master.switch_frame(Screen3),
|
||||||
|
height=2, width=20, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||||
|
self.done_button.pack(side="right", padx=(10, 20))
|
||||||
|
|
||||||
|
# Initialize users list from users.json
|
||||||
self.users = self.get_users_from_file()
|
self.users = self.get_users_from_file()
|
||||||
self.update_users_list()
|
self.update_users_list()
|
||||||
|
|
||||||
# Highlight selected user if one exists
|
|
||||||
if GlobalVars.selected_user is not None:
|
|
||||||
for widget in self.container.winfo_children():
|
|
||||||
if isinstance(widget, tk.Button) and widget['text'] == GlobalVars.selected_user:
|
|
||||||
widget.configure(relief=tk.SUNKEN, bg="light blue")
|
|
||||||
self.selected_label = widget
|
|
||||||
|
|
||||||
|
|
||||||
# The 'Done' button to navigate to next screen
|
|
||||||
self.done_button = tk.Button(self, text="Done", command=lambda: master.switch_frame(Screen3), height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
|
||||||
self.done_button.pack(side="bottom", padx=20, pady=10)
|
|
||||||
|
|
||||||
# The 'Refresh List' button
|
|
||||||
self.refresh_button = tk.Button(self, text="Refresh List (takes 30 seconds or so)", command=self.refresh_users, height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
|
||||||
self.refresh_button.pack(side="bottom", padx=20, pady=10)
|
|
||||||
|
|
||||||
master.add_home_button(self)
|
master.add_home_button(self)
|
||||||
|
|
||||||
def refresh_users(self):
|
|
||||||
try:
|
|
||||||
# Update users list from Scuttlebutt and display it
|
|
||||||
self.users = self.get_scuttlebutt_users()
|
|
||||||
self.update_users_list()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An error occurred while refreshing the user list: {e}")
|
|
||||||
messagebox.showerror("Error", "An error occurred while refreshing the user list. Please try again later.")
|
|
||||||
|
|
||||||
def get_scuttlebutt_users(self):
|
|
||||||
result = subprocess.run(['node', 'scuttlebot.js'], capture_output=True, text=True)
|
|
||||||
if result.returncode == 0:
|
|
||||||
users = json.loads(result.stdout)
|
|
||||||
return users
|
|
||||||
else:
|
|
||||||
raise Exception("Command failed: " + result.stderr)
|
|
||||||
|
|
||||||
def get_users_from_file(self):
|
|
||||||
with open('users.json') as f:
|
|
||||||
users = json.load(f)
|
|
||||||
return users
|
|
||||||
|
|
||||||
def update_users_list(self):
|
def update_users_list(self):
|
||||||
# Remove all widgets from container
|
search_text = self.entry.get().lower()
|
||||||
for widget in self.container.winfo_children():
|
self.filtered_users = [user for user in self.users if search_text in user['id'].lower() or search_text in self.unescape_unicode(user.get('alias', '')).lower()]
|
||||||
|
self.display_users()
|
||||||
|
|
||||||
|
def display_users(self):
|
||||||
|
for widget in self.scrollable_frame.winfo_children():
|
||||||
widget.destroy()
|
widget.destroy()
|
||||||
|
|
||||||
# Filter users based on search text
|
for index, user in enumerate(self.filtered_users):
|
||||||
|
try:
|
||||||
|
frame = tk.Frame(self.scrollable_frame, bg='#bcfef9')
|
||||||
|
frame.pack(fill='x', expand=True, pady=2)
|
||||||
|
|
||||||
|
alias = self.unescape_unicode(user.get('alias', ''))
|
||||||
|
id = user.get('id', '')
|
||||||
|
|
||||||
|
alias_label = tk.Label(frame, text=alias, font=('Helvetica', 14, 'bold'), width=20, anchor='w', bg='#bcfef9')
|
||||||
|
alias_label.pack(side='left', padx=(0, 10))
|
||||||
|
|
||||||
|
id_label = tk.Label(frame, text=id, font=('Helvetica', 14), anchor='w', bg='#bcfef9')
|
||||||
|
id_label.pack(side='left', expand=True, fill='x')
|
||||||
|
|
||||||
|
frame.bind('<Button-1>', lambda e, u=user, f=frame: self.on_user_clicked(f, u))
|
||||||
|
alias_label.bind('<Button-1>', lambda e, u=user, f=frame: self.on_user_clicked(f, u))
|
||||||
|
id_label.bind('<Button-1>', lambda e, u=user, f=frame: self.on_user_clicked(f, u))
|
||||||
|
|
||||||
|
if GlobalVars.selected_user == id:
|
||||||
|
self.highlight_frame(frame)
|
||||||
|
self.selected_label = frame
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error displaying user {index + 1}: {str(e)}")
|
||||||
|
print(f"User data: {user}")
|
||||||
|
print(traceback.format_exc())
|
||||||
|
|
||||||
|
self.scrollable_frame.update_idletasks()
|
||||||
|
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
|
||||||
|
|
||||||
|
def on_user_clicked(self, frame, user):
|
||||||
|
# Unhighlight the previously selected user
|
||||||
|
if self.selected_label is not None and self.widget_exists(self.selected_label):
|
||||||
|
self.unhighlight_frame(self.selected_label)
|
||||||
|
|
||||||
|
# Update the selected user
|
||||||
|
GlobalVars.selected_user = user['id']
|
||||||
|
self.selected_label = frame
|
||||||
|
|
||||||
|
# Highlight the newly selected user
|
||||||
|
self.highlight_frame(frame)
|
||||||
|
self.update_done_button_state()
|
||||||
|
|
||||||
|
# Print debug information
|
||||||
|
print(f"User clicked: {user['id']}")
|
||||||
|
print(f"Selected label: {self.selected_label}")
|
||||||
|
print(f"Global selected user: {GlobalVars.selected_user}")
|
||||||
|
|
||||||
|
def highlight_frame(self, frame):
|
||||||
|
frame.configure(bg="light blue")
|
||||||
|
for child in frame.winfo_children():
|
||||||
|
child.configure(bg="light blue")
|
||||||
|
print(f"Highlighted frame: {frame}")
|
||||||
|
|
||||||
|
def unhighlight_frame(self, frame):
|
||||||
|
frame.configure(bg="#bcfef9")
|
||||||
|
for child in frame.winfo_children():
|
||||||
|
child.configure(bg="#bcfef9")
|
||||||
|
print(f"Unhighlighted frame: {frame}")
|
||||||
|
|
||||||
|
def update_users_list(self):
|
||||||
search_text = self.entry.get().lower()
|
search_text = self.entry.get().lower()
|
||||||
filtered_users = [user for user in self.users if search_text in user['id'].lower()]
|
self.filtered_users = [user for user in self.users if search_text in user['id'].lower() or search_text in self.unescape_unicode(user.get('alias', '')).lower()]
|
||||||
|
self.display_users()
|
||||||
|
|
||||||
|
# Preserve selection after filtering
|
||||||
|
if GlobalVars.selected_user:
|
||||||
|
for widget in self.scrollable_frame.winfo_children():
|
||||||
|
if isinstance(widget, tk.Frame):
|
||||||
|
id_label = widget.winfo_children()[-1]
|
||||||
|
if id_label['text'] == GlobalVars.selected_user:
|
||||||
|
self.highlight_frame(widget)
|
||||||
|
self.selected_label = widget
|
||||||
|
break
|
||||||
|
|
||||||
# Display filtered users
|
def scroll_to_widget(self, widget):
|
||||||
self.display_users(filtered_users)
|
self.canvas.update_idletasks()
|
||||||
|
self.canvas.yview_moveto(widget.winfo_y() / self.scrollable_frame.winfo_height())
|
||||||
|
|
||||||
def display_users(self, users):
|
def update_done_button_state(self):
|
||||||
# Scrollable list of users
|
if GlobalVars.selected_user:
|
||||||
canvas = tk.Canvas(self.container, width=460) # Decrease the width by scrollbar's width
|
self.done_button.configure(state="normal")
|
||||||
style = ttk.Style()
|
else:
|
||||||
style.configure("Vertical.TScrollbar", gripcount=0,
|
self.done_button.configure(state="disabled")
|
||||||
arrowsize=50, width=50) # Adjust width here
|
|
||||||
scrollbar = ttk.Scrollbar(self.container, orient='vertical', command=canvas.yview, style="Vertical.TScrollbar")
|
|
||||||
scrollable_frame = ttk.Frame(canvas)
|
|
||||||
|
|
||||||
scrollable_frame.bind(
|
|
||||||
"<Configure>",
|
|
||||||
lambda e: canvas.configure(
|
|
||||||
scrollregion=canvas.bbox("all")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
|
|
||||||
canvas.configure(yscrollcommand=scrollbar.set)
|
|
||||||
|
|
||||||
# Add user buttons to scrollable frame
|
|
||||||
for user in users:
|
|
||||||
button = tk.Button(scrollable_frame, text=user['id'], font=('Liberation Mono', 24), bd=0) # Adjust font size here
|
|
||||||
button.pack(anchor="w")
|
|
||||||
button.config(command=lambda button=button, user=user: self.on_user_clicked(button, user))
|
|
||||||
|
|
||||||
canvas.pack(side="left", fill="both", expand=True)
|
|
||||||
scrollbar.pack(side="right", fill="y")
|
|
||||||
|
|
||||||
def widget_exists(self, widget):
|
def widget_exists(self, widget):
|
||||||
try:
|
try:
|
||||||
@ -280,20 +372,50 @@ class Screen2(tk.Frame):
|
|||||||
except tk.TclError:
|
except tk.TclError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def on_user_clicked(self, button, user):
|
def refresh_users(self):
|
||||||
# Remove highlight from previously selected user
|
try:
|
||||||
if self.selected_label is not None and self.widget_exists(self.selected_label):
|
self.users = self.get_scuttlebutt_users()
|
||||||
self.selected_label.configure(relief=tk.FLAT, bg='SystemButtonFace') # default color
|
self.update_users_list()
|
||||||
|
self.save_users_to_file(self.users)
|
||||||
|
messagebox.showinfo("Success", "User list has been refreshed and updated with aliases.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred while refreshing the user list: {e}")
|
||||||
|
messagebox.showerror("Error", "An error occurred while refreshing the user list. Please try again later.")
|
||||||
|
|
||||||
# Store selected user and button
|
def get_scuttlebutt_users(self):
|
||||||
GlobalVars.selected_user = user['id']
|
try:
|
||||||
self.selected_label = button
|
result = subprocess.run(['node', 'scuttlebot.js'], capture_output=True, text=True, timeout=60)
|
||||||
|
if result.returncode == 0:
|
||||||
# Highlight clicked label
|
users = json.loads(result.stdout)
|
||||||
self.selected_label.configure(relief=tk.SUNKEN, bg="light blue")
|
return users
|
||||||
|
else:
|
||||||
|
print(f"Command failed with error: {result.stderr}")
|
||||||
|
return []
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
print("Command timed out after 60 seconds")
|
||||||
|
return []
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print("Failed to parse JSON output")
|
||||||
|
return []
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An unexpected error occurred: {str(e)}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_users_from_file(self):
|
||||||
|
try:
|
||||||
|
with open('users.json') as f:
|
||||||
|
users = json.load(f)
|
||||||
|
return users
|
||||||
|
except FileNotFoundError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def save_users_to_file(self, users):
|
||||||
|
with open('users.json', 'w') as f:
|
||||||
|
json.dump(users, f)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def unescape_unicode(s):
|
||||||
|
return s.encode('utf-8').decode('unicode_escape')
|
||||||
|
|
||||||
#take photo of item
|
#take photo of item
|
||||||
class Screen3(tk.Frame):
|
class Screen3(tk.Frame):
|
||||||
@ -304,7 +426,7 @@ class Screen3(tk.Frame):
|
|||||||
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||||
home_button.place(x=0, y=0) # top-left corner
|
home_button.place(x=0, y=0) # top-left corner
|
||||||
|
|
||||||
self.vid = cv2.VideoCapture(0)
|
self.vid = cv2.VideoCapture(2)
|
||||||
self.is_capturing = True
|
self.is_capturing = True
|
||||||
self.freeze_frame = None
|
self.freeze_frame = None
|
||||||
|
|
||||||
@ -333,7 +455,7 @@ class Screen3(tk.Frame):
|
|||||||
self.__del__()
|
self.__del__()
|
||||||
self.master.switch_frame(Screen0)
|
self.master.switch_frame(Screen0)
|
||||||
|
|
||||||
self.vid = cv2.VideoCapture(0)
|
self.vid = cv2.VideoCapture(2)
|
||||||
self.is_capturing = True
|
self.is_capturing = True
|
||||||
self.freeze_frame = None
|
self.freeze_frame = None
|
||||||
|
|
||||||
@ -366,7 +488,7 @@ class Screen3(tk.Frame):
|
|||||||
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||||
home_button.place(x=0, y=0) # top-left corner
|
home_button.place(x=0, y=0) # top-left corner
|
||||||
|
|
||||||
self.vid = cv2.VideoCapture(0)
|
self.vid = cv2.VideoCapture(2)
|
||||||
self.is_capturing = True
|
self.is_capturing = True
|
||||||
self.freeze_frame = None
|
self.freeze_frame = None
|
||||||
self.countdown_text = None
|
self.countdown_text = None
|
||||||
@ -1011,14 +1133,15 @@ class Screen12(tk.Frame):
|
|||||||
try:
|
try:
|
||||||
qr_code_str = GlobalVars.qr_code_value if isinstance(GlobalVars.qr_code_value, str) else GlobalVars.qr_code_value.decode('utf-8')
|
qr_code_str = GlobalVars.qr_code_value if isinstance(GlobalVars.qr_code_value, str) else GlobalVars.qr_code_value.decode('utf-8')
|
||||||
print(f"Attempting to get message content for: {qr_code_str}")
|
print(f"Attempting to get message content for: {qr_code_str}")
|
||||||
message_content, image_path = addtoDB.get_message_content(qr_code_str)
|
message_content, image_path, replies = addtoDB.get_message_content(qr_code_str)
|
||||||
print(f"Received message content: {message_content}")
|
print(f"Received message content: {message_content}")
|
||||||
print(f"Received image path: {image_path}")
|
print(f"Received image path: {image_path}")
|
||||||
|
print(f"Received replies: {replies}")
|
||||||
|
|
||||||
if message_content is None:
|
if message_content is None:
|
||||||
self.display_error(f"Error: Failed to retrieve message content for {qr_code_str}")
|
self.display_error(f"Error: Failed to retrieve message content for {qr_code_str}")
|
||||||
else:
|
else:
|
||||||
self.display_content(message_content, image_path)
|
self.display_content(message_content, image_path, replies)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.display_error(f"An error occurred while processing message: {str(e)}")
|
self.display_error(f"An error occurred while processing message: {str(e)}")
|
||||||
|
|
||||||
@ -1033,7 +1156,18 @@ class Screen12(tk.Frame):
|
|||||||
tk.Button(error_frame, text="Go Back", command=lambda: self.master.switch_frame(Screen0),
|
tk.Button(error_frame, text="Go Back", command=lambda: self.master.switch_frame(Screen0),
|
||||||
height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
||||||
|
|
||||||
def display_content(self, message_content, image_path):
|
def get_alias(self, user_id):
|
||||||
|
try:
|
||||||
|
with open('users.json') as f:
|
||||||
|
users = json.load(f)
|
||||||
|
for user in users:
|
||||||
|
if user['id'] == user_id:
|
||||||
|
return user.get('alias', '')
|
||||||
|
except FileNotFoundError:
|
||||||
|
return ''
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def display_content(self, message_content, image_path, replies):
|
||||||
# Main content frame
|
# Main content frame
|
||||||
content_frame = tk.Frame(self, bg='#bcfef9')
|
content_frame = tk.Frame(self, bg='#bcfef9')
|
||||||
content_frame.pack(expand=True, fill='both', padx=20, pady=10)
|
content_frame.pack(expand=True, fill='both', padx=20, pady=10)
|
||||||
@ -1074,11 +1208,23 @@ class Screen12(tk.Frame):
|
|||||||
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
|
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
|
||||||
canvas.configure(yscrollcommand=scrollbar.set)
|
canvas.configure(yscrollcommand=scrollbar.set)
|
||||||
|
|
||||||
|
# Display original message
|
||||||
text_content = message_content.get('content', {}).get('text', '')
|
text_content = message_content.get('content', {}).get('text', '')
|
||||||
# Remove markdown image syntax
|
# Remove markdown image syntax
|
||||||
text_content = re.sub(r'!\[.*?\]\(.*?\)', '', text_content).strip()
|
text_content = re.sub(r'!\[.*?\]\(.*?\)', '', text_content).strip()
|
||||||
tk.Label(scrollable_frame, text=text_content, wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 28)).pack(pady=5, padx=(5, 0))
|
tk.Label(scrollable_frame, text=text_content, wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 28)).pack(pady=5, padx=(5, 0))
|
||||||
|
|
||||||
|
# Display replies
|
||||||
|
if replies:
|
||||||
|
tk.Label(scrollable_frame, text="Replies:", wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 24, "bold")).pack(pady=(20, 5), padx=(5, 0))
|
||||||
|
for reply in replies:
|
||||||
|
author_id = reply.get('value', {}).get('author', 'Unknown')
|
||||||
|
author_alias = self.get_alias(author_id)
|
||||||
|
author_display = f"{author_alias} ({author_id})" if author_alias else author_id
|
||||||
|
reply_text = reply.get('value', {}).get('content', {}).get('text', '')
|
||||||
|
tk.Label(scrollable_frame, text=f"{author_display}:", wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 20, "bold")).pack(pady=(10, 0), padx=(5, 0))
|
||||||
|
tk.Label(scrollable_frame, text=reply_text, wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 18)).pack(pady=(0, 10), padx=(5, 0))
|
||||||
|
|
||||||
canvas.pack(side="left", fill="both", expand=True)
|
canvas.pack(side="left", fill="both", expand=True)
|
||||||
scrollbar.pack(side="right", fill="y")
|
scrollbar.pack(side="right", fill="y")
|
||||||
|
|
||||||
@ -1090,7 +1236,6 @@ class Screen12(tk.Frame):
|
|||||||
tk.Button(self, text="Done", command=lambda: self.master.switch_frame(Screen0),
|
tk.Button(self, text="Done", command=lambda: self.master.switch_frame(Screen0),
|
||||||
height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side="bottom", pady=20)
|
height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side="bottom", pady=20)
|
||||||
|
|
||||||
|
|
||||||
#time to print
|
#time to print
|
||||||
class Screen13(tk.Frame):
|
class Screen13(tk.Frame):
|
||||||
def __init__(self, master):
|
def __init__(self, master):
|
||||||
|
39
scuttlebot (copy 1).js
Normal file
39
scuttlebot (copy 1).js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// scuttlebot.js
|
||||||
|
|
||||||
|
const ssbClient = require('ssb-client');
|
||||||
|
const ssbKeys = require('ssb-keys');
|
||||||
|
const pull = require('pull-stream');
|
||||||
|
|
||||||
|
const keys = ssbKeys.loadOrCreateSync('~/.ssb/secret');
|
||||||
|
|
||||||
|
ssbClient(keys, (err, sbot) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(JSON.stringify({ "error": "Failed to connect to the Scuttlebot server. Is it running?" }));
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const authors = new Set();
|
||||||
|
|
||||||
|
pull(
|
||||||
|
sbot.messagesByType("contact"),
|
||||||
|
pull.drain((msg) => {
|
||||||
|
authors.add(msg.value.author);
|
||||||
|
}, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(JSON.stringify({ "error": "Failed to retrieve messages." }));
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const feeds = Array.from(authors).map(author => { return { id: author } });
|
||||||
|
console.log(JSON.stringify(feeds));
|
||||||
|
try {
|
||||||
|
sbot.close(() => {});
|
||||||
|
} catch(err) {
|
||||||
|
console.error("Error closing SSB server connection: ", err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
@ -14,6 +14,7 @@ ssbClient(keys, (err, sbot) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const authors = new Set();
|
const authors = new Set();
|
||||||
|
const aliases = new Map();
|
||||||
|
|
||||||
pull(
|
pull(
|
||||||
sbot.messagesByType("contact"),
|
sbot.messagesByType("contact"),
|
||||||
@ -26,14 +27,42 @@ ssbClient(keys, (err, sbot) => {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const feeds = Array.from(authors).map(author => { return { id: author } });
|
// Fetch aliases for all authors
|
||||||
console.log(JSON.stringify(feeds));
|
pull(
|
||||||
try {
|
sbot.query.read({
|
||||||
sbot.close(() => {});
|
query: [{
|
||||||
} catch(err) {
|
$filter: {
|
||||||
console.error("Error closing SSB server connection: ", err);
|
value: {
|
||||||
}
|
content: { type: 'about' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}),
|
||||||
|
pull.drain((msg) => {
|
||||||
|
if (msg.value.content.about && msg.value.content.name) {
|
||||||
|
aliases.set(msg.value.content.about, msg.value.content.name);
|
||||||
|
}
|
||||||
|
}, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(JSON.stringify({ "error": "Failed to retrieve aliases." }));
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const feeds = Array.from(authors).map(author => {
|
||||||
|
return {
|
||||||
|
id: author,
|
||||||
|
alias: aliases.get(author) || ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify(feeds));
|
||||||
|
try {
|
||||||
|
sbot.close(() => {});
|
||||||
|
} catch(err) {
|
||||||
|
console.error("Error closing SSB server connection: ", err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,6 +141,12 @@ else
|
|||||||
echo "No blobs found in the message." >&2
|
echo "No blobs found in the message." >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Output message content
|
# Get replies
|
||||||
|
replies=$(ssb-server query.read --private --reverse --limit 200 --query '{"value":{"content":{"root":"'$messageID'"}}}')
|
||||||
|
|
||||||
|
# Output message content and replies
|
||||||
echo "$message_content"
|
echo "$message_content"
|
||||||
|
echo "REPLIES_START"
|
||||||
|
echo "$replies"
|
||||||
|
echo "REPLIES_END"
|
||||||
fi
|
fi
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user