commit 310c4bac8aabd31718310cab4aee136ae710b79d Author: LibraHp_0928 <1941163264@qq.com> Date: Thu Sep 19 17:36:17 2024 +0800 first diff --git a/.flutter_custom_devices.json b/.flutter_custom_devices.json new file mode 100644 index 0000000..e17ec38 --- /dev/null +++ b/.flutter_custom_devices.json @@ -0,0 +1,46 @@ +{ + "$schema": "file:///D:/Environment/flutter/2.2.3/packages/flutter_tools/static/custom-devices.schema.json", + "custom-devices": [ + { + "id": "test1", + "label": "Test Device", + "sdkNameAndVersion": "Test Device 4 Model B+", + "disabled": true, + "ping": [ + "ping", + "-w", + "500", + "-n", + "1", + "raspberrypi" + ], + "pingSuccessRegex": "ms TTL=", + "postBuild": null, + "install": [ + "scp", + "-r", + "${localPath}", + "pi@raspberrypi:/tmp/${appName}" + ], + "uninstall": [ + "ssh", + "pi@raspberrypi", + "rm -rf \"/tmp/${appName}\"" + ], + "runDebug": [ + "ssh", + "pi@raspberrypi", + "flutter-pi \"/tmp/${appName}\"" + ], + "forwardPort": [ + "ssh", + "-o", + "ExitOnForwardFailure=yes", + "-L", + "127.0.0.1:${hostPort}:127.0.0.1:${devicePort}", + "pi@raspberrypi" + ], + "forwardPortSuccessRegex": "Linux" + } + ] +} diff --git a/.flutter_tool_state b/.flutter_tool_state new file mode 100644 index 0000000..f8e1ab1 --- /dev/null +++ b/.flutter_tool_state @@ -0,0 +1,4 @@ +{ + "is-bot": true, + "license-hash": "3e8c85e63b26ce223cda96a9a8fbb410" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68bc17f --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..4f18a49 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# A getqzonehistory Flet app + +An example of a minimal Flet app. + +To run the app: + +``` +flet run [app_directory] +``` \ No newline at end of file diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..bebc6d5 Binary files /dev/null and b/assets/icon.png differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..febda31 --- /dev/null +++ b/main.py @@ -0,0 +1,272 @@ +import flet as ft +import requests +import base64 +import re +import time + +is_finsh = False + +def bkn(pSkey): + # 计算bkn + + t, n, o = 5381, 0, len(pSkey) + + while n < o: + t += (t << 5) + ord(pSkey[n]) + n += 1 + + return t & 2147483647 + + +def ptqrToken(qrsig): + # 计算ptqrtoken + n, i, e = len(qrsig), 0, 0 + + while n > i: + e += (e << 5) + ord(qrsig[i]) + i += 1 + + return 2147483647 & e + +def QR(): + # 获取 qq空间 二维码 + url = 'https://ssl.ptlogin2.qq.com/ptqrshow?appid=549000912&e=2&l=M&s=3&d=72&v=4&t=0.8692955245720428&daid=5&pt_3rd_aid=0' + + try: + response = requests.get(url) + response.raise_for_status() # 确保请求成功 + + # 获取二维码图片的二进制内容 + image_data = response.content + + # 将二进制内容转换为 Base64 编码 + base64_image = base64.b64encode(image_data).decode('utf-8') + + # 获取 qrsig (可选) + qrsig = requests.utils.dict_from_cookiejar(response.cookies).get('qrsig') + + return base64_image, qrsig + + except Exception as e: + print(e) + return None, None + + +def create_card(img_url, title, subtitle): + return ft.Card( + content=ft.Container( + content=ft.Column( + [ + ft.ListTile( + # 如果img_url为空 显示https://picsum.photos/200 + leading=ft.Image(src=img_url, border_radius=100), + title=ft.Text(title), + subtitle=ft.Text(subtitle), + ), + ft.Row( + [ft.TextButton("购票"), ft.TextButton("试听")], + alignment=ft.MainAxisAlignment.END, + ), + ] + ), + width=400, + padding=10, + ) + ) + +def main(page: ft.Page): + page.window.center() + page.title = "QQ空间历史内容获取 v1.0 Powered by LibraHp" + page.horizontal_alignment = "start" + page.vertical_alignment = "center" + page.window.resizable = False + page.padding = 20 + page.bgcolor = "#f0f0f0" + + # 路由改变函数 + def change_route(e): + selected_tab = e.control.data + if selected_tab == "GetContent": + content_area.content = create_get_content_page() + elif selected_tab == "User": + content_area.content = ft.Text("说说列表", size=30) + elif selected_tab == "Leave": + content_area.content = ft.Text("留言列表", size=30) + elif selected_tab == "Friends": + content_area.content = ft.Text("好友列表", size=30) + elif selected_tab == "Forward": + content_area.content = ft.Text("转发列表", size=30) + elif selected_tab == "Other": + content_area.content = ft.Text("其他列表", size=30) + elif selected_tab == "Pictures": + content_area.content = ft.Text("图片列表", size=30) + + page.update() + + # 获取内容页面 + def create_get_content_page(): + base64_image, qrsig = QR() + + # 更新二维码状态的函数(模拟,需实际实现逻辑) + def update_qr_code_status(e): + ptqrtoken = ptqrToken(qrsig) + url = 'https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara' \ + '%3Dizone&ptqrtoken=' + str(ptqrtoken) + '&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-' \ + + str(time.time()) + '&js_ver=20032614&js_type=1&login_sig=&pt_uistyle=40&aid=549000912&daid=5&' + cookies = {'qrsig': qrsig} + try: + r = requests.get(url, cookies=cookies) + print(r.text) + if '二维码未失效' in r.text: + qr_status.value = "二维码状态:未失效" + pass + elif '二维码认证中' in r.text: + qr_status.value = "二维码状态:认证中" + elif '二维码已失效' in r.text: + qr_status.value = "二维码状态:已失效" + elif '本次登录已被拒绝' in r.text: + qr_status.value = "二维码状态:已拒绝" + elif '登录成功' in r.text: + qr_status.value = "二维码状态:已登录" + cookies = requests.utils.dict_from_cookiejar(r.cookies) + uin = requests.utils.dict_from_cookiejar(r.cookies).get('uin') + regex = re.compile(r'ptsigx=(.*?)&') + sigx = re.findall(regex, r.text)[0] + url = 'https://ptlogin2.qzone.qq.com/check_sig?pttype=1&uin=' + uin + '&service=ptqrlogin&nodirect=0' \ + '&ptsigx=' + sigx + \ + '&s_url=https%3A%2F%2Fqzs.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&f_url=&ptlang' \ + '=2052&ptredirect=100&aid=549000912&daid=5&j_later=0&low_login_hour=0®master=0&pt_login_type' \ + '=3&pt_aid=0&pt_aaid=16&pt_light=0&pt_3rd_aid=0' + try: + r = requests.get(url, cookies=cookies, allow_redirects=False) + target_cookies = requests.utils.dict_from_cookiejar(r.cookies) + print(target_cookies) + p_skey = requests.utils.dict_from_cookiejar(r.cookies).get('p_skey') + is_finsh = True + page.update() + except Exception as e: + print(e) + except Exception as e: + print(e) + + page.update() + + # 获取新的二维码的函数(模拟,需实际实现逻辑) + def refresh_qr_code(e): + base64_image, qrsig = QR() + # 刷新已渲染的图片 + qr_image.src_base64 = base64_image + qr_status.value = "二维码状态:等待扫描" # 重置状态为等待扫描 + page.update() + + qr_image = ft.Image(src_base64=base64_image, width=200, height=200) + qr_status = ft.Text("二维码状态:等待扫描", size=16, color="green") + + # 返回一个包含二维码和状态更新的布局 + return ft.Column( + controls=[ + ft.Text("请使用手机QQ扫码登录", size=24, weight="bold"), + qr_image, # 展示二维码 + qr_status, # 展示二维码状态 + ft.Row( + [ + ft.ElevatedButton("刷新二维码", on_click=refresh_qr_code), + ft.ElevatedButton("更新状态", on_click=update_qr_code_status), + ], + alignment=ft.MainAxisAlignment.CENTER, + ), + ], + alignment="center", + horizontal_alignment="center", + expand=True, + ) + + # 用户信息 + user_info = ft.Container( + content=ft.Column( + controls=[ + ft.Image(src="https://picsum.photos/200", width=80, height=80, border_radius=100), # Replace with actual avatar URL + ft.Text("Username", size=20, weight="bold") + ], + alignment="center", + horizontal_alignment="center" + ), + width=200, + padding=20 + ) + + # 左侧标签页 + tabs = ft.Column( + controls=[ + ft.ElevatedButton("获取内容", on_click=change_route, data="GetContent", width=200), + ft.ElevatedButton("说说列表", on_click=change_route, data="User", width=200, disabled=not is_finsh), + ft.ElevatedButton("留言列表", on_click=change_route, data="Leave", width=200, disabled=not is_finsh), + ft.ElevatedButton("好友列表", on_click=change_route, data="Friends", width=200, disabled=not is_finsh), + ft.ElevatedButton("转发列表", on_click=change_route, data="Forward", width=200, disabled=not is_finsh), + ft.ElevatedButton("其他列表", on_click=change_route, data="Other", width=200, disabled=not is_finsh), + ft.ElevatedButton("图片列表", on_click=change_route, data="Pictures", width=200, disabled=not is_finsh), + ft.Column( + controls=[ + ft.TextButton("Powered by LibraHp", url="https://github.com/LibraHp"), + ft.TextButton("Bilibili @高数带我飞", url="https://space.bilibili.com/1117414477"), + ft.Text("程序完全免费且开源!", size=12, color="red", text_align="center") + ], + alignment="center", + horizontal_alignment="center", + width=200 + ) + ], + scroll=True, + alignment="start", + spacing=10 + ) + + # 左侧标签容器 + left_panel = ft.Container( + content=ft.Column( + controls=[user_info, tabs], + spacing=30, + horizontal_alignment="start" + ), + width=220, + bgcolor="#ffffff", + border_radius=10, + padding=10 + ) + + try: + home_content_md = requests.get("https://raw.githubusercontent.com/LibraHp/GetQzonehistory/main/README.MD").text + except: + home_content_md = "获取失败" + # 路由容器 + content_area = ft.Container( + content=ft.Column( + controls=[ + ft.Markdown( + value=home_content_md, + selectable=True, + extension_set=ft.MarkdownExtensionSet.GITHUB_WEB, + on_tap_link=lambda e: page.launch_url(e.data) + ), + ], + expand=True, + scroll=True + ), + bgcolor="#ffffff", + expand=True, + padding=20, + border_radius=10 + ) + + # 主布局 + main_layout = ft.Row( + controls=[left_panel, content_area], + expand=True, + alignment="start" + ) + + page.add(main_layout) + + +if __name__ == "__main__": + ft.app(target=main) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d54c7ec --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +flet==0.22.* \ No newline at end of file