PySimpleGUI番外1 - 短信自动同步至服务器
最近想到一个idea,有的时候电脑登陆账号的时候需要发验证码,但并不是所有时候手机都在身边,专门去拿就很麻烦,要是短信可以自动同步到电脑就好了。这篇文章就讲讲我的实现,以及提供 PySimpleGUI 的前端代码参考。
简述
简单来说,实现逻辑如下:
手机使用tasker获取短信后自动发送http请求,服务器接到请求后把短信存在本地。电脑端需要查询短信时就向服务器请求拉取。
接下来来讲讲具体步骤。
Tasker
Tasker是手机端的一个自动化软件,非常厉害,这里只使用了它的一部分功能,下面是一些参考步骤。
- 打开Tasker,首先进入“任务”栏,点击右下加号,创建我们的http请求任务。
- 再点加号添加操作。在“网络”栏里选“HTTP POST”。
- 接下来就可以自定义你的请求格式了。我在我的服务器上配置了web服务器来接收请求,我可以通过
/recv
api来上传我的短信内容。
这里截图对应的包格式:
{
token: "*******", //自定义密码
title: "my text", //标题,一般短信没有
content: "it's a text message.", //短信内容
local_date: "2022-3-15", //日期
local_time: "09.52", //时间
user: "1xxxxxxxxxx", //发送人(手机)号码
user_name: "1xxxxxxxxxx" //发送人名称,一般与发送人号码相同
}
截图里的参数都是Tasker定义的,直接选择即可。这样http请求就定好了。接下来设置触发器:
- 回到主页面“配置文件”栏,点击加号,选择“事件” > “电话” > “收到短信”,类型选择任意,返回;
- 这时需要选择待触发的任务。选中我们之前的请求任务,配置就完成了。
需要注意以下,Tasker需要保持运行,这个就看下网上教程吧,不同机型未必一样。
后端
后端用flask简单实现了一个储存与查询服务。需要源码可参考链接:
https://github.com/wzy1935/message_forward
前端
前端就是 PySimpleGUI 的内容了。直接给源码吧:
service.py:
import requests, time, json
def to_timestamp(local_date, local_time):
return int(time.mktime(time.strptime(f'{local_date} {local_time}', "%Y-%m-%d %H.%M")))
def to_time_str(timestamp):
return time.strftime("%Y-%m-%d %H:%M", time.localtime(timestamp))
def msg_list(page, page_size=20):
url = "http://YOUR_URL/list"
res = requests.post(url, data={'token': '******', 'page': page, 'page_size': page_size})
res_json = json.loads(res.text)
return res_json
main.py:
import service
import PySimpleGUI as sg
sg.theme('LightBlue2')
def data_list_display(data_list):
return [f'{x["user"]} - {service.to_time_str(x["time"])}' for x in data_list]
def data_dislpay(data=None):
if data is None:
return '[empty]'
else:
return f'{data["user"]} - {data["user_name"]}\n' \
f'{service.to_time_str(data["time"])}\n' \
f'---------------------------------------\n' \
f'{data["content"]}'
init_data = service.msg_list(1)
count = init_data['count']
data_list = init_data['data']
page = 1
left = sg.Button('<<', key='/left', size=(4,1), disabled=True)
current = sg.Text(f'1/{(count+19)//20}', key='/current', size=(6,1), justification='center')
right = sg.Button('>>', key='/right', size=(4,1), disabled=(True if count <= 20 else False))
refresh = sg.Button('refresh', key='/refresh', size=(8,1))
list_view = sg.Listbox(data_list_display(data_list), key='/list', size=(30,16), enable_events=True)
full_text = sg.Multiline(data_dislpay(None if count == 0 else data_list[0]), key='/text', size=(50,19))
def update(after):
global page, data_list, count
init_data = service.msg_list(1)
count = init_data['count']
data_list = init_data['data']
left.update(disabled=after <= 1)
right.update(disabled=after >= count//20)
list_view.update(data_list_display(data_list))
current.update(f'{after}/{(count+19)//20}')
full_text.update(data_dislpay(None if count == 0 else data_list[0]))
page = after
def update_text(id):
full_text.update(data_dislpay(data_list[id[0]]))
layout_l = [
[list_view],
[left, current, right, refresh]
]
layout = [[sg.Column(layout_l), full_text]]
window = sg.Window('message', layout)
while True:
e, v = window.read()
if e == sg.WINDOW_CLOSED: break
if e == '/left':
update(page-1)
if e == '/right':
update(page+1)
if e == '/refresh':
update(page)
if e == '/list':
update_text(list_view.get_indexes())
window.close()
最后效果如图: