Skip to content

Commit f87e83c

Browse files
author
denwii25
committed
Add phone number selector script
0 parents  commit f87e83c

File tree

1 file changed

+336
-0
lines changed

1 file changed

+336
-0
lines changed

phone_numbers.py

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Phone Number Manager with GUI
4+
Handles phone number collection, message input, and macOS integration
5+
"""
6+
7+
import tkinter as tk
8+
from tkinter import ttk, messagebox, simpledialog
9+
import random
10+
import subprocess
11+
import sys
12+
import os
13+
14+
15+
class PhoneNumberManager:
16+
def __init__(self):
17+
self.phone_numbers = []
18+
self.message_text = ""
19+
self.root = tk.Tk()
20+
self.setup_main_window()
21+
22+
def setup_main_window(self):
23+
"""Setup the main phone number input window"""
24+
self.root.title("Phone Number Manager")
25+
self.root.geometry("450x400")
26+
self.root.configure(bg='#f0f0f0')
27+
28+
# Center the window
29+
self.center_window(450, 400)
30+
31+
# Title label
32+
title_label = tk.Label(
33+
self.root,
34+
text="Phone Number Manager",
35+
font=('Arial', 16, 'bold'),
36+
bg='#f0f0f0'
37+
)
38+
title_label.pack(pady=10)
39+
40+
# Phone number input frame
41+
input_frame = tk.Frame(self.root, bg='#f0f0f0')
42+
input_frame.pack(pady=10)
43+
44+
tk.Label(input_frame, text="Phone Number:", bg='#f0f0f0').pack(anchor='w')
45+
self.phone_entry = tk.Entry(input_frame, width=30, font=('Arial', 12))
46+
self.phone_entry.pack(pady=5)
47+
self.phone_entry.focus()
48+
49+
# Phone numbers list
50+
list_frame = tk.Frame(self.root, bg='#f0f0f0')
51+
list_frame.pack(pady=10, fill='both', expand=True)
52+
53+
tk.Label(list_frame, text="Added Phone Numbers:", bg='#f0f0f0').pack(anchor='w')
54+
55+
# Listbox with scrollbar
56+
listbox_frame = tk.Frame(list_frame)
57+
listbox_frame.pack(fill='both', expand=True, padx=10)
58+
59+
scrollbar = tk.Scrollbar(listbox_frame)
60+
scrollbar.pack(side='right', fill='y')
61+
62+
self.phone_listbox = tk.Listbox(
63+
listbox_frame,
64+
yscrollcommand=scrollbar.set,
65+
font=('Arial', 10)
66+
)
67+
self.phone_listbox.pack(side='left', fill='both', expand=True)
68+
scrollbar.config(command=self.phone_listbox.yview)
69+
70+
# Buttons frame
71+
button_frame = tk.Frame(self.root, bg='#f0f0f0')
72+
button_frame.pack(pady=20)
73+
74+
# Buttons
75+
add_btn = tk.Button(
76+
button_frame,
77+
text="Add Another Phone Number",
78+
command=self.add_phone_number,
79+
bg='#4CAF50',
80+
fg='black',
81+
font=('Arial', 10, 'bold'),
82+
padx=10,
83+
relief='raised',
84+
bd=2
85+
)
86+
add_btn.pack(side='left', padx=5)
87+
88+
ok_btn = tk.Button(
89+
button_frame,
90+
text="OK",
91+
command=self.proceed_to_message,
92+
bg='#4CAF50',
93+
fg='black',
94+
font=('Arial', 10, 'bold'),
95+
padx=20,
96+
relief='raised',
97+
bd=2
98+
)
99+
ok_btn.pack(side='left', padx=5)
100+
101+
cancel_btn = tk.Button(
102+
button_frame,
103+
text="Cancel",
104+
command=self.cancel_operation,
105+
bg='#4CAF50',
106+
fg='black',
107+
font=('Arial', 10, 'bold'),
108+
padx=15,
109+
relief='raised',
110+
bd=2
111+
)
112+
cancel_btn.pack(side='left', padx=5)
113+
114+
# Bind Enter key to add phone number
115+
self.phone_entry.bind('<Return>', lambda e: self.add_phone_number())
116+
117+
def center_window(self, width, height):
118+
"""Center window on screen"""
119+
screen_width = self.root.winfo_screenwidth()
120+
screen_height = self.root.winfo_screenheight()
121+
x = (screen_width - width) // 2
122+
y = (screen_height - height) // 2
123+
self.root.geometry(f"{width}x{height}+{x}+{y}")
124+
125+
def add_phone_number(self):
126+
"""Add phone number to the list"""
127+
phone = self.phone_entry.get().strip()
128+
if phone:
129+
if phone not in self.phone_numbers:
130+
self.phone_numbers.append(phone)
131+
self.phone_listbox.insert(tk.END, phone)
132+
self.phone_entry.delete(0, tk.END)
133+
print(f"Added phone number: {phone}")
134+
else:
135+
messagebox.showwarning("Duplicate", "This phone number is already in the list!")
136+
else:
137+
messagebox.showwarning("Empty Field", "Please enter a phone number!")
138+
139+
def proceed_to_message(self):
140+
"""Proceed to message input if we have phone numbers"""
141+
if not self.phone_numbers:
142+
messagebox.showwarning("No Phone Numbers", "Please add at least one phone number!")
143+
return
144+
145+
# Add current entry if it exists
146+
current_phone = self.phone_entry.get().strip()
147+
if current_phone and current_phone not in self.phone_numbers:
148+
self.phone_numbers.append(current_phone)
149+
150+
print(f"Proceeding with {len(self.phone_numbers)} phone numbers: {self.phone_numbers}")
151+
self.show_message_window()
152+
153+
def cancel_operation(self):
154+
"""Cancel and exit"""
155+
self.root.destroy()
156+
157+
def show_message_window(self):
158+
"""Show the message input window"""
159+
self.root.withdraw() # Hide main window
160+
161+
# Create message window
162+
self.message_window = tk.Toplevel()
163+
self.message_window.title("Enter Message")
164+
self.message_window.geometry("450x300")
165+
self.message_window.configure(bg='#f0f0f0')
166+
self.center_message_window(450, 300)
167+
168+
# Title
169+
title_label = tk.Label(
170+
self.message_window,
171+
text="Enter Your Message",
172+
font=('Arial', 16, 'bold'),
173+
bg='#f0f0f0'
174+
)
175+
title_label.pack(pady=10)
176+
177+
# Message input
178+
tk.Label(self.message_window, text="Message:", bg='#f0f0f0').pack(anchor='w', padx=20)
179+
180+
# Text area with scrollbar
181+
text_frame = tk.Frame(self.message_window)
182+
text_frame.pack(pady=10, padx=20, fill='both', expand=True)
183+
184+
text_scrollbar = tk.Scrollbar(text_frame)
185+
text_scrollbar.pack(side='right', fill='y')
186+
187+
self.message_text_widget = tk.Text(
188+
text_frame,
189+
height=8,
190+
font=('Arial', 12),
191+
yscrollcommand=text_scrollbar.set,
192+
wrap='word'
193+
)
194+
self.message_text_widget.pack(side='left', fill='both', expand=True)
195+
text_scrollbar.config(command=self.message_text_widget.yview)
196+
197+
self.message_text_widget.focus()
198+
199+
# Buttons
200+
button_frame = tk.Frame(self.message_window, bg='#f0f0f0')
201+
button_frame.pack(pady=20)
202+
203+
ok_btn = tk.Button(
204+
button_frame,
205+
text="OK",
206+
command=self.send_message,
207+
bg='#4CAF50',
208+
fg='black',
209+
font=('Arial', 10, 'bold'),
210+
padx=30,
211+
relief='raised',
212+
bd=2
213+
)
214+
ok_btn.pack(side='left', padx=10)
215+
216+
cancel_btn = tk.Button(
217+
button_frame,
218+
text="Cancel",
219+
command=self.cancel_message,
220+
bg='#4CAF50',
221+
fg='black',
222+
font=('Arial', 10, 'bold'),
223+
padx=20,
224+
relief='raised',
225+
bd=2
226+
)
227+
cancel_btn.pack(side='left', padx=10)
228+
229+
# Handle window close
230+
self.message_window.protocol("WM_DELETE_WINDOW", self.cancel_message)
231+
232+
def center_message_window(self, width, height):
233+
"""Center message window on screen"""
234+
screen_width = self.message_window.winfo_screenwidth()
235+
screen_height = self.message_window.winfo_screenheight()
236+
x = (screen_width - width) // 2
237+
y = (screen_height - height) // 2
238+
self.message_window.geometry(f"{width}x{height}+{x}+{y}")
239+
240+
def send_message(self):
241+
"""Process the message and integrate with macOS"""
242+
self.message_text = self.message_text_widget.get("1.0", tk.END).strip()
243+
244+
if not self.message_text:
245+
messagebox.showwarning("Empty Message", "Please enter a message!")
246+
return
247+
248+
# Select random phone number (but don't show it to user)
249+
selected_phone = random.choice(self.phone_numbers)
250+
print(f"Selected phone number: {selected_phone}")
251+
print(f"Message: {self.message_text}")
252+
253+
# Show confirmation without revealing the phone number
254+
result = messagebox.askyesno(
255+
"Send Message",
256+
f"Ready to send your message!\n\n"
257+
f"This will add a new contact and send your message.\n\n"
258+
f"Continue?"
259+
)
260+
261+
if result:
262+
try:
263+
self.add_contact_to_system(selected_phone)
264+
self.send_imessage(selected_phone, self.message_text)
265+
messagebox.showinfo("Success", "Contact added and SMS sent!")
266+
except Exception as e:
267+
messagebox.showerror("Error", f"An error occurred: {str(e)}")
268+
269+
self.cleanup()
270+
271+
def add_contact_to_system(self, phone_number):
272+
"""Add contact to macOS Contacts app using AppleScript"""
273+
applescript = f'''
274+
tell application "Contacts"
275+
set newContact to make new person
276+
set first name of newContact to "Test"
277+
make new phone at end of phones of newContact with properties {{label:"mobile", value:"{phone_number}"}}
278+
save
279+
end tell
280+
'''
281+
282+
try:
283+
subprocess.run(['osascript', '-e', applescript], check=True)
284+
print(f"Added contact 'Test' with phone number: {phone_number}")
285+
except subprocess.CalledProcessError as e:
286+
print(f"Error adding contact: {e}")
287+
raise Exception("Failed to add contact. Make sure Contacts app is accessible.")
288+
289+
def send_imessage(self, phone_number, message):
290+
"""Send SMS text message using AppleScript"""
291+
# Clean the phone number and message for AppleScript
292+
clean_phone = phone_number.replace('"', '\\"')
293+
clean_message = message.replace('"', '\\"').replace('\n', '\\n')
294+
295+
applescript = f'''
296+
tell application "Messages"
297+
set targetService to 1st account whose service type = SMS
298+
set targetBuddy to participant "{clean_phone}" of targetService
299+
send "{clean_message}" to targetBuddy
300+
end tell
301+
'''
302+
303+
try:
304+
subprocess.run(['osascript', '-e', applescript], check=True)
305+
print(f"Sent SMS to {phone_number}: {message}")
306+
except subprocess.CalledProcessError as e:
307+
print(f"Error sending SMS: {e}")
308+
raise Exception("Failed to send SMS. Make sure Messages app is accessible and SMS is set up.")
309+
310+
def cancel_message(self):
311+
"""Cancel message input and return to main window"""
312+
self.message_window.destroy()
313+
self.root.deiconify() # Show main window again
314+
315+
def cleanup(self):
316+
"""Clean up and exit"""
317+
if hasattr(self, 'message_window'):
318+
self.message_window.destroy()
319+
self.root.destroy()
320+
321+
def run(self):
322+
"""Start the application"""
323+
self.root.mainloop()
324+
325+
326+
def main():
327+
"""Main function to run the application"""
328+
print("Starting Phone Number Manager...")
329+
print("Note: This app requires macOS and proper permissions for Contacts and Messages.")
330+
331+
app = PhoneNumberManager()
332+
app.run()
333+
334+
335+
if __name__ == "__main__":
336+
main()

0 commit comments

Comments
 (0)